ae-base 0.3.50__py3-none-any.whl → 0.3.52__py3-none-any.whl
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.
- ae/base.py +38 -12
- {ae_base-0.3.50.dist-info → ae_base-0.3.52.dist-info}/METADATA +7 -6
- ae_base-0.3.52.dist-info/RECORD +7 -0
- {ae_base-0.3.50.dist-info → ae_base-0.3.52.dist-info}/WHEEL +1 -1
- ae_base-0.3.50.dist-info/RECORD +0 -7
- {ae_base-0.3.50.dist-info → ae_base-0.3.52.dist-info/licenses}/LICENSE.md +0 -0
- {ae_base-0.3.50.dist-info → ae_base-0.3.52.dist-info}/top_level.txt +0 -0
- {ae_base-0.3.50.dist-info → ae_base-0.3.52.dist-info}/zip-safe +0 -0
ae/base.py
CHANGED
|
@@ -40,6 +40,9 @@ and :func:`write_file` are wrapping Python's built-in :func:`open` function and
|
|
|
40
40
|
|
|
41
41
|
the function :func:`duplicates` returns the duplicates of an iterable type.
|
|
42
42
|
|
|
43
|
+
in order to hide/mask secrets like credit card numbers, passwords or tokens in deeply nested data structures,
|
|
44
|
+
before they get dumped e.g. to an app log file, the function :func:`mask_secrets` can be used.
|
|
45
|
+
|
|
43
46
|
:func:`norm_line_sep` is converting any combination of line separators of a string to a single new-line character.
|
|
44
47
|
|
|
45
48
|
:func:`norm_name` converts any string into a name that can be used e.g. as file name or as method/attribute name.
|
|
@@ -157,10 +160,10 @@ from contextlib import contextmanager
|
|
|
157
160
|
from importlib.machinery import ModuleSpec
|
|
158
161
|
from inspect import getinnerframes, getouterframes, getsourcefile
|
|
159
162
|
from types import ModuleType
|
|
160
|
-
from typing import Any, Callable,
|
|
163
|
+
from typing import Any, Callable, Generator, Iterable, Optional, Union, cast
|
|
161
164
|
|
|
162
165
|
|
|
163
|
-
__version__ = '0.3.
|
|
166
|
+
__version__ = '0.3.52'
|
|
164
167
|
|
|
165
168
|
|
|
166
169
|
os_path_abspath = os.path.abspath
|
|
@@ -272,7 +275,7 @@ def app_name_guess() -> str:
|
|
|
272
275
|
return defuse(app_name)
|
|
273
276
|
|
|
274
277
|
|
|
275
|
-
def build_config_variable_values(*names_defaults:
|
|
278
|
+
def build_config_variable_values(*names_defaults: tuple[str, Any], section: str = 'app') -> tuple[Any, ...]:
|
|
276
279
|
""" determine build config variable values from the ``buildozer.spec`` file in the current directory.
|
|
277
280
|
|
|
278
281
|
:param names_defaults: tuple of tuples of build config variable names and default values.
|
|
@@ -634,7 +637,7 @@ def load_env_var_defaults(start_dir: str):
|
|
|
634
637
|
file_path = os_path_join(os_path_dirname(os_path_dirname(file_path)), DOTENV_FILE_NAME)
|
|
635
638
|
|
|
636
639
|
|
|
637
|
-
def main_file_paths_parts(portion_name: str) ->
|
|
640
|
+
def main_file_paths_parts(portion_name: str) -> tuple[tuple[str, ...], ...]:
|
|
638
641
|
""" determine tuple of supported main/version file name path part tuples.
|
|
639
642
|
|
|
640
643
|
:param portion_name: portion or package name.
|
|
@@ -650,6 +653,29 @@ def main_file_paths_parts(portion_name: str) -> Tuple[Tuple[str, ...], ...]:
|
|
|
650
653
|
)
|
|
651
654
|
|
|
652
655
|
|
|
656
|
+
def mask_secrets(data: Union[dict, Iterable], fragments: Iterable[str] = ('password', 'pwd')) -> Union[dict, Iterable]:
|
|
657
|
+
""" partially-hide secret string values like passwords/credit-card-numbers in deeply nestable data structures.
|
|
658
|
+
|
|
659
|
+
:param data: iterable deep data structure wherein its item values get masked if their related dict
|
|
660
|
+
item key contains one of the fragments specified in :paramref:`~mask_secrets.fragments`.
|
|
661
|
+
:param fragments: dict key string fragments of which the related value will be masked. each fragment has
|
|
662
|
+
to be specified in lower case! defaults to ('password', 'pwd') if not passed.
|
|
663
|
+
:return: specified data structure with the secrets masked (¡in-place!).
|
|
664
|
+
"""
|
|
665
|
+
is_dict = isinstance(data, dict)
|
|
666
|
+
|
|
667
|
+
for idx, val in tuple(data.items()) if is_dict else enumerate(data): # type: ignore # silly mypy not sees is_dict
|
|
668
|
+
val_is_str = isinstance(val, str)
|
|
669
|
+
if not val_is_str and isinstance(val, Iterable):
|
|
670
|
+
mask_secrets(val, fragments=fragments)
|
|
671
|
+
elif is_dict and val_is_str and isinstance(idx, str):
|
|
672
|
+
idx_lower = idx.lower()
|
|
673
|
+
if any(_frag in idx_lower for _frag in fragments):
|
|
674
|
+
data[idx] = val[:3] + "*" * 9 # type: ignore # silly mypy not sees is_dict
|
|
675
|
+
|
|
676
|
+
return data
|
|
677
|
+
|
|
678
|
+
|
|
653
679
|
def module_attr(import_name: str, attr_name: str = "") -> Optional[Any]:
|
|
654
680
|
""" determine dynamically a reference to a module or to any attribute (variable/func/class) declared in the module.
|
|
655
681
|
|
|
@@ -722,7 +748,7 @@ def norm_name(name: str, allow_num_prefix: bool = False) -> str:
|
|
|
722
748
|
:param allow_num_prefix: pass True to allow leading digits in the returned normalized name.
|
|
723
749
|
:return: cleaned/normalized/converted name string (e.g. for a variable-/method-/file-name).
|
|
724
750
|
"""
|
|
725
|
-
str_parts:
|
|
751
|
+
str_parts: list[str] = []
|
|
726
752
|
for char in name:
|
|
727
753
|
if char.isalpha() or char.isalnum() and (allow_num_prefix or str_parts):
|
|
728
754
|
str_parts.append(char)
|
|
@@ -855,13 +881,13 @@ def os_user_name() -> str:
|
|
|
855
881
|
return getpass.getuser()
|
|
856
882
|
|
|
857
883
|
|
|
858
|
-
def parse_dotenv(file_path: str) ->
|
|
884
|
+
def parse_dotenv(file_path: str) -> dict[str, str]:
|
|
859
885
|
""" parse ``.env`` file content and return environment variable names as dict keys and values as dict values.
|
|
860
886
|
|
|
861
887
|
:param file_path: string with the name/path of an existing ``.env``/:data:`DOTENV_FILE_NAME` file.
|
|
862
888
|
:return: dict with environment variable names and values
|
|
863
889
|
"""
|
|
864
|
-
env_vars:
|
|
890
|
+
env_vars: dict[str, str] = {}
|
|
865
891
|
for line in cast(str, read_file(file_path)).splitlines():
|
|
866
892
|
match = _env_line.search(line)
|
|
867
893
|
if not match:
|
|
@@ -1017,7 +1043,7 @@ def stack_var(name: str, *skip_modules: str, scope: str = '', depth: int = 1) ->
|
|
|
1017
1043
|
|
|
1018
1044
|
def stack_vars(*skip_modules: str,
|
|
1019
1045
|
find_name: str = '', min_depth: int = 1, max_depth: int = 0, scope: str = ''
|
|
1020
|
-
) ->
|
|
1046
|
+
) -> tuple[dict[str, Any], dict[str, Any], int]:
|
|
1021
1047
|
""" determine all global and local variables in a calling stack/frames.
|
|
1022
1048
|
|
|
1023
1049
|
:param skip_modules: module names to skip (def=see :data:`SKIPPED_MODULES` module constant).
|
|
@@ -1057,7 +1083,7 @@ def stack_vars(*skip_modules: str,
|
|
|
1057
1083
|
return glo.copy(), loc, depth - 1
|
|
1058
1084
|
|
|
1059
1085
|
|
|
1060
|
-
def sys_env_dict() ->
|
|
1086
|
+
def sys_env_dict() -> dict[str, Any]:
|
|
1061
1087
|
""" returns dict with python system run-time environment values.
|
|
1062
1088
|
|
|
1063
1089
|
:return: python system run-time environment values like python_ver, argv, cwd, executable,
|
|
@@ -1065,7 +1091,7 @@ def sys_env_dict() -> Dict[str, Any]:
|
|
|
1065
1091
|
|
|
1066
1092
|
.. hint:: see also https://pyinstaller.readthedocs.io/en/stable/runtime-information.html
|
|
1067
1093
|
"""
|
|
1068
|
-
sed:
|
|
1094
|
+
sed: dict[str, Any] = {
|
|
1069
1095
|
'python ver': sys.version.replace('\n', ' '),
|
|
1070
1096
|
'platform': os_platform,
|
|
1071
1097
|
'argv': sys.argv,
|
|
@@ -1076,7 +1102,7 @@ def sys_env_dict() -> Dict[str, Any]:
|
|
|
1076
1102
|
'host name': os_host_name(),
|
|
1077
1103
|
'device id': os_device_id,
|
|
1078
1104
|
'app_name_guess': app_name_guess(),
|
|
1079
|
-
'os env': os.environ.copy(),
|
|
1105
|
+
'os env': mask_secrets(os.environ.copy()),
|
|
1080
1106
|
}
|
|
1081
1107
|
|
|
1082
1108
|
if sed['frozen']:
|
|
@@ -1086,7 +1112,7 @@ def sys_env_dict() -> Dict[str, Any]:
|
|
|
1086
1112
|
|
|
1087
1113
|
|
|
1088
1114
|
def sys_env_text(ind_ch: str = " ", ind_len: int = 12, key_ch: str = "=", key_len: int = 15,
|
|
1089
|
-
extra_sys_env_dict: Optional[
|
|
1115
|
+
extra_sys_env_dict: Optional[dict[str, str]] = None) -> str:
|
|
1090
1116
|
""" compile formatted text block with system environment info.
|
|
1091
1117
|
|
|
1092
1118
|
:param ind_ch: indent character (defaults to " ").
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: ae_base
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.52
|
|
4
4
|
Summary: ae namespace module portion base: basic constants, helper functions and context manager
|
|
5
5
|
Home-page: https://gitlab.com/ae-group/ae_base
|
|
6
6
|
Author: AndiEcker
|
|
@@ -61,6 +61,7 @@ Dynamic: description-content-type
|
|
|
61
61
|
Dynamic: home-page
|
|
62
62
|
Dynamic: keywords
|
|
63
63
|
Dynamic: license
|
|
64
|
+
Dynamic: license-file
|
|
64
65
|
Dynamic: project-url
|
|
65
66
|
Dynamic: provides-extra
|
|
66
67
|
Dynamic: requires-python
|
|
@@ -68,17 +69,17 @@ Dynamic: summary
|
|
|
68
69
|
|
|
69
70
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae V0.3.95 -->
|
|
70
71
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.tpl_namespace_root V0.3.14 -->
|
|
71
|
-
# base 0.3.
|
|
72
|
+
# base 0.3.52
|
|
72
73
|
|
|
73
74
|
[](
|
|
74
75
|
https://gitlab.com/ae-group/ae_base)
|
|
75
76
|
[](
|
|
78
|
+
https://gitlab.com/ae-group/ae_base/-/tree/release0.3.51)
|
|
78
79
|
[](
|
|
79
80
|
https://pypi.org/project/ae-base/#history)
|
|
80
81
|
|
|
81
|
-
>ae_base module 0.3.
|
|
82
|
+
>ae_base module 0.3.52.
|
|
82
83
|
|
|
83
84
|
[](
|
|
84
85
|
https://ae-group.gitlab.io/ae_base/coverage/index.html)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ae/base.py,sha256=IpEnDdbJdhFU8r-t8qg2LaY4sR6p2I2CO5VE4fVIsDs,64611
|
|
2
|
+
ae_base-0.3.52.dist-info/licenses/LICENSE.md,sha256=uoIIfORuk4V8ZeNh6SN0EUhiU79RC-indIMFqePKVhY,35002
|
|
3
|
+
ae_base-0.3.52.dist-info/METADATA,sha256=xcJk6cnwOehC0Quvkr-VeJ9maJtIeKSUEnoBoEozE_E,5658
|
|
4
|
+
ae_base-0.3.52.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
|
|
5
|
+
ae_base-0.3.52.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
+
ae_base-0.3.52.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
+
ae_base-0.3.52.dist-info/RECORD,,
|
ae_base-0.3.50.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
ae/base.py,sha256=1me3TvKdrXFKVDI9qqXYzJ52d0d3qVw21rY643gymY0,62992
|
|
2
|
-
ae_base-0.3.50.dist-info/LICENSE.md,sha256=uoIIfORuk4V8ZeNh6SN0EUhiU79RC-indIMFqePKVhY,35002
|
|
3
|
-
ae_base-0.3.50.dist-info/METADATA,sha256=1YUr5FieYlbsSE_1atpH6N0uJmYfTRd4tcpxrtqmJRQ,5636
|
|
4
|
-
ae_base-0.3.50.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
5
|
-
ae_base-0.3.50.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
-
ae_base-0.3.50.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
-
ae_base-0.3.50.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|