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 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.41'
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 = os.path.splitext(os.path.basename(path))[0]
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 = os.path.basename(path)
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 os.path.exists(BUILD_CONFIG_FILE):
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('.', os.path.sep)
421
- path += PY_EXT if os.path.isfile(path + PY_EXT) else os.path.sep + PY_INIT
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(os.path.dirname(os.path.abspath(file_name)))
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 = os.path.abspath(os.path.join(start_dir, DOTENV_FILE_NAME))
489
- if not os.path.isfile(file_path):
490
- file_path = os.path.join(os.path.dirname(start_dir), DOTENV_FILE_NAME)
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 os.path.isfile(file_path):
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 = os.path.join(os.path.dirname(os.path.dirname(file_path)), DOTENV_FILE_NAME)
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 = os.path.expanduser(path)
644
+ path = os_path_expanduser(path)
624
645
 
625
646
  if remove_dots:
626
- path = os.path.normpath(path)
647
+ path = os_path_normpath(path)
627
648
 
628
649
  if resolve_sym_links:
629
- path = os.path.realpath(path)
650
+ path = os_path_realpath(path)
630
651
  elif make_absolute:
631
- path = os.path.abspath(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 = os.path.expanduser(remove_base_path)
636
- path = os.path.relpath(path, remove_base_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 os.path.basename(project_path) != project_name:
779
- module_paths.append(join(os.path.dirname(project_path), project_name, *namespace_dirs))
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(join(project_path, *namespace_dirs))
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 = join(module_path, *path_parts)
787
- if os.path.isfile(main_file):
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:`~stack_var.find_name` get not passed then the
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 passed as string or list of line strings (will be
1024
- concatenated with the line separator of the current OS: os.linesep).
1025
- :param extra_mode: open mode flag characters. passed unchanged to the `mode` argument of :func:`open` if
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:`~read_file.file_path` is misspelled or contains invalid characters.
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
- with open(file_path, ('' if extra_mode.startswith('a') else 'w') + extra_mode, encoding=encoding) as file_handle:
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 os.path.exists(BUILD_CONFIG_FILE): # pragma: no cover
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 os.path.basename(_importing_package) in (PY_INIT, PY_MAIN):
1080
- _importing_package = os.path.dirname(_importing_package)
1081
- _importing_package = os.path.splitext(os.path.basename(_importing_package))[0]
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.41
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.41
58
+ # base 0.3.42
59
59
 
60
60
  [![GitLab develop](https://img.shields.io/gitlab/pipeline/ae-group/ae_base/develop?logo=python)](
61
61
  https://gitlab.com/ae-group/ae_base)
62
62
  [![LatestPyPIrelease](
63
- https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.40?logo=python)](
64
- https://gitlab.com/ae-group/ae_base/-/tree/release0.3.40)
63
+ https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.41?logo=python)](
64
+ https://gitlab.com/ae-group/ae_base/-/tree/release0.3.41)
65
65
  [![PyPIVersions](https://img.shields.io/pypi/v/ae_base)](
66
66
  https://pypi.org/project/ae-base/#history)
67
67
 
68
- >ae_base module 0.3.41.
68
+ >ae_base module 0.3.42.
69
69
 
70
70
  [![Coverage](https://ae-group.gitlab.io/ae_base/coverage.svg)](
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,,
@@ -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,,