cli2 2.7.2__tar.gz → 2.8.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cli2-2.7.2/cli2.egg-info → cli2-2.8.0}/PKG-INFO +1 -1
- {cli2-2.7.2 → cli2-2.8.0}/cli2/argument.py +21 -1
- {cli2-2.7.2 → cli2-2.8.0}/cli2/command.py +31 -26
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_command.py +12 -0
- {cli2-2.7.2 → cli2-2.8.0/cli2.egg-info}/PKG-INFO +1 -1
- {cli2-2.7.2 → cli2-2.8.0}/setup.py +1 -1
- {cli2-2.7.2 → cli2-2.8.0}/MANIFEST.in +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/README.rst +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/classifiers.txt +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/__init__.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/cli.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/colors.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/decorators.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/entry_point.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/group.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/node.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/table.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_cli.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_decorators.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_entrypoint.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_group.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_inject.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_node.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2/test_table.py +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/SOURCES.txt +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/dependency_links.txt +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/entry_points.txt +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/requires.txt +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/top_level.txt +0 -0
- {cli2-2.7.2 → cli2-2.8.0}/setup.cfg +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import inspect
|
|
1
2
|
import re
|
|
2
3
|
import json
|
|
3
4
|
|
|
@@ -10,12 +11,14 @@ class Argument:
|
|
|
10
11
|
"""
|
|
11
12
|
# TODO: why not split this into a bunch of simpler sub-classes now that
|
|
12
13
|
# it's pretty featureful ?
|
|
13
|
-
def __init__(self, cmd, param, doc=None, color=None,
|
|
14
|
+
def __init__(self, cmd, param, doc=None, color=None, factory=None,
|
|
15
|
+
**kwargs):
|
|
14
16
|
self.cmd = cmd
|
|
15
17
|
self.param = param
|
|
16
18
|
self.color = color
|
|
17
19
|
# Let default be set to None :)
|
|
18
20
|
self.default = kwargs.pop('default', param.default)
|
|
21
|
+
self.factory = factory
|
|
19
22
|
|
|
20
23
|
self.doc = doc or ''
|
|
21
24
|
if not doc:
|
|
@@ -227,6 +230,23 @@ class Argument:
|
|
|
227
230
|
)
|
|
228
231
|
)
|
|
229
232
|
|
|
233
|
+
def factory_value(self):
|
|
234
|
+
"""
|
|
235
|
+
Run the factory function and return the value.
|
|
236
|
+
|
|
237
|
+
If the factory function takes a `cmd` argument, it will pass the
|
|
238
|
+
command object.
|
|
239
|
+
|
|
240
|
+
If the factory function takes an `arg` argument, it will pass self.
|
|
241
|
+
"""
|
|
242
|
+
kwargs = dict()
|
|
243
|
+
sig = inspect.signature(self.factory)
|
|
244
|
+
if 'cmd' in sig.parameters:
|
|
245
|
+
kwargs['cmd'] = self.cmd
|
|
246
|
+
if 'arg' in sig.parameters:
|
|
247
|
+
kwargs['arg'] = self
|
|
248
|
+
return self.factory(**kwargs)
|
|
249
|
+
|
|
230
250
|
@property
|
|
231
251
|
def value(self):
|
|
232
252
|
"""Return the value bound to this argument."""
|
|
@@ -141,7 +141,10 @@ class Command(EntryPoint, dict):
|
|
|
141
141
|
if extra:
|
|
142
142
|
return 'No parameters for these arguments: ' + ', '.join(extra)
|
|
143
143
|
|
|
144
|
-
for name, arg in self.items():
|
|
144
|
+
for name, arg in self.items(factories=None):
|
|
145
|
+
if arg.factory:
|
|
146
|
+
arg.value = arg.factory_value()
|
|
147
|
+
continue
|
|
145
148
|
if not arg.default:
|
|
146
149
|
continue
|
|
147
150
|
if name in self.bound.arguments:
|
|
@@ -188,41 +191,41 @@ class Command(EntryPoint, dict):
|
|
|
188
191
|
result = self.call(*self.bound.args, **self.bound.kwargs)
|
|
189
192
|
if inspect.iscoroutine(result):
|
|
190
193
|
result = asyncio.run(result)
|
|
191
|
-
except TypeError as exc:
|
|
192
|
-
# keeping this as fallback for now, in case the above missing
|
|
193
|
-
# detection doesn't work
|
|
194
|
-
self.exit_code = 1
|
|
195
|
-
if hasattr(self.target, '__name__'):
|
|
196
|
-
rep = getattr(self.target, '__name__')
|
|
197
|
-
elif hasattr(self.target, '__call__'):
|
|
198
|
-
rep = '__call__'
|
|
199
|
-
error = str(exc)
|
|
200
|
-
function = error.split(' ')[0].split('.')[-1]
|
|
201
|
-
if function.startswith(rep + '('):
|
|
202
|
-
return self.help(error=error.replace(rep + '()', self.name))
|
|
203
|
-
raise
|
|
204
194
|
except KeyboardInterrupt:
|
|
205
195
|
print('exiting')
|
|
206
196
|
sys.exit(1)
|
|
207
197
|
return result
|
|
208
198
|
|
|
209
|
-
|
|
210
|
-
def ordered(self):
|
|
199
|
+
def ordered(self, factories=False):
|
|
211
200
|
"""
|
|
212
201
|
Order the parameters by priority.
|
|
202
|
+
|
|
203
|
+
:param factories: Show only arguments with factory.
|
|
213
204
|
"""
|
|
214
|
-
return {key: self[key] for key in self.keys()}
|
|
205
|
+
return {key: self[key] for key in self.keys(factories=factories)}
|
|
215
206
|
|
|
216
|
-
def values(self):
|
|
217
|
-
"""
|
|
218
|
-
|
|
207
|
+
def values(self, factories=False):
|
|
208
|
+
"""
|
|
209
|
+
Return ordered values.
|
|
219
210
|
|
|
220
|
-
|
|
221
|
-
"""
|
|
222
|
-
return self.ordered.
|
|
211
|
+
:param factories: Show only arguments with factory.
|
|
212
|
+
"""
|
|
213
|
+
return self.ordered(factories=factories).values()
|
|
214
|
+
|
|
215
|
+
def items(self, factories=False):
|
|
216
|
+
"""
|
|
217
|
+
Return ordered items.
|
|
223
218
|
|
|
224
|
-
|
|
225
|
-
"""
|
|
219
|
+
:param factories: Show only arguments with factory.
|
|
220
|
+
"""
|
|
221
|
+
return self.ordered(factories=factories).items()
|
|
222
|
+
|
|
223
|
+
def keys(self, factories=False):
|
|
224
|
+
"""
|
|
225
|
+
Return ordered keys.
|
|
226
|
+
|
|
227
|
+
:param factories: Show only arguments with factory.
|
|
228
|
+
"""
|
|
226
229
|
order = (
|
|
227
230
|
inspect.Parameter.POSITIONAL_ONLY,
|
|
228
231
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
@@ -233,6 +236,8 @@ class Command(EntryPoint, dict):
|
|
|
233
236
|
keys = []
|
|
234
237
|
for kind in order:
|
|
235
238
|
for name, arg in super().items():
|
|
239
|
+
if factories is False and arg.factory:
|
|
240
|
+
continue
|
|
236
241
|
if name in self.positions:
|
|
237
242
|
continue
|
|
238
243
|
if arg.param.kind == kind:
|
|
@@ -242,7 +247,7 @@ class Command(EntryPoint, dict):
|
|
|
242
247
|
return keys
|
|
243
248
|
|
|
244
249
|
def __iter__(self):
|
|
245
|
-
return self.ordered.__iter__()
|
|
250
|
+
return self.ordered().__iter__()
|
|
246
251
|
|
|
247
252
|
def arg(
|
|
248
253
|
self,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import pytest
|
|
3
3
|
|
|
4
|
+
from .decorators import arg
|
|
4
5
|
from .argument import Argument
|
|
5
6
|
from .command import Command
|
|
6
7
|
from .test import autotest, Outfile
|
|
@@ -521,3 +522,14 @@ def test_helphack():
|
|
|
521
522
|
cmd('a', 'b', '--help')
|
|
522
523
|
assert cmd.exit_code == 0
|
|
523
524
|
assert not getattr(cmd, 'help_shown', False)
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
def test_factory():
|
|
528
|
+
class Foo:
|
|
529
|
+
@arg('self', factory=lambda cmd, arg: Foo())
|
|
530
|
+
@arg('auto', factory=lambda: 'autoval')
|
|
531
|
+
def test(self, auto, arg):
|
|
532
|
+
return auto, arg
|
|
533
|
+
|
|
534
|
+
cmd = Command(Foo.test)
|
|
535
|
+
assert cmd('hello') == ('autoval', 'hello')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|