more docstrings and properly support (and use) encoding=None throughout

This commit is contained in:
Jean-Paul Calderone 2020-12-07 09:47:48 -05:00
parent 05d271c7c8
commit 72744c9464
3 changed files with 63 additions and 8 deletions

View File

@ -10,7 +10,24 @@ def parse_options(basedir, command, args):
return o
class CLITestMixin(ReallyEqualMixin):
"""
A mixin for use with ``GridTestMixin`` to execute CLI commands against
nodes created by methods of that mixin.
"""
def do_cli_unicode(self, verb, argv, client_num=0, **kwargs):
"""
Run a Tahoe-LAFS CLI command.
:param verb: See ``run_cli_unicode``.
:param argv: See ``run_cli_unicode``.
:param int client_num: The number of the ``GridTestMixin``-created
node against which to execute the command.
:param kwargs: Additional keyword arguments to pass to
``run_cli_unicode``.
"""
# client_num is used to execute client CLI commands on a specific
# client.
client_dir = self.get_clientdir(i=client_num)
@ -19,6 +36,10 @@ class CLITestMixin(ReallyEqualMixin):
def do_cli(self, verb, *args, **kwargs):
"""
Like ``do_cli_unicode`` but work with ``bytes`` everywhere instead of
``unicode``.
"""
# client_num is used to execute client CLI commands on a specific
# client.
client_num = kwargs.pop("client_num", 0)

View File

@ -20,10 +20,13 @@ class ListAlias(GridTestMixin, CLITestMixin, unittest.TestCase):
:param unicode alias: The alias to try to create.
:param str encoding: The name of an encoding to force the
:param NoneType|str encoding: The name of an encoding to force the
``create-alias`` implementation to use. This simulates the
effects of setting LANG and doing other locale-foolishness without
actually having to mess with this process's global locale state.
If this is ``None`` then the encoding used will be ascii but the
stdio objects given to the code under test will not declare any
encoding (this is like Python 2 when stdio is not a tty).
:return Deferred: A Deferred that fires with success if the alias can
be created and that creation is reported on stdout appropriately
@ -38,7 +41,7 @@ class ListAlias(GridTestMixin, CLITestMixin, unittest.TestCase):
# monkey-patch that value to our desired value here. This is the code
# that most directly takes the place of messing with LANG or the
# locale module.
self.patch(encodingutil, "io_encoding", encoding)
self.patch(encodingutil, "io_encoding", encoding or "ascii")
rc, stdout, stderr = yield self.do_cli_unicode(
u"create-alias",
@ -74,6 +77,17 @@ class ListAlias(GridTestMixin, CLITestMixin, unittest.TestCase):
self.assertIn(u"readonly", data)
def test_list_none(self):
"""
An alias composed of all ASCII-encodeable code points can be created when
stdio aren't clearly marked with an encoding.
"""
return self._test_list(
u"tahoe",
encoding=None,
)
def test_list_ascii(self):
"""
An alias composed of all ASCII-encodeable code points can be created when

View File

@ -91,6 +91,24 @@ def run_cli_bytes(verb, *args, **kwargs):
def run_cli_unicode(verb, argv, nodeargs=None, stdin=None, encoding=None):
"""
Run a Tahoe-LAFS CLI command.
:param unicode verb: The command to run. For example, ``u"create-node"``.
:param [unicode] argv: The arguments to pass to the command. For example,
``[u"--hostname=localhost"]``.
:param [unicode] nodeargs: Extra arguments to pass to the Tahoe executable
before ``verb``.
:param unicode stdin: Text to pass to the command via stdin.
:param NoneType|str encoding: The name of an encoding to use for all
bytes/unicode conversions necessary *and* the encoding to cause stdio
to declare with its ``encoding`` attribute. ``None`` means ASCII will
be used and no declaration will be made at all.
"""
if nodeargs is None:
nodeargs = []
precondition(
@ -100,19 +118,21 @@ def run_cli_unicode(verb, argv, nodeargs=None, stdin=None, encoding=None):
nodeargs=nodeargs,
argv=argv,
)
codec = encoding or "ascii"
encode = lambda t: None if t is None else t.encode(codec)
d = run_cli_bytes(
verb.encode(encoding),
nodeargs=list(arg.encode(encoding) for arg in nodeargs),
stdin=stdin,
encode(verb),
nodeargs=list(encode(arg) for arg in nodeargs),
stdin=encode(stdin),
encoding=encoding,
*list(arg.encode(encoding) for arg in argv)
*list(encode(arg) for arg in argv)
)
def maybe_decode(result):
code, stdout, stderr = result
if isinstance(stdout, bytes):
stdout = stdout.decode(encoding)
stdout = stdout.decode(codec)
if isinstance(stderr, bytes):
stderr = stderr.decode(encoding)
stderr = stderr.decode(codec)
return code, stdout, stderr
d.addCallback(maybe_decode)
return d