Commit a18b7e71 authored by John Kirkwood's avatar John Kirkwood

Handle introspection of builtins with no signature.

parent 62dc12e2
Pipeline #2798 failed with stages
in 16 seconds
......@@ -186,16 +186,38 @@ class Callable(Importable):
return getattr(cb, 'cli2', cls(cb.__name__, cb))
def __call__(self, *args, **kwargs):
if len(args) < len(self.required_args):
req_args = self.required_args
if len(args) < len(req_args):
raise Cli2ArgsException(self, args)
return self.target(*args, **kwargs)
try:
return self.target(*args, **kwargs)
except TypeError as exc:
# catch builtins that don't provide info for required_args
if exc.args[0].startswith('Required argument'):
raise Cli2ArgsException(self, args)
else:
raise
@property
def required_args(self):
if self.is_module:
return []
argspec = inspect.getfullargspec(self.target)
if argspec.defaults:
return argspec.args[:-len(argspec.defaults)]
else:
return argspec.args
try:
argspec = inspect.getfullargspec(self.target)
"""
This edge case is for builtin datetime.datetime.now() which
returns args=['type', 'tz'] for some reason, rather than ['tz'].
The freezegun mocking module changes 'type' to 'cls' for tests...
"""
if (self.name.startswith('datetime')
and argspec.args[0] in ['cls', 'type']):
del argspec.args[0]
if argspec.defaults:
return argspec.args[:-len(argspec.defaults)]
else:
return argspec.args
except TypeError:
# catch builtins that don't provide a signature
# TODO: parse first line of inspect.getdoc() for builtin signature?
return []
import pytest
from freezegun import freeze_time
import cli2
import pytest
@pytest.mark.parametrize('name,command', [
......@@ -14,17 +17,20 @@ import pytest
('run_module_missing_attr', 'cli2.missing'),
('run_module_missing', 'missinggggggg.foo'),
('run_module_nodoc', 'test_cli2.test_cli2'),
('run_module_builtin', 'datetime.datetime.now'),
('help_module', 'help cli2'),
('help_module_attr_notfound', 'help cli2.skipppp'),
('help_module_no_callables', 'help datetime'),
('help_module_no_signature', 'help datetime.datetime'),
('help_module_no_signature', 'help datetime.date.fromtimestamp'),
('docmod', 'docmod cli2'),
('docmod_noargs', 'docmod'),
('docfile', 'docfile cli2/cli.py'),
('docfile_missing', 'docfile missing.py'),
('debug', 'debug cli2.run to see=how -it --parses=me'),
])
@freeze_time("2010-02-01") # so datetime.datetime.now() output is unchanging
def test_cli2(name, command):
cli2.autotest(
f'tests/{name}.txt',
'cli2 ' + command,
......
command: cli2 help datetime.datetime
command: cli2 help datetime.date.fromtimestamp
retcode: 1
stdout:
Signature: datetime.datetime
datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
The year, month and day arguments are required. tzinfo may be None, or an
instance of a tzinfo subclass. The remaining arguments may be ints.
Signature: datetime.date.fromtimestamp
timestamp -> local date from a POSIX timestamp (like time.time()).
command: cli2 datetime.datetime.now
retcode: 1
stdout:
FakeDatetime(2010, 2, 1, 0, 0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment