Skip to content

Commit fda2048

Browse files
authored
Merge pull request datalad#7578 from christian-monch/fix-remote-interaction
Raise exception if an annex remote process without console tries to interact with the user, e.g. prompt for a password
2 parents 864dc4a + c6aa6ae commit fda2048

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

changelog.d/pr-7578.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### 🐛 Bug Fixes
2+
3+
- Raise exception if an annex remote process without console tries to interact with the user, e.g. prompt for a password. [PR #7578](https://github.com/datalad/datalad/pull/7578) (by [@christian-monch](https://github.com/christian-monch))

datalad/ui/dialog.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from ..utils import auto_repr
3232
from ..utils import on_windows
3333
from .base import InteractiveUI
34+
from .utils import can_prompt
3435
from datalad.support.exceptions import CapturedException
3536

3637
# Example APIs which might be useful to look for "inspiration"
@@ -357,6 +358,32 @@ def get_progressbar(self, *args, **kwargs):
357358
return super(UnderAnnexUI, self).get_progressbar(
358359
*args, **kwargs)
359360

361+
def input(self, prompt, hidden=False):
362+
if not can_prompt():
363+
# we are not interactive
364+
raise RuntimeError('Interactive input not available for `ui.input()` in annex remotes')
365+
return super(UnderAnnexUI, self).input(prompt, hidden)
366+
367+
def question(self,
368+
text,
369+
title=None,
370+
choices=None,
371+
default=None,
372+
hidden=False,
373+
repeat=None):
374+
if not can_prompt():
375+
# need to do a more specific that `is_interactive` check, since `is_interactive` checks
376+
# all streams including stdin/out which are to "talk" to git-annex, and thus not tty.
377+
raise RuntimeError('A terminal required for interactive input in annex remotes')
378+
return super(UnderAnnexUI, self).question(
379+
text,
380+
title=title,
381+
choices=choices,
382+
default=default,
383+
hidden=hidden,
384+
repeat=repeat
385+
)
386+
360387

361388
@auto_repr
362389
class UnderTestsUI(DialogUI):

datalad/ui/utils.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,22 @@ def show_hint(msg):
7373
ui.message("{}".format(
7474
ansi_colors.color_word(
7575
msg,
76-
ansi_colors.YELLOW)))
76+
ansi_colors.YELLOW)))
77+
78+
79+
def can_prompt() -> bool:
80+
"""Return True if the process can prompt for credentials
81+
82+
On Linux this method checks for a controlling terminal.
83+
On Windows it always returns True.
84+
Unlike :func:`datalad.utils.is_interactive` it does not check all the streams to be a tty,
85+
and just tries to open `/dev/tty` directly.
86+
"""
87+
if on_windows:
88+
return True
89+
else:
90+
try:
91+
open('/dev/tty', 'r').close()
92+
return True
93+
except (IOError, OSError):
94+
return False

0 commit comments

Comments
 (0)