ae-base 0.3.71__py3-none-any.whl → 0.3.73__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 +119 -48
- {ae_base-0.3.71.dist-info → ae_base-0.3.73.dist-info}/METADATA +8 -8
- ae_base-0.3.73.dist-info/RECORD +7 -0
- {ae_base-0.3.71.dist-info → ae_base-0.3.73.dist-info}/licenses/LICENSE.md +1 -1
- ae_base-0.3.71.dist-info/RECORD +0 -7
- {ae_base-0.3.71.dist-info → ae_base-0.3.73.dist-info}/WHEEL +0 -0
- {ae_base-0.3.71.dist-info → ae_base-0.3.73.dist-info}/top_level.txt +0 -0
- {ae_base-0.3.71.dist-info → ae_base-0.3.73.dist-info}/zip-safe +0 -0
ae/base.py
CHANGED
|
@@ -44,6 +44,7 @@ inspect the operating system and manage environment variables.
|
|
|
44
44
|
OS information
|
|
45
45
|
^^^^^^^^^^^^^^
|
|
46
46
|
|
|
47
|
+
* :func:`on_ci_host`: detects if it is running on the CI of a Git repository server (GitHub or GitLab).
|
|
47
48
|
* :data:`os_platform`: a string identifying the operating system (e.g., 'linux', 'win32', 'android', 'ios').
|
|
48
49
|
* :data:`os_device_id`: a string with the ID/name of the device.
|
|
49
50
|
* :func:`os_host_name`: determines the operating system's host/machine name.
|
|
@@ -58,10 +59,11 @@ environment variables & `.env` files
|
|
|
58
59
|
* :func:`env_str`: retrieves the string value of an OS environment variable, with an option to automatically convert the
|
|
59
60
|
variable name to the conventional format.
|
|
60
61
|
* :func:`parse_dotenv`: parses a `.env` file and returns its key-value pairs as a dictionary.
|
|
61
|
-
* :func:`
|
|
62
|
-
variables.
|
|
62
|
+
* :func:`late_env_var_resolver`: substitutes environment variables within the value of other environment variables.
|
|
63
63
|
* :func:`load_dotenvs`: detects and loads all relevant `.env` files from the current working directory and optional
|
|
64
64
|
also from the main module's path.
|
|
65
|
+
* :func:`load_env_var_defaults`: recursively searches parent directories for `.env` files and loads any undeclared
|
|
66
|
+
variables.
|
|
65
67
|
|
|
66
68
|
|
|
67
69
|
data structure utilities
|
|
@@ -243,10 +245,10 @@ from urllib.error import HTTPError, URLError
|
|
|
243
245
|
from urllib.parse import urlparse, urlunparse
|
|
244
246
|
from urllib.request import Request, urlopen
|
|
245
247
|
from types import ModuleType
|
|
246
|
-
from typing import Any, Callable, Generator, Iterable, MutableMapping, Optional, Union, cast
|
|
248
|
+
from typing import Any, Callable, Container, Generator, Iterable, MutableMapping, Optional, Union, cast
|
|
247
249
|
|
|
248
250
|
|
|
249
|
-
__version__ = '0.3.
|
|
251
|
+
__version__ = '0.3.73'
|
|
250
252
|
|
|
251
253
|
|
|
252
254
|
os_path_abspath = os.path.abspath
|
|
@@ -290,41 +292,45 @@ DEF_ENCODING = 'ascii'
|
|
|
290
292
|
"""
|
|
291
293
|
|
|
292
294
|
DOTENV_FILE_NAME = '.env' #: name of the file containing console/shell environment variables
|
|
293
|
-
|
|
295
|
+
DOTENV_LINE_MATCHER = re.compile(r"""
|
|
294
296
|
^
|
|
295
|
-
(?:export\s+)?
|
|
296
|
-
([\w.]+)
|
|
297
|
-
(?:\s*=\s*|:\s+?)
|
|
298
|
-
(
|
|
299
|
-
'(?:\'|[^'])*'
|
|
300
|
-
|
|
|
301
|
-
"(?:\"|[^"])*"
|
|
302
|
-
|
|
|
303
|
-
[^#\n]+
|
|
304
|
-
)?
|
|
305
|
-
(?:\s*\#.*)?
|
|
297
|
+
(?:export\s+)? # optional export
|
|
298
|
+
([\w.]+) # env variable name
|
|
299
|
+
(?:\s*=\s*|:\s+?) # separator
|
|
300
|
+
( # optional value begin
|
|
301
|
+
'(?:\'|[^'])*' # single quoted value
|
|
302
|
+
| # or
|
|
303
|
+
"(?:\"|[^"])*" # double quoted value
|
|
304
|
+
| # or
|
|
305
|
+
[^#\n]+ # unquoted value
|
|
306
|
+
)? # value end
|
|
307
|
+
(?:\s*\#.*)? # optional comment
|
|
306
308
|
$
|
|
307
309
|
""", re.VERBOSE)
|
|
308
|
-
|
|
309
|
-
(\\)?
|
|
310
|
-
(\$)
|
|
311
|
-
(
|
|
312
|
-
\{?
|
|
313
|
-
([A-
|
|
314
|
-
}?
|
|
315
|
-
)
|
|
310
|
+
DOTENV_VAR_IN_VAL_MATCHER = re.compile(r"""
|
|
311
|
+
(\\)? # is it escaped with a backslash? (env variable name matcher groups item 0 | evn_groups[0])
|
|
312
|
+
(\$) # literal $ (matcher evn_groups[1])
|
|
313
|
+
( # group for easier subsitution via evn_groups[0:-1] (matcher evn_groups[2])
|
|
314
|
+
\{? # allow brace wrapping
|
|
315
|
+
([A-Za-z0-9_]+) # match var name; allowing lowercase letters in env var names (matcher evn_groups[3|-1]
|
|
316
|
+
}? # closing brace
|
|
317
|
+
) # braces end
|
|
316
318
|
""", re.IGNORECASE | re.VERBOSE)
|
|
317
319
|
|
|
320
|
+
EnvVarsType = MutableMapping[str, str] #: environment variables dict/mapping
|
|
321
|
+
EnvVarsLateResolvedType = dict[str, list[tuple[str, str, str, str]]] #: mapping of DOTENV_VAR_IN_VAL_MATCHER results
|
|
318
322
|
|
|
319
323
|
NAME_PARTS_SEP = '_' #: name parts separator character, e.g. for :func:`norm_name`
|
|
320
324
|
|
|
321
325
|
NOW_STR_FORMAT = "{sep}%Y%m%d{sep}%H%M%S{sep}%f" #: timestamp format of :func:`now_str`
|
|
322
326
|
|
|
323
|
-
SKIPPED_MODULES = ('ae.base', 'ae.
|
|
327
|
+
SKIPPED_MODULES = ('ae.base', 'ae.files', 'ae.paths', 'ae.dynamicod',
|
|
328
|
+
'ae.core', 'ae.console', 'ae.snell', 'ae.templates', 'ae.dev_ops',
|
|
324
329
|
'ae.gui', 'ae.gui.app', 'ae.gui.tours', 'ae.gui.utils',
|
|
325
330
|
'ae.kivy', 'ae.kivy.apps', 'ae.kivy.behaviors', 'ae.kivy.i18n', 'ae.kivy.tours', 'ae.kivy.widgets',
|
|
326
|
-
'ae.enaml_app', 'ae.
|
|
327
|
-
'ae.qpython_app', 'ae.appjar_app',
|
|
331
|
+
'ae.enaml_app', 'ae.toga_app', 'ae.pyglet_app', 'ae.pygobject_app', 'ae.dabo_app',
|
|
332
|
+
'ae.qpython_app', 'ae.appjar_app',
|
|
333
|
+
'importlib._bootstrap', 'importlib._bootstrap_external')
|
|
328
334
|
""" skipped modules used as default by :func:`module_name`, :func:`stack_var` and :func:`stack_vars` """
|
|
329
335
|
|
|
330
336
|
|
|
@@ -723,6 +729,51 @@ def in_wd(new_cwd: str) -> Generator[None, None, None]:
|
|
|
723
729
|
os.chdir(cur_dir)
|
|
724
730
|
|
|
725
731
|
|
|
732
|
+
def late_env_var_resolver(env_vars: EnvVarsType, loaded_vars: EnvVarsType, late_resolved: EnvVarsLateResolvedType):
|
|
733
|
+
""" late resolve/expand/substitute of env variables in env var values.
|
|
734
|
+
|
|
735
|
+
:param env_vars: all cached environment variables (preferred to os.environ), will get substituted.
|
|
736
|
+
also used to search&resolve env var values (if not found then searched in os.environ).
|
|
737
|
+
:param loaded_vars: recently loaded environment variables, will get substituted.
|
|
738
|
+
:param late_resolved: matches of loaded env vars to be resolve late (after all env vars got detected and
|
|
739
|
+
loaded). the key of this dict is the name of the env variable which has other env vars
|
|
740
|
+
in its values to be resolved/substituted. the item value of this dict is a list of
|
|
741
|
+
matcher group tuples for each found env variable. the group/tuple items are
|
|
742
|
+
(0) escape character, (1) the dollar character, (2) the env var name literal (optionally
|
|
743
|
+
in curly brackets) and (3/-1) the env var name.
|
|
744
|
+
"""
|
|
745
|
+
retries = len(late_resolved) # retry if later-/not-yet-replaced env var in env var value
|
|
746
|
+
while late_resolved and retries: # pylint: disable=too-many-nested-blocks
|
|
747
|
+
for var_nam, matches in late_resolved.copy().items():
|
|
748
|
+
# substitute declared and not escaped env variables found via :data:`DOTENV_VAR_IN_VAL_MATCHER` in a value
|
|
749
|
+
for evn_groups in matches.copy(): # try to replace env vars with its values, removed from matches
|
|
750
|
+
if evn_groups[0] == '\\': # if escaped '$' character
|
|
751
|
+
replace: Optional[str] = "".join(evn_groups[1:-1]) # then only unescape (no var search&substitute)
|
|
752
|
+
elif (replace := env_vars.get(evn_groups[-1])) is None:
|
|
753
|
+
replace = os.environ.get(evn_groups[-1])
|
|
754
|
+
|
|
755
|
+
if replace is not None:
|
|
756
|
+
var_val = loaded_vars[var_nam]
|
|
757
|
+
env_vars[var_nam] = loaded_vars[var_nam] = var_val.replace("".join(evn_groups[0:-1]), replace)
|
|
758
|
+
matches.remove(evn_groups)
|
|
759
|
+
if replacement_matches := DOTENV_VAR_IN_VAL_MATCHER.findall(replace):
|
|
760
|
+
if any(_[-1] == var_nam for _ in replacement_matches):
|
|
761
|
+
warnings.warn(f" ## ignoring recursive environment variable {var_nam} ({var_val=})")
|
|
762
|
+
replacement_matches = [_ for _ in replacement_matches if _[-1] != var_nam]
|
|
763
|
+
matches.extend(replacement_matches) # extend matches with env vars in replaced var value
|
|
764
|
+
retries += len(replacement_matches)
|
|
765
|
+
|
|
766
|
+
if not matches:
|
|
767
|
+
late_resolved.pop(var_nam)
|
|
768
|
+
|
|
769
|
+
retries -= 1
|
|
770
|
+
|
|
771
|
+
for var_nam, matches in late_resolved.items():
|
|
772
|
+
warnings.warn(f" ## {var_nam=} has unresolved environment variables in its value: {[_[-1] for _ in matches]}"
|
|
773
|
+
f"; env_vars['{var_nam}']={env_vars.get(var_nam, 'not in dict')}"
|
|
774
|
+
f" loaded_vars['{var_nam}']={loaded_vars.get(var_nam, 'not in dict')}")
|
|
775
|
+
|
|
776
|
+
|
|
726
777
|
def load_dotenvs(from_module_path: bool = False):
|
|
727
778
|
""" detect and load not defined OS environment variables from ``.env`` files.
|
|
728
779
|
|
|
@@ -746,7 +797,7 @@ def load_dotenvs(from_module_path: bool = False):
|
|
|
746
797
|
load_env_var_defaults(os_path_dirname(os_path_abspath(file_name)), env_vars)
|
|
747
798
|
|
|
748
799
|
|
|
749
|
-
def load_env_var_defaults(start_dir: str, env_vars:
|
|
800
|
+
def load_env_var_defaults(start_dir: str, env_vars: EnvVarsType) -> EnvVarsType:
|
|
750
801
|
""" load undeclared env var defaults from a chain of ``.env`` files starting in the specified folder or its parent.
|
|
751
802
|
|
|
752
803
|
:param start_dir: folder to start search of an ``.env`` file, if not found, then also checks the parent
|
|
@@ -758,7 +809,7 @@ def load_env_var_defaults(start_dir: str, env_vars: MutableMapping[str, str]) ->
|
|
|
758
809
|
:param env_vars: environment variables mapping to be amended with env variable values from any
|
|
759
810
|
found ``.env`` file. pass Python's :data:`os.environ` to amend this mapping directly
|
|
760
811
|
with all the already not declared environment variables.
|
|
761
|
-
:return:
|
|
812
|
+
:return: env var names (keys) and values added to :paramref:`~load_env_var_defaults.env_vars`.
|
|
762
813
|
"""
|
|
763
814
|
start_dir = norm_path(start_dir)
|
|
764
815
|
file_path = os_path_join(start_dir, DOTENV_FILE_NAME)
|
|
@@ -766,15 +817,17 @@ def load_env_var_defaults(start_dir: str, env_vars: MutableMapping[str, str]) ->
|
|
|
766
817
|
file_path = os_path_join(os_path_dirname(start_dir), DOTENV_FILE_NAME)
|
|
767
818
|
|
|
768
819
|
loaded_vars = {}
|
|
820
|
+
late_resolved: EnvVarsLateResolvedType = {}
|
|
769
821
|
while os_path_isfile(file_path):
|
|
770
|
-
for var_nam, var_val in parse_dotenv(file_path).items():
|
|
771
|
-
|
|
772
|
-
env_vars[var_nam] = loaded_vars[var_nam] = var_val
|
|
822
|
+
for var_nam, var_val in parse_dotenv(file_path, late_resolved, exclude_vars=env_vars).items():
|
|
823
|
+
env_vars[var_nam] = loaded_vars[var_nam] = var_val
|
|
773
824
|
|
|
774
825
|
if os.sep not in file_path:
|
|
775
826
|
break # pragma: no cover # prevent endless-loop for ``.env`` file in root dir (os.sep == '/')
|
|
776
827
|
file_path = os_path_join(os_path_dirname(os_path_dirname(file_path)), DOTENV_FILE_NAME)
|
|
777
828
|
|
|
829
|
+
late_env_var_resolver(env_vars, loaded_vars, late_resolved)
|
|
830
|
+
|
|
778
831
|
return loaded_vars
|
|
779
832
|
|
|
780
833
|
|
|
@@ -967,6 +1020,16 @@ def now_str(sep: str = "") -> str:
|
|
|
967
1020
|
return utc_datetime().strftime(NOW_STR_FORMAT.format(sep=sep))
|
|
968
1021
|
|
|
969
1022
|
|
|
1023
|
+
def on_ci_host() -> bool:
|
|
1024
|
+
""" check and return True if it is running on the GitLab/GitHub CI host/server.
|
|
1025
|
+
|
|
1026
|
+
:return: True if running on CI host, else False.
|
|
1027
|
+
|
|
1028
|
+
.. note:: env vars always available: 'CI' on GitHub (Pre-pipeline); 'CI_PROJECT_ID' (internal ProjectId) on GitLab
|
|
1029
|
+
"""
|
|
1030
|
+
return 'CI' in os.environ or 'CI_PROJECT_ID' in os.environ
|
|
1031
|
+
|
|
1032
|
+
|
|
970
1033
|
def os_host_name() -> str:
|
|
971
1034
|
""" determine the operating system host/machine name.
|
|
972
1035
|
|
|
@@ -1042,21 +1105,34 @@ def os_user_name() -> str:
|
|
|
1042
1105
|
return getpass.getuser()
|
|
1043
1106
|
|
|
1044
1107
|
|
|
1045
|
-
def parse_dotenv(file_path: str
|
|
1108
|
+
def parse_dotenv(file_path: str, late_resolved: EnvVarsLateResolvedType, exclude_vars: Container = ()) -> EnvVarsType:
|
|
1046
1109
|
""" parse ``.env`` file content and return environment variable names as dict keys and values as dict values.
|
|
1047
1110
|
|
|
1048
1111
|
:param file_path: string with the name/path of an existing ``.env``/:data:`DOTENV_FILE_NAME` file.
|
|
1049
|
-
:
|
|
1112
|
+
:param late_resolved: mapping extended with matches of env vars found in the returned env var values.
|
|
1113
|
+
:param exclude_vars: names of env vars to preserve their value (do not return).
|
|
1114
|
+
:return: mapping with parsed environment variable names and values.
|
|
1050
1115
|
"""
|
|
1051
|
-
|
|
1116
|
+
lines = [] # unwrap multi-line .env variable values with backslash at line end (Docker/UNIX-style format)
|
|
1117
|
+
prev_lines = ""
|
|
1052
1118
|
for line in cast(str, read_file(file_path)).splitlines():
|
|
1053
|
-
|
|
1119
|
+
if line.endswith('\\'):
|
|
1120
|
+
prev_lines += line[:-1]
|
|
1121
|
+
continue
|
|
1122
|
+
lines.append(prev_lines + line)
|
|
1123
|
+
prev_lines = ""
|
|
1124
|
+
|
|
1125
|
+
env_vars: EnvVarsType = {}
|
|
1126
|
+
for line in lines:
|
|
1127
|
+
match = DOTENV_LINE_MATCHER.search(line)
|
|
1054
1128
|
if not match:
|
|
1055
1129
|
if not re.search(r'^\s*(?:#.*)?$', line): # not comment or blank
|
|
1056
1130
|
warnings.warn(f"'{line!r}' in '{file_path}' doesn't match {DOTENV_FILE_NAME} format", SyntaxWarning)
|
|
1057
1131
|
continue
|
|
1058
1132
|
|
|
1059
1133
|
var_nam, var_val = match.groups()
|
|
1134
|
+
if var_nam in exclude_vars:
|
|
1135
|
+
continue
|
|
1060
1136
|
var_val = "" if var_val is None else var_val.strip()
|
|
1061
1137
|
|
|
1062
1138
|
# remove surrounding quotes, unescape all chars except $ so variables can be escaped properly
|
|
@@ -1067,13 +1143,9 @@ def parse_dotenv(file_path: str) -> dict[str, str]:
|
|
|
1067
1143
|
var_val = re.sub(r'\\([^$])', r'\1', var_val)
|
|
1068
1144
|
else:
|
|
1069
1145
|
delimiter = None
|
|
1070
|
-
if delimiter != "'":
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
if parts[0] == '\\' or (replace := env_vars.get(parts[-1], os.environ.get(parts[-1], UNSET))) is UNSET:
|
|
1074
|
-
replace = "".join(parts[1:-1]) # don't replace escaped/undeclared vars to prevent value cut at '$'
|
|
1075
|
-
|
|
1076
|
-
var_val = var_val.replace("".join(parts[0:-1]), cast(str, replace))
|
|
1146
|
+
if delimiter != "'": # https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Single-Quotes
|
|
1147
|
+
if matches := DOTENV_VAR_IN_VAL_MATCHER.findall(var_val):
|
|
1148
|
+
late_resolved[var_nam] = matches
|
|
1077
1149
|
|
|
1078
1150
|
env_vars[var_nam] = var_val
|
|
1079
1151
|
|
|
@@ -1283,7 +1355,7 @@ def sys_env_dict() -> dict[str, Any]:
|
|
|
1283
1355
|
|
|
1284
1356
|
|
|
1285
1357
|
def sys_env_text(ind_ch: str = " ", ind_len: int = 12, key_ch: str = "=", key_len: int = 15,
|
|
1286
|
-
extra_sys_env_dict: Optional[
|
|
1358
|
+
extra_sys_env_dict: Optional[EnvVarsType] = None) -> str:
|
|
1287
1359
|
""" compile a formatted text block with system environment info.
|
|
1288
1360
|
|
|
1289
1361
|
:param ind_ch: indent character (defaults to " ").
|
|
@@ -1327,7 +1399,8 @@ def url_failure(url: str, token: str = "", username: str = "", password: str = "
|
|
|
1327
1399
|
:param username: optional username to authenticate (for HTTPS, together with the password argument).
|
|
1328
1400
|
:param password: optional password to authenticate (for HTTPS, together with the username argument).
|
|
1329
1401
|
:param git_repo: optimized check for Git repository HTTP servers/sites (like GitHub, GitLab, Bitbucket,
|
|
1330
|
-
Gitea, SourceHut, Mercury, etc. as long as they implement Smart HTTP).
|
|
1402
|
+
Gitea, SourceHut, Mercury, etc. as long as they implement Smart HTTP). if specified
|
|
1403
|
+
then the :paramref:`~url_failure.url` has to point to a repository.
|
|
1331
1404
|
:param timeout: connection timeout in seconds (see :func:`urllib.request.urlopen`).
|
|
1332
1405
|
:return: empty string if target header is available, else an error description. if an
|
|
1333
1406
|
FTP|HTTP response error occurred then the error/status code
|
|
@@ -1449,9 +1522,7 @@ class ErrorMsgMixin: # pylint: di
|
|
|
1449
1522
|
|
|
1450
1523
|
except (ImportError, AssertionError, Exception) as exc: # pylint: disable=broad-except
|
|
1451
1524
|
print(f"{self.__class__.__name__}.__init__() raised {exc}; using print() instead of main app error loggers")
|
|
1452
|
-
|
|
1453
|
-
# self.main_app = None
|
|
1454
|
-
# self.po = self.dpo = self.vpo = print
|
|
1525
|
+
# fallbacks assigned as/in class attributes: self.main_app = None; self.po = self.dpo = self.vpo = print
|
|
1455
1526
|
|
|
1456
1527
|
@property
|
|
1457
1528
|
def error_message(self) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ae_base
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.73
|
|
4
4
|
Summary: ae namespace module portion base: basic constants, helper functions and context managers
|
|
5
5
|
Home-page: https://gitlab.com/ae-group/ae_base
|
|
6
6
|
Author: AndiEcker
|
|
@@ -27,7 +27,7 @@ Requires-Dist: aedev_project_tpls; extra == "dev"
|
|
|
27
27
|
Requires-Dist: ae_ae; extra == "dev"
|
|
28
28
|
Requires-Dist: anybadge; extra == "dev"
|
|
29
29
|
Requires-Dist: coverage-badge; extra == "dev"
|
|
30
|
-
Requires-Dist:
|
|
30
|
+
Requires-Dist: aedev_project_manager; extra == "dev"
|
|
31
31
|
Requires-Dist: flake8; extra == "dev"
|
|
32
32
|
Requires-Dist: mypy; extra == "dev"
|
|
33
33
|
Requires-Dist: pylint; extra == "dev"
|
|
@@ -40,7 +40,7 @@ Provides-Extra: docs
|
|
|
40
40
|
Provides-Extra: tests
|
|
41
41
|
Requires-Dist: anybadge; extra == "tests"
|
|
42
42
|
Requires-Dist: coverage-badge; extra == "tests"
|
|
43
|
-
Requires-Dist:
|
|
43
|
+
Requires-Dist: aedev_project_manager; extra == "tests"
|
|
44
44
|
Requires-Dist: flake8; extra == "tests"
|
|
45
45
|
Requires-Dist: mypy; extra == "tests"
|
|
46
46
|
Requires-Dist: pylint; extra == "tests"
|
|
@@ -63,15 +63,15 @@ Dynamic: provides-extra
|
|
|
63
63
|
Dynamic: requires-python
|
|
64
64
|
Dynamic: summary
|
|
65
65
|
|
|
66
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.
|
|
67
|
-
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.
|
|
68
|
-
# base 0.3.
|
|
66
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.100 -->
|
|
67
|
+
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.21 -->
|
|
68
|
+
# base 0.3.73
|
|
69
69
|
|
|
70
70
|
[](
|
|
71
71
|
https://gitlab.com/ae-group/ae_base)
|
|
72
72
|
[](
|
|
74
|
+
https://gitlab.com/ae-group/ae_base/-/tree/release0.3.73)
|
|
75
75
|
[](
|
|
76
76
|
https://pypi.org/project/ae-base/#history)
|
|
77
77
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ae/base.py,sha256=jzWVdtMEAwbyEBeMEEblWPXOxRKxAa-VXMcHWvHkk4Q,84067
|
|
2
|
+
ae_base-0.3.73.dist-info/licenses/LICENSE.md,sha256=yRfpmSMzp1Wptz3JUTguKtnRFEICTd2wWrpteTz9fUI,35003
|
|
3
|
+
ae_base-0.3.73.dist-info/METADATA,sha256=mf0vHJ_i_dDJAZDLqv9z5aPVB1Ye879dzYqojT5_0dA,5469
|
|
4
|
+
ae_base-0.3.73.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
+
ae_base-0.3.73.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
+
ae_base-0.3.73.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
+
ae_base-0.3.73.dist-info/RECORD,,
|
ae_base-0.3.71.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
ae/base.py,sha256=_bOfJ1OGOPYqGfPzX5_AyjS_0GVQqQa_dyPfL5l7820,78906
|
|
2
|
-
ae_base-0.3.71.dist-info/licenses/LICENSE.md,sha256=0g3tHWG2bfmLGyuM0e0YzSXT8As8eN1b0VQIqXMWTMg,35003
|
|
3
|
-
ae_base-0.3.71.dist-info/METADATA,sha256=1u-ON7hlDqyVq-JiYQ4ikI-7FmasQrP3PQAc-m1eHpc,5470
|
|
4
|
-
ae_base-0.3.71.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
5
|
-
ae_base-0.3.71.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
-
ae_base-0.3.71.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
-
ae_base-0.3.71.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|