We used to set LC_ALL=C unconditionally when executing a command. This
is a problem if we want the output of a specific command to be
translated (provided a locale definition and an actual translation exist
for the requested language).
This patch adds the clean_locale parameter, which can be used to specify
if we want the locale variable to be cleaned, to most of the helpers
that execute commands.
The value defaults to True so the default behavior is preserved.
If one wants a command to be translated, they have to explicitly pass
clean_locale=False.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
calling asyncio.create_task(...) without storing a reference to the
result can lead to the task being garbage collected before it actually
executed.
https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
The documentation gives an example of a reliable way to run
fire-and-forget background tasks.
This patch adds an helper to do exactly that.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
The new ConfirmationOverlay object along with the
BaseView.ask_confirmation helper can be used to open a confirmation
dialog and get back the decision from the user.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
Specifying the value of subprocess.PIPE as the stdin argument of
astart_command did not have any effect. This happened because the
parameter was not forwarded to the subprocess function. The parameter
was effectively unused.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
Attempting to close an overlay that does not exist is pretty much always
a bug in the code. Making not_found_ok true by default will hide obvious
bugs from us ; which is not a good thing. Perhaps more importantly, we
might just remove the wrong overlay.
Instead, we should just pass not_found_ok=True as a workaround when we
know the code is buggy and don't have time to fix the bug cleanly.
This is what happens for SSH keys import. If the import fails, we remove
the loading animation. However for answers-based runs, we do not have a
loading animation so the code bails. Let's add not_found_ok=True in this
context and we can fix the code later.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
BaseView.remove_overlay() would crash with AttributeError if no overlay
was found. We now add a not_found_ok parameter (defaulting to True) that
makes the function silently return if the overlay could not be found.
Passing not_found_ok=False and catching OverlayNotFoundError can be
helpful in some scenarios to do something different if no overlay was
found.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
I implemented these a long time ago to help working on parts of the ui
by allowing a way to script moving past some screens. I haven't used
them in ages, it's pretty bad code and probably a fragmentary answers
file is a better solution to the same problem. What do you think?
When executing a command via arun_command with check=True, we forge
and then raise a CalledProcessError exception if the command exits
abnormally (i.e., exit code != 0).
When doing so, we only instantiate the exception with the exit code and
the command executed. This means that we lose access to any output
captured so far. This is usually fine for stdout but stderr oftentimes
contains invaluable information to understand what caused the command to
exit abnormally.
Back in Python 3.5, stdout and stderr were introduced as new attributes
for CalledProcessError.
We now also include stdout and stderr in the CalledProcessError
instances that we forge. This allows us to access stderr (if any) when
catching the exception with:
try:
...
except CalledProcessError as exc:
print(exc.stderr)
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
asyncio.create_task() calls asyncio.get_running_loop() under the hood so
there is no need to call get_running_loop() ourselves if the sole
purpose is to create a task.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
The behavior of asyncio.get_event_loop() will change in a future Python
version. It is deprecated starting Python 3.10.
The functions that we can use instead are:
* asyncio.new_event_loop() - which creates a new event loop
* asyncio.get_running_loop() - which returns the event loop only if it
is already running
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
We now have the view display the user-code fetched via u-a-c and
automatically validate the contract token when the contract selection
succeeds.
If the magic token expires (i.e., u-a-c times out), a new contract
selection is initiated.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
Tests that use run_coro are at risk of being broken by the introduction
of another test using IsolatedAsyncioTestCase. Switch over to only use
IsolatedAsyncioTestCase.
Instead of using isinstance(self.widget, SubFormWidget) in
BoundFormField.is_in_error, we now implement a BoundSubFormField
class that inherits from BoundFormField. It is meant to be instantianted
for subforms fields only.
This class overrides is_in_error() to perform the additional checks in
the forms' sub-fields.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
When the validation of a field fails in a form, we disable the Done
button. With child forms, however, it did not work because they have
their own set of hidden buttons ; that are not the ones the users
interacts with.
This patch makes parent forms recurse on the child forms when checking
if any field is in error. Also, when a child form undertakes validation,
it now propagates to the parent, so that the done button can be
immediately enabled/disabled.
Having a validation error in a child form that is not currently enabled
should not prevent the user from moving forward, so we disable recursion
for child forms that are disabled.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
cancel_restart is a mode for SingleInstanceTask that changes the
behavior when starting the task - if the task is already running, do not
cancel it to start another.
We used to rely on the narrow non-breakable space to be displayed as a
star in basic mode. This is not great and could impact other screens.
We now make use of two check-marks (each replaced by a star in basic
mode) and mask one of them in rich mode using display attributes.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
The "**" signs replace the check-mark for a verified publisher when in
basic mode.
These "**" signs where still used green foreground color. This was the
only place where we tried to display colors in basic mode.
Keep the default colors instead. This should be more compatible.
Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>