cli2 3.3.23__tar.gz → 3.3.25__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 (45) hide show
  1. {cli2-3.3.23/cli2.egg-info → cli2-3.3.25}/PKG-INFO +1 -1
  2. {cli2-3.3.23 → cli2-3.3.25}/cli2/__init__.py +0 -1
  3. {cli2-3.3.23 → cli2-3.3.25}/cli2/client.py +16 -98
  4. {cli2-3.3.23 → cli2-3.3.25}/cli2/group.py +2 -0
  5. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_client.py +24 -57
  6. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_group.py +6 -1
  7. {cli2-3.3.23 → cli2-3.3.25/cli2.egg-info}/PKG-INFO +1 -1
  8. {cli2-3.3.23 → cli2-3.3.25}/setup.py +1 -1
  9. {cli2-3.3.23 → cli2-3.3.25}/MANIFEST.in +0 -0
  10. {cli2-3.3.23 → cli2-3.3.25}/README.rst +0 -0
  11. {cli2-3.3.23 → cli2-3.3.25}/classifiers.txt +0 -0
  12. {cli2-3.3.23 → cli2-3.3.25}/cli2/argument.py +0 -0
  13. {cli2-3.3.23 → cli2-3.3.25}/cli2/asyncio.py +0 -0
  14. {cli2-3.3.23 → cli2-3.3.25}/cli2/cli.py +0 -0
  15. {cli2-3.3.23 → cli2-3.3.25}/cli2/colors.py +0 -0
  16. {cli2-3.3.23 → cli2-3.3.25}/cli2/command.py +0 -0
  17. {cli2-3.3.23 → cli2-3.3.25}/cli2/configuration.py +0 -0
  18. {cli2-3.3.23 → cli2-3.3.25}/cli2/decorators.py +0 -0
  19. {cli2-3.3.23 → cli2-3.3.25}/cli2/display.py +0 -0
  20. {cli2-3.3.23 → cli2-3.3.25}/cli2/entry_point.py +0 -0
  21. {cli2-3.3.23 → cli2-3.3.25}/cli2/example_client.py +0 -0
  22. {cli2-3.3.23 → cli2-3.3.25}/cli2/example_client_complex.py +0 -0
  23. {cli2-3.3.23 → cli2-3.3.25}/cli2/example_nesting.py +0 -0
  24. {cli2-3.3.23 → cli2-3.3.25}/cli2/example_obj.py +0 -0
  25. {cli2-3.3.23 → cli2-3.3.25}/cli2/logging.py +0 -0
  26. {cli2-3.3.23 → cli2-3.3.25}/cli2/node.py +0 -0
  27. {cli2-3.3.23 → cli2-3.3.25}/cli2/overrides.py +0 -0
  28. {cli2-3.3.23 → cli2-3.3.25}/cli2/sphinx.py +0 -0
  29. {cli2-3.3.23 → cli2-3.3.25}/cli2/table.py +0 -0
  30. {cli2-3.3.23 → cli2-3.3.25}/cli2/test.py +0 -0
  31. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_cli.py +0 -0
  32. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_command.py +0 -0
  33. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_configuration.py +0 -0
  34. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_decorators.py +0 -0
  35. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_display.py +0 -0
  36. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_entry_point.py +0 -0
  37. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_inject.py +0 -0
  38. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_node.py +0 -0
  39. {cli2-3.3.23 → cli2-3.3.25}/cli2/test_table.py +0 -0
  40. {cli2-3.3.23 → cli2-3.3.25}/cli2.egg-info/SOURCES.txt +0 -0
  41. {cli2-3.3.23 → cli2-3.3.25}/cli2.egg-info/dependency_links.txt +0 -0
  42. {cli2-3.3.23 → cli2-3.3.25}/cli2.egg-info/entry_points.txt +0 -0
  43. {cli2-3.3.23 → cli2-3.3.25}/cli2.egg-info/requires.txt +0 -0
  44. {cli2-3.3.23 → cli2-3.3.25}/cli2.egg-info/top_level.txt +0 -0
  45. {cli2-3.3.23 → cli2-3.3.25}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cli2
3
- Version: 3.3.23
3
+ Version: 3.3.25
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
@@ -16,7 +16,6 @@ try:
16
16
  FieldValueError,
17
17
  FieldExternalizeError,
18
18
  Client,
19
- ClientProxy,
20
19
  DateTimeField,
21
20
  Field,
22
21
  Handler,
@@ -675,21 +675,19 @@ class ModelGroup(Group):
675
675
  )
676
676
  )
677
677
 
678
+ url_list_methods = ['find', 'get', 'delete', 'create']
678
679
  if cls.url_list:
679
- self.cmd(cls.find)
680
- self.cmd(cls.get)
681
- self.cmd(cls.delete)
682
- self.cmd(cls.create)
680
+ for name in url_list_methods:
681
+ self.cmd(getattr(cls, name))
683
682
 
684
- self.load_cls(cls, exclude=['find', 'get', 'delete', 'create'])
683
+ self.load_cls(cls, exclude=url_list_methods)
685
684
 
686
685
 
687
686
  class ModelMetaclass(type):
688
- def __new__(cls, name, bases, attributes, client=None):
689
- attributes['_client_key'] = client
687
+ def __new__(cls, name, bases, attributes):
690
688
  cls = super().__new__(cls, name, bases, attributes)
691
-
692
- if getattr(cls, 'client', None):
689
+ client = getattr(cls, 'client', None)
690
+ if client:
693
691
  return cls
694
692
 
695
693
  client_class = getattr(cls, '_client_class', None)
@@ -740,6 +738,7 @@ class Model(metaclass=ModelMetaclass):
740
738
 
741
739
  The URL to get the list of objects, you're supposed to configure it as
742
740
  a model attribute in your model subclass.
741
+ This may be a format string using a client ``client`` variable.
743
742
 
744
743
  .. py:attribute:: url_detail
745
744
 
@@ -1198,11 +1197,9 @@ class Client(metaclass=ClientMetaclass):
1198
1197
  self.token = None
1199
1198
 
1200
1199
  for model in self.models:
1201
- if model._client_key:
1202
- client = getattr(self, model._client_key)
1203
- else:
1204
- client = self
1205
- model = type(model.__name__, (model,), dict(client=client))
1200
+ model = type(model.__name__, (model,), dict(client=self))
1201
+ if model.url_list:
1202
+ model.url_list = model.url_list.format(client=self)
1206
1203
  setattr(self, model.__name__, model)
1207
1204
 
1208
1205
  @property
@@ -1479,6 +1476,11 @@ class Client(metaclass=ClientMetaclass):
1479
1476
 
1480
1477
  return data
1481
1478
 
1479
+ @cmd
1480
+ async def get(self, url, *args, **kwargs):
1481
+ """ GET Request """
1482
+ return await self.request('GET', url, *args, **kwargs)
1483
+
1482
1484
  @cmd(name='request')
1483
1485
  async def request_cmd(self, method, url, *args, **kwargs):
1484
1486
  """
@@ -1505,11 +1507,6 @@ class Client(metaclass=ClientMetaclass):
1505
1507
  kwargs[key] = yaml.safe_load(fh.read())
1506
1508
  return await self.request(method, url, *args, **kwargs)
1507
1509
 
1508
- @cmd
1509
- async def get(self, url, *args, **kwargs):
1510
- """ GET Request """
1511
- return await self.request('GET', url, *args, **kwargs)
1512
-
1513
1510
  async def post(self, url, *args, **kwargs):
1514
1511
  """ POST Request """
1515
1512
  return await self.request('POST', url, *args, **kwargs)
@@ -1552,85 +1549,6 @@ class Client(metaclass=ClientMetaclass):
1552
1549
  details.
1553
1550
  """
1554
1551
 
1555
- @property
1556
- def base_url(self):
1557
- return self.client.base_url
1558
-
1559
-
1560
- class ClientProxy:
1561
- """
1562
- Proxy a :py:cls:`Client` with another :py:attr:`base_url`.
1563
-
1564
- Allows to declare sub-clients:
1565
-
1566
- .. code-block:: python
1567
-
1568
- class YourClient(cli2.Client):
1569
- def __init__(self, *args, **kwargs):
1570
- super().__init__(*args, **kwargs)
1571
- self.widget_client = cli2.ClientProxy(self, '/widgets')
1572
- self.thing_client = cli2.ClientProxy(self, '/things')
1573
-
1574
- You generally don't need this class.
1575
-
1576
- .. py:attribute:: client
1577
-
1578
- Actual :py:cls:`Client` instance
1579
-
1580
- .. py.attribute:: base_url
1581
-
1582
- Extra base_url
1583
- """
1584
- def __init__(self, client, base_url):
1585
- self.base_url = base_url
1586
- self.client = client
1587
-
1588
- def url_rewrite(self, url):
1589
- return '/'.join([
1590
- str(self.client.base_url),
1591
- str(self.base_url.lstrip('/')),
1592
- url.lstrip('/')
1593
- ])
1594
-
1595
- async def request(self, method, url, *args, **kwargs):
1596
- """
1597
- Join the actual client's base_url, our base_url and the url.
1598
- """
1599
- return await self.client.request(
1600
- method, self.url_rewrite(url), *args, **kwargs
1601
- )
1602
-
1603
- @cmd
1604
- async def get(self, url, *args, **kwargs):
1605
- """ GET Request """
1606
- return await self.request('GET', url, *args, **kwargs)
1607
-
1608
- async def post(self, url, *args, **kwargs):
1609
- """ POST Request """
1610
- return await self.request('POST', url, *args, **kwargs)
1611
-
1612
- async def put(self, url, *args, **kwargs):
1613
- """ PUT Request """
1614
- return await self.request('PUT', url, *args, **kwargs)
1615
-
1616
- async def head(self, url, *args, **kwargs):
1617
- """ HEAD Request """
1618
- return await self.request('HEAD', url, *args, **kwargs)
1619
-
1620
- async def delete(self, url, *args, **kwargs):
1621
- """ DELETE Request """
1622
- return await self.request('DELETE', url, *args, **kwargs)
1623
-
1624
- def paginate(self, url, *args, **kwargs):
1625
- """ Paginate proxy """
1626
- return self.client.paginate(self.url_rewrite(url), *args, **kwargs)
1627
-
1628
- def pagination_initialize(self, paginator, data):
1629
- return self.client.pagination_initialize(paginator, data)
1630
-
1631
- def pagination_parameters(self, paginator, page_number):
1632
- return self.client.pagination_parameters(paginator, page_number)
1633
-
1634
1552
 
1635
1553
  class Expression:
1636
1554
  def __init__(self, field, value):
@@ -183,6 +183,8 @@ class Group(EntryPoint, dict):
183
183
  """
184
184
  exclude = exclude or []
185
185
  for name, method in cls.__dict__.items():
186
+ if name in exclude:
187
+ continue
186
188
  wrapped_method = getattr(method, '__func__', None)
187
189
  if hasattr(wrapped_method, 'cli2'):
188
190
  self.cmd(wrapped_method)
@@ -4,7 +4,6 @@ import httpx
4
4
  import inspect
5
5
  import mock
6
6
  import pytest
7
- import uuid
8
7
 
9
8
 
10
9
  async def _response(**kwargs):
@@ -53,6 +52,23 @@ async def test_client_cli(client_class, httpx_mock):
53
52
  await client_class.cli['testmodel']['find'].async_call()
54
53
 
55
54
 
55
+ @pytest.mark.asyncio
56
+ async def test_client_cli_override(client_class, httpx_mock):
57
+ class Client(client_class):
58
+ def __init__(self, *args, **kwargs):
59
+ self.test = 'bar'
60
+ super().__init__(*args, **kwargs)
61
+
62
+ class TestModel(Client.Model):
63
+ url_list = '{client.test}/foo'
64
+
65
+ @classmethod
66
+ @cli2.cmd
67
+ async def find(cls, foo):
68
+ return cls.url_list
69
+ assert await Client.cli['testmodel']['find'].async_call('bar') == 'bar/foo'
70
+
71
+
56
72
  def test_client_model(client_class):
57
73
  assert issubclass(client_class.Model, cli2.Model)
58
74
  assert client_class.Model._client_class == client_class
@@ -942,66 +958,17 @@ async def test_debug():
942
958
 
943
959
 
944
960
  @pytest.mark.asyncio
945
- async def test_client_proxy(httpx_mock):
946
- class ProxyTestClient(cli2.Client):
961
+ async def test_url_list(client_class):
962
+ class Client(client_class):
947
963
  def __init__(self, *args, **kwargs):
948
- self.sub = cli2.ClientProxy(self, base_url='/bar')
964
+ self.foo = '/foo'
949
965
  super().__init__(*args, **kwargs)
950
- self.tokens = []
951
-
952
- async def token_get(self):
953
- token = str(uuid.uuid4())
954
- self.tokens.append(token)
955
- return token
956
-
957
- class TestModel(ProxyTestClient.Model, client='sub'):
958
- url_list = '/foo'
959
- id = cli2.Field()
960
-
961
- client = ProxyTestClient(base_url='http://ex')
962
- assert not client.token
963
966
 
964
- # TestModel uses a sub-client
965
- assert client.TestModel.client == client.sub
966
-
967
- httpx_mock.add_response(url='http://ex/test1')
968
- await client.get('/test1')
969
-
970
- httpx_mock.add_response(url='http://ex/bar/sub')
971
- await client.sub.get('/sub')
972
- # don't get a new token, use the parent's
973
- assert len(client.tokens) == 1
974
-
975
- client = ProxyTestClient(base_url='http://ex2')
976
- assert not client.token
977
- httpx_mock.add_response(url='http://ex2/bar/sub2')
978
- await client.sub.get('/sub2')
979
-
980
- httpx_mock.add_response(url='http://ex2/root')
981
- await client.get('/root')
982
- # don't get a new token, use the parent's
983
- assert len(client.tokens) == 1
984
-
985
- httpx_mock.add_response(
986
- url='http://ex2/bar/foo',
987
- json=[dict(id=1), dict(id=2)],
988
- )
989
- result = await client.TestModel.find().list()
990
- assert result[0].id == 1
991
- assert result[1].id == 2
992
-
993
- httpx_mock.add_response(
994
- url='http://ex2/bar/foo/1',
995
- json=dict(id=1),
996
- )
997
- result = await client.TestModel.get(id=1)
998
- assert result.id == 1
967
+ class TestModel(Client.Model):
968
+ url_list = '{client.foo}/bar'
999
969
 
1000
- httpx_mock.add_response(
1001
- url='http://ex2/bar/foo/1',
1002
- method='DELETE',
1003
- )
1004
- await result.delete()
970
+ client = Client()
971
+ assert client.TestModel.url_list == '/foo/bar'
1005
972
 
1006
973
 
1007
974
  @pytest.mark.asyncio
@@ -224,8 +224,13 @@ def test_load_cls():
224
224
  @cli2.cmd
225
225
  def test2(self):
226
226
  pass
227
+
228
+ @cli2.cmd
229
+ def exclude(self):
230
+ pass
227
231
  group = Group()
228
- group.load_cls(Foo)
232
+ group.load_cls(Foo, exclude=['exclude'])
229
233
  assert 'bar' not in group
230
234
  assert 'test' in group
231
235
  assert 'test2' in group
236
+ assert 'exclude' not in group
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cli2
3
- Version: 3.3.23
3
+ Version: 3.3.25
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='3.3.23',
6
+ version='3.3.25',
7
7
  setup_requires='setupmeta',
8
8
  install_requires=[
9
9
  'docstring_parser',
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
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