cli2 5.0.3__tar.gz → 5.1.0rc1__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-5.0.3/cli2.egg-info → cli2-5.1.0rc1}/PKG-INFO +1 -1
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/log.py +36 -13
- {cli2-5.0.3 → cli2-5.1.0rc1/cli2.egg-info}/PKG-INFO +1 -1
- {cli2-5.0.3 → cli2-5.1.0rc1}/setup.py +1 -1
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_client.py +54 -2
- {cli2-5.0.3 → cli2-5.1.0rc1}/MANIFEST.in +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/README.rst +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/classifiers.txt +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/__init__.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/asyncio.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/cli.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/cli2.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/colors.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/configuration.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/decorators.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/display.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/__init__.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/conf.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/example.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/example_obj.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/nesting.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/obj.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/obj2.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/test.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/lock.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/mask.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/node.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/sphinx.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/table.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/test.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/SOURCES.txt +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/dependency_links.txt +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/entry_points.txt +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/requires.txt +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/top_level.txt +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/setup.cfg +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_ansible.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_ansible_variables.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_asyncio.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_cli.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_command.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_configuration.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_decorators.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_display.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_entry_point.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_group.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_inject.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_lock.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_mask.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_node.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_restful.py +0 -0
- {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_table.py +0 -0
|
@@ -37,6 +37,16 @@ variables.
|
|
|
37
37
|
|
|
38
38
|
Setting this to ``INFO``, ``DEBUG``, or any other log level is safe.
|
|
39
39
|
|
|
40
|
+
.. envvar:: LOG_FILE
|
|
41
|
+
|
|
42
|
+
Path to log file to use, with a couple of special values:
|
|
43
|
+
|
|
44
|
+
- if ``LOG_FILE=auto``, then a path will be calculated in
|
|
45
|
+
``~/.local/cli2/log``,
|
|
46
|
+
- if ``LOG_FILE=none``, then there will be no file logging.
|
|
47
|
+
|
|
48
|
+
Default: ``auto``
|
|
49
|
+
|
|
40
50
|
.. envvar:: DEBUG
|
|
41
51
|
|
|
42
52
|
Setting this will set :envvar:`LOG_LEVEL` to `DEBUG`, but also activate
|
|
@@ -72,6 +82,7 @@ class YAMLFormatter:
|
|
|
72
82
|
|
|
73
83
|
def configure():
|
|
74
84
|
LOG_LEVEL = os.getenv('LOG_LEVEL', 'WARNING').upper()
|
|
85
|
+
LOG_FILE = os.getenv('LOG_FILE', 'auto').upper()
|
|
75
86
|
|
|
76
87
|
if os.getenv('DEBUG'):
|
|
77
88
|
LOG_LEVEL = 'DEBUG'
|
|
@@ -92,11 +103,21 @@ def configure():
|
|
|
92
103
|
for arg in sys.argv
|
|
93
104
|
])[:155]
|
|
94
105
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
106
|
+
if LOG_FILE == 'auto':
|
|
107
|
+
log_dir = Path(os.getenv("HOME")) / '.local/cli2/log'
|
|
108
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
109
|
+
ts = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
|
|
110
|
+
file_name = f'{sys.argv[0].split("/")[-1]}-{ts}-{cmd}.log'
|
|
111
|
+
LOG_FILE = log_dir / file_name
|
|
112
|
+
elif LOG_FILE == 'none' or not LOG_FILE:
|
|
113
|
+
LOG_FILE = None
|
|
114
|
+
else:
|
|
115
|
+
LOG_FILE = Path(LOG_FILE)
|
|
116
|
+
|
|
117
|
+
handlers = ['default']
|
|
118
|
+
if LOG_FILE:
|
|
119
|
+
handlers.append('file')
|
|
120
|
+
|
|
100
121
|
LOGGING = {
|
|
101
122
|
'version': 1,
|
|
102
123
|
'disable_existing_loggers': True,
|
|
@@ -156,16 +177,10 @@ def configure():
|
|
|
156
177
|
'class': 'logging.StreamHandler',
|
|
157
178
|
'formatter': 'colored',
|
|
158
179
|
},
|
|
159
|
-
'file': {
|
|
160
|
-
'level': 'DEBUG',
|
|
161
|
-
'class': 'logging.handlers.WatchedFileHandler',
|
|
162
|
-
'formatter': 'plain',
|
|
163
|
-
'filename': str(file_path),
|
|
164
|
-
},
|
|
165
180
|
},
|
|
166
181
|
'loggers': {
|
|
167
182
|
'cli2': {
|
|
168
|
-
'handlers':
|
|
183
|
+
'handlers': handlers,
|
|
169
184
|
'level': 'DEBUG',
|
|
170
185
|
'propagate': True,
|
|
171
186
|
}
|
|
@@ -175,12 +190,20 @@ def configure():
|
|
|
175
190
|
if os.getenv('HTTP_DEBUG'):
|
|
176
191
|
LOGGING['loggers'].update({
|
|
177
192
|
key: {
|
|
178
|
-
'handlers':
|
|
193
|
+
'handlers': handlers,
|
|
179
194
|
'level': 'DEBUG',
|
|
180
195
|
'propagate': True,
|
|
181
196
|
} for key in ('httpx', 'httpcore')
|
|
182
197
|
})
|
|
183
198
|
|
|
199
|
+
if LOG_FILE:
|
|
200
|
+
LOGGING['handlers']['file'] = {
|
|
201
|
+
'level': 'DEBUG',
|
|
202
|
+
'class': 'logging.handlers.WatchedFileHandler',
|
|
203
|
+
'formatter': 'plain',
|
|
204
|
+
'filename': str(LOG_FILE),
|
|
205
|
+
}
|
|
206
|
+
|
|
184
207
|
logging.config.dictConfig(LOGGING)
|
|
185
208
|
|
|
186
209
|
structlog.configure(
|
|
@@ -645,10 +645,11 @@ def test_descriptor(client_class):
|
|
|
645
645
|
assert model.data['undeclared']['foo'] == 3
|
|
646
646
|
|
|
647
647
|
model = Model()
|
|
648
|
-
assert model.foo
|
|
648
|
+
assert model.foo is None
|
|
649
|
+
assert 'foo' not in model._data
|
|
649
650
|
assert not model.changed_fields
|
|
650
651
|
model.foo = 'bar'
|
|
651
|
-
assert model.changed_fields == dict(foo=
|
|
652
|
+
assert model.changed_fields == dict(foo=None)
|
|
652
653
|
model = Model(foo='bar')
|
|
653
654
|
model.foo = 'foo'
|
|
654
655
|
assert model.changed_fields == dict(foo='bar')
|
|
@@ -1246,3 +1247,54 @@ def test_client_command(client_class, httpx_mock):
|
|
|
1246
1247
|
cmd = Client.cli['request']
|
|
1247
1248
|
cmd()
|
|
1248
1249
|
assert not Client.post_call_called
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
def test_field_callback(client_class):
|
|
1253
|
+
class TestModel(client_class.Model):
|
|
1254
|
+
foo = chttpx.Field()
|
|
1255
|
+
bar = chttpx.Field()
|
|
1256
|
+
other = chttpx.Field()
|
|
1257
|
+
|
|
1258
|
+
@other.factory
|
|
1259
|
+
def other_factory(self):
|
|
1260
|
+
return 'nice'
|
|
1261
|
+
|
|
1262
|
+
@bar.factory(foo)
|
|
1263
|
+
def bar_factory(self):
|
|
1264
|
+
return f'bar{self.foo}'
|
|
1265
|
+
|
|
1266
|
+
model = client_class().TestModel(foo='test')
|
|
1267
|
+
assert model.bar == 'bartest'
|
|
1268
|
+
assert model.other == 'nice'
|
|
1269
|
+
|
|
1270
|
+
model = client_class().TestModel(foo='test')
|
|
1271
|
+
assert model.data['bar'] == 'bartest'
|
|
1272
|
+
assert model.data['other'] == 'nice'
|
|
1273
|
+
|
|
1274
|
+
model = client_class().TestModel()
|
|
1275
|
+
assert model.data == dict(other='nice')
|
|
1276
|
+
|
|
1277
|
+
model = client_class().TestModel(bar='lol')
|
|
1278
|
+
assert model.bar == 'lol'
|
|
1279
|
+
assert model.data['bar'] == 'lol'
|
|
1280
|
+
|
|
1281
|
+
|
|
1282
|
+
def test_field_callback_recursion(client_class):
|
|
1283
|
+
class TestModel(client_class.Model):
|
|
1284
|
+
final = chttpx.Field()
|
|
1285
|
+
req2 = chttpx.Field()
|
|
1286
|
+
req1 = chttpx.Field()
|
|
1287
|
+
|
|
1288
|
+
@final.factory(req2)
|
|
1289
|
+
def final_factory(self):
|
|
1290
|
+
return f'{self.req2}val3'
|
|
1291
|
+
|
|
1292
|
+
@req2.factory(req1)
|
|
1293
|
+
def req2_factory(self):
|
|
1294
|
+
return f'{self.req1}val2'
|
|
1295
|
+
|
|
1296
|
+
model = client_class().TestModel(req1='lol')
|
|
1297
|
+
assert model.data['final'] == 'lolval2val3'
|
|
1298
|
+
|
|
1299
|
+
model = client_class().TestModel(req1='lol')
|
|
1300
|
+
assert model.final == 'lolval2val3'
|
|
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
|