nuclear 2.2.0__tar.gz → 2.2.3__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 (67) hide show
  1. {nuclear-2.2.0 → nuclear-2.2.3}/PKG-INFO +16 -7
  2. {nuclear-2.2.0 → nuclear-2.2.3}/README.md +15 -6
  3. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/inspection/inspection.py +5 -5
  4. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/sublog/context_error.py +1 -1
  5. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/sublog/exception.py +1 -1
  6. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/sublog/logging.py +34 -20
  7. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/collections.py +7 -3
  8. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/time.py +5 -0
  9. nuclear-2.2.3/nuclear/version.py +1 -0
  10. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear.egg-info/PKG-INFO +16 -7
  11. nuclear-2.2.0/nuclear/version.py +0 -1
  12. {nuclear-2.2.0 → nuclear-2.2.3}/LICENSE +0 -0
  13. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/__init__.py +0 -0
  14. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/__init__.py +0 -0
  15. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/args/__init__.py +0 -0
  16. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/args/args_que.py +0 -0
  17. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/args/container.py +0 -0
  18. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/autocomplete/__init__.py +0 -0
  19. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/autocomplete/autocomplete.py +0 -0
  20. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/autocomplete/install.py +0 -0
  21. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/builder/__init__.py +0 -0
  22. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/builder/builder.py +0 -0
  23. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/builder/decorator_builder.py +0 -0
  24. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/builder/rule.py +0 -0
  25. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/builder/rule_factory.py +0 -0
  26. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/builder/typedef.py +0 -0
  27. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/completers/__init__.py +0 -0
  28. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/completers/file.py +0 -0
  29. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/help.py +0 -0
  30. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/__init__.py +0 -0
  31. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/context.py +0 -0
  32. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/error.py +0 -0
  33. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/inject.py +0 -0
  34. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/internal_vars.py +0 -0
  35. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/keyword.py +0 -0
  36. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/matcher.py +0 -0
  37. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/parser.py +0 -0
  38. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/transform.py +0 -0
  39. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/validate.py +0 -0
  40. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/parser/value.py +0 -0
  41. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/types/__init__.py +0 -0
  42. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/types/boolean.py +0 -0
  43. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/types/filesystem.py +0 -0
  44. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/cli/types/time.py +0 -0
  45. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/inspection/__init__.py +0 -0
  46. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/py.typed +0 -0
  47. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/shell/__init__.py +0 -0
  48. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/shell/background_cmd.py +0 -0
  49. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/shell/shell_utils.py +0 -0
  50. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/sublog/__init__.py +0 -0
  51. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/sublog/catch.py +0 -0
  52. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/__init__.py +0 -0
  53. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/config.py +0 -0
  54. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/datamodel.py +0 -0
  55. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/env.py +0 -0
  56. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/files.py +0 -0
  57. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/functools.py +0 -0
  58. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/input.py +0 -0
  59. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/regex.py +0 -0
  60. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/strings.py +0 -0
  61. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear/utils/url.py +0 -0
  62. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear.egg-info/SOURCES.txt +0 -0
  63. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear.egg-info/dependency_links.txt +0 -0
  64. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear.egg-info/requires.txt +0 -0
  65. {nuclear-2.2.0 → nuclear-2.2.3}/nuclear.egg-info/top_level.txt +0 -0
  66. {nuclear-2.2.0 → nuclear-2.2.3}/setup.cfg +0 -0
  67. {nuclear-2.2.0 → nuclear-2.2.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nuclear
3
- Version: 2.2.0
3
+ Version: 2.2.3
4
4
  Summary: Declarative parser for command line interfaces
5
5
  Home-page: https://github.com/igrek51/nuclear
6
6
  Author: igrek51
@@ -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
 
@@ -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:
@@ -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]:
@@ -1,31 +1,34 @@
1
1
  from contextlib import contextmanager
2
2
  from datetime import datetime, timezone
3
3
  import logging
4
+ import json
4
5
  import os
5
6
  import sys
6
7
  import threading
7
- from typing import Dict, Any, Callable
8
- import json
8
+ import time
9
+ from typing import Dict, Any, Callable, List, Optional
9
10
 
10
11
  from colorama import init, Fore, Style
11
12
 
12
13
  from nuclear.sublog.context_error import ContextError
13
14
  from nuclear.sublog.exception import extended_exception_details
15
+ from nuclear.utils.collections import filter_not_none
14
16
  from nuclear.utils.env import is_env_flag_enabled
15
17
  from nuclear.utils.strings import strip_ansi_colors
16
18
 
17
19
  LOG_FORMAT = f'{Style.DIM}[%(asctime)s]{Style.RESET_ALL} %(levelname)s %(message)s'
18
20
  LOG_DATE_FORMAT = r'%Y-%m-%d %H:%M:%S'
21
+ LOG_DATE_FORMAT_UTC = r'%Y-%m-%d %H:%M:%SZ'
19
22
  ISO_DATE_FORMAT = r'%Y-%m-%dT%H:%M:%S.%fZ'
20
23
  LOGGING_LOGGER_NAME = 'nuclear.sublog'
21
- STRUCTURED_LOGGING = is_env_flag_enabled('STRUCTURED_LOGGING', 'false')
22
24
 
23
- log_level: str = os.environ.get('LOG_LEVEL', 'debug')
25
+ log_level: str = os.environ.get('NUCLEAR_LOG_LEVEL', 'debug')
26
+ log_level_show: bool = is_env_flag_enabled('NUCLEAR_LOG_LEVEL_SHOW', 'true')
27
+ log_time_show: bool = is_env_flag_enabled('NUCLEAR_LOG_TIME', 'true')
24
28
  simultaneous_print_lock = threading.Lock()
25
29
  _logging_logger: logging.Logger = logging.getLogger(LOGGING_LOGGER_NAME)
26
- _log_state = {
27
- 'init': False,
28
- }
30
+ _log_state = {'init': False}
31
+
29
32
 
30
33
  def init_logs():
31
34
  """Configure loggers: formatters, handlers and log levels"""
@@ -37,15 +40,15 @@ def init_logs():
37
40
  }
38
41
  if sys.version_info[1] >= 8:
39
42
  logging_kwargs['force'] = True
40
- if not is_env_flag_enabled('STRUCTURED_LOGGING', 'false'):
43
+ if is_env_flag_enabled('NUCLEAR_STRUCTURED_LOGGING', 'false'):
44
+ logging_kwargs['datefmt'] = ISO_DATE_FORMAT
41
45
  logging.basicConfig(**logging_kwargs)
42
46
  for handler in logging.getLogger().handlers:
43
- handler.setFormatter(ColoredFormatter(handler.formatter))
47
+ handler.setFormatter(StructuredFormatter())
44
48
  else:
45
- logging_kwargs['datefmt'] = ISO_DATE_FORMAT
46
49
  logging.basicConfig(**logging_kwargs)
47
50
  for handler in logging.getLogger().handlers:
48
- handler.setFormatter(StructuredFormatter(handler.formatter))
51
+ handler.setFormatter(ColoredFormatter())
49
52
 
50
53
  level = _get_logging_level(log_level)
51
54
  root_logger = logging.getLogger(LOGGING_LOGGER_NAME)
@@ -65,7 +68,7 @@ def get_logger(logger_name: str) -> logging.Logger:
65
68
  class ContextLogger:
66
69
  def __init__(self, ctx: Dict[str, Any]):
67
70
  self.ctx: Dict[str, Any] = ctx
68
- self.structured_logging: bool = STRUCTURED_LOGGING
71
+ self.structured_logging: bool = is_env_flag_enabled('NUCLEAR_STRUCTURED_LOGGING', 'false')
69
72
  self.first_use = True
70
73
 
71
74
  def error(self, message: str, **ctx):
@@ -101,7 +104,7 @@ class ContextLogger:
101
104
  if display_context:
102
105
  if message.endswith(':'):
103
106
  message = message[:-1]
104
- logger_func(f'{message}: {display_context}')
107
+ logger_func(f'{message}, {display_context}')
105
108
  else:
106
109
  logger_func(message)
107
110
 
@@ -147,9 +150,8 @@ def add_context(context_name: str, log: bool = False, **ctx):
147
150
 
148
151
 
149
152
  class ColoredFormatter(logging.Formatter):
150
- def __init__(self, plain_formatter):
153
+ def __init__(self):
151
154
  logging.Formatter.__init__(self)
152
- self.plain_formatter = plain_formatter
153
155
 
154
156
  log_level_templates = {
155
157
  'CRITICAL': f'{Style.BRIGHT + Fore.RED}CRIT {Style.RESET_ALL}',
@@ -160,18 +162,30 @@ class ColoredFormatter(logging.Formatter):
160
162
  }
161
163
 
162
164
  def format(self, record: logging.LogRecord) -> str:
163
- if record.levelname in self.log_level_templates:
164
- record.levelname = self.log_level_templates[record.levelname].format(record.levelname)
165
- line: str = self.plain_formatter.format(record)
165
+ part_levelname = self.log_level_templates.get(record.levelname, record.levelname) if log_level_show else None
166
+ part_message = record.msg
167
+ part_time = self.format_time()
168
+ parts: List[str] = filter_not_none([part_time, part_levelname, part_message])
169
+ line = ' '.join(parts)
166
170
  if not sys.stdout.isatty():
167
171
  line = strip_ansi_colors(line)
168
172
  return line
173
+
174
+ @staticmethod
175
+ def format_time() -> Optional[str]:
176
+ if not log_time_show:
177
+ return None
178
+ now_tz = datetime.now().astimezone()
179
+ if time.timezone == 0:
180
+ time_formatted = now_tz.strftime(LOG_DATE_FORMAT_UTC)
181
+ else:
182
+ time_formatted = now_tz.strftime(LOG_DATE_FORMAT)
183
+ return f'{Style.DIM}[{time_formatted}]{Style.RESET_ALL}'
169
184
 
170
185
 
171
186
  class StructuredFormatter(logging.Formatter):
172
- def __init__(self, plain_formatter):
187
+ def __init__(self):
173
188
  logging.Formatter.__init__(self)
174
- self.plain_formatter = plain_formatter
175
189
 
176
190
  def format(self, record: logging.LogRecord) -> str:
177
191
  timestamp: float = record.created
@@ -1,4 +1,4 @@
1
- from typing import Any, Callable, Iterable, TypeVar, List, Union
1
+ from typing import Any, Callable, Iterable, TypeVar, List, Union, Optional
2
2
 
3
3
  T = TypeVar('T')
4
4
 
@@ -9,7 +9,7 @@ def chunks(lst: List[T], n: int) -> Iterable[List[T]]:
9
9
  yield lst[i:i + n]
10
10
 
11
11
 
12
- def deduplicate_latest(items: list[T], key: Callable[[T], Any]) -> list[T]:
12
+ def deduplicate_latest(items: List[T], key: Callable[[T], Any]) -> List[T]:
13
13
  """Deduplicate items in the list by key. Keep the earliest items first, remove the latest duplicates"""
14
14
  ids = set()
15
15
  dedup_items: List[T] = []
@@ -21,7 +21,7 @@ def deduplicate_latest(items: list[T], key: Callable[[T], Any]) -> list[T]:
21
21
  return dedup_items
22
22
 
23
23
 
24
- def deduplicate_earliest(items: list[T], key: Callable[[T], Any]) -> list[T]:
24
+ def deduplicate_earliest(items: List[T], key: Callable[[T], Any]) -> List[T]:
25
25
  """Deduplicate items in the list by key. Keep the latest items, remove the earliest duplicates"""
26
26
  ids = set()
27
27
  dedup_items: List[T] = []
@@ -42,3 +42,7 @@ def flatten(collection: Iterable[Union[T, List[T]]]) -> List[T]:
42
42
  else:
43
43
  flat.append(item)
44
44
  return flat
45
+
46
+
47
+ def filter_not_none(items: List[Optional[T]]) -> List[T]:
48
+ return [item for item in items if item is not None]
@@ -14,6 +14,11 @@ def now() -> datetime:
14
14
  return datetime.now(timezone.utc)
15
15
 
16
16
 
17
+ def now_tz() -> datetime:
18
+ """Return current datetime with local timezone set"""
19
+ return datetime.now().astimezone()
20
+
21
+
17
22
  def now_timestamp() -> int:
18
23
  return datetime_to_timestamp(now())
19
24
 
@@ -0,0 +1 @@
1
+ __version__ = "2.2.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nuclear
3
- Version: 2.2.0
3
+ Version: 2.2.3
4
4
  Summary: Declarative parser for command line interfaces
5
5
  Home-page: https://github.com/igrek51/nuclear
6
6
  Author: igrek51
@@ -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 +0,0 @@
1
- __version__ = "2.2.0"
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