ae-base 0.3.38__py3-none-any.whl → 0.3.39__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
@@ -42,7 +42,7 @@ absolute, call the function :func:`norm_path`.
42
42
 
43
43
  :func:`camel_to_snake` and :func:`snake_to_camel` providing name conversions of class and method names.
44
44
 
45
- to encode unicode strings to other codecs the functions :func:`force_encoding` and :func:`to_ascii` can be used.
45
+ to encode Unicode strings to other codecs the functions :func:`force_encoding` and :func:`to_ascii` can be used.
46
46
 
47
47
  the :func:`round_traditional` function get provided by this module for traditional rounding of float values. the
48
48
  function signature is fully compatible to Python's :func:`round` function.
@@ -137,6 +137,7 @@ import shutil
137
137
  import socket
138
138
  import sys
139
139
  import unicodedata
140
+ import urllib.parse
140
141
  import warnings
141
142
 
142
143
  from configparser import ConfigParser, ExtendedInterpolation
@@ -146,7 +147,8 @@ from inspect import getinnerframes, getouterframes, getsourcefile
146
147
  from types import ModuleType
147
148
  from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Tuple, Union, cast
148
149
 
149
- __version__ = '0.3.38'
150
+
151
+ __version__ = '0.3.39'
150
152
 
151
153
 
152
154
  DOCS_FOLDER = 'docs' #: project documentation root folder name
@@ -921,7 +923,7 @@ def sys_env_text(ind_ch: str = " ", ind_len: int = 12, key_ch: str = "=", key_le
921
923
  extra_sys_env_dict: Optional[Dict[str, str]] = None) -> str:
922
924
  """ compile formatted text block with system environment info.
923
925
 
924
- :param ind_ch: indent character (default=" ").
926
+ :param ind_ch: indent character (defaults to " ").
925
927
  :param ind_len: indent depths (default=12 characters).
926
928
  :param key_ch: key-value separator character (default="=").
927
929
  :param key_len: key-name minimum length (default=15 characters).
@@ -940,7 +942,7 @@ def sys_env_text(ind_ch: str = " ", ind_len: int = 12, key_ch: str = "=", key_le
940
942
 
941
943
 
942
944
  def to_ascii(unicode_str: str) -> str:
943
- """ converts unicode string into ascii representation.
945
+ """ converts Unicode string into ascii representation.
944
946
 
945
947
  useful for fuzzy string compare; inspired by MiniQuark's answer
946
948
  in: https://stackoverflow.com/questions/517923/what-is-the-best-way-to-remove-accents-in-a-python-unicode-string
@@ -952,6 +954,36 @@ def to_ascii(unicode_str: str) -> str:
952
954
  return "".join([c for c in nfkd_form if not unicodedata.combining(c)]).replace('ß', "ss").replace('€', "Euro")
953
955
 
954
956
 
957
+ def uri2filename(uri: str) -> str:
958
+ """ convert a URI to be usable as name of a file or folder
959
+
960
+ :param uri: URI to convert to a corresponding file name, that will be revertible back to this URI.
961
+ :return: name of a file/folder representing the specified URI.
962
+
963
+ in *nix only / and \0 are not allowed characters in file names.
964
+ in MS Windows are not allowed: ASCII 0...31): / \\ : * ? ” < > | (). some blogs recommend to also not allow
965
+ (convert) the characters # and '.
966
+ only old POSIX seems to be even more restricted (only allowing alphanumeric characters plus . - and _).
967
+
968
+ file name length is not restricted/shortened by this function, although the maximum is 255 characters on most OSs.
969
+
970
+ more on allowed characters in file names in the answers of RedGrittyBrick on https://superuser.com/questions/358855
971
+ and of Christopher Oezbek on https://stackoverflow.com/questions/1976007.
972
+ """
973
+ # using urllib.parse.quote(uri, safe="") instead would convert also any non-ascii (e.g. umlaut) characters into hex
974
+ # added [] to str.join() argument because List comprehensions are faster than generator expressions
975
+ return "".join([f"%{hex(ord(_))[2:].upper()}" if _ in '/|\\:*?"<>%' else _ for _ in uri])
976
+
977
+
978
+ def filename2uri(file_name: str) -> str:
979
+ """ convert a file name converted by :func:`uri2filename` back to its representation as a URI
980
+
981
+ :param file_name: name of the file/folder to convert back to its URI representation.
982
+ :return: URI string.
983
+ """
984
+ return urllib.parse.unquote(file_name)
985
+
986
+
955
987
  def write_file(file_path: str, content: Union[str, bytes], extra_mode: str = "", encoding: Optional[str] = None):
956
988
  """ (over)write the file specified by :paramref:`~write_file.file_path` with text or binary/bytes content.
957
989
 
@@ -966,11 +998,42 @@ def write_file(file_path: str, content: Union[str, bytes], extra_mode: str = "",
966
998
  :raises OSError: if :paramref:`~read_file.file_path` is misspelled or contains invalid characters.
967
999
  :raises PermissionError: if current OS user account lacks permissions to read the file content.
968
1000
  :raises ValueError: on decoding errors.
1001
+
1002
+ to extend this function for Android 14+ see https://github.com/beeware/toga/pull/1158#issuecomment-2254564657
1003
+ and https://gist.github.com/neonankiti/05922cf0a44108a2e2732671ed9ef386
1004
+ Yes, to use ACTION_CREATE_DOCUMENT, you don't supply a URI in the intent. You wait for the intent result, and that
1005
+ will contain a URI which you can write to.
1006
+ See #1158 (comment - https://github.com/beeware/toga/pull/1158#issuecomment-2254564657) for a link to a Java
1007
+ example, and #1158 (comment - https://github.com/beeware/toga/pull/1158#issuecomment-1446196973) for how to wait
1008
+ for an intent result.
1009
+ Related german docs: https://developer.android.com/training/data-storage/shared/media?hl=de
969
1010
  """
970
1011
  with open(file_path, ('' if extra_mode.startswith('a') else 'w') + extra_mode, encoding=encoding) as file_handle:
971
1012
  file_handle.write(content)
972
1013
 
973
1014
 
1015
+ class ErrorMsgMixin:
1016
+ """ mixin class providing error message """
1017
+ _err_msg: str = ""
1018
+
1019
+ @property
1020
+ def error_message(self) -> str:
1021
+ """ error message string if an error occurred or an empty string if not.
1022
+
1023
+ :getter: return the accumulated error message of the recently occurred error(s).
1024
+ :setter: any assigned error message will be accumulated to recent error messages.
1025
+ pass an empty string to reset the error message.
1026
+ """
1027
+ return self._err_msg
1028
+
1029
+ @error_message.setter
1030
+ def error_message(self, next_err_msg: str):
1031
+ if next_err_msg:
1032
+ self._err_msg += ("\n\n" if self._err_msg else "") + next_err_msg
1033
+ else:
1034
+ self._err_msg = ""
1035
+
1036
+
974
1037
  PACKAGE_NAME = stack_var('__name__') or 'unspecified_package'
975
1038
  PACKAGE_DOMAIN = 'org.test'
976
1039
  PERMISSIONS = "INTERNET, VIBRATE, READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ae_base
3
- Version: 0.3.38
3
+ Version: 0.3.39
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
@@ -22,48 +22,48 @@ Requires-Python: >=3.9
22
22
  Description-Content-Type: text/markdown
23
23
  License-File: LICENSE.md
24
24
  Provides-Extra: dev
25
- Requires-Dist: aedev-tpl-project ; extra == 'dev'
26
- Requires-Dist: ae-ae ; extra == 'dev'
27
- Requires-Dist: anybadge ; extra == 'dev'
28
- Requires-Dist: coverage-badge ; extra == 'dev'
29
- Requires-Dist: aedev-git-repo-manager ; extra == 'dev'
30
- Requires-Dist: flake8 ; extra == 'dev'
31
- Requires-Dist: mypy ; extra == 'dev'
32
- Requires-Dist: pylint ; extra == 'dev'
33
- Requires-Dist: pytest ; extra == 'dev'
34
- Requires-Dist: pytest-cov ; extra == 'dev'
35
- Requires-Dist: typing ; extra == 'dev'
36
- Requires-Dist: types-setuptools ; extra == 'dev'
37
- Requires-Dist: wheel ; extra == 'dev'
38
- Requires-Dist: twine ; extra == 'dev'
25
+ Requires-Dist: aedev-tpl-project; extra == "dev"
26
+ Requires-Dist: ae-ae; extra == "dev"
27
+ Requires-Dist: anybadge; extra == "dev"
28
+ Requires-Dist: coverage-badge; extra == "dev"
29
+ Requires-Dist: aedev-git-repo-manager; extra == "dev"
30
+ Requires-Dist: flake8; extra == "dev"
31
+ Requires-Dist: mypy; extra == "dev"
32
+ Requires-Dist: pylint; extra == "dev"
33
+ Requires-Dist: pytest; extra == "dev"
34
+ Requires-Dist: pytest-cov; extra == "dev"
35
+ Requires-Dist: typing; extra == "dev"
36
+ Requires-Dist: types-setuptools; extra == "dev"
37
+ Requires-Dist: wheel; extra == "dev"
38
+ Requires-Dist: twine; extra == "dev"
39
39
  Provides-Extra: docs
40
40
  Provides-Extra: tests
41
- Requires-Dist: anybadge ; extra == 'tests'
42
- Requires-Dist: coverage-badge ; extra == 'tests'
43
- Requires-Dist: aedev-git-repo-manager ; extra == 'tests'
44
- Requires-Dist: flake8 ; extra == 'tests'
45
- Requires-Dist: mypy ; extra == 'tests'
46
- Requires-Dist: pylint ; extra == 'tests'
47
- Requires-Dist: pytest ; extra == 'tests'
48
- Requires-Dist: pytest-cov ; extra == 'tests'
49
- Requires-Dist: typing ; extra == 'tests'
50
- Requires-Dist: types-setuptools ; extra == 'tests'
51
- Requires-Dist: wheel ; extra == 'tests'
52
- Requires-Dist: twine ; extra == 'tests'
41
+ Requires-Dist: anybadge; extra == "tests"
42
+ Requires-Dist: coverage-badge; extra == "tests"
43
+ Requires-Dist: aedev-git-repo-manager; extra == "tests"
44
+ Requires-Dist: flake8; extra == "tests"
45
+ Requires-Dist: mypy; extra == "tests"
46
+ Requires-Dist: pylint; extra == "tests"
47
+ Requires-Dist: pytest; extra == "tests"
48
+ Requires-Dist: pytest-cov; extra == "tests"
49
+ Requires-Dist: typing; extra == "tests"
50
+ Requires-Dist: types-setuptools; extra == "tests"
51
+ Requires-Dist: wheel; extra == "tests"
52
+ Requires-Dist: twine; extra == "tests"
53
53
 
54
54
  <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae V0.3.94 -->
55
55
  <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.tpl_namespace_root V0.3.14 -->
56
- # base 0.3.38
56
+ # base 0.3.39
57
57
 
58
58
  [![GitLab develop](https://img.shields.io/gitlab/pipeline/ae-group/ae_base/develop?logo=python)](
59
59
  https://gitlab.com/ae-group/ae_base)
60
60
  [![LatestPyPIrelease](
61
- https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.37?logo=python)](
62
- https://gitlab.com/ae-group/ae_base/-/tree/release0.3.37)
61
+ https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.38?logo=python)](
62
+ https://gitlab.com/ae-group/ae_base/-/tree/release0.3.38)
63
63
  [![PyPIVersions](https://img.shields.io/pypi/v/ae_base)](
64
64
  https://pypi.org/project/ae-base/#history)
65
65
 
66
- >ae_base module 0.3.38.
66
+ >ae_base module 0.3.39.
67
67
 
68
68
  [![Coverage](https://ae-group.gitlab.io/ae_base/coverage.svg)](
69
69
  https://ae-group.gitlab.io/ae_base/coverage/index.html)
@@ -0,0 +1,7 @@
1
+ ae/base.py,sha256=aA_qa4s-17EzXKjN9wwfya688eGnFNJP0EglSLeYJjw,55182
2
+ ae_base-0.3.39.dist-info/LICENSE.md,sha256=3X7IwvwQFt4PqRHb7mV8qoJjQ1E-HmcGioyT4Y6-6c8,35002
3
+ ae_base-0.3.39.dist-info/METADATA,sha256=YPZbM4qKqfaO-3WvDLvV77O9WNWOfxg6uxhkO7nu0vA,5219
4
+ ae_base-0.3.39.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
5
+ ae_base-0.3.39.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
6
+ ae_base-0.3.39.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
+ ae_base-0.3.39.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,7 +0,0 @@
1
- ae/base.py,sha256=HAkWF2Ft6XPRF9DpPVHalbrsD7YwxqBNoihmJHLK-8E,52051
2
- ae_base-0.3.38.dist-info/LICENSE.md,sha256=3X7IwvwQFt4PqRHb7mV8qoJjQ1E-HmcGioyT4Y6-6c8,35002
3
- ae_base-0.3.38.dist-info/METADATA,sha256=CpX74Z8BWOU201lQrKvn5JjDX8IN1ihff65-F8nCpDw,5245
4
- ae_base-0.3.38.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
5
- ae_base-0.3.38.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
6
- ae_base-0.3.38.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
7
- ae_base-0.3.38.dist-info/RECORD,,