divineapi 1.1.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.1.0 → divineapi-1.3.0}/PKG-INFO +21 -12
- {divineapi-1.1.0 → divineapi-1.3.0}/README.md +20 -11
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/__init__.py +6 -4
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/calculators.py +2 -2
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/horoscope.py +27 -11
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/indian/festival.py +8 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/pdf.py +23 -16
- divineapi-1.3.0/divineapi/western/_house_system.py +52 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/composite.py +2 -1
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/natal.py +5 -4
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/planet_returns.py +5 -3
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/prenatal.py +2 -1
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/progressions.py +16 -5
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/synastry.py +2 -1
- divineapi-1.3.0/divineapi/western/transit.py +218 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi.egg-info/PKG-INFO +21 -12
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi.egg-info/SOURCES.txt +1 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/pyproject.toml +1 -1
- divineapi-1.1.0/divineapi/western/transit.py +0 -110
- {divineapi-1.1.0 → divineapi-1.3.0}/LICENSE +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/client.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/exceptions.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/indian/__init__.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/indian/kundli.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/indian/match_making.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/indian/panchang.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/lifestyle.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/numerology.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/py.typed +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi/western/__init__.py +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi.egg-info/dependency_links.txt +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi.egg-info/requires.txt +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/divineapi.egg-info/top_level.txt +0 -0
- {divineapi-1.1.0 → divineapi-1.3.0}/setup.cfg +0 -0
- {divineapi-1.1.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(
|
|
@@ -174,6 +176,9 @@ client.indian.festival.malayalam_festivals(
|
|
|
174
176
|
client.indian.festival.tamil_festivals(
|
|
175
177
|
year=2027, place="Chennai", lat=13.0827, lon=80.2707, tzone=5.5
|
|
176
178
|
)
|
|
179
|
+
client.indian.festival.sankranti_festivals(
|
|
180
|
+
year=2027, place="New Delhi", lat=28.6139, lon=77.2090, tzone=5.5
|
|
181
|
+
)
|
|
177
182
|
```
|
|
178
183
|
|
|
179
184
|
### Western Astrology - Natal
|
|
@@ -190,7 +195,7 @@ client.western.natal.house_cusps(**birth_w)
|
|
|
190
195
|
client.western.natal.aspect_table(**birth_w)
|
|
191
196
|
client.western.natal.natal_wheel_chart(**birth_w)
|
|
192
197
|
client.western.natal.natal_insights(**birth_w)
|
|
193
|
-
client.western.natal.dominants(method="
|
|
198
|
+
client.western.natal.dominants(method="TRADITIONAL", **birth_w)
|
|
194
199
|
```
|
|
195
200
|
|
|
196
201
|
### Western Astrology - Synastry
|
|
@@ -249,7 +254,7 @@ client.lifestyle.astro_chic_picks(sign="virgo", h_day="today", tzone=5.5)
|
|
|
249
254
|
### Calculators
|
|
250
255
|
|
|
251
256
|
```python
|
|
252
|
-
client.calculators.flames(
|
|
257
|
+
client.calculators.flames(your_name="John", partner_name="Jane")
|
|
253
258
|
client.calculators.love_calculator(
|
|
254
259
|
your_name="John", partner_name="Jane",
|
|
255
260
|
your_gender="male", partner_gender="female",
|
|
@@ -259,11 +264,15 @@ client.calculators.love_calculator(
|
|
|
259
264
|
### PDF Reports
|
|
260
265
|
|
|
261
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.
|
|
262
269
|
client.pdf.kundali_sampoorna(
|
|
263
270
|
full_name="John", day=1, month=1, year=1990,
|
|
264
271
|
hour=10, min=30, sec=0, gender="male",
|
|
265
272
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
266
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",
|
|
267
276
|
)
|
|
268
277
|
```
|
|
269
278
|
|
|
@@ -275,7 +284,7 @@ from divineapi import DivineApi, AuthenticationError, ValidationError, RateLimit
|
|
|
275
284
|
client = DivineApi(api_key="...", auth_token="...")
|
|
276
285
|
|
|
277
286
|
try:
|
|
278
|
-
result = client.horoscope.daily(sign="aries",
|
|
287
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
279
288
|
except AuthenticationError as e:
|
|
280
289
|
print(f"Auth failed: {e}")
|
|
281
290
|
except ValidationError as e:
|
|
@@ -288,7 +297,7 @@ except RateLimitError as e:
|
|
|
288
297
|
|
|
289
298
|
```python
|
|
290
299
|
with DivineApi(api_key="...", auth_token="...") as client:
|
|
291
|
-
result = client.horoscope.daily(sign="aries",
|
|
300
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
292
301
|
```
|
|
293
302
|
|
|
294
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(
|
|
@@ -146,6 +148,9 @@ client.indian.festival.malayalam_festivals(
|
|
|
146
148
|
client.indian.festival.tamil_festivals(
|
|
147
149
|
year=2027, place="Chennai", lat=13.0827, lon=80.2707, tzone=5.5
|
|
148
150
|
)
|
|
151
|
+
client.indian.festival.sankranti_festivals(
|
|
152
|
+
year=2027, place="New Delhi", lat=28.6139, lon=77.2090, tzone=5.5
|
|
153
|
+
)
|
|
149
154
|
```
|
|
150
155
|
|
|
151
156
|
### Western Astrology - Natal
|
|
@@ -162,7 +167,7 @@ client.western.natal.house_cusps(**birth_w)
|
|
|
162
167
|
client.western.natal.aspect_table(**birth_w)
|
|
163
168
|
client.western.natal.natal_wheel_chart(**birth_w)
|
|
164
169
|
client.western.natal.natal_insights(**birth_w)
|
|
165
|
-
client.western.natal.dominants(method="
|
|
170
|
+
client.western.natal.dominants(method="TRADITIONAL", **birth_w)
|
|
166
171
|
```
|
|
167
172
|
|
|
168
173
|
### Western Astrology - Synastry
|
|
@@ -221,7 +226,7 @@ client.lifestyle.astro_chic_picks(sign="virgo", h_day="today", tzone=5.5)
|
|
|
221
226
|
### Calculators
|
|
222
227
|
|
|
223
228
|
```python
|
|
224
|
-
client.calculators.flames(
|
|
229
|
+
client.calculators.flames(your_name="John", partner_name="Jane")
|
|
225
230
|
client.calculators.love_calculator(
|
|
226
231
|
your_name="John", partner_name="Jane",
|
|
227
232
|
your_gender="male", partner_gender="female",
|
|
@@ -231,11 +236,15 @@ client.calculators.love_calculator(
|
|
|
231
236
|
### PDF Reports
|
|
232
237
|
|
|
233
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.
|
|
234
241
|
client.pdf.kundali_sampoorna(
|
|
235
242
|
full_name="John", day=1, month=1, year=1990,
|
|
236
243
|
hour=10, min=30, sec=0, gender="male",
|
|
237
244
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
238
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",
|
|
239
248
|
)
|
|
240
249
|
```
|
|
241
250
|
|
|
@@ -247,7 +256,7 @@ from divineapi import DivineApi, AuthenticationError, ValidationError, RateLimit
|
|
|
247
256
|
client = DivineApi(api_key="...", auth_token="...")
|
|
248
257
|
|
|
249
258
|
try:
|
|
250
|
-
result = client.horoscope.daily(sign="aries",
|
|
259
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
251
260
|
except AuthenticationError as e:
|
|
252
261
|
print(f"Auth failed: {e}")
|
|
253
262
|
except ValidationError as e:
|
|
@@ -260,7 +269,7 @@ except RateLimitError as e:
|
|
|
260
269
|
|
|
261
270
|
```python
|
|
262
271
|
with DivineApi(api_key="...", auth_token="...") as client:
|
|
263
|
-
result = client.horoscope.daily(sign="aries",
|
|
272
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
264
273
|
```
|
|
265
274
|
|
|
266
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
|
})
|
|
@@ -129,3 +129,11 @@ class FestivalApi:
|
|
|
129
129
|
"""Tamil Festivals for a year."""
|
|
130
130
|
return self._c.post(HOST, "/indian-api/v1/tamil-festivals",
|
|
131
131
|
self._festival_loc(year, place, lat, lon, tzone))
|
|
132
|
+
|
|
133
|
+
def sankranti_festivals(
|
|
134
|
+
self, year: int,
|
|
135
|
+
place: str, lat: float, lon: float, tzone: float,
|
|
136
|
+
) -> Dict[str, Any]:
|
|
137
|
+
"""Sankranti Festivals for a year."""
|
|
138
|
+
return self._c.post(HOST, "/indian-api/v1/sankranti-festivals",
|
|
139
|
+
self._festival_loc(year, place, lat, lon, tzone))
|
|
@@ -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(
|
|
@@ -174,6 +176,9 @@ client.indian.festival.malayalam_festivals(
|
|
|
174
176
|
client.indian.festival.tamil_festivals(
|
|
175
177
|
year=2027, place="Chennai", lat=13.0827, lon=80.2707, tzone=5.5
|
|
176
178
|
)
|
|
179
|
+
client.indian.festival.sankranti_festivals(
|
|
180
|
+
year=2027, place="New Delhi", lat=28.6139, lon=77.2090, tzone=5.5
|
|
181
|
+
)
|
|
177
182
|
```
|
|
178
183
|
|
|
179
184
|
### Western Astrology - Natal
|
|
@@ -190,7 +195,7 @@ client.western.natal.house_cusps(**birth_w)
|
|
|
190
195
|
client.western.natal.aspect_table(**birth_w)
|
|
191
196
|
client.western.natal.natal_wheel_chart(**birth_w)
|
|
192
197
|
client.western.natal.natal_insights(**birth_w)
|
|
193
|
-
client.western.natal.dominants(method="
|
|
198
|
+
client.western.natal.dominants(method="TRADITIONAL", **birth_w)
|
|
194
199
|
```
|
|
195
200
|
|
|
196
201
|
### Western Astrology - Synastry
|
|
@@ -249,7 +254,7 @@ client.lifestyle.astro_chic_picks(sign="virgo", h_day="today", tzone=5.5)
|
|
|
249
254
|
### Calculators
|
|
250
255
|
|
|
251
256
|
```python
|
|
252
|
-
client.calculators.flames(
|
|
257
|
+
client.calculators.flames(your_name="John", partner_name="Jane")
|
|
253
258
|
client.calculators.love_calculator(
|
|
254
259
|
your_name="John", partner_name="Jane",
|
|
255
260
|
your_gender="male", partner_gender="female",
|
|
@@ -259,11 +264,15 @@ client.calculators.love_calculator(
|
|
|
259
264
|
### PDF Reports
|
|
260
265
|
|
|
261
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.
|
|
262
269
|
client.pdf.kundali_sampoorna(
|
|
263
270
|
full_name="John", day=1, month=1, year=1990,
|
|
264
271
|
hour=10, min=30, sec=0, gender="male",
|
|
265
272
|
place="Mumbai", lat=19.07, lon=72.87, tzone=5.5,
|
|
266
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",
|
|
267
276
|
)
|
|
268
277
|
```
|
|
269
278
|
|
|
@@ -275,7 +284,7 @@ from divineapi import DivineApi, AuthenticationError, ValidationError, RateLimit
|
|
|
275
284
|
client = DivineApi(api_key="...", auth_token="...")
|
|
276
285
|
|
|
277
286
|
try:
|
|
278
|
-
result = client.horoscope.daily(sign="aries",
|
|
287
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
279
288
|
except AuthenticationError as e:
|
|
280
289
|
print(f"Auth failed: {e}")
|
|
281
290
|
except ValidationError as e:
|
|
@@ -288,7 +297,7 @@ except RateLimitError as e:
|
|
|
288
297
|
|
|
289
298
|
```python
|
|
290
299
|
with DivineApi(api_key="...", auth_token="...") as client:
|
|
291
|
-
result = client.horoscope.daily(sign="aries",
|
|
300
|
+
result = client.horoscope.daily(sign="aries", h_day="today", tzone=5.5)
|
|
292
301
|
```
|
|
293
302
|
|
|
294
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
|