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.
Files changed (31) hide show
  1. {cli2-2.7.2/cli2.egg-info → cli2-2.8.0}/PKG-INFO +1 -1
  2. {cli2-2.7.2 → cli2-2.8.0}/cli2/argument.py +21 -1
  3. {cli2-2.7.2 → cli2-2.8.0}/cli2/command.py +31 -26
  4. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_command.py +12 -0
  5. {cli2-2.7.2 → cli2-2.8.0/cli2.egg-info}/PKG-INFO +1 -1
  6. {cli2-2.7.2 → cli2-2.8.0}/setup.py +1 -1
  7. {cli2-2.7.2 → cli2-2.8.0}/MANIFEST.in +0 -0
  8. {cli2-2.7.2 → cli2-2.8.0}/README.rst +0 -0
  9. {cli2-2.7.2 → cli2-2.8.0}/classifiers.txt +0 -0
  10. {cli2-2.7.2 → cli2-2.8.0}/cli2/__init__.py +0 -0
  11. {cli2-2.7.2 → cli2-2.8.0}/cli2/cli.py +0 -0
  12. {cli2-2.7.2 → cli2-2.8.0}/cli2/colors.py +0 -0
  13. {cli2-2.7.2 → cli2-2.8.0}/cli2/decorators.py +0 -0
  14. {cli2-2.7.2 → cli2-2.8.0}/cli2/entry_point.py +0 -0
  15. {cli2-2.7.2 → cli2-2.8.0}/cli2/group.py +0 -0
  16. {cli2-2.7.2 → cli2-2.8.0}/cli2/node.py +0 -0
  17. {cli2-2.7.2 → cli2-2.8.0}/cli2/table.py +0 -0
  18. {cli2-2.7.2 → cli2-2.8.0}/cli2/test.py +0 -0
  19. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_cli.py +0 -0
  20. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_decorators.py +0 -0
  21. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_entrypoint.py +0 -0
  22. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_group.py +0 -0
  23. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_inject.py +0 -0
  24. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_node.py +0 -0
  25. {cli2-2.7.2 → cli2-2.8.0}/cli2/test_table.py +0 -0
  26. {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/SOURCES.txt +0 -0
  27. {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/dependency_links.txt +0 -0
  28. {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/entry_points.txt +0 -0
  29. {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/requires.txt +0 -0
  30. {cli2-2.7.2 → cli2-2.8.0}/cli2.egg-info/top_level.txt +0 -0
  31. {cli2-2.7.2 → cli2-2.8.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cli2
3
- Version: 2.7.2
3
+ Version: 2.8.0
4
4
  Summary: image:: https://yourlabs.io/oss/cli2/badges/master/pipeline.svg
5
5
  Home-page: https://yourlabs.io/oss/cli2
6
6
  Author: James Pic
@@ -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, **kwargs):
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
- @property
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
- """ Return ordered values """
218
- return self.ordered.values()
207
+ def values(self, factories=False):
208
+ """
209
+ Return ordered values.
219
210
 
220
- def items(self):
221
- """ Return ordered items """
222
- return self.ordered.items()
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
- def keys(self):
225
- """ Return ordered keys """
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')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cli2
3
- Version: 2.7.2
3
+ Version: 2.8.0
4
4
  Summary: image:: https://yourlabs.io/oss/cli2/badges/master/pipeline.svg
5
5
  Home-page: https://yourlabs.io/oss/cli2
6
6
  Author: James Pic
@@ -3,7 +3,7 @@ from setuptools import setup
3
3
 
4
4
  setup(
5
5
  name='cli2',
6
- version='2.7.2',
6
+ version='2.8.0',
7
7
  setup_requires='setupmeta',
8
8
  install_requires=['docstring_parser'],
9
9
  extras_require=dict(
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