kerykeion 5.0.0b2__py3-none-any.whl → 5.0.0b5__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.

Potentially problematic release.


This version of kerykeion might be problematic. Click here for more details.

Files changed (36) hide show
  1. kerykeion/__init__.py +3 -2
  2. kerykeion/aspects/aspects_factory.py +60 -21
  3. kerykeion/aspects/aspects_utils.py +1 -1
  4. kerykeion/backword.py +111 -18
  5. kerykeion/chart_data_factory.py +72 -7
  6. kerykeion/charts/chart_drawer.py +524 -203
  7. kerykeion/charts/charts_utils.py +416 -253
  8. kerykeion/charts/templates/aspect_grid_only.xml +269 -312
  9. kerykeion/charts/templates/chart.xml +248 -304
  10. kerykeion/charts/templates/wheel_only.xml +271 -312
  11. kerykeion/charts/themes/black-and-white.css +148 -0
  12. kerykeion/kr_types/__init__.py +70 -0
  13. kerykeion/kr_types/chart_template_model.py +20 -0
  14. kerykeion/kr_types/kerykeion_exception.py +20 -0
  15. kerykeion/kr_types/kr_literals.py +20 -0
  16. kerykeion/kr_types/kr_models.py +20 -0
  17. kerykeion/kr_types/settings_models.py +20 -0
  18. kerykeion/relationship_score_factory.py +12 -2
  19. kerykeion/schemas/__init__.py +7 -0
  20. kerykeion/schemas/kr_literals.py +12 -1
  21. kerykeion/settings/__init__.py +16 -2
  22. kerykeion/settings/chart_defaults.py +444 -0
  23. kerykeion/settings/config_constants.py +0 -5
  24. kerykeion/settings/kerykeion_settings.py +31 -74
  25. kerykeion/settings/translation_strings.py +1479 -0
  26. kerykeion/settings/translations.py +74 -0
  27. kerykeion/transits_time_range_factory.py +10 -1
  28. {kerykeion-5.0.0b2.dist-info → kerykeion-5.0.0b5.dist-info}/METADATA +333 -207
  29. {kerykeion-5.0.0b2.dist-info → kerykeion-5.0.0b5.dist-info}/RECORD +31 -26
  30. kerykeion/settings/kr.config.json +0 -1474
  31. kerykeion/settings/legacy/__init__.py +0 -0
  32. kerykeion/settings/legacy/legacy_celestial_points_settings.py +0 -299
  33. kerykeion/settings/legacy/legacy_chart_aspects_settings.py +0 -71
  34. kerykeion/settings/legacy/legacy_color_settings.py +0 -42
  35. {kerykeion-5.0.0b2.dist-info → kerykeion-5.0.0b5.dist-info}/WHEEL +0 -0
  36. {kerykeion-5.0.0b2.dist-info → kerykeion-5.0.0b5.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,444 @@
1
+ """
2
+ Default settings and presets used by chart generation and calculation routines.
3
+
4
+ This module centralizes the static values that were previously stored in
5
+ `kerykeion.settings.legacy`. Keeping them here avoids scattering hard-coded
6
+ configuration across the codebase while still exposing them for reuse.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Final, TypedDict
12
+
13
+
14
+ class _CelestialPointSetting(TypedDict, total=False):
15
+ id: int
16
+ name: str
17
+ color: str
18
+ element_points: int
19
+ label: str
20
+ is_active: bool
21
+
22
+
23
+ class _ChartAspectSetting(TypedDict, total=False):
24
+ degree: int
25
+ name: str
26
+ is_major: bool
27
+ color: str
28
+ orb: int
29
+
30
+
31
+ DEFAULT_CHART_COLORS: Final[dict[str, str]] = {
32
+ "paper_0": "var(--kerykeion-chart-color-paper-0)",
33
+ "paper_1": "var(--kerykeion-chart-color-paper-1)",
34
+ "zodiac_bg_0": "var(--kerykeion-chart-color-zodiac-bg-0)",
35
+ "zodiac_bg_1": "var(--kerykeion-chart-color-zodiac-bg-1)",
36
+ "zodiac_bg_2": "var(--kerykeion-chart-color-zodiac-bg-2)",
37
+ "zodiac_bg_3": "var(--kerykeion-chart-color-zodiac-bg-3)",
38
+ "zodiac_bg_4": "var(--kerykeion-chart-color-zodiac-bg-4)",
39
+ "zodiac_bg_5": "var(--kerykeion-chart-color-zodiac-bg-5)",
40
+ "zodiac_bg_6": "var(--kerykeion-chart-color-zodiac-bg-6)",
41
+ "zodiac_bg_7": "var(--kerykeion-chart-color-zodiac-bg-7)",
42
+ "zodiac_bg_8": "var(--kerykeion-chart-color-zodiac-bg-8)",
43
+ "zodiac_bg_9": "var(--kerykeion-chart-color-zodiac-bg-9)",
44
+ "zodiac_bg_10": "var(--kerykeion-chart-color-zodiac-bg-10)",
45
+ "zodiac_bg_11": "var(--kerykeion-chart-color-zodiac-bg-11)",
46
+ "zodiac_icon_0": "var(--kerykeion-chart-color-zodiac-icon-0)",
47
+ "zodiac_icon_1": "var(--kerykeion-chart-color-zodiac-icon-1)",
48
+ "zodiac_icon_2": "var(--kerykeion-chart-color-zodiac-icon-2)",
49
+ "zodiac_icon_3": "var(--kerykeion-chart-color-zodiac-icon-3)",
50
+ "zodiac_icon_4": "var(--kerykeion-chart-color-zodiac-icon-4)",
51
+ "zodiac_icon_5": "var(--kerykeion-chart-color-zodiac-icon-5)",
52
+ "zodiac_icon_6": "var(--kerykeion-chart-color-zodiac-icon-6)",
53
+ "zodiac_icon_7": "var(--kerykeion-chart-color-zodiac-icon-7)",
54
+ "zodiac_icon_8": "var(--kerykeion-chart-color-zodiac-icon-8)",
55
+ "zodiac_icon_9": "var(--kerykeion-chart-color-zodiac-icon-9)",
56
+ "zodiac_icon_10": "var(--kerykeion-chart-color-zodiac-icon-10)",
57
+ "zodiac_icon_11": "var(--kerykeion-chart-color-zodiac-icon-11)",
58
+ "zodiac_radix_ring_0": "var(--kerykeion-chart-color-zodiac-radix-ring-0)",
59
+ "zodiac_radix_ring_1": "var(--kerykeion-chart-color-zodiac-radix-ring-1)",
60
+ "zodiac_radix_ring_2": "var(--kerykeion-chart-color-zodiac-radix-ring-2)",
61
+ "zodiac_transit_ring_0": "var(--kerykeion-chart-color-zodiac-transit-ring-0)",
62
+ "zodiac_transit_ring_1": "var(--kerykeion-chart-color-zodiac-transit-ring-1)",
63
+ "zodiac_transit_ring_2": "var(--kerykeion-chart-color-zodiac-transit-ring-2)",
64
+ "zodiac_transit_ring_3": "var(--kerykeion-chart-color-zodiac-transit-ring-3)",
65
+ "houses_radix_line": "var(--kerykeion-chart-color-houses-radix-line)",
66
+ "houses_transit_line": "var(--kerykeion-chart-color-houses-transit-line)",
67
+ "lunar_phase_0": "var(--kerykeion-chart-color-lunar-phase-0)",
68
+ "lunar_phase_1": "var(--kerykeion-chart-color-lunar-phase-1)",
69
+ }
70
+
71
+
72
+ DEFAULT_CELESTIAL_POINTS_SETTINGS: Final[list[_CelestialPointSetting]] = [
73
+ {
74
+ "id": 0,
75
+ "name": "Sun",
76
+ "color": "var(--kerykeion-chart-color-sun)",
77
+ "element_points": 40,
78
+ "label": "Sun",
79
+ },
80
+ {
81
+ "id": 1,
82
+ "name": "Moon",
83
+ "color": "var(--kerykeion-chart-color-moon)",
84
+ "element_points": 40,
85
+ "label": "Moon",
86
+ },
87
+ {
88
+ "id": 2,
89
+ "name": "Mercury",
90
+ "color": "var(--kerykeion-chart-color-mercury)",
91
+ "element_points": 15,
92
+ "label": "Mercury",
93
+ },
94
+ {
95
+ "id": 3,
96
+ "name": "Venus",
97
+ "color": "var(--kerykeion-chart-color-venus)",
98
+ "element_points": 15,
99
+ "label": "Venus",
100
+ },
101
+ {
102
+ "id": 4,
103
+ "name": "Mars",
104
+ "color": "var(--kerykeion-chart-color-mars)",
105
+ "element_points": 15,
106
+ "label": "Mars",
107
+ },
108
+ {
109
+ "id": 5,
110
+ "name": "Jupiter",
111
+ "color": "var(--kerykeion-chart-color-jupiter)",
112
+ "element_points": 10,
113
+ "label": "Jupiter",
114
+ },
115
+ {
116
+ "id": 6,
117
+ "name": "Saturn",
118
+ "color": "var(--kerykeion-chart-color-saturn)",
119
+ "element_points": 10,
120
+ "label": "Saturn",
121
+ },
122
+ {
123
+ "id": 7,
124
+ "name": "Uranus",
125
+ "color": "var(--kerykeion-chart-color-uranus)",
126
+ "element_points": 10,
127
+ "label": "Uranus",
128
+ },
129
+ {
130
+ "id": 8,
131
+ "name": "Neptune",
132
+ "color": "var(--kerykeion-chart-color-neptune)",
133
+ "element_points": 10,
134
+ "label": "Neptune",
135
+ },
136
+ {
137
+ "id": 9,
138
+ "name": "Pluto",
139
+ "color": "var(--kerykeion-chart-color-pluto)",
140
+ "element_points": 10,
141
+ "label": "Pluto",
142
+ },
143
+ {
144
+ "id": 10,
145
+ "name": "Mean_North_Lunar_Node",
146
+ "color": "var(--kerykeion-chart-color-mean-node)",
147
+ "element_points": 0,
148
+ "label": "Mean_North_Lunar_Node",
149
+ },
150
+ {
151
+ "id": 11,
152
+ "name": "True_North_Lunar_Node",
153
+ "color": "var(--kerykeion-chart-color-true-node)",
154
+ "element_points": 0,
155
+ "label": "True_North_Lunar_Node",
156
+ },
157
+ {
158
+ "id": 12,
159
+ "name": "Chiron",
160
+ "color": "var(--kerykeion-chart-color-chiron)",
161
+ "element_points": 0,
162
+ "label": "Chiron",
163
+ },
164
+ {
165
+ "id": 13,
166
+ "name": "Ascendant",
167
+ "color": "var(--kerykeion-chart-color-first-house)",
168
+ "element_points": 40,
169
+ "label": "Asc",
170
+ },
171
+ {
172
+ "id": 14,
173
+ "name": "Medium_Coeli",
174
+ "color": "var(--kerykeion-chart-color-tenth-house)",
175
+ "element_points": 20,
176
+ "label": "Mc",
177
+ },
178
+ {
179
+ "id": 15,
180
+ "name": "Descendant",
181
+ "color": "var(--kerykeion-chart-color-seventh-house)",
182
+ "element_points": 0,
183
+ "label": "Dsc",
184
+ },
185
+ {
186
+ "id": 16,
187
+ "name": "Imum_Coeli",
188
+ "color": "var(--kerykeion-chart-color-fourth-house)",
189
+ "element_points": 0,
190
+ "label": "Ic",
191
+ },
192
+ {
193
+ "id": 17,
194
+ "name": "Mean_Lilith",
195
+ "color": "var(--kerykeion-chart-color-mean-lilith)",
196
+ "element_points": 0,
197
+ "label": "Mean_Lilith",
198
+ },
199
+ {
200
+ "id": 18,
201
+ "name": "Mean_South_Lunar_Node",
202
+ "color": "var(--kerykeion-chart-color-mean-node)",
203
+ "element_points": 0,
204
+ "label": "Mean_South_Lunar_Node",
205
+ },
206
+ {
207
+ "id": 19,
208
+ "name": "True_South_Lunar_Node",
209
+ "color": "var(--kerykeion-chart-color-true-node)",
210
+ "element_points": 0,
211
+ "label": "True_South_Lunar_Node",
212
+ },
213
+ {
214
+ "id": 20,
215
+ "name": "True_Lilith",
216
+ "color": "var(--kerykeion-chart-color-mean-lilith)",
217
+ "element_points": 0,
218
+ "label": "True_Lilith",
219
+ },
220
+ {
221
+ "id": 21,
222
+ "name": "Earth",
223
+ "color": "var(--kerykeion-chart-color-earth)",
224
+ "element_points": 0,
225
+ "label": "Earth",
226
+ },
227
+ {
228
+ "id": 22,
229
+ "name": "Pholus",
230
+ "color": "var(--kerykeion-chart-color-pholus)",
231
+ "element_points": 0,
232
+ "label": "Pholus",
233
+ },
234
+ {
235
+ "id": 23,
236
+ "name": "Ceres",
237
+ "color": "var(--kerykeion-chart-color-ceres)",
238
+ "element_points": 0,
239
+ "label": "Ceres",
240
+ },
241
+ {
242
+ "id": 24,
243
+ "name": "Pallas",
244
+ "color": "var(--kerykeion-chart-color-pallas)",
245
+ "element_points": 0,
246
+ "label": "Pallas",
247
+ },
248
+ {
249
+ "id": 25,
250
+ "name": "Juno",
251
+ "color": "var(--kerykeion-chart-color-juno)",
252
+ "element_points": 0,
253
+ "label": "Juno",
254
+ },
255
+ {
256
+ "id": 26,
257
+ "name": "Vesta",
258
+ "color": "var(--kerykeion-chart-color-vesta)",
259
+ "element_points": 0,
260
+ "label": "Vesta",
261
+ },
262
+ {
263
+ "id": 27,
264
+ "name": "Eris",
265
+ "color": "var(--kerykeion-chart-color-eris)",
266
+ "element_points": 0,
267
+ "label": "Eris",
268
+ },
269
+ {
270
+ "id": 28,
271
+ "name": "Sedna",
272
+ "color": "var(--kerykeion-chart-color-sedna)",
273
+ "element_points": 0,
274
+ "label": "Sedna",
275
+ },
276
+ {
277
+ "id": 29,
278
+ "name": "Haumea",
279
+ "color": "var(--kerykeion-chart-color-haumea)",
280
+ "element_points": 0,
281
+ "label": "Haumea",
282
+ },
283
+ {
284
+ "id": 30,
285
+ "name": "Makemake",
286
+ "color": "var(--kerykeion-chart-color-makemake)",
287
+ "element_points": 0,
288
+ "label": "Makemake",
289
+ },
290
+ {
291
+ "id": 31,
292
+ "name": "Ixion",
293
+ "color": "var(--kerykeion-chart-color-ixion)",
294
+ "element_points": 0,
295
+ "label": "Ixion",
296
+ },
297
+ {
298
+ "id": 32,
299
+ "name": "Orcus",
300
+ "color": "var(--kerykeion-chart-color-orcus)",
301
+ "element_points": 0,
302
+ "label": "Orcus",
303
+ },
304
+ {
305
+ "id": 33,
306
+ "name": "Quaoar",
307
+ "color": "var(--kerykeion-chart-color-quaoar)",
308
+ "element_points": 0,
309
+ "label": "Quaoar",
310
+ },
311
+ {
312
+ "id": 34,
313
+ "name": "Regulus",
314
+ "color": "var(--kerykeion-chart-color-regulus)",
315
+ "element_points": 0,
316
+ "label": "Regulus",
317
+ },
318
+ {
319
+ "id": 35,
320
+ "name": "Spica",
321
+ "color": "var(--kerykeion-chart-color-spica)",
322
+ "element_points": 0,
323
+ "label": "Spica",
324
+ },
325
+ {
326
+ "id": 36,
327
+ "name": "Pars_Fortunae",
328
+ "color": "var(--kerykeion-chart-color-pars-fortunae)",
329
+ "element_points": 5,
330
+ "label": "Fortune",
331
+ },
332
+ {
333
+ "id": 37,
334
+ "name": "Pars_Spiritus",
335
+ "color": "var(--kerykeion-chart-color-pars-spiritus)",
336
+ "element_points": 0,
337
+ "label": "Spirit",
338
+ },
339
+ {
340
+ "id": 38,
341
+ "name": "Pars_Amoris",
342
+ "color": "var(--kerykeion-chart-color-pars-amoris)",
343
+ "element_points": 0,
344
+ "label": "Love",
345
+ },
346
+ {
347
+ "id": 39,
348
+ "name": "Pars_Fidei",
349
+ "color": "var(--kerykeion-chart-color-pars-fidei)",
350
+ "element_points": 0,
351
+ "label": "Faith",
352
+ },
353
+ {
354
+ "id": 40,
355
+ "name": "Vertex",
356
+ "color": "var(--kerykeion-chart-color-vertex)",
357
+ "element_points": 0,
358
+ "label": "Vertex",
359
+ },
360
+ {
361
+ "id": 41,
362
+ "name": "Anti_Vertex",
363
+ "color": "var(--kerykeion-chart-color-anti-vertex)",
364
+ "element_points": 0,
365
+ "label": "Anti_Vertex",
366
+ },
367
+ ]
368
+
369
+
370
+ DEFAULT_CHART_ASPECTS_SETTINGS: Final[list[_ChartAspectSetting]] = [
371
+ {
372
+ "degree": 0,
373
+ "name": "conjunction",
374
+ "is_major": True,
375
+ "color": "var(--kerykeion-chart-color-conjunction)",
376
+ },
377
+ {
378
+ "degree": 30,
379
+ "name": "semi-sextile",
380
+ "is_major": False,
381
+ "color": "var(--kerykeion-chart-color-semi-sextile)",
382
+ },
383
+ {
384
+ "degree": 45,
385
+ "name": "semi-square",
386
+ "is_major": False,
387
+ "color": "var(--kerykeion-chart-color-semi-square)",
388
+ },
389
+ {
390
+ "degree": 60,
391
+ "name": "sextile",
392
+ "is_major": True,
393
+ "color": "var(--kerykeion-chart-color-sextile)",
394
+ },
395
+ {
396
+ "degree": 72,
397
+ "name": "quintile",
398
+ "is_major": False,
399
+ "color": "var(--kerykeion-chart-color-quintile)",
400
+ },
401
+ {
402
+ "degree": 90,
403
+ "name": "square",
404
+ "is_major": True,
405
+ "color": "var(--kerykeion-chart-color-square)",
406
+ },
407
+ {
408
+ "degree": 120,
409
+ "name": "trine",
410
+ "is_major": True,
411
+ "color": "var(--kerykeion-chart-color-trine)",
412
+ },
413
+ {
414
+ "degree": 135,
415
+ "name": "sesquiquadrate",
416
+ "is_major": False,
417
+ "color": "var(--kerykeion-chart-color-sesquiquadrate)",
418
+ },
419
+ {
420
+ "degree": 144,
421
+ "name": "biquintile",
422
+ "is_major": False,
423
+ "color": "var(--kerykeion-chart-color-biquintile)",
424
+ },
425
+ {
426
+ "degree": 150,
427
+ "name": "quincunx",
428
+ "is_major": False,
429
+ "color": "var(--kerykeion-chart-color-quincunx)",
430
+ },
431
+ {
432
+ "degree": 180,
433
+ "name": "opposition",
434
+ "is_major": True,
435
+ "color": "var(--kerykeion-chart-color-opposition)",
436
+ },
437
+ ]
438
+
439
+
440
+ __all__ = [
441
+ "DEFAULT_CHART_COLORS",
442
+ "DEFAULT_CELESTIAL_POINTS_SETTINGS",
443
+ "DEFAULT_CHART_ASPECTS_SETTINGS",
444
+ ]
@@ -150,8 +150,3 @@ DISCEPOLO_SCORE_ACTIVE_ASPECTS: List[ActiveAspect] = [
150
150
  """
151
151
  List of active aspects with their orbs according to Ciro Discepolo's affinity scoring methodology.
152
152
  """
153
-
154
- DEFAULT_AXIS_ORBIT: int = 1
155
- """
156
- Default orbit for the axes aspects.
157
- """
@@ -1,94 +1,51 @@
1
- # -*- coding: utf-8 -*-
2
1
  """
3
- This is part of Kerykeion (C) 2025 Giacomo Battaglia
4
- """
5
-
6
-
7
- from json import load
8
- import logging
9
- from pathlib import Path
10
- from typing import Dict, Union
11
- from kerykeion.schemas import KerykeionSettingsModel
12
- import functools
13
-
14
-
15
- def get_settings(new_settings_file: Union[Path, None, KerykeionSettingsModel, dict] = None) -> KerykeionSettingsModel:
16
- """
17
- This function is used to get the settings dict from the settings file.
18
- If no settings file is passed as argument, or the file is not found, it will fallback to:
19
- - The system wide config file, located in ~/.config/kerykeion/kr.config.json
20
- - The default config file, located in the package folder
21
-
22
- Args:
23
- new_settings_file (Union[Path, None], optional): The path of the settings file. Defaults to None.
24
-
25
- Returns:
26
- Dict: The settings dict
27
- """
28
-
29
- if isinstance(new_settings_file, dict):
30
- return KerykeionSettingsModel(**new_settings_file)
31
- elif isinstance(new_settings_file, KerykeionSettingsModel):
32
- return new_settings_file
33
-
34
- # Config path we passed as argument
35
- if new_settings_file is not None:
36
- settings_file = new_settings_file
2
+ Utilities for loading Kerykeion configuration settings from Python sources.
37
3
 
38
- if not settings_file.exists():
39
- raise FileNotFoundError(f"File {settings_file} does not exist")
4
+ The translation strings are now stored directly in :mod:`translation_strings`,
5
+ so the loader simply wraps those dictionaries (or any user-provided overrides).
6
+ """
40
7
 
41
- # System wide config path
42
- else:
43
- home_folder = Path.home()
44
- settings_file = home_folder / ".config" / "kerykeion" / "kr.config.json"
8
+ from __future__ import annotations
45
9
 
46
- # Fallback to the default config in the package
47
- if not settings_file.exists():
48
- settings_file = Path(__file__).parent / "kr.config.json"
10
+ from copy import deepcopy
11
+ from typing import Any, Mapping, Optional, cast
49
12
 
50
- logging.debug(f"Kerykeion config file path: {settings_file}")
51
- settings_dict = load_settings_file(settings_file)
13
+ from .translation_strings import LANGUAGE_SETTINGS
52
14
 
53
- return KerykeionSettingsModel(**settings_dict)
15
+ SettingsSource = Optional[Mapping[str, Any]]
54
16
 
55
17
 
56
- @functools.lru_cache
57
- def merge_settings(settings: KerykeionSettingsModel, new_settings: Dict) -> KerykeionSettingsModel:
18
+ def load_settings_mapping(settings_source: Optional[SettingsSource] = None) -> Mapping[str, Any]:
58
19
  """
59
- This function is used to merge the settings file with the default settings,
60
- it's useful to add new settings to the config file without breaking the old ones.
20
+ Resolve the configuration mapping from the provided source.
61
21
 
62
22
  Args:
63
- settings (KerykeionSettingsModel): The default settings
64
- new_settings (Dict): The new settings to add to the default ones
23
+ settings_source (Mapping | None): Optional overrides for the bundled
24
+ language settings. When provided, keys and nested dictionaries are
25
+ merged on top of the default values.
65
26
 
66
27
  Returns:
67
- KerykeionSettingsModel: The new settings
68
- """
69
- new_settings_dict = settings.model_dump() | new_settings
70
- return KerykeionSettingsModel(**new_settings_dict)
71
-
72
-
73
- @functools.lru_cache
74
- def load_settings_file(settings_file_path: str) -> dict:
28
+ Mapping[str, Any]: The resolved configuration dictionary.
75
29
  """
76
- This function is used to load the settings file from a path.
30
+ language_settings = deepcopy(LANGUAGE_SETTINGS)
77
31
 
78
- Args:
79
- settings_file (Path): The path of the settings file
32
+ if settings_source:
33
+ overrides = cast(Mapping[str, Any], settings_source)
34
+ if "language_settings" in overrides:
35
+ overrides = cast(Mapping[str, Any], overrides["language_settings"])
36
+ language_settings = _deep_merge(language_settings, overrides)
80
37
 
81
- Returns:
82
- dict: The settings dict
83
- """
84
- with open(settings_file_path, "r", encoding="utf8") as f:
85
- settings_dict = load(f)
38
+ return {"language_settings": language_settings}
86
39
 
87
- return settings_dict
88
40
 
41
+ def _deep_merge(base: Mapping[str, Any], overrides: Mapping[str, Any]) -> dict[str, Any]:
42
+ merged: dict[str, Any] = {key: deepcopy(value) for key, value in base.items()}
43
+ for key, value in overrides.items():
44
+ if key in merged and isinstance(merged[key], Mapping) and isinstance(value, Mapping):
45
+ merged[key] = _deep_merge(cast(Mapping[str, Any], merged[key]), cast(Mapping[str, Any], value))
46
+ else:
47
+ merged[key] = deepcopy(value)
48
+ return merged
89
49
 
90
- if __name__ == "__main__":
91
- from kerykeion.utilities import setup_logging
92
- setup_logging(level="debug")
93
50
 
94
- print(get_settings())
51
+ __all__ = ["SettingsSource", "load_settings_mapping", "LANGUAGE_SETTINGS"]