ae-base 0.3.48__py3-none-any.whl → 0.3.50__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 +92 -5
- {ae_base-0.3.48.dist-info → ae_base-0.3.50.dist-info}/METADATA +5 -5
- ae_base-0.3.50.dist-info/RECORD +7 -0
- {ae_base-0.3.48.dist-info → ae_base-0.3.50.dist-info}/WHEEL +1 -1
- ae_base-0.3.48.dist-info/RECORD +0 -7
- {ae_base-0.3.48.dist-info → ae_base-0.3.50.dist-info}/LICENSE.md +0 -0
- {ae_base-0.3.48.dist-info → ae_base-0.3.50.dist-info}/top_level.txt +0 -0
- {ae_base-0.3.48.dist-info → ae_base-0.3.50.dist-info}/zip-safe +0 -0
ae/base.py
CHANGED
|
@@ -100,6 +100,9 @@ allowing also ``None`` is an accepted argument value.
|
|
|
100
100
|
|
|
101
101
|
to extend any class with an intelligent error message handling, add the mixin :class:`ErrorMsgMixin` to it.
|
|
102
102
|
|
|
103
|
+
the classes :class:`UnformattedValue` and :class:`GivenFormatter` can be used to format strings with placeholders
|
|
104
|
+
enclosed in curly brackets. the function :func:`format_given` is using them to format templates with placeholders.
|
|
105
|
+
|
|
103
106
|
|
|
104
107
|
generic context manager
|
|
105
108
|
-----------------------
|
|
@@ -144,6 +147,7 @@ import platform
|
|
|
144
147
|
import re
|
|
145
148
|
import shutil
|
|
146
149
|
import socket
|
|
150
|
+
import string
|
|
147
151
|
import sys
|
|
148
152
|
import unicodedata
|
|
149
153
|
import warnings
|
|
@@ -156,7 +160,7 @@ from types import ModuleType
|
|
|
156
160
|
from typing import Any, Callable, Dict, Generator, Iterable, List, Optional, Tuple, Union, cast
|
|
157
161
|
|
|
158
162
|
|
|
159
|
-
__version__ = '0.3.
|
|
163
|
+
__version__ = '0.3.50'
|
|
160
164
|
|
|
161
165
|
|
|
162
166
|
os_path_abspath = os.path.abspath
|
|
@@ -469,6 +473,50 @@ def force_encoding(text: Union[str, bytes], encoding: str = DEF_ENCODING, errors
|
|
|
469
473
|
return enc_str.decode(encoding=encoding)
|
|
470
474
|
|
|
471
475
|
|
|
476
|
+
class UnformattedValue:
|
|
477
|
+
""" helper class for :func:`~ae.base.format_given` to keep placeholder with format unchanged if not found. """
|
|
478
|
+
def __init__(self, key: str):
|
|
479
|
+
self.key = key
|
|
480
|
+
|
|
481
|
+
def __format__(self, format_spec: str):
|
|
482
|
+
""" overriding Python object class method to return placeholder unchanged including the curly brackets. """
|
|
483
|
+
return "{{{}{}}}".format(self.key, ":" + format_spec if format_spec else "")
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
class GivenFormatter(string.Formatter):
|
|
487
|
+
""" helper class for :func:`~ae.base.format_given` to keep placeholder with format unchanged if not found. """
|
|
488
|
+
def get_value(self, key, args, kwargs):
|
|
489
|
+
""" overriding to keep placeholder unchanged if not found """
|
|
490
|
+
try:
|
|
491
|
+
return super().get_value(key, args, kwargs)
|
|
492
|
+
except KeyError:
|
|
493
|
+
return UnformattedValue(key)
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
def format_given(text: str, placeholder_map: dict[str, Any], strict: bool = False):
|
|
497
|
+
""" replacement for Python's str.format_map(), keeping intact placeholders that are not in the specified mapping.
|
|
498
|
+
|
|
499
|
+
:param text: text/template in which the given/specified placeholders will get replaced. in contrary
|
|
500
|
+
to str.format_map() no KeyError will be raised for placeholders not specified in
|
|
501
|
+
:paramref:`~format_given.placeholder_map`.
|
|
502
|
+
:param placeholder_map: dict with placeholder keys to be replaced in :paramref:`~format_given.text` argument.
|
|
503
|
+
:param strict: pass True to raise error for text templates containing unpaired curly brackets.
|
|
504
|
+
:return: the specified :paramref:`~format_given.text` with only the placeholders specified in
|
|
505
|
+
:paramref:`~format_given.placeholder_map` replaced with their respective map value.
|
|
506
|
+
additionally any ValueError that would be thrown by str.format_map(), e.g. if the
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
inspired by the answer of CodeManX in `https://stackoverflow.com/questions/3536303`__
|
|
510
|
+
"""
|
|
511
|
+
formatter = GivenFormatter()
|
|
512
|
+
try:
|
|
513
|
+
return formatter.vformat(text, (), placeholder_map)
|
|
514
|
+
except (ValueError, Exception) as ex:
|
|
515
|
+
if strict:
|
|
516
|
+
raise ex
|
|
517
|
+
return text
|
|
518
|
+
|
|
519
|
+
|
|
472
520
|
def full_stack_trace(ex: Exception) -> str:
|
|
473
521
|
""" get full stack trace from an exception.
|
|
474
522
|
|
|
@@ -1018,15 +1066,17 @@ def sys_env_dict() -> Dict[str, Any]:
|
|
|
1018
1066
|
.. hint:: see also https://pyinstaller.readthedocs.io/en/stable/runtime-information.html
|
|
1019
1067
|
"""
|
|
1020
1068
|
sed: Dict[str, Any] = {
|
|
1021
|
-
'
|
|
1069
|
+
'python ver': sys.version.replace('\n', ' '),
|
|
1022
1070
|
'platform': os_platform,
|
|
1023
1071
|
'argv': sys.argv,
|
|
1024
1072
|
'executable': sys.executable,
|
|
1025
1073
|
'cwd': os.getcwd(),
|
|
1026
1074
|
'frozen': getattr(sys, 'frozen', False),
|
|
1027
|
-
'
|
|
1028
|
-
'
|
|
1075
|
+
'user name': os_user_name(),
|
|
1076
|
+
'host name': os_host_name(),
|
|
1077
|
+
'device id': os_device_id,
|
|
1029
1078
|
'app_name_guess': app_name_guess(),
|
|
1079
|
+
'os env': os.environ.copy(),
|
|
1030
1080
|
}
|
|
1031
1081
|
|
|
1032
1082
|
if sed['frozen']:
|
|
@@ -1172,7 +1222,39 @@ class ErrorMsgMixin:
|
|
|
1172
1222
|
self._err_msg = ""
|
|
1173
1223
|
|
|
1174
1224
|
|
|
1175
|
-
|
|
1225
|
+
# platform-specific patches
|
|
1226
|
+
os_device_id = os_host_name()
|
|
1227
|
+
""" user-definable id/name of the device, defaults to os_host_name() on most platforms, alternatives are:
|
|
1228
|
+
|
|
1229
|
+
on all platforms:
|
|
1230
|
+
- socket.gethostname()
|
|
1231
|
+
on Android (check with adb shell 'settings get global device_name' and adb shell 'settings list global'):
|
|
1232
|
+
- Settings.Global.DEVICE_NAME (Settings.Global.getString(context.getContentResolver(), "device_name"))
|
|
1233
|
+
- android.os.Build.DEVICE/.MANUFACTURER/.BRAND/.HOST
|
|
1234
|
+
- DeviceName.getDeviceName()
|
|
1235
|
+
on MS Windows:
|
|
1236
|
+
- os.environ['COMPUTERNAME']
|
|
1237
|
+
"""
|
|
1238
|
+
if os_platform == 'android': # pragma: no cover
|
|
1239
|
+
# determine Android device id because os_host_name() returns mostly 'localhost' and not the user-definable device id
|
|
1240
|
+
from jnius import autoclass # type: ignore
|
|
1241
|
+
|
|
1242
|
+
# noinspection PyBroadException
|
|
1243
|
+
try:
|
|
1244
|
+
Settings = autoclass('android.provider.Settings$Global')
|
|
1245
|
+
PythonActivity = autoclass('org.kivy.android.PythonActivity')
|
|
1246
|
+
|
|
1247
|
+
# mActivity inherits from Context so no need to cast('android.content.Context',..) neither get app context
|
|
1248
|
+
# _Context = autoclass('android.content.Context')
|
|
1249
|
+
# context = cast('android.content.Context', PythonActivity.mActivity)
|
|
1250
|
+
# context = PythonActivity.mActivity.getApplicationContext()
|
|
1251
|
+
context = PythonActivity.mActivity
|
|
1252
|
+
if _dev_id := Settings.getString(context.getContentResolver(), 'device_name'):
|
|
1253
|
+
os_device_id = defuse(_dev_id)
|
|
1254
|
+
|
|
1255
|
+
except Exception:
|
|
1256
|
+
pass
|
|
1257
|
+
|
|
1176
1258
|
# monkey patch the :func:`shutil.copystat` and :func:`shutil.copymode` helper functions, which are crashing on
|
|
1177
1259
|
# 'android' (see # `<https://bugs.python.org/issue28141>`__ and `<https://bugs.python.org/issue32073>`__). these
|
|
1178
1260
|
# functions are used by shutil.copy2/copy/copytree/move to copy OS-specific file attributes.
|
|
@@ -1181,3 +1263,8 @@ if os_platform == 'android': # pragma: no cov
|
|
|
1181
1263
|
# on the destination root directory.
|
|
1182
1264
|
shutil.copymode = dummy_function
|
|
1183
1265
|
shutil.copystat = dummy_function
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
elif os_platform in ('win32', 'cygwin'): # pragma: no cover
|
|
1269
|
+
if _dev_id := os.environ.get('COMPUTERNAME'):
|
|
1270
|
+
os_device_id = defuse(_dev_id)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: ae_base
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.50
|
|
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
|
|
@@ -68,17 +68,17 @@ Dynamic: summary
|
|
|
68
68
|
|
|
69
69
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae V0.3.95 -->
|
|
70
70
|
<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.tpl_namespace_root V0.3.14 -->
|
|
71
|
-
# base 0.3.
|
|
71
|
+
# base 0.3.50
|
|
72
72
|
|
|
73
73
|
[](
|
|
74
74
|
https://gitlab.com/ae-group/ae_base)
|
|
75
75
|
[](
|
|
77
|
+
https://gitlab.com/ae-group/ae_base/-/tree/release0.3.49)
|
|
78
78
|
[](
|
|
79
79
|
https://pypi.org/project/ae-base/#history)
|
|
80
80
|
|
|
81
|
-
>ae_base module 0.3.
|
|
81
|
+
>ae_base module 0.3.50.
|
|
82
82
|
|
|
83
83
|
[](
|
|
84
84
|
https://ae-group.gitlab.io/ae_base/coverage/index.html)
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ae/base.py,sha256=1me3TvKdrXFKVDI9qqXYzJ52d0d3qVw21rY643gymY0,62992
|
|
2
|
+
ae_base-0.3.50.dist-info/LICENSE.md,sha256=uoIIfORuk4V8ZeNh6SN0EUhiU79RC-indIMFqePKVhY,35002
|
|
3
|
+
ae_base-0.3.50.dist-info/METADATA,sha256=1YUr5FieYlbsSE_1atpH6N0uJmYfTRd4tcpxrtqmJRQ,5636
|
|
4
|
+
ae_base-0.3.50.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
|
5
|
+
ae_base-0.3.50.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
+
ae_base-0.3.50.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
+
ae_base-0.3.50.dist-info/RECORD,,
|
ae_base-0.3.48.dist-info/RECORD
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
ae/base.py,sha256=oZBQxpBifv7BEcygj_JmsEMebDnEBaZiL5v1DCUxPOE,58770
|
|
2
|
-
ae_base-0.3.48.dist-info/LICENSE.md,sha256=uoIIfORuk4V8ZeNh6SN0EUhiU79RC-indIMFqePKVhY,35002
|
|
3
|
-
ae_base-0.3.48.dist-info/METADATA,sha256=HEFW7mCBlpRR8EHFK0B0ZgIEuCD1lXSVA73Bb9kRE_4,5636
|
|
4
|
-
ae_base-0.3.48.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
5
|
-
ae_base-0.3.48.dist-info/top_level.txt,sha256=vUdgAslSmhZLXWU48fm8AG2BjVnkOWLco8rzuW-5zY0,3
|
|
6
|
-
ae_base-0.3.48.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
7
|
-
ae_base-0.3.48.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|