djresttoolkit 0.17.4__py3-none-any.whl → 1.0.0__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.
- djresttoolkit/envconfig/__init__.py +3 -2
- djresttoolkit/envconfig/_base_env_config.py +84 -0
- djresttoolkit/mail/_email_sender.py +4 -1
- {djresttoolkit-0.17.4.dist-info → djresttoolkit-1.0.0.dist-info}/METADATA +34 -63
- {djresttoolkit-0.17.4.dist-info → djresttoolkit-1.0.0.dist-info}/RECORD +8 -8
- djresttoolkit/envconfig/_env_settings.py +0 -84
- {djresttoolkit-0.17.4.dist-info → djresttoolkit-1.0.0.dist-info}/WHEEL +0 -0
- {djresttoolkit-0.17.4.dist-info → djresttoolkit-1.0.0.dist-info}/entry_points.txt +0 -0
- {djresttoolkit-0.17.4.dist-info → djresttoolkit-1.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
import threading
|
2
|
+
import json
|
3
|
+
from os import getenv
|
4
|
+
from typing import Any, Self, get_type_hints
|
5
|
+
import logging
|
6
|
+
|
7
|
+
logger = logging.getLogger(__name__)
|
8
|
+
|
9
|
+
|
10
|
+
class BaseEnvConfig:
|
11
|
+
"""Production-ready environment loader."""
|
12
|
+
|
13
|
+
_instance_lock = threading.Lock()
|
14
|
+
_instance = None
|
15
|
+
|
16
|
+
def __new__(cls, *args: Any, **kwargs: Any) -> Self:
|
17
|
+
if cls._instance is None:
|
18
|
+
with cls._instance_lock:
|
19
|
+
if cls._instance is None:
|
20
|
+
cls._instance = super().__new__(cls)
|
21
|
+
return cls._instance
|
22
|
+
|
23
|
+
def __init__(self) -> None:
|
24
|
+
if getattr(self, "_initialized", False):
|
25
|
+
return
|
26
|
+
|
27
|
+
self._env_cache: dict[str, Any] = {}
|
28
|
+
self._sync_env()
|
29
|
+
self._initialized = True
|
30
|
+
|
31
|
+
def _sync_env(self) -> None:
|
32
|
+
hints = get_type_hints(self.__class__)
|
33
|
+
for field, _ in hints.items():
|
34
|
+
raw = getenv(field)
|
35
|
+
|
36
|
+
if raw is None:
|
37
|
+
if hasattr(self, field):
|
38
|
+
value = getattr(self, field)
|
39
|
+
logger.info(f"{field} not set, using default: {value}")
|
40
|
+
else:
|
41
|
+
raise EnvironmentError(
|
42
|
+
f"Missing required environment variable: {field}"
|
43
|
+
)
|
44
|
+
else:
|
45
|
+
if field in self._env_cache:
|
46
|
+
value = self._env_cache[field]
|
47
|
+
else:
|
48
|
+
value = self._parse_env_value(raw)
|
49
|
+
self._env_cache[field] = value
|
50
|
+
|
51
|
+
setattr(self, field, value)
|
52
|
+
|
53
|
+
def _parse_env_value(self, raw: str) -> Any:
|
54
|
+
"""Parse string from environment."""
|
55
|
+
lowered = raw.lower()
|
56
|
+
|
57
|
+
# Boolean parsing
|
58
|
+
if lowered == "true":
|
59
|
+
return True
|
60
|
+
if lowered == "false":
|
61
|
+
return False
|
62
|
+
|
63
|
+
# JSON parsing
|
64
|
+
try:
|
65
|
+
return json.loads(raw)
|
66
|
+
except json.JSONDecodeError:
|
67
|
+
pass
|
68
|
+
|
69
|
+
# Numeric parsing
|
70
|
+
if raw.isdigit():
|
71
|
+
return int(raw)
|
72
|
+
try:
|
73
|
+
return float(raw)
|
74
|
+
except ValueError:
|
75
|
+
pass
|
76
|
+
|
77
|
+
# Fallback: plain string
|
78
|
+
return raw
|
79
|
+
|
80
|
+
def reload(self) -> None:
|
81
|
+
"""Reload environment variables at runtime."""
|
82
|
+
self._env_cache.clear()
|
83
|
+
self._sync_env()
|
84
|
+
logger.info("Environment variables reloaded.")
|
@@ -80,7 +80,10 @@ class EmailSender:
|
|
80
80
|
to=unique_recipients,
|
81
81
|
)
|
82
82
|
email.attach_alternative(
|
83
|
-
content=
|
83
|
+
content=render_to_string(
|
84
|
+
self.email_content["template"]["html"],
|
85
|
+
self.email_content["context"],
|
86
|
+
),
|
84
87
|
mimetype="text/html",
|
85
88
|
)
|
86
89
|
email.send()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: djresttoolkit
|
3
|
-
Version: 0.
|
3
|
+
Version: 1.0.0
|
4
4
|
Summary: A collection of Django and DRF utilities to simplify API development.
|
5
5
|
Project-URL: Homepage, https://github.com/shaileshpandit141/djresttoolkit
|
6
6
|
Project-URL: Documentation, https://shaileshpandit141.github.io/djresttoolkit
|
@@ -47,9 +47,7 @@ Classifier: Topic :: Utilities
|
|
47
47
|
Classifier: Typing :: Typed
|
48
48
|
Requires-Python: >=3.13
|
49
49
|
Requires-Dist: faker>=37.5.3
|
50
|
-
Requires-Dist: pydantic-settings>=2.10.1
|
51
50
|
Requires-Dist: pydantic>=2.11.7
|
52
|
-
Requires-Dist: pyyaml>=6.0.2
|
53
51
|
Provides-Extra: dev
|
54
52
|
Requires-Dist: mypy; extra == 'dev'
|
55
53
|
Requires-Dist: pytest; extra == 'dev'
|
@@ -72,8 +70,8 @@ djresttoolkit is a collection of utilities and helpers for Django and Django RES
|
|
72
70
|
- **DB Flush Command (`dbflush`)**
|
73
71
|
Management command to flush all models or a specific model, resetting auto-increment IDs safely with transaction support.
|
74
72
|
|
75
|
-
- **
|
76
|
-
|
73
|
+
- **BaseEnvConfig**
|
74
|
+
Singleton environment loader that reads and parses environment variables.
|
77
75
|
|
78
76
|
- **EmailSender**
|
79
77
|
Custom class to send templated emails (`text` and `html`) with context. Supports error handling and logging.
|
@@ -186,10 +184,6 @@ python manage.py dbseed --count 10
|
|
186
184
|
python manage.py dbseed --model User --seed 42
|
187
185
|
```
|
188
186
|
|
189
|
-
Here’s a **concise API reference** for your database flush management command for `djresttoolkit`:
|
190
|
-
|
191
|
-
---
|
192
|
-
|
193
187
|
### 2. DB Flush Command — API Reference
|
194
188
|
|
195
189
|
```python
|
@@ -246,77 +240,54 @@ or
|
|
246
240
|
Flushed 120 records from all models and reset IDs.
|
247
241
|
```
|
248
242
|
|
249
|
-
###
|
243
|
+
### 3. BaseEnvConfig — API Reference
|
250
244
|
|
251
245
|
```python
|
252
|
-
from djresttoolkit.envconfig import
|
246
|
+
from djresttoolkit.envconfig import BaseEnvConfig
|
253
247
|
```
|
254
248
|
|
255
|
-
#### `
|
256
|
-
|
257
|
-
A **base settings class** for managing application configuration using:
|
258
|
-
|
259
|
-
- YAML files (default `.environ.yaml`)
|
260
|
-
- Environment variables (default `.env`)
|
261
|
-
|
262
|
-
Supports **nested configuration** using double underscores (`__`) in environment variable names.
|
263
|
-
|
264
|
-
#### Class Attributes
|
265
|
-
|
266
|
-
- Attributes
|
267
|
-
- `env_file`
|
268
|
-
- Type: `str`
|
269
|
-
- Default: `.env`
|
270
|
-
- Description: Environment variable file path.
|
271
|
-
- `yaml_file`
|
272
|
-
- Type: `str`
|
273
|
-
- Default: `.environ.yaml`
|
274
|
-
- Description: YAML configuration file path.
|
275
|
-
- `model_config`
|
276
|
-
- Type: `SettingsConfigDict`
|
277
|
-
- Description: Pydantic settings configuration (file encoding, nested delimiter).
|
249
|
+
#### `BaseEnvConfig`
|
278
250
|
|
279
|
-
|
251
|
+
Singleton environment loader that reads and parses environment variables with support for booleans, numbers, and JSON.
|
280
252
|
|
281
|
-
|
253
|
+
> ⚠️ **Note:** Note: If you are using a .env file, load it first with python-dotenv:
|
254
|
+
>
|
255
|
+
> ```python
|
256
|
+
> from dotenv import load_dotenv
|
257
|
+
> load_dotenv()
|
258
|
+
> ```
|
282
259
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
- `warning` — Emit a warning if YAML file is missing (default `True`).
|
290
|
-
|
291
|
-
#### Returns
|
292
|
-
|
293
|
-
- Instance of `EnvBaseSettings` (or subclass) with loaded configuration.
|
294
|
-
|
295
|
-
#### Raises
|
296
|
-
|
297
|
-
- `UserWarning` if YAML file not found and `warning=True`.
|
260
|
+
or
|
261
|
+
>
|
262
|
+
> ```python
|
263
|
+
> from djresttoolkit.envconfig import load_dotenv
|
264
|
+
> load_dotenv()
|
265
|
+
> ```
|
298
266
|
|
299
|
-
|
267
|
+
#### Usage Example
|
300
268
|
|
301
269
|
```python
|
302
|
-
from djresttoolkit.envconfig import
|
270
|
+
from djresttoolkit.envconfig import load_dotenv, BaseEnvConfig
|
271
|
+
|
272
|
+
load_dotenv()
|
303
273
|
|
304
|
-
class
|
305
|
-
|
306
|
-
|
274
|
+
class EnvConfig(BaseEnvConfig):
|
275
|
+
DEBUG: bool = False
|
276
|
+
DATABASE_URL: str
|
307
277
|
|
308
|
-
|
309
|
-
|
278
|
+
config = EnvConfig()
|
279
|
+
print(config.DEBUG)
|
280
|
+
print(config.DATABASE_URL)
|
310
281
|
|
311
|
-
|
312
|
-
print(settings.database_url)
|
282
|
+
config.reload()
|
313
283
|
```
|
314
284
|
|
315
285
|
#### Features
|
316
286
|
|
317
|
-
-
|
318
|
-
-
|
319
|
-
-
|
287
|
+
- Thread-safe singleton.
|
288
|
+
- Automatic type parsing for environment variables.
|
289
|
+
- Supports default values and runtime reloading.
|
290
|
+
- Designed for subclassing with project-specific settings.
|
320
291
|
|
321
292
|
### 4. EmailSender — API Reference
|
322
293
|
|
@@ -14,10 +14,10 @@ djresttoolkit/dbseed/models/__init__.py,sha256=uuynQIcfVqEaZN9hF_caI24zm8az23JdX
|
|
14
14
|
djresttoolkit/dbseed/models/_choice_field.py,sha256=T7LAzbyXqlYp2mtCAKL8E1Da_MEh9RzgLZrFJ7fa4gM,446
|
15
15
|
djresttoolkit/dbseed/models/_gen.py,sha256=qBPQaLvh1rcEam0YmE4JBJqpa-Vv5IFlIIagkEMHDVw,206
|
16
16
|
djresttoolkit/dbseed/models/_seed_model.py,sha256=0cmbi0VNKjmJbwhjeCFsvb3iKYjok6TJOk6Y2MF_3N4,2443
|
17
|
-
djresttoolkit/envconfig/__init__.py,sha256=
|
18
|
-
djresttoolkit/envconfig/
|
17
|
+
djresttoolkit/envconfig/__init__.py,sha256=ABYwK1rsH15txGsbh5myqerF_ls6RafUlGhLyvaF2t8,119
|
18
|
+
djresttoolkit/envconfig/_base_env_config.py,sha256=7buy7khKDR1PLag9w4rtjRhk9EUtIQvqcyqn_LehuV4,2340
|
19
19
|
djresttoolkit/mail/__init__.py,sha256=tB9SdMlhfWQ640q4aobZ0H1c7fTWalpDL2I-onkr2VI,268
|
20
|
-
djresttoolkit/mail/_email_sender.py,sha256=
|
20
|
+
djresttoolkit/mail/_email_sender.py,sha256=nXnH1JSiiu51IFQSKw8W6pzaGjDPg2GUKEq0XQ2gSJM,3207
|
21
21
|
djresttoolkit/mail/_models.py,sha256=of5KsLGvsN2OWgDYgdtLEijulg817TXgsLKuUdsnDQc,1447
|
22
22
|
djresttoolkit/mail/_types.py,sha256=zf6CcXR1ei_UmZ1nLAJa378OAJ6ftnBICqEOkzXPNw8,646
|
23
23
|
djresttoolkit/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -50,8 +50,8 @@ djresttoolkit/views/_exceptions/__init__.py,sha256=DrCUxuPNyBR4WhzNutn5HDxLa--q5
|
|
50
50
|
djresttoolkit/views/_exceptions/_exception_handler.py,sha256=_o7If47bzWLl57LeSXSWsIDsJGo2RIpwYAwNQ-hsHVY,2839
|
51
51
|
djresttoolkit/views/mixins/__init__.py,sha256=K-1tk5d8tCVViMynw5DdffJ3Oo5uHpEx32E3_4X2UxM,154
|
52
52
|
djresttoolkit/views/mixins/_retrieve_object_mixin.py,sha256=Q9znYPb07YXXUhsL7VIrk3BC-zDwjOhwLJKe2GPJ-k0,1155
|
53
|
-
djresttoolkit-0.
|
54
|
-
djresttoolkit-0.
|
55
|
-
djresttoolkit-0.
|
56
|
-
djresttoolkit-0.
|
57
|
-
djresttoolkit-0.
|
53
|
+
djresttoolkit-1.0.0.dist-info/METADATA,sha256=pyiY9lXJeoLC9xHgZSuE4f72eRkugl0Zkt00hWaDrSU,31832
|
54
|
+
djresttoolkit-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
55
|
+
djresttoolkit-1.0.0.dist-info/entry_points.txt,sha256=YMhfTF-7mYppO8QqqWnvR_hyMWvoYxD6XI94_ViFu3k,60
|
56
|
+
djresttoolkit-1.0.0.dist-info/licenses/LICENSE,sha256=8-oZM3yuuTRjySMbVKX9YXYA7Y4M_KhQNBYXPFjeWUo,1074
|
57
|
+
djresttoolkit-1.0.0.dist-info/RECORD,,
|
@@ -1,84 +0,0 @@
|
|
1
|
-
import warnings
|
2
|
-
from pathlib import Path
|
3
|
-
from typing import Any, ClassVar
|
4
|
-
|
5
|
-
import yaml
|
6
|
-
from pydantic_settings import BaseSettings, SettingsConfigDict
|
7
|
-
|
8
|
-
|
9
|
-
class EnvBaseSettings[T: "EnvBaseSettings"](BaseSettings):
|
10
|
-
""" "
|
11
|
-
EnvBaseSettings is a base settings class for managing application configuration
|
12
|
-
using both YAML files and environment variables.
|
13
|
-
This class is designed to load configuration values from a YAML file first,
|
14
|
-
and then override those values with environment variables if present. It supports
|
15
|
-
nested configuration using a double underscore (`__`) as the delimiter in
|
16
|
-
environment variable names, allowing for hierarchical settings.
|
17
|
-
|
18
|
-
Class Attributes:
|
19
|
-
env_file (str): The default filename for the environment variables file (default: ".env").
|
20
|
-
yaml_file (str): The default filename for the YAML configuration file (default: ".environ.yaml").
|
21
|
-
model_config (SettingsConfigDict): Configuration for environment variable parsing, including file encoding and nested delimiter.
|
22
|
-
|
23
|
-
Methods:
|
24
|
-
load(cls, *, env_file: str | None = None, ymal_file: str | None = None, warning: bool = True) -> "EnvBaseSettings":
|
25
|
-
Loads configuration from a YAML file (if it exists), then overrides with environment variables.
|
26
|
-
- env_file: Optional custom path to the .env file.
|
27
|
-
- ymal_file: Optional custom path to the YAML file.
|
28
|
-
- warning: If True, emits a warning if the YAML file is not found.
|
29
|
-
Returns an instance of EnvBaseSettings with the loaded configuration.
|
30
|
-
|
31
|
-
Usage:
|
32
|
-
- Define your settings as subclasses of EnvBaseSettings.
|
33
|
-
- Call `YourSettingsClass.load()` to load configuration from files and environment variables.
|
34
|
-
- Supports nested configuration via double underscore in environment variable names (e.g., `DATABASE__HOST`).
|
35
|
-
|
36
|
-
Raises:
|
37
|
-
- UserWarning: If the YAML file is not found and `warning` is True.
|
38
|
-
|
39
|
-
Example:
|
40
|
-
```python
|
41
|
-
from djresttoolkit.envconfig import EnvBaseSettings
|
42
|
-
|
43
|
-
class EnvSettings(EnvBaseSettings):
|
44
|
-
debug: bool = False
|
45
|
-
database_url: str
|
46
|
-
|
47
|
-
settings = EnvSettings.load(warning=False)
|
48
|
-
```
|
49
|
-
|
50
|
-
"""
|
51
|
-
|
52
|
-
env_file: ClassVar[str] = ".env"
|
53
|
-
yaml_file: ClassVar[str] = ".environ.yaml"
|
54
|
-
|
55
|
-
model_config = SettingsConfigDict(
|
56
|
-
env_file=env_file,
|
57
|
-
env_file_encoding="utf-8",
|
58
|
-
env_nested_delimiter="__",
|
59
|
-
)
|
60
|
-
|
61
|
-
@classmethod
|
62
|
-
def load(
|
63
|
-
cls: type[T],
|
64
|
-
*,
|
65
|
-
env_file: str | None = None,
|
66
|
-
ymal_file: str | None = None,
|
67
|
-
warning: bool = True,
|
68
|
-
) -> T:
|
69
|
-
"""Load from YAML first, then override with .env."""
|
70
|
-
if env_file:
|
71
|
-
cls.env_file = env_file
|
72
|
-
if ymal_file:
|
73
|
-
cls.yaml_file = ymal_file
|
74
|
-
|
75
|
-
config_file = Path(cls.yaml_file)
|
76
|
-
yaml_data: dict[str, Any] = {}
|
77
|
-
if config_file.exists():
|
78
|
-
with config_file.open("r") as f:
|
79
|
-
yaml_data = yaml.safe_load(f) or {}
|
80
|
-
elif warning:
|
81
|
-
msg: str = f"Config file {config_file} not found, using only env vars."
|
82
|
-
warnings.warn(msg, UserWarning, stacklevel=1)
|
83
|
-
|
84
|
-
return cls(**yaml_data)
|
File without changes
|
File without changes
|
File without changes
|