cli2 4.3.4__tar.gz → 5.0.0rc2__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.3.4/cli2.egg-info → cli2-5.0.0rc2}/PKG-INFO +1 -1
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/__init__.py +0 -25
- {cli2-4.3.4 → cli2-5.0.0rc2/cli2.egg-info}/PKG-INFO +1 -1
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2.egg-info/SOURCES.txt +0 -6
- {cli2-4.3.4 → cli2-5.0.0rc2}/setup.py +1 -1
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_ansible.py +12 -11
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_ansible_variables.py +5 -5
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_cli.py +1 -1
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_client.py +56 -56
- cli2-4.3.4/cli2/ansible/__init__.py +0 -16
- cli2-4.3.4/cli2/ansible/action.py +0 -400
- cli2-4.3.4/cli2/ansible/playbook.py +0 -215
- cli2-4.3.4/cli2/ansible/variables.py +0 -115
- cli2-4.3.4/cli2/client.py +0 -1870
- cli2-4.3.4/cli2/examples/client.py +0 -61
- {cli2-4.3.4 → cli2-5.0.0rc2}/MANIFEST.in +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/README.rst +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/classifiers.txt +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/asyncio.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/cli.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/cli2.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/colors.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/configuration.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/decorators.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/display.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/__init__.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/conf.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/example.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/example_obj.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/nesting.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/obj.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/obj2.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/examples/test.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/lock.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/log.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/mask.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/node.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/sphinx.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/table.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2/test.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2.egg-info/dependency_links.txt +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2.egg-info/entry_points.txt +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2.egg-info/requires.txt +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/cli2.egg-info/top_level.txt +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/setup.cfg +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_asyncio.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_command.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_configuration.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_decorators.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_display.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_entry_point.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_group.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_inject.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_lock.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_mask.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_node.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_restful.py +0 -0
- {cli2-4.3.4 → cli2-5.0.0rc2}/tests/test_table.py +0 -0
|
@@ -13,31 +13,6 @@ from .asyncio import async_resolve, async_run
|
|
|
13
13
|
from .colors import colors as c
|
|
14
14
|
|
|
15
15
|
from .configuration import Configuration, cfg
|
|
16
|
-
try:
|
|
17
|
-
from .client import (
|
|
18
|
-
ClientError,
|
|
19
|
-
ResponseError,
|
|
20
|
-
TokenGetError,
|
|
21
|
-
RefusedResponseError,
|
|
22
|
-
RetriesExceededError,
|
|
23
|
-
FieldError,
|
|
24
|
-
FieldValueError,
|
|
25
|
-
FieldExternalizeError,
|
|
26
|
-
Client,
|
|
27
|
-
ClientCommand,
|
|
28
|
-
DateTimeField,
|
|
29
|
-
Field,
|
|
30
|
-
Handler,
|
|
31
|
-
JSONStringField,
|
|
32
|
-
Model,
|
|
33
|
-
ModelCommand,
|
|
34
|
-
Paginator,
|
|
35
|
-
Related,
|
|
36
|
-
)
|
|
37
|
-
except ImportError:
|
|
38
|
-
raise
|
|
39
|
-
# httpx not installed
|
|
40
|
-
pass
|
|
41
16
|
from .display import diff, diff_data, render, print, highlight, yaml_highlight
|
|
42
17
|
from .lock import Lock
|
|
43
18
|
from .log import configure, log
|
|
@@ -6,7 +6,6 @@ cli2/__init__.py
|
|
|
6
6
|
cli2/asyncio.py
|
|
7
7
|
cli2/cli.py
|
|
8
8
|
cli2/cli2.py
|
|
9
|
-
cli2/client.py
|
|
10
9
|
cli2/colors.py
|
|
11
10
|
cli2/configuration.py
|
|
12
11
|
cli2/decorators.py
|
|
@@ -24,12 +23,7 @@ cli2.egg-info/dependency_links.txt
|
|
|
24
23
|
cli2.egg-info/entry_points.txt
|
|
25
24
|
cli2.egg-info/requires.txt
|
|
26
25
|
cli2.egg-info/top_level.txt
|
|
27
|
-
cli2/ansible/__init__.py
|
|
28
|
-
cli2/ansible/action.py
|
|
29
|
-
cli2/ansible/playbook.py
|
|
30
|
-
cli2/ansible/variables.py
|
|
31
26
|
cli2/examples/__init__.py
|
|
32
|
-
cli2/examples/client.py
|
|
33
27
|
cli2/examples/conf.py
|
|
34
28
|
cli2/examples/example.py
|
|
35
29
|
cli2/examples/example_obj.py
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import cli2
|
|
2
|
+
import cclient
|
|
2
3
|
import httpx
|
|
3
4
|
import mock
|
|
4
5
|
import pytest
|
|
5
6
|
import textwrap
|
|
6
7
|
import yaml
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
import cansible
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
class ActionModule(
|
|
12
|
+
class ActionModule(cansible.ActionBase):
|
|
12
13
|
mask_keys = ['a']
|
|
13
14
|
|
|
14
15
|
async def run_async(self):
|
|
@@ -31,10 +32,10 @@ async def test_mask(monkeypatch):
|
|
|
31
32
|
|
|
32
33
|
@pytest.mark.asyncio
|
|
33
34
|
async def test_response_error(httpx_mock):
|
|
34
|
-
class Client(
|
|
35
|
+
class Client(cclient.Client):
|
|
35
36
|
mask_keys = ['secret']
|
|
36
37
|
|
|
37
|
-
class Action(
|
|
38
|
+
class Action(cansible.ActionBase):
|
|
38
39
|
async def client_factory(self):
|
|
39
40
|
return Client(base_url='http://foo')
|
|
40
41
|
|
|
@@ -59,9 +60,9 @@ async def test_response_error(httpx_mock):
|
|
|
59
60
|
|
|
60
61
|
@pytest.mark.asyncio
|
|
61
62
|
async def test_option():
|
|
62
|
-
class Action(
|
|
63
|
-
fact =
|
|
64
|
-
arg =
|
|
63
|
+
class Action(cansible.ActionBase):
|
|
64
|
+
fact = cansible.Option(fact='fact', default='default fact')
|
|
65
|
+
arg = cansible.Option(arg='arg', fact='arg_fact')
|
|
65
66
|
|
|
66
67
|
async def run_async(self):
|
|
67
68
|
self.result['arg'] = self.arg
|
|
@@ -90,8 +91,8 @@ async def test_option():
|
|
|
90
91
|
error="Missing arg `arg` or fact `arg_fact`",
|
|
91
92
|
)
|
|
92
93
|
|
|
93
|
-
class Action(
|
|
94
|
-
name =
|
|
94
|
+
class Action(cansible.ActionBase):
|
|
95
|
+
name = cansible.Option('name')
|
|
95
96
|
|
|
96
97
|
async def run_async(self):
|
|
97
98
|
self.result['name'] = self.name
|
|
@@ -108,8 +109,8 @@ async def test_diff(monkeypatch):
|
|
|
108
109
|
_print = mock.Mock()
|
|
109
110
|
monkeypatch.setattr(cli2.display, '_print', _print)
|
|
110
111
|
|
|
111
|
-
class Action(
|
|
112
|
-
name =
|
|
112
|
+
class Action(cansible.ActionBase):
|
|
113
|
+
name = cansible.Option('name', 'object_name', 'Test object')
|
|
113
114
|
|
|
114
115
|
async def run_async(self):
|
|
115
116
|
self.before_set(dict(foo=1))
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import cansible
|
|
2
2
|
import pytest
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def test_story():
|
|
7
|
-
variables =
|
|
7
|
+
variables = cansible.Variables(
|
|
8
8
|
root_path=os.path.dirname(__file__),
|
|
9
9
|
pass_path=os.path.dirname(__file__) + '/vault_pass',
|
|
10
10
|
)
|
|
@@ -14,7 +14,7 @@ def test_story():
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def test_exceptions():
|
|
17
|
-
variables =
|
|
17
|
+
variables = cansible.Variables()
|
|
18
18
|
with pytest.raises(Exception) as exc:
|
|
19
19
|
variables['variables.yml']
|
|
20
20
|
assert exc.value.args == (
|
|
@@ -25,12 +25,12 @@ def test_exceptions():
|
|
|
25
25
|
variables['/variables_vault.yml']
|
|
26
26
|
assert exc.value.args == ('/variables_vault.yml does not exist',)
|
|
27
27
|
|
|
28
|
-
variables =
|
|
28
|
+
variables = cansible.Variables(root_path=os.path.dirname(__file__))
|
|
29
29
|
with pytest.raises(Exception) as exc:
|
|
30
30
|
variables['variables_vault.yml']
|
|
31
31
|
assert exc.value.args == ('Vault password required in pass_path',)
|
|
32
32
|
|
|
33
|
-
variables =
|
|
33
|
+
variables = cansible.Variables(
|
|
34
34
|
root_path=os.path.dirname(__file__),
|
|
35
35
|
pass_path='/does/not/exist',
|
|
36
36
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
import cli2
|
|
3
|
-
import
|
|
3
|
+
import cclient
|
|
4
4
|
import httpx
|
|
5
5
|
import inspect
|
|
6
6
|
import mock
|
|
@@ -11,7 +11,7 @@ async def _response(**kwargs):
|
|
|
11
11
|
return httpx.Response(**kwargs)
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class HandlerSentinel(
|
|
14
|
+
class HandlerSentinel(cclient.Handler):
|
|
15
15
|
def __init__(self, *args, **kwargs):
|
|
16
16
|
super().__init__(*args, **kwargs)
|
|
17
17
|
self.calls = []
|
|
@@ -23,9 +23,9 @@ class HandlerSentinel(cli2.Handler):
|
|
|
23
23
|
|
|
24
24
|
@pytest.fixture
|
|
25
25
|
def client_class():
|
|
26
|
-
class TestClient(
|
|
26
|
+
class TestClient(cclient.Client):
|
|
27
27
|
""" doc """
|
|
28
|
-
class Paginator(
|
|
28
|
+
class Paginator(cclient.Paginator):
|
|
29
29
|
def pagination_parameters(self, params, page_number):
|
|
30
30
|
if page_number > 1:
|
|
31
31
|
params['page'] = page_number
|
|
@@ -118,7 +118,7 @@ async def test_client_cli_override(client_class, httpx_mock):
|
|
|
118
118
|
|
|
119
119
|
|
|
120
120
|
def test_client_model(client_class):
|
|
121
|
-
assert issubclass(client_class.Model,
|
|
121
|
+
assert issubclass(client_class.Model, cclient.Model)
|
|
122
122
|
assert client_class.Model._client_class == client_class
|
|
123
123
|
|
|
124
124
|
class TestModel(client_class.Model):
|
|
@@ -152,27 +152,27 @@ async def test_async_factory(httpx_mock, client_class):
|
|
|
152
152
|
|
|
153
153
|
@pytest.mark.asyncio
|
|
154
154
|
async def test_client_cli_side_effect(client_class, httpx_mock):
|
|
155
|
-
from
|
|
155
|
+
from cclient import example
|
|
156
156
|
|
|
157
157
|
# test that this didn't spill over client_class
|
|
158
158
|
test_client_cli(client_class, httpx_mock)
|
|
159
159
|
|
|
160
160
|
# Test that Client's __init_subclass__ did setup a factory for self
|
|
161
161
|
assert isinstance(
|
|
162
|
-
await
|
|
163
|
-
|
|
162
|
+
await example.APIClient.cli['get']['self'].factory_value(),
|
|
163
|
+
example.APIClient,
|
|
164
164
|
)
|
|
165
165
|
|
|
166
166
|
# Test that Model's __init_subclass__ did setup a factory for cls
|
|
167
167
|
httpx_mock.add_response(url='http://localhost:8000/1', json=[1])
|
|
168
|
-
result = await
|
|
168
|
+
result = await example.cli['get'].async_call('/1')
|
|
169
169
|
assert result.json() == [1]
|
|
170
170
|
|
|
171
171
|
httpx_mock.add_response(
|
|
172
172
|
url='http://localhost:8000/objects/1/',
|
|
173
173
|
json=dict(id=1, a=2),
|
|
174
174
|
)
|
|
175
|
-
result = await
|
|
175
|
+
result = await example.cli['object']['get'].async_call('id=1')
|
|
176
176
|
assert result.id == 1
|
|
177
177
|
assert result.data['a'] == 2
|
|
178
178
|
|
|
@@ -261,7 +261,7 @@ async def test_handler(client_class):
|
|
|
261
261
|
client = client_class()
|
|
262
262
|
client.client_reset = mock.AsyncMock()
|
|
263
263
|
client.token_reset = mock.AsyncMock()
|
|
264
|
-
handler =
|
|
264
|
+
handler = cclient.Handler(accepts=[201], refuses=[218], retokens=[418])
|
|
265
265
|
|
|
266
266
|
response = httpx.Response(status_code=201)
|
|
267
267
|
result = await handler(client, response, 0, log)
|
|
@@ -276,7 +276,7 @@ async def test_handler(client_class):
|
|
|
276
276
|
|
|
277
277
|
response = httpx.Response(status_code=200, content='[2]')
|
|
278
278
|
response.request = httpx.Request('POST', '/', json=[1])
|
|
279
|
-
with pytest.raises(
|
|
279
|
+
with pytest.raises(cclient.RetriesExceededError) as exc:
|
|
280
280
|
await handler(client, response, handler.tries + 1, log)
|
|
281
281
|
log.info.assert_called_once_with(
|
|
282
282
|
'retry', status_code=200, tries=0, sleep=.0
|
|
@@ -287,7 +287,7 @@ async def test_handler(client_class):
|
|
|
287
287
|
|
|
288
288
|
response = httpx.Response(status_code=200)
|
|
289
289
|
response.request = httpx.Request('GET', '/')
|
|
290
|
-
with pytest.raises(
|
|
290
|
+
with pytest.raises(cclient.RetriesExceededError) as exc:
|
|
291
291
|
await handler(client, response, handler.tries + 1, log)
|
|
292
292
|
|
|
293
293
|
msg = 'Unacceptable response <Response [200 OK]> after 31 tries\n\x1b[0m\x1b[1mGET /\x1b[0m\n\x1b[1mHTTP 200\x1b[0m' # noqa
|
|
@@ -295,7 +295,7 @@ async def test_handler(client_class):
|
|
|
295
295
|
|
|
296
296
|
response = httpx.Response(status_code=218)
|
|
297
297
|
response.request = httpx.Request('POST', '/')
|
|
298
|
-
with pytest.raises(
|
|
298
|
+
with pytest.raises(cclient.RefusedResponseError) as exc:
|
|
299
299
|
await handler(client, response, 1, log)
|
|
300
300
|
|
|
301
301
|
assert exc.value.response
|
|
@@ -306,7 +306,7 @@ async def test_handler(client_class):
|
|
|
306
306
|
|
|
307
307
|
response = httpx.Response(status_code=418)
|
|
308
308
|
response.request = httpx.Request('POST', '/')
|
|
309
|
-
with pytest.raises(
|
|
309
|
+
with pytest.raises(cclient.TokenGetError):
|
|
310
310
|
await handler(client, response, 1, log)
|
|
311
311
|
|
|
312
312
|
assert not client.client_reset.await_count
|
|
@@ -337,7 +337,7 @@ async def test_handler(client_class):
|
|
|
337
337
|
assert not result
|
|
338
338
|
assert client.token_reset.await_count == 1
|
|
339
339
|
|
|
340
|
-
handler =
|
|
340
|
+
handler = cclient.Handler(accepts=[], refuses=[222])
|
|
341
341
|
|
|
342
342
|
response = httpx.Response(status_code=123)
|
|
343
343
|
result = await handler(client, response, 0, log)
|
|
@@ -476,7 +476,7 @@ async def test_pagination_model(httpx_mock, client_class):
|
|
|
476
476
|
|
|
477
477
|
|
|
478
478
|
def test_paginator_fields(client_class):
|
|
479
|
-
paginator =
|
|
479
|
+
paginator = cclient.Paginator(client_class(), '/')
|
|
480
480
|
paginator.total_items = 95
|
|
481
481
|
paginator.per_page = 10
|
|
482
482
|
assert paginator.total_pages == 10
|
|
@@ -517,7 +517,7 @@ async def test_pagination_patterns(httpx_mock, client_class):
|
|
|
517
517
|
class Offset(client_class.Model):
|
|
518
518
|
url_list = '/off'
|
|
519
519
|
|
|
520
|
-
class Paginator(
|
|
520
|
+
class Paginator(cclient.Paginator):
|
|
521
521
|
def pagination_initialize(self, data):
|
|
522
522
|
self.total_items = data['total']
|
|
523
523
|
|
|
@@ -584,9 +584,9 @@ async def test_pagination_reverse(httpx_mock, client_class):
|
|
|
584
584
|
|
|
585
585
|
def test_descriptor(client_class):
|
|
586
586
|
class Model(client_class.Model):
|
|
587
|
-
id =
|
|
588
|
-
bar =
|
|
589
|
-
foo =
|
|
587
|
+
id = cclient.Field()
|
|
588
|
+
bar = cclient.Field('nested/bar')
|
|
589
|
+
foo = cclient.Field('undeclared/foo')
|
|
590
590
|
|
|
591
591
|
model = Model(data=dict(id=1, nested=dict(bar=2)))
|
|
592
592
|
assert model.data['id'] == 1
|
|
@@ -621,7 +621,7 @@ def test_descriptor(client_class):
|
|
|
621
621
|
|
|
622
622
|
def test_jsonstring(client_class):
|
|
623
623
|
class Model(client_class.Model):
|
|
624
|
-
json =
|
|
624
|
+
json = cclient.JSONStringField()
|
|
625
625
|
|
|
626
626
|
client = client_class()
|
|
627
627
|
model = client.Model(data=dict(json='{"foo": 1}'))
|
|
@@ -641,7 +641,7 @@ def test_jsonstring(client_class):
|
|
|
641
641
|
|
|
642
642
|
def test_datetime(client_class):
|
|
643
643
|
class Model(client_class.Model):
|
|
644
|
-
dt =
|
|
644
|
+
dt = cclient.DateTimeField()
|
|
645
645
|
|
|
646
646
|
model = Model(dict(dt='2020-11-12T01:02:03'))
|
|
647
647
|
assert model.dt == datetime(2020, 11, 12, 1, 2, 3)
|
|
@@ -651,10 +651,10 @@ def test_datetime(client_class):
|
|
|
651
651
|
|
|
652
652
|
def test_model_inheritance(client_class):
|
|
653
653
|
class Model(client_class.Model):
|
|
654
|
-
foo =
|
|
654
|
+
foo = cclient.Field()
|
|
655
655
|
|
|
656
656
|
class Model2(Model):
|
|
657
|
-
bar =
|
|
657
|
+
bar = cclient.Field()
|
|
658
658
|
|
|
659
659
|
client = client_class()
|
|
660
660
|
assert [*client.Model._fields.keys()] == ['foo']
|
|
@@ -663,10 +663,10 @@ def test_model_inheritance(client_class):
|
|
|
663
663
|
|
|
664
664
|
def test_relation_simple(client_class):
|
|
665
665
|
class Child(client_class.Model):
|
|
666
|
-
foo =
|
|
666
|
+
foo = cclient.Field()
|
|
667
667
|
|
|
668
668
|
class Father(client_class.Model):
|
|
669
|
-
child =
|
|
669
|
+
child = cclient.Related('Child')
|
|
670
670
|
|
|
671
671
|
client = client_class()
|
|
672
672
|
model = client.Father(dict(child=dict(foo=1)))
|
|
@@ -685,10 +685,10 @@ def test_relation_simple(client_class):
|
|
|
685
685
|
|
|
686
686
|
def test_relation_many(client_class):
|
|
687
687
|
class Child(client_class.Model):
|
|
688
|
-
foo =
|
|
688
|
+
foo = cclient.Field()
|
|
689
689
|
|
|
690
690
|
class Father(client_class.Model):
|
|
691
|
-
children =
|
|
691
|
+
children = cclient.Related('Child', many=True)
|
|
692
692
|
|
|
693
693
|
client = client_class()
|
|
694
694
|
model = client.Father(dict(children=[dict(foo=1)]))
|
|
@@ -714,8 +714,8 @@ async def test_python_expression(httpx_mock, client_class):
|
|
|
714
714
|
|
|
715
715
|
class Model(client_class.Model):
|
|
716
716
|
url_list = '/foo'
|
|
717
|
-
a =
|
|
718
|
-
b =
|
|
717
|
+
a = cclient.Field()
|
|
718
|
+
b = cclient.Field()
|
|
719
719
|
paginator = Paginator
|
|
720
720
|
|
|
721
721
|
def mock():
|
|
@@ -766,8 +766,8 @@ async def test_python_expression(httpx_mock, client_class):
|
|
|
766
766
|
async def test_expression_parameter(httpx_mock, client_class):
|
|
767
767
|
class Model(client_class.Model):
|
|
768
768
|
url_list = '/foo'
|
|
769
|
-
a =
|
|
770
|
-
b =
|
|
769
|
+
a = cclient.Field()
|
|
770
|
+
b = cclient.Field(parameter='b')
|
|
771
771
|
|
|
772
772
|
httpx_mock.add_response(url='http://lol/foo?b=1', json=dict(
|
|
773
773
|
items=[dict(a=1, b=1), dict(a=3, b=1)],
|
|
@@ -796,7 +796,7 @@ async def test_model_crud(httpx_mock, client_class):
|
|
|
796
796
|
@pytest.mark.asyncio
|
|
797
797
|
async def test_client_cli2(httpx_mock, client_class):
|
|
798
798
|
class Foo(client_class.Model):
|
|
799
|
-
id =
|
|
799
|
+
id = cclient.Field()
|
|
800
800
|
url_list = '/foo'
|
|
801
801
|
|
|
802
802
|
assert client_class.cli.name == 'test'
|
|
@@ -837,14 +837,14 @@ async def test_object_command(httpx_mock, client_class):
|
|
|
837
837
|
))
|
|
838
838
|
def test_datetime_fmts(intern, extern, client_class):
|
|
839
839
|
class DtModel(client_class.Model):
|
|
840
|
-
dt =
|
|
840
|
+
dt = cclient.DateTimeField()
|
|
841
841
|
model = client_class().DtModel(dict(dt=intern))
|
|
842
842
|
assert model.dt == extern
|
|
843
843
|
|
|
844
844
|
|
|
845
845
|
def test_datetime_fmt(client_class):
|
|
846
846
|
class DtModel(client_class.Model):
|
|
847
|
-
dt =
|
|
847
|
+
dt = cclient.DateTimeField(fmt='%d/%m/%Y %H:%M:%S')
|
|
848
848
|
model = client_class().DtModel(dict(dt='13/02/2025 12:34:56'))
|
|
849
849
|
assert model.dt == datetime(2025, 2, 13, 12, 34, 56)
|
|
850
850
|
|
|
@@ -854,15 +854,15 @@ def test_datetime_fmt(client_class):
|
|
|
854
854
|
|
|
855
855
|
def test_datetime_error(client_class):
|
|
856
856
|
class DtModel(client_class.Model):
|
|
857
|
-
dt =
|
|
857
|
+
dt = cclient.DateTimeField()
|
|
858
858
|
model = client_class().DtModel(dict(dt='13/024:56'))
|
|
859
|
-
with pytest.raises(
|
|
859
|
+
with pytest.raises(cclient.FieldExternalizeError):
|
|
860
860
|
model.dt
|
|
861
861
|
|
|
862
862
|
|
|
863
863
|
def test_datetime_default_fmt(client_class):
|
|
864
864
|
class DtModel(client_class.Model):
|
|
865
|
-
dt =
|
|
865
|
+
dt = cclient.DateTimeField()
|
|
866
866
|
model = client_class().DtModel()
|
|
867
867
|
model.dt = datetime(2025, 2, 13, 16, 9, 30)
|
|
868
868
|
assert model.data['dt'] == '2025-02-13T16:09:30.000000'
|
|
@@ -874,11 +874,11 @@ def test_datetime_default_fmt(client_class):
|
|
|
874
874
|
|
|
875
875
|
@pytest.mark.asyncio
|
|
876
876
|
async def test_mask_recursive(client_class, monkeypatch):
|
|
877
|
-
client = client_class(mask=
|
|
877
|
+
client = client_class(mask=cclient.Mask(['scrt', 'password']))
|
|
878
878
|
client.client.send = mock.AsyncMock()
|
|
879
879
|
|
|
880
880
|
log = mock.Mock()
|
|
881
|
-
monkeypatch.setattr(
|
|
881
|
+
monkeypatch.setattr(cclient, 'log', log)
|
|
882
882
|
response = httpx.Response(
|
|
883
883
|
status_code=200,
|
|
884
884
|
content='{"pub": 1, "foo": [{"scrt": "pass"}]}',
|
|
@@ -908,11 +908,11 @@ async def test_mask_recursive(client_class, monkeypatch):
|
|
|
908
908
|
'key', ('json', 'data'),
|
|
909
909
|
)
|
|
910
910
|
async def test_mask_logs(client_class, key, monkeypatch):
|
|
911
|
-
client = client_class(mask=
|
|
911
|
+
client = client_class(mask=cclient.Mask(['scrt', 'password']))
|
|
912
912
|
client.client.send = mock.AsyncMock()
|
|
913
913
|
|
|
914
914
|
log = mock.Mock()
|
|
915
|
-
monkeypatch.setattr(
|
|
915
|
+
monkeypatch.setattr(cclient, 'log', log)
|
|
916
916
|
response = httpx.Response(
|
|
917
917
|
status_code=200,
|
|
918
918
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -948,26 +948,26 @@ async def test_mask_exceptions(client_class):
|
|
|
948
948
|
response.request = httpx.Request('POST', '/', json=dict(a=1, b=2))
|
|
949
949
|
client.mask.keys.add('a')
|
|
950
950
|
client.mask.keys.add('c')
|
|
951
|
-
error =
|
|
951
|
+
error = cclient.ResponseError(client, response, 1)
|
|
952
952
|
expected = "\n\x1b[0m\x1b[1mPOST /\x1b[0m\n\x1b[94ma\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[33m***MASKED***\x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[37m\x1b[39;49;00m\n\x1b[94mb\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m2\x1b[37m\x1b[39;49;00m\n\n\x1b[1mHTTP 218\x1b[0m\n\x1b[94mc\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[33m***MASKED***\x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[37m\x1b[39;49;00m\n\x1b[94md\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m4\x1b[37m\x1b[39;49;00m\n" # noqa
|
|
953
953
|
assert str(error) == expected
|
|
954
954
|
|
|
955
955
|
# this needs to work with form data too
|
|
956
956
|
response = httpx.Response(status_code=218, content='{"c": 3, "d": 4}')
|
|
957
957
|
response.request = httpx.Request('POST', '/', data=dict(a=1, b=2))
|
|
958
|
-
client.mask =
|
|
959
|
-
error =
|
|
958
|
+
client.mask = cclient.Mask(['a', 'c'])
|
|
959
|
+
error = cclient.ResponseError(client, response, 1)
|
|
960
960
|
expected = "\n\x1b[0m\x1b[1mPOST /\x1b[0m\n\x1b[94ma\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[33m***MASKED***\x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[37m\x1b[39;49;00m\n\x1b[94mb\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[33m2\x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[37m\x1b[39;49;00m\n\n\x1b[1mHTTP 218\x1b[0m\n\x1b[94mc\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[33m***MASKED***\x1b[39;49;00m\x1b[33m'\x1b[39;49;00m\x1b[37m\x1b[39;49;00m\n\x1b[94md\x1b[39;49;00m:\x1b[37m \x1b[39;49;00m4\x1b[37m\x1b[39;49;00m\n" # noqa
|
|
961
961
|
assert str(error) == expected
|
|
962
962
|
|
|
963
963
|
|
|
964
964
|
@pytest.mark.asyncio
|
|
965
965
|
async def test_request_mask(client_class, monkeypatch):
|
|
966
|
-
client = client_class(mask=
|
|
966
|
+
client = client_class(mask=cclient.Mask(['password']))
|
|
967
967
|
client.client.send = mock.AsyncMock()
|
|
968
968
|
|
|
969
969
|
log = mock.Mock()
|
|
970
|
-
monkeypatch.setattr(
|
|
970
|
+
monkeypatch.setattr(cclient, 'log', log)
|
|
971
971
|
response = httpx.Response(
|
|
972
972
|
status_code=200,
|
|
973
973
|
content='{"pub": 1, "scrt": "pass"}',
|
|
@@ -998,7 +998,7 @@ async def test_log_content(client_class, monkeypatch):
|
|
|
998
998
|
client = client_class()
|
|
999
999
|
client.client.send = mock.AsyncMock()
|
|
1000
1000
|
log = mock.Mock()
|
|
1001
|
-
monkeypatch.setattr(
|
|
1001
|
+
monkeypatch.setattr(cclient, 'log', log)
|
|
1002
1002
|
response = httpx.Response(status_code=200, content='lol:]bar')
|
|
1003
1003
|
response.request = httpx.Request('POST', '/')
|
|
1004
1004
|
client.client.send.return_value = response
|
|
@@ -1019,7 +1019,7 @@ async def test_log_quiet(client_class, monkeypatch):
|
|
|
1019
1019
|
client = client_class()
|
|
1020
1020
|
client.client.send = mock.AsyncMock()
|
|
1021
1021
|
log = mock.Mock()
|
|
1022
|
-
monkeypatch.setattr(
|
|
1022
|
+
monkeypatch.setattr(cclient, 'log', log)
|
|
1023
1023
|
response = httpx.Response(status_code=200, content='[1]')
|
|
1024
1024
|
response.request = httpx.Request('GET', '/')
|
|
1025
1025
|
client.client.send.return_value = response
|
|
@@ -1047,8 +1047,8 @@ def test_class_override(client_class):
|
|
|
1047
1047
|
@pytest.mark.asyncio
|
|
1048
1048
|
async def test_save(client_class, httpx_mock):
|
|
1049
1049
|
class TestModel(client_class.Model):
|
|
1050
|
-
id =
|
|
1051
|
-
foo =
|
|
1050
|
+
id = cclient.Field()
|
|
1051
|
+
foo = cclient.Field()
|
|
1052
1052
|
|
|
1053
1053
|
client = client_class()
|
|
1054
1054
|
model = client.TestModel(id=1, foo='bar')
|
|
@@ -1081,22 +1081,22 @@ async def test_save(client_class, httpx_mock):
|
|
|
1081
1081
|
|
|
1082
1082
|
def test_id_value(client_class):
|
|
1083
1083
|
class TestModel(client_class.Model):
|
|
1084
|
-
id =
|
|
1084
|
+
id = cclient.Field()
|
|
1085
1085
|
assert client_class().TestModel(id=1).id_value == 1
|
|
1086
1086
|
|
|
1087
1087
|
class TestModel2(client_class.Model):
|
|
1088
|
-
bar =
|
|
1088
|
+
bar = cclient.Field()
|
|
1089
1089
|
id_field = 'bar'
|
|
1090
1090
|
assert client_class().TestModel2(bar=1).id_value == 1
|
|
1091
1091
|
|
|
1092
1092
|
|
|
1093
1093
|
@pytest.mark.asyncio
|
|
1094
1094
|
async def test_debug(client_class, monkeypatch):
|
|
1095
|
-
client = client_class(mask=
|
|
1095
|
+
client = client_class(mask=cclient.Mask(['scrt', 'password']), debug=True)
|
|
1096
1096
|
client.client.send = mock.AsyncMock()
|
|
1097
1097
|
|
|
1098
1098
|
log = mock.Mock()
|
|
1099
|
-
monkeypatch.setattr(
|
|
1099
|
+
monkeypatch.setattr(cclient, 'log', log)
|
|
1100
1100
|
|
|
1101
1101
|
response = httpx.Response(
|
|
1102
1102
|
status_code=200,
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# flake8: noqa
|
|
2
|
-
"""
|
|
3
|
-
Wrapping all imports in a try/except because pytest always tries to import
|
|
4
|
-
this even when we're using cli2 without ansible
|
|
5
|
-
"""
|
|
6
|
-
try:
|
|
7
|
-
from .action import (
|
|
8
|
-
ansi_escape,
|
|
9
|
-
Option,
|
|
10
|
-
AnsibleError,
|
|
11
|
-
AnsibleOptionError,
|
|
12
|
-
ActionBase,
|
|
13
|
-
)
|
|
14
|
-
from .variables import Variables
|
|
15
|
-
except ImportError:
|
|
16
|
-
pass
|