cli2 4.0.7__tar.gz → 4.0.10__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-4.0.7/cli2.egg-info → cli2-4.0.10}/PKG-INFO +1 -1
- {cli2-4.0.7 → cli2-4.0.10}/cli2/__init__.py +1 -1
- {cli2-4.0.7 → cli2-4.0.10}/cli2/client.py +37 -29
- {cli2-4.0.7 → cli2-4.0.10}/cli2/log.py +2 -16
- {cli2-4.0.7 → cli2-4.0.10/cli2.egg-info}/PKG-INFO +1 -1
- {cli2-4.0.7 → cli2-4.0.10}/setup.py +1 -1
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_client.py +56 -56
- {cli2-4.0.7 → cli2-4.0.10}/MANIFEST.in +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/README.rst +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/classifiers.txt +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/ansible/__init__.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/ansible/action.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/ansible/playbook.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/ansible/pytest.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/ansible/variables.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/asyncio.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/cli.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/cli2.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/colors.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/configuration.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/decorators.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/display.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/__init__.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/client.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/conf.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/example.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/example_obj.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/nesting.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/obj.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/obj2.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/examples/test.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/lock.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/node.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/sphinx.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/table.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2/test.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2.egg-info/SOURCES.txt +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2.egg-info/dependency_links.txt +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2.egg-info/entry_points.txt +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2.egg-info/requires.txt +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/cli2.egg-info/top_level.txt +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/setup.cfg +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_ansible.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_ansible_variables.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_cli.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_command.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_configuration.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_decorators.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_display.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_entry_point.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_group.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_inject.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_lock.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_node.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_restful.py +0 -0
- {cli2-4.0.7 → cli2-4.0.10}/tests/test_table.py +0 -0
|
@@ -10,7 +10,6 @@ import json
|
|
|
10
10
|
import math
|
|
11
11
|
import os
|
|
12
12
|
import ssl
|
|
13
|
-
import structlog
|
|
14
13
|
import yaml
|
|
15
14
|
|
|
16
15
|
from datetime import datetime
|
|
@@ -26,6 +25,7 @@ from . import display
|
|
|
26
25
|
from .asyncio import async_resolve
|
|
27
26
|
from .cli import Command, Group, cmd, hide
|
|
28
27
|
from .colors import colors
|
|
28
|
+
from .log import log
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
class Paginator:
|
|
@@ -690,6 +690,7 @@ class ModelMetaclass(type):
|
|
|
690
690
|
def __new__(cls, name, bases, attributes):
|
|
691
691
|
if 'Paginator' in attributes:
|
|
692
692
|
attributes['paginator'] = attributes['Paginator']
|
|
693
|
+
|
|
693
694
|
cls = super().__new__(cls, name, bases, attributes)
|
|
694
695
|
client = getattr(cls, 'client', None)
|
|
695
696
|
if client:
|
|
@@ -700,11 +701,6 @@ class ModelMetaclass(type):
|
|
|
700
701
|
client_class = getattr(cls, '_client_class', None)
|
|
701
702
|
if client_class:
|
|
702
703
|
client_class.models.append(cls)
|
|
703
|
-
client_cli = getattr(client_class, 'cli', None)
|
|
704
|
-
if client_cli:
|
|
705
|
-
group = ModelGroup(cls)
|
|
706
|
-
if len(group) > 1:
|
|
707
|
-
cls.cli = client_cli[cls.__name__.lower()] = group
|
|
708
704
|
|
|
709
705
|
cls._fields = dict()
|
|
710
706
|
|
|
@@ -939,6 +935,8 @@ class Model(metaclass=ModelMetaclass):
|
|
|
939
935
|
|
|
940
936
|
|
|
941
937
|
class ClientMetaclass(type):
|
|
938
|
+
cli_kwargs = dict()
|
|
939
|
+
|
|
942
940
|
def __new__(cls, name, bases, attributes):
|
|
943
941
|
if 'Paginator' in attributes:
|
|
944
942
|
attributes['paginator'] = attributes['Paginator']
|
|
@@ -947,22 +945,29 @@ class ClientMetaclass(type):
|
|
|
947
945
|
# bind ourself as _client_class to any inherited model
|
|
948
946
|
cls.Model = type('Model', (Model,), dict(_client_class=cls))
|
|
949
947
|
cls.models = []
|
|
950
|
-
|
|
951
|
-
cli_kwargs = dict(
|
|
952
|
-
name=cls.__name__.lower().replace('client', '') or 'client',
|
|
953
|
-
doc=inspect.getdoc(cls),
|
|
954
|
-
overrides=dict(
|
|
955
|
-
cls=dict(factory=lambda: cls),
|
|
956
|
-
self=dict(factory=lambda: cls())
|
|
957
|
-
),
|
|
958
|
-
)
|
|
959
|
-
if new_kwargs := getattr(cls, 'cli2', None):
|
|
960
|
-
cli_kwargs.update(new_kwargs)
|
|
961
|
-
cli_kwargs.update(cls.__dict__.get('cli_kwargs', dict()))
|
|
962
|
-
cls.cli = Group(**cli_kwargs)
|
|
963
|
-
cls.cli.load(cls)
|
|
964
948
|
return cls
|
|
965
949
|
|
|
950
|
+
@property
|
|
951
|
+
def cli(cls):
|
|
952
|
+
if '_cli' not in cls.__dict__:
|
|
953
|
+
cli_kwargs = dict(
|
|
954
|
+
name=cls.__name__.lower().replace('client', '') or 'client',
|
|
955
|
+
doc=inspect.getdoc(cls),
|
|
956
|
+
overrides=dict(
|
|
957
|
+
cls=dict(factory=lambda: cls),
|
|
958
|
+
self=dict(factory=lambda: cls())
|
|
959
|
+
),
|
|
960
|
+
)
|
|
961
|
+
cli_kwargs.update(cls.cli_kwargs)
|
|
962
|
+
cli = Group(**cli_kwargs)
|
|
963
|
+
cli.load(cls)
|
|
964
|
+
for model in cls.models:
|
|
965
|
+
group = ModelGroup(model)
|
|
966
|
+
if len(group) > 1:
|
|
967
|
+
cli[model.__name__.lower()] = group
|
|
968
|
+
cls._cli = cli
|
|
969
|
+
return cls._cli
|
|
970
|
+
|
|
966
971
|
|
|
967
972
|
class Handler:
|
|
968
973
|
"""
|
|
@@ -1024,11 +1029,14 @@ class Handler:
|
|
|
1024
1029
|
self.backoff = self.backoff_default if backoff is None else backoff
|
|
1025
1030
|
|
|
1026
1031
|
async def __call__(self, client, response, tries, mask, log):
|
|
1032
|
+
seconds = tries * self.backoff
|
|
1033
|
+
|
|
1027
1034
|
if isinstance(response, Exception):
|
|
1028
1035
|
if tries >= self.tries:
|
|
1029
1036
|
raise response
|
|
1030
1037
|
# httpx session is rendered unusable after a TransportError
|
|
1031
1038
|
if isinstance(response, httpx.TransportError):
|
|
1039
|
+
await asyncio.sleep(seconds)
|
|
1032
1040
|
log.warn('reconnect', error=repr(response))
|
|
1033
1041
|
await client.client_reset()
|
|
1034
1042
|
return
|
|
@@ -1045,7 +1053,6 @@ class Handler:
|
|
|
1045
1053
|
if tries >= self.tries:
|
|
1046
1054
|
raise RetriesExceededError(client, response, tries, mask)
|
|
1047
1055
|
|
|
1048
|
-
seconds = tries * self.backoff
|
|
1049
1056
|
kwargs = dict(
|
|
1050
1057
|
status_code=response.status_code,
|
|
1051
1058
|
tries=tries,
|
|
@@ -1209,8 +1216,10 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1209
1216
|
.. py:attribute:: cli
|
|
1210
1217
|
|
|
1211
1218
|
Generated :py:class:`~cli2.cli.Group` for this client.
|
|
1219
|
+
Uses :py:attr:`cli_kwargs` to pass kwargs to the generated group.
|
|
1220
|
+
Note that this is a cached property.
|
|
1212
1221
|
|
|
1213
|
-
.. py:attribute::
|
|
1222
|
+
.. py:attribute:: cli_kwargs
|
|
1214
1223
|
|
|
1215
1224
|
Dict of overrides for the generated :py:class:`~cli2.cli.Group`.
|
|
1216
1225
|
Example:
|
|
@@ -1218,7 +1227,7 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1218
1227
|
.. code-block:: python
|
|
1219
1228
|
|
|
1220
1229
|
class YourClient(cli2.Client):
|
|
1221
|
-
|
|
1230
|
+
cli_kwargs = dict(cmdclass=YourCommandClass)
|
|
1222
1231
|
|
|
1223
1232
|
.. py:attribute:: debug
|
|
1224
1233
|
|
|
@@ -1256,7 +1265,6 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1256
1265
|
truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT),
|
|
1257
1266
|
)
|
|
1258
1267
|
|
|
1259
|
-
self.logger = structlog.get_logger('cli2')
|
|
1260
1268
|
self.token_getting = False
|
|
1261
1269
|
self.token = None
|
|
1262
1270
|
|
|
@@ -1493,13 +1501,13 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1493
1501
|
extensions=extensions,
|
|
1494
1502
|
)
|
|
1495
1503
|
|
|
1496
|
-
|
|
1504
|
+
_log = log.bind(method=method, url=str(request.url))
|
|
1497
1505
|
if not quiet or self.debug:
|
|
1498
1506
|
key, value = self.request_log_data(request, mask, quiet)
|
|
1499
1507
|
kwargs = dict()
|
|
1500
1508
|
if value:
|
|
1501
1509
|
kwargs[key] = value
|
|
1502
|
-
|
|
1510
|
+
_log.debug('request', **kwargs)
|
|
1503
1511
|
|
|
1504
1512
|
response = await self.send(
|
|
1505
1513
|
request,
|
|
@@ -1512,13 +1520,13 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1512
1520
|
follow_redirects=follow_redirects,
|
|
1513
1521
|
)
|
|
1514
1522
|
|
|
1515
|
-
|
|
1523
|
+
kwargs = dict(status_code=response.status_code)
|
|
1516
1524
|
if not quiet or self.debug:
|
|
1517
1525
|
key, value = self.response_log_data(response, mask)
|
|
1518
1526
|
if value:
|
|
1519
|
-
|
|
1527
|
+
kwargs[key] = value
|
|
1520
1528
|
|
|
1521
|
-
|
|
1529
|
+
_log.info('response', **kwargs)
|
|
1522
1530
|
|
|
1523
1531
|
return response
|
|
1524
1532
|
|
|
@@ -70,9 +70,6 @@ class YAMLFormatter:
|
|
|
70
70
|
return '\n' + value
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
configured = False
|
|
74
|
-
|
|
75
|
-
|
|
76
73
|
def configure():
|
|
77
74
|
LOG_LEVEL = os.getenv('LOG_LEVEL', 'WARNING').upper()
|
|
78
75
|
|
|
@@ -200,17 +197,6 @@ def configure():
|
|
|
200
197
|
],
|
|
201
198
|
)
|
|
202
199
|
|
|
203
|
-
global configured
|
|
204
|
-
configured = True
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
def get_logger():
|
|
208
|
-
"""
|
|
209
|
-
Return the beautiful and configured cli2 logger.
|
|
210
|
-
"""
|
|
211
|
-
if not configured:
|
|
212
|
-
configure()
|
|
213
|
-
return structlog.get_logger('cli2')
|
|
214
|
-
|
|
215
200
|
|
|
216
|
-
|
|
201
|
+
configure()
|
|
202
|
+
log = structlog.get_logger('cli2')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
import cli2
|
|
3
|
+
import cli2.client
|
|
3
4
|
import httpx
|
|
4
5
|
import inspect
|
|
5
6
|
import mock
|
|
@@ -37,6 +38,17 @@ def client_class():
|
|
|
37
38
|
|
|
38
39
|
@pytest.mark.asyncio
|
|
39
40
|
async def test_client_cli(client_class, httpx_mock):
|
|
41
|
+
class TestModel(client_class.Model):
|
|
42
|
+
url_list = '/'
|
|
43
|
+
|
|
44
|
+
class TestModel2(client_class.Model):
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
class TestModel3(client_class.Model):
|
|
48
|
+
@cli2.cmd
|
|
49
|
+
def find():
|
|
50
|
+
pass
|
|
51
|
+
|
|
40
52
|
assert client_class.cli
|
|
41
53
|
factory = client_class.cli.overrides['self']['factory']
|
|
42
54
|
assert isinstance(factory(), client_class)
|
|
@@ -45,8 +57,6 @@ async def test_client_cli(client_class, httpx_mock):
|
|
|
45
57
|
response = await client_class.cli['get'].async_call('http://lol')
|
|
46
58
|
assert response.json() == [1]
|
|
47
59
|
|
|
48
|
-
class TestModel(client_class.Model):
|
|
49
|
-
url_list = '/'
|
|
50
60
|
assert 'testmodel' in client_class.cli
|
|
51
61
|
assert client_class.cli['testmodel']['get'].overrides['cls']['factory']
|
|
52
62
|
assert not inspect.ismethod(client_class.cli['testmodel']['get'].target)
|
|
@@ -58,16 +68,8 @@ async def test_client_cli(client_class, httpx_mock):
|
|
|
58
68
|
httpx_mock.add_response(url='http://lol/?page=2', json=[])
|
|
59
69
|
await client_class.cli['testmodel']['find'].async_call()
|
|
60
70
|
|
|
61
|
-
class TestModel2(client_class.Model):
|
|
62
|
-
pass
|
|
63
|
-
|
|
64
71
|
assert 'testmodel2' not in client_class.cli
|
|
65
72
|
|
|
66
|
-
class TestModel3(client_class.Model):
|
|
67
|
-
@cli2.cmd
|
|
68
|
-
def find():
|
|
69
|
-
pass
|
|
70
|
-
|
|
71
73
|
assert list(client_class.cli['testmodel3'].keys()) == ['help', 'find']
|
|
72
74
|
|
|
73
75
|
|
|
@@ -85,7 +87,6 @@ async def test_client_cli_override(client_class, httpx_mock):
|
|
|
85
87
|
@cli2.cmd
|
|
86
88
|
async def find(cls, foo):
|
|
87
89
|
return cls.url_list
|
|
88
|
-
assert await Client.cli['testmodel']['find'].async_call('bar') == 'bar/foo'
|
|
89
90
|
|
|
90
91
|
class TestModel2(Client.Model):
|
|
91
92
|
@classmethod
|
|
@@ -93,12 +94,15 @@ async def test_client_cli_override(client_class, httpx_mock):
|
|
|
93
94
|
async def find(cls):
|
|
94
95
|
return 'foo'
|
|
95
96
|
|
|
96
|
-
assert await Client.cli['testmodel2']['find'].async_call() == 'foo'
|
|
97
|
-
assert 'get' not in Client.cli['testmodel2']
|
|
98
|
-
|
|
99
97
|
class TestModel3(Client.Model):
|
|
100
98
|
url_list = '{client.test}/foo'
|
|
101
99
|
create = None
|
|
100
|
+
|
|
101
|
+
assert await Client.cli['testmodel']['find'].async_call('bar') == 'bar/foo'
|
|
102
|
+
|
|
103
|
+
assert await Client.cli['testmodel2']['find'].async_call() == 'foo'
|
|
104
|
+
assert 'get' not in Client.cli['testmodel2']
|
|
105
|
+
|
|
102
106
|
assert 'create' not in Client.cli['testmodel3']
|
|
103
107
|
|
|
104
108
|
|
|
@@ -123,13 +127,13 @@ async def test_async_factory(httpx_mock, client_class):
|
|
|
123
127
|
async def factory(cls):
|
|
124
128
|
return cls(base_url='http://bar')
|
|
125
129
|
|
|
130
|
+
class TestModel(TestClient.Model):
|
|
131
|
+
url_list = '/2'
|
|
132
|
+
|
|
126
133
|
TestClient.cli.overrides['self']['factory'] = TestClient.factory
|
|
127
134
|
httpx_mock.add_response(url='http://bar/', json=[dict(a=1)])
|
|
128
135
|
assert await TestClient.cli['get'].async_call('/')
|
|
129
136
|
|
|
130
|
-
class TestModel(TestClient.Model):
|
|
131
|
-
url_list = '/2'
|
|
132
|
-
|
|
133
137
|
httpx_mock.add_response(url='http://bar/2', json=[dict(a=1)])
|
|
134
138
|
httpx_mock.add_response(url='http://bar/2?page=2', json=[])
|
|
135
139
|
await TestClient.cli['testmodel']['find'].async_call()
|
|
@@ -777,6 +781,10 @@ async def test_model_crud(httpx_mock, client_class):
|
|
|
777
781
|
|
|
778
782
|
@pytest.mark.asyncio
|
|
779
783
|
async def test_client_cli2(httpx_mock, client_class):
|
|
784
|
+
class Foo(client_class.Model):
|
|
785
|
+
id = cli2.Field()
|
|
786
|
+
url_list = '/foo'
|
|
787
|
+
|
|
780
788
|
assert client_class.cli.name == 'test'
|
|
781
789
|
assert client_class.cli.doc == 'doc'
|
|
782
790
|
|
|
@@ -785,10 +793,6 @@ async def test_client_cli2(httpx_mock, client_class):
|
|
|
785
793
|
resp = await meth.async_call('/foo')
|
|
786
794
|
assert resp.json() == [1]
|
|
787
795
|
|
|
788
|
-
class Foo(client_class.Model):
|
|
789
|
-
id = cli2.Field()
|
|
790
|
-
url_list = '/foo'
|
|
791
|
-
|
|
792
796
|
meth = client_class.cli['foo']['get']
|
|
793
797
|
httpx_mock.add_response(url='http://lol/foo/1', json=dict(id=1, a=2))
|
|
794
798
|
result = await meth.async_call('id=1')
|
|
@@ -855,11 +859,12 @@ def test_datetime_default_fmt(client_class):
|
|
|
855
859
|
|
|
856
860
|
|
|
857
861
|
@pytest.mark.asyncio
|
|
858
|
-
async def test_mask_recursive(client_class):
|
|
862
|
+
async def test_mask_recursive(client_class, monkeypatch):
|
|
859
863
|
client = client_class(mask=['scrt', 'password'])
|
|
860
864
|
client.client.send = mock.AsyncMock()
|
|
861
865
|
|
|
862
|
-
|
|
866
|
+
log = mock.Mock()
|
|
867
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
863
868
|
response = httpx.Response(
|
|
864
869
|
status_code=200,
|
|
865
870
|
content='{"pub": 1, "foo": [{"scrt": "pass"}]}',
|
|
@@ -868,11 +873,11 @@ async def test_mask_recursive(client_class):
|
|
|
868
873
|
response.request = httpx.Request('POST', '/', json=data)
|
|
869
874
|
client.client.send.return_value = response
|
|
870
875
|
await client.post('/', json=data)
|
|
871
|
-
|
|
876
|
+
log.bind.assert_called_once_with(
|
|
872
877
|
method='POST',
|
|
873
878
|
url='http://lol/',
|
|
874
879
|
)
|
|
875
|
-
log =
|
|
880
|
+
log = log.bind.return_value
|
|
876
881
|
log.debug.assert_called_once_with(
|
|
877
882
|
'request',
|
|
878
883
|
json=[{'foo': [{'src': 'pass'}]}],
|
|
@@ -888,11 +893,12 @@ async def test_mask_recursive(client_class):
|
|
|
888
893
|
@pytest.mark.parametrize(
|
|
889
894
|
'key', ('json', 'data'),
|
|
890
895
|
)
|
|
891
|
-
async def test_mask_logs(client_class, key):
|
|
896
|
+
async def test_mask_logs(client_class, key, monkeypatch):
|
|
892
897
|
client = client_class(mask=['scrt', 'password'])
|
|
893
898
|
client.client.send = mock.AsyncMock()
|
|
894
899
|
|
|
895
|
-
|
|
900
|
+
log = mock.Mock()
|
|
901
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
896
902
|
response = httpx.Response(
|
|
897
903
|
status_code=200,
|
|
898
904
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -901,11 +907,11 @@ async def test_mask_logs(client_class, key):
|
|
|
901
907
|
response.request = httpx.Request('POST', '/', **{key: data})
|
|
902
908
|
client.client.send.return_value = response
|
|
903
909
|
await client.post('/', **{key: data})
|
|
904
|
-
|
|
910
|
+
log.bind.assert_called_once_with(
|
|
905
911
|
method='POST',
|
|
906
912
|
url='http://lol/',
|
|
907
913
|
)
|
|
908
|
-
log =
|
|
914
|
+
log = log.bind.return_value
|
|
909
915
|
log.debug.assert_called_once_with(
|
|
910
916
|
'request',
|
|
911
917
|
**{key: dict(foo='bar', password='***MASKED***')},
|
|
@@ -939,11 +945,12 @@ async def test_mask_exceptions(client_class):
|
|
|
939
945
|
|
|
940
946
|
|
|
941
947
|
@pytest.mark.asyncio
|
|
942
|
-
async def test_request_mask(client_class):
|
|
948
|
+
async def test_request_mask(client_class, monkeypatch):
|
|
943
949
|
client = client_class(mask=['password'])
|
|
944
950
|
client.client.send = mock.AsyncMock()
|
|
945
951
|
|
|
946
|
-
|
|
952
|
+
log = mock.Mock()
|
|
953
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
947
954
|
response = httpx.Response(
|
|
948
955
|
status_code=200,
|
|
949
956
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -952,11 +959,11 @@ async def test_request_mask(client_class):
|
|
|
952
959
|
response.request = httpx.Request('POST', '/', json=data)
|
|
953
960
|
client.client.send.return_value = response
|
|
954
961
|
await client.post('/', json=data, mask=['scrt'])
|
|
955
|
-
|
|
962
|
+
log.bind.assert_called_once_with(
|
|
956
963
|
method='POST',
|
|
957
964
|
url='http://lol/'
|
|
958
965
|
)
|
|
959
|
-
log =
|
|
966
|
+
log = log.bind.return_value
|
|
960
967
|
log.debug.assert_called_once_with(
|
|
961
968
|
'request',
|
|
962
969
|
json=dict(foo='bar', password='secret'),
|
|
@@ -969,19 +976,20 @@ async def test_request_mask(client_class):
|
|
|
969
976
|
|
|
970
977
|
|
|
971
978
|
@pytest.mark.asyncio
|
|
972
|
-
async def test_log_content(client_class):
|
|
979
|
+
async def test_log_content(client_class, monkeypatch):
|
|
973
980
|
client = client_class()
|
|
974
981
|
client.client.send = mock.AsyncMock()
|
|
975
|
-
|
|
982
|
+
log = mock.Mock()
|
|
983
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
976
984
|
response = httpx.Response(status_code=200, content='lol:]bar')
|
|
977
985
|
response.request = httpx.Request('POST', '/')
|
|
978
986
|
client.client.send.return_value = response
|
|
979
987
|
await client.post('/', content='lol:]foo')
|
|
980
|
-
|
|
988
|
+
log.bind.assert_called_once_with(
|
|
981
989
|
method='POST',
|
|
982
990
|
url='http://lol/'
|
|
983
991
|
)
|
|
984
|
-
log =
|
|
992
|
+
log = log.bind.return_value
|
|
985
993
|
log.debug.assert_called_once_with('request', content='lol:]foo')
|
|
986
994
|
log.info.assert_called_once_with(
|
|
987
995
|
'response', status_code=200, content=b'lol:]bar'
|
|
@@ -989,20 +997,20 @@ async def test_log_content(client_class):
|
|
|
989
997
|
|
|
990
998
|
|
|
991
999
|
@pytest.mark.asyncio
|
|
992
|
-
async def test_log_quiet(client_class):
|
|
1000
|
+
async def test_log_quiet(client_class, monkeypatch):
|
|
993
1001
|
client = client_class()
|
|
994
1002
|
client.client.send = mock.AsyncMock()
|
|
995
|
-
|
|
1003
|
+
log = mock.Mock()
|
|
1004
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
996
1005
|
response = httpx.Response(status_code=200, content='[1]')
|
|
997
1006
|
response.request = httpx.Request('GET', '/')
|
|
998
1007
|
client.client.send.return_value = response
|
|
999
1008
|
await client.get('/', json=[1], quiet=True)
|
|
1000
|
-
log
|
|
1001
|
-
client.logger.bind.assert_called_once_with(
|
|
1009
|
+
log.bind.assert_called_once_with(
|
|
1002
1010
|
method='GET',
|
|
1003
1011
|
url='http://lol/',
|
|
1004
1012
|
)
|
|
1005
|
-
log =
|
|
1013
|
+
log = log.bind.return_value
|
|
1006
1014
|
assert not log.debug.call_args_list
|
|
1007
1015
|
log.info.assert_called_once_with('response', status_code=200)
|
|
1008
1016
|
|
|
@@ -1065,11 +1073,13 @@ def test_id_value(client_class):
|
|
|
1065
1073
|
|
|
1066
1074
|
|
|
1067
1075
|
@pytest.mark.asyncio
|
|
1068
|
-
async def test_debug(client_class):
|
|
1076
|
+
async def test_debug(client_class, monkeypatch):
|
|
1069
1077
|
client = client_class(mask=['scrt', 'password'], debug=True)
|
|
1070
1078
|
client.client.send = mock.AsyncMock()
|
|
1071
1079
|
|
|
1072
|
-
|
|
1080
|
+
log = mock.Mock()
|
|
1081
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
1082
|
+
|
|
1073
1083
|
response = httpx.Response(
|
|
1074
1084
|
status_code=200,
|
|
1075
1085
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -1078,11 +1088,11 @@ async def test_debug(client_class):
|
|
|
1078
1088
|
response.request = httpx.Request('POST', '/', json=data)
|
|
1079
1089
|
client.client.send.return_value = response
|
|
1080
1090
|
await client.post('/', json=data, quiet=True)
|
|
1081
|
-
|
|
1091
|
+
log.bind.assert_called_once_with(
|
|
1082
1092
|
method='POST',
|
|
1083
1093
|
url='http://lol/',
|
|
1084
1094
|
)
|
|
1085
|
-
log =
|
|
1095
|
+
log = log.bind.return_value
|
|
1086
1096
|
log.debug.assert_called_once_with(
|
|
1087
1097
|
'request',
|
|
1088
1098
|
json=dict(foo='bar', password='secret'),
|
|
@@ -1135,13 +1145,3 @@ async def test_client_token_apply(client_class, httpx_mock):
|
|
|
1135
1145
|
await client.client_reset()
|
|
1136
1146
|
assert client.token == 2
|
|
1137
1147
|
assert client.client.token == 2
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
def test_client_kwargs(client_class):
|
|
1141
|
-
class TestCmd(cli2.Command):
|
|
1142
|
-
pass
|
|
1143
|
-
|
|
1144
|
-
class TestClient(client_class):
|
|
1145
|
-
cli2 = dict(cmdclass=TestCmd)
|
|
1146
|
-
|
|
1147
|
-
assert TestClient.cli.cmdclass == TestCmd
|
|
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
|
|
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
|