kerykeion 3.1.1__py3-none-any.whl → 5.1.9__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 (75) hide show
  1. kerykeion/__init__.py +58 -141
  2. kerykeion/aspects/__init__.py +14 -0
  3. kerykeion/aspects/aspects_factory.py +568 -0
  4. kerykeion/aspects/aspects_utils.py +164 -0
  5. kerykeion/astrological_subject_factory.py +1901 -0
  6. kerykeion/backword.py +820 -0
  7. kerykeion/chart_data_factory.py +552 -0
  8. kerykeion/charts/__init__.py +5 -0
  9. kerykeion/charts/chart_drawer.py +2794 -0
  10. kerykeion/charts/charts_utils.py +1840 -0
  11. kerykeion/charts/draw_planets.py +658 -0
  12. kerykeion/charts/templates/aspect_grid_only.xml +596 -0
  13. kerykeion/charts/templates/chart.xml +741 -0
  14. kerykeion/charts/templates/wheel_only.xml +653 -0
  15. kerykeion/charts/themes/black-and-white.css +148 -0
  16. kerykeion/charts/themes/classic.css +113 -0
  17. kerykeion/charts/themes/dark-high-contrast.css +159 -0
  18. kerykeion/charts/themes/dark.css +160 -0
  19. kerykeion/charts/themes/light.css +160 -0
  20. kerykeion/charts/themes/strawberry.css +158 -0
  21. kerykeion/composite_subject_factory.py +408 -0
  22. kerykeion/ephemeris_data_factory.py +443 -0
  23. kerykeion/fetch_geonames.py +105 -61
  24. kerykeion/house_comparison/__init__.py +6 -0
  25. kerykeion/house_comparison/house_comparison_factory.py +103 -0
  26. kerykeion/house_comparison/house_comparison_utils.py +126 -0
  27. kerykeion/kr_types/__init__.py +70 -0
  28. kerykeion/kr_types/chart_template_model.py +20 -0
  29. kerykeion/kr_types/kerykeion_exception.py +20 -0
  30. kerykeion/kr_types/kr_literals.py +20 -0
  31. kerykeion/kr_types/kr_models.py +20 -0
  32. kerykeion/kr_types/settings_models.py +20 -0
  33. kerykeion/planetary_return_factory.py +805 -0
  34. kerykeion/relationship_score_factory.py +301 -0
  35. kerykeion/report.py +779 -0
  36. kerykeion/schemas/__init__.py +106 -0
  37. kerykeion/schemas/chart_template_model.py +367 -0
  38. kerykeion/schemas/kerykeion_exception.py +20 -0
  39. kerykeion/schemas/kr_literals.py +181 -0
  40. kerykeion/schemas/kr_models.py +603 -0
  41. kerykeion/schemas/settings_models.py +188 -0
  42. kerykeion/settings/__init__.py +20 -0
  43. kerykeion/settings/chart_defaults.py +444 -0
  44. kerykeion/settings/config_constants.py +152 -0
  45. kerykeion/settings/kerykeion_settings.py +51 -0
  46. kerykeion/settings/translation_strings.py +1499 -0
  47. kerykeion/settings/translations.py +74 -0
  48. kerykeion/sweph/README.md +3 -0
  49. kerykeion/sweph/ast136/s136108s.se1 +0 -0
  50. kerykeion/sweph/ast136/s136199s.se1 +0 -0
  51. kerykeion/sweph/ast136/s136472s.se1 +0 -0
  52. kerykeion/sweph/ast28/se28978s.se1 +0 -0
  53. kerykeion/sweph/ast50/se50000s.se1 +0 -0
  54. kerykeion/sweph/ast90/se90377s.se1 +0 -0
  55. kerykeion/sweph/ast90/se90482s.se1 +0 -0
  56. kerykeion/sweph/seas_18.se1 +0 -0
  57. kerykeion/sweph/sefstars.txt +1602 -0
  58. kerykeion/transits_time_range_factory.py +302 -0
  59. kerykeion/utilities.py +762 -130
  60. kerykeion-5.1.9.dist-info/METADATA +1793 -0
  61. kerykeion-5.1.9.dist-info/RECORD +63 -0
  62. {kerykeion-3.1.1.dist-info → kerykeion-5.1.9.dist-info}/WHEEL +1 -2
  63. kerykeion-5.1.9.dist-info/licenses/LICENSE +661 -0
  64. kerykeion/aspects.py +0 -331
  65. kerykeion/charts/charts_svg.py +0 -1607
  66. kerykeion/charts/templates/basic.xml +0 -285
  67. kerykeion/charts/templates/extended.xml +0 -294
  68. kerykeion/kr.config.json +0 -464
  69. kerykeion/main.py +0 -595
  70. kerykeion/print_all_data.py +0 -44
  71. kerykeion/relationship_score.py +0 -219
  72. kerykeion/types.py +0 -190
  73. kerykeion-3.1.1.dist-info/METADATA +0 -204
  74. kerykeion-3.1.1.dist-info/RECORD +0 -17
  75. kerykeion-3.1.1.dist-info/top_level.txt +0 -1
@@ -1,43 +1,60 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
- This is part of Kerykeion (C) 2022 Giacomo Battaglia
3
+ Author: Giacomo Battaglia
4
+ Copyright: (C) 2025 Kerykeion Project
5
+ License: AGPL-3.0
3
6
  """
4
- #!/usr/bin/env python3
5
- # -*- coding: utf-8 -*-
6
7
 
7
- import logging
8
+
9
+ from logging import getLogger
10
+ from datetime import timedelta
11
+ from os import getenv
12
+ from pathlib import Path
13
+ from typing import Optional, Union
14
+
8
15
  from requests import Request
9
16
  from requests_cache import CachedSession
10
- from typing import Union
11
17
 
12
- logging.basicConfig(
13
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
14
- level=logging.INFO
15
- )
18
+
19
+ logger = getLogger(__name__)
20
+
21
+
22
+ DEFAULT_GEONAMES_CACHE_NAME = Path("cache") / "kerykeion_geonames_cache"
23
+ GEONAMES_CACHE_ENV_VAR = "KERYKEION_GEONAMES_CACHE_NAME"
16
24
 
17
25
 
18
26
  class FetchGeonames:
19
27
  """
20
- Class to handle requests to the geonames API
28
+ Class to handle requests to the GeoNames API for location data and timezone information.
29
+
30
+ This class provides cached access to the GeoNames API to retrieve location coordinates,
31
+ timezone information, and other geographical data for astrological calculations.
21
32
 
22
33
  Args:
23
- city_name (str): Name of the city
24
- country_code (str): Two letters country code
25
- username (str, optional): Geonames username, defaults to "century.boy".
26
- logger (Union[logging.Logger, None], optional):
27
- Optional logger, defaults to None. If none provided creates one.
34
+ city_name: Name of the city to search for.
35
+ country_code: Two-letter country code (ISO 3166-1 alpha-2).
36
+ username: GeoNames username for API access, defaults to "century.boy".
37
+ cache_expire_after_days: Number of days to cache responses, defaults to 30.
38
+ cache_name: Optional path (directory or filename stem) used by requests-cache.
39
+ Defaults to "cache/kerykeion_geonames_cache" and may also be overridden
40
+ via the environment variable ``KERYKEION_GEONAMES_CACHE_NAME`` or by
41
+ calling :meth:`FetchGeonames.set_default_cache_name`.
28
42
  """
29
43
 
44
+ default_cache_name: Path = DEFAULT_GEONAMES_CACHE_NAME
45
+
30
46
  def __init__(
31
- self, city_name: str,
47
+ self,
48
+ city_name: str,
32
49
  country_code: str,
33
50
  username: str = "century.boy",
34
- logger: Union[logging.Logger, None] = None
51
+ cache_expire_after_days=30,
52
+ cache_name: Optional[Union[str, Path]] = None,
35
53
  ):
36
-
37
54
  self.session = CachedSession(
38
- cache_name='cache/kerykeion_geonames_cache',
39
- backend='sqlite',
40
- expire_after=86400
55
+ cache_name=str(self._resolve_cache_name(cache_name)),
56
+ backend="sqlite",
57
+ expire_after=timedelta(days=cache_expire_after_days),
41
58
  )
42
59
 
43
60
  self.username = username
@@ -45,111 +62,138 @@ class FetchGeonames:
45
62
  self.country_code = country_code
46
63
  self.base_url = "http://api.geonames.org/searchJSON"
47
64
  self.timezone_url = "http://api.geonames.org/timezoneJSON"
48
- self.__logger = logger or logging.getLogger(self.__class__.__name__)
65
+
66
+ @classmethod
67
+ def set_default_cache_name(cls, cache_name: Union[str, Path]) -> None:
68
+ """Override the default cache name used when none is provided."""
69
+
70
+ cls.default_cache_name = Path(cache_name)
71
+
72
+ @classmethod
73
+ def _resolve_cache_name(cls, cache_name: Optional[Union[str, Path]]) -> Path:
74
+ """Return the resolved cache name applying overrides in priority order."""
75
+
76
+ if cache_name is not None:
77
+ return Path(cache_name)
78
+
79
+ env_override = getenv(GEONAMES_CACHE_ENV_VAR)
80
+ if env_override:
81
+ return Path(env_override)
82
+
83
+ return cls.default_cache_name
49
84
 
50
85
  def __get_timezone(self, lat: Union[str, float, int], lon: Union[str, float, int]) -> dict[str, str]:
51
86
  """
52
- Get the timezone for a given latitude and longitude
87
+ Get timezone information for a given latitude and longitude.
88
+
89
+ Args:
90
+ lat: Latitude coordinate.
91
+ lon: Longitude coordinate.
92
+
93
+ Returns:
94
+ dict: Timezone data including timezone string and cache status.
53
95
  """
54
96
  # Dictionary that will be returned:
55
97
  timezone_data = {}
56
98
 
57
- params = {
58
- "lat": lat,
59
- "lng": lon,
60
- "username": self.username
61
- }
99
+ params = {"lat": lat, "lng": lon, "username": self.username}
62
100
 
63
- prepared_request = Request(
64
- "GET", self.timezone_url, params=params).prepare()
65
- self.__logger.debug(
66
- f"Requesting data from geonames timezones: {prepared_request.url}")
101
+ prepared_request = Request("GET", self.timezone_url, params=params).prepare()
102
+ logger.debug("GeoNames timezone lookup url=%s", prepared_request.url)
67
103
 
68
104
  try:
69
105
  response = self.session.send(prepared_request)
70
106
  response_json = response.json()
71
107
 
72
108
  except Exception as e:
73
- self.__logger.error(f"Error fetching {self.timezone_url}: {e}")
109
+ logger.error("GeoNames timezone request failed for %s: %s", self.timezone_url, e)
74
110
  return {}
75
111
 
76
112
  try:
77
- timezone_data['timezonestr'] = response_json['timezoneId']
113
+ timezone_data["timezonestr"] = response_json["timezoneId"]
78
114
 
79
115
  except Exception as e:
80
- self.__logger.error(
81
- f"Error serializing data maybe wrong username? Details: {e}")
116
+ logger.error("GeoNames timezone payload missing expected keys: %s", e)
82
117
  return {}
83
118
 
84
- if hasattr(response, 'from_cache'):
85
- timezone_data['from_tz_cache'] = response.from_cache
119
+ if hasattr(response, "from_cache"):
120
+ timezone_data["from_tz_cache"] = response.from_cache # type: ignore
86
121
 
87
122
  return timezone_data
88
123
 
89
124
  def __get_contry_data(self, city_name: str, country_code: str) -> dict[str, str]:
90
125
  """
91
- Get the city data *whitout timezone* for a given city and country name
126
+ Get city location data without timezone for a given city and country.
127
+
128
+ Args:
129
+ city_name: Name of the city to search for.
130
+ country_code: Two-letter country code.
131
+
132
+ Returns:
133
+ dict: City location data excluding timezone information.
92
134
  """
93
135
  # Dictionary that will be returned:
94
136
  city_data_whitout_tz = {}
95
137
 
96
138
  params = {
97
139
  "q": city_name,
98
- "contry": country_code,
140
+ "country": country_code,
99
141
  "username": self.username,
100
142
  "maxRows": 1,
101
- "style": "FULL"
143
+ "style": "SHORT",
144
+ "featureClass": ["A", "P"],
102
145
  }
103
146
 
104
- prepared_request = Request(
105
- "GET", self.base_url, params=params).prepare()
106
- self.__logger.debug(
107
- f"Requesting data from geonames basic: {prepared_request.url}")
147
+ prepared_request = Request("GET", self.base_url, params=params).prepare()
148
+ logger.debug("GeoNames search url=%s", prepared_request.url)
108
149
 
109
150
  try:
110
151
  response = self.session.send(prepared_request)
152
+ response.raise_for_status()
111
153
  response_json = response.json()
154
+ logger.debug("GeoNames search response: %s", response_json)
112
155
 
113
156
  except Exception as e:
114
- self.__logger.error(f"Error in fetching {self.base_url}: {e}")
157
+ logger.error("GeoNames search request failed for %s: %s", self.base_url, e)
115
158
  return {}
116
159
 
117
160
  try:
118
- city_data_whitout_tz['name'] = response_json['geonames'][0]['name']
119
- city_data_whitout_tz['lat'] = response_json['geonames'][0]['lat']
120
- city_data_whitout_tz['lng'] = response_json['geonames'][0]['lng']
121
- city_data_whitout_tz['countryCode'] = response_json['geonames'][0]['countryCode']
161
+ city_data_whitout_tz["name"] = response_json["geonames"][0]["name"]
162
+ city_data_whitout_tz["lat"] = response_json["geonames"][0]["lat"]
163
+ city_data_whitout_tz["lng"] = response_json["geonames"][0]["lng"]
164
+ city_data_whitout_tz["countryCode"] = response_json["geonames"][0]["countryCode"]
122
165
 
123
166
  except Exception as e:
124
- self.__logger.error(
125
- f"Error serializing data maybe wrong username? Details: {e}")
167
+ logger.error("GeoNames search payload missing expected keys: %s", e)
126
168
  return {}
127
169
 
128
- if hasattr(response, 'from_cache'):
129
- city_data_whitout_tz['from_country_cache'] = response.from_cache
170
+ if hasattr(response, "from_cache"):
171
+ city_data_whitout_tz["from_country_cache"] = response.from_cache # type: ignore
130
172
 
131
173
  return city_data_whitout_tz
132
174
 
133
175
  def get_serialized_data(self) -> dict[str, str]:
134
176
  """
135
- Returns all the data necessary for the Kerykeion calculation.
177
+ Returns all the data necessary for the Kerykeion calculation.
136
178
 
137
179
  Returns:
138
180
  dict[str, str]: _description_
139
181
  """
140
- city_data_response = self.__get_contry_data(
141
- self.city_name, self.country_code)
182
+ city_data_response = self.__get_contry_data(self.city_name, self.country_code)
142
183
  try:
143
- timezone_response = self.__get_timezone(
144
- city_data_response['lat'], city_data_response['lng'])
184
+ timezone_response = self.__get_timezone(city_data_response["lat"], city_data_response["lng"])
145
185
 
146
186
  except Exception as e:
147
- self.__logger.error(f"Error in fetching timezone: {e}")
187
+ logger.error("Unable to fetch timezone details: %s", e)
148
188
  return {}
149
189
 
150
190
  return {**timezone_response, **city_data_response}
151
191
 
152
192
 
153
193
  if __name__ == "__main__":
154
- geonames = FetchGeonames("Roma", "IT")
194
+ """Run a tiny demonstration when executing the module directly."""
195
+ from kerykeion.utilities import setup_logging as configure_logging
196
+
197
+ configure_logging("debug")
198
+ geonames = FetchGeonames("Montichiari", "IT")
155
199
  print(geonames.get_serialized_data())
@@ -0,0 +1,6 @@
1
+
2
+ from .house_comparison_factory import HouseComparisonFactory
3
+
4
+ __all__ = [
5
+ "HouseComparisonFactory",
6
+ ]
@@ -0,0 +1,103 @@
1
+ """
2
+ House Comparison Factory Module
3
+
4
+ Provides factory class for house comparison analysis between astrological subjects.
5
+ Enables bidirectional analysis of astrological point placements in house systems.
6
+
7
+ Author: Giacomo Battaglia
8
+ Copyright: (C) 2025 Kerykeion Project
9
+ License: AGPL-3.0
10
+ """
11
+
12
+ from kerykeion.house_comparison.house_comparison_utils import calculate_points_in_reciprocal_houses
13
+ from typing import Union
14
+ from kerykeion.settings.config_constants import DEFAULT_ACTIVE_POINTS
15
+ from kerykeion.schemas.kr_models import HouseComparisonModel
16
+ from kerykeion.astrological_subject_factory import AstrologicalSubjectFactory
17
+ from kerykeion.schemas import AstrologicalSubjectModel, PlanetReturnModel
18
+ from kerykeion.schemas.kr_literals import AstrologicalPoint
19
+
20
+
21
+ class HouseComparisonFactory:
22
+ """
23
+ Factory for creating house comparison analyses between two astrological subjects.
24
+
25
+ Analyzes placement of astrological points from one subject within the house system
26
+ of another subject, performing bidirectional analysis for synastry studies and
27
+ subject comparisons. Supports both natal subjects and planetary return subjects.
28
+
29
+ Attributes:
30
+ first_subject: First astrological subject (natal or return subject)
31
+ second_subject: Second astrological subject (natal or return subject)
32
+ active_points: List of astrological points to include in analysis
33
+
34
+ Example:
35
+ >>> natal_chart = AstrologicalSubjectFactory.from_birth_data(
36
+ ... "Person A", 1990, 5, 15, 10, 30, "Rome", "IT"
37
+ ... )
38
+ >>> partner_chart = AstrologicalSubjectFactory.from_birth_data(
39
+ ... "Person B", 1992, 8, 23, 14, 45, "Milan", "IT"
40
+ ... )
41
+ >>> factory = HouseComparisonFactory(natal_chart, partner_chart)
42
+ >>> comparison = factory.get_house_comparison()
43
+
44
+ """
45
+ def __init__(self,
46
+ first_subject: Union["AstrologicalSubjectModel", "PlanetReturnModel"],
47
+ second_subject: Union["AstrologicalSubjectModel", "PlanetReturnModel"],
48
+ active_points: list[AstrologicalPoint] = DEFAULT_ACTIVE_POINTS,
49
+
50
+ ):
51
+ """
52
+ Initialize the house comparison factory.
53
+
54
+ Args:
55
+ first_subject: First astrological subject for comparison
56
+ second_subject: Second astrological subject for comparison
57
+ active_points: List of astrological points to include in analysis.
58
+ Defaults to standard active points.
59
+
60
+ Note:
61
+ Both subjects must have valid house system data for accurate analysis.
62
+ """
63
+ self.first_subject = first_subject
64
+ self.second_subject = second_subject
65
+ self.active_points = active_points
66
+
67
+ def get_house_comparison(self) -> "HouseComparisonModel":
68
+ """
69
+ Generate bidirectional house comparison analysis between the two subjects.
70
+
71
+ Calculates where each active astrological point from one subject falls within
72
+ the house system of the other subject, and vice versa.
73
+
74
+ Returns:
75
+ HouseComparisonModel: Model containing:
76
+ - first_subject_name: Name of the first subject
77
+ - second_subject_name: Name of the second subject
78
+ - first_points_in_second_houses: First subject's points in second subject's houses
79
+ - second_points_in_first_houses: Second subject's points in first subject's houses
80
+
81
+ Note:
82
+ Analysis scope is determined by the active_points list. Only specified
83
+ points will be included in the results.
84
+ """
85
+ first_points_in_second_houses = calculate_points_in_reciprocal_houses(self.first_subject, self.second_subject, self.active_points)
86
+ second_points_in_first_houses = calculate_points_in_reciprocal_houses(self.second_subject, self.first_subject, self.active_points)
87
+
88
+ return HouseComparisonModel(
89
+ first_subject_name=self.first_subject.name,
90
+ second_subject_name=self.second_subject.name,
91
+ first_points_in_second_houses=first_points_in_second_houses,
92
+ second_points_in_first_houses=second_points_in_first_houses,
93
+ )
94
+
95
+
96
+ if __name__ == "__main__":
97
+ natal_chart = AstrologicalSubjectFactory.from_birth_data("Person A", 1990, 5, 15, 10, 30, "Rome", "IT")
98
+ partner_chart = AstrologicalSubjectFactory.from_birth_data("Person B", 1992, 8, 23, 14, 45, "Milan", "IT")
99
+
100
+ factory = HouseComparisonFactory(natal_chart, partner_chart)
101
+ comparison = factory.get_house_comparison()
102
+
103
+ print(comparison.model_dump_json(indent=4))
@@ -0,0 +1,126 @@
1
+ """
2
+ House Comparison Utilities
3
+
4
+ Utility functions for calculating house placement relationships between astrological subjects.
5
+ Provides core calculation logic for determining where points from one subject fall within
6
+ another subject's house system.
7
+
8
+ Author: Giacomo Battaglia
9
+ Copyright: (C) 2025 Kerykeion Project
10
+ License: AGPL-3.0
11
+ """
12
+
13
+ from kerykeion.schemas.kr_models import AstrologicalSubjectModel, PlanetReturnModel, PointInHouseModel
14
+ from kerykeion.schemas.kr_literals import AstrologicalPoint
15
+ from kerykeion.settings.config_constants import DEFAULT_ACTIVE_POINTS
16
+ from kerykeion.utilities import get_planet_house, get_house_number
17
+ from typing import Union
18
+
19
+
20
+ def calculate_points_in_reciprocal_houses(
21
+ point_subject: Union[AstrologicalSubjectModel, PlanetReturnModel],
22
+ house_subject: Union[AstrologicalSubjectModel, PlanetReturnModel],
23
+ active_points: list[AstrologicalPoint] = DEFAULT_ACTIVE_POINTS,
24
+ ) -> list[PointInHouseModel]:
25
+ """
26
+ Calculate house placements of one subject's points within another subject's house system.
27
+
28
+ Analyzes where each astrological point from the point_subject falls within the
29
+ house structure of the house_subject. Creates detailed mapping including both
30
+ the point's original house position and its projected house placement.
31
+
32
+ Args:
33
+ point_subject: Subject whose astrological points are being analyzed
34
+ house_subject: Subject whose house system provides the projection framework
35
+ active_points: List of astrological points to include in the analysis.
36
+ Defaults to standard active points configuration.
37
+
38
+ Returns:
39
+ list[PointInHouseModel]: List of point placement models containing detailed
40
+ information about each point's house relationships,
41
+ including original and projected house positions.
42
+
43
+ Note:
44
+ Only processes points that exist in both the point_subject's active_points
45
+ and the provided active_points list. Points with None values are skipped.
46
+
47
+ Example:
48
+ >>> points_in_houses = calculate_points_in_reciprocal_houses(
49
+ ... natal_chart, partner_chart, ["Sun", "Moon"]
50
+ ... )
51
+ >>> sun_placement = points_in_houses[0] # Assuming Sun is first
52
+ >>> print(f"Sun falls in house: {sun_placement.projected_house_name}")
53
+ """
54
+ points_in_houses: list[PointInHouseModel] = []
55
+
56
+ # List of points to consider
57
+ celestial_points = []
58
+
59
+ for point in point_subject.active_points:
60
+ if point not in active_points:
61
+ continue
62
+
63
+ point_obj = getattr(point_subject, point.lower())
64
+ if point_obj is not None:
65
+ celestial_points.append(point_obj)
66
+
67
+ # Ordered list of house cusps degrees for house_subject
68
+ house_cusps = [
69
+ house_subject.first_house.abs_pos,
70
+ house_subject.second_house.abs_pos,
71
+ house_subject.third_house.abs_pos,
72
+ house_subject.fourth_house.abs_pos,
73
+ house_subject.fifth_house.abs_pos,
74
+ house_subject.sixth_house.abs_pos,
75
+ house_subject.seventh_house.abs_pos,
76
+ house_subject.eighth_house.abs_pos,
77
+ house_subject.ninth_house.abs_pos,
78
+ house_subject.tenth_house.abs_pos,
79
+ house_subject.eleventh_house.abs_pos,
80
+ house_subject.twelfth_house.abs_pos,
81
+ ]
82
+
83
+ # Ordered list of house cusps degrees for point_subject
84
+ point_subject_house_cusps = [
85
+ point_subject.first_house.abs_pos,
86
+ point_subject.second_house.abs_pos,
87
+ point_subject.third_house.abs_pos,
88
+ point_subject.fourth_house.abs_pos,
89
+ point_subject.fifth_house.abs_pos,
90
+ point_subject.sixth_house.abs_pos,
91
+ point_subject.seventh_house.abs_pos,
92
+ point_subject.eighth_house.abs_pos,
93
+ point_subject.ninth_house.abs_pos,
94
+ point_subject.tenth_house.abs_pos,
95
+ point_subject.eleventh_house.abs_pos,
96
+ point_subject.twelfth_house.abs_pos,
97
+ ]
98
+
99
+ # For each point, determine which house it falls in
100
+ for point in celestial_points:
101
+ if point is None:
102
+ continue
103
+
104
+ point_degree = point.abs_pos
105
+ house_name = get_planet_house(point_degree, house_cusps)
106
+ house_number = get_house_number(house_name)
107
+
108
+ # Find which house the point is in its own chart (point_subject)
109
+ point_owner_house_name = get_planet_house(point_degree, point_subject_house_cusps)
110
+ point_owner_house_number = get_house_number(point_owner_house_name)
111
+
112
+ point_in_house = PointInHouseModel(
113
+ point_name=point.name,
114
+ point_degree=point.position,
115
+ point_sign=point.sign,
116
+ point_owner_name=point_subject.name,
117
+ point_owner_house_name=point_owner_house_name,
118
+ point_owner_house_number=point_owner_house_number,
119
+ projected_house_number=house_number,
120
+ projected_house_name=house_name,
121
+ projected_house_owner_name=house_subject.name,
122
+ )
123
+
124
+ points_in_houses.append(point_in_house)
125
+
126
+ return points_in_houses
@@ -0,0 +1,70 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Backward compatibility module for Kerykeion v4.x imports.
4
+
5
+ DEPRECATED: This module will be removed in Kerykeion v6.0.
6
+ Please update your imports:
7
+ OLD: from kerykeion.kr_types import ...
8
+ NEW: from kerykeion.schemas import ...
9
+ """
10
+ import warnings
11
+
12
+ # Issue deprecation warning when this module is imported
13
+ warnings.warn(
14
+ "The 'kerykeion.kr_types' module is deprecated and will be removed in v6.0. "
15
+ "Please update your imports to use 'kerykeion.schemas' instead.",
16
+ DeprecationWarning,
17
+ stacklevel=2,
18
+ )
19
+
20
+ # Re-export everything from schemas for backward compatibility
21
+ from kerykeion.schemas import * # noqa: F401, F403
22
+ from kerykeion.schemas.kerykeion_exception import * # noqa: F401, F403
23
+ from kerykeion.schemas.kr_literals import * # noqa: F401, F403
24
+ from kerykeion.schemas.kr_models import * # noqa: F401, F403
25
+ from kerykeion.schemas.settings_models import * # noqa: F401, F403
26
+ from kerykeion.schemas.chart_template_model import * # noqa: F401, F403
27
+
28
+ __all__ = [
29
+ # Re-export from schemas
30
+ "KerykeionException",
31
+ # kr_literals
32
+ "ZodiacType",
33
+ "Sign",
34
+ "SignNumbers",
35
+ "AspectMovementType",
36
+ "Houses",
37
+ "HouseNumbers",
38
+ "AstrologicalPoint",
39
+ "Element",
40
+ "Quality",
41
+ "ChartType",
42
+ "PointType",
43
+ "LunarPhaseEmoji",
44
+ "LunarPhaseName",
45
+ "SiderealMode",
46
+ "HousesSystemIdentifier",
47
+ "PerspectiveType",
48
+ "SignsEmoji",
49
+ "KerykeionChartTheme",
50
+ "KerykeionChartLanguage",
51
+ "RelationshipScoreDescription",
52
+ "CompositeChartType",
53
+ "AspectName",
54
+ # kr_models
55
+ "AstrologicalSubjectModel",
56
+ "CompositeSubjectModel",
57
+ "KerykeionPointModel",
58
+ "AspectModel",
59
+ "ActiveAspect",
60
+ "SingleChartAspectsModel",
61
+ "DualChartAspectsModel",
62
+ "ElementDistributionModel",
63
+ "QualityDistributionModel",
64
+ "SingleChartDataModel",
65
+ "DualChartDataModel",
66
+ # settings_models
67
+ "KerykeionSettingsModel",
68
+ # chart_template_model
69
+ "ChartTemplateModel",
70
+ ]
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Backward compatibility module for chart_template_model.
4
+
5
+ DEPRECATED: This module will be removed in Kerykeion v6.0.
6
+ Please update your imports:
7
+ OLD: from kerykeion.kr_types.chart_template_model import ...
8
+ NEW: from kerykeion.schemas.chart_template_model import ...
9
+ """
10
+ import warnings
11
+
12
+ warnings.warn(
13
+ "The 'kerykeion.kr_types.chart_template_model' module is deprecated and will be removed in v6.0. "
14
+ "Please update your imports to use 'kerykeion.schemas.chart_template_model' instead.",
15
+ DeprecationWarning,
16
+ stacklevel=2,
17
+ )
18
+
19
+ # Re-export everything from schemas.chart_template_model for backward compatibility
20
+ from kerykeion.schemas.chart_template_model import * # noqa: F401, F403
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Backward compatibility module for kerykeion_exception.
4
+
5
+ DEPRECATED: This module will be removed in Kerykeion v6.0.
6
+ Please update your imports:
7
+ OLD: from kerykeion.kr_types.kerykeion_exception import ...
8
+ NEW: from kerykeion.schemas.kerykeion_exception import ...
9
+ """
10
+ import warnings
11
+
12
+ warnings.warn(
13
+ "The 'kerykeion.kr_types.kerykeion_exception' module is deprecated and will be removed in v6.0. "
14
+ "Please update your imports to use 'kerykeion.schemas.kerykeion_exception' instead.",
15
+ DeprecationWarning,
16
+ stacklevel=2,
17
+ )
18
+
19
+ # Re-export everything from schemas.kerykeion_exception for backward compatibility
20
+ from kerykeion.schemas.kerykeion_exception import * # noqa: F401, F403
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Backward compatibility module for kr_literals.
4
+
5
+ DEPRECATED: This module will be removed in Kerykeion v6.0.
6
+ Please update your imports:
7
+ OLD: from kerykeion.kr_types.kr_literals import ...
8
+ NEW: from kerykeion.schemas.kr_literals import ...
9
+ """
10
+ import warnings
11
+
12
+ warnings.warn(
13
+ "The 'kerykeion.kr_types.kr_literals' module is deprecated and will be removed in v6.0. "
14
+ "Please update your imports to use 'kerykeion.schemas.kr_literals' instead.",
15
+ DeprecationWarning,
16
+ stacklevel=2,
17
+ )
18
+
19
+ # Re-export everything from schemas.kr_literals for backward compatibility
20
+ from kerykeion.schemas.kr_literals import * # noqa: F401, F403
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Backward compatibility module for kr_models.
4
+
5
+ DEPRECATED: This module will be removed in Kerykeion v6.0.
6
+ Please update your imports:
7
+ OLD: from kerykeion.kr_types.kr_models import ...
8
+ NEW: from kerykeion.schemas.kr_models import ...
9
+ """
10
+ import warnings
11
+
12
+ warnings.warn(
13
+ "The 'kerykeion.kr_types.kr_models' module is deprecated and will be removed in v6.0. "
14
+ "Please update your imports to use 'kerykeion.schemas.kr_models' instead.",
15
+ DeprecationWarning,
16
+ stacklevel=2,
17
+ )
18
+
19
+ # Re-export everything from schemas.kr_models for backward compatibility
20
+ from kerykeion.schemas.kr_models import * # noqa: F401, F403
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Backward compatibility module for settings_models.
4
+
5
+ DEPRECATED: This module will be removed in Kerykeion v6.0.
6
+ Please update your imports:
7
+ OLD: from kerykeion.kr_types.settings_models import ...
8
+ NEW: from kerykeion.schemas.settings_models import ...
9
+ """
10
+ import warnings
11
+
12
+ warnings.warn(
13
+ "The 'kerykeion.kr_types.settings_models' module is deprecated and will be removed in v6.0. "
14
+ "Please update your imports to use 'kerykeion.schemas.settings_models' instead.",
15
+ DeprecationWarning,
16
+ stacklevel=2,
17
+ )
18
+
19
+ # Re-export everything from schemas.settings_models for backward compatibility
20
+ from kerykeion.schemas.settings_models import * # noqa: F401, F403