kerykeion 4.26.0rc1__tar.gz → 4.26.1__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.

Potentially problematic release.


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

Files changed (46) hide show
  1. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/PKG-INFO +81 -26
  2. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/README.md +80 -25
  3. kerykeion-4.26.1/kerykeion/.DS_Store +0 -0
  4. kerykeion-4.26.1/kerykeion/charts/.DS_Store +0 -0
  5. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/kerykeion_chart_svg.py +235 -48
  6. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/utilities.py +55 -0
  7. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/pyproject.toml +1 -1
  8. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/LICENSE +0 -0
  9. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/__init__.py +0 -0
  10. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/aspects/__init__.py +0 -0
  11. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/aspects/aspects_utils.py +0 -0
  12. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/aspects/natal_aspects.py +0 -0
  13. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/aspects/synastry_aspects.py +0 -0
  14. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/aspects/transits_time_range.py +0 -0
  15. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/astrological_subject.py +0 -0
  16. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/__init__.py +0 -0
  17. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/charts_utils.py +0 -0
  18. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/draw_planets.py +0 -0
  19. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/templates/aspect_grid_only.xml +0 -0
  20. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/templates/chart.xml +0 -0
  21. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/templates/wheel_only.xml +0 -0
  22. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/themes/classic.css +0 -0
  23. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/themes/dark-high-contrast.css +0 -0
  24. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/themes/dark.css +0 -0
  25. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/charts/themes/light.css +0 -0
  26. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/composite_subject_factory.py +0 -0
  27. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/enums.py +0 -0
  28. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/ephemeris_data.py +0 -0
  29. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/fetch_geonames.py +0 -0
  30. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/kr_types/__init__.py +0 -0
  31. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/kr_types/chart_types.py +0 -0
  32. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/kr_types/kerykeion_exception.py +0 -0
  33. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/kr_types/kr_literals.py +0 -0
  34. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/kr_types/kr_models.py +0 -0
  35. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/kr_types/settings_models.py +0 -0
  36. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/relationship_score/__init__.py +0 -0
  37. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/relationship_score/relationship_score.py +0 -0
  38. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/relationship_score/relationship_score_factory.py +0 -0
  39. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/report.py +0 -0
  40. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/settings/__init__.py +0 -0
  41. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/settings/config_constants.py +0 -0
  42. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/settings/kerykeion_settings.py +0 -0
  43. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/settings/kr.config.json +0 -0
  44. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/sweph/README.md +0 -0
  45. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/sweph/seas_18.se1 +0 -0
  46. {kerykeion-4.26.0rc1 → kerykeion-4.26.1}/kerykeion/transits_time_range.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kerykeion
3
- Version: 4.26.0rc1
3
+ Version: 4.26.1
4
4
  Summary: A python library for astrology.
5
5
  Home-page: https://www.kerykeion.net/
6
6
  License: AGPL-3.0
@@ -53,17 +53,18 @@ Description-Content-Type: text/markdown
53
53
 
54
54
   
55
55
 
56
- Kerykeion is a Python library for astrology. It computes planetary and house positions, detects aspects (individual, synastry, composite), and generates SVG charts—including birth, synastry, transit, and composite charts. You can also customize which planets to include in your calculations.
56
+ Kerykeion is a Python library for astrology. It computes planetary and house positions, detects aspects, and generates SVG charts—including birth, synastry, transit, and composite charts. You can also customize which planets to include in your calculations.
57
57
 
58
58
  The main goal of this project is to offer a clean, data-driven approach to astrology, making it accessible and programmable.
59
59
 
60
- Kerykeion also integrates seamlessly with AI applications. It is designed to work well as a backend for chatbots, recommendation systems, or personal assistants that require astrological insights. You can access structured data in JSON format, making it easy to combine with natural language processing models or knowledge-based systems.
60
+ Kerykeion also integrates seamlessly with LLM and AI applications.
61
61
 
62
62
  Here is an example of a birthchart:
63
63
 
64
64
  ![John Lenon Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Dark%20Theme%20-%20Natal%20Chart.svg)
65
65
 
66
- ## Web API
66
+ **Web API**
67
+ ---
67
68
 
68
69
  If you want to use Kerykeion in a web application, you can try the dedicated web API:
69
70
 
@@ -71,12 +72,40 @@ If you want to use Kerykeion in a web application, you can try the dedicated web
71
72
 
72
73
  It is [open source](https://github.com/g-battaglia/Astrologer-API) and directly supports this project.
73
74
 
74
- ## Donate
75
+ **Donate**
76
+ --
75
77
 
76
78
  Maintaining this project requires substantial time and effort. The Astrologer API alone cannot cover the costs of full-time development. If you find Kerykeion valuable and would like to support further development, please consider donating:
77
79
 
78
80
  [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/kerykeion)
79
81
 
82
+
83
+ ## Table of Contents
84
+ - [Installation](#installation)
85
+ - [Basic Usage](#basic-usage)
86
+ - [Generate a SVG Chart](#generate-a-svg-chart)
87
+ - [Birth Chart](#birth-chart)
88
+ - [Synastry Chart](#synastry-chart)
89
+ - [Transit Chart](#transit-chart)
90
+ - [Composite Chart](#composite-chart)
91
+ - [Change the Output Directory](#change-the-output-directory)
92
+ - [Change Language](#change-language)
93
+ - [Report](#report)
94
+ - [Example: Retrieving Aspects](#example-retrieving-aspects)
95
+ - [Ayanamsa (Sidereal Modes)](#ayanamsa-sidereal-modes)
96
+ - [House Systems](#house-systems)
97
+ - [Perspective Type](#perspective-type)
98
+ - [Themes](#themes)
99
+ - [Alternative Initialization](#alternative-initialization)
100
+ - [Lunar Nodes (Rahu \& Ketu)](#lunar-nodes-rahu--ketu)
101
+ - [JSON Support](#json-support)
102
+ - [Auto Generated Documentation](#auto-generated-documentation)
103
+ - [Development](#development)
104
+ - [Integrating Kerykeion into Your Project](#integrating-kerykeion-into-your-project)
105
+ - [License](#license)
106
+ - [Contributing](#contributing)
107
+ - [Citations](#citations)
108
+
80
109
  ## Installation
81
110
 
82
111
  Kerykeion requires **Python 3.9** or higher.
@@ -382,34 +411,49 @@ subject = AstrologicalSubject.get_from_iso_utc_time(
382
411
 
383
412
  ## Lunar Nodes (Rahu & Ketu)
384
413
 
385
- The following are present:
414
+ Kerykeion supports both **True** and **Mean** Lunar Nodes:
386
415
 
387
- - True North Lunar Node: Simply referred to as "true_node" (without the term "north") for backward compatibility.
388
- - True South Lunar Node: Referred to as "true_south_node."
389
- - Mean North Lunar Node: Referred to as "mean_node" (without the term "north") for backward compatibility.
390
- - Mean South Lunar Node: Referred to as "mean_south_node."
416
+ - **True North Lunar Node**: `"true_node"` (name kept without "north" for backward compatibility).
417
+ - **True South Lunar Node**: `"true_south_node"`.
418
+ - **Mean North Lunar Node**: `"mean_node"` (name kept without "north" for backward compatibility).
419
+ - **Mean South Lunar Node**: `"mean_south_node"`.
391
420
 
392
421
  In instances of the AstrologicalSubject class, all of them are active by default.
393
422
 
394
- In instances of the classes used to generate aspects and SVG charts, only the mean nodes are active. To activate the true nodes, you need to edit the configuration file (kr.config.json).
423
+ In instances of the classes used to generate aspects and SVG charts, only the mean nodes are active. To activate the true nodes, you need to pass the `active_points` parameter to the `KerykeionChartSVG` class.
424
+
395
425
  Example:
396
426
 
397
- ```json
398
- ...
399
- {
400
- "id": 19,
401
- "name": "True_South_Node",
402
- "color": "var(--kerykeion-chart-color-true-node)",
403
- "is_active": true, // Set to true to activate the true node
404
- "element_points": 0,
405
- "related_zodiac_signs": [],
406
- "label": "True_South_Node"
407
- }
408
- ...
409
- ```
427
+ ```python
428
+ from kerykeion import AstrologicalSubject, KerykeionChartSVG
429
+
430
+ subject = AstrologicalSubject("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
410
431
 
411
- In the charts, by default, the mean nodes (M) are displayed, while the true nodes are not displayed.
412
- To display them, you need to edit the configuration file (kr.config.json).
432
+ chart = KerykeionChartSVG(
433
+ subject,
434
+ active_points=[
435
+ "Sun",
436
+ "Moon",
437
+ "Mercury",
438
+ "Venus",
439
+ "Mars",
440
+ "Jupiter",
441
+ "Saturn",
442
+ "Uranus",
443
+ "Neptune",
444
+ "Pluto",
445
+ "Mean_Node",
446
+ "Mean_South_Node",
447
+ "True_Node", # Activates True North Node
448
+ "True_South_Node", # Activates True South Node
449
+ "Ascendant",
450
+ "Medium_Coeli",
451
+ "Descendant",
452
+ "Imum_Coeli"
453
+ ]
454
+ )
455
+ chart.makeSVG()
456
+ ```
413
457
 
414
458
  ## JSON Support
415
459
 
@@ -441,7 +485,18 @@ This project is covered under the AGPL-3.0 License. For detailed information, pl
441
485
 
442
486
  As a rule of thumb, if you use this library in a project, you should open-source that project under a compatible license. Alternatively, if you wish to keep your source closed, consider using the [AstrologerAPI](https://rapidapi.com/gbattaglia/api/astrologer/), which is AGPL-3.0 compliant and also helps support the project.
443
487
 
488
+ Since the AstrologerAPI is an external third-party service, using it does *not* require your code to be open-source.
489
+
444
490
  ## Contributing
445
491
 
446
492
  Contributions are welcome! Feel free to submit pull requests or report issues.
447
493
 
494
+ ## Citations
495
+
496
+ If using Kerykeion in published or academic work, please cite as follows:
497
+
498
+ ```
499
+ Battaglia, G. (2025). Kerykeion: A Python Library for Astrological Calculations and Chart Generation.
500
+ https://github.com/g-battaglia/kerykeion
501
+ ```
502
+
@@ -14,17 +14,18 @@
14
14
 
15
15
   
16
16
 
17
- Kerykeion is a Python library for astrology. It computes planetary and house positions, detects aspects (individual, synastry, composite), and generates SVG charts—including birth, synastry, transit, and composite charts. You can also customize which planets to include in your calculations.
17
+ Kerykeion is a Python library for astrology. It computes planetary and house positions, detects aspects, and generates SVG charts—including birth, synastry, transit, and composite charts. You can also customize which planets to include in your calculations.
18
18
 
19
19
  The main goal of this project is to offer a clean, data-driven approach to astrology, making it accessible and programmable.
20
20
 
21
- Kerykeion also integrates seamlessly with AI applications. It is designed to work well as a backend for chatbots, recommendation systems, or personal assistants that require astrological insights. You can access structured data in JSON format, making it easy to combine with natural language processing models or knowledge-based systems.
21
+ Kerykeion also integrates seamlessly with LLM and AI applications.
22
22
 
23
23
  Here is an example of a birthchart:
24
24
 
25
25
  ![John Lenon Chart](https://raw.githubusercontent.com/g-battaglia/kerykeion/refs/heads/master/tests/charts/svg/John%20Lennon%20-%20Dark%20Theme%20-%20Natal%20Chart.svg)
26
26
 
27
- ## Web API
27
+ **Web API**
28
+ ---
28
29
 
29
30
  If you want to use Kerykeion in a web application, you can try the dedicated web API:
30
31
 
@@ -32,12 +33,40 @@ If you want to use Kerykeion in a web application, you can try the dedicated web
32
33
 
33
34
  It is [open source](https://github.com/g-battaglia/Astrologer-API) and directly supports this project.
34
35
 
35
- ## Donate
36
+ **Donate**
37
+ --
36
38
 
37
39
  Maintaining this project requires substantial time and effort. The Astrologer API alone cannot cover the costs of full-time development. If you find Kerykeion valuable and would like to support further development, please consider donating:
38
40
 
39
41
  [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/kerykeion)
40
42
 
43
+
44
+ ## Table of Contents
45
+ - [Installation](#installation)
46
+ - [Basic Usage](#basic-usage)
47
+ - [Generate a SVG Chart](#generate-a-svg-chart)
48
+ - [Birth Chart](#birth-chart)
49
+ - [Synastry Chart](#synastry-chart)
50
+ - [Transit Chart](#transit-chart)
51
+ - [Composite Chart](#composite-chart)
52
+ - [Change the Output Directory](#change-the-output-directory)
53
+ - [Change Language](#change-language)
54
+ - [Report](#report)
55
+ - [Example: Retrieving Aspects](#example-retrieving-aspects)
56
+ - [Ayanamsa (Sidereal Modes)](#ayanamsa-sidereal-modes)
57
+ - [House Systems](#house-systems)
58
+ - [Perspective Type](#perspective-type)
59
+ - [Themes](#themes)
60
+ - [Alternative Initialization](#alternative-initialization)
61
+ - [Lunar Nodes (Rahu \& Ketu)](#lunar-nodes-rahu--ketu)
62
+ - [JSON Support](#json-support)
63
+ - [Auto Generated Documentation](#auto-generated-documentation)
64
+ - [Development](#development)
65
+ - [Integrating Kerykeion into Your Project](#integrating-kerykeion-into-your-project)
66
+ - [License](#license)
67
+ - [Contributing](#contributing)
68
+ - [Citations](#citations)
69
+
41
70
  ## Installation
42
71
 
43
72
  Kerykeion requires **Python 3.9** or higher.
@@ -343,34 +372,49 @@ subject = AstrologicalSubject.get_from_iso_utc_time(
343
372
 
344
373
  ## Lunar Nodes (Rahu & Ketu)
345
374
 
346
- The following are present:
375
+ Kerykeion supports both **True** and **Mean** Lunar Nodes:
347
376
 
348
- - True North Lunar Node: Simply referred to as "true_node" (without the term "north") for backward compatibility.
349
- - True South Lunar Node: Referred to as "true_south_node."
350
- - Mean North Lunar Node: Referred to as "mean_node" (without the term "north") for backward compatibility.
351
- - Mean South Lunar Node: Referred to as "mean_south_node."
377
+ - **True North Lunar Node**: `"true_node"` (name kept without "north" for backward compatibility).
378
+ - **True South Lunar Node**: `"true_south_node"`.
379
+ - **Mean North Lunar Node**: `"mean_node"` (name kept without "north" for backward compatibility).
380
+ - **Mean South Lunar Node**: `"mean_south_node"`.
352
381
 
353
382
  In instances of the AstrologicalSubject class, all of them are active by default.
354
383
 
355
- In instances of the classes used to generate aspects and SVG charts, only the mean nodes are active. To activate the true nodes, you need to edit the configuration file (kr.config.json).
384
+ In instances of the classes used to generate aspects and SVG charts, only the mean nodes are active. To activate the true nodes, you need to pass the `active_points` parameter to the `KerykeionChartSVG` class.
385
+
356
386
  Example:
357
387
 
358
- ```json
359
- ...
360
- {
361
- "id": 19,
362
- "name": "True_South_Node",
363
- "color": "var(--kerykeion-chart-color-true-node)",
364
- "is_active": true, // Set to true to activate the true node
365
- "element_points": 0,
366
- "related_zodiac_signs": [],
367
- "label": "True_South_Node"
368
- }
369
- ...
370
- ```
388
+ ```python
389
+ from kerykeion import AstrologicalSubject, KerykeionChartSVG
390
+
391
+ subject = AstrologicalSubject("John Lennon", 1940, 10, 9, 18, 30, "Liverpool", "GB")
371
392
 
372
- In the charts, by default, the mean nodes (M) are displayed, while the true nodes are not displayed.
373
- To display them, you need to edit the configuration file (kr.config.json).
393
+ chart = KerykeionChartSVG(
394
+ subject,
395
+ active_points=[
396
+ "Sun",
397
+ "Moon",
398
+ "Mercury",
399
+ "Venus",
400
+ "Mars",
401
+ "Jupiter",
402
+ "Saturn",
403
+ "Uranus",
404
+ "Neptune",
405
+ "Pluto",
406
+ "Mean_Node",
407
+ "Mean_South_Node",
408
+ "True_Node", # Activates True North Node
409
+ "True_South_Node", # Activates True South Node
410
+ "Ascendant",
411
+ "Medium_Coeli",
412
+ "Descendant",
413
+ "Imum_Coeli"
414
+ ]
415
+ )
416
+ chart.makeSVG()
417
+ ```
374
418
 
375
419
  ## JSON Support
376
420
 
@@ -402,6 +446,17 @@ This project is covered under the AGPL-3.0 License. For detailed information, pl
402
446
 
403
447
  As a rule of thumb, if you use this library in a project, you should open-source that project under a compatible license. Alternatively, if you wish to keep your source closed, consider using the [AstrologerAPI](https://rapidapi.com/gbattaglia/api/astrologer/), which is AGPL-3.0 compliant and also helps support the project.
404
448
 
449
+ Since the AstrologerAPI is an external third-party service, using it does *not* require your code to be open-source.
450
+
405
451
  ## Contributing
406
452
 
407
453
  Contributions are welcome! Feel free to submit pull requests or report issues.
454
+
455
+ ## Citations
456
+
457
+ If using Kerykeion in published or academic work, please cite as follows:
458
+
459
+ ```
460
+ Battaglia, G. (2025). Kerykeion: A Python Library for Astrological Calculations and Chart Generation.
461
+ https://github.com/g-battaglia/kerykeion
462
+ ```
Binary file
@@ -37,7 +37,7 @@ from kerykeion.charts.charts_utils import (
37
37
  draw_planet_grid,
38
38
  )
39
39
  from kerykeion.charts.draw_planets import draw_planets # type: ignore
40
- from kerykeion.utilities import get_houses_list
40
+ from kerykeion.utilities import get_houses_list, inline_css_variables_in_svg
41
41
  from kerykeion.settings.config_constants import DEFAULT_ACTIVE_POINTS, DEFAULT_ACTIVE_ASPECTS
42
42
  from pathlib import Path
43
43
  from scour.scour import scourString
@@ -47,23 +47,44 @@ from datetime import datetime
47
47
 
48
48
  class KerykeionChartSVG:
49
49
  """
50
- Creates the instance that can generate the chart with the
51
- function makeSVG().
52
-
53
- Parameters:
54
- - first_obj: First kerykeion object
55
- - chart_type: Natal, ExternalNatal, Transit, Synastry (Default: Type="Natal").
56
- - second_obj: Second kerykeion object (Not required if type is Natal)
57
- - new_output_directory: Set the output directory (default: home directory).
58
- - new_settings_file: Set the settings file (default: kr.config.json).
59
- In the settings file you can set the language, colors, planets, aspects, etc.
60
- - theme: Set the theme for the chart (default: classic). If None the <style> tag will be empty.
61
- That's useful if you want to use your own CSS file customizing the value of the default theme variables.
62
- - double_chart_aspect_grid_type: Set the type of the aspect grid for the double chart (transit or synastry). (Default: list.)
63
- - chart_language: Set the language for the chart (default: EN).
64
- - active_points: Set the active points for the chart (default: DEFAULT_ACTIVE_POINTS). Example:
65
- ["Sun", "Moon", "Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto", "True_Node", "True_South_Node", "Ascendant", "Medium_Coeli", "Descendant", "Imum_Coeli"]
66
- - active_aspects: Set the active aspects for the chart (default: DEFAULT_ACTIVE_ASPECTS). Example:
50
+ KerykeionChartSVG generates astrological chart visualizations as SVG files.
51
+
52
+ This class supports creating full chart SVGs, wheel-only SVGs, and aspect-grid-only SVGs
53
+ for various chart types including Natal, ExternalNatal, Transit, Synastry, and Composite.
54
+ Charts are rendered using XML templates and drawing utilities, with customizable themes,
55
+ language, active points, and aspects.
56
+ The rendered SVGs can be saved to a specified output directory or, by default, to the user's home directory.
57
+
58
+ NOTE:
59
+ The generated SVG files are optimized for web use, opening in browsers. If you want to
60
+ use them in other applications, you might need to adjust the SVG settings or styles.
61
+
62
+ Args:
63
+ first_obj (AstrologicalSubject | AstrologicalSubjectModel | CompositeSubjectModel):
64
+ The primary astrological subject for the chart.
65
+ chart_type (ChartType, optional):
66
+ The type of chart to generate ('Natal', 'ExternalNatal', 'Transit', 'Synastry', 'Composite').
67
+ Defaults to 'Natal'.
68
+ second_obj (AstrologicalSubject | AstrologicalSubjectModel, optional):
69
+ The secondary subject for Transit or Synastry charts. Not required for Natal or Composite.
70
+ new_output_directory (str | Path, optional):
71
+ Directory to write generated SVG files. Defaults to the user's home directory.
72
+ new_settings_file (Path | dict | KerykeionSettingsModel, optional):
73
+ Path or settings object to override default chart configuration (colors, fonts, aspects).
74
+ theme (KerykeionChartTheme, optional):
75
+ CSS theme for the chart. If None, no default styles are applied. Defaults to 'classic'.
76
+ double_chart_aspect_grid_type (Literal['list', 'table'], optional):
77
+ Specifies rendering style for double-chart aspect grids. Defaults to 'list'.
78
+ chart_language (KerykeionChartLanguage, optional):
79
+ Language code for chart labels. Defaults to 'EN'.
80
+ active_points (list[Planet | AxialCusps], optional):
81
+ List of celestial points and angles to include. Defaults to DEFAULT_ACTIVE_POINTS.
82
+ Example:
83
+ ["Sun", "Moon", "Mercury", "Venus"]
84
+
85
+ active_aspects (list[ActiveAspect], optional):
86
+ List of aspects (name and orb) to calculate. Defaults to DEFAULT_ACTIVE_ASPECTS.
87
+ Example:
67
88
  [
68
89
  {"name": "conjunction", "orb": 10},
69
90
  {"name": "opposition", "orb": 10},
@@ -72,6 +93,30 @@ class KerykeionChartSVG:
72
93
  {"name": "square", "orb": 5},
73
94
  {"name": "quintile", "orb": 1},
74
95
  ]
96
+
97
+ Public Methods:
98
+ makeTemplate(minify=False, remove_css_variables=False) -> str:
99
+ Render the full chart SVG as a string without writing to disk. Use `minify=True`
100
+ to remove whitespace and quotes, and `remove_css_variables=True` to embed CSS vars.
101
+
102
+ makeSVG(minify=False, remove_css_variables=False) -> None:
103
+ Generate and write the full chart SVG file to the output directory.
104
+ Filenames follow the pattern:
105
+ '{subject.name} - {chart_type} Chart.svg'.
106
+
107
+ makeWheelOnlyTemplate(minify=False, remove_css_variables=False) -> str:
108
+ Render only the chart wheel (no aspect grid) as an SVG string.
109
+
110
+ makeWheelOnlySVG(minify=False, remove_css_variables=False) -> None:
111
+ Generate and write the wheel-only SVG file:
112
+ '{subject.name} - {chart_type} Chart - Wheel Only.svg'.
113
+
114
+ makeAspectGridOnlyTemplate(minify=False, remove_css_variables=False) -> str:
115
+ Render only the aspect grid as an SVG string.
116
+
117
+ makeAspectGridOnlySVG(minify=False, remove_css_variables=False) -> None:
118
+ Generate and write the aspect-grid-only SVG file:
119
+ '{subject.name} - {chart_type} Chart - Aspect Grid Only.svg'.
75
120
  """
76
121
 
77
122
  # Constants
@@ -131,8 +176,33 @@ class KerykeionChartSVG:
131
176
  double_chart_aspect_grid_type: Literal["list", "table"] = "list",
132
177
  chart_language: KerykeionChartLanguage = "EN",
133
178
  active_points: List[Union[Planet, AxialCusps]] = DEFAULT_ACTIVE_POINTS,
134
- active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
179
+ active_aspects: List[ActiveAspect] = DEFAULT_ACTIVE_ASPECTS,
135
180
  ):
181
+ """
182
+ Initialize the chart generator with subject data and configuration options.
183
+
184
+ Args:
185
+ first_obj (AstrologicalSubject, AstrologicalSubjectModel, or CompositeSubjectModel):
186
+ Primary astrological subject instance.
187
+ chart_type (ChartType, optional):
188
+ Type of chart to generate (e.g., 'Natal', 'Transit').
189
+ second_obj (AstrologicalSubject or AstrologicalSubjectModel, optional):
190
+ Secondary subject for Transit or Synastry charts.
191
+ new_output_directory (str or Path, optional):
192
+ Base directory to save generated SVG files.
193
+ new_settings_file (Path, dict, or KerykeionSettingsModel, optional):
194
+ Custom settings source for chart colors, fonts, and aspects.
195
+ theme (KerykeionChartTheme or None, optional):
196
+ CSS theme to apply; None for default styling.
197
+ double_chart_aspect_grid_type (Literal['list','table'], optional):
198
+ Layout style for double-chart aspect grids ('list' or 'table').
199
+ chart_language (KerykeionChartLanguage, optional):
200
+ Language code for chart labels (e.g., 'EN', 'IT').
201
+ active_points (List[Planet or AxialCusps], optional):
202
+ Celestial points to include in the chart visualization.
203
+ active_aspects (List[ActiveAspect], optional):
204
+ Aspects to calculate, each defined by name and orb.
205
+ """
136
206
  home_directory = Path.home()
137
207
  self.new_settings_file = new_settings_file
138
208
  self.chart_language = chart_language
@@ -269,7 +339,10 @@ class KerykeionChartSVG:
269
339
 
270
340
  def set_up_theme(self, theme: Union[KerykeionChartTheme, None] = None) -> None:
271
341
  """
272
- Set the theme for the chart.
342
+ Load and apply a CSS theme for the chart visualization.
343
+
344
+ Args:
345
+ theme (KerykeionChartTheme or None): Name of the theme to apply. If None, no CSS is applied.
273
346
  """
274
347
  if theme is None:
275
348
  self.color_style_tag = ""
@@ -282,14 +355,21 @@ class KerykeionChartSVG:
282
355
 
283
356
  def set_output_directory(self, dir_path: Path) -> None:
284
357
  """
285
- Sets the output direcotry and returns it's path.
358
+ Set the directory where generated SVG files will be saved.
359
+
360
+ Args:
361
+ dir_path (Path): Target directory for SVG output.
286
362
  """
287
363
  self.output_directory = dir_path
288
364
  logging.info(f"Output direcotry set to: {self.output_directory}")
289
365
 
290
366
  def parse_json_settings(self, settings_file_or_dict: Union[Path, dict, KerykeionSettingsModel, None]) -> None:
291
367
  """
292
- Parse the settings file.
368
+ Load and parse chart configuration settings.
369
+
370
+ Args:
371
+ settings_file_or_dict (Path, dict, or KerykeionSettingsModel):
372
+ Source for custom chart settings.
293
373
  """
294
374
  settings = get_settings(settings_file_or_dict)
295
375
 
@@ -300,14 +380,13 @@ class KerykeionChartSVG:
300
380
 
301
381
  def _draw_zodiac_circle_slices(self, r):
302
382
  """
303
- Generate the SVG string representing the zodiac circle
304
- with the 12 slices for each zodiac sign.
383
+ Draw zodiac circle slices for each sign.
305
384
 
306
385
  Args:
307
- r (float): The radius of the zodiac slices.
386
+ r (float): Outer radius of the zodiac ring.
308
387
 
309
388
  Returns:
310
- str: The SVG string representing the zodiac circle.
389
+ str: Concatenated SVG elements for zodiac slices.
311
390
  """
312
391
  sings = get_args(Sign)
313
392
  output = ""
@@ -326,10 +405,13 @@ class KerykeionChartSVG:
326
405
 
327
406
  def _calculate_elements_points_from_planets(self):
328
407
  """
329
- Calculate chart element points from a planet.
330
- TODO: Refactor this method.
331
- Should be completely rewritten. Maybe even part of the AstrologicalSubject class.
332
- The points should include just the standard way of calculating the elements points.
408
+ Compute elemental point totals based on active planetary positions.
409
+
410
+ Iterates over each active planet to determine its zodiac element and adds extra points
411
+ if the planet is in a related sign. Updates self.fire, self.earth, self.air, and self.water.
412
+
413
+ Returns:
414
+ None
333
415
  """
334
416
 
335
417
  ZODIAC = (
@@ -381,6 +463,16 @@ class KerykeionChartSVG:
381
463
  self.water = self.water + self.available_planets_setting[i]["element_points"] + extra_points
382
464
 
383
465
  def _draw_all_aspects_lines(self, r, ar):
466
+ """
467
+ Render SVG lines for all aspects in the chart.
468
+
469
+ Args:
470
+ r (float): Radius at which aspect lines originate.
471
+ ar (float): Radius at which aspect lines terminate.
472
+
473
+ Returns:
474
+ str: SVG markup for all aspect lines.
475
+ """
384
476
  out = ""
385
477
  for aspect in self.aspects_list:
386
478
  aspect_name = aspect["aspect"]
@@ -396,6 +488,16 @@ class KerykeionChartSVG:
396
488
  return out
397
489
 
398
490
  def _draw_all_transit_aspects_lines(self, r, ar):
491
+ """
492
+ Render SVG lines for all transit aspects in the chart.
493
+
494
+ Args:
495
+ r (float): Radius at which transit aspect lines originate.
496
+ ar (float): Radius at which transit aspect lines terminate.
497
+
498
+ Returns:
499
+ str: SVG markup for all transit aspect lines.
500
+ """
399
501
  out = ""
400
502
  for aspect in self.aspects_list:
401
503
  aspect_name = aspect["aspect"]
@@ -412,10 +514,13 @@ class KerykeionChartSVG:
412
514
 
413
515
  def _create_template_dictionary(self) -> ChartTemplateDictionary:
414
516
  """
415
- Create a dictionary containing the template data for generating an astrological chart.
517
+ Assemble chart data and rendering instructions into a template dictionary.
518
+
519
+ Gathers styling, dimensions, and SVG fragments for chart components based on
520
+ chart type and subjects.
416
521
 
417
522
  Returns:
418
- ChartTemplateDictionary: A dictionary with template data for the chart.
523
+ ChartTemplateDictionary: Populated structure of template variables.
419
524
  """
420
525
  # Initialize template dictionary
421
526
  template_dict: dict = {}
@@ -702,8 +807,20 @@ class KerykeionChartSVG:
702
807
 
703
808
  return ChartTemplateDictionary(**template_dict)
704
809
 
705
- def makeTemplate(self, minify: bool = False) -> str:
706
- """Creates the template for the SVG file"""
810
+ def makeTemplate(self, minify: bool = False, remove_css_variables = False) -> str:
811
+ """
812
+ Render the full chart SVG as a string.
813
+
814
+ Reads the XML template, substitutes variables, and optionally inlines CSS
815
+ variables and minifies the output.
816
+
817
+ Args:
818
+ minify (bool): Remove whitespace and quotes for compactness.
819
+ remove_css_variables (bool): Embed CSS variable definitions.
820
+
821
+ Returns:
822
+ str: SVG markup as a string.
823
+ """
707
824
  td = self._create_template_dictionary()
708
825
 
709
826
  DATA_DIR = Path(__file__).parent
@@ -719,6 +836,9 @@ class KerykeionChartSVG:
719
836
 
720
837
  self._create_template_dictionary()
721
838
 
839
+ if remove_css_variables:
840
+ template = inline_css_variables_in_svg(template)
841
+
722
842
  if minify:
723
843
  template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
724
844
 
@@ -727,11 +847,22 @@ class KerykeionChartSVG:
727
847
 
728
848
  return template
729
849
 
730
- def makeSVG(self, minify: bool = False):
731
- """Prints out the SVG file in the specified folder"""
850
+ def makeSVG(self, minify: bool = False, remove_css_variables = False):
851
+ """
852
+ Generate and save the full chart SVG to disk.
853
+
854
+ Calls makeTemplate to render the SVG, then writes a file named
855
+ "{subject.name} - {chart_type} Chart.svg" in the output directory.
856
+
857
+ Args:
858
+ minify (bool): Pass-through to makeTemplate for compact output.
859
+ remove_css_variables (bool): Pass-through to makeTemplate to embed CSS variables.
860
+
861
+ Returns:
862
+ None
863
+ """
732
864
 
733
- if not hasattr(self, "template"):
734
- self.template = self.makeTemplate(minify)
865
+ self.template = self.makeTemplate(minify, remove_css_variables)
735
866
 
736
867
  chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart.svg"
737
868
 
@@ -739,8 +870,21 @@ class KerykeionChartSVG:
739
870
  output_file.write(self.template)
740
871
 
741
872
  print(f"SVG Generated Correctly in: {chartname}")
742
- def makeWheelOnlyTemplate(self, minify: bool = False):
743
- """Creates the template for the SVG file with only the wheel"""
873
+
874
+ def makeWheelOnlyTemplate(self, minify: bool = False, remove_css_variables = False):
875
+ """
876
+ Render the wheel-only chart SVG as a string.
877
+
878
+ Reads the wheel-only XML template, substitutes chart data, and applies optional
879
+ CSS inlining and minification.
880
+
881
+ Args:
882
+ minify (bool): Remove whitespace and quotes for compactness.
883
+ remove_css_variables (bool): Embed CSS variable definitions.
884
+
885
+ Returns:
886
+ str: SVG markup for the chart wheel only.
887
+ """
744
888
 
745
889
  with open(Path(__file__).parent / "templates" / "wheel_only.xml", "r", encoding="utf-8", errors="ignore") as f:
746
890
  template = f.read()
@@ -748,6 +892,9 @@ class KerykeionChartSVG:
748
892
  template_dict = self._create_template_dictionary()
749
893
  template = Template(template).substitute(template_dict)
750
894
 
895
+ if remove_css_variables:
896
+ template = inline_css_variables_in_svg(template)
897
+
751
898
  if minify:
752
899
  template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
753
900
 
@@ -756,18 +903,43 @@ class KerykeionChartSVG:
756
903
 
757
904
  return template
758
905
 
759
- def makeWheelOnlySVG(self, minify: bool = False):
760
- """Prints out the SVG file in the specified folder with only the wheel"""
906
+ def makeWheelOnlySVG(self, minify: bool = False, remove_css_variables = False):
907
+ """
908
+ Generate and save wheel-only chart SVG to disk.
909
+
910
+ Calls makeWheelOnlyTemplate and writes a file named
911
+ "{subject.name} - {chart_type} Chart - Wheel Only.svg" in the output directory.
912
+
913
+ Args:
914
+ minify (bool): Pass-through to makeWheelOnlyTemplate for compact output.
915
+ remove_css_variables (bool): Pass-through to makeWheelOnlyTemplate to embed CSS variables.
761
916
 
762
- template = self.makeWheelOnlyTemplate(minify)
917
+ Returns:
918
+ None
919
+ """
920
+
921
+ template = self.makeWheelOnlyTemplate(minify, remove_css_variables)
763
922
  chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart - Wheel Only.svg"
764
923
 
765
924
  with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
766
925
  output_file.write(template)
767
926
 
768
927
  print(f"SVG Generated Correctly in: {chartname}")
769
- def makeAspectGridOnlyTemplate(self, minify: bool = False):
770
- """Creates the template for the SVG file with only the aspect grid"""
928
+
929
+ def makeAspectGridOnlyTemplate(self, minify: bool = False, remove_css_variables = False):
930
+ """
931
+ Render the aspect-grid-only chart SVG as a string.
932
+
933
+ Reads the aspect-grid XML template, generates the aspect grid based on chart type,
934
+ and applies optional CSS inlining and minification.
935
+
936
+ Args:
937
+ minify (bool): Remove whitespace and quotes for compactness.
938
+ remove_css_variables (bool): Embed CSS variable definitions.
939
+
940
+ Returns:
941
+ str: SVG markup for the aspect grid only.
942
+ """
771
943
 
772
944
  with open(Path(__file__).parent / "templates" / "aspect_grid_only.xml", "r", encoding="utf-8", errors="ignore") as f:
773
945
  template = f.read()
@@ -781,6 +953,9 @@ class KerykeionChartSVG:
781
953
 
782
954
  template = Template(template).substitute({**template_dict, "makeAspectGrid": aspects_grid})
783
955
 
956
+ if remove_css_variables:
957
+ template = inline_css_variables_in_svg(template)
958
+
784
959
  if minify:
785
960
  template = scourString(template).replace('"', "'").replace("\n", "").replace("\t","").replace(" ", "").replace(" ", "")
786
961
 
@@ -789,10 +964,22 @@ class KerykeionChartSVG:
789
964
 
790
965
  return template
791
966
 
792
- def makeAspectGridOnlySVG(self, minify: bool = False):
793
- """Prints out the SVG file in the specified folder with only the aspect grid"""
967
+ def makeAspectGridOnlySVG(self, minify: bool = False, remove_css_variables = False):
968
+ """
969
+ Generate and save aspect-grid-only chart SVG to disk.
970
+
971
+ Calls makeAspectGridOnlyTemplate and writes a file named
972
+ "{subject.name} - {chart_type} Chart - Aspect Grid Only.svg" in the output directory.
973
+
974
+ Args:
975
+ minify (bool): Pass-through to makeAspectGridOnlyTemplate for compact output.
976
+ remove_css_variables (bool): Pass-through to makeAspectGridOnlyTemplate to embed CSS variables.
977
+
978
+ Returns:
979
+ None
980
+ """
794
981
 
795
- template = self.makeAspectGridOnlyTemplate(minify)
982
+ template = self.makeAspectGridOnlyTemplate(minify, remove_css_variables)
796
983
  chartname = self.output_directory / f"{self.user.name} - {self.chart_type} Chart - Aspect Grid Only.svg"
797
984
 
798
985
  with open(chartname, "w", encoding="utf-8", errors="ignore") as output_file:
@@ -3,6 +3,7 @@ from kerykeion.kr_types.kr_literals import LunarPhaseEmoji, LunarPhaseName, Poin
3
3
  from typing import Union, get_args, TYPE_CHECKING
4
4
  import logging
5
5
  import math
6
+ import re
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from kerykeion import AstrologicalSubject
@@ -440,3 +441,57 @@ def circular_sort(degrees: list[Union[int, float]]) -> list[Union[int, float]]:
440
441
 
441
442
  # Return the reference followed by the sorted remaining elements
442
443
  return [reference] + sorted_remaining
444
+
445
+
446
+ def inline_css_variables_in_svg(svg_content: str) -> str:
447
+ """
448
+ Process an SVG string to inline all CSS custom properties.
449
+
450
+ Args:
451
+ svg_content (str): The original SVG string with CSS variables
452
+
453
+ Returns:
454
+ str: The modified SVG with all CSS variables replaced by their values
455
+ and all style blocks removed
456
+ """
457
+ # Find and extract CSS custom properties from style tags
458
+ css_variable_map = {}
459
+ style_tag_pattern = re.compile(r"<style.*?>(.*?)</style>", re.DOTALL)
460
+ style_blocks = style_tag_pattern.findall(svg_content)
461
+
462
+ # Parse all CSS custom properties from style blocks
463
+ for style_block in style_blocks:
464
+ # Match patterns like --color-primary: #ff0000;
465
+ css_variable_pattern = re.compile(r"--([a-zA-Z0-9_-]+)\s*:\s*([^;]+);")
466
+ for match in css_variable_pattern.finditer(style_block):
467
+ variable_name = match.group(1)
468
+ variable_value = match.group(2).strip()
469
+ css_variable_map[f"--{variable_name}"] = variable_value
470
+
471
+ # Remove all style blocks from the SVG
472
+ svg_without_style_blocks = style_tag_pattern.sub("", svg_content)
473
+
474
+ # Function to replace var() references with their actual values
475
+ def replace_css_variable_reference(match):
476
+ variable_name = match.group(1).strip()
477
+ fallback_value = match.group(2) if match.group(2) else None
478
+
479
+ if variable_name in css_variable_map:
480
+ return css_variable_map[variable_name]
481
+ elif fallback_value:
482
+ return fallback_value.strip(", ")
483
+ else:
484
+ return "" # If variable not found and no fallback provided
485
+
486
+ # Pattern to match var(--name) or var(--name, fallback)
487
+ variable_usage_pattern = re.compile(r"var\(\s*(--([\w-]+))\s*(,\s*([^)]+))?\s*\)")
488
+
489
+ # Repeatedly replace all var() references until none remain
490
+ # This handles nested variables or variables that reference other variables
491
+ processed_svg = svg_without_style_blocks
492
+ while variable_usage_pattern.search(processed_svg):
493
+ processed_svg = variable_usage_pattern.sub(
494
+ lambda m: replace_css_variable_reference(m), processed_svg
495
+ )
496
+
497
+ return processed_svg
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "kerykeion"
3
- version = "4.26.0rc1"
3
+ version = "4.26.1"
4
4
  authors = ["Giacomo Battaglia <kerykeion.astrology@gmail.com>"]
5
5
  description = "A python library for astrology."
6
6
  license = "AGPL-3.0"
File without changes