ae-base 0.3.42__py3-none-any.whl → 0.3.43__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
@@ -46,8 +46,9 @@ the function :func:`duplicates` returns the duplicates of an iterable type.
46
46
  to normalize a file path, in order to remove `.`, `..` placeholders, to resolve symbolic links or to make it relative or
47
47
  absolute, call the function :func:`norm_path`.
48
48
 
49
- :func:`uri2filename` converts special characters of a URI/URL resulting in a string that can be used as a file name.
50
- use the function :func:`filename2uri` to convert this string back to the corresponding URL/URI.
49
+ :func:`defuse` converts special characters of a URI/URL or a file path string, resulting in a string that can be used
50
+ either as a URL slug or as a file name. use the function :func:`dedefuse` to convert this string back to the
51
+ corresponding URL/URI or file path.
51
52
 
52
53
  :func:`camel_to_snake` and :func:`snake_to_camel` providing name conversions of class and method names.
53
54
 
@@ -162,7 +163,6 @@ import shutil
162
163
  import socket
163
164
  import sys
164
165
  import unicodedata
165
- import urllib.parse
166
166
  import warnings
167
167
 
168
168
  from configparser import ConfigParser, ExtendedInterpolation
@@ -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.42'
176
+ __version__ = '0.3.43'
177
177
 
178
178
 
179
179
  os_path_abspath = os.path.abspath
@@ -336,6 +336,96 @@ def deep_dict_update(data: dict, update: dict):
336
336
  data[upd_key] = upd_val
337
337
 
338
338
 
339
+ URI_SEP_CHAR = '⫻' # U+2AFB: TRIPLE SOLIDUS BINARY RELATION
340
+ ASCII_UNICODE = (
341
+ ('/', '⁄'), # U+2044: Fraction Slash; '∕' U+2215: Division Slash; '⧸' U+29F8: Big Solidus
342
+ # ; '╱' U+FF0F: Fullwidth Solidus; '╱' U+2571: Box Drawings Light Diagonal Upper Right to Lower Left
343
+ ('|', '।'), # U+0964: Devanagari Danda
344
+ ('\\', '﹨'), # U+FE68: SMALL REVERSE SOLIDUS; '⑊' U+244A OCR DOUBLE BACKSLASH; '⧵' U+29F5 REV. SOLIDUS OPERATOR
345
+ (':', '﹕'), # U+FE55: Small Colon
346
+ ('*', '﹡'), # U+FE61: Small Asterisk
347
+ ('?', '﹖'), # U+FE56: Small Question Mark
348
+ ('"', '"'), # U+FF02: Fullwidth Quotation Mark
349
+ ("'", '‘'), # U+2018: Left Single; '’' U+2019: Right Single; '‛' U+201B: Single High-Reversed-9 Quotation Mark
350
+ ('<', '⟨'), # U+27E8: LEFT ANGLE BRACKET; '‹' U+2039: Single Left-Pointing Angle Quotation Mark
351
+ ('>', '⟩'), # U+27E9: RIGHT ANGLE BRACKET; '›' U+203A: Single Right-Pointing Angle Quotation Mark
352
+ ('(', '⟮'), # U+27EE: MATHEMATICAL LEFT FLATTENED PARENTHESIS
353
+ (')', '⟯'), # U+27EF: MATHEMATICAL RIGHT FLATTENED PARENTHESIS
354
+ ('[', '⟦'), # U+27E6: MATHEMATICAL LEFT WHITE SQUARE BRACKET
355
+ (']', '⟧'), # U+27E7: MATHEMATICAL RIGHT WHITE SQUARE BRACKET
356
+ ('_', '𛲖'), # U+1BC96: Duployan Affix Low Line; '_' U+FF3F Fullwidth Low Line
357
+ ('#', '﹟'), # U+FE5F: Small Number Sign
358
+ (';', '﹔'), # U+FE54: Small Semicolon
359
+ ('@', '﹫'), # U+FE6B: Small Commercial At
360
+ ('&', '﹠'), # U+FE60: Small Ampersand
361
+ ('=', '﹦'), # U+FE66: Small Equals Sign
362
+ ('+', '﹢'), # U+FE62: Small Plus Sign
363
+ ('$', '﹩'), # U+FE69: Small Dollar Sign
364
+ ('%', '﹪'), # U+FE6A: Small Percent Sign
365
+ ('^', '^'), # U+FF3E: Fullwidth Circumflex Accent
366
+ (',', '﹐'), # U+FE50: Small Comma
367
+ (' ', ' '), # U+3000: Ideographic Space; ' ' U+200A Hair Space; ' ' U+2007 Figure Space;
368
+ # ' ' U+2009 Thin; ' ' U+2003 Em Space; ' ' U+2002 En Space; ' ' U+2008 Punctuation Space
369
+ # ' ' U+00A0: No-Break Space (NBSP); ' ' U+202F: Narrow No-Break Space (NNBSP)
370
+ (chr(127), '␡'), # U+2421: DELETE SYMBOL
371
+ )
372
+ """ transformation table of special ASCII to Unicode alternative character,
373
+ see https://www.compart.com/en/unicode/category/Po and https://xahlee.info/comp/unicode_naming_slash.html (http!) """
374
+
375
+ ASCII_TO_UNICODE = dict(ASCII_UNICODE) #: map to convert ASCII to an alternative defused Unicode character
376
+ UNICODE_TO_ASCII = {unicode_char: ascii_char for ascii_char, unicode_char in ASCII_UNICODE} #: Unicode to ASCII map
377
+
378
+
379
+ def dedefuse(value: str) -> str:
380
+ """ convert a string that got defused with :func:`defuse` back to its original form.
381
+
382
+ :param value: string defused with the function :func:`defuse`.
383
+ :return: re-activated form of the string (with all ASCII special characters recovered).
384
+ """
385
+ original = ""
386
+ for char in value:
387
+ if char in UNICODE_TO_ASCII:
388
+ char = UNICODE_TO_ASCII[char]
389
+ elif 0x2400 <= (code := ord(char)) <= 0x241F:
390
+ char = chr(code - 0x2400)
391
+ original += char
392
+
393
+ return original.replace(URI_SEP_CHAR, '://')
394
+
395
+
396
+ def defuse(value: str) -> str:
397
+ """ convert a file path or a URI into a defused/presentational form to be usable as URL slug or file/folder name.
398
+
399
+ :param value: any string to defuse (replace special chars with Unicode alternatives).
400
+ :return: string with its special characters replaced by its pure presentational alternatives.
401
+
402
+ the ASCII character range 0..31 gets converted to the Unicode range U+2400 + ord(char): 0==U+2400 ... 31==U+241F.
403
+
404
+ in *nix only / and \0 are not allowed characters in file names.
405
+
406
+ in MS Windows are not allowed: ASCII 0...31): / | \\ : * ? ” % < > ( ). some blogs recommend to also not allow
407
+ (convert) the characters # and '.
408
+ only old POSIX seems to be even more restricted (only allowing alphanumeric characters plus . - and _).
409
+
410
+ more on allowed characters in file names in the answers of RedGrittyBrick on https://superuser.com/questions/358855
411
+ and of Christopher Oezbek on https://stackoverflow.com/questions/1976007.
412
+
413
+ file name length is not restricted/shortened by this function, although the maximum is 255 characters on most OSs.
414
+
415
+ .. hint:: use :func:`dedefuse` to convert the defused string back to the corresponding URI/file-path.
416
+
417
+ """
418
+ defused = ""
419
+ value = value.replace('://', URI_SEP_CHAR) # make URIs shorter
420
+ for char in value:
421
+ if char in ASCII_TO_UNICODE:
422
+ char = ASCII_TO_UNICODE[char]
423
+ elif (code := ord(char)) <= 31:
424
+ char = chr(0x2400 + code)
425
+ defused += char
426
+ return defused
427
+
428
+
339
429
  def dummy_function(*_args, **_kwargs):
340
430
  """ null function accepting any arguments and returning None.
341
431
 
@@ -379,17 +469,6 @@ def env_str(name: str, convert_name: bool = False) -> Optional[str]:
379
469
  return os.environ.get(name)
380
470
 
381
471
 
382
- def filename2uri(file_name: str) -> str:
383
- """ convert a file name converted by :func:`uri2filename` back to its representation as a URI
384
-
385
- :param file_name: name of the file/folder to convert back to its URI representation.
386
- :return: URI string.
387
-
388
- .. hint:: to ensure proper conversion the specified file name has to be created by :func:`uri2filename`.
389
- """
390
- return urllib.parse.unquote(file_name)
391
-
392
-
393
472
  def force_encoding(text: Union[str, bytes], encoding: str = DEF_ENCODING, errors: str = DEF_ENCODE_ERRORS) -> str:
394
473
  """ force/ensure the encoding of text (str or bytes) without any UnicodeDecodeError/UnicodeEncodeError.
395
474
 
@@ -1005,29 +1084,6 @@ def to_ascii(unicode_str: str) -> str:
1005
1084
  return "".join([c for c in nfkd_form if not unicodedata.combining(c)]).replace('ß', "ss").replace('€', "Euro")
1006
1085
 
1007
1086
 
1008
- def uri2filename(uri: str) -> str:
1009
- """ convert a URI to be usable as name of a file or folder
1010
-
1011
- :param uri: URI to convert to a corresponding file name, that will be revertible back to this URI.
1012
- :return: name of a file/folder representing the specified URI.
1013
-
1014
- in *nix only / and \0 are not allowed characters in file names.
1015
- in MS Windows are not allowed: ASCII 0...31): / \\ : * ? ” < > | (). some blogs recommend to also not allow
1016
- (convert) the characters # and '.
1017
- only old POSIX seems to be even more restricted (only allowing alphanumeric characters plus . - and _).
1018
-
1019
- file name length is not restricted/shortened by this function, although the maximum is 255 characters on most OSs.
1020
-
1021
- more on allowed characters in file names in the answers of RedGrittyBrick on https://superuser.com/questions/358855
1022
- and of Christopher Oezbek on https://stackoverflow.com/questions/1976007.
1023
-
1024
- .. hint:: use :func:`filename2uri` to convert the resulting file name back to the corresponding URO
1025
- """
1026
- # using urllib.parse.quote(uri, safe="") instead would convert also any non-ascii (e.g. umlaut) characters into hex
1027
- # added [] to str.join() argument because List comprehensions are faster than generator expressions
1028
- return "".join([f"%{hex(ord(_))[2:].upper()}" if _ in '/|\\:*?"<>%' else _ for _ in uri])
1029
-
1030
-
1031
1087
  def utc_datetime() -> datetime.datetime:
1032
1088
  """ return the current UTC timestamp as string (to use as suffix for file and variable/attribute names).
1033
1089
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ae_base
3
- Version: 0.3.42
3
+ Version: 0.3.43
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.42
58
+ # base 0.3.43
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.41?logo=python)](
64
- https://gitlab.com/ae-group/ae_base/-/tree/release0.3.41)
63
+ https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.42?logo=python)](
64
+ https://gitlab.com/ae-group/ae_base/-/tree/release0.3.42)
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.42.
68
+ >ae_base module 0.3.43.
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=SomP4LSOql8hbXH2rzcrutx_hIBAmeV0kmEEarF4k0g,60888
2
+ ae_base-0.3.43.dist-info/LICENSE.md,sha256=eHVr16LWo8bsm2NbdFOBcQp-F_3MUXo9I922sABpsMQ,35002
3
+ ae_base-0.3.43.dist-info/METADATA,sha256=ha7RhCCUS7BHy9yAqBPWzCGSXbZ2c4toQDW2z0RPRNU,5311
4
+ ae_base-0.3.43.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
5
+ ae_base-0.3.43.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
6
+ ae_base-0.3.43.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
+ ae_base-0.3.43.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.2.0)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,7 +0,0 @@
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,,