make the base controller have no ui, add subclass for one that has ui
This commit is contained in:
parent
f6757af8d1
commit
edc65dbbfb
|
@ -20,12 +20,12 @@ from console_conf.ui.views import (
|
||||||
ChooserConfirmView,
|
ChooserConfirmView,
|
||||||
)
|
)
|
||||||
|
|
||||||
from subiquitycore.controller import BaseController
|
from subiquitycore.tuicontroller import TuiController
|
||||||
|
|
||||||
log = logging.getLogger("console_conf.controllers.chooser")
|
log = logging.getLogger("console_conf.controllers.chooser")
|
||||||
|
|
||||||
|
|
||||||
class RecoveryChooserBaseController(BaseController):
|
class RecoveryChooserBaseController(TuiController):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
|
|
|
@ -20,9 +20,9 @@ import pwd
|
||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from subiquitycore.controller import BaseController
|
|
||||||
from subiquitycore.ssh import host_key_info, get_ips_standalone
|
from subiquitycore.ssh import host_key_info, get_ips_standalone
|
||||||
from subiquitycore.snapd import SnapdConnection
|
from subiquitycore.snapd import SnapdConnection
|
||||||
|
from subiquitycore.tuicontroller import TuiController
|
||||||
from subiquitycore.utils import disable_console_conf, run_command
|
from subiquitycore.utils import disable_console_conf, run_command
|
||||||
|
|
||||||
from console_conf.ui.views import IdentityView, LoginView
|
from console_conf.ui.views import IdentityView, LoginView
|
||||||
|
@ -141,7 +141,7 @@ def write_login_details_standalone():
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
class IdentityController(BaseController):
|
class IdentityController(TuiController):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
|
|
||||||
from console_conf.ui.views import WelcomeView, ChooserWelcomeView
|
from console_conf.ui.views import WelcomeView, ChooserWelcomeView
|
||||||
|
|
||||||
from subiquitycore.controller import BaseController
|
from subiquitycore.tuicontroller import TuiController
|
||||||
|
|
||||||
|
|
||||||
class WelcomeController(BaseController):
|
class WelcomeController(TuiController):
|
||||||
|
|
||||||
welcome_view = WelcomeView
|
welcome_view = WelcomeView
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@ import jsonschema
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.controller import (
|
from subiquitycore.controller import (
|
||||||
BaseController,
|
BaseController,
|
||||||
|
)
|
||||||
|
from subiquitycore.tuicontroller import (
|
||||||
RepeatedController,
|
RepeatedController,
|
||||||
Skip,
|
TuiController,
|
||||||
)
|
)
|
||||||
|
|
||||||
log = logging.getLogger("subiquity.controller")
|
log = logging.getLogger("subiquity.controller")
|
||||||
|
@ -39,6 +41,9 @@ class SubiquityController(BaseController):
|
||||||
self.context.set('controller', self)
|
self.context.set('controller', self)
|
||||||
self.setup_autoinstall()
|
self.setup_autoinstall()
|
||||||
|
|
||||||
|
def interactive(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def setup_autoinstall(self):
|
def setup_autoinstall(self):
|
||||||
if self.app.autoinstall_config:
|
if self.app.autoinstall_config:
|
||||||
with self.context.child("load_autoinstall_data"):
|
with self.context.child("load_autoinstall_data"):
|
||||||
|
@ -68,15 +73,6 @@ class SubiquityController(BaseController):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def interactive(self):
|
|
||||||
if not self.app.autoinstall_config:
|
|
||||||
return True
|
|
||||||
i_sections = self.app.autoinstall_config.get(
|
|
||||||
'interactive-sections', [])
|
|
||||||
if '*' in i_sections or self.autoinstall_key in i_sections:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def configured(self):
|
def configured(self):
|
||||||
"""Let the world know that this controller's model is now configured.
|
"""Let the world know that this controller's model is now configured.
|
||||||
"""
|
"""
|
||||||
|
@ -90,15 +86,15 @@ class SubiquityController(BaseController):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class NoUIController(SubiquityController):
|
class SubiquityTuiController(SubiquityController, TuiController):
|
||||||
|
|
||||||
def start_ui(self):
|
|
||||||
raise Skip
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def interactive(self):
|
def interactive(self):
|
||||||
|
if not self.app.autoinstall_config:
|
||||||
|
return True
|
||||||
|
i_sections = self.app.autoinstall_config.get(
|
||||||
|
'interactive-sections', [])
|
||||||
|
if '*' in i_sections or self.autoinstall_key in i_sections:
|
||||||
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,10 @@ import os
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.utils import arun_command
|
from subiquitycore.utils import arun_command
|
||||||
|
|
||||||
from subiquity.controller import NoUIController
|
from subiquity.controller import SubiquityController
|
||||||
|
|
||||||
|
|
||||||
class CmdListController(NoUIController):
|
class CmdListController(SubiquityController):
|
||||||
|
|
||||||
autoinstall_default = []
|
autoinstall_default = []
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from subiquity.controller import NoUIController
|
from subiquity.controller import SubiquityController
|
||||||
|
|
||||||
|
|
||||||
class DebconfController(NoUIController):
|
class DebconfController(SubiquityController):
|
||||||
|
|
||||||
model_name = "debconf_selections"
|
model_name = "debconf_selections"
|
||||||
autoinstall_key = "debconf-selections"
|
autoinstall_key = "debconf-selections"
|
||||||
|
|
|
@ -34,7 +34,7 @@ from subiquitycore.utils import (
|
||||||
|
|
||||||
|
|
||||||
from subiquity.common.errorreport import ErrorReportKind
|
from subiquity.common.errorreport import ErrorReportKind
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.models.filesystem import (
|
from subiquity.models.filesystem import (
|
||||||
align_up,
|
align_up,
|
||||||
Bootloader,
|
Bootloader,
|
||||||
|
@ -61,7 +61,7 @@ PREP_GRUB_SIZE_BYTES = 8 * 1024 * 1024 # 8MiB
|
||||||
UEFI_GRUB_SIZE_BYTES = 512 * 1024 * 1024 # 512MiB EFI partition
|
UEFI_GRUB_SIZE_BYTES = 512 * 1024 * 1024 # 512MiB EFI partition
|
||||||
|
|
||||||
|
|
||||||
class FilesystemController(SubiquityController):
|
class FilesystemController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = "storage"
|
autoinstall_key = "storage"
|
||||||
autoinstall_schema = {'type': 'object'} # ...
|
autoinstall_schema = {'type': 'object'} # ...
|
||||||
|
|
|
@ -19,13 +19,13 @@ import attr
|
||||||
|
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views import IdentityView
|
from subiquity.ui.views import IdentityView
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controllers.identity')
|
log = logging.getLogger('subiquity.controllers.identity')
|
||||||
|
|
||||||
|
|
||||||
class IdentityController(SubiquityController):
|
class IdentityController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = model_name = "identity"
|
autoinstall_key = model_name = "identity"
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -44,7 +44,7 @@ from subiquitycore.utils import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from subiquity.common.errorreport import ErrorReportKind
|
from subiquity.common.errorreport import ErrorReportKind
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.journald import journald_listener
|
from subiquity.journald import journald_listener
|
||||||
from subiquity.ui.views.installprogress import ProgressView
|
from subiquity.ui.views.installprogress import ProgressView
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ class TracebackExtractor:
|
||||||
self.traceback.append(line)
|
self.traceback.append(line)
|
||||||
|
|
||||||
|
|
||||||
class InstallProgressController(SubiquityController):
|
class InstallProgressController(SubiquityTuiController):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
|
|
|
@ -20,14 +20,14 @@ import attr
|
||||||
from subiquitycore.async_helpers import schedule_task
|
from subiquitycore.async_helpers import schedule_task
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.models.keyboard import KeyboardSetting
|
from subiquity.models.keyboard import KeyboardSetting
|
||||||
from subiquity.ui.views import KeyboardView
|
from subiquity.ui.views import KeyboardView
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controllers.keyboard')
|
log = logging.getLogger('subiquity.controllers.keyboard')
|
||||||
|
|
||||||
|
|
||||||
class KeyboardController(SubiquityController):
|
class KeyboardController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = model_name = "keyboard"
|
autoinstall_key = model_name = "keyboard"
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -27,7 +27,7 @@ from subiquitycore.async_helpers import (
|
||||||
)
|
)
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views.mirror import MirrorView
|
from subiquity.ui.views.mirror import MirrorView
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controllers.mirror')
|
log = logging.getLogger('subiquity.controllers.mirror')
|
||||||
|
@ -40,7 +40,7 @@ class CheckState(enum.IntEnum):
|
||||||
DONE = enum.auto()
|
DONE = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
class MirrorController(SubiquityController):
|
class MirrorController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = "apt"
|
autoinstall_key = "apt"
|
||||||
autoinstall_schema = { # This is obviously incomplete.
|
autoinstall_schema = { # This is obviously incomplete.
|
||||||
|
|
|
@ -21,7 +21,7 @@ from subiquitycore.context import with_context
|
||||||
from subiquitycore.controllers.network import NetworkController
|
from subiquitycore.controllers.network import NetworkController
|
||||||
|
|
||||||
from subiquity.common.errorreport import ErrorReportKind
|
from subiquity.common.errorreport import ErrorReportKind
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger("subiquity.controllers.network")
|
log = logging.getLogger("subiquity.controllers.network")
|
||||||
|
@ -65,7 +65,7 @@ NETPLAN_SCHEMA = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class NetworkController(NetworkController, SubiquityController):
|
class NetworkController(NetworkController, SubiquityTuiController):
|
||||||
|
|
||||||
ai_data = None
|
ai_data = None
|
||||||
autoinstall_key = "network"
|
autoinstall_key = "network"
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from subiquity.controller import NoUIController
|
from subiquity.controller import SubiquityController
|
||||||
|
|
||||||
|
|
||||||
class PackageController(NoUIController):
|
class PackageController(SubiquityController):
|
||||||
|
|
||||||
model_name = autoinstall_key = "packages"
|
model_name = autoinstall_key = "packages"
|
||||||
autoinstall_default = []
|
autoinstall_default = []
|
||||||
|
|
|
@ -18,13 +18,13 @@ import os
|
||||||
|
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views.proxy import ProxyView
|
from subiquity.ui.views.proxy import ProxyView
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controllers.proxy')
|
log = logging.getLogger('subiquity.controllers.proxy')
|
||||||
|
|
||||||
|
|
||||||
class ProxyController(SubiquityController):
|
class ProxyController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = model_name = "proxy"
|
autoinstall_key = model_name = "proxy"
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -22,12 +22,12 @@ from subiquitycore.async_helpers import schedule_task
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.utils import arun_command, run_command
|
from subiquitycore.utils import arun_command, run_command
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
|
|
||||||
log = logging.getLogger("subiquity.controllers.restart")
|
log = logging.getLogger("subiquity.controllers.restart")
|
||||||
|
|
||||||
|
|
||||||
class RebootController(SubiquityController):
|
class RebootController(SubiquityTuiController):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
|
|
|
@ -25,12 +25,12 @@ from subiquitycore.async_helpers import (
|
||||||
SingleInstanceTask,
|
SingleInstanceTask,
|
||||||
)
|
)
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.controller import (
|
from subiquitycore.tuicontroller import (
|
||||||
Skip,
|
Skip,
|
||||||
)
|
)
|
||||||
|
|
||||||
from subiquity.controller import (
|
from subiquity.controller import (
|
||||||
SubiquityController,
|
SubiquityTuiController,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ class CheckState(enum.IntEnum):
|
||||||
UNAVAILABLE = enum.auto()
|
UNAVAILABLE = enum.auto()
|
||||||
|
|
||||||
|
|
||||||
class RefreshController(SubiquityController):
|
class RefreshController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = "refresh-installer"
|
autoinstall_key = "refresh-installer"
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -29,7 +29,7 @@ from curtin.reporter.handlers import (
|
||||||
LogHandler,
|
LogHandler,
|
||||||
)
|
)
|
||||||
|
|
||||||
from subiquity.controller import NoUIController
|
from subiquity.controller import SubiquityController
|
||||||
|
|
||||||
|
|
||||||
class LogHandler(LogHandler):
|
class LogHandler(LogHandler):
|
||||||
|
@ -46,7 +46,7 @@ INITIAL_CONFIG = {'logging': {'type': 'log'}}
|
||||||
NON_INTERACTIVE_CONFIG = {'builtin': {'type': 'print'}}
|
NON_INTERACTIVE_CONFIG = {'builtin': {'type': 'print'}}
|
||||||
|
|
||||||
|
|
||||||
class ReportingController(NoUIController):
|
class ReportingController(SubiquityController):
|
||||||
|
|
||||||
autoinstall_key = "reporting"
|
autoinstall_key = "reporting"
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -21,12 +21,12 @@ from subiquitycore.async_helpers import (
|
||||||
schedule_task,
|
schedule_task,
|
||||||
)
|
)
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.controller import (
|
from subiquitycore.tuicontroller import (
|
||||||
Skip,
|
Skip,
|
||||||
)
|
)
|
||||||
|
|
||||||
from subiquity.controller import (
|
from subiquity.controller import (
|
||||||
SubiquityController,
|
SubiquityTuiController,
|
||||||
)
|
)
|
||||||
|
|
||||||
from subiquity.models.snaplist import SnapSelection
|
from subiquity.models.snaplist import SnapSelection
|
||||||
|
@ -104,7 +104,7 @@ class SnapdSnapInfoLoader:
|
||||||
return self.tasks[snap]
|
return self.tasks[snap]
|
||||||
|
|
||||||
|
|
||||||
class SnapListController(SubiquityController):
|
class SnapListController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = "snaps"
|
autoinstall_key = "snaps"
|
||||||
autoinstall_default = []
|
autoinstall_default = []
|
||||||
|
|
|
@ -20,7 +20,7 @@ from subiquitycore.async_helpers import schedule_task
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore import utils
|
from subiquitycore import utils
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views.ssh import SSHView
|
from subiquity.ui.views.ssh import SSHView
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controllers.ssh')
|
log = logging.getLogger('subiquity.controllers.ssh')
|
||||||
|
@ -32,7 +32,7 @@ class FetchSSHKeysFailure(Exception):
|
||||||
self.output = output
|
self.output = output
|
||||||
|
|
||||||
|
|
||||||
class SSHController(SubiquityController):
|
class SSHController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = model_name = "ssh"
|
autoinstall_key = model_name = "ssh"
|
||||||
autoinstall_schema = {
|
autoinstall_schema = {
|
||||||
|
|
|
@ -13,10 +13,10 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from subiquity.controller import NoUIController
|
from subiquity.controller import SubiquityController
|
||||||
|
|
||||||
|
|
||||||
class UserdataController(NoUIController):
|
class UserdataController(SubiquityController):
|
||||||
|
|
||||||
model_name = 'userdata'
|
model_name = 'userdata'
|
||||||
autoinstall_key = "user-data"
|
autoinstall_key = "user-data"
|
||||||
|
|
|
@ -18,14 +18,14 @@ import os
|
||||||
|
|
||||||
from subiquitycore.screen import is_linux_tty
|
from subiquitycore.screen import is_linux_tty
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views import WelcomeView
|
from subiquity.ui.views import WelcomeView
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger('subiquity.controllers.welcome')
|
log = logging.getLogger('subiquity.controllers.welcome')
|
||||||
|
|
||||||
|
|
||||||
class WelcomeController(SubiquityController):
|
class WelcomeController(SubiquityTuiController):
|
||||||
|
|
||||||
autoinstall_key = model_name = "locale"
|
autoinstall_key = model_name = "locale"
|
||||||
autoinstall_schema = {'type': 'string'}
|
autoinstall_schema = {'type': 'string'}
|
||||||
|
|
|
@ -24,7 +24,7 @@ from urwid import Text
|
||||||
from subiquitycore.ui.utils import Color
|
from subiquitycore.ui.utils import Color
|
||||||
from subiquitycore.utils import run_command
|
from subiquitycore.utils import run_command
|
||||||
|
|
||||||
from subiquity.controller import SubiquityController
|
from subiquity.controller import SubiquityTuiController
|
||||||
from subiquity.ui.views import ZdevView
|
from subiquity.ui.views import ZdevView
|
||||||
|
|
||||||
|
|
||||||
|
@ -631,7 +631,7 @@ class ZdevInfo:
|
||||||
return self.type
|
return self.type
|
||||||
|
|
||||||
|
|
||||||
class ZdevController(SubiquityController):
|
class ZdevController(SubiquityTuiController):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
super().__init__(app)
|
super().__init__(app)
|
||||||
|
|
|
@ -31,7 +31,7 @@ from subiquitycore.async_helpers import (
|
||||||
run_in_thread,
|
run_in_thread,
|
||||||
schedule_task,
|
schedule_task,
|
||||||
)
|
)
|
||||||
from subiquitycore.controller import Skip
|
from subiquitycore.tuicontroller import Skip
|
||||||
from subiquitycore.tui import TuiApplication
|
from subiquitycore.tui import TuiApplication
|
||||||
from subiquitycore.snapd import (
|
from subiquitycore.snapd import (
|
||||||
AsyncSnapd,
|
AsyncSnapd,
|
||||||
|
|
|
@ -13,16 +13,12 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
log = logging.getLogger("subiquitycore.controller")
|
log = logging.getLogger("subiquitycore.controller")
|
||||||
|
|
||||||
|
|
||||||
class Skip(Exception):
|
|
||||||
"""Raise this from a controller's start_ui method to skip a screen."""
|
|
||||||
|
|
||||||
|
|
||||||
class BaseController(ABC):
|
class BaseController(ABC):
|
||||||
"""Base class for controllers."""
|
"""Base class for controllers."""
|
||||||
|
|
||||||
|
@ -31,12 +27,10 @@ class BaseController(ABC):
|
||||||
|
|
||||||
def __init__(self, app):
|
def __init__(self, app):
|
||||||
self.name = type(self).__name__[:-len("Controller")]
|
self.name = type(self).__name__[:-len("Controller")]
|
||||||
self.ui = app.ui
|
|
||||||
self.signal = app.signal
|
self.signal = app.signal
|
||||||
self.opts = app.opts
|
self.opts = app.opts
|
||||||
self.app = app
|
self.app = app
|
||||||
self.context = self.app.context.child(self.name, childlevel="DEBUG")
|
self.context = self.app.context.child(self.name, childlevel="DEBUG")
|
||||||
self.answers = app.answers.get(self.name, {})
|
|
||||||
if self.model_name is not None:
|
if self.model_name is not None:
|
||||||
self.model = getattr(self.app.base_model, self.model_name)
|
self.model = getattr(self.app.base_model, self.model_name)
|
||||||
|
|
||||||
|
@ -57,92 +51,9 @@ class BaseController(ABC):
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def cancel(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
|
||||||
def showing(self):
|
|
||||||
inst = self.app.controllers.cur
|
|
||||||
while isinstance(inst, RepeatedController):
|
|
||||||
inst = inst.orig
|
|
||||||
return inst is self
|
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def start_ui(self):
|
|
||||||
"""Start running this controller's UI.
|
|
||||||
|
|
||||||
This method should call self.ui.set_body.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def end_ui(self):
|
|
||||||
"""Stop running this controller's UI.
|
|
||||||
|
|
||||||
This method doesn't actually need to remove this controller's UI
|
|
||||||
as the next one is about to replace it, it's more of a hook to
|
|
||||||
stop any background tasks that can be stopped when the UI is not
|
|
||||||
running.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def deserialize(self, data):
|
def deserialize(self, data):
|
||||||
if data is not None:
|
if data is not None:
|
||||||
raise Exception("missing deserialize method on {}".format(self))
|
raise Exception("missing deserialize method on {}".format(self))
|
||||||
|
|
||||||
# Stuff for fine grained actions, used by filesystem and network
|
|
||||||
# controller at time of writing this comment.
|
|
||||||
|
|
||||||
def _enter_form_data(self, form, data, submit, clean_suffix=''):
|
|
||||||
for k, v in data.items():
|
|
||||||
c = getattr(
|
|
||||||
self, '_action_clean_{}_{}'.format(k, clean_suffix), None)
|
|
||||||
if c is None:
|
|
||||||
c = getattr(self, '_action_clean_{}'.format(k), lambda x: x)
|
|
||||||
field = getattr(form, k)
|
|
||||||
from subiquitycore.ui.selector import Selector
|
|
||||||
v = c(v)
|
|
||||||
if isinstance(field.widget, Selector):
|
|
||||||
field.widget._emit('select', v)
|
|
||||||
field.value = v
|
|
||||||
yield
|
|
||||||
yield
|
|
||||||
for bf in form._fields:
|
|
||||||
bf.validate()
|
|
||||||
form.validated()
|
|
||||||
if submit:
|
|
||||||
if not form.done_btn.enabled:
|
|
||||||
raise Exception("answers left form invalid!")
|
|
||||||
form._click_done(None)
|
|
||||||
|
|
||||||
def _run_actions(self, actions):
|
|
||||||
for action in actions:
|
|
||||||
yield from self._answers_action(action)
|
|
||||||
|
|
||||||
def _run_iterator(self, it, delay=None):
|
|
||||||
if delay is None:
|
|
||||||
delay = 0.2/self.app.scale_factor
|
|
||||||
try:
|
|
||||||
next(it)
|
|
||||||
except StopIteration:
|
|
||||||
return
|
|
||||||
self.app.aio_loop.call_later(delay, self._run_iterator, it, delay/1.1)
|
|
||||||
|
|
||||||
|
|
||||||
class RepeatedController(BaseController):
|
|
||||||
|
|
||||||
def __init__(self, orig, index):
|
|
||||||
self.name = "{}-{}".format(orig.name, index)
|
|
||||||
self.orig = orig
|
|
||||||
self.index = index
|
|
||||||
self.context = orig.context
|
|
||||||
|
|
||||||
def register_signals(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def start_ui(self):
|
|
||||||
self.orig.start_ui(self.index)
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
self.orig.cancel()
|
|
||||||
|
|
|
@ -24,13 +24,13 @@ from probert.network import IFF_UP, NetworkEventReceiver
|
||||||
|
|
||||||
from subiquitycore.async_helpers import SingleInstanceTask
|
from subiquitycore.async_helpers import SingleInstanceTask
|
||||||
from subiquitycore.context import with_context
|
from subiquitycore.context import with_context
|
||||||
from subiquitycore.controller import BaseController
|
|
||||||
from subiquitycore.file_util import write_file
|
from subiquitycore.file_util import write_file
|
||||||
from subiquitycore.models.network import (
|
from subiquitycore.models.network import (
|
||||||
BondParameters,
|
BondParameters,
|
||||||
NetDevAction,
|
NetDevAction,
|
||||||
)
|
)
|
||||||
from subiquitycore import netplan
|
from subiquitycore import netplan
|
||||||
|
from subiquitycore.tuicontroller import TuiController
|
||||||
from subiquitycore.ui.stretchy import StretchyOverlay
|
from subiquitycore.ui.stretchy import StretchyOverlay
|
||||||
from subiquitycore.ui.views.network import (
|
from subiquitycore.ui.views.network import (
|
||||||
NetworkView,
|
NetworkView,
|
||||||
|
@ -134,7 +134,7 @@ network:
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
class NetworkController(BaseController):
|
class NetworkController(TuiController):
|
||||||
|
|
||||||
model_name = "network"
|
model_name = "network"
|
||||||
root = "/"
|
root = "/"
|
||||||
|
|
|
@ -20,13 +20,13 @@ import yaml
|
||||||
import urwid
|
import urwid
|
||||||
|
|
||||||
from subiquitycore.async_helpers import schedule_task
|
from subiquitycore.async_helpers import schedule_task
|
||||||
from subiquitycore.controller import Skip
|
|
||||||
from subiquitycore.core import Application
|
from subiquitycore.core import Application
|
||||||
from subiquitycore.palette import (
|
from subiquitycore.palette import (
|
||||||
PALETTE_COLOR,
|
PALETTE_COLOR,
|
||||||
PALETTE_MONO,
|
PALETTE_MONO,
|
||||||
)
|
)
|
||||||
from subiquitycore.screen import make_screen
|
from subiquitycore.screen import make_screen
|
||||||
|
from subiquitycore.tuicontroller import Skip
|
||||||
from subiquitycore.ui.frame import SubiquityCoreUI
|
from subiquitycore.ui.frame import SubiquityCoreUI
|
||||||
from subiquitycore.utils import arun_command
|
from subiquitycore.utils import arun_command
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ class TuiApplication(Application):
|
||||||
# Set rich_mode to the opposite of what we want, so we can
|
# Set rich_mode to the opposite of what we want, so we can
|
||||||
# call toggle_rich to get the right things set up.
|
# call toggle_rich to get the right things set up.
|
||||||
self.rich_mode = opts.run_on_serial
|
self.rich_mode = opts.run_on_serial
|
||||||
|
|
||||||
self.urwid_loop = None
|
self.urwid_loop = None
|
||||||
|
self.cur_screen = None
|
||||||
|
|
||||||
def _remove_last_screen(self):
|
def _remove_last_screen(self):
|
||||||
last_screen = self.state_path('last-screen')
|
last_screen = self.state_path('last-screen')
|
||||||
|
@ -102,6 +102,7 @@ class TuiApplication(Application):
|
||||||
raise Skip
|
raise Skip
|
||||||
try:
|
try:
|
||||||
new.start_ui()
|
new.start_ui()
|
||||||
|
self.cur_screen = new
|
||||||
except Skip:
|
except Skip:
|
||||||
new.context.exit("(skipped)")
|
new.context.exit("(skipped)")
|
||||||
raise
|
raise
|
||||||
|
@ -110,7 +111,7 @@ class TuiApplication(Application):
|
||||||
|
|
||||||
def _move_screen(self, increment):
|
def _move_screen(self, increment):
|
||||||
self.save_state()
|
self.save_state()
|
||||||
old = self.controllers.cur
|
old, self.cur_screen = self.cur_screen, None
|
||||||
if old is not None:
|
if old is not None:
|
||||||
old.context.exit("completed")
|
old.context.exit("completed")
|
||||||
old.end_ui()
|
old.end_ui()
|
||||||
|
@ -142,6 +143,8 @@ class TuiApplication(Application):
|
||||||
for controller in self.controllers.instances[:controller_index]:
|
for controller in self.controllers.instances[:controller_index]:
|
||||||
controller.configured()
|
controller.configured()
|
||||||
self.controllers.index = controller_index - 1
|
self.controllers.index = controller_index - 1
|
||||||
|
for controller in self.controllers.instances[:controller_index]:
|
||||||
|
controller.configured()
|
||||||
self.next_screen()
|
self.next_screen()
|
||||||
|
|
||||||
def run_scripts(self, scripts):
|
def run_scripts(self, scripts):
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
# Copyright 2020 Canonical, Ltd.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from abc import abstractmethod
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from subiquitycore.controller import BaseController
|
||||||
|
|
||||||
|
log = logging.getLogger("subiquitycore.tuicontroller")
|
||||||
|
|
||||||
|
|
||||||
|
class Skip(Exception):
|
||||||
|
"""Raise this from a controller's start_ui method to skip a screen."""
|
||||||
|
|
||||||
|
|
||||||
|
class TuiController(BaseController):
|
||||||
|
"""Base class for controllers."""
|
||||||
|
|
||||||
|
def __init__(self, app):
|
||||||
|
super().__init__(app)
|
||||||
|
self.ui = app.ui
|
||||||
|
self.answers = app.answers.get(self.name, {})
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def cancel(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def showing(self):
|
||||||
|
inst = self.app.controllers.cur
|
||||||
|
while isinstance(inst, RepeatedController):
|
||||||
|
inst = inst.orig
|
||||||
|
return inst is self
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def start_ui(self):
|
||||||
|
"""Start running this controller's UI.
|
||||||
|
|
||||||
|
This method should call self.ui.set_body.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def end_ui(self):
|
||||||
|
"""Stop running this controller's UI.
|
||||||
|
|
||||||
|
This method doesn't actually need to remove this controller's UI
|
||||||
|
as the next one is about to replace it, it's more of a hook to
|
||||||
|
stop any background tasks that can be stopped when the UI is not
|
||||||
|
running.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Stuff for fine grained actions, used by filesystem and network
|
||||||
|
# controller at time of writing this comment.
|
||||||
|
|
||||||
|
def _enter_form_data(self, form, data, submit, clean_suffix=''):
|
||||||
|
for k, v in data.items():
|
||||||
|
c = getattr(
|
||||||
|
self, '_action_clean_{}_{}'.format(k, clean_suffix), None)
|
||||||
|
if c is None:
|
||||||
|
c = getattr(self, '_action_clean_{}'.format(k), lambda x: x)
|
||||||
|
field = getattr(form, k)
|
||||||
|
from subiquitycore.ui.selector import Selector
|
||||||
|
v = c(v)
|
||||||
|
if isinstance(field.widget, Selector):
|
||||||
|
field.widget._emit('select', v)
|
||||||
|
field.value = v
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
for bf in form._fields:
|
||||||
|
bf.validate()
|
||||||
|
form.validated()
|
||||||
|
if submit:
|
||||||
|
if not form.done_btn.enabled:
|
||||||
|
raise Exception("answers left form invalid!")
|
||||||
|
form._click_done(None)
|
||||||
|
|
||||||
|
def _run_actions(self, actions):
|
||||||
|
for action in actions:
|
||||||
|
yield from self._answers_action(action)
|
||||||
|
|
||||||
|
def _run_iterator(self, it, delay=None):
|
||||||
|
if delay is None:
|
||||||
|
delay = 0.2/self.app.scale_factor
|
||||||
|
try:
|
||||||
|
next(it)
|
||||||
|
except StopIteration:
|
||||||
|
return
|
||||||
|
self.app.aio_loop.call_later(delay, self._run_iterator, it, delay/1.1)
|
||||||
|
|
||||||
|
|
||||||
|
class RepeatedController(BaseController):
|
||||||
|
|
||||||
|
def __init__(self, orig, index):
|
||||||
|
self.name = "{}-{}".format(orig.name, index)
|
||||||
|
self.orig = orig
|
||||||
|
self.index = index
|
||||||
|
self.context = orig.context
|
||||||
|
|
||||||
|
def register_signals(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_ui(self):
|
||||||
|
self.orig.start_ui(self.index)
|
||||||
|
|
||||||
|
def end_ui(self):
|
||||||
|
self.orig.end_ui()
|
||||||
|
|
||||||
|
def cancel(self):
|
||||||
|
self.orig.cancel()
|
Loading…
Reference in New Issue