cli2 4.0.8__tar.gz → 4.0.11__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.8/cli2.egg-info → cli2-4.0.11}/PKG-INFO +1 -1
- {cli2-4.0.8 → cli2-4.0.11}/cli2/__init__.py +1 -1
- {cli2-4.0.8 → cli2-4.0.11}/cli2/client.py +16 -8
- {cli2-4.0.8 → cli2-4.0.11}/cli2/log.py +2 -16
- {cli2-4.0.8 → cli2-4.0.11/cli2.egg-info}/PKG-INFO +1 -1
- {cli2-4.0.8 → cli2-4.0.11}/setup.py +1 -1
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_client.py +32 -25
- {cli2-4.0.8 → cli2-4.0.11}/MANIFEST.in +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/README.rst +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/classifiers.txt +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/ansible/__init__.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/ansible/action.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/ansible/playbook.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/ansible/pytest.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/ansible/variables.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/asyncio.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/cli.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/cli2.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/colors.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/configuration.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/decorators.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/display.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/__init__.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/client.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/conf.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/example.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/example_obj.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/nesting.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/obj.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/obj2.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/examples/test.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/lock.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/node.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/sphinx.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/table.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2/test.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2.egg-info/SOURCES.txt +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2.egg-info/dependency_links.txt +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2.egg-info/entry_points.txt +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2.egg-info/requires.txt +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/cli2.egg-info/top_level.txt +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/setup.cfg +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_ansible.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_ansible_variables.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_cli.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_command.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_configuration.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_decorators.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_display.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_entry_point.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_group.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_inject.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_lock.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_node.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/tests/test_restful.py +0 -0
- {cli2-4.0.8 → cli2-4.0.11}/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:
|
|
@@ -196,7 +196,14 @@ class Paginator:
|
|
|
196
196
|
data = response.json()
|
|
197
197
|
except json.JSONDecodeError:
|
|
198
198
|
return []
|
|
199
|
+
return self.data_items(data)
|
|
199
200
|
|
|
201
|
+
def data_items(self, data):
|
|
202
|
+
"""
|
|
203
|
+
Given response data, return items.
|
|
204
|
+
|
|
205
|
+
:param data: Response JSON data
|
|
206
|
+
"""
|
|
200
207
|
items_list = []
|
|
201
208
|
if isinstance(data, list):
|
|
202
209
|
items_list = data
|
|
@@ -1029,11 +1036,14 @@ class Handler:
|
|
|
1029
1036
|
self.backoff = self.backoff_default if backoff is None else backoff
|
|
1030
1037
|
|
|
1031
1038
|
async def __call__(self, client, response, tries, mask, log):
|
|
1039
|
+
seconds = tries * self.backoff
|
|
1040
|
+
|
|
1032
1041
|
if isinstance(response, Exception):
|
|
1033
1042
|
if tries >= self.tries:
|
|
1034
1043
|
raise response
|
|
1035
1044
|
# httpx session is rendered unusable after a TransportError
|
|
1036
1045
|
if isinstance(response, httpx.TransportError):
|
|
1046
|
+
await asyncio.sleep(seconds)
|
|
1037
1047
|
log.warn('reconnect', error=repr(response))
|
|
1038
1048
|
await client.client_reset()
|
|
1039
1049
|
return
|
|
@@ -1050,7 +1060,6 @@ class Handler:
|
|
|
1050
1060
|
if tries >= self.tries:
|
|
1051
1061
|
raise RetriesExceededError(client, response, tries, mask)
|
|
1052
1062
|
|
|
1053
|
-
seconds = tries * self.backoff
|
|
1054
1063
|
kwargs = dict(
|
|
1055
1064
|
status_code=response.status_code,
|
|
1056
1065
|
tries=tries,
|
|
@@ -1263,7 +1272,6 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1263
1272
|
truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT),
|
|
1264
1273
|
)
|
|
1265
1274
|
|
|
1266
|
-
self.logger = structlog.get_logger('cli2')
|
|
1267
1275
|
self.token_getting = False
|
|
1268
1276
|
self.token = None
|
|
1269
1277
|
|
|
@@ -1500,13 +1508,13 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1500
1508
|
extensions=extensions,
|
|
1501
1509
|
)
|
|
1502
1510
|
|
|
1503
|
-
|
|
1511
|
+
_log = log.bind(method=method, url=str(request.url))
|
|
1504
1512
|
if not quiet or self.debug:
|
|
1505
1513
|
key, value = self.request_log_data(request, mask, quiet)
|
|
1506
1514
|
kwargs = dict()
|
|
1507
1515
|
if value:
|
|
1508
1516
|
kwargs[key] = value
|
|
1509
|
-
|
|
1517
|
+
_log.debug('request', **kwargs)
|
|
1510
1518
|
|
|
1511
1519
|
response = await self.send(
|
|
1512
1520
|
request,
|
|
@@ -1519,13 +1527,13 @@ class Client(metaclass=ClientMetaclass):
|
|
|
1519
1527
|
follow_redirects=follow_redirects,
|
|
1520
1528
|
)
|
|
1521
1529
|
|
|
1522
|
-
|
|
1530
|
+
kwargs = dict(status_code=response.status_code)
|
|
1523
1531
|
if not quiet or self.debug:
|
|
1524
1532
|
key, value = self.response_log_data(response, mask)
|
|
1525
1533
|
if value:
|
|
1526
|
-
|
|
1534
|
+
kwargs[key] = value
|
|
1527
1535
|
|
|
1528
|
-
|
|
1536
|
+
_log.info('response', **kwargs)
|
|
1529
1537
|
|
|
1530
1538
|
return response
|
|
1531
1539
|
|
|
@@ -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
|
|
@@ -858,11 +859,12 @@ def test_datetime_default_fmt(client_class):
|
|
|
858
859
|
|
|
859
860
|
|
|
860
861
|
@pytest.mark.asyncio
|
|
861
|
-
async def test_mask_recursive(client_class):
|
|
862
|
+
async def test_mask_recursive(client_class, monkeypatch):
|
|
862
863
|
client = client_class(mask=['scrt', 'password'])
|
|
863
864
|
client.client.send = mock.AsyncMock()
|
|
864
865
|
|
|
865
|
-
|
|
866
|
+
log = mock.Mock()
|
|
867
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
866
868
|
response = httpx.Response(
|
|
867
869
|
status_code=200,
|
|
868
870
|
content='{"pub": 1, "foo": [{"scrt": "pass"}]}',
|
|
@@ -871,11 +873,11 @@ async def test_mask_recursive(client_class):
|
|
|
871
873
|
response.request = httpx.Request('POST', '/', json=data)
|
|
872
874
|
client.client.send.return_value = response
|
|
873
875
|
await client.post('/', json=data)
|
|
874
|
-
|
|
876
|
+
log.bind.assert_called_once_with(
|
|
875
877
|
method='POST',
|
|
876
878
|
url='http://lol/',
|
|
877
879
|
)
|
|
878
|
-
log =
|
|
880
|
+
log = log.bind.return_value
|
|
879
881
|
log.debug.assert_called_once_with(
|
|
880
882
|
'request',
|
|
881
883
|
json=[{'foo': [{'src': 'pass'}]}],
|
|
@@ -891,11 +893,12 @@ async def test_mask_recursive(client_class):
|
|
|
891
893
|
@pytest.mark.parametrize(
|
|
892
894
|
'key', ('json', 'data'),
|
|
893
895
|
)
|
|
894
|
-
async def test_mask_logs(client_class, key):
|
|
896
|
+
async def test_mask_logs(client_class, key, monkeypatch):
|
|
895
897
|
client = client_class(mask=['scrt', 'password'])
|
|
896
898
|
client.client.send = mock.AsyncMock()
|
|
897
899
|
|
|
898
|
-
|
|
900
|
+
log = mock.Mock()
|
|
901
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
899
902
|
response = httpx.Response(
|
|
900
903
|
status_code=200,
|
|
901
904
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -904,11 +907,11 @@ async def test_mask_logs(client_class, key):
|
|
|
904
907
|
response.request = httpx.Request('POST', '/', **{key: data})
|
|
905
908
|
client.client.send.return_value = response
|
|
906
909
|
await client.post('/', **{key: data})
|
|
907
|
-
|
|
910
|
+
log.bind.assert_called_once_with(
|
|
908
911
|
method='POST',
|
|
909
912
|
url='http://lol/',
|
|
910
913
|
)
|
|
911
|
-
log =
|
|
914
|
+
log = log.bind.return_value
|
|
912
915
|
log.debug.assert_called_once_with(
|
|
913
916
|
'request',
|
|
914
917
|
**{key: dict(foo='bar', password='***MASKED***')},
|
|
@@ -942,11 +945,12 @@ async def test_mask_exceptions(client_class):
|
|
|
942
945
|
|
|
943
946
|
|
|
944
947
|
@pytest.mark.asyncio
|
|
945
|
-
async def test_request_mask(client_class):
|
|
948
|
+
async def test_request_mask(client_class, monkeypatch):
|
|
946
949
|
client = client_class(mask=['password'])
|
|
947
950
|
client.client.send = mock.AsyncMock()
|
|
948
951
|
|
|
949
|
-
|
|
952
|
+
log = mock.Mock()
|
|
953
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
950
954
|
response = httpx.Response(
|
|
951
955
|
status_code=200,
|
|
952
956
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -955,11 +959,11 @@ async def test_request_mask(client_class):
|
|
|
955
959
|
response.request = httpx.Request('POST', '/', json=data)
|
|
956
960
|
client.client.send.return_value = response
|
|
957
961
|
await client.post('/', json=data, mask=['scrt'])
|
|
958
|
-
|
|
962
|
+
log.bind.assert_called_once_with(
|
|
959
963
|
method='POST',
|
|
960
964
|
url='http://lol/'
|
|
961
965
|
)
|
|
962
|
-
log =
|
|
966
|
+
log = log.bind.return_value
|
|
963
967
|
log.debug.assert_called_once_with(
|
|
964
968
|
'request',
|
|
965
969
|
json=dict(foo='bar', password='secret'),
|
|
@@ -972,19 +976,20 @@ async def test_request_mask(client_class):
|
|
|
972
976
|
|
|
973
977
|
|
|
974
978
|
@pytest.mark.asyncio
|
|
975
|
-
async def test_log_content(client_class):
|
|
979
|
+
async def test_log_content(client_class, monkeypatch):
|
|
976
980
|
client = client_class()
|
|
977
981
|
client.client.send = mock.AsyncMock()
|
|
978
|
-
|
|
982
|
+
log = mock.Mock()
|
|
983
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
979
984
|
response = httpx.Response(status_code=200, content='lol:]bar')
|
|
980
985
|
response.request = httpx.Request('POST', '/')
|
|
981
986
|
client.client.send.return_value = response
|
|
982
987
|
await client.post('/', content='lol:]foo')
|
|
983
|
-
|
|
988
|
+
log.bind.assert_called_once_with(
|
|
984
989
|
method='POST',
|
|
985
990
|
url='http://lol/'
|
|
986
991
|
)
|
|
987
|
-
log =
|
|
992
|
+
log = log.bind.return_value
|
|
988
993
|
log.debug.assert_called_once_with('request', content='lol:]foo')
|
|
989
994
|
log.info.assert_called_once_with(
|
|
990
995
|
'response', status_code=200, content=b'lol:]bar'
|
|
@@ -992,20 +997,20 @@ async def test_log_content(client_class):
|
|
|
992
997
|
|
|
993
998
|
|
|
994
999
|
@pytest.mark.asyncio
|
|
995
|
-
async def test_log_quiet(client_class):
|
|
1000
|
+
async def test_log_quiet(client_class, monkeypatch):
|
|
996
1001
|
client = client_class()
|
|
997
1002
|
client.client.send = mock.AsyncMock()
|
|
998
|
-
|
|
1003
|
+
log = mock.Mock()
|
|
1004
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
999
1005
|
response = httpx.Response(status_code=200, content='[1]')
|
|
1000
1006
|
response.request = httpx.Request('GET', '/')
|
|
1001
1007
|
client.client.send.return_value = response
|
|
1002
1008
|
await client.get('/', json=[1], quiet=True)
|
|
1003
|
-
log
|
|
1004
|
-
client.logger.bind.assert_called_once_with(
|
|
1009
|
+
log.bind.assert_called_once_with(
|
|
1005
1010
|
method='GET',
|
|
1006
1011
|
url='http://lol/',
|
|
1007
1012
|
)
|
|
1008
|
-
log =
|
|
1013
|
+
log = log.bind.return_value
|
|
1009
1014
|
assert not log.debug.call_args_list
|
|
1010
1015
|
log.info.assert_called_once_with('response', status_code=200)
|
|
1011
1016
|
|
|
@@ -1068,11 +1073,13 @@ def test_id_value(client_class):
|
|
|
1068
1073
|
|
|
1069
1074
|
|
|
1070
1075
|
@pytest.mark.asyncio
|
|
1071
|
-
async def test_debug(client_class):
|
|
1076
|
+
async def test_debug(client_class, monkeypatch):
|
|
1072
1077
|
client = client_class(mask=['scrt', 'password'], debug=True)
|
|
1073
1078
|
client.client.send = mock.AsyncMock()
|
|
1074
1079
|
|
|
1075
|
-
|
|
1080
|
+
log = mock.Mock()
|
|
1081
|
+
monkeypatch.setattr(cli2.client, 'log', log)
|
|
1082
|
+
|
|
1076
1083
|
response = httpx.Response(
|
|
1077
1084
|
status_code=200,
|
|
1078
1085
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -1081,11 +1088,11 @@ async def test_debug(client_class):
|
|
|
1081
1088
|
response.request = httpx.Request('POST', '/', json=data)
|
|
1082
1089
|
client.client.send.return_value = response
|
|
1083
1090
|
await client.post('/', json=data, quiet=True)
|
|
1084
|
-
|
|
1091
|
+
log.bind.assert_called_once_with(
|
|
1085
1092
|
method='POST',
|
|
1086
1093
|
url='http://lol/',
|
|
1087
1094
|
)
|
|
1088
|
-
log =
|
|
1095
|
+
log = log.bind.return_value
|
|
1089
1096
|
log.debug.assert_called_once_with(
|
|
1090
1097
|
'request',
|
|
1091
1098
|
json=dict(foo='bar', password='secret'),
|
|
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
|