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.
Files changed (52) hide show
  1. {cli2-5.0.3/cli2.egg-info → cli2-5.1.0rc1}/PKG-INFO +1 -1
  2. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/log.py +36 -13
  3. {cli2-5.0.3 → cli2-5.1.0rc1/cli2.egg-info}/PKG-INFO +1 -1
  4. {cli2-5.0.3 → cli2-5.1.0rc1}/setup.py +1 -1
  5. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_client.py +54 -2
  6. {cli2-5.0.3 → cli2-5.1.0rc1}/MANIFEST.in +0 -0
  7. {cli2-5.0.3 → cli2-5.1.0rc1}/README.rst +0 -0
  8. {cli2-5.0.3 → cli2-5.1.0rc1}/classifiers.txt +0 -0
  9. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/__init__.py +0 -0
  10. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/asyncio.py +0 -0
  11. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/cli.py +0 -0
  12. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/cli2.py +0 -0
  13. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/colors.py +0 -0
  14. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/configuration.py +0 -0
  15. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/decorators.py +0 -0
  16. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/display.py +0 -0
  17. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/__init__.py +0 -0
  18. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/conf.py +0 -0
  19. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/example.py +0 -0
  20. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/example_obj.py +0 -0
  21. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/nesting.py +0 -0
  22. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/obj.py +0 -0
  23. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/obj2.py +0 -0
  24. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/examples/test.py +0 -0
  25. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/lock.py +0 -0
  26. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/mask.py +0 -0
  27. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/node.py +0 -0
  28. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/sphinx.py +0 -0
  29. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/table.py +0 -0
  30. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2/test.py +0 -0
  31. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/SOURCES.txt +0 -0
  32. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/dependency_links.txt +0 -0
  33. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/entry_points.txt +0 -0
  34. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/requires.txt +0 -0
  35. {cli2-5.0.3 → cli2-5.1.0rc1}/cli2.egg-info/top_level.txt +0 -0
  36. {cli2-5.0.3 → cli2-5.1.0rc1}/setup.cfg +0 -0
  37. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_ansible.py +0 -0
  38. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_ansible_variables.py +0 -0
  39. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_asyncio.py +0 -0
  40. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_cli.py +0 -0
  41. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_command.py +0 -0
  42. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_configuration.py +0 -0
  43. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_decorators.py +0 -0
  44. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_display.py +0 -0
  45. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_entry_point.py +0 -0
  46. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_group.py +0 -0
  47. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_inject.py +0 -0
  48. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_lock.py +0 -0
  49. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_mask.py +0 -0
  50. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_node.py +0 -0
  51. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_restful.py +0 -0
  52. {cli2-5.0.3 → cli2-5.1.0rc1}/tests/test_table.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cli2
3
- Version: 5.0.3
3
+ Version: 5.1.0rc1
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
@@ -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
- log_dir = Path(os.getenv("HOME")) / '.local/cli2/log'
96
- log_dir.mkdir(parents=True, exist_ok=True)
97
- ts = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
98
- file_name = f'{sys.argv[0].split("/")[-1]}-{ts}-{cmd}.log'
99
- file_path = log_dir / file_name
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': ['default', 'file'],
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': ['default', 'file'],
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(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: cli2
3
- Version: 5.0.3
3
+ Version: 5.1.0rc1
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
@@ -44,7 +44,7 @@ from setuptools import setup
44
44
 
45
45
  setup(
46
46
  name='cli2',
47
- version='5.0.3',
47
+ version='5.1.0rc1',
48
48
  setup_requires='setupmeta',
49
49
  packages=['cli2'],
50
50
  install_requires=[
@@ -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