source: give the option to search for third-party drivers

The source screen now includes a checkbox that makes Subiquity search
for third-party drivers in a later stage.

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2022-03-29 15:18:56 +02:00
parent 800801b7d0
commit c76a8f23e3
7 changed files with 57 additions and 14 deletions

View File

@ -27,18 +27,27 @@ class SourceController(SubiquityTuiController):
async def make_ui(self):
sources = await self.endpoint.GET()
return SourceView(self, sources.sources, sources.current_id)
return SourceView(self,
sources.sources,
sources.current_id,
sources.search_drivers)
def run_answers(self):
form = self.app.ui.body.form
if "search_drivers" in self.answers:
form.search_drivers.value = self.answers["search_drivers"]
if 'source' in self.answers:
wanted_id = self.answers['source']
for bf in self.app.ui.body.form._fields:
for bf in form._fields:
if bf is form.search_drivers:
continue
bf.value = bf.field.name == wanted_id
self.app.ui.body.form._click_done(None)
form._click_done(None)
def cancel(self):
self.app.prev_screen()
def done(self, source_id):
log.debug("SourceController.done source_id=%s", source_id)
self.app.next_screen(self.endpoint.POST(source_id))
def done(self, source_id, search_drivers: bool):
log.debug("SourceController.done source_id=%s, search_drivers=%s",
source_id, search_drivers)
self.app.next_screen(self.endpoint.POST(source_id, search_drivers))

View File

@ -145,7 +145,7 @@ class API:
class source:
def GET() -> SourceSelectionAndSetting: ...
def POST(source_id: str) -> None: ...
def POST(source_id: str, search_drivers: bool) -> None: ...
class zdev:
def GET() -> List[ZdevInfo]: ...

View File

@ -183,6 +183,7 @@ class SourceSelection:
class SourceSelectionAndSetting:
sources: List[SourceSelection]
current_id: str
search_drivers: bool
@attr.s(auto_attribs=True)

View File

@ -68,6 +68,7 @@ class SourceModel:
self.current = fake_entries['server']
self.sources = [self.current]
self.lang = None
self.search_drivers = False
def load_from_file(self, fp):
self._dir = os.path.dirname(fp.name)

View File

@ -86,7 +86,8 @@ class SourceController(SubiquityController):
convert_source(source, cur_lang)
for source in self.model.sources
],
self.model.current.id)
self.model.current.id,
search_drivers=self.model.search_drivers)
async def configured(self):
if self._handler is not None:
@ -100,7 +101,8 @@ class SourceController(SubiquityController):
await super().configured()
self.app.base_model.set_source_variant(self.model.current.variant)
async def POST(self, source_id: str) -> None:
async def POST(self, source_id: str, search_drivers: bool) -> None:
self.model.search_drivers = search_drivers
for source in self.model.sources:
if source.id == source_id:
self.model.current = source

View File

@ -948,6 +948,8 @@ class TestCancel(TestAPI):
async def test_cancel_drivers(self):
with patch.dict(os.environ, {'SUBIQUITY_DEBUG': 'has-drivers'}):
async with start_server('examples/simple.json') as inst:
await inst.post('/source', source_id="dummy",
search_drivers=True)
# /drivers?wait=true is expected to block until APT is
# configured.
# Let's make sure we cancel it.

View File

@ -14,13 +14,21 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
from urwid import connect_signal
from typing import List
from urwid import (
connect_signal,
Text,
)
from subiquitycore.view import BaseView
from subiquitycore.ui.container import ListBox
from subiquitycore.ui.form import (
BooleanField,
Form,
RadioButtonField,
)
from subiquitycore.ui.utils import screen
log = logging.getLogger('subiquity.ui.views.source')
@ -29,10 +37,10 @@ class SourceView(BaseView):
title = _("Choose type of install")
def __init__(self, controller, sources, current_id):
def __init__(self, controller, sources, current_id, search_drivers: bool):
self.controller = controller
group = []
group: List[RadioButtonField] = []
ns = {
'cancel_label': _("Back"),
@ -47,6 +55,12 @@ class SourceView(BaseView):
group, source.name, '\n' + source.description)
initial[source.id] = source.id == current_id
ns["search_drivers"] = BooleanField(
_("Search for third-party drivers"), "\n" +
_("This software is subject to license terms included with its "
"documentation. Some is proprietary."))
initial["search_drivers"] = search_drivers
SourceForm = type(Form)('SourceForm', (Form,), ns)
log.debug('%r %r', ns, current_id)
@ -57,13 +71,27 @@ class SourceView(BaseView):
excerpt = _("Choose the base for the installation.")
super().__init__(self.form.as_screen(excerpt=excerpt))
# NOTE Hack to insert the "Additional options" text between two fields
# of the form.
rows = self.form.as_rows()
rows.insert(-2, Text(""))
rows.insert(-2, Text("Additional options"))
super().__init__(
screen(
ListBox(rows),
self.form.buttons,
excerpt=excerpt,
focus_buttons=True))
def done(self, result):
log.debug("User input: {}".format(result.as_data()))
search_drivers = result.as_data()["search_drivers"]
for k, v in result.as_data().items():
if k == "search_drivers":
continue
if v:
self.controller.done(k)
self.controller.done(k, search_drivers=search_drivers)
def cancel(self, result=None):
self.controller.cancel()