divineapi 1.2.0__tar.gz → 1.3.0__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.
- {divineapi-1.2.0 → divineapi-1.3.0}/PKG-INFO +18 -12
- {divineapi-1.2.0 → divineapi-1.3.0}/README.md +17 -11
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/__init__.py +6 -4
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/calculators.py +2 -2
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/horoscope.py +27 -11
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/pdf.py +23 -16
- divineapi-1.3.0/divineapi/western/_house_system.py +52 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/composite.py +2 -1
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/natal.py +5 -4
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/planet_returns.py +5 -3
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/prenatal.py +2 -1
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/progressions.py +16 -5
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/synastry.py +2 -1
- divineapi-1.3.0/divineapi/western/transit.py +218 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi.egg-info/PKG-INFO +18 -12
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi.egg-info/SOURCES.txt +1 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/pyproject.toml +1 -1
- divineapi-1.2.0/divineapi/western/transit.py +0 -110
- {divineapi-1.2.0 → divineapi-1.3.0}/LICENSE +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/client.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/exceptions.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/indian/__init__.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/indian/festival.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/indian/kundli.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/indian/match_making.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/indian/panchang.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/lifestyle.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/numerology.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/py.typed +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi/western/__init__.py +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi.egg-info/dependency_links.txt +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi.egg-info/requires.txt +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/divineapi.egg-info/top_level.txt +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/setup.cfg +0 -0
- {divineapi-1.2.0 → divineapi-1.3.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: divineapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Official Python SDK for the Divine API - Astrology, Numerology, Tarot & more
|
|
5
5
|
Author-email: Divine API <support@divineapi.com>
|
|
6
6
|
License: MIT
|
|
@@ -51,9 +51,9 @@ from divineapi import DivineApi
|
|
|
51
51
|
|
|
52
52
|
client = DivineApi(api_key="your-api-key", auth_token="your-bearer-token")
|
|
53
53
|
|
|
54
|
-
# Daily Horoscope
|
|
54
|
+
# Daily Horoscope (h_day = today, tomorrow, or yesterday)
|
|
55
55
|
result = client.horoscope.daily(
|
|
56
|
-
sign="aries",
|
|
56
|
+
sign="aries", h_day="today", tzone=5.5
|
|
57
57
|
)
|
|
58
58
|
print(result)
|
|
59
59
|
```
|
|
@@ -64,10 +64,11 @@ print(result)
|
|
|
64
64
|
|
|
65
65
|
```python
|
|
66
66
|
# Daily / Weekly / Monthly / Yearly Horoscope
|
|
67
|
-
|
|
68
|
-
client.horoscope.
|
|
69
|
-
client.horoscope.
|
|
70
|
-
client.horoscope.
|
|
67
|
+
# daily h_day = today / tomorrow / yesterday; weekly/monthly/yearly = current / prev / next
|
|
68
|
+
client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
69
|
+
client.horoscope.weekly(sign="leo", week="current", tzone=5.5)
|
|
70
|
+
client.horoscope.monthly(sign="cancer", month="current", tzone=5.5)
|
|
71
|
+
client.horoscope.yearly(sign="virgo", year="current", tzone=5.5)
|
|
71
72
|
|
|
72
73
|
# Chinese & Numerology Horoscope
|
|
73
74
|
client.horoscope.chinese(sign="rat", h_day="today", tzone=5.5)
|
|
@@ -164,8 +165,9 @@ client.indian.festival.chaitra_festivals(
|
|
|
164
165
|
client.indian.festival.english_calendar(
|
|
165
166
|
year=2024, month=3, place="Delhi", lat=28.6, lon=77.2, tzone=5.5
|
|
166
167
|
)
|
|
168
|
+
# festival is a lowercase snake_case slug from the Divine festival list
|
|
167
169
|
client.indian.festival.find_festival(
|
|
168
|
-
festival="
|
|
170
|
+
festival="maha_shivratri", year=2024,
|
|
169
171
|
place="Delhi", lat=28.6, lon=77.2, tzone=5.5
|
|
170
172
|
)
|
|
171
173
|
client.indian.festival.malayalam_festivals(
|
|
@@ -193,7 +195,7 @@ client.western.natal.house_cusps(**birth_w)
|
|
|
193
195
|
client.western.natal.aspect_table(**birth_w)
|
|
194
196
|
client.western.natal.natal_wheel_chart(**birth_w)
|
|
195
197
|
client.western.natal.natal_insights(**birth_w)
|
|
196
|
-
client.western.natal.dominants(method="
|
|
198
|
+
client.western.natal.dominants(method="TRADITIONAL", **birth_w)
|
|
197
199
|
```
|
|
198
200
|
|
|
199
201
|
### Western Astrology - Synastry
|
|
@@ -252,7 +254,7 @@ client.lifestyle.astro_chic_picks(sign="virgo", h_day="today", tzone=5.5)
|
|
|
252
254
|
### Calculators
|
|
253
255
|
|
|
254
256
|
```python
|
|
255
|
-
client.calculators.flames(
|
|
257
|
+
client.calculators.flames(your_name="John", partner_name="Jane")
|
|
256
258
|
client.calculators.love_calculator(
|
|
257
259
|
your_name="John", partner_name="Jane",
|
|
258
260
|
your_gender="male", partner_gender="female",
|
|
@@ -262,11 +264,15 @@ client.calculators.love_calculator(
|
|
|
262
264
|
### PDF Reports
|
|
263
265
|
|
|
264
266
|
```python
|
|
267
|
+
# The six branding fields (company_url, logo_url, footer_text, company_name,
|
|
268
|
+
# company_email, company_bio) are REQUIRED by the PDF backend.
|
|
265
269
|
client.pdf.kundali_sampoorna(
|
|
266
270
|
full_name="John", day=1, month=1, year=1990,
|
|
267
271
|
hour=10, min=30, sec=0, gender="male",
|
|
268
272
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
269
273
|
company_name="AstroCo", company_url="https://example.com",
|
|
274
|
+
company_email="hello@example.com", company_bio="We do astrology.",
|
|
275
|
+
logo_url="https://example.com/logo.png", footer_text="(c) AstroCo",
|
|
270
276
|
)
|
|
271
277
|
```
|
|
272
278
|
|
|
@@ -278,7 +284,7 @@ from divineapi import DivineApi, AuthenticationError, ValidationError, RateLimit
|
|
|
278
284
|
client = DivineApi(api_key="...", auth_token="...")
|
|
279
285
|
|
|
280
286
|
try:
|
|
281
|
-
result = client.horoscope.daily(sign="aries",
|
|
287
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
282
288
|
except AuthenticationError as e:
|
|
283
289
|
print(f"Auth failed: {e}")
|
|
284
290
|
except ValidationError as e:
|
|
@@ -291,7 +297,7 @@ except RateLimitError as e:
|
|
|
291
297
|
|
|
292
298
|
```python
|
|
293
299
|
with DivineApi(api_key="...", auth_token="...") as client:
|
|
294
|
-
result = client.horoscope.daily(sign="aries",
|
|
300
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
295
301
|
```
|
|
296
302
|
|
|
297
303
|
## Configuration
|
|
@@ -23,9 +23,9 @@ from divineapi import DivineApi
|
|
|
23
23
|
|
|
24
24
|
client = DivineApi(api_key="your-api-key", auth_token="your-bearer-token")
|
|
25
25
|
|
|
26
|
-
# Daily Horoscope
|
|
26
|
+
# Daily Horoscope (h_day = today, tomorrow, or yesterday)
|
|
27
27
|
result = client.horoscope.daily(
|
|
28
|
-
sign="aries",
|
|
28
|
+
sign="aries", h_day="today", tzone=5.5
|
|
29
29
|
)
|
|
30
30
|
print(result)
|
|
31
31
|
```
|
|
@@ -36,10 +36,11 @@ print(result)
|
|
|
36
36
|
|
|
37
37
|
```python
|
|
38
38
|
# Daily / Weekly / Monthly / Yearly Horoscope
|
|
39
|
-
|
|
40
|
-
client.horoscope.
|
|
41
|
-
client.horoscope.
|
|
42
|
-
client.horoscope.
|
|
39
|
+
# daily h_day = today / tomorrow / yesterday; weekly/monthly/yearly = current / prev / next
|
|
40
|
+
client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
41
|
+
client.horoscope.weekly(sign="leo", week="current", tzone=5.5)
|
|
42
|
+
client.horoscope.monthly(sign="cancer", month="current", tzone=5.5)
|
|
43
|
+
client.horoscope.yearly(sign="virgo", year="current", tzone=5.5)
|
|
43
44
|
|
|
44
45
|
# Chinese & Numerology Horoscope
|
|
45
46
|
client.horoscope.chinese(sign="rat", h_day="today", tzone=5.5)
|
|
@@ -136,8 +137,9 @@ client.indian.festival.chaitra_festivals(
|
|
|
136
137
|
client.indian.festival.english_calendar(
|
|
137
138
|
year=2024, month=3, place="Delhi", lat=28.6, lon=77.2, tzone=5.5
|
|
138
139
|
)
|
|
140
|
+
# festival is a lowercase snake_case slug from the Divine festival list
|
|
139
141
|
client.indian.festival.find_festival(
|
|
140
|
-
festival="
|
|
142
|
+
festival="maha_shivratri", year=2024,
|
|
141
143
|
place="Delhi", lat=28.6, lon=77.2, tzone=5.5
|
|
142
144
|
)
|
|
143
145
|
client.indian.festival.malayalam_festivals(
|
|
@@ -165,7 +167,7 @@ client.western.natal.house_cusps(**birth_w)
|
|
|
165
167
|
client.western.natal.aspect_table(**birth_w)
|
|
166
168
|
client.western.natal.natal_wheel_chart(**birth_w)
|
|
167
169
|
client.western.natal.natal_insights(**birth_w)
|
|
168
|
-
client.western.natal.dominants(method="
|
|
170
|
+
client.western.natal.dominants(method="TRADITIONAL", **birth_w)
|
|
169
171
|
```
|
|
170
172
|
|
|
171
173
|
### Western Astrology - Synastry
|
|
@@ -224,7 +226,7 @@ client.lifestyle.astro_chic_picks(sign="virgo", h_day="today", tzone=5.5)
|
|
|
224
226
|
### Calculators
|
|
225
227
|
|
|
226
228
|
```python
|
|
227
|
-
client.calculators.flames(
|
|
229
|
+
client.calculators.flames(your_name="John", partner_name="Jane")
|
|
228
230
|
client.calculators.love_calculator(
|
|
229
231
|
your_name="John", partner_name="Jane",
|
|
230
232
|
your_gender="male", partner_gender="female",
|
|
@@ -234,11 +236,15 @@ client.calculators.love_calculator(
|
|
|
234
236
|
### PDF Reports
|
|
235
237
|
|
|
236
238
|
```python
|
|
239
|
+
# The six branding fields (company_url, logo_url, footer_text, company_name,
|
|
240
|
+
# company_email, company_bio) are REQUIRED by the PDF backend.
|
|
237
241
|
client.pdf.kundali_sampoorna(
|
|
238
242
|
full_name="John", day=1, month=1, year=1990,
|
|
239
243
|
hour=10, min=30, sec=0, gender="male",
|
|
240
244
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
241
245
|
company_name="AstroCo", company_url="https://example.com",
|
|
246
|
+
company_email="hello@example.com", company_bio="We do astrology.",
|
|
247
|
+
logo_url="https://example.com/logo.png", footer_text="(c) AstroCo",
|
|
242
248
|
)
|
|
243
249
|
```
|
|
244
250
|
|
|
@@ -250,7 +256,7 @@ from divineapi import DivineApi, AuthenticationError, ValidationError, RateLimit
|
|
|
250
256
|
client = DivineApi(api_key="...", auth_token="...")
|
|
251
257
|
|
|
252
258
|
try:
|
|
253
|
-
result = client.horoscope.daily(sign="aries",
|
|
259
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
254
260
|
except AuthenticationError as e:
|
|
255
261
|
print(f"Auth failed: {e}")
|
|
256
262
|
except ValidationError as e:
|
|
@@ -263,7 +269,7 @@ except RateLimitError as e:
|
|
|
263
269
|
|
|
264
270
|
```python
|
|
265
271
|
with DivineApi(api_key="...", auth_token="...") as client:
|
|
266
|
-
result = client.horoscope.daily(sign="aries",
|
|
272
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
267
273
|
```
|
|
268
274
|
|
|
269
275
|
## Configuration
|
|
@@ -5,7 +5,7 @@ Usage::
|
|
|
5
5
|
from divineapi import DivineApi
|
|
6
6
|
|
|
7
7
|
client = DivineApi(api_key="your-api-key", auth_token="your-bearer-token")
|
|
8
|
-
result = client.horoscope.daily(sign="aries",
|
|
8
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
9
9
|
print(result)
|
|
10
10
|
"""
|
|
11
11
|
|
|
@@ -29,7 +29,7 @@ from .numerology import NumerologyApi
|
|
|
29
29
|
from .pdf import PdfReportApi
|
|
30
30
|
from .western import WesternApi
|
|
31
31
|
|
|
32
|
-
__version__ = "1.
|
|
32
|
+
__version__ = "1.3.0"
|
|
33
33
|
|
|
34
34
|
__all__ = [
|
|
35
35
|
"DivineApi",
|
|
@@ -57,7 +57,7 @@ class DivineApi:
|
|
|
57
57
|
client = DivineApi(api_key="...", auth_token="...")
|
|
58
58
|
|
|
59
59
|
# Horoscope & Tarot
|
|
60
|
-
client.horoscope.daily(sign="aries",
|
|
60
|
+
client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
61
61
|
|
|
62
62
|
# Indian Panchang
|
|
63
63
|
client.indian.panchang.find_panchang(
|
|
@@ -100,7 +100,9 @@ class DivineApi:
|
|
|
100
100
|
full_name="John", day=1, month=1, year=1990,
|
|
101
101
|
hour=10, min=30, sec=0, gender="male",
|
|
102
102
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
103
|
-
company_name="MyCompany",
|
|
103
|
+
company_name="MyCompany", company_url="https://example.com",
|
|
104
|
+
company_email="hello@example.com", company_bio="We do astrology.",
|
|
105
|
+
logo_url="https://example.com/logo.png", footer_text="(c) MyCompany",
|
|
104
106
|
)
|
|
105
107
|
"""
|
|
106
108
|
|
|
@@ -13,10 +13,10 @@ class CalculatorApi:
|
|
|
13
13
|
def __init__(self, client: BaseClient) -> None:
|
|
14
14
|
self._c = client
|
|
15
15
|
|
|
16
|
-
def flames(self,
|
|
16
|
+
def flames(self, your_name: str, partner_name: str) -> Dict[str, Any]:
|
|
17
17
|
"""FLAMES Calculator."""
|
|
18
18
|
return self._c.post(HOST, "/calculator/v1/flames-calculator", {
|
|
19
|
-
"
|
|
19
|
+
"your_name": your_name, "partner_name": partner_name,
|
|
20
20
|
})
|
|
21
21
|
|
|
22
22
|
def love_calculator(
|
|
@@ -20,16 +20,21 @@ class HoroscopeApi:
|
|
|
20
20
|
def daily(
|
|
21
21
|
self,
|
|
22
22
|
sign: str,
|
|
23
|
-
|
|
24
|
-
month: int,
|
|
25
|
-
year: int,
|
|
23
|
+
h_day: str,
|
|
26
24
|
tzone: float,
|
|
27
25
|
lan: str = "en",
|
|
26
|
+
day: Optional[int] = None,
|
|
27
|
+
month: Optional[int] = None,
|
|
28
|
+
year: Optional[int] = None,
|
|
28
29
|
) -> Dict[str, Any]:
|
|
29
|
-
"""Daily Horoscope.
|
|
30
|
+
"""Daily Horoscope.
|
|
31
|
+
|
|
32
|
+
The reading is selected with ``h_day`` ('today', 'tomorrow', or
|
|
33
|
+
'yesterday'). ``day``/``month``/``year`` are deprecated: the API
|
|
34
|
+
ignores them and they are accepted only for backward compatibility.
|
|
35
|
+
"""
|
|
30
36
|
return self._c.post(HOST, "/api/v5/daily-horoscope", {
|
|
31
|
-
"sign": sign, "
|
|
32
|
-
"tzone": tzone, "lan": lan,
|
|
37
|
+
"sign": sign, "h_day": h_day, "tzone": tzone, "lan": lan,
|
|
33
38
|
})
|
|
34
39
|
|
|
35
40
|
def weekly(
|
|
@@ -39,7 +44,10 @@ class HoroscopeApi:
|
|
|
39
44
|
tzone: float,
|
|
40
45
|
lan: str = "en",
|
|
41
46
|
) -> Dict[str, Any]:
|
|
42
|
-
"""Weekly Horoscope.
|
|
47
|
+
"""Weekly Horoscope.
|
|
48
|
+
|
|
49
|
+
``week`` is a selector: 'current', 'prev', or 'next' (not a date).
|
|
50
|
+
"""
|
|
43
51
|
return self._c.post(HOST, "/api/v5/weekly-horoscope", {
|
|
44
52
|
"sign": sign, "week": week, "tzone": tzone, "lan": lan,
|
|
45
53
|
})
|
|
@@ -47,11 +55,15 @@ class HoroscopeApi:
|
|
|
47
55
|
def monthly(
|
|
48
56
|
self,
|
|
49
57
|
sign: str,
|
|
50
|
-
month:
|
|
58
|
+
month: str,
|
|
51
59
|
tzone: float,
|
|
52
60
|
lan: str = "en",
|
|
53
61
|
) -> Dict[str, Any]:
|
|
54
|
-
"""Monthly Horoscope.
|
|
62
|
+
"""Monthly Horoscope.
|
|
63
|
+
|
|
64
|
+
``month`` is a selector: 'current', 'prev', or 'next' (not a calendar
|
|
65
|
+
month number).
|
|
66
|
+
"""
|
|
55
67
|
return self._c.post(HOST, "/api/v5/monthly-horoscope", {
|
|
56
68
|
"sign": sign, "month": month, "tzone": tzone, "lan": lan,
|
|
57
69
|
})
|
|
@@ -59,11 +71,15 @@ class HoroscopeApi:
|
|
|
59
71
|
def yearly(
|
|
60
72
|
self,
|
|
61
73
|
sign: str,
|
|
62
|
-
year:
|
|
74
|
+
year: str,
|
|
63
75
|
tzone: float,
|
|
64
76
|
lan: str = "en",
|
|
65
77
|
) -> Dict[str, Any]:
|
|
66
|
-
"""Yearly Horoscope.
|
|
78
|
+
"""Yearly Horoscope.
|
|
79
|
+
|
|
80
|
+
``year`` is a selector: 'current', 'prev', or 'next' (not a calendar
|
|
81
|
+
year number).
|
|
82
|
+
"""
|
|
67
83
|
return self._c.post(HOST, "/api/v5/yearly-horoscope", {
|
|
68
84
|
"sign": sign, "year": year, "tzone": tzone, "lan": lan,
|
|
69
85
|
})
|
|
@@ -22,23 +22,26 @@ class PdfReportApi:
|
|
|
22
22
|
full_name: str, day: int, month: int, year: int,
|
|
23
23
|
hour: int, min: int, sec: int, gender: str,
|
|
24
24
|
place: str, lat: float, lon: float, tzone: float,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
company_bio: str = "", logo_url: str = "",
|
|
29
|
-
footer_text: str = "",
|
|
25
|
+
company_name: str, company_url: str, company_email: str,
|
|
26
|
+
company_bio: str, logo_url: str, footer_text: str,
|
|
27
|
+
lan: str = "en", company_mobile: str = "",
|
|
30
28
|
**extra: Any,
|
|
31
29
|
) -> Dict[str, Any]:
|
|
30
|
+
# The six branding fields are REQUIRED by the PDF backend (it rejects
|
|
31
|
+
# requests without them). company_mobile is optional and sent only when
|
|
32
|
+
# provided.
|
|
32
33
|
d: Dict[str, Any] = {
|
|
33
34
|
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
34
35
|
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
35
36
|
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
36
37
|
"lan": lan,
|
|
37
38
|
"company_name": company_name, "company_url": company_url,
|
|
38
|
-
"company_email": company_email,
|
|
39
|
+
"company_email": company_email,
|
|
39
40
|
"company_bio": company_bio, "logo_url": logo_url,
|
|
40
41
|
"footer_text": footer_text,
|
|
41
42
|
}
|
|
43
|
+
if company_mobile:
|
|
44
|
+
d["company_mobile"] = company_mobile
|
|
42
45
|
d.update(extra)
|
|
43
46
|
return d
|
|
44
47
|
|
|
@@ -50,13 +53,12 @@ class PdfReportApi:
|
|
|
50
53
|
p2_full_name: str, p2_day: int, p2_month: int, p2_year: int,
|
|
51
54
|
p2_hour: int, p2_min: int, p2_sec: int, p2_gender: str,
|
|
52
55
|
p2_place: str, p2_lat: float, p2_lon: float, p2_tzone: float,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
company_bio: str = "", logo_url: str = "",
|
|
57
|
-
footer_text: str = "",
|
|
56
|
+
company_name: str, company_url: str, company_email: str,
|
|
57
|
+
company_bio: str, logo_url: str, footer_text: str,
|
|
58
|
+
lan: str = "en", company_mobile: str = "",
|
|
58
59
|
**extra: Any,
|
|
59
60
|
) -> Dict[str, Any]:
|
|
61
|
+
# The six branding fields are REQUIRED by the PDF backend.
|
|
60
62
|
d: Dict[str, Any] = {
|
|
61
63
|
"p1_full_name": p1_full_name, "p1_day": p1_day, "p1_month": p1_month,
|
|
62
64
|
"p1_year": p1_year, "p1_hour": p1_hour, "p1_min": p1_min,
|
|
@@ -68,10 +70,12 @@ class PdfReportApi:
|
|
|
68
70
|
"p2_lat": p2_lat, "p2_lon": p2_lon, "p2_tzone": p2_tzone,
|
|
69
71
|
"lan": lan,
|
|
70
72
|
"company_name": company_name, "company_url": company_url,
|
|
71
|
-
"company_email": company_email,
|
|
73
|
+
"company_email": company_email,
|
|
72
74
|
"company_bio": company_bio, "logo_url": logo_url,
|
|
73
75
|
"footer_text": footer_text,
|
|
74
76
|
}
|
|
77
|
+
if company_mobile:
|
|
78
|
+
d["company_mobile"] = company_mobile
|
|
75
79
|
d.update(extra)
|
|
76
80
|
return d
|
|
77
81
|
|
|
@@ -133,11 +137,14 @@ class PdfReportApi:
|
|
|
133
137
|
# Astrology / Numerology reports with report_code
|
|
134
138
|
# ------------------------------------------------------------------ #
|
|
135
139
|
|
|
136
|
-
def natal_report(self, report_code: str, theme: str
|
|
137
|
-
"""Natal Report PDF.
|
|
140
|
+
def natal_report(self, report_code: str, theme: str, **kw: Any) -> Dict[str, Any]:
|
|
141
|
+
"""Natal Report PDF.
|
|
142
|
+
|
|
143
|
+
Both ``report_code`` (e.g. 'CAREER-REPORT') and ``theme`` (e.g. '001')
|
|
144
|
+
are required by the API, along with the six company branding fields.
|
|
145
|
+
"""
|
|
138
146
|
kw["report_code"] = report_code
|
|
139
|
-
|
|
140
|
-
kw["theme"] = theme
|
|
147
|
+
kw["theme"] = theme
|
|
141
148
|
return self._post_birth("/astrology/v2/report", **kw)
|
|
142
149
|
|
|
143
150
|
def natal_couple_report(self, report_code: str, **kw: Any) -> Dict[str, Any]:
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""House-system name resolution for the Western API.
|
|
2
|
+
|
|
3
|
+
The live Western API accepts ONLY single-letter Swiss Ephemeris house-system
|
|
4
|
+
codes. Word values like ``placidus`` are rejected on astroapi-4 and silently
|
|
5
|
+
ignored on astroapi-8, so every payload must send the letter code. This mirrors
|
|
6
|
+
the mapping used by the Divine Western MCP server.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
# Friendly house-system names mapped to the single-letter API codes.
|
|
12
|
+
HOUSE_SYSTEM_MAP = {
|
|
13
|
+
"placidus": "P",
|
|
14
|
+
"koch": "K",
|
|
15
|
+
"porphyry": "O",
|
|
16
|
+
"regiomontanus": "R",
|
|
17
|
+
"campanus": "C",
|
|
18
|
+
"equal": "E",
|
|
19
|
+
"whole-sign": "W",
|
|
20
|
+
"whole_sign": "W",
|
|
21
|
+
"wholesign": "W",
|
|
22
|
+
"morinus": "M",
|
|
23
|
+
"alcabitius": "B",
|
|
24
|
+
}
|
|
25
|
+
VALID_HOUSE_SYSTEM_LETTERS = set(HOUSE_SYSTEM_MAP.values())
|
|
26
|
+
HOUSE_SYSTEM_FRIENDLY_NAMES = (
|
|
27
|
+
"placidus, koch, porphyry, regiomontanus, campanus, equal, "
|
|
28
|
+
"whole-sign, morinus, alcabitius"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def resolve_house_system(value: Optional[str]) -> str:
|
|
33
|
+
"""Map a friendly house-system name to its single-letter API code.
|
|
34
|
+
|
|
35
|
+
Accepts friendly names case-insensitively (e.g. ``placidus``, ``Whole-Sign``)
|
|
36
|
+
and already-valid single letters (passed through unchanged, upper-cased).
|
|
37
|
+
An empty value defaults to ``P`` (Placidus). Raises ``ValueError`` for
|
|
38
|
+
anything else.
|
|
39
|
+
"""
|
|
40
|
+
hs = (value or "").strip()
|
|
41
|
+
if not hs:
|
|
42
|
+
return "P"
|
|
43
|
+
if hs.upper() in VALID_HOUSE_SYSTEM_LETTERS:
|
|
44
|
+
return hs.upper()
|
|
45
|
+
mapped = HOUSE_SYSTEM_MAP.get(hs.lower())
|
|
46
|
+
if mapped:
|
|
47
|
+
return mapped
|
|
48
|
+
raise ValueError(
|
|
49
|
+
f"Invalid house_system '{value}'. Must be one of: "
|
|
50
|
+
f"{HOUSE_SYSTEM_FRIENDLY_NAMES} (or a single-letter code: "
|
|
51
|
+
f"{', '.join(sorted(VALID_HOUSE_SYSTEM_LETTERS))})"
|
|
52
|
+
)
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from typing import Any, Dict
|
|
4
4
|
|
|
5
5
|
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
6
7
|
|
|
7
8
|
HOST = "astroapi-8"
|
|
8
9
|
|
|
@@ -33,7 +34,7 @@ class CompositeApi:
|
|
|
33
34
|
"p2_year": p2_year, "p2_hour": p2_hour, "p2_min": p2_min,
|
|
34
35
|
"p2_sec": p2_sec, "p2_gender": p2_gender, "p2_place": p2_place,
|
|
35
36
|
"p2_lat": p2_lat, "p2_lon": p2_lon, "p2_tzone": p2_tzone,
|
|
36
|
-
"lan": lan, "house_system": house_system,
|
|
37
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
37
38
|
}
|
|
38
39
|
d.update(extra)
|
|
39
40
|
return d
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Western API - Natal endpoints (astroapi-4 and astroapi-8)."""
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict
|
|
3
|
+
from typing import Any, Dict
|
|
4
4
|
|
|
5
5
|
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class NatalApi:
|
|
@@ -27,7 +28,7 @@ class NatalApi:
|
|
|
27
28
|
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
28
29
|
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
29
30
|
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
30
|
-
"lan": lan, "house_system": house_system,
|
|
31
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
31
32
|
}
|
|
32
33
|
d.update(extra)
|
|
33
34
|
return d
|
|
@@ -44,11 +45,11 @@ class NatalApi:
|
|
|
44
45
|
|
|
45
46
|
def planetary_positions(self, **kw: Any) -> Dict[str, Any]:
|
|
46
47
|
"""Natal Planetary Positions."""
|
|
47
|
-
return self._post4("/western-api/
|
|
48
|
+
return self._post4("/western-api/v1/planetary-positions", **kw)
|
|
48
49
|
|
|
49
50
|
def house_cusps(self, **kw: Any) -> Dict[str, Any]:
|
|
50
51
|
"""Natal House Cusps."""
|
|
51
|
-
return self._post4("/western-api/
|
|
52
|
+
return self._post4("/western-api/v1/house-cusps", **kw)
|
|
52
53
|
|
|
53
54
|
def aspect_table(self, **kw: Any) -> Dict[str, Any]:
|
|
54
55
|
"""Natal Aspect Table."""
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from typing import Any, Dict
|
|
4
4
|
|
|
5
5
|
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
6
7
|
|
|
7
8
|
HOST = "astroapi-8"
|
|
8
9
|
|
|
@@ -25,7 +26,7 @@ class PlanetReturnsApi:
|
|
|
25
26
|
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
26
27
|
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
27
28
|
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
28
|
-
"lan": lan, "house_system": house_system,
|
|
29
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
29
30
|
}
|
|
30
31
|
d.update(extra)
|
|
31
32
|
return d
|
|
@@ -46,14 +47,15 @@ class PlanetReturnsApi:
|
|
|
46
47
|
return self._c.post(HOST, "/western-api/v1/planet-returns-list", self._birth(**kw))
|
|
47
48
|
|
|
48
49
|
def planet_return_details(
|
|
49
|
-
self, planet: str, return_key: str,
|
|
50
|
+
self, planet: str, return_key: str, return_year: int,
|
|
50
51
|
return_lat: float, return_lon: float,
|
|
51
52
|
return_tzone: float, return_place: str,
|
|
52
53
|
**kw: Any,
|
|
53
54
|
) -> Dict[str, Any]:
|
|
54
|
-
"""Planet Return Details."""
|
|
55
|
+
"""Planet Return Details (``return_key`` comes from ``planet_return_list``)."""
|
|
55
56
|
kw["planet"] = planet
|
|
56
57
|
kw["return_key"] = return_key
|
|
58
|
+
kw["return_year"] = return_year
|
|
57
59
|
kw["return_lat"] = return_lat
|
|
58
60
|
kw["return_lon"] = return_lon
|
|
59
61
|
kw["return_tzone"] = return_tzone
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from typing import Any, Dict
|
|
4
4
|
|
|
5
5
|
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
6
7
|
|
|
7
8
|
HOST = "astroapi-8"
|
|
8
9
|
|
|
@@ -25,7 +26,7 @@ class PrenatalApi:
|
|
|
25
26
|
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
26
27
|
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
27
28
|
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
28
|
-
"lan": lan, "house_system": house_system,
|
|
29
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
29
30
|
}
|
|
30
31
|
d.update(extra)
|
|
31
32
|
return d
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"""Western API - Progressions endpoints (astroapi-8)."""
|
|
2
2
|
|
|
3
|
-
from typing import Any, Dict
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
4
|
|
|
5
5
|
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
6
7
|
|
|
7
8
|
HOST = "astroapi-8"
|
|
8
9
|
|
|
@@ -25,7 +26,7 @@ class ProgressionsApi:
|
|
|
25
26
|
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
26
27
|
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
27
28
|
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
28
|
-
"lan": lan, "house_system": house_system,
|
|
29
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
29
30
|
}
|
|
30
31
|
d.update(extra)
|
|
31
32
|
return d
|
|
@@ -48,15 +49,25 @@ class ProgressionsApi:
|
|
|
48
49
|
return self._c.post(HOST, "/western-api/v1/planetary-arc-directions", self._birth(**kw))
|
|
49
50
|
|
|
50
51
|
def secondary_progressions(
|
|
51
|
-
self,
|
|
52
|
+
self,
|
|
52
53
|
progressed_day: int, progressed_month: int, progressed_year: int,
|
|
54
|
+
progressed_hour: int, progressed_min: int, progressed_sec: int,
|
|
53
55
|
progressed_type: str,
|
|
56
|
+
planet: Optional[str] = None,
|
|
54
57
|
**kw: Any,
|
|
55
58
|
) -> Dict[str, Any]:
|
|
56
|
-
"""Secondary Progressions.
|
|
57
|
-
|
|
59
|
+
"""Secondary Progressions.
|
|
60
|
+
|
|
61
|
+
``progressed_day/month/year/hour/min/sec`` and ``progressed_type`` are
|
|
62
|
+
required by the API; ``planet`` is optional.
|
|
63
|
+
"""
|
|
58
64
|
kw["progressed_day"] = progressed_day
|
|
59
65
|
kw["progressed_month"] = progressed_month
|
|
60
66
|
kw["progressed_year"] = progressed_year
|
|
67
|
+
kw["progressed_hour"] = progressed_hour
|
|
68
|
+
kw["progressed_min"] = progressed_min
|
|
69
|
+
kw["progressed_sec"] = progressed_sec
|
|
61
70
|
kw["progressed_type"] = progressed_type
|
|
71
|
+
if planet is not None:
|
|
72
|
+
kw["planet"] = planet
|
|
62
73
|
return self._c.post(HOST, "/western-api/v1/secondary-progressions", self._birth(**kw))
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from typing import Any, Dict
|
|
4
4
|
|
|
5
5
|
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
6
7
|
|
|
7
8
|
HOST = "astroapi-4"
|
|
8
9
|
HOST8 = "astroapi-8"
|
|
@@ -38,7 +39,7 @@ class SynastryApi:
|
|
|
38
39
|
"p2_year": p2_year, "p2_hour": p2_hour, "p2_min": p2_min,
|
|
39
40
|
"p2_sec": p2_sec, "p2_gender": p2_gender, "p2_place": p2_place,
|
|
40
41
|
"p2_lat": p2_lat, "p2_lon": p2_lon, "p2_tzone": p2_tzone,
|
|
41
|
-
"lan": lan, "house_system": house_system,
|
|
42
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
42
43
|
}
|
|
43
44
|
d.update(extra)
|
|
44
45
|
return d
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""Western API - Transit endpoints (astroapi-4 and astroapi-8)."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
|
|
5
|
+
from ..client import BaseClient
|
|
6
|
+
from ._house_system import resolve_house_system
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TransitApi:
|
|
10
|
+
"""Transit endpoints for Western astrology."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client: BaseClient) -> None:
|
|
13
|
+
self._c = client
|
|
14
|
+
|
|
15
|
+
# ------------------------------------------------------------------ #
|
|
16
|
+
# Payload helpers
|
|
17
|
+
# ------------------------------------------------------------------ #
|
|
18
|
+
|
|
19
|
+
@staticmethod
|
|
20
|
+
def _birth(
|
|
21
|
+
full_name: str, day: int, month: int, year: int,
|
|
22
|
+
hour: int, min: int, sec: int, gender: str,
|
|
23
|
+
place: str, lat: float, lon: float, tzone: float,
|
|
24
|
+
lan: str = "en", house_system: str = "placidus",
|
|
25
|
+
**extra: Any,
|
|
26
|
+
) -> Dict[str, Any]:
|
|
27
|
+
d: Dict[str, Any] = {
|
|
28
|
+
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
29
|
+
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
30
|
+
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
31
|
+
"lan": lan, "house_system": resolve_house_system(house_system),
|
|
32
|
+
}
|
|
33
|
+
d.update(extra)
|
|
34
|
+
return d
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def _transit_dt(
|
|
38
|
+
transit_day: int, transit_month: int, transit_year: int,
|
|
39
|
+
transit_hour: int = 0, transit_min: int = 0, transit_sec: int = 0,
|
|
40
|
+
) -> Dict[str, Any]:
|
|
41
|
+
return {
|
|
42
|
+
"transit_day": transit_day, "transit_month": transit_month,
|
|
43
|
+
"transit_year": transit_year, "transit_hour": transit_hour,
|
|
44
|
+
"transit_min": transit_min, "transit_sec": transit_sec,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def _transit_loc(
|
|
49
|
+
transit_lat: float, transit_lon: float,
|
|
50
|
+
transit_tzone: float, transit_place: str,
|
|
51
|
+
) -> Dict[str, Any]:
|
|
52
|
+
return {
|
|
53
|
+
"transit_lat": transit_lat, "transit_lon": transit_lon,
|
|
54
|
+
"transit_tzone": transit_tzone, "transit_place": transit_place,
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
def _post4(self, path: str, **kw: Any) -> Dict[str, Any]:
|
|
58
|
+
return self._c.post("astroapi-4", path, self._birth(**kw))
|
|
59
|
+
|
|
60
|
+
def _post8(self, path: str, **kw: Any) -> Dict[str, Any]:
|
|
61
|
+
return self._c.post("astroapi-8", path, self._birth(**kw))
|
|
62
|
+
|
|
63
|
+
# ------------------------------------------------------------------ #
|
|
64
|
+
# astroapi-4 transit endpoints
|
|
65
|
+
# ------------------------------------------------------------------ #
|
|
66
|
+
|
|
67
|
+
def basic(
|
|
68
|
+
self,
|
|
69
|
+
transit_day: int, transit_month: int, transit_year: int,
|
|
70
|
+
transit_hour: int = 0, transit_min: int = 0, transit_sec: int = 0,
|
|
71
|
+
**kw: Any,
|
|
72
|
+
) -> Dict[str, Any]:
|
|
73
|
+
"""Transit Basic. Requires the transit date; time defaults to 00:00:00."""
|
|
74
|
+
payload = self._birth(**kw)
|
|
75
|
+
payload.update(self._transit_dt(
|
|
76
|
+
transit_day, transit_month, transit_year,
|
|
77
|
+
transit_hour, transit_min, transit_sec,
|
|
78
|
+
))
|
|
79
|
+
return self._c.post("astroapi-4", "/western-api/v1/transit/basic", payload)
|
|
80
|
+
|
|
81
|
+
def daily(self, **kw: Any) -> Dict[str, Any]:
|
|
82
|
+
"""Transit Daily."""
|
|
83
|
+
return self._post4("/western-api/v1/transit/daily", **kw)
|
|
84
|
+
|
|
85
|
+
def weekly(self, transit_planet: str, **kw: Any) -> Dict[str, Any]:
|
|
86
|
+
"""Transit Weekly. Requires the transiting planet (e.g. 'moon')."""
|
|
87
|
+
kw["transit_planet"] = transit_planet
|
|
88
|
+
return self._post4("/western-api/v1/transit/weekly", **kw)
|
|
89
|
+
|
|
90
|
+
def house(
|
|
91
|
+
self,
|
|
92
|
+
transit_day: int, transit_month: int, transit_year: int,
|
|
93
|
+
transit_lat: float, transit_lon: float,
|
|
94
|
+
transit_tzone: float, transit_place: str,
|
|
95
|
+
transit_hour: int = 0, transit_min: int = 0, transit_sec: int = 0,
|
|
96
|
+
**kw: Any,
|
|
97
|
+
) -> Dict[str, Any]:
|
|
98
|
+
"""Transit House. Requires transit date + location; time defaults to 00:00:00."""
|
|
99
|
+
payload = self._birth(**kw)
|
|
100
|
+
payload.update(self._transit_dt(
|
|
101
|
+
transit_day, transit_month, transit_year,
|
|
102
|
+
transit_hour, transit_min, transit_sec,
|
|
103
|
+
))
|
|
104
|
+
payload.update(self._transit_loc(
|
|
105
|
+
transit_lat, transit_lon, transit_tzone, transit_place,
|
|
106
|
+
))
|
|
107
|
+
return self._c.post("astroapi-4", "/western-api/v1/transit/house", payload)
|
|
108
|
+
|
|
109
|
+
# ------------------------------------------------------------------ #
|
|
110
|
+
# astroapi-8 transit endpoints
|
|
111
|
+
# ------------------------------------------------------------------ #
|
|
112
|
+
|
|
113
|
+
def monthly(
|
|
114
|
+
self,
|
|
115
|
+
transit_planet: str, transit_month: int, transit_year: int,
|
|
116
|
+
transit_lat: float, transit_lon: float,
|
|
117
|
+
transit_tzone: float, transit_place: str,
|
|
118
|
+
**kw: Any,
|
|
119
|
+
) -> Dict[str, Any]:
|
|
120
|
+
"""Transit Monthly. Requires the transiting planet, month, year and location."""
|
|
121
|
+
payload = self._birth(**kw)
|
|
122
|
+
payload.update({
|
|
123
|
+
"transit_planet": transit_planet,
|
|
124
|
+
"transit_month": transit_month, "transit_year": transit_year,
|
|
125
|
+
})
|
|
126
|
+
payload.update(self._transit_loc(
|
|
127
|
+
transit_lat, transit_lon, transit_tzone, transit_place,
|
|
128
|
+
))
|
|
129
|
+
return self._c.post("astroapi-8", "/western-api/v2/transit/monthly", payload)
|
|
130
|
+
|
|
131
|
+
def full(
|
|
132
|
+
self,
|
|
133
|
+
transit_planet: str,
|
|
134
|
+
transit_day: int, transit_month: int, transit_year: int,
|
|
135
|
+
transit_lat: float, transit_lon: float,
|
|
136
|
+
transit_tzone: float, transit_place: str,
|
|
137
|
+
transit_hour: int = 0, transit_min: int = 0, transit_sec: int = 0,
|
|
138
|
+
**kw: Any,
|
|
139
|
+
) -> Dict[str, Any]:
|
|
140
|
+
"""Full Transit. Requires the transiting planet, transit date and location."""
|
|
141
|
+
payload = self._birth(**kw)
|
|
142
|
+
payload["transit_planet"] = transit_planet
|
|
143
|
+
payload.update(self._transit_dt(
|
|
144
|
+
transit_day, transit_month, transit_year,
|
|
145
|
+
transit_hour, transit_min, transit_sec,
|
|
146
|
+
))
|
|
147
|
+
payload.update(self._transit_loc(
|
|
148
|
+
transit_lat, transit_lon, transit_tzone, transit_place,
|
|
149
|
+
))
|
|
150
|
+
return self._c.post("astroapi-8", "/western-api/v1/full-transit", payload)
|
|
151
|
+
|
|
152
|
+
def planet_retrograde(
|
|
153
|
+
self, planet: str, month: int, year: int,
|
|
154
|
+
place: str, lat: float, lon: float, tzone: float,
|
|
155
|
+
) -> Dict[str, Any]:
|
|
156
|
+
"""Planet Retrograde Transit."""
|
|
157
|
+
return self._c.post("astroapi-8", "/western-api/v1/planet-retrograde-transit", {
|
|
158
|
+
"planet": planet, "month": month, "year": year,
|
|
159
|
+
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
def planetary_ingress(
|
|
163
|
+
self, planet: str, month: int, year: int,
|
|
164
|
+
place: str, lat: float, lon: float, tzone: float,
|
|
165
|
+
) -> Dict[str, Any]:
|
|
166
|
+
"""Planetary Ingress."""
|
|
167
|
+
return self._c.post("astroapi-8", "/western-api/v1/planetary-ingress", {
|
|
168
|
+
"planet": planet, "month": month, "year": year,
|
|
169
|
+
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
def planet_combustion(
|
|
173
|
+
self, planet: str, month: int, year: int,
|
|
174
|
+
place: str, lat: float, lon: float, tzone: float,
|
|
175
|
+
) -> Dict[str, Any]:
|
|
176
|
+
"""Planet Combustion Transit."""
|
|
177
|
+
return self._c.post("astroapi-8", "/western-api/v1/planet-combustion-transit", {
|
|
178
|
+
"planet": planet, "month": month, "year": year,
|
|
179
|
+
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
def wheel_chart(
|
|
183
|
+
self,
|
|
184
|
+
transit_day: int, transit_month: int, transit_year: int,
|
|
185
|
+
transit_lat: float, transit_lon: float,
|
|
186
|
+
transit_tzone: float, transit_place: str,
|
|
187
|
+
transit_hour: int = 0, transit_min: int = 0, transit_sec: int = 0,
|
|
188
|
+
**kw: Any,
|
|
189
|
+
) -> Dict[str, Any]:
|
|
190
|
+
"""Transit Wheel Chart. Requires transit date + location."""
|
|
191
|
+
payload = self._birth(**kw)
|
|
192
|
+
payload.update(self._transit_dt(
|
|
193
|
+
transit_day, transit_month, transit_year,
|
|
194
|
+
transit_hour, transit_min, transit_sec,
|
|
195
|
+
))
|
|
196
|
+
payload.update(self._transit_loc(
|
|
197
|
+
transit_lat, transit_lon, transit_tzone, transit_place,
|
|
198
|
+
))
|
|
199
|
+
return self._c.post("astroapi-8", "/western-api/v1/transit/wheel-chart", payload)
|
|
200
|
+
|
|
201
|
+
def planetary_positions(
|
|
202
|
+
self,
|
|
203
|
+
transit_day: int, transit_month: int, transit_year: int,
|
|
204
|
+
transit_lat: float, transit_lon: float,
|
|
205
|
+
transit_tzone: float, transit_place: str,
|
|
206
|
+
transit_hour: int = 0, transit_min: int = 0, transit_sec: int = 0,
|
|
207
|
+
**kw: Any,
|
|
208
|
+
) -> Dict[str, Any]:
|
|
209
|
+
"""Transit Planetary Positions. Requires transit date + location."""
|
|
210
|
+
payload = self._birth(**kw)
|
|
211
|
+
payload.update(self._transit_dt(
|
|
212
|
+
transit_day, transit_month, transit_year,
|
|
213
|
+
transit_hour, transit_min, transit_sec,
|
|
214
|
+
))
|
|
215
|
+
payload.update(self._transit_loc(
|
|
216
|
+
transit_lat, transit_lon, transit_tzone, transit_place,
|
|
217
|
+
))
|
|
218
|
+
return self._c.post("astroapi-8", "/western-api/v1/transit/planetary-positions", payload)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: divineapi
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Official Python SDK for the Divine API - Astrology, Numerology, Tarot & more
|
|
5
5
|
Author-email: Divine API <support@divineapi.com>
|
|
6
6
|
License: MIT
|
|
@@ -51,9 +51,9 @@ from divineapi import DivineApi
|
|
|
51
51
|
|
|
52
52
|
client = DivineApi(api_key="your-api-key", auth_token="your-bearer-token")
|
|
53
53
|
|
|
54
|
-
# Daily Horoscope
|
|
54
|
+
# Daily Horoscope (h_day = today, tomorrow, or yesterday)
|
|
55
55
|
result = client.horoscope.daily(
|
|
56
|
-
sign="aries",
|
|
56
|
+
sign="aries", h_day="today", tzone=5.5
|
|
57
57
|
)
|
|
58
58
|
print(result)
|
|
59
59
|
```
|
|
@@ -64,10 +64,11 @@ print(result)
|
|
|
64
64
|
|
|
65
65
|
```python
|
|
66
66
|
# Daily / Weekly / Monthly / Yearly Horoscope
|
|
67
|
-
|
|
68
|
-
client.horoscope.
|
|
69
|
-
client.horoscope.
|
|
70
|
-
client.horoscope.
|
|
67
|
+
# daily h_day = today / tomorrow / yesterday; weekly/monthly/yearly = current / prev / next
|
|
68
|
+
client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
69
|
+
client.horoscope.weekly(sign="leo", week="current", tzone=5.5)
|
|
70
|
+
client.horoscope.monthly(sign="cancer", month="current", tzone=5.5)
|
|
71
|
+
client.horoscope.yearly(sign="virgo", year="current", tzone=5.5)
|
|
71
72
|
|
|
72
73
|
# Chinese & Numerology Horoscope
|
|
73
74
|
client.horoscope.chinese(sign="rat", h_day="today", tzone=5.5)
|
|
@@ -164,8 +165,9 @@ client.indian.festival.chaitra_festivals(
|
|
|
164
165
|
client.indian.festival.english_calendar(
|
|
165
166
|
year=2024, month=3, place="Delhi", lat=28.6, lon=77.2, tzone=5.5
|
|
166
167
|
)
|
|
168
|
+
# festival is a lowercase snake_case slug from the Divine festival list
|
|
167
169
|
client.indian.festival.find_festival(
|
|
168
|
-
festival="
|
|
170
|
+
festival="maha_shivratri", year=2024,
|
|
169
171
|
place="Delhi", lat=28.6, lon=77.2, tzone=5.5
|
|
170
172
|
)
|
|
171
173
|
client.indian.festival.malayalam_festivals(
|
|
@@ -193,7 +195,7 @@ client.western.natal.house_cusps(**birth_w)
|
|
|
193
195
|
client.western.natal.aspect_table(**birth_w)
|
|
194
196
|
client.western.natal.natal_wheel_chart(**birth_w)
|
|
195
197
|
client.western.natal.natal_insights(**birth_w)
|
|
196
|
-
client.western.natal.dominants(method="
|
|
198
|
+
client.western.natal.dominants(method="TRADITIONAL", **birth_w)
|
|
197
199
|
```
|
|
198
200
|
|
|
199
201
|
### Western Astrology - Synastry
|
|
@@ -252,7 +254,7 @@ client.lifestyle.astro_chic_picks(sign="virgo", h_day="today", tzone=5.5)
|
|
|
252
254
|
### Calculators
|
|
253
255
|
|
|
254
256
|
```python
|
|
255
|
-
client.calculators.flames(
|
|
257
|
+
client.calculators.flames(your_name="John", partner_name="Jane")
|
|
256
258
|
client.calculators.love_calculator(
|
|
257
259
|
your_name="John", partner_name="Jane",
|
|
258
260
|
your_gender="male", partner_gender="female",
|
|
@@ -262,11 +264,15 @@ client.calculators.love_calculator(
|
|
|
262
264
|
### PDF Reports
|
|
263
265
|
|
|
264
266
|
```python
|
|
267
|
+
# The six branding fields (company_url, logo_url, footer_text, company_name,
|
|
268
|
+
# company_email, company_bio) are REQUIRED by the PDF backend.
|
|
265
269
|
client.pdf.kundali_sampoorna(
|
|
266
270
|
full_name="John", day=1, month=1, year=1990,
|
|
267
271
|
hour=10, min=30, sec=0, gender="male",
|
|
268
272
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
269
273
|
company_name="AstroCo", company_url="https://example.com",
|
|
274
|
+
company_email="hello@example.com", company_bio="We do astrology.",
|
|
275
|
+
logo_url="https://example.com/logo.png", footer_text="(c) AstroCo",
|
|
270
276
|
)
|
|
271
277
|
```
|
|
272
278
|
|
|
@@ -278,7 +284,7 @@ from divineapi import DivineApi, AuthenticationError, ValidationError, RateLimit
|
|
|
278
284
|
client = DivineApi(api_key="...", auth_token="...")
|
|
279
285
|
|
|
280
286
|
try:
|
|
281
|
-
result = client.horoscope.daily(sign="aries",
|
|
287
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
282
288
|
except AuthenticationError as e:
|
|
283
289
|
print(f"Auth failed: {e}")
|
|
284
290
|
except ValidationError as e:
|
|
@@ -291,7 +297,7 @@ except RateLimitError as e:
|
|
|
291
297
|
|
|
292
298
|
```python
|
|
293
299
|
with DivineApi(api_key="...", auth_token="...") as client:
|
|
294
|
-
result = client.horoscope.daily(sign="aries",
|
|
300
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
295
301
|
```
|
|
296
302
|
|
|
297
303
|
## Configuration
|
|
@@ -22,6 +22,7 @@ divineapi/indian/kundli.py
|
|
|
22
22
|
divineapi/indian/match_making.py
|
|
23
23
|
divineapi/indian/panchang.py
|
|
24
24
|
divineapi/western/__init__.py
|
|
25
|
+
divineapi/western/_house_system.py
|
|
25
26
|
divineapi/western/composite.py
|
|
26
27
|
divineapi/western/natal.py
|
|
27
28
|
divineapi/western/planet_returns.py
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"""Western API - Transit endpoints (astroapi-4 and astroapi-8)."""
|
|
2
|
-
|
|
3
|
-
from typing import Any, Dict
|
|
4
|
-
|
|
5
|
-
from ..client import BaseClient
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TransitApi:
|
|
9
|
-
"""Transit endpoints for Western astrology."""
|
|
10
|
-
|
|
11
|
-
def __init__(self, client: BaseClient) -> None:
|
|
12
|
-
self._c = client
|
|
13
|
-
|
|
14
|
-
# ------------------------------------------------------------------ #
|
|
15
|
-
# Birth-data helper
|
|
16
|
-
# ------------------------------------------------------------------ #
|
|
17
|
-
|
|
18
|
-
@staticmethod
|
|
19
|
-
def _birth(
|
|
20
|
-
full_name: str, day: int, month: int, year: int,
|
|
21
|
-
hour: int, min: int, sec: int, gender: str,
|
|
22
|
-
place: str, lat: float, lon: float, tzone: float,
|
|
23
|
-
lan: str = "en", house_system: str = "placidus",
|
|
24
|
-
**extra: Any,
|
|
25
|
-
) -> Dict[str, Any]:
|
|
26
|
-
d: Dict[str, Any] = {
|
|
27
|
-
"full_name": full_name, "day": day, "month": month, "year": year,
|
|
28
|
-
"hour": hour, "min": min, "sec": sec, "gender": gender,
|
|
29
|
-
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
30
|
-
"lan": lan, "house_system": house_system,
|
|
31
|
-
}
|
|
32
|
-
d.update(extra)
|
|
33
|
-
return d
|
|
34
|
-
|
|
35
|
-
def _post4(self, path: str, **kw: Any) -> Dict[str, Any]:
|
|
36
|
-
return self._c.post("astroapi-4", path, self._birth(**kw))
|
|
37
|
-
|
|
38
|
-
def _post8(self, path: str, **kw: Any) -> Dict[str, Any]:
|
|
39
|
-
return self._c.post("astroapi-8", path, self._birth(**kw))
|
|
40
|
-
|
|
41
|
-
# ------------------------------------------------------------------ #
|
|
42
|
-
# astroapi-4 transit endpoints
|
|
43
|
-
# ------------------------------------------------------------------ #
|
|
44
|
-
|
|
45
|
-
def basic(self, **kw: Any) -> Dict[str, Any]:
|
|
46
|
-
"""Transit Basic (pass transit_day/month/year/hour/min/sec via **kw)."""
|
|
47
|
-
return self._post4("/western-api/v1/transit/basic", **kw)
|
|
48
|
-
|
|
49
|
-
def daily(self, **kw: Any) -> Dict[str, Any]:
|
|
50
|
-
"""Transit Daily."""
|
|
51
|
-
return self._post4("/western-api/v1/transit/daily", **kw)
|
|
52
|
-
|
|
53
|
-
def weekly(self, transit_planet: str, **kw: Any) -> Dict[str, Any]:
|
|
54
|
-
"""Transit Weekly."""
|
|
55
|
-
kw["transit_planet"] = transit_planet
|
|
56
|
-
return self._post4("/western-api/v1/transit/weekly", **kw)
|
|
57
|
-
|
|
58
|
-
def house(self, **kw: Any) -> Dict[str, Any]:
|
|
59
|
-
"""Transit House (pass full transit params via **kw)."""
|
|
60
|
-
return self._post4("/western-api/v1/transit/house", **kw)
|
|
61
|
-
|
|
62
|
-
# ------------------------------------------------------------------ #
|
|
63
|
-
# astroapi-8 transit endpoints
|
|
64
|
-
# ------------------------------------------------------------------ #
|
|
65
|
-
|
|
66
|
-
def monthly(self, **kw: Any) -> Dict[str, Any]:
|
|
67
|
-
"""Transit Monthly (pass extensive transit params via **kw)."""
|
|
68
|
-
return self._post8("/western-api/v2/transit/monthly", **kw)
|
|
69
|
-
|
|
70
|
-
def full(self, **kw: Any) -> Dict[str, Any]:
|
|
71
|
-
"""Full Transit (pass extensive transit params via **kw)."""
|
|
72
|
-
return self._post8("/western-api/v1/full-transit", **kw)
|
|
73
|
-
|
|
74
|
-
def planet_retrograde(
|
|
75
|
-
self, planet: str, month: int, year: int,
|
|
76
|
-
place: str, lat: float, lon: float, tzone: float,
|
|
77
|
-
) -> Dict[str, Any]:
|
|
78
|
-
"""Planet Retrograde Transit."""
|
|
79
|
-
return self._c.post("astroapi-8", "/western-api/v1/planet-retrograde-transit", {
|
|
80
|
-
"planet": planet, "month": month, "year": year,
|
|
81
|
-
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
def planetary_ingress(
|
|
85
|
-
self, planet: str, month: int, year: int,
|
|
86
|
-
place: str, lat: float, lon: float, tzone: float,
|
|
87
|
-
) -> Dict[str, Any]:
|
|
88
|
-
"""Planetary Ingress."""
|
|
89
|
-
return self._c.post("astroapi-8", "/western-api/v1/planetary-ingress", {
|
|
90
|
-
"planet": planet, "month": month, "year": year,
|
|
91
|
-
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
def planet_combustion(
|
|
95
|
-
self, planet: str, month: int, year: int,
|
|
96
|
-
place: str, lat: float, lon: float, tzone: float,
|
|
97
|
-
) -> Dict[str, Any]:
|
|
98
|
-
"""Planet Combustion Transit."""
|
|
99
|
-
return self._c.post("astroapi-8", "/western-api/v1/planet-combustion-transit", {
|
|
100
|
-
"planet": planet, "month": month, "year": year,
|
|
101
|
-
"place": place, "lat": lat, "lon": lon, "tzone": tzone,
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
def wheel_chart(self, **kw: Any) -> Dict[str, Any]:
|
|
105
|
-
"""Transit Wheel Chart."""
|
|
106
|
-
return self._post8("/western-api/v1/transit/wheel-chart", **kw)
|
|
107
|
-
|
|
108
|
-
def planetary_positions(self, **kw: Any) -> Dict[str, Any]:
|
|
109
|
-
"""Transit Planetary Positions."""
|
|
110
|
-
return self._post8("/western-api/v1/transit/planetary-positions", **kw)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|