ae-base 0.3.43__tar.gz → 0.3.45__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.
- {ae_base-0.3.43/ae_base.egg-info → ae_base-0.3.45}/PKG-INFO +5 -5
- {ae_base-0.3.43 → ae_base-0.3.45}/README.md +4 -4
- {ae_base-0.3.43 → ae_base-0.3.45}/ae/base.py +16 -6
- {ae_base-0.3.43 → ae_base-0.3.45/ae_base.egg-info}/PKG-INFO +5 -5
- {ae_base-0.3.43 → ae_base-0.3.45}/tests/test_base.py +41 -6
- {ae_base-0.3.43 → ae_base-0.3.45}/LICENSE.md +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/ae_base.egg-info/SOURCES.txt +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/ae_base.egg-info/dependency_links.txt +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/ae_base.egg-info/requires.txt +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/ae_base.egg-info/top_level.txt +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/ae_base.egg-info/zip-safe +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/setup.cfg +0 -0
- {ae_base-0.3.43 → ae_base-0.3.45}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ae_base
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.45
|
|
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.45
|
|
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.44)
|
|
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.45.
|
|
69
69
|
|
|
70
70
|
[](
|
|
71
71
|
https://ae-group.gitlab.io/ae_base/coverage/index.html)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae V0.3.94 -->
|
|
2
2
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.tpl_namespace_root V0.3.14 -->
|
|
3
|
-
# base 0.3.
|
|
3
|
+
# base 0.3.45
|
|
4
4
|
|
|
5
5
|
[](
|
|
6
6
|
https://gitlab.com/ae-group/ae_base)
|
|
7
7
|
[](
|
|
9
|
+
https://gitlab.com/ae-group/ae_base/-/tree/release0.3.44)
|
|
10
10
|
[](
|
|
11
11
|
https://pypi.org/project/ae-base/#history)
|
|
12
12
|
|
|
13
|
-
>ae_base module 0.3.
|
|
13
|
+
>ae_base module 0.3.45.
|
|
14
14
|
|
|
15
15
|
[](
|
|
16
16
|
https://ae-group.gitlab.io/ae_base/coverage/index.html)
|
|
@@ -173,7 +173,7 @@ from types import ModuleType
|
|
|
173
173
|
from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Tuple, Union, cast
|
|
174
174
|
|
|
175
175
|
|
|
176
|
-
__version__ = '0.3.
|
|
176
|
+
__version__ = '0.3.45'
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
os_path_abspath = os.path.abspath
|
|
@@ -353,7 +353,6 @@ ASCII_UNICODE = (
|
|
|
353
353
|
(')', '⟯'), # U+27EF: MATHEMATICAL RIGHT FLATTENED PARENTHESIS
|
|
354
354
|
('[', '⟦'), # U+27E6: MATHEMATICAL LEFT WHITE SQUARE BRACKET
|
|
355
355
|
(']', '⟧'), # U+27E7: MATHEMATICAL RIGHT WHITE SQUARE BRACKET
|
|
356
|
-
('_', '𛲖'), # U+1BC96: Duployan Affix Low Line; '_' U+FF3F Fullwidth Low Line
|
|
357
356
|
('#', '﹟'), # U+FE5F: Small Number Sign
|
|
358
357
|
(';', '﹔'), # U+FE54: Small Semicolon
|
|
359
358
|
('@', '﹫'), # U+FE6B: Small Commercial At
|
|
@@ -364,10 +363,15 @@ ASCII_UNICODE = (
|
|
|
364
363
|
('%', '﹪'), # U+FE6A: Small Percent Sign
|
|
365
364
|
('^', '^'), # U+FF3E: Fullwidth Circumflex Accent
|
|
366
365
|
(',', '﹐'), # U+FE50: Small Comma
|
|
367
|
-
(' ', '
|
|
368
|
-
# '
|
|
369
|
-
# ' ' U+
|
|
366
|
+
(' ', '␣'), # U+2423: Open Box; more see underneath and https://unicode-explorer.com/articles/space-characters:
|
|
367
|
+
# ' ' U+00A0: No-Break Space (NBSP); '?¿?' U+1680 Ogham Space Mark; ' ' U+2000 En Quad;
|
|
368
|
+
# ' ' U+2001 Em Quad; ' ' U+2002 En Space; ' ' U+2003 Em Space; ' ' U+2004 Three-Per-Em
|
|
369
|
+
# ' ' U+2005 Four-Per-Em; ' ' U+2006 Six-Per-Em; ' ' U+2007 Figure Space;
|
|
370
|
+
# ' ' U+2008 Punctuation Space; ' ' U+2009 Thin; ' ' U+200A Hair Space;
|
|
371
|
+
# ' ' U+202F: Narrow No-Break Space (NNBSP); ' ' U+205F Medium Mathematical Space;
|
|
372
|
+
# '␠' U+2420 symbol for space; '␣' U+2423 Open Box; ' ' U+3000: Ideographic Space
|
|
370
373
|
(chr(127), '␡'), # U+2421: DELETE SYMBOL
|
|
374
|
+
# ('_', '𛲖'), # U+1BC96: Duployan Affix Low Line; '_' U+FF3F Fullwidth Low Line
|
|
371
375
|
)
|
|
372
376
|
""" transformation table of special ASCII to Unicode alternative character,
|
|
373
377
|
see https://www.compart.com/en/unicode/category/Po and https://xahlee.info/comp/unicode_naming_slash.html (http!) """
|
|
@@ -1092,7 +1096,8 @@ def utc_datetime() -> datetime.datetime:
|
|
|
1092
1096
|
return datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
|
|
1093
1097
|
|
|
1094
1098
|
|
|
1095
|
-
def write_file(file_path: str, content: Union[str, bytes],
|
|
1099
|
+
def write_file(file_path: str, content: Union[str, bytes],
|
|
1100
|
+
extra_mode: str = "", encoding: Optional[str] = None, make_dirs: bool = False):
|
|
1096
1101
|
""" (over)write the file specified by :paramref:`~write_file.file_path` with text or binary/bytes content.
|
|
1097
1102
|
|
|
1098
1103
|
:param file_path: file path/name to write the passed content into (overwriting any previous content!).
|
|
@@ -1105,6 +1110,8 @@ def write_file(file_path: str, content: Union[str, bytes], extra_mode: str = "",
|
|
|
1105
1110
|
be automatically added to the `mode` argument of :func:`open` (if not already specified
|
|
1106
1111
|
in this argument).
|
|
1107
1112
|
:param encoding: encoding used to write/convert/interpret the file content to write.
|
|
1113
|
+
:param make_dirs: pass True to automatically create not existing folders specified in
|
|
1114
|
+
:paramref:`~write_file.file_path`.
|
|
1108
1115
|
:raises FileExistsError: if file exists already and is write-protected.
|
|
1109
1116
|
:raises FileNotFoundError: if parts of the file path do not exist.
|
|
1110
1117
|
:raises OSError: if :paramref:`~write_file.file_path` is misspelled or contains invalid characters.
|
|
@@ -1120,6 +1127,9 @@ def write_file(file_path: str, content: Union[str, bytes], extra_mode: str = "",
|
|
|
1120
1127
|
for an intent result.
|
|
1121
1128
|
Related german docs: https://developer.android.com/training/data-storage/shared/media?hl=de
|
|
1122
1129
|
"""
|
|
1130
|
+
if make_dirs and (dir_path := os_path_dirname(file_path)):
|
|
1131
|
+
os.makedirs(dir_path, exist_ok=True)
|
|
1132
|
+
|
|
1123
1133
|
if isinstance(content, bytes) and 'b' not in extra_mode:
|
|
1124
1134
|
extra_mode += 'b'
|
|
1125
1135
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ae_base
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.45
|
|
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.45
|
|
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.44)
|
|
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.45.
|
|
69
69
|
|
|
70
70
|
[](
|
|
71
71
|
https://ae-group.gitlab.io/ae_base/coverage/index.html)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
""" ae.base unit tests """
|
|
2
2
|
import datetime
|
|
3
3
|
import os
|
|
4
|
+
import string
|
|
4
5
|
import tempfile
|
|
5
6
|
|
|
6
7
|
import pytest
|
|
@@ -27,8 +28,9 @@ from ae.base import (
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
tst_uri1 = "schema://user:pwd@domain/path_root/path_sub\\path+file% Üml?ä|ït.path_ext*\"<>|*'()[]{}#^;&=$,~" + chr(127)
|
|
30
|
-
tst_fna1 = "schema⫻user﹕pwd﹫domain⁄
|
|
31
|
-
|
|
31
|
+
tst_fna1 = "schema⫻user﹕pwd﹫domain⁄path_root⁄path_sub﹨path﹢file﹪␣Üml﹖ä।ït.path_ext﹡"⟨⟩।﹡‘⟮⟯⟦⟧{}﹟^﹔﹠﹦﹩﹐~␡"
|
|
32
|
+
tst_uri2 = "test control chars" + "".join(chr(_) for _ in range(1, 32))
|
|
33
|
+
tst_fna2 = "test␣control␣chars␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏␐␑␒␓␔␕␖␗␘␙␚␛␜␝␞␟"
|
|
32
34
|
|
|
33
35
|
env_var_name = 'env_var_nam1'
|
|
34
36
|
env_var_val = 'value of env var'
|
|
@@ -176,13 +178,17 @@ class TestBaseHelpers:
|
|
|
176
178
|
|
|
177
179
|
def test_dedefuse_file_name(self):
|
|
178
180
|
assert dedefuse(tst_fna1) == tst_uri1
|
|
179
|
-
assert
|
|
181
|
+
assert dedefuse(tst_fna2) == tst_uri2
|
|
180
182
|
|
|
181
|
-
assert dedefuse(defuse(
|
|
183
|
+
assert dedefuse(defuse(tst_uri1)) == tst_uri1
|
|
184
|
+
assert dedefuse(defuse(tst_uri2)) == tst_uri2
|
|
182
185
|
|
|
183
186
|
def test_defuse_file_name(self):
|
|
184
187
|
assert defuse(tst_uri1) == tst_fna1
|
|
185
|
-
assert
|
|
188
|
+
assert defuse(tst_uri2) == tst_fna2
|
|
189
|
+
|
|
190
|
+
assert defuse(dedefuse(tst_fna1)) == tst_fna1
|
|
191
|
+
assert defuse(dedefuse(tst_fna2)) == tst_fna2
|
|
186
192
|
|
|
187
193
|
def test_defuse_os_file_name(self):
|
|
188
194
|
try:
|
|
@@ -196,10 +202,18 @@ class TestBaseHelpers:
|
|
|
196
202
|
if os.path.exists(tst_fna2):
|
|
197
203
|
os.remove(tst_fna2)
|
|
198
204
|
|
|
199
|
-
def
|
|
205
|
+
def test_defuse_maps_integrity(self):
|
|
200
206
|
assert URI_SEP_CHAR not in UNICODE_TO_ASCII
|
|
201
207
|
assert len(UNICODE_TO_ASCII) == len(ASCII_TO_UNICODE) # check for duplicates in the ASCII_UNICODE map
|
|
202
208
|
|
|
209
|
+
def test_defuse_maps_not_touching_chars_allowed_as_slug_and_filename(self):
|
|
210
|
+
assert '-' not in ASCII_TO_UNICODE
|
|
211
|
+
assert '_' not in ASCII_TO_UNICODE
|
|
212
|
+
assert '.' not in ASCII_TO_UNICODE
|
|
213
|
+
assert '~' not in ASCII_TO_UNICODE
|
|
214
|
+
for char in string.ascii_letters + string.digits:
|
|
215
|
+
assert char not in ASCII_TO_UNICODE
|
|
216
|
+
|
|
203
217
|
def test_dummy_function(self):
|
|
204
218
|
assert dummy_function() is None
|
|
205
219
|
assert dummy_function(999, "any_args") is None
|
|
@@ -769,6 +783,27 @@ class TestBaseHelpers:
|
|
|
769
783
|
if os.path.exists(test_file):
|
|
770
784
|
os.remove(test_file)
|
|
771
785
|
|
|
786
|
+
def test_write_file_make_dirs(self):
|
|
787
|
+
root_dir = os.path.join(TESTS_FOLDER, 'root path of file')
|
|
788
|
+
test_dir = os.path.join(root_dir, '1st sub dir of file', 'subDir2')
|
|
789
|
+
test_file = os.path.join(test_dir, 'file in sub dir.ext')
|
|
790
|
+
content = "any content"
|
|
791
|
+
assert not os.path.exists(test_dir)
|
|
792
|
+
assert not os.path.exists(test_file)
|
|
793
|
+
try:
|
|
794
|
+
with pytest.raises(FileNotFoundError):
|
|
795
|
+
write_file(test_file, content)
|
|
796
|
+
write_file(test_file, content, make_dirs=True)
|
|
797
|
+
assert os.path.exists(test_dir)
|
|
798
|
+
assert os.path.isdir(test_dir)
|
|
799
|
+
assert os.path.exists(test_file)
|
|
800
|
+
assert os.path.isfile(test_file)
|
|
801
|
+
assert read_file(test_file) == content
|
|
802
|
+
|
|
803
|
+
finally:
|
|
804
|
+
if os.path.exists(root_dir):
|
|
805
|
+
shutil.rmtree(root_dir)
|
|
806
|
+
|
|
772
807
|
|
|
773
808
|
class TestModuleHelpers:
|
|
774
809
|
def test_module_attr_callable_with_args(self):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|