Skip to content

Commit

Permalink
Add NoDialogUnderAnnexUI
Browse files Browse the repository at this point in the history
This adds a non-interactive UI backend for annex special remotes and the
respective capacity for the UI_Switcher.

Closes #7345
  • Loading branch information
bpoldrack committed Mar 24, 2023
1 parent 253b527 commit 6cfd40b
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 18 deletions.
2 changes: 1 addition & 1 deletion datalad/customremotes/__init__.py
Expand Up @@ -56,7 +56,7 @@ class SpecialRemote(_SpecialRemote):
def __init__(self, annex):
super(SpecialRemote, self).__init__(annex=annex)
# instruct annex backend UI to use this remote
if ui.backend == 'annex':
if ui.backend in ['annex', 'annex-no-dialog']:
ui.set_specialremote(self)

def message(self, msg, type='debug'):
Expand Down
4 changes: 4 additions & 0 deletions datalad/ui/__init__.py
Expand Up @@ -22,6 +22,7 @@
ConsoleLog,
DialogUI,
IPythonUI,
NoDialogUnderAnnexUI,
UnderAnnexUI,
UnderTestsUI,
SilentConsoleLog,
Expand All @@ -36,6 +37,7 @@
'dialog': DialogUI,
'ipython': IPythonUI,
'annex': UnderAnnexUI,
'annex-no-dialog': NoDialogUnderAnnexUI,
'tests': UnderTestsUI,
'tests-noninteractive': QuietConsoleLog,
'no-progress': SilentConsoleLog,
Expand Down Expand Up @@ -82,6 +84,8 @@ def set_backend(self, backend):
backend = 'dialog'
else:
backend = 'dialog' if is_interactive else 'no-progress'
if not is_interactive and backend == 'annex':
backend = 'annex-no-dialog'
self._ui = KNOWN_BACKENDS[backend]()
lgr.debug("UI set to %s", self._ui)
self._backend = backend
Expand Down
24 changes: 24 additions & 0 deletions datalad/ui/dialog.py
Expand Up @@ -357,6 +357,30 @@ def get_progressbar(self, *args, **kwargs):
*args, **kwargs)


@auto_repr
class NoDialogUnderAnnexUI(SilentConsoleLog):
def __init__(self, specialremote=None, **kwargs):
if 'out' not in kwargs:
# to avoid buffering
# http://stackoverflow.com/a/181654/1265472
#kwargs['out'] = os.fdopen(sys.stderr.fileno(), 'w', 0)
# but wasn't effective! sp kist straogjt for now
kwargs['out'] = sys.stderr
super(NoDialogUnderAnnexUI, self).__init__(**kwargs)
self.specialremote = specialremote

def set_specialremote(self, specialremote):
self.specialremote = specialremote

def get_progressbar(self, *args, **kwargs):
if self.specialremote:
kwargs = kwargs.copy()
kwargs['backend'] = 'annex-remote'
kwargs['remote'] = self.specialremote
return super(NoDialogUnderAnnexUI, self).get_progressbar(
*args, **kwargs)


@auto_repr
class UnderTestsUI(DialogUI):
"""UI to help with testing functionality requiring interaction
Expand Down
13 changes: 12 additions & 1 deletion datalad/ui/tests/test_base.py
Expand Up @@ -15,15 +15,21 @@
from ...tests.utils_pytest import (
assert_equal,
assert_false,
assert_is_instance,
assert_not_equal,
assert_raises,
with_testsui,
)
from .. import _UI_Switcher
from .. import (
_UI_Switcher,
is_interactive
)
from ..dialog import (
ConsoleLog,
DialogUI,
IPythonUI,
NoDialogUnderAnnexUI,
UnderAnnexUI,
)


Expand All @@ -41,6 +47,11 @@ def test_ui_switcher():
ui.yesno

ui.set_backend('annex')
if is_interactive:
assert_is_instance(ui._ui, UnderAnnexUI)
else:
assert_is_instance(ui._ui, NoDialogUnderAnnexUI)
assert_equal(is_interactive, ui._ui.is_interactive)

# Let's pretend we are under IPython
class ZMQInteractiveShell(object):
Expand Down
33 changes: 17 additions & 16 deletions datalad/ui/tests/test_dialog.py
Expand Up @@ -173,22 +173,23 @@ def test_silent_question():
# SilentConsoleLog must not be asked questions.
# If it is asked, RuntimeError would be thrown with details to help
# troubleshooting WTF is happening
from ..dialog import SilentConsoleLog
ui = SilentConsoleLog()
with assert_raises(RuntimeError) as cme:
ui.question("could you help me", title="Pretty please")
assert_in('question: could you help me. Title: Pretty please.', str(cme.value))

with assert_raises(RuntimeError) as cme:
ui.question("could you help me", title="Pretty please", choices=['secret1'], hidden=True)
assert_in('question: could you help me. Title: Pretty please.', str(cme.value))
assert_not_in('secret1', str(cme.value))
assert_in('not shown', str(cme.value))

# additional kwargs, no title, choices
with assert_raises(RuntimeError) as cme:
ui.question("q", choices=['secret1'])
assert_in('secret1', str(cme.value))
from ..dialog import SilentConsoleLog, NoDialogUnderAnnexUI
for k in [SilentConsoleLog, NoDialogUnderAnnexUI]:
ui = k()
with assert_raises(RuntimeError) as cme:
ui.question("could you help me", title="Pretty please")
assert_in('question: could you help me. Title: Pretty please.', str(cme.value))

with assert_raises(RuntimeError) as cme:
ui.question("could you help me", title="Pretty please", choices=['secret1'], hidden=True)
assert_in('question: could you help me. Title: Pretty please.', str(cme.value))
assert_not_in('secret1', str(cme.value))
assert_in('not shown', str(cme.value))

# additional kwargs, no title, choices
with assert_raises(RuntimeError) as cme:
ui.question("q", choices=['secret1'])
assert_in('secret1', str(cme.value))


@patch("datalad.log.is_interactive", False)
Expand Down

0 comments on commit 6cfd40b

Please sign in to comment.