oe-python-template 0.16.3__tar.gz → 0.16.6__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.
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/PKG-INFO +1 -1
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/pyproject.toml +2 -2
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_service.py +104 -27
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/.gitignore +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/LICENSE +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/README.md +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/__init__.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/api.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/cli.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/constants.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/__init__.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_api.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_cli.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_constants.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_gui.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_models.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_service.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_settings.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/__init__.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_api.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_cli.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_gui.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_settings.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/.vendored/bottle.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/__init__.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_api.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_cli.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_console.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_constants.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_di.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_gui.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_health.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_log.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_logfire.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_notebook.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_process.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_sentry.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_service.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_settings.py +0 -0
- {oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/boot.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: oe-python-template
|
3
|
-
Version: 0.16.
|
3
|
+
Version: 0.16.6
|
4
4
|
Summary: 🧠 Copier template to scaffold Python projects compliant with best practices and modern tooling.
|
5
5
|
Project-URL: Homepage, https://oe-python-template.readthedocs.io/en/latest/
|
6
6
|
Project-URL: Documentation, https://oe-python-template.readthedocs.io/en/latest/
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "oe-python-template"
|
3
|
-
version = "0.16.
|
3
|
+
version = "0.16.6"
|
4
4
|
description = "🧠 Copier template to scaffold Python projects compliant with best practices and modern tooling."
|
5
5
|
readme = "README.md"
|
6
6
|
authors = [{ name = "Helmut Hoffer von Ankershoffen", email = "helmuthva@gmail.com" }]
|
@@ -288,7 +288,7 @@ source = ["src/"]
|
|
288
288
|
|
289
289
|
|
290
290
|
[tool.bumpversion]
|
291
|
-
current_version = "0.16.
|
291
|
+
current_version = "0.16.6"
|
292
292
|
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
293
293
|
serialize = ["{major}.{minor}.{patch}"]
|
294
294
|
search = "{current_version}"
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_service.py
RENAMED
@@ -6,9 +6,12 @@ import platform
|
|
6
6
|
import pwd
|
7
7
|
import sys
|
8
8
|
import time
|
9
|
-
from
|
9
|
+
from socket import AF_INET, SOCK_DGRAM, socket
|
10
|
+
from typing import Any, NotRequired, TypedDict, cast
|
11
|
+
from urllib.error import HTTPError
|
10
12
|
|
11
13
|
from pydantic_settings import BaseSettings
|
14
|
+
from requests import get
|
12
15
|
from uptime import boottime, uptime
|
13
16
|
|
14
17
|
from ..utils import ( # noqa: TID252
|
@@ -27,7 +30,28 @@ from ..utils import ( # noqa: TID252
|
|
27
30
|
)
|
28
31
|
from ._settings import Settings
|
29
32
|
|
30
|
-
|
33
|
+
log = get_logger(__name__)
|
34
|
+
|
35
|
+
|
36
|
+
class RuntimeDict(TypedDict, total=False):
|
37
|
+
"""Type for runtime information dictionary."""
|
38
|
+
|
39
|
+
environment: str
|
40
|
+
username: str
|
41
|
+
process: dict[str, Any]
|
42
|
+
host: dict[str, Any]
|
43
|
+
python: dict[str, Any]
|
44
|
+
environ: dict[str, str]
|
45
|
+
|
46
|
+
|
47
|
+
class InfoDict(TypedDict, total=False):
|
48
|
+
"""Type for the info dictionary."""
|
49
|
+
|
50
|
+
package: dict[str, Any]
|
51
|
+
runtime: RuntimeDict
|
52
|
+
settings: dict[str, Any]
|
53
|
+
# Allow additional string keys with any values for service info
|
54
|
+
__extra__: NotRequired[dict[str, Any]]
|
31
55
|
|
32
56
|
|
33
57
|
class Service(BaseService):
|
@@ -74,12 +98,47 @@ class Service(BaseService):
|
|
74
98
|
Returns:
|
75
99
|
bool: True if the token is valid, False otherwise.
|
76
100
|
"""
|
77
|
-
|
101
|
+
log.info(token)
|
78
102
|
if not self._settings.token:
|
79
|
-
|
103
|
+
log.warning("Token is not set in settings.")
|
80
104
|
return False
|
81
105
|
return token == self._settings.token.get_secret_value()
|
82
106
|
|
107
|
+
@staticmethod
|
108
|
+
def _get_public_ipv4(timeout: int = 5) -> str | None:
|
109
|
+
"""Get the public IPv4 address of the system.
|
110
|
+
|
111
|
+
Args:
|
112
|
+
timeout (int): Timeout for the request in seconds.
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
str: The public IPv4 address.
|
116
|
+
"""
|
117
|
+
try:
|
118
|
+
response = get(url="https://api.ipify.org", timeout=timeout)
|
119
|
+
response.raise_for_status()
|
120
|
+
return response.text
|
121
|
+
except HTTPError as e:
|
122
|
+
message = f"Failed to get public IP: {e}"
|
123
|
+
log.exception(message)
|
124
|
+
return None
|
125
|
+
|
126
|
+
@staticmethod
|
127
|
+
def _get_local_ipv4() -> str | None:
|
128
|
+
"""Get the local IPv4 address of the system.
|
129
|
+
|
130
|
+
Returns:
|
131
|
+
str: The local IPv4 address.
|
132
|
+
"""
|
133
|
+
try:
|
134
|
+
with socket(AF_INET, SOCK_DGRAM) as connection:
|
135
|
+
connection.connect(("8.8.8.8", 80))
|
136
|
+
return str(connection.getsockname()[0])
|
137
|
+
except Exception as e:
|
138
|
+
message = f"Failed to get local IP: {e}"
|
139
|
+
log.exception(message)
|
140
|
+
return None
|
141
|
+
|
83
142
|
@staticmethod
|
84
143
|
def info(include_environ: bool = False, filter_secrets: bool = True) -> dict[str, Any]:
|
85
144
|
"""
|
@@ -95,7 +154,7 @@ class Service(BaseService):
|
|
95
154
|
dict[str, Any]: Service configuration.
|
96
155
|
"""
|
97
156
|
bootdatetime = boottime()
|
98
|
-
rtn = {
|
157
|
+
rtn: InfoDict = {
|
99
158
|
"package": {
|
100
159
|
"version": __version__,
|
101
160
|
"name": __project_name__,
|
@@ -104,35 +163,49 @@ class Service(BaseService):
|
|
104
163
|
},
|
105
164
|
"runtime": {
|
106
165
|
"environment": __env__,
|
166
|
+
"username": pwd.getpwuid(os.getuid())[0],
|
167
|
+
"process": {
|
168
|
+
"command_line": " ".join(sys.argv),
|
169
|
+
"entry_point": sys.argv[0] if sys.argv else None,
|
170
|
+
"process_info": json.loads(get_process_info().model_dump_json()),
|
171
|
+
},
|
172
|
+
"host": {
|
173
|
+
"os": {
|
174
|
+
"platform": platform.platform(),
|
175
|
+
"system": platform.system(),
|
176
|
+
"release": platform.release(),
|
177
|
+
"version": platform.version(),
|
178
|
+
},
|
179
|
+
"machine": {
|
180
|
+
"arch": platform.machine(),
|
181
|
+
"processor": platform.processor(),
|
182
|
+
"cpu_count": os.cpu_count(),
|
183
|
+
},
|
184
|
+
"network": {
|
185
|
+
"hostname": platform.node(),
|
186
|
+
"local_ipv4": Service._get_local_ipv4(),
|
187
|
+
"public_ipv4": Service._get_public_ipv4(),
|
188
|
+
},
|
189
|
+
"uptime": {
|
190
|
+
"seconds": uptime(),
|
191
|
+
"boottime": bootdatetime.isoformat() if bootdatetime else None,
|
192
|
+
},
|
193
|
+
},
|
107
194
|
"python": {
|
108
195
|
"version": platform.python_version(),
|
109
196
|
"compiler": platform.python_compiler(),
|
110
197
|
"implementation": platform.python_implementation(),
|
111
198
|
"sys.path": sys.path,
|
112
|
-
|
113
|
-
"interpreter_path": sys.executable,
|
114
|
-
"command_line": " ".join(sys.argv),
|
115
|
-
"entry_point": sys.argv[0] if sys.argv else None,
|
116
|
-
"process_info": json.loads(get_process_info().model_dump_json()),
|
117
|
-
"username": pwd.getpwuid(os.getuid())[0],
|
118
|
-
"host": {
|
119
|
-
"system": platform.system(),
|
120
|
-
"release": platform.release(),
|
121
|
-
"version": platform.version(),
|
122
|
-
"machine": platform.machine(),
|
123
|
-
"processor": platform.processor(),
|
124
|
-
"hostname": platform.node(),
|
125
|
-
"ip_address": platform.uname().node,
|
126
|
-
"cpu_count": os.cpu_count(),
|
127
|
-
"uptime": uptime(),
|
128
|
-
"boottime": bootdatetime.isoformat() if bootdatetime else None,
|
199
|
+
"interpreter_path": sys.executable,
|
129
200
|
},
|
130
201
|
},
|
202
|
+
"settings": {},
|
131
203
|
}
|
132
204
|
|
205
|
+
runtime = cast("RuntimeDict", rtn["runtime"])
|
133
206
|
if include_environ:
|
134
207
|
if filter_secrets:
|
135
|
-
|
208
|
+
runtime["environ"] = {
|
136
209
|
k: v
|
137
210
|
for k, v in os.environ.items()
|
138
211
|
if not (
|
@@ -144,9 +217,9 @@ class Service(BaseService):
|
|
144
217
|
)
|
145
218
|
}
|
146
219
|
else:
|
147
|
-
|
220
|
+
runtime["environ"] = dict(os.environ)
|
148
221
|
|
149
|
-
settings = {}
|
222
|
+
settings: dict[str, Any] = {}
|
150
223
|
for settings_class in locate_subclasses(BaseSettings):
|
151
224
|
settings_instance = load_settings(settings_class)
|
152
225
|
env_prefix = settings_instance.model_config.get("env_prefix", "")
|
@@ -158,12 +231,16 @@ class Service(BaseService):
|
|
158
231
|
settings[flat_key] = value
|
159
232
|
rtn["settings"] = settings
|
160
233
|
|
234
|
+
# Convert the TypedDict to a regular dict before adding dynamic service keys
|
235
|
+
result_dict: dict[str, Any] = dict(rtn)
|
236
|
+
|
161
237
|
for service_class in locate_subclasses(BaseService):
|
162
238
|
if service_class is not Service:
|
163
239
|
service = service_class()
|
164
|
-
|
240
|
+
result_dict[service.key()] = service.info()
|
165
241
|
|
166
|
-
|
242
|
+
log.info("Service info: %s", result_dict)
|
243
|
+
return result_dict
|
167
244
|
|
168
245
|
@staticmethod
|
169
246
|
def div_by_zero() -> float:
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/__init__.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_api.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_cli.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_constants.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_gui.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_models.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_service.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/hello/_settings.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/__init__.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_api.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_cli.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_gui.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/system/_settings.py
RENAMED
File without changes
|
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/__init__.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_api.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_cli.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_console.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_constants.py
RENAMED
File without changes
|
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_gui.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_health.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_log.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_logfire.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_notebook.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_process.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_sentry.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_service.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/_settings.py
RENAMED
File without changes
|
{oe_python_template-0.16.3 → oe_python_template-0.16.6}/src/oe_python_template/utils/boot.py
RENAMED
File without changes
|