cli2 3.3.36__tar.gz → 3.3.40__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-3.3.36/cli2.egg-info → cli2-3.3.40}/PKG-INFO +13 -2
- {cli2-3.3.36 → cli2-3.3.40}/cli2/client.py +29 -89
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_client.py +69 -48
- {cli2-3.3.36 → cli2-3.3.40/cli2.egg-info}/PKG-INFO +13 -2
- {cli2-3.3.36 → cli2-3.3.40}/setup.py +1 -1
- {cli2-3.3.36 → cli2-3.3.40}/MANIFEST.in +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/README.rst +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/classifiers.txt +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/__init__.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/argument.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/asyncio.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/cli.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/colors.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/command.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/configuration.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/decorators.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/display.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/entry_point.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/example_client.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/example_client_complex.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/example_nesting.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/example_obj.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/group.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/logging.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/node.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/overrides.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/sphinx.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/table.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_cli.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_command.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_configuration.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_decorators.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_display.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_entry_point.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_group.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_inject.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_node.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2/test_table.py +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2.egg-info/SOURCES.txt +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2.egg-info/dependency_links.txt +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2.egg-info/entry_points.txt +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2.egg-info/requires.txt +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/cli2.egg-info/top_level.txt +0 -0
- {cli2-3.3.36 → cli2-3.3.40}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: cli2
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.40
|
|
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
|
|
@@ -23,6 +23,17 @@ Requires-Dist: pytest-cov; extra == "test"
|
|
|
23
23
|
Requires-Dist: pytest-mock; extra == "test"
|
|
24
24
|
Requires-Dist: pytest-asyncio; extra == "test"
|
|
25
25
|
Requires-Dist: pytest-httpx; extra == "test"
|
|
26
|
+
Dynamic: author
|
|
27
|
+
Dynamic: author-email
|
|
28
|
+
Dynamic: description
|
|
29
|
+
Dynamic: description-content-type
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: keywords
|
|
32
|
+
Dynamic: license
|
|
33
|
+
Dynamic: provides-extra
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
26
37
|
|
|
27
38
|
.. image:: https://yourlabs.io/oss/cli2/badges/master/pipeline.svg
|
|
28
39
|
:target: https://yourlabs.io/oss/cli2/pipelines
|
|
@@ -34,19 +34,11 @@ class Paginator:
|
|
|
34
34
|
"""
|
|
35
35
|
Generic pagination class.
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
Should work with most paginations by default, if you're extending this then
|
|
38
|
+
override:
|
|
39
39
|
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
:py:meth:`~Client.pagination_parameters` methods
|
|
43
|
-
|
|
44
|
-
- or also, per model, in the :py:class:`~Model` class with the
|
|
45
|
-
:py:meth:`~Model.pagination_initialize` and
|
|
46
|
-
:py:meth:`~Model.pagination_parameters` methods
|
|
47
|
-
|
|
48
|
-
Refer to :py:meth:`pagination_parameters` and
|
|
49
|
-
:py:meth:`pagination_initialize` for details.
|
|
40
|
+
- :py:meth:`~Paginator.pagination_initialize`
|
|
41
|
+
- :py:meth:`~Paginator.pagination_parameters`
|
|
50
42
|
|
|
51
43
|
.. py:attribute:: total_pages
|
|
52
44
|
|
|
@@ -76,17 +68,15 @@ class Paginator:
|
|
|
76
68
|
|
|
77
69
|
:py:class:`Model` class or ``dict`` by default.
|
|
78
70
|
|
|
79
|
-
.. py:attribute::
|
|
80
|
-
|
|
81
|
-
Callback called for every item after filtering.
|
|
82
|
-
|
|
83
|
-
.. py:attribute:: prefilter
|
|
71
|
+
.. py:attribute:: callback
|
|
84
72
|
|
|
85
|
-
Callback called for every item before filtering.
|
|
73
|
+
Callback called for every item before filtering by expressions.
|
|
74
|
+
This must return True or the item will be filtered *out* of yielded
|
|
75
|
+
results.
|
|
86
76
|
"""
|
|
87
77
|
|
|
88
78
|
def __init__(self, client, url, params=None, model=None, expressions=None,
|
|
89
|
-
|
|
79
|
+
callback=None):
|
|
90
80
|
"""
|
|
91
81
|
Initialize a paginator object with a client on a URL with parameters.
|
|
92
82
|
|
|
@@ -102,8 +92,7 @@ class Paginator:
|
|
|
102
92
|
self.page_start = 1
|
|
103
93
|
self.per_page = None
|
|
104
94
|
self.initialized = False
|
|
105
|
-
self.
|
|
106
|
-
self.postfilter = postfilter
|
|
95
|
+
self.callback = callback
|
|
107
96
|
self.expressions = []
|
|
108
97
|
for expression in (expressions or []):
|
|
109
98
|
if not isinstance(expression, Expression):
|
|
@@ -180,12 +169,6 @@ class Paginator:
|
|
|
180
169
|
|
|
181
170
|
:param data: Data of the first response
|
|
182
171
|
"""
|
|
183
|
-
try:
|
|
184
|
-
self.model.pagination_initialize
|
|
185
|
-
except AttributeError:
|
|
186
|
-
return self.client.pagination_initialize(self, data)
|
|
187
|
-
else:
|
|
188
|
-
return self.model.pagination_initialize(self, data)
|
|
189
172
|
|
|
190
173
|
def pagination_parameters(self, page_number):
|
|
191
174
|
"""
|
|
@@ -199,15 +182,12 @@ class Paginator:
|
|
|
199
182
|
|
|
200
183
|
.. code-block:: python
|
|
201
184
|
|
|
202
|
-
def pagination_parameters(self,
|
|
185
|
+
def pagination_parameters(self, page_number):
|
|
186
|
+
# this is the default implementation
|
|
203
187
|
return dict(page=page_number)
|
|
204
188
|
"""
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
except AttributeError:
|
|
208
|
-
return self.client.pagination_parameters(self, page_number)
|
|
209
|
-
else:
|
|
210
|
-
return self.model.pagination_parameters(self, page_number)
|
|
189
|
+
if page_number > 1:
|
|
190
|
+
return dict(page=page_number)
|
|
211
191
|
|
|
212
192
|
def response_items(self, response):
|
|
213
193
|
"""
|
|
@@ -277,16 +257,17 @@ class Paginator:
|
|
|
277
257
|
await self.initialize(response)
|
|
278
258
|
return response
|
|
279
259
|
|
|
280
|
-
async def __aiter__(self,
|
|
260
|
+
async def __aiter__(self, callback=None):
|
|
281
261
|
"""
|
|
282
262
|
Asynchronous iterator.
|
|
283
263
|
"""
|
|
284
|
-
|
|
285
|
-
postfilter = postfilter or self.postfilter
|
|
264
|
+
callback = callback or self.callback
|
|
286
265
|
|
|
287
266
|
if self._reverse and not self.total_pages:
|
|
288
267
|
first_page_response = await self.page_response(1)
|
|
289
268
|
page = self.total_pages
|
|
269
|
+
if not self.total_pages:
|
|
270
|
+
raise Exception('Reverse pagination without total_pages')
|
|
290
271
|
else:
|
|
291
272
|
page = self.page_start
|
|
292
273
|
|
|
@@ -294,11 +275,10 @@ class Paginator:
|
|
|
294
275
|
|
|
295
276
|
async def yielder(items):
|
|
296
277
|
for item in items:
|
|
297
|
-
if
|
|
298
|
-
await async_resolve(
|
|
278
|
+
if callback:
|
|
279
|
+
if not await async_resolve(callback(item)):
|
|
280
|
+
continue
|
|
299
281
|
if not python_filter or python_filter.matches(item):
|
|
300
|
-
if postfilter:
|
|
301
|
-
await async_resolve(postfilter(item))
|
|
302
282
|
yield item
|
|
303
283
|
|
|
304
284
|
while items := await self.page_items(page):
|
|
@@ -708,6 +688,8 @@ class ModelMetaclass(type):
|
|
|
708
688
|
cls = super().__new__(cls, name, bases, attributes)
|
|
709
689
|
client = getattr(cls, 'client', None)
|
|
710
690
|
if client:
|
|
691
|
+
if not cls.paginator:
|
|
692
|
+
cls.paginator = client.paginator
|
|
711
693
|
return cls
|
|
712
694
|
|
|
713
695
|
client_class = getattr(cls, '_client_class', None)
|
|
@@ -776,7 +758,7 @@ class Model(metaclass=ModelMetaclass):
|
|
|
776
758
|
|
|
777
759
|
Object URL based on :py:attr:`url_detail` and :py:attr:`id_field`.
|
|
778
760
|
"""
|
|
779
|
-
paginator =
|
|
761
|
+
paginator = None
|
|
780
762
|
model_command = ModelCommand
|
|
781
763
|
model_group = ModelGroup
|
|
782
764
|
url_list = None
|
|
@@ -834,32 +816,6 @@ class Model(metaclass=ModelMetaclass):
|
|
|
834
816
|
"""
|
|
835
817
|
return cls.paginator(cls.client, url, params, cls, expressions)
|
|
836
818
|
|
|
837
|
-
@classmethod
|
|
838
|
-
def pagination_initialize(cls, paginator, data):
|
|
839
|
-
"""
|
|
840
|
-
Implement Model-specific pagination initialization here.
|
|
841
|
-
|
|
842
|
-
Otherwise, :py:meth:`Client.pagination_initialize` will
|
|
843
|
-
take place.
|
|
844
|
-
|
|
845
|
-
Refer to :py:meth:`Paginator.pagination_initialize` for
|
|
846
|
-
details.
|
|
847
|
-
"""
|
|
848
|
-
cls.client.pagination_initialize(paginator, data)
|
|
849
|
-
|
|
850
|
-
@classmethod
|
|
851
|
-
def pagination_parameters(cls, paginator, page_number):
|
|
852
|
-
"""
|
|
853
|
-
Implement Model-specific pagination parameters here.
|
|
854
|
-
|
|
855
|
-
Otherwise, :py:meth:`Client.pagination_parameters` will
|
|
856
|
-
take place.
|
|
857
|
-
|
|
858
|
-
Refer to :py:meth:`Paginator.pagination_parameters` for
|
|
859
|
-
details.
|
|
860
|
-
"""
|
|
861
|
-
return cls.client.pagination_parameters(paginator, page_number)
|
|
862
|
-
|
|
863
819
|
@property
|
|
864
820
|
def cli2_display(self):
|
|
865
821
|
return self.data
|
|
@@ -1177,9 +1133,7 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1177
1133
|
|
|
1178
1134
|
.. py:attribute:: paginator
|
|
1179
1135
|
|
|
1180
|
-
:py:class:`Paginator` class
|
|
1181
|
-
implement :py:meth:`pagination_initialize` and
|
|
1182
|
-
:py:meth:`pagination_parameters`.
|
|
1136
|
+
:py:class:`Paginator` class
|
|
1183
1137
|
|
|
1184
1138
|
.. py:attribute:: semaphore
|
|
1185
1139
|
|
|
@@ -1605,7 +1559,8 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1605
1559
|
""" DELETE Request """
|
|
1606
1560
|
return await self.request('DELETE', url, *args, **kwargs)
|
|
1607
1561
|
|
|
1608
|
-
def paginate(self, url, params=None, model=None
|
|
1562
|
+
def paginate(self, url, *expressions, params=None, model=None,
|
|
1563
|
+
callback=None):
|
|
1609
1564
|
"""
|
|
1610
1565
|
Return a paginator to iterate over results
|
|
1611
1566
|
|
|
@@ -1613,23 +1568,8 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1613
1568
|
:param params: GET parameters
|
|
1614
1569
|
:param model: Model class to cast for items
|
|
1615
1570
|
"""
|
|
1616
|
-
return self.paginator(self, url, params or {}, model or dict
|
|
1617
|
-
|
|
1618
|
-
def pagination_parameters(self, paginator, page_number):
|
|
1619
|
-
"""
|
|
1620
|
-
Implement Model-specific pagination parameters here.
|
|
1621
|
-
|
|
1622
|
-
Refer to :py:meth:`Paginator.pagination_parameters` for
|
|
1623
|
-
details.
|
|
1624
|
-
"""
|
|
1625
|
-
|
|
1626
|
-
def pagination_initialize(self, paginator, data):
|
|
1627
|
-
"""
|
|
1628
|
-
Implement Model-specific pagination initialization here.
|
|
1629
|
-
|
|
1630
|
-
Refer to :py:meth:`Paginator.pagination_initialize` for
|
|
1631
|
-
details.
|
|
1632
|
-
"""
|
|
1571
|
+
return self.paginator(self, url, params or {}, model or dict,
|
|
1572
|
+
expressions, callback)
|
|
1633
1573
|
|
|
1634
1574
|
|
|
1635
1575
|
class Expression:
|
|
@@ -49,6 +49,7 @@ async def test_client_cli(client_class, httpx_mock):
|
|
|
49
49
|
assert isinstance(result.client, client_class)
|
|
50
50
|
|
|
51
51
|
httpx_mock.add_response(url='http://lol/', json=[dict(a=1)])
|
|
52
|
+
httpx_mock.add_response(url='http://lol/?page=2', json=[])
|
|
52
53
|
await client_class.cli['testmodel']['find'].async_call()
|
|
53
54
|
|
|
54
55
|
class TestModel2(client_class.Model):
|
|
@@ -124,6 +125,7 @@ async def test_async_factory(httpx_mock):
|
|
|
124
125
|
url_list = '/2'
|
|
125
126
|
|
|
126
127
|
httpx_mock.add_response(url='http://bar/2', json=[dict(a=1)])
|
|
128
|
+
httpx_mock.add_response(url='http://bar/2?page=2', json=[])
|
|
127
129
|
await TestClient.cli['testmodel']['find'].async_call()
|
|
128
130
|
|
|
129
131
|
|
|
@@ -369,33 +371,48 @@ async def test_token(httpx_mock):
|
|
|
369
371
|
|
|
370
372
|
@pytest.mark.asyncio
|
|
371
373
|
async def test_pagination(httpx_mock):
|
|
372
|
-
httpx_mock.add_response(url='http://lol
|
|
374
|
+
httpx_mock.add_response(url='http://lol/', json=[dict(a=1)])
|
|
373
375
|
httpx_mock.add_response(url='http://lol/?page=2', json=[dict(a=2)])
|
|
374
376
|
httpx_mock.add_response(url='http://lol/?page=3', json=[])
|
|
375
377
|
client = Client(base_url='http://lol')
|
|
376
|
-
paginator = client.paginate('/')
|
|
377
378
|
|
|
378
|
-
def
|
|
379
|
+
def callback(item):
|
|
379
380
|
item['b'] = item['a']
|
|
381
|
+
return True
|
|
380
382
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
paginator = client.paginate(
|
|
384
|
+
'/',
|
|
385
|
+
lambda item: item['b'] == 2,
|
|
386
|
+
callback=callback,
|
|
387
|
+
)
|
|
386
388
|
assert await paginator.list() == [
|
|
387
|
-
dict(a=
|
|
388
|
-
dict(a=2, b=2, c=2)
|
|
389
|
+
dict(a=2, b=2)
|
|
389
390
|
]
|
|
390
391
|
|
|
391
392
|
|
|
393
|
+
def test_paginator(client_class):
|
|
394
|
+
class Client(client_class):
|
|
395
|
+
paginator = 'foo'
|
|
396
|
+
|
|
397
|
+
class Model1(Client.Model):
|
|
398
|
+
pass
|
|
399
|
+
|
|
400
|
+
class Model2(Client.Model):
|
|
401
|
+
paginator = 'bar'
|
|
402
|
+
|
|
403
|
+
client = Client()
|
|
404
|
+
assert client.Model1.paginator == 'foo'
|
|
405
|
+
assert client.Model2.paginator == 'bar'
|
|
406
|
+
|
|
407
|
+
|
|
392
408
|
@pytest.mark.asyncio
|
|
393
409
|
async def test_pagination_initialize(httpx_mock):
|
|
394
|
-
httpx_mock.add_response(url='http://lol
|
|
410
|
+
httpx_mock.add_response(url='http://lol/', json=dict(
|
|
395
411
|
total_pages=2,
|
|
396
412
|
items=[dict(a=1)],
|
|
397
413
|
))
|
|
398
414
|
httpx_mock.add_response(url='http://lol/?page=2', json=[dict(a=2)])
|
|
415
|
+
httpx_mock.add_response(url='http://lol/?page=3', json=[])
|
|
399
416
|
|
|
400
417
|
class PaginatedClient(Client):
|
|
401
418
|
def pagination_initialize(self, paginator, data):
|
|
@@ -404,7 +421,7 @@ async def test_pagination_initialize(httpx_mock):
|
|
|
404
421
|
client = PaginatedClient(base_url='http://lol')
|
|
405
422
|
assert await client.paginate('/').list() == [dict(a=1), dict(a=2)]
|
|
406
423
|
|
|
407
|
-
httpx_mock.add_response(url='http://lol
|
|
424
|
+
httpx_mock.add_response(url='http://lol/', json=dict(
|
|
408
425
|
total_pages=2,
|
|
409
426
|
items=[dict(a=1)],
|
|
410
427
|
))
|
|
@@ -414,7 +431,7 @@ async def test_pagination_initialize(httpx_mock):
|
|
|
414
431
|
@pytest.mark.asyncio
|
|
415
432
|
async def test_token_get(httpx_mock):
|
|
416
433
|
httpx_mock.add_response(url='http://lol/token', json=dict(token=123))
|
|
417
|
-
httpx_mock.add_response(url='http://lol
|
|
434
|
+
httpx_mock.add_response(url='http://lol/', json=[])
|
|
418
435
|
|
|
419
436
|
class TokenClient(Client):
|
|
420
437
|
async def token_get(self):
|
|
@@ -431,7 +448,7 @@ async def test_pagination_model(httpx_mock):
|
|
|
431
448
|
class Model(dict):
|
|
432
449
|
pass
|
|
433
450
|
|
|
434
|
-
httpx_mock.add_response(url='http://lol
|
|
451
|
+
httpx_mock.add_response(url='http://lol/', json=[dict(a=2)])
|
|
435
452
|
httpx_mock.add_response(url='http://lol/?page=2', json=[])
|
|
436
453
|
client = Client(base_url='http://lol')
|
|
437
454
|
result = await client.paginate('/', model=Model).list()
|
|
@@ -450,47 +467,50 @@ async def test_pagination_patterns(httpx_mock):
|
|
|
450
467
|
# I'm dealing with APIs which have a different pagination system on
|
|
451
468
|
# different resources, and on some resources no pagination at all
|
|
452
469
|
# Would like to define that per model
|
|
470
|
+
|
|
471
|
+
class TotalPaginator(cli2.Paginator):
|
|
472
|
+
def pagination_initialize(self, data):
|
|
473
|
+
self.total_items = data['total_items']
|
|
474
|
+
self.per_page = len(data['items'])
|
|
475
|
+
|
|
453
476
|
class TotalModel(Client.Model):
|
|
477
|
+
paginator = TotalPaginator
|
|
454
478
|
url_list = '/foo'
|
|
455
479
|
|
|
456
|
-
@classmethod
|
|
457
|
-
def pagination_initialize(cls, paginator, data):
|
|
458
|
-
paginator.total_items = data['total_items']
|
|
459
|
-
paginator.per_page = len(data['items'])
|
|
460
|
-
|
|
461
480
|
httpx_mock.add_response(
|
|
462
|
-
url='http://lol/foo
|
|
481
|
+
url='http://lol/foo',
|
|
463
482
|
json=dict(total_items=2, items=[dict(a=1)]),
|
|
464
483
|
)
|
|
465
484
|
|
|
485
|
+
class PagesPaginator(cli2.Paginator):
|
|
486
|
+
def pagination_initialize(self, data):
|
|
487
|
+
self.total_pages = data['total_pages']
|
|
488
|
+
self.per_page = len(data['items'])
|
|
489
|
+
|
|
466
490
|
class Pages(Client.Model):
|
|
467
491
|
url_list = '/bar'
|
|
468
|
-
|
|
469
|
-
@classmethod
|
|
470
|
-
def pagination_initialize(cls, paginator, data):
|
|
471
|
-
paginator.total_pages = data['total_pages']
|
|
472
|
-
paginator.per_page = len(data['items'])
|
|
492
|
+
paginator = PagesPaginator
|
|
473
493
|
|
|
474
494
|
httpx_mock.add_response(
|
|
475
|
-
url='http://lol/bar
|
|
495
|
+
url='http://lol/bar',
|
|
476
496
|
json=dict(total_pages=1, items=[dict(a=1)]),
|
|
477
497
|
)
|
|
478
498
|
|
|
479
|
-
class
|
|
480
|
-
|
|
499
|
+
class OffsetPaginator(cli2.Paginator):
|
|
500
|
+
def pagination_initialize(self, data):
|
|
501
|
+
self.total_items = data['total']
|
|
481
502
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
paginator.total_items = data['total']
|
|
485
|
-
|
|
486
|
-
@classmethod
|
|
487
|
-
def pagination_parameters(cls, paginator, page_number):
|
|
488
|
-
paginator.per_page = 1
|
|
503
|
+
def pagination_parameters(self, page_number):
|
|
504
|
+
self.per_page = 1
|
|
489
505
|
return dict(
|
|
490
506
|
offset=(page_number - 1) * paginator.per_page,
|
|
491
507
|
limit=paginator.per_page,
|
|
492
508
|
)
|
|
493
509
|
|
|
510
|
+
class Offset(Client.Model):
|
|
511
|
+
url_list = '/off'
|
|
512
|
+
paginator = OffsetPaginator
|
|
513
|
+
|
|
494
514
|
httpx_mock.add_response(
|
|
495
515
|
url='http://lol/off?offset=0&limit=1',
|
|
496
516
|
json=dict(total=2, items=[dict(a=1)]),
|
|
@@ -519,7 +539,7 @@ async def test_pagination_patterns(httpx_mock):
|
|
|
519
539
|
@pytest.mark.asyncio
|
|
520
540
|
async def test_pagination_reverse(httpx_mock):
|
|
521
541
|
httpx_mock.add_response(
|
|
522
|
-
url='http://lol/bar
|
|
542
|
+
url='http://lol/bar',
|
|
523
543
|
json=dict(total_pages=3, items=[dict(a=1), dict(a=2)]),
|
|
524
544
|
)
|
|
525
545
|
httpx_mock.add_response(
|
|
@@ -531,13 +551,13 @@ async def test_pagination_reverse(httpx_mock):
|
|
|
531
551
|
json=dict(total_pages=3, items=[dict(a=5)]),
|
|
532
552
|
)
|
|
533
553
|
|
|
554
|
+
class Paginator(cli2.Paginator):
|
|
555
|
+
def pagination_initialize(self, data):
|
|
556
|
+
self.total_pages = data['total_pages']
|
|
557
|
+
|
|
534
558
|
# test that we can reverse pagination too
|
|
535
559
|
class Client(cli2.Client):
|
|
536
|
-
|
|
537
|
-
paginator.total_pages = data['total_pages']
|
|
538
|
-
|
|
539
|
-
def pagination_parameters(self, paginator, page_number):
|
|
540
|
-
return dict(page=page_number)
|
|
560
|
+
paginator = Paginator
|
|
541
561
|
|
|
542
562
|
client = Client(base_url='http://lol')
|
|
543
563
|
paginator = client.paginate('/bar')
|
|
@@ -663,17 +683,18 @@ def test_relation_many():
|
|
|
663
683
|
|
|
664
684
|
@pytest.mark.asyncio
|
|
665
685
|
async def test_python_expression(httpx_mock):
|
|
686
|
+
class Paginator(cli2.Paginator):
|
|
687
|
+
def pagination_initialize(self, data):
|
|
688
|
+
self.total_pages = data['total_pages']
|
|
689
|
+
|
|
666
690
|
class Model(Client.Model):
|
|
667
691
|
url_list = '/foo'
|
|
668
692
|
a = cli2.Field()
|
|
669
693
|
b = cli2.Field()
|
|
670
|
-
|
|
671
|
-
@classmethod
|
|
672
|
-
def pagination_initialize(cls, paginator, data):
|
|
673
|
-
paginator.total_pages = data['total_pages']
|
|
694
|
+
paginator = Paginator
|
|
674
695
|
|
|
675
696
|
def mock():
|
|
676
|
-
httpx_mock.add_response(url='http://lol/foo
|
|
697
|
+
httpx_mock.add_response(url='http://lol/foo', json=dict(
|
|
677
698
|
total_pages=2,
|
|
678
699
|
items=[dict(a=1, b=1), dict(a=2, b=2), dict(a=3, b=1)],
|
|
679
700
|
))
|
|
@@ -723,7 +744,7 @@ async def test_expression_parameter(httpx_mock):
|
|
|
723
744
|
a = cli2.Field()
|
|
724
745
|
b = cli2.Field(parameter='b')
|
|
725
746
|
|
|
726
|
-
httpx_mock.add_response(url='http://lol/foo?
|
|
747
|
+
httpx_mock.add_response(url='http://lol/foo?b=1', json=dict(
|
|
727
748
|
items=[dict(a=1, b=1), dict(a=3, b=1)],
|
|
728
749
|
))
|
|
729
750
|
httpx_mock.add_response(url='http://lol/foo?page=2&b=1', json=dict())
|
|
@@ -769,7 +790,7 @@ async def test_client_cli2(httpx_mock):
|
|
|
769
790
|
|
|
770
791
|
meth = Client.cli['foo']['find']
|
|
771
792
|
httpx_mock.add_response(
|
|
772
|
-
url='http://lol/foo
|
|
793
|
+
url='http://lol/foo',
|
|
773
794
|
json=[dict(id=1, a=2)],
|
|
774
795
|
)
|
|
775
796
|
httpx_mock.add_response(url='http://lol/foo?page=2', json=[])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: cli2
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.40
|
|
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
|
|
@@ -23,6 +23,17 @@ Requires-Dist: pytest-cov; extra == "test"
|
|
|
23
23
|
Requires-Dist: pytest-mock; extra == "test"
|
|
24
24
|
Requires-Dist: pytest-asyncio; extra == "test"
|
|
25
25
|
Requires-Dist: pytest-httpx; extra == "test"
|
|
26
|
+
Dynamic: author
|
|
27
|
+
Dynamic: author-email
|
|
28
|
+
Dynamic: description
|
|
29
|
+
Dynamic: description-content-type
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: keywords
|
|
32
|
+
Dynamic: license
|
|
33
|
+
Dynamic: provides-extra
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
26
37
|
|
|
27
38
|
.. image:: https://yourlabs.io/oss/cli2/badges/master/pipeline.svg
|
|
28
39
|
:target: https://yourlabs.io/oss/cli2/pipelines
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|