nuclear 2.1.2__tar.gz → 2.2.2__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 (69) hide show
  1. {nuclear-2.1.2 → nuclear-2.2.2}/PKG-INFO +17 -8
  2. {nuclear-2.1.2 → nuclear-2.2.2}/README.md +16 -7
  3. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/inspection/inspection.py +8 -7
  4. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/sublog/context_error.py +1 -1
  5. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/sublog/exception.py +1 -1
  6. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/sublog/logging.py +1 -1
  7. nuclear-2.2.2/nuclear/utils/collections.py +44 -0
  8. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/config.py +6 -11
  9. nuclear-2.2.2/nuclear/utils/datamodel.py +45 -0
  10. nuclear-2.2.2/nuclear/version.py +1 -0
  11. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear.egg-info/PKG-INFO +17 -8
  12. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear.egg-info/requires.txt +1 -1
  13. nuclear-2.1.2/nuclear/utils/collections.py +0 -4
  14. nuclear-2.1.2/nuclear/utils/datamodel.py +0 -112
  15. nuclear-2.1.2/nuclear/version.py +0 -1
  16. {nuclear-2.1.2 → nuclear-2.2.2}/LICENSE +0 -0
  17. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/__init__.py +0 -0
  18. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/__init__.py +0 -0
  19. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/args/__init__.py +0 -0
  20. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/args/args_que.py +0 -0
  21. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/args/container.py +0 -0
  22. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/autocomplete/__init__.py +0 -0
  23. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/autocomplete/autocomplete.py +0 -0
  24. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/autocomplete/install.py +0 -0
  25. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/builder/__init__.py +0 -0
  26. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/builder/builder.py +0 -0
  27. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/builder/decorator_builder.py +0 -0
  28. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/builder/rule.py +0 -0
  29. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/builder/rule_factory.py +0 -0
  30. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/builder/typedef.py +0 -0
  31. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/completers/__init__.py +0 -0
  32. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/completers/file.py +0 -0
  33. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/help.py +0 -0
  34. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/__init__.py +0 -0
  35. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/context.py +0 -0
  36. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/error.py +0 -0
  37. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/inject.py +0 -0
  38. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/internal_vars.py +0 -0
  39. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/keyword.py +0 -0
  40. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/matcher.py +0 -0
  41. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/parser.py +0 -0
  42. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/transform.py +0 -0
  43. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/validate.py +0 -0
  44. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/parser/value.py +0 -0
  45. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/types/__init__.py +0 -0
  46. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/types/boolean.py +0 -0
  47. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/types/filesystem.py +0 -0
  48. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/cli/types/time.py +0 -0
  49. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/inspection/__init__.py +0 -0
  50. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/py.typed +0 -0
  51. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/shell/__init__.py +0 -0
  52. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/shell/background_cmd.py +0 -0
  53. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/shell/shell_utils.py +0 -0
  54. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/sublog/__init__.py +0 -0
  55. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/sublog/catch.py +0 -0
  56. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/__init__.py +0 -0
  57. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/env.py +0 -0
  58. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/files.py +0 -0
  59. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/functools.py +0 -0
  60. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/input.py +0 -0
  61. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/regex.py +0 -0
  62. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/strings.py +0 -0
  63. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/time.py +0 -0
  64. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear/utils/url.py +0 -0
  65. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear.egg-info/SOURCES.txt +0 -0
  66. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear.egg-info/dependency_links.txt +0 -0
  67. {nuclear-2.1.2 → nuclear-2.2.2}/nuclear.egg-info/top_level.txt +0 -0
  68. {nuclear-2.1.2 → nuclear-2.2.2}/setup.cfg +0 -0
  69. {nuclear-2.1.2 → nuclear-2.2.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nuclear
3
- Version: 2.1.2
3
+ Version: 2.2.2
4
4
  Summary: Declarative parser for command line interfaces
5
5
  Home-page: https://github.com/igrek51/nuclear
6
6
  Author: igrek51
@@ -115,7 +115,7 @@ you don't even need to install **nuclear** package to use `wat` inspector.
115
115
  Load it on the fly by pasting this snippet to your Python interpreter:
116
116
  ```python
117
117
  import base64, zlib
118
- code = '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'
118
+ code = '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'
119
119
  exec(zlib.decompress(base64.b64decode(code.encode())).decode(), globals())
120
120
  ```
121
121
 
@@ -136,13 +136,13 @@ with the following **modifiers**:
136
136
  - `.nodocs` to hide documentation for functions and classes
137
137
  - `.all` to include all available information
138
138
 
139
- You can chain modifiers, e.g. `wat.long.dunder / object`.
139
+ You can chain modifiers, e.g. `wat.long.dunder.nodocs / object`.
140
140
 
141
141
  Call `wat()` to inspect `locals()` variables.
142
142
 
143
143
  Type `wat` in the interpreter to learn more about this object itself.
144
144
 
145
- ## Use cases
145
+ ## Use Cases Examples
146
146
 
147
147
  ### Determine type
148
148
  In a dynamic typing language like Python, it's often hard to determine the type of an object. WAT Inspector can help you with that by showing the name of the type with the module it comes from.
@@ -162,12 +162,14 @@ type: django.contrib.auth.models.User
162
162
  parents: django.contrib.auth.models.AbstractUser, django.contrib.auth.base_user.AbstractBaseUser, django.contrib.auth.models.PermissionsMixin, django.db.models.base.Model, django.db.models.utils.AltersData
163
163
  ```
164
164
 
165
+ Now that you've identified the actual type, you can put the type annotations in your code to reduce the confusion.
166
+
165
167
  ### Look up methods
166
168
  Listing methods, functions and looking up their signature is extremely beneficial to see how to use them.
167
169
  Plus, you can read their docstrings.
168
170
 
169
171
  ```python
170
- wat('stringy')
172
+ wat / 'stringy'
171
173
  ```
172
174
 
173
175
  ![](https://github.com/igrek51/nuclear/blob/master/docs/img/wat-string.png?raw=true)
@@ -176,13 +178,13 @@ wat('stringy')
176
178
  See the docstrings and the signature of a function or a method to see how to use it.
177
179
 
178
180
  ```python
179
- wat(str.split)
181
+ wat / str.split
180
182
  ```
181
183
 
182
184
  ![](https://github.com/igrek51/nuclear/blob/master/docs/img/wat-str-split.png?raw=true)
183
185
 
184
- ### Look up variables
185
- Check what's inside, list the value of variables and their types to see what's really inside the inspected object.
186
+ ### Look up attributes
187
+ List the attribues and their types to see what's really inside the inspected object.
186
188
  ```python
187
189
  wat / re.match('(\d)_(.*)', '1_title')
188
190
  ```
@@ -244,6 +246,13 @@ wat / __builtins__
244
246
  ### Look up local variables
245
247
  ```python
246
248
  wat()
249
+ # or
250
+ wat.locals
251
+ ```
252
+
253
+ ### Look up global variables
254
+ ```python
255
+ wat.globals
247
256
  ```
248
257
 
249
258
 
@@ -100,7 +100,7 @@ you don't even need to install **nuclear** package to use `wat` inspector.
100
100
  Load it on the fly by pasting this snippet to your Python interpreter:
101
101
  ```python
102
102
  import base64, zlib
103
- code = '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'
103
+ code = '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'
104
104
  exec(zlib.decompress(base64.b64decode(code.encode())).decode(), globals())
105
105
  ```
106
106
 
@@ -121,13 +121,13 @@ with the following **modifiers**:
121
121
  - `.nodocs` to hide documentation for functions and classes
122
122
  - `.all` to include all available information
123
123
 
124
- You can chain modifiers, e.g. `wat.long.dunder / object`.
124
+ You can chain modifiers, e.g. `wat.long.dunder.nodocs / object`.
125
125
 
126
126
  Call `wat()` to inspect `locals()` variables.
127
127
 
128
128
  Type `wat` in the interpreter to learn more about this object itself.
129
129
 
130
- ## Use cases
130
+ ## Use Cases Examples
131
131
 
132
132
  ### Determine type
133
133
  In a dynamic typing language like Python, it's often hard to determine the type of an object. WAT Inspector can help you with that by showing the name of the type with the module it comes from.
@@ -147,12 +147,14 @@ type: django.contrib.auth.models.User
147
147
  parents: django.contrib.auth.models.AbstractUser, django.contrib.auth.base_user.AbstractBaseUser, django.contrib.auth.models.PermissionsMixin, django.db.models.base.Model, django.db.models.utils.AltersData
148
148
  ```
149
149
 
150
+ Now that you've identified the actual type, you can put the type annotations in your code to reduce the confusion.
151
+
150
152
  ### Look up methods
151
153
  Listing methods, functions and looking up their signature is extremely beneficial to see how to use them.
152
154
  Plus, you can read their docstrings.
153
155
 
154
156
  ```python
155
- wat('stringy')
157
+ wat / 'stringy'
156
158
  ```
157
159
 
158
160
  ![](https://github.com/igrek51/nuclear/blob/master/docs/img/wat-string.png?raw=true)
@@ -161,13 +163,13 @@ wat('stringy')
161
163
  See the docstrings and the signature of a function or a method to see how to use it.
162
164
 
163
165
  ```python
164
- wat(str.split)
166
+ wat / str.split
165
167
  ```
166
168
 
167
169
  ![](https://github.com/igrek51/nuclear/blob/master/docs/img/wat-str-split.png?raw=true)
168
170
 
169
- ### Look up variables
170
- Check what's inside, list the value of variables and their types to see what's really inside the inspected object.
171
+ ### Look up attributes
172
+ List the attribues and their types to see what's really inside the inspected object.
171
173
  ```python
172
174
  wat / re.match('(\d)_(.*)', '1_title')
173
175
  ```
@@ -229,6 +231,13 @@ wat / __builtins__
229
231
  ### Look up local variables
230
232
  ```python
231
233
  wat()
234
+ # or
235
+ wat.locals
236
+ ```
237
+
238
+ ### Look up global variables
239
+ ```python
240
+ wat.globals
232
241
  ```
233
242
 
234
243
 
@@ -141,7 +141,7 @@ def _iter_attributes(obj: Any, config: InspectConfig) -> Iterable[InspectAttribu
141
141
  def _get_attribute_value(obj: Any, key: str) -> Any:
142
142
  try:
143
143
  return getattr(obj, key)
144
- except AttributeError as e:
144
+ except BaseException as e:
145
145
  return e
146
146
 
147
147
 
@@ -171,8 +171,8 @@ def _get_callable_signature(name: str, obj: Any) -> Optional[str]:
171
171
  def _get_source_code(obj: Any) -> Optional[str]:
172
172
  try:
173
173
  return std_inspect.getsource(obj)
174
- except (OSError, TypeError, IndentationError):
175
- return None
174
+ except (OSError, TypeError, IndentationError) as e:
175
+ return f'failed to get source code: {type(e)}: {e}'
176
176
 
177
177
 
178
178
  def _get_doc(obj: Any, long: bool) -> Optional[str]:
@@ -244,9 +244,9 @@ def _format_dict_value(dic: Dict, indent: int) -> str:
244
244
  return f'{STYLE_YELLOW}{{}}{RESET}'
245
245
 
246
246
 
247
- def _format_list_value(l: List, indent: int) -> str:
247
+ def _format_list_value(lst: List, indent: int) -> str:
248
248
  lines: List[str] = []
249
- for value in l:
249
+ for value in lst:
250
250
  value_str = _format_value(value, indent)
251
251
  lines.append(' ' * indent + f'{value_str},')
252
252
  if lines:
@@ -362,8 +362,9 @@ Call {STYLE_YELLOW}wat(){RESET} to inspect {STYLE_YELLOW}locals(){RESET} variabl
362
362
 
363
363
  def __call__(self, *args: Any, **kwargs: Any) -> Union['Wat', None]:
364
364
  if args:
365
- self._params.update(kwargs)
366
- return inspect(*args, **self._params)
365
+ new_params = self._params.copy()
366
+ new_params.update(kwargs)
367
+ return inspect(*args, **new_params)
367
368
  elif kwargs:
368
369
  return Wat(**kwargs)
369
370
  else:
@@ -22,7 +22,7 @@ class ContextError(RuntimeError):
22
22
  self.__cause__ = cause
23
23
 
24
24
  def __str__(self) -> str:
25
- e: Exception = self
25
+ e: Optional[BaseException] = self
26
26
  layers = []
27
27
  while e is not None:
28
28
  if isinstance(e, ContextError):
@@ -17,7 +17,7 @@ def exception_details(e: BaseException) -> str:
17
17
  traceback_str = ', '.join(traceback_lines)
18
18
  cause = _root_cause_type(e)
19
19
  error_msg = _error_message(e)
20
- return f'{error_msg}: cause={cause}, traceback={traceback_str}'
20
+ return f'{error_msg}, cause={cause}, traceback={traceback_str}'
21
21
 
22
22
 
23
23
  def extended_exception_details(e: BaseException) -> Tuple[str, Dict]:
@@ -101,7 +101,7 @@ class ContextLogger:
101
101
  if display_context:
102
102
  if message.endswith(':'):
103
103
  message = message[:-1]
104
- logger_func(f'{message}: {display_context}')
104
+ logger_func(f'{message}, {display_context}')
105
105
  else:
106
106
  logger_func(message)
107
107
 
@@ -0,0 +1,44 @@
1
+ from typing import Any, Callable, Iterable, TypeVar, List, Union
2
+
3
+ T = TypeVar('T')
4
+
5
+
6
+ def chunks(lst: List[T], n: int) -> Iterable[List[T]]:
7
+ """Yield successive n-sized chunks from lst."""
8
+ for i in range(0, len(lst), n):
9
+ yield lst[i:i + n]
10
+
11
+
12
+ def deduplicate_latest(items: List[T], key: Callable[[T], Any]) -> List[T]:
13
+ """Deduplicate items in the list by key. Keep the earliest items first, remove the latest duplicates"""
14
+ ids = set()
15
+ dedup_items: List[T] = []
16
+ for item in items:
17
+ ikey = key(item)
18
+ if ikey not in ids:
19
+ ids.add(ikey)
20
+ dedup_items.append(item)
21
+ return dedup_items
22
+
23
+
24
+ def deduplicate_earliest(items: List[T], key: Callable[[T], Any]) -> List[T]:
25
+ """Deduplicate items in the list by key. Keep the latest items, remove the earliest duplicates"""
26
+ ids = set()
27
+ dedup_items: List[T] = []
28
+ for item in reversed(items):
29
+ ikey = key(item)
30
+ if ikey not in ids:
31
+ ids.add(ikey)
32
+ dedup_items.append(item)
33
+ return dedup_items[::-1]
34
+
35
+
36
+ def flatten(collection: Iterable[Union[T, List[T]]]) -> List[T]:
37
+ """Transform a list of lists into a flat list"""
38
+ flat: List[T] = []
39
+ for item in collection:
40
+ if isinstance(item, list):
41
+ flat.extend(flatten(item))
42
+ else:
43
+ flat.append(item)
44
+ return flat
@@ -1,25 +1,21 @@
1
1
  import os
2
2
  from pathlib import Path
3
- from typing import Type, TypeVar
3
+ from typing import Dict
4
4
 
5
- from pydantic import BaseModel
6
5
  import yaml
7
6
 
8
7
  from nuclear import logger
9
8
 
10
- T = TypeVar("T", bound=BaseModel)
11
9
 
12
-
13
- def load_config(clazz: Type[T]) -> T:
10
+ def load_config() -> Dict:
14
11
  """
15
12
  Load general configuration from YAML file given in CONFIG_FILE environment var or load default config.
16
- :param clazz: pydantic.BaseModel type that should be loaded
17
- :return: configuration object of given "clazz" type
13
+ :return: loaded configuration dictionary object
18
14
  """
19
15
  config_file_path = os.environ.get('CONFIG_FILE')
20
16
  if not config_file_path:
21
17
  logger.warning('CONFIG_FILE unspecified, loading default config')
22
- return clazz()
18
+ return {}
23
19
 
24
20
  path = Path(config_file_path)
25
21
  if not path.is_file():
@@ -28,9 +24,8 @@ def load_config(clazz: Type[T]) -> T:
28
24
  try:
29
25
  with path.open() as file:
30
26
  config_dict = yaml.load(file, Loader=yaml.FullLoader)
31
- config = clazz.model_validate(config_dict)
32
27
 
33
- logger.info(f'config loaded from {config_file_path}: {config}')
34
- return config
28
+ logger.info(f'config loaded from {config_file_path}: {config_dict}')
29
+ return config_dict
35
30
  except Exception as e:
36
31
  raise RuntimeError('loading config failed') from e
@@ -0,0 +1,45 @@
1
+ import dataclasses
2
+ from datetime import date, datetime
3
+ import json
4
+ from pathlib import PosixPath
5
+
6
+ import yaml
7
+
8
+
9
+ def to_json(obj) -> str:
10
+ obj = to_json_serializable(obj)
11
+ obj = remove_none(obj)
12
+ return json.dumps(obj)
13
+
14
+
15
+ def to_yaml(obj) -> str:
16
+ obj = to_json_serializable(obj)
17
+ obj = remove_none(obj)
18
+ return yaml.dump(obj, sort_keys=False)
19
+
20
+
21
+ def remove_none(obj):
22
+ """Remove unwanted null values"""
23
+ if isinstance(obj, list):
24
+ return [remove_none(x) for x in obj if x is not None]
25
+ elif isinstance(obj, dict):
26
+ return {k: remove_none(v) for k, v in obj.items() if k is not None and v is not None}
27
+ else:
28
+ return obj
29
+
30
+
31
+ def to_json_serializable(obj):
32
+ if dataclasses.is_dataclass(obj):
33
+ return to_json_serializable(dataclasses.asdict(obj))
34
+ elif isinstance(obj, PosixPath):
35
+ return str(obj)
36
+ elif isinstance(obj, (date, datetime)):
37
+ return obj.isoformat()
38
+ elif isinstance(obj, list):
39
+ return [to_json_serializable(x) for x in obj]
40
+ elif isinstance(obj, dict):
41
+ return {k: to_json_serializable(v) for k, v in obj.items()}
42
+ elif hasattr(obj, '__to_json__'):
43
+ return getattr(obj, '__to_json__')()
44
+ else:
45
+ return obj
@@ -0,0 +1 @@
1
+ __version__ = "2.2.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nuclear
3
- Version: 2.1.2
3
+ Version: 2.2.2
4
4
  Summary: Declarative parser for command line interfaces
5
5
  Home-page: https://github.com/igrek51/nuclear
6
6
  Author: igrek51
@@ -115,7 +115,7 @@ you don't even need to install **nuclear** package to use `wat` inspector.
115
115
  Load it on the fly by pasting this snippet to your Python interpreter:
116
116
  ```python
117
117
  import base64, zlib
118
- code = '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'
118
+ code = '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'
119
119
  exec(zlib.decompress(base64.b64decode(code.encode())).decode(), globals())
120
120
  ```
121
121
 
@@ -136,13 +136,13 @@ with the following **modifiers**:
136
136
  - `.nodocs` to hide documentation for functions and classes
137
137
  - `.all` to include all available information
138
138
 
139
- You can chain modifiers, e.g. `wat.long.dunder / object`.
139
+ You can chain modifiers, e.g. `wat.long.dunder.nodocs / object`.
140
140
 
141
141
  Call `wat()` to inspect `locals()` variables.
142
142
 
143
143
  Type `wat` in the interpreter to learn more about this object itself.
144
144
 
145
- ## Use cases
145
+ ## Use Cases Examples
146
146
 
147
147
  ### Determine type
148
148
  In a dynamic typing language like Python, it's often hard to determine the type of an object. WAT Inspector can help you with that by showing the name of the type with the module it comes from.
@@ -162,12 +162,14 @@ type: django.contrib.auth.models.User
162
162
  parents: django.contrib.auth.models.AbstractUser, django.contrib.auth.base_user.AbstractBaseUser, django.contrib.auth.models.PermissionsMixin, django.db.models.base.Model, django.db.models.utils.AltersData
163
163
  ```
164
164
 
165
+ Now that you've identified the actual type, you can put the type annotations in your code to reduce the confusion.
166
+
165
167
  ### Look up methods
166
168
  Listing methods, functions and looking up their signature is extremely beneficial to see how to use them.
167
169
  Plus, you can read their docstrings.
168
170
 
169
171
  ```python
170
- wat('stringy')
172
+ wat / 'stringy'
171
173
  ```
172
174
 
173
175
  ![](https://github.com/igrek51/nuclear/blob/master/docs/img/wat-string.png?raw=true)
@@ -176,13 +178,13 @@ wat('stringy')
176
178
  See the docstrings and the signature of a function or a method to see how to use it.
177
179
 
178
180
  ```python
179
- wat(str.split)
181
+ wat / str.split
180
182
  ```
181
183
 
182
184
  ![](https://github.com/igrek51/nuclear/blob/master/docs/img/wat-str-split.png?raw=true)
183
185
 
184
- ### Look up variables
185
- Check what's inside, list the value of variables and their types to see what's really inside the inspected object.
186
+ ### Look up attributes
187
+ List the attribues and their types to see what's really inside the inspected object.
186
188
  ```python
187
189
  wat / re.match('(\d)_(.*)', '1_title')
188
190
  ```
@@ -244,6 +246,13 @@ wat / __builtins__
244
246
  ### Look up local variables
245
247
  ```python
246
248
  wat()
249
+ # or
250
+ wat.locals
251
+ ```
252
+
253
+ ### Look up global variables
254
+ ```python
255
+ wat.globals
247
256
  ```
248
257
 
249
258
 
@@ -1,2 +1,2 @@
1
1
  colorama>=0.4.0
2
- pydantic>=2.0
2
+ PyYAML>=6.0
@@ -1,4 +0,0 @@
1
- def chunks(lst, n):
2
- """Yield successive n-sized chunks from lst."""
3
- for i in range(0, len(lst), n):
4
- yield lst[i:i + n]
@@ -1,112 +0,0 @@
1
- import dataclasses
2
- from datetime import date, datetime
3
- import json
4
- from pathlib import Path, PosixPath
5
- from typing import Dict, List, Type, TypeVar
6
-
7
- from pydantic import BaseModel
8
- import yaml
9
-
10
- T = TypeVar("T", bound=BaseModel)
11
-
12
-
13
- def parse_dict_datamodel(
14
- obj_dict: Dict,
15
- clazz: Type[T],
16
- ) -> T:
17
- """
18
- Cast dict object to expected pydantic model
19
- :param obj_dict: dict object to be transformed to pydantic.BaseModel
20
- :param clazz: pydantic.BaseModel type
21
- """
22
- return clazz.model_validate(obj_dict)
23
-
24
-
25
- def parse_dict_datamodels(
26
- obj_list: List[Dict],
27
- clazz: Type[T],
28
- ) -> List[T]:
29
- """Cast list of dict objects to expected data model types (pydantic.BaseModel)"""
30
- return [parse_dict_datamodel(obj_dict, clazz) for obj_dict in obj_list]
31
-
32
-
33
- def parse_yaml_datamodel(
34
- yaml_obj: str,
35
- clazz: Type[T],
36
- ) -> T:
37
- """
38
- Parse YAML and convert it to expected data model
39
- :param yaml_obj: YAML string
40
- :param clazz: pydantic.BaseModel type
41
- """
42
- data = yaml.load(yaml_obj, Loader=yaml.FullLoader)
43
- if data is None:
44
- data = {}
45
- return clazz.model_validate(data)
46
-
47
-
48
- def parse_yaml_file_datamodel(
49
- path: Path,
50
- clazz: Type[T],
51
- ) -> T:
52
- """
53
- Parse YAML file and convert it to expected data model
54
- :param path: Path to a YAML file
55
- :param clazz: pydantic.BaseModel type
56
- """
57
- assert path.is_file(), f"File doesn't exist: {path}"
58
- data = path.read_text()
59
- return parse_yaml_datamodel(data, clazz)
60
-
61
-
62
- def datamodel_to_yaml_str(dt: BaseModel) -> str:
63
- data_dict = datamodel_to_dict(dt)
64
- return yaml.dump(data_dict)
65
-
66
-
67
- def to_json(obj) -> str:
68
- obj = to_json_serializable(obj)
69
- obj = remove_none(obj)
70
- return json.dumps(obj)
71
-
72
-
73
- def to_yaml(obj) -> str:
74
- obj = to_json_serializable(obj)
75
- obj = remove_none(obj)
76
- return yaml.dump(obj, sort_keys=False)
77
-
78
-
79
- def datamodel_to_dict(dt: BaseModel) -> Dict:
80
- data_dict = dt.model_dump()
81
- data_dict = remove_none(data_dict)
82
- data_dict = to_json_serializable(data_dict)
83
- return data_dict
84
-
85
-
86
- def remove_none(obj):
87
- """Remove unwanted null values"""
88
- if isinstance(obj, list):
89
- return [remove_none(x) for x in obj if x is not None]
90
- elif isinstance(obj, dict):
91
- return {k: remove_none(v) for k, v in obj.items() if k is not None and v is not None}
92
- else:
93
- return obj
94
-
95
-
96
- def to_json_serializable(obj):
97
- if dataclasses.is_dataclass(obj):
98
- return to_json_serializable(dataclasses.asdict(obj))
99
- elif isinstance(obj, BaseModel):
100
- return obj.model_dump()
101
- elif isinstance(obj, PosixPath):
102
- return str(obj)
103
- elif isinstance(obj, (date, datetime)):
104
- return obj.isoformat()
105
- elif isinstance(obj, list):
106
- return [to_json_serializable(x) for x in obj]
107
- elif isinstance(obj, dict):
108
- return {k: to_json_serializable(v) for k, v in obj.items()}
109
- elif hasattr(obj, '__to_json__'):
110
- return getattr(obj, '__to_json__')()
111
- else:
112
- return obj
@@ -1 +0,0 @@
1
- __version__ = "2.1.2"
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