mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-28 08:03:36 +00:00
app: Introduce API for managing setup state of the app
Useful for replacing setup_helper. This API should be considered EXPERIMENTAL and may change. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
929e7f6dba
commit
47cb5e027f
@ -4,6 +4,8 @@ Base class for all Freedombox applications.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import enum
|
||||
import sys
|
||||
|
||||
from . import clients as clients_module
|
||||
|
||||
@ -40,6 +42,12 @@ class App:
|
||||
|
||||
_all_apps = collections.OrderedDict()
|
||||
|
||||
class SetupState(enum.Enum):
|
||||
"""Various states of app being setup."""
|
||||
NEEDS_SETUP = 'needs-setup'
|
||||
NEEDS_UPDATE = 'needs-update'
|
||||
UP_TO_DATE = 'up-to-date'
|
||||
|
||||
def __init__(self):
|
||||
"""Build the app by adding components.
|
||||
|
||||
@ -118,6 +126,51 @@ class App:
|
||||
for component in self.components.values():
|
||||
component.setup(old_version=old_version)
|
||||
|
||||
def get_setup_state(self) -> SetupState:
|
||||
"""Return whether the app is not setup or needs upgrade."""
|
||||
current_version = self.get_setup_version()
|
||||
if current_version and self.info.version <= current_version:
|
||||
return self.SetupState.UP_TO_DATE
|
||||
|
||||
# If an app needs installing/updating but no setup method is available,
|
||||
# then automatically set version.
|
||||
#
|
||||
# Minor violation of 'get' only discipline for convenience.
|
||||
module = sys.modules[self.__module__]
|
||||
if not hasattr(module, 'setup'):
|
||||
self.set_setup_version(self.info.version)
|
||||
return self.SetupState.UP_TO_DATE
|
||||
|
||||
if not current_version:
|
||||
return self.SetupState.NEEDS_SETUP
|
||||
|
||||
return self.SetupState.NEEDS_UPDATE
|
||||
|
||||
def get_setup_version(self) -> int:
|
||||
"""Return the setup version of the app."""
|
||||
# XXX: Optimize version gets
|
||||
from . import models
|
||||
|
||||
try:
|
||||
app_entry = models.Module.objects.get(pk=self.app_id)
|
||||
return app_entry.setup_version
|
||||
except models.Module.DoesNotExist:
|
||||
return 0
|
||||
|
||||
def needs_setup(self) -> bool:
|
||||
"""Return whether the app needs to be setup.
|
||||
|
||||
A simple shortcut for get_setup_state() == NEEDS_SETUP
|
||||
"""
|
||||
return self.get_setup_state() == self.SetupState.NEEDS_SETUP
|
||||
|
||||
def set_setup_version(self, version: int) -> None:
|
||||
"""Set the app's setup version."""
|
||||
from . import models
|
||||
|
||||
models.Module.objects.update_or_create(
|
||||
pk=self.app_id, defaults={'setup_version': version})
|
||||
|
||||
def enable(self):
|
||||
"""Enable all the components of the app."""
|
||||
for component in self.components.values():
|
||||
|
||||
@ -4,6 +4,7 @@ Test module for App, base class for all applications.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import sys
|
||||
from unittest.mock import Mock, call, patch
|
||||
|
||||
import pytest
|
||||
@ -18,6 +19,16 @@ class AppTest(App):
|
||||
app_id = 'test-app'
|
||||
|
||||
|
||||
class AppSetupTest(App):
|
||||
"""Sample App for testing setup operations."""
|
||||
app_id = 'test-app-setup'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
info = Info('test-app-setup', 3)
|
||||
self.add(info)
|
||||
|
||||
|
||||
class LeaderTest(FollowerComponent):
|
||||
"""Test class for using LeaderComponent in tests."""
|
||||
is_leader = True
|
||||
@ -124,6 +135,52 @@ def test_app_setup(app_with_components):
|
||||
component.setup.assert_has_calls([call(old_version=2)])
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_setup_state():
|
||||
"""Test retrieving the current setup state of the app."""
|
||||
app = AppSetupTest()
|
||||
app.info.version = 3
|
||||
module = sys.modules[__name__]
|
||||
|
||||
app.set_setup_version(3)
|
||||
assert app.get_setup_state() == App.SetupState.UP_TO_DATE
|
||||
assert not app.needs_setup()
|
||||
|
||||
app.set_setup_version(0)
|
||||
try:
|
||||
delattr(module, 'setup')
|
||||
except AttributeError:
|
||||
pass
|
||||
assert app.get_setup_state() == App.SetupState.UP_TO_DATE
|
||||
assert not app.needs_setup()
|
||||
assert app.get_setup_version() == 3
|
||||
|
||||
setattr(module, 'setup', True)
|
||||
app.set_setup_version(0)
|
||||
assert app.get_setup_state() == App.SetupState.NEEDS_SETUP
|
||||
assert app.needs_setup()
|
||||
|
||||
app.set_setup_version(2)
|
||||
assert app.get_setup_state() == App.SetupState.NEEDS_UPDATE
|
||||
assert not app.needs_setup()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_get_set_setup_version():
|
||||
"""Setting and getting the setup version of the app."""
|
||||
app = AppSetupTest()
|
||||
|
||||
from plinth import models
|
||||
try:
|
||||
models.Module.objects.get(pk=app.app_id).delete()
|
||||
except models.Module.DoesNotExist:
|
||||
pass
|
||||
assert app.get_setup_version() == 0
|
||||
|
||||
app.set_setup_version(5)
|
||||
assert app.get_setup_version() == 5
|
||||
|
||||
|
||||
def test_app_enable(app_with_components):
|
||||
"""Test that enabling an app enables components."""
|
||||
app_with_components.disable()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user