kerykeion 4.12.3__py3-none-any.whl → 4.14.2__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.

kerykeion/__init__.py CHANGED
@@ -14,3 +14,4 @@ from .aspects import SynastryAspects, NatalAspects
14
14
  from .report import Report
15
15
  from .settings import KerykeionSettingsModel, get_settings
16
16
  from .enums import Planets, Aspects, Signs
17
+ from .ephemeris_data import EphemerisDataFactory
@@ -131,17 +131,18 @@ def get_aspect_from_two_points(aspects_settings: dict, point_one: Union[float, i
131
131
  name = None
132
132
  distance = 0
133
133
  aspect_degrees = 0
134
- color = None
135
134
  aid = None
136
135
 
137
- return (
138
- verdict,
139
- name,
140
- distance - aspect_degrees,
141
- aspect_degrees,
142
- aid,
143
- diff,
144
- )
136
+
137
+ return {
138
+ "verdict": verdict,
139
+ "name": name,
140
+ "orbit": distance - aspect_degrees,
141
+ "distance": distance - aspect_degrees,
142
+ "aspect_degrees": aspect_degrees,
143
+ "aid": aid,
144
+ "diff": diff
145
+ }
145
146
 
146
147
 
147
148
  def planet_id_decoder(planets_settings: dict, name: str):
@@ -52,10 +52,18 @@ class NatalAspects:
52
52
  for first in range(len(active_points_list)):
53
53
  # Generates the aspects list without repetitions
54
54
  for second in range(first + 1, len(active_points_list)):
55
- verdict, name, orbit, aspect_degrees, aid, diff = get_aspect_from_two_points(
55
+ aspect = get_aspect_from_two_points(
56
56
  self.aspects_settings, active_points_list[first]["abs_pos"], active_points_list[second]["abs_pos"]
57
57
  )
58
58
 
59
+ verdict = aspect["verdict"]
60
+ name = aspect["name"]
61
+ orbit = aspect["orbit"]
62
+ aspect_degrees = aspect["aspect_degrees"]
63
+ aid = aspect["aid"]
64
+ diff = aspect["diff"]
65
+
66
+
59
67
  if verdict == True:
60
68
  d_asp = {
61
69
  "p1_name": active_points_list[first]["name"],
@@ -60,12 +60,20 @@ class SynastryAspects(NatalAspects):
60
60
  for first in range(len(first_active_points_list)):
61
61
  # Generates the aspects list whitout repetitions
62
62
  for second in range(len(second_active_points_list)):
63
- verdict, name, orbit, aspect_degrees, aid, diff = get_aspect_from_two_points(
63
+ aspect = get_aspect_from_two_points(
64
64
  self.aspects_settings,
65
65
  first_active_points_list[first]["abs_pos"],
66
66
  second_active_points_list[second]["abs_pos"],
67
67
  )
68
68
 
69
+ verdict = aspect["verdict"]
70
+ name = aspect["name"]
71
+ orbit = aspect["orbit"]
72
+ aspect_degrees = aspect["aspect_degrees"]
73
+ aid = aspect["aid"]
74
+ diff = aspect["diff"]
75
+
76
+
69
77
  if verdict == True:
70
78
  d_asp = {
71
79
  "p1_name": first_active_points_list[first]["name"],
@@ -96,7 +104,7 @@ if __name__ == "__main__":
96
104
  setup_logging(level="debug")
97
105
 
98
106
  john = AstrologicalSubject("John", 1940, 10, 9, 18, 30, "Liverpool")
99
- yoko = AstrologicalSubject("Yoko", 1933, 2, 18, 18, 30, "Tokyo")
107
+ yoko = AstrologicalSubject("Yoko", 1933, 2, 18, 18, 30, "Tokyo", "JP")
100
108
 
101
109
  synastry_aspects = SynastryAspects(john, yoko)
102
110
 
@@ -6,6 +6,7 @@
6
6
  import pytz
7
7
  import swisseph as swe
8
8
  import logging
9
+ import warnings
9
10
 
10
11
  from datetime import datetime
11
12
  from functools import cached_property
@@ -75,8 +76,7 @@ class AstrologicalSubject:
75
76
  You can get one for free here: https://www.geonames.org/login
76
77
  - online (bool, optional): Sets if you want to use the online mode, which fetches the timezone and coordinates from geonames.
77
78
  If you already have the coordinates and timezone, set this to False. Defaults to True.
78
- - disable_chiron (bool, optional): Disables the calculation of Chiron. Defaults to False.
79
- Chiron calculation can create some issues with the Swiss Ephemeris when the date is too far in the past.
79
+ - disable_chiron: Deprecated, use disable_chiron_and_lilith instead.
80
80
  - sidereal_mode (SiderealMode, optional): Also known as Ayanamsa.
81
81
  The mode to use for the sidereal zodiac, according to the Swiss Ephemeris.
82
82
  Defaults to "FAGAN_BRADLEY".
@@ -87,6 +87,11 @@ class AstrologicalSubject:
87
87
  - perspective_type (PerspectiveType, optional): The perspective to use for the calculation of the chart.
88
88
  Defaults to "Apparent Geocentric".
89
89
  Available perspectives are visible in the PerspectiveType Literal.
90
+ - is_dst (Union[None, bool], optional): Specify if the time is in DST. Defaults to None.
91
+ By default (None), the library will try to guess if the time is in DST or not and raise an AmbiguousTimeError
92
+ if it can't guess. If you know the time is in DST, set this to True, if you know it's not, set it to False.
93
+ - disable_chiron_and_lilith (bool, optional): boolean representing if Chiron and Lilith should be disabled. Default is False.
94
+ Chiron calculation can create some issues with the Swiss Ephemeris when the date is too far in the past.
90
95
  """
91
96
 
92
97
  # Defined by the user
@@ -96,18 +101,19 @@ class AstrologicalSubject:
96
101
  day: int
97
102
  hour: int
98
103
  minute: int
99
- city: str
100
- nation: str
101
- lng: Union[int, float]
102
- lat: Union[int, float]
103
- tz_str: str
104
- geonames_username: str
104
+ city: Union[str, None]
105
+ nation: Union[str, None]
106
+ lng: Union[int, float, None]
107
+ lat: Union[int, float, None]
108
+ tz_str: Union[str, None]
109
+ geonames_username: Union[str, None]
105
110
  online: bool
106
111
  zodiac_type: ZodiacType
107
- sidereal_mode: SiderealMode
112
+ sidereal_mode: Union[SiderealMode, None]
108
113
  houses_system_identifier: HousesSystemIdentifier
109
114
  houses_system_name: str
110
115
  perspective_type: PerspectiveType
116
+ is_dst: Union[None, bool]
111
117
 
112
118
  # Generated internally
113
119
  city_data: dict[str, str]
@@ -130,6 +136,7 @@ class AstrologicalSubject:
130
136
  true_node: KerykeionPointModel
131
137
  mean_node: KerykeionPointModel
132
138
  chiron: Union[KerykeionPointModel, None]
139
+ mean_lilit: Union[KerykeionPointModel, None]
133
140
 
134
141
  # Houses
135
142
  first_house: KerykeionPointModel
@@ -151,6 +158,10 @@ class AstrologicalSubject:
151
158
  planets_degrees_ut: list[float]
152
159
  houses_degree_ut: list[float]
153
160
 
161
+ # Enable or disable features
162
+ disable_chiron: bool # Deprecated
163
+ disable_chiron_and_lilith: bool
164
+
154
165
  def __init__(
155
166
  self,
156
167
  name="Now",
@@ -167,13 +178,29 @@ class AstrologicalSubject:
167
178
  geonames_username: Union[str, None] = None,
168
179
  zodiac_type: ZodiacType = DEFAULT_ZODIAC_TYPE,
169
180
  online: bool = True,
170
- disable_chiron: bool = False,
181
+ disable_chiron: Union[None, bool] = None,
171
182
  sidereal_mode: Union[SiderealMode, None] = None,
172
183
  houses_system_identifier: HousesSystemIdentifier = DEFAULT_HOUSES_SYSTEM_IDENTIFIER,
173
- perspective_type: PerspectiveType = DEFAULT_PERSPECTIVE_TYPE
184
+ perspective_type: PerspectiveType = DEFAULT_PERSPECTIVE_TYPE,
185
+ is_dst: Union[None, bool] = None,
186
+ disable_chiron_and_lilith: bool = False
174
187
  ) -> None:
175
188
  logging.debug("Starting Kerykeion")
176
189
 
190
+ # Deprecation warnings --->
191
+ if disable_chiron is not None:
192
+ warnings.warn(
193
+ "The 'disable_chiron' argument is deprecated and will be removed in a future version. "
194
+ "Please use 'disable_chiron' instead.",
195
+ DeprecationWarning
196
+ )
197
+
198
+ if disable_chiron_and_lilith:
199
+ raise ValueError("Cannot specify both 'disable_chiron' and 'disable_chiron_and_lilith'. Use 'disable_chiron_and_lilith' only.")
200
+
201
+ self.disable_chiron_and_lilith = disable_chiron
202
+ # <--- Deprecation warnings
203
+
177
204
  self.name = name
178
205
  self.year = year
179
206
  self.month = month
@@ -193,6 +220,8 @@ class AstrologicalSubject:
193
220
  self.sidereal_mode = sidereal_mode
194
221
  self.houses_system_identifier = houses_system_identifier
195
222
  self.perspective_type = perspective_type
223
+ self.is_dst = is_dst
224
+ self.disable_chiron_and_lilith = disable_chiron_and_lilith
196
225
 
197
226
  #---------------#
198
227
  # General setup #
@@ -200,9 +229,7 @@ class AstrologicalSubject:
200
229
 
201
230
  # This message is set to encourage the user to set a custom geonames username
202
231
  if geonames_username is None and online:
203
- logging.warning(
204
-
205
- )
232
+ logging.warning(GEONAMES_DEFAULT_USERNAME_WARNING)
206
233
 
207
234
  self.geonames_username = DEFAULT_GEONAMES_USERNAME
208
235
 
@@ -214,11 +241,11 @@ class AstrologicalSubject:
214
241
  self.nation = "GB"
215
242
  logging.info("No nation specified, using GB as default")
216
243
 
217
- if not self.lat:
244
+ if not self.lat and not self.online:
218
245
  self.lat = 51.5074
219
246
  logging.info("No latitude specified, using London as default")
220
247
 
221
- if not self.lng:
248
+ if not self.lng and not self.online:
222
249
  self.lng = 0
223
250
  logging.info("No longitude specified, using London as default")
224
251
 
@@ -246,6 +273,8 @@ class AstrologicalSubject:
246
273
  elif self.perspective_type == "Topocentric":
247
274
  self._iflag += swe.FLG_TOPOCTR
248
275
  # geopos_is_set, for topocentric
276
+ if (self.online) and (not self.tz_str) and (not self.lat) and (not self.lng):
277
+ self._fetch_and_set_tz_and_coordinates_from_geonames()
249
278
  swe.set_topo(self.lng, self.lat, 0)
250
279
  # <--- Chart Perspective check and setup
251
280
 
@@ -281,17 +310,22 @@ class AstrologicalSubject:
281
310
  #------------------------#
282
311
  # Start the calculations #
283
312
  #------------------------#
284
-
285
- check_and_adjust_polar_latitude(self.lat, self.lng)
286
313
 
287
314
  # UTC, julian day and local time setup --->
288
- if (self.online) and (not self.tz_str):
289
- self._fetch_tz_from_geonames()
315
+ if (self.online) and (not self.tz_str) and (not self.lat) and (not self.lng):
316
+ self._fetch_and_set_tz_and_coordinates_from_geonames()
317
+
318
+ self.lat = check_and_adjust_polar_latitude(self.lat)
290
319
 
291
320
  # Local time to UTC
292
321
  local_time = pytz.timezone(self.tz_str)
293
322
  naive_datetime = datetime(self.year, self.month, self.day, self.hour, self.minute, 0)
294
- local_datetime = local_time.localize(naive_datetime, is_dst=None)
323
+
324
+ try:
325
+ local_datetime = local_time.localize(naive_datetime, is_dst=self.is_dst)
326
+ except pytz.exceptions.AmbiguousTimeError:
327
+ raise KerykeionException("Ambiguous time! Please specify if the time is in DST or not with the is_dst argument.")
328
+
295
329
  utc_object = local_datetime.astimezone(pytz.utc)
296
330
  self.iso_formatted_utc_datetime = utc_object.isoformat()
297
331
 
@@ -325,7 +359,7 @@ class AstrologicalSubject:
325
359
  def get(self, item, default=None):
326
360
  return getattr(self, item, default)
327
361
 
328
- def _fetch_tz_from_geonames(self) -> None:
362
+ def _fetch_and_set_tz_and_coordinates_from_geonames(self) -> None:
329
363
  """Gets the nearest time zone for the calculation"""
330
364
  logging.info("Fetching timezone/coordinates from geonames")
331
365
 
@@ -349,8 +383,6 @@ class AstrologicalSubject:
349
383
  self.lat = float(self.city_data["lat"])
350
384
  self.tz_str = self.city_data["timezonestr"]
351
385
 
352
- check_and_adjust_polar_latitude(self.lat, self.lng)
353
-
354
386
  def _houses(self) -> None:
355
387
  """
356
388
  Calculate positions and store them in dictionaries
@@ -447,11 +479,6 @@ class AstrologicalSubject:
447
479
  pluto_deg = swe.calc(self.julian_day, 9, self._iflag)[0][0]
448
480
  mean_node_deg = swe.calc(self.julian_day, 10, self._iflag)[0][0]
449
481
  true_node_deg = swe.calc(self.julian_day, 11, self._iflag)[0][0]
450
-
451
- if not self.disable_chiron:
452
- chiron_deg = swe.calc(self.julian_day, 15, self._iflag)[0][0]
453
- else:
454
- chiron_deg = 0
455
482
 
456
483
  self.planets_degrees_ut = [
457
484
  sun_deg,
@@ -468,9 +495,18 @@ class AstrologicalSubject:
468
495
  true_node_deg,
469
496
  ]
470
497
 
471
- if not self.disable_chiron:
498
+ if not self.disable_chiron_and_lilith:
499
+ chiron_deg = swe.calc(self.julian_day, 15, self._iflag)[0][0]
472
500
  self.planets_degrees_ut.append(chiron_deg)
473
501
 
502
+ mean_lilith_deg = swe.calc(self.julian_day, 12, self._iflag)[0][0]
503
+ self.planets_degrees_ut.append(mean_lilith_deg)
504
+
505
+ else:
506
+ self.chiron = None
507
+ self.mean_lilith = None
508
+
509
+
474
510
  def _planets(self) -> None:
475
511
  """Defines body positon in signs and information and
476
512
  stores them in dictionaries"""
@@ -490,10 +526,14 @@ class AstrologicalSubject:
490
526
  self.mean_node = calculate_position(self.planets_degrees_ut[10], "Mean_Node", point_type=point_type)
491
527
  self.true_node = calculate_position(self.planets_degrees_ut[11], "True_Node", point_type=point_type)
492
528
 
493
- if not self.disable_chiron:
529
+ if not self.disable_chiron_and_lilith:
494
530
  self.chiron = calculate_position(self.planets_degrees_ut[12], "Chiron", point_type=point_type)
531
+ self.mean_lilith = calculate_position(self.planets_degrees_ut[13], "Mean_Lilith", point_type=point_type)
532
+
495
533
  else:
496
534
  self.chiron = None
535
+ self.mean_lilith = None
536
+
497
537
 
498
538
  def _planets_in_houses(self) -> None:
499
539
  """Calculates the house of the planet and updates
@@ -512,11 +552,6 @@ class AstrologicalSubject:
512
552
  self.mean_node.house = get_planet_house(self.planets_degrees_ut[10], self.houses_degree_ut)
513
553
  self.true_node.house = get_planet_house(self.planets_degrees_ut[11], self.houses_degree_ut)
514
554
 
515
- if not self.disable_chiron:
516
- self.chiron.house = get_planet_house(self.planets_degrees_ut[12], self.houses_degree_ut)
517
- else:
518
- self.chiron = None
519
-
520
555
  self.planets_list = [
521
556
  self.sun,
522
557
  self.moon,
@@ -532,9 +567,17 @@ class AstrologicalSubject:
532
567
  self.true_node,
533
568
  ]
534
569
 
535
- if not self.disable_chiron:
570
+ if not self.disable_chiron_and_lilith:
571
+ self.chiron.house = get_planet_house(self.planets_degrees_ut[12], self.houses_degree_ut)
536
572
  self.planets_list.append(self.chiron)
537
573
 
574
+ self.mean_lilith.house = get_planet_house(self.planets_degrees_ut[13], self.houses_degree_ut)
575
+ self.planets_list.append(self.mean_lilith)
576
+
577
+ else:
578
+ self.chiron = None
579
+ self.mean_lilith = None
580
+
538
581
  # Check in retrograde or not:
539
582
  planets_ret = []
540
583
  for planet in self.planets_list:
@@ -698,7 +741,7 @@ class AstrologicalSubject:
698
741
  lat: Union[int, float] = 51.5074,
699
742
  geonames_username: str = DEFAULT_GEONAMES_USERNAME,
700
743
  zodiac_type: ZodiacType = DEFAULT_ZODIAC_TYPE,
701
- disable_chiron: bool = False,
744
+ disable_chiron_and_lilith: bool = False,
702
745
  sidereal_mode: Union[SiderealMode, None] = None,
703
746
  houses_system_identifier: HousesSystemIdentifier = DEFAULT_HOUSES_SYSTEM_IDENTIFIER,
704
747
  perspective_type: PerspectiveType = DEFAULT_PERSPECTIVE_TYPE
@@ -721,7 +764,7 @@ class AstrologicalSubject:
721
764
  - geonames_username (str, optional): The username for the geonames API. Note: Change this to your own username to avoid rate limits!
722
765
  You can get one for free here: https://www.geonames.org/login
723
766
  - zodiac_type (ZodiacType, optional): The zodiac type to use. Defaults to "Tropic".
724
- - disable_chiron (bool, optional): Disables the calculation of Chiron. Defaults to False.
767
+ - disable_chiron_and_lilith: boolean representing if Chiron and Lilith should be disabled. Default is False.
725
768
  Chiron calculation can create some issues with the Swiss Ephemeris when the date is too far in the past.
726
769
  - sidereal_mode (SiderealMode, optional): Also known as Ayanamsa.
727
770
  The mode to use for the sidereal zodiac, according to the Swiss Ephemeris.
@@ -767,10 +810,10 @@ class AstrologicalSubject:
767
810
  online=False,
768
811
  geonames_username=geonames_username,
769
812
  zodiac_type=zodiac_type,
770
- disable_chiron=disable_chiron,
771
813
  sidereal_mode=sidereal_mode,
772
814
  houses_system_identifier=houses_system_identifier,
773
- perspective_type=perspective_type
815
+ perspective_type=perspective_type,
816
+ disable_chiron_and_lilith=disable_chiron_and_lilith
774
817
  )
775
818
 
776
819
  return subject
@@ -812,4 +855,8 @@ if __name__ == "__main__":
812
855
  print(johnny.json(dump=True, indent=2))
813
856
 
814
857
  # With Topocentric Perspective
815
- johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", perspective_type="Topocentric")
858
+ johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", perspective_type="Topocentric")
859
+
860
+ # Test Mean Lilith
861
+ johnny = AstrologicalSubject("Johnny Depp", 1963, 6, 9, 0, 0, "Owensboro", "US", disable_chiron_and_lilith=True)
862
+ print(johnny.mean_lilith)