Coverage for /home/runner/work/viur-core/viur-core/viur/src/viur/core/utils/__init__.py: 15%
97 statements
« prev ^ index » next coverage.py v7.6.10, created at 2025-02-07 19:28 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2025-02-07 19:28 +0000
1import logging
2import typing as t
3import warnings
4import datetime
5from collections.abc import Iterable
6from . import string, parse, json # noqa: used by external imports
7from viur.core import current, db
8from viur.core.config import conf
11def utcNow() -> datetime.datetime:
12 """
13 Returns an actual timestamp with UTC timezone setting.
14 """
15 return datetime.datetime.now(datetime.timezone.utc)
18def seoUrlToEntry(module: str,
19 entry: t.Optional["SkeletonInstance"] = None,
20 skelType: t.Optional[str] = None,
21 language: t.Optional[str] = None) -> str:
22 """
23 Return the seo-url to a skeleton instance or the module.
25 :param module: The module name.
26 :param entry: A skeleton instance or None, to get the path to the module.
27 :param skelType: # FIXME: Not used
28 :param language: For which language.
29 If None, the language of the current request is used.
30 :return: The path (with a leading /).
31 """
32 from viur.core import conf
33 pathComponents = [""]
34 if language is None:
35 language = current.language.get()
36 if conf.i18n.language_method == "url":
37 pathComponents.append(language)
38 if module in conf.i18n.language_module_map and language in conf.i18n.language_module_map[module]:
39 module = conf.i18n.language_module_map[module][language]
40 pathComponents.append(module)
41 if not entry:
42 return "/".join(pathComponents)
43 else:
44 try:
45 currentSeoKeys = entry["viurCurrentSeoKeys"]
46 except:
47 return "/".join(pathComponents)
48 if language in (currentSeoKeys or {}):
49 pathComponents.append(str(currentSeoKeys[language]))
50 elif "key" in entry:
51 key = entry["key"]
52 if isinstance(key, str):
53 try:
54 key = db.Key.from_legacy_urlsafe(key)
55 except:
56 pass
57 pathComponents.append(str(key.id_or_name) if isinstance(key, db.Key) else str(key))
58 elif "name" in dir(entry):
59 pathComponents.append(str(entry.name))
60 return "/".join(pathComponents)
63def seoUrlToFunction(module: str, function: str, render: t.Optional[str] = None) -> str:
64 from viur.core import conf
65 lang = current.language.get()
66 if module in conf.i18n.language_module_map and lang in conf.i18n.language_module_map[module]:
67 module = conf.i18n.language_module_map[module][lang]
68 if conf.i18n.language_method == "url":
69 pathComponents = ["", lang]
70 else:
71 pathComponents = [""]
72 targetObject = conf.main_resolver
73 if module in targetObject:
74 pathComponents.append(module)
75 targetObject = targetObject[module]
76 if render and render in targetObject:
77 pathComponents.append(render)
78 targetObject = targetObject[render]
79 if function in targetObject:
80 func = targetObject[function]
81 if func.seo_language_map and lang in func.seo_language_map:
82 pathComponents.append(func.seo_language_map[lang])
83 else:
84 pathComponents.append(function)
85 return "/".join(pathComponents)
88def normalizeKey(key: t.Union[None, 'db.KeyClass']) -> t.Union[None, 'db.KeyClass']:
89 """
90 Normalizes a datastore key (replacing _application with the current one)
92 :param key: Key to be normalized.
94 :return: Normalized key in string representation.
95 """
96 if key is None:
97 return None
98 if key.parent:
99 parent = normalizeKey(key.parent)
100 else:
101 parent = None
102 return db.Key(key.kind, key.id_or_name, parent=parent)
105def ensure_iterable(
106 obj: t.Any,
107 *,
108 test: t.Optional[t.Callable[[t.Any], bool]] = None,
109 allow_callable: bool = True,
110) -> t.Iterable[t.Any]:
111 """
112 Ensures an object to be iterable.
114 An additional test can be provided to check additionally.
116 If the object is not considered to be iterable, a tuple with the object is returned.
117 """
118 if allow_callable and callable(obj):
119 obj = obj()
121 if isinstance(obj, Iterable): # uses collections.abc.Iterable
122 if test is None or test(obj):
123 return obj # return the obj, which is an iterable
125 return () # empty tuple
127 elif obj is None:
128 return () # empty tuple
130 return obj, # return a tuple with the obj
133# DEPRECATED ATTRIBUTES HANDLING
134__UTILS_CONF_REPLACEMENT = {
135 "projectID": "viur.instance.project_id",
136 "isLocalDevelopmentServer": "viur.instance.is_dev_server",
137 "projectBasePath": "viur.instance.project_base_path",
138 "coreBasePath": "viur.instance.core_base_path"
139}
141__UTILS_NAME_REPLACEMENT = {
142 "currentLanguage": ("current.language", current.language),
143 "currentRequest": ("current.request", current.request),
144 "currentRequestData": ("current.request_data", current.request_data),
145 "currentSession": ("current.session", current.session),
146 "downloadUrlFor": ("modules.file.File.create_download_url", "viur.core.modules.file.File.create_download_url"),
147 "escapeString": ("utils.string.escape", string.escape),
148 "generateRandomString": ("utils.string.random", string.random),
149 "getCurrentUser": ("current.user.get", current.user.get),
150 "is_prefix": ("utils.string.is_prefix", string.is_prefix),
151 "parse_bool": ("utils.parse.bool", parse.bool),
152 "srcSetFor": ("modules.file.File.create_src_set", "viur.core.modules.file.File.create_src_set"),
153}
156def __getattr__(attr):
157 if replace := __UTILS_CONF_REPLACEMENT.get(attr): 157 ↛ 158line 157 didn't jump to line 158 because the condition on line 157 was never true
158 msg = f"Use of `utils.{attr}` is deprecated; Use `conf.{replace}` instead!"
159 warnings.warn(msg, DeprecationWarning, stacklevel=3)
160 logging.warning(msg, stacklevel=3)
161 return conf[replace]
163 if replace := __UTILS_NAME_REPLACEMENT.get(attr): 163 ↛ 164line 163 didn't jump to line 164 because the condition on line 163 was never true
164 msg = f"Use of `utils.{attr}` is deprecated; Use `{replace[0]}` instead!"
165 warnings.warn(msg, DeprecationWarning, stacklevel=3)
166 logging.warning(msg, stacklevel=3)
168 ret = replace[1]
170 # When this is a string, try to resolve by dynamic import
171 if isinstance(ret, str):
172 mod, item, attr = ret.rsplit(".", 2)
173 mod = __import__(mod, fromlist=(item,))
174 item = getattr(mod, item)
175 ret = getattr(item, attr)
177 return ret
179 return super(__import__(__name__).__class__).__getattribute__(attr)