ae-base 0.3.41__py3-none-any.whl → 0.3.42__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 +65 -35
- {ae_base-0.3.41.dist-info → ae_base-0.3.42.dist-info}/METADATA +5 -5
- ae_base-0.3.42.dist-info/RECORD +7 -0
- ae_base-0.3.41.dist-info/RECORD +0 -7
- {ae_base-0.3.41.dist-info → ae_base-0.3.42.dist-info}/LICENSE.md +0 -0
- {ae_base-0.3.41.dist-info → ae_base-0.3.42.dist-info}/WHEEL +0 -0
- {ae_base-0.3.41.dist-info → ae_base-0.3.42.dist-info}/top_level.txt +0 -0
- {ae_base-0.3.41.dist-info → ae_base-0.3.42.dist-info}/zip-safe +0 -0
ae/base.py
CHANGED
|
@@ -143,6 +143,13 @@ to determine e.g. variable values of the callers of a function/method.
|
|
|
143
143
|
:attr:`title <AppBase.app_title>` of an application, if these values are not specified in the instance initializer.
|
|
144
144
|
|
|
145
145
|
another useful helper function provided by this portion to inspect and debug your code is :func:`full_stack_trace`.
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
os.path shortcuts
|
|
149
|
+
-----------------
|
|
150
|
+
|
|
151
|
+
the following data items are pointers to shortcut the lookup to their related functions in the
|
|
152
|
+
Python module :mod:`os.path`:
|
|
146
153
|
"""
|
|
147
154
|
import datetime
|
|
148
155
|
import getpass
|
|
@@ -166,7 +173,21 @@ from types import ModuleType
|
|
|
166
173
|
from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Tuple, Union, cast
|
|
167
174
|
|
|
168
175
|
|
|
169
|
-
__version__ = '0.3.
|
|
176
|
+
__version__ = '0.3.42'
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
os_path_abspath = os.path.abspath
|
|
180
|
+
os_path_basename = os.path.basename
|
|
181
|
+
os_path_dirname = os.path.dirname
|
|
182
|
+
os_path_expanduser = os.path.expanduser
|
|
183
|
+
os_path_isdir = os.path.isdir
|
|
184
|
+
os_path_isfile = os.path.isfile
|
|
185
|
+
os_path_join = os.path.join
|
|
186
|
+
os_path_normpath = os.path.normpath
|
|
187
|
+
os_path_realpath = os.path.realpath
|
|
188
|
+
os_path_relpath = os.path.relpath
|
|
189
|
+
os_path_sep = os.path.sep
|
|
190
|
+
os_path_splitext = os.path.splitext
|
|
170
191
|
|
|
171
192
|
|
|
172
193
|
DOCS_FOLDER = 'docs' #: project documentation root folder name
|
|
@@ -256,10 +277,10 @@ def app_name_guess() -> str:
|
|
|
256
277
|
if not app_name:
|
|
257
278
|
unspecified_app_names = ('ae_base', 'app', '_jb_pytest_runner', 'main', '__main__', 'pydevconsole', 'src')
|
|
258
279
|
path = sys.argv[0]
|
|
259
|
-
app_name =
|
|
280
|
+
app_name = os_path_splitext(os_path_basename(path))[0]
|
|
260
281
|
if app_name.lower() in unspecified_app_names:
|
|
261
282
|
path = os.getcwd()
|
|
262
|
-
app_name =
|
|
283
|
+
app_name = os_path_basename(path)
|
|
263
284
|
if app_name.lower() in unspecified_app_names:
|
|
264
285
|
app_name = "unguessable"
|
|
265
286
|
return app_name
|
|
@@ -273,7 +294,7 @@ def build_config_variable_values(*names_defaults: Tuple[str, Any], section: str
|
|
|
273
294
|
:return: tuple of build config variable values (using the passed default value if not specified
|
|
274
295
|
in the :data:`BUILD_CONFIG_FILE` spec file or if the spec file does not exist in cwd).
|
|
275
296
|
"""
|
|
276
|
-
if not
|
|
297
|
+
if not os_path_isfile(BUILD_CONFIG_FILE):
|
|
277
298
|
return tuple(def_val for name, def_val in names_defaults)
|
|
278
299
|
|
|
279
300
|
config = instantiate_config_parser()
|
|
@@ -417,8 +438,8 @@ def import_module(import_name: str, path: Optional[Union[str, UnsetType]] = UNSE
|
|
|
417
438
|
:return: a reference to the loaded module or ``None`` if module could not be imported.
|
|
418
439
|
"""
|
|
419
440
|
if path is UNSET:
|
|
420
|
-
path = import_name.replace('.',
|
|
421
|
-
path += PY_EXT if
|
|
441
|
+
path = import_name.replace('.', os_path_sep)
|
|
442
|
+
path += PY_EXT if os_path_isfile(path + PY_EXT) else os_path_sep + PY_INIT
|
|
422
443
|
mod_ref = None
|
|
423
444
|
|
|
424
445
|
spec = importlib.util.spec_from_file_location(import_name, path) # type: ignore # silly mypy
|
|
@@ -469,7 +490,7 @@ def load_dotenvs():
|
|
|
469
490
|
"""
|
|
470
491
|
load_env_var_defaults(os.getcwd())
|
|
471
492
|
if file_name := stack_var('__file__'):
|
|
472
|
-
load_env_var_defaults(
|
|
493
|
+
load_env_var_defaults(os_path_dirname(os_path_abspath(file_name)))
|
|
473
494
|
|
|
474
495
|
|
|
475
496
|
def load_env_var_defaults(start_dir: str):
|
|
@@ -485,18 +506,18 @@ def load_env_var_defaults(start_dir: str):
|
|
|
485
506
|
only variables that are not declared in :data:`os.environ` will be added (with the
|
|
486
507
|
value specified in the ``.env`` file to be loaded).
|
|
487
508
|
"""
|
|
488
|
-
file_path =
|
|
489
|
-
if not
|
|
490
|
-
file_path =
|
|
509
|
+
file_path = os_path_abspath(os_path_join(start_dir, DOTENV_FILE_NAME))
|
|
510
|
+
if not os_path_isfile(file_path):
|
|
511
|
+
file_path = os_path_join(os_path_dirname(start_dir), DOTENV_FILE_NAME)
|
|
491
512
|
|
|
492
|
-
while
|
|
513
|
+
while os_path_isfile(file_path):
|
|
493
514
|
for var_nam, var_val in parse_dotenv(file_path).items():
|
|
494
515
|
if var_nam not in os.environ:
|
|
495
516
|
os.environ[var_nam] = var_val
|
|
496
517
|
|
|
497
518
|
if os.sep not in file_path:
|
|
498
519
|
break # pragma: no cover # prevent endless-loop for ``.env`` file in root dir (os.sep == '/')
|
|
499
|
-
file_path =
|
|
520
|
+
file_path = os_path_join(os_path_dirname(os_path_dirname(file_path)), DOTENV_FILE_NAME)
|
|
500
521
|
|
|
501
522
|
|
|
502
523
|
def main_file_paths_parts(portion_name: str) -> Tuple[Tuple[str, ...], ...]:
|
|
@@ -620,20 +641,20 @@ def norm_path(path: str, make_absolute: bool = True, remove_base_path: str = "",
|
|
|
620
641
|
"""
|
|
621
642
|
path = path or "."
|
|
622
643
|
if path[0] == "~":
|
|
623
|
-
path =
|
|
644
|
+
path = os_path_expanduser(path)
|
|
624
645
|
|
|
625
646
|
if remove_dots:
|
|
626
|
-
path =
|
|
647
|
+
path = os_path_normpath(path)
|
|
627
648
|
|
|
628
649
|
if resolve_sym_links:
|
|
629
|
-
path =
|
|
650
|
+
path = os_path_realpath(path)
|
|
630
651
|
elif make_absolute:
|
|
631
|
-
path =
|
|
652
|
+
path = os_path_abspath(path)
|
|
632
653
|
|
|
633
654
|
if remove_base_path:
|
|
634
655
|
if remove_base_path[0] == "~":
|
|
635
|
-
remove_base_path =
|
|
636
|
-
path =
|
|
656
|
+
remove_base_path = os_path_expanduser(remove_base_path)
|
|
657
|
+
path = os_path_relpath(path, remove_base_path)
|
|
637
658
|
|
|
638
659
|
return path
|
|
639
660
|
|
|
@@ -768,23 +789,22 @@ def project_main_file(import_name: str, project_path: str = "") -> str:
|
|
|
768
789
|
sister project (under the same project parent folder).
|
|
769
790
|
:return: absolute file path/name of main module or empty string if no main/version file found.
|
|
770
791
|
"""
|
|
771
|
-
join = os.path.join
|
|
772
792
|
*namespace_dirs, portion_name = import_name.split('.')
|
|
773
793
|
project_name = ('_'.join(namespace_dirs) + '_' if namespace_dirs else "") + portion_name
|
|
774
794
|
paths_parts = main_file_paths_parts(portion_name)
|
|
775
795
|
|
|
776
796
|
project_path = norm_path(project_path)
|
|
777
797
|
module_paths = []
|
|
778
|
-
if
|
|
779
|
-
module_paths.append(
|
|
798
|
+
if os_path_basename(project_path) != project_name:
|
|
799
|
+
module_paths.append(os_path_join(os_path_dirname(project_path), project_name, *namespace_dirs))
|
|
780
800
|
if namespace_dirs:
|
|
781
|
-
module_paths.append(
|
|
801
|
+
module_paths.append(os_path_join(project_path, *namespace_dirs))
|
|
782
802
|
module_paths.append(project_path)
|
|
783
803
|
|
|
784
804
|
for module_path in module_paths:
|
|
785
805
|
for path_parts in paths_parts:
|
|
786
|
-
main_file =
|
|
787
|
-
if
|
|
806
|
+
main_file = os_path_join(module_path, *path_parts)
|
|
807
|
+
if os_path_isfile(main_file):
|
|
788
808
|
return main_file
|
|
789
809
|
return ""
|
|
790
810
|
|
|
@@ -899,7 +919,7 @@ def stack_vars(*skip_modules: str,
|
|
|
899
919
|
:param max_depth: the maximum depth in the call stack from which to return the variables. if the specified
|
|
900
920
|
argument is not zero and no :paramref:`~stack_vars.skip_modules` are specified then the
|
|
901
921
|
first deeper stack frame that is not within the default :data:`SKIPPED_MODULES` will be
|
|
902
|
-
returned. if this argument and :paramref:`~
|
|
922
|
+
returned. if this argument and :paramref:`~stack_vars.find_name` get not passed then the
|
|
903
923
|
variables of the top stack frame will be returned.
|
|
904
924
|
:return: tuple of the global and local variable dicts and the depth in the call stack.
|
|
905
925
|
"""
|
|
@@ -1020,14 +1040,18 @@ def write_file(file_path: str, content: Union[str, bytes], extra_mode: str = "",
|
|
|
1020
1040
|
""" (over)write the file specified by :paramref:`~write_file.file_path` with text or binary/bytes content.
|
|
1021
1041
|
|
|
1022
1042
|
:param file_path: file path/name to write the passed content into (overwriting any previous content!).
|
|
1023
|
-
:param content: new file content either
|
|
1024
|
-
|
|
1025
|
-
:param extra_mode: open mode flag characters. passed
|
|
1026
|
-
this argument starts with 'a', else this argument value will be appended to 'w'
|
|
1043
|
+
:param content: new file content passed either as string or bytes array. if a bytes array get passed
|
|
1044
|
+
then this method will automatically write the content as binary.
|
|
1045
|
+
:param extra_mode: additional open mode flag characters. passed to the `mode` argument of :func:`open` if
|
|
1046
|
+
this argument starts with 'a' or 'w', else this argument value will be appended to 'w'
|
|
1047
|
+
before it get passed to the `mode` argument of :func:`open`.
|
|
1048
|
+
if the :paramref:`~write_file.content` is a bytes array, then a 'b' character will
|
|
1049
|
+
be automatically added to the `mode` argument of :func:`open` (if not already specified
|
|
1050
|
+
in this argument).
|
|
1027
1051
|
:param encoding: encoding used to write/convert/interpret the file content to write.
|
|
1028
1052
|
:raises FileExistsError: if file exists already and is write-protected.
|
|
1029
1053
|
:raises FileNotFoundError: if parts of the file path do not exist.
|
|
1030
|
-
:raises OSError: if :paramref:`~
|
|
1054
|
+
:raises OSError: if :paramref:`~write_file.file_path` is misspelled or contains invalid characters.
|
|
1031
1055
|
:raises PermissionError: if current OS user account lacks permissions to read the file content.
|
|
1032
1056
|
:raises ValueError: on decoding errors.
|
|
1033
1057
|
|
|
@@ -1040,7 +1064,13 @@ def write_file(file_path: str, content: Union[str, bytes], extra_mode: str = "",
|
|
|
1040
1064
|
for an intent result.
|
|
1041
1065
|
Related german docs: https://developer.android.com/training/data-storage/shared/media?hl=de
|
|
1042
1066
|
"""
|
|
1043
|
-
|
|
1067
|
+
if isinstance(content, bytes) and 'b' not in extra_mode:
|
|
1068
|
+
extra_mode += 'b'
|
|
1069
|
+
|
|
1070
|
+
if extra_mode == '' or extra_mode[0] not in ('a', 'w'):
|
|
1071
|
+
extra_mode = 'w' + extra_mode
|
|
1072
|
+
|
|
1073
|
+
with open(file_path, mode=extra_mode, encoding=encoding) as file_handle:
|
|
1044
1074
|
file_handle.write(content)
|
|
1045
1075
|
|
|
1046
1076
|
|
|
@@ -1069,16 +1099,16 @@ class ErrorMsgMixin:
|
|
|
1069
1099
|
PACKAGE_NAME = stack_var('__name__') or 'unspecified_package'
|
|
1070
1100
|
PACKAGE_DOMAIN = 'org.test'
|
|
1071
1101
|
PERMISSIONS = "INTERNET, VIBRATE, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE"
|
|
1072
|
-
if
|
|
1102
|
+
if os_path_isfile(BUILD_CONFIG_FILE): # pragma: no cover
|
|
1073
1103
|
PACKAGE_NAME, PACKAGE_DOMAIN, PERMISSIONS = build_config_variable_values(
|
|
1074
1104
|
('package.name', PACKAGE_NAME),
|
|
1075
1105
|
('package.domain', PACKAGE_DOMAIN),
|
|
1076
1106
|
('android.permissions', PERMISSIONS))
|
|
1077
1107
|
elif os_platform == 'android': # pragma: no cover
|
|
1078
1108
|
_importing_package = norm_path(stack_var('__file__') or 'empty_package' + PY_EXT)
|
|
1079
|
-
if
|
|
1080
|
-
_importing_package =
|
|
1081
|
-
_importing_package =
|
|
1109
|
+
if os_path_basename(_importing_package) in (PY_INIT, PY_MAIN):
|
|
1110
|
+
_importing_package = os_path_dirname(_importing_package)
|
|
1111
|
+
_importing_package = os_path_splitext(os_path_basename(_importing_package))[0]
|
|
1082
1112
|
write_file(f'{_importing_package}_debug.log', f"{BUILD_CONFIG_FILE} not bundled - using defaults\n", extra_mode='a')
|
|
1083
1113
|
|
|
1084
1114
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ae_base
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.42
|
|
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
|
|
@@ -55,17 +55,17 @@ Requires-Dist: twine; extra == "tests"
|
|
|
55
55
|
|
|
56
56
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae V0.3.94 -->
|
|
57
57
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.tpl_namespace_root V0.3.14 -->
|
|
58
|
-
# base 0.3.
|
|
58
|
+
# base 0.3.42
|
|
59
59
|
|
|
60
60
|
[](
|
|
61
61
|
https://gitlab.com/ae-group/ae_base)
|
|
62
62
|
[](
|
|
64
|
+
https://gitlab.com/ae-group/ae_base/-/tree/release0.3.41)
|
|
65
65
|
[](
|
|
66
66
|
https://pypi.org/project/ae-base/#history)
|
|
67
67
|
|
|
68
|
-
>ae_base module 0.3.
|
|
68
|
+
>ae_base module 0.3.42.
|
|
69
69
|
|
|
70
70
|
[](
|
|
71
71
|
https://ae-group.gitlab.io/ae_base/coverage/index.html)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ae/base.py,sha256=cvkGRht-0pQXaokHocJ0h6P5mZOpkUR3JjG357rxyJU,57805
|
|
2
|
+
ae_base-0.3.42.dist-info/LICENSE.md,sha256=eHVr16LWo8bsm2NbdFOBcQp-F_3MUXo9I922sABpsMQ,35002
|
|
3
|
+
ae_base-0.3.42.dist-info/METADATA,sha256=ceQT7h6abqzZYIuaNnIY3EREiZ8rOlpR4qFiX-bn2EI,5311
|
|
4
|
+
ae_base-0.3.42.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
5
|
+
ae_base-0.3.42.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
+
ae_base-0.3.42.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
+
ae_base-0.3.42.dist-info/RECORD,,
|
ae_base-0.3.41.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
ae/base.py,sha256=9qixFzNhWVcGztz9Y7zv7vsQL485LEXH-IsfF61yo_M,56696
|
|
2
|
-
ae_base-0.3.41.dist-info/LICENSE.md,sha256=eHVr16LWo8bsm2NbdFOBcQp-F_3MUXo9I922sABpsMQ,35002
|
|
3
|
-
ae_base-0.3.41.dist-info/METADATA,sha256=pr0WsX0BOV067Vj5cxyfuWPNtr0rTHURIlRoacPaZe0,5311
|
|
4
|
-
ae_base-0.3.41.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
5
|
-
ae_base-0.3.41.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
-
ae_base-0.3.41.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
-
ae_base-0.3.41.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|