astroapi-io-client 0.2.9__tar.gz → 0.2.10__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.
Files changed (26) hide show
  1. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/PKG-INFO +5 -4
  2. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/README.md +4 -3
  3. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/pyproject.toml +1 -1
  4. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/__init__.py +3 -3
  5. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/_validation.py +22 -0
  6. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/client.py +7 -3
  7. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/types.py +28 -0
  8. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_io_client.egg-info/PKG-INFO +5 -4
  9. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_client.py +6 -0
  10. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/LICENSE.txt +0 -0
  11. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/setup.cfg +0 -0
  12. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/errors.py +0 -0
  13. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/py.typed +0 -0
  14. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_client/receipts.py +0 -0
  15. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_io_client.egg-info/SOURCES.txt +0 -0
  16. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_io_client.egg-info/dependency_links.txt +0 -0
  17. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_io_client.egg-info/requires.txt +0 -0
  18. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/src/astroapi_io_client.egg-info/top_level.txt +0 -0
  19. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_aspect_windows_client.py +0 -0
  20. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_calendar_export.py +0 -0
  21. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_davison_input.py +0 -0
  22. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_house_ingresses_client.py +0 -0
  23. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_next_expansions_client.py +0 -0
  24. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_onboarding_context_client.py +0 -0
  25. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_planetary_events_client.py +0 -0
  26. {astroapi_io_client-0.2.9 → astroapi_io_client-0.2.10}/tests/test_varga_input.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astroapi-io-client
3
- Version: 0.2.9
3
+ Version: 0.2.10
4
4
  Summary: Synchronous Python client for the AstroAPI.io calculation gateway
5
5
  License-Expression: ISC
6
6
  Classifier: Programming Language :: Python :: 3
@@ -14,13 +14,13 @@ Dynamic: license-file
14
14
 
15
15
  # AstroAPI.io Python client
16
16
 
17
- The R201 source client `astroapi-io-client==0.2.9` covers all forty-nine calculation routes: forty-eight standard operations plus the separate Pro Nakshatra Timeline. This package version is the verified R201 client publication; service availability still requires R201 promotion. Minor-body calculations are not part of the contract.
17
+ The R202 source client `astroapi-io-client==0.2.10` covers all fifty calculation routes: forty-nine standard operations plus the separate Pro Nakshatra Timeline. This package version is the verified R202 client publication; service availability still requires R202 promotion. Minor-body calculations are not part of the contract.
18
18
 
19
19
  A synchronous client for Python 3.10+, with no runtime dependencies.
20
20
  The package import is `astroapi_client`; the distribution name is
21
- `astroapi-io-client`. Version 0.2.9 is the R201 source client; package availability never implies that source-only R201 API capabilities are deployed.
21
+ `astroapi-io-client`. Version 0.2.10 is the R202 source client; package availability never implies that source-only R202 API capabilities are deployed.
22
22
 
23
- Install from PyPI with `python -m pip install astroapi-io-client==0.2.9`, or install the current source from a local checkout using `python -m pip install ./clients/python`.
23
+ Install from PyPI with `python -m pip install astroapi-io-client==0.2.10`, or install the R202 source from a local checkout using `python -m pip install ./clients/python`.
24
24
  Building needs setuptools and wheel; the installed client uses only the standard
25
25
  library. Keep API credentials in trusted server or command-line environments.
26
26
 
@@ -102,6 +102,7 @@ Type hints describe the server contract and do not perform response validation.
102
102
  | `house_placement_stability` **beta** | `calculateHousePlacementStability` | exact birth and explicit tropical/sidereal profile | exact assignments, unweighted agreement ratios, and deterministic equivalence groups across available 12-house systems |
103
103
  | `aspect_policy_stability` **beta** | `calculateAspectPolicyStability` | exact birth, explicit profile, optional 3–10 points, and 2–4 named aspect policies | admission reasons, signed orb margins, set fingerprints, and deterministic equivalence groups |
104
104
  | `house_boundary_proximity` **beta** | `calculateHouseBoundaryProximity` | exact birth, explicit profile, optional 1–10 points and 0.1–10° threshold | exact two-sided cusp clearance, normalized position, nearest-boundary ties, and explicit no-fallback geometry failures |
105
+ | `location_precision_audit` **beta** | `calculateLocationPrecisionAudit` | exact birth, one explicit 12-house system, 0.1–500 km radius, optional 1–10 points | nine sample rows, planet-house stability, maximum angle/cusp displacement, and explicit no-fallback geometry failures |
105
106
  | `synastry_svg` **beta** | `calculateSynastrySvg` | two births; optional zodiac/houses/theme/aspects/`include_png` | `result["svg"]`, optional `result["png"]` |
106
107
  | `transit_svg` **beta** | `calculateTransitSvg` | birth and transit date; optional display controls/`include_png` | `result["svg"]`, optional `result["png"]` |
107
108
  | `natal_report` **beta** | `calculateNatalReport` | birth; optional zodiac/houses/theme/SVG/download | `result["html"]`, source-linked `result["facts"]`, optional `result["download"]` |
@@ -1,12 +1,12 @@
1
1
  # AstroAPI.io Python client
2
2
 
3
- The R201 source client `astroapi-io-client==0.2.9` covers all forty-nine calculation routes: forty-eight standard operations plus the separate Pro Nakshatra Timeline. This package version is the verified R201 client publication; service availability still requires R201 promotion. Minor-body calculations are not part of the contract.
3
+ The R202 source client `astroapi-io-client==0.2.10` covers all fifty calculation routes: forty-nine standard operations plus the separate Pro Nakshatra Timeline. This package version is the verified R202 client publication; service availability still requires R202 promotion. Minor-body calculations are not part of the contract.
4
4
 
5
5
  A synchronous client for Python 3.10+, with no runtime dependencies.
6
6
  The package import is `astroapi_client`; the distribution name is
7
- `astroapi-io-client`. Version 0.2.9 is the R201 source client; package availability never implies that source-only R201 API capabilities are deployed.
7
+ `astroapi-io-client`. Version 0.2.10 is the R202 source client; package availability never implies that source-only R202 API capabilities are deployed.
8
8
 
9
- Install from PyPI with `python -m pip install astroapi-io-client==0.2.9`, or install the current source from a local checkout using `python -m pip install ./clients/python`.
9
+ Install from PyPI with `python -m pip install astroapi-io-client==0.2.10`, or install the R202 source from a local checkout using `python -m pip install ./clients/python`.
10
10
  Building needs setuptools and wheel; the installed client uses only the standard
11
11
  library. Keep API credentials in trusted server or command-line environments.
12
12
 
@@ -88,6 +88,7 @@ Type hints describe the server contract and do not perform response validation.
88
88
  | `house_placement_stability` **beta** | `calculateHousePlacementStability` | exact birth and explicit tropical/sidereal profile | exact assignments, unweighted agreement ratios, and deterministic equivalence groups across available 12-house systems |
89
89
  | `aspect_policy_stability` **beta** | `calculateAspectPolicyStability` | exact birth, explicit profile, optional 3–10 points, and 2–4 named aspect policies | admission reasons, signed orb margins, set fingerprints, and deterministic equivalence groups |
90
90
  | `house_boundary_proximity` **beta** | `calculateHouseBoundaryProximity` | exact birth, explicit profile, optional 1–10 points and 0.1–10° threshold | exact two-sided cusp clearance, normalized position, nearest-boundary ties, and explicit no-fallback geometry failures |
91
+ | `location_precision_audit` **beta** | `calculateLocationPrecisionAudit` | exact birth, one explicit 12-house system, 0.1–500 km radius, optional 1–10 points | nine sample rows, planet-house stability, maximum angle/cusp displacement, and explicit no-fallback geometry failures |
91
92
  | `synastry_svg` **beta** | `calculateSynastrySvg` | two births; optional zodiac/houses/theme/aspects/`include_png` | `result["svg"]`, optional `result["png"]` |
92
93
  | `transit_svg` **beta** | `calculateTransitSvg` | birth and transit date; optional display controls/`include_png` | `result["svg"]`, optional `result["png"]` |
93
94
  | `natal_report` **beta** | `calculateNatalReport` | birth; optional zodiac/houses/theme/SVG/download | `result["html"]`, source-linked `result["facts"]`, optional `result["download"]` |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "astroapi-io-client"
7
- version = "0.2.9"
7
+ version = "0.2.10"
8
8
  description = "Synchronous Python client for the AstroAPI.io calculation gateway"
9
9
  readme = "README.md"
10
10
  license = "ISC"
@@ -17,7 +17,7 @@ from .types import (
17
17
  GeographicLocation, RelocationChartInput, AstrocartographyBody, AstrocartographyInput,
18
18
  EclipseType, EclipseGeometryInput, EclipseObserverSnapshot, EclipseEvent, EclipseGeometryResponse, MoonPhaseSector, ElectionalAspectFilter,
19
19
  ElectionalFilters, ElectionalSearchInput,
20
- EventRule, EventRuleSearchInput, ConventionProfile, ConventionCompareInput, ReleaseCompareInput, ChartRobustnessInput, CivilTimeAuditInput, ChartInputReadinessExactTime, ChartInputReadinessApproximateTime, ChartInputReadinessUnknownTime, ChartInputReadinessBirthTime, ChartInputReadinessInput, HouseSystemReadinessInput, HousePlacementStabilityInput, AspectPolicyStabilityPoint, AspectPolicyStabilityPolicy, AspectPolicyStabilityInput, HouseBoundaryProximityPoint, HouseBoundaryProximityInput,
20
+ EventRule, EventRuleSearchInput, ConventionProfile, ConventionCompareInput, ReleaseCompareInput, ChartRobustnessInput, CivilTimeAuditInput, ChartInputReadinessExactTime, ChartInputReadinessApproximateTime, ChartInputReadinessUnknownTime, ChartInputReadinessBirthTime, ChartInputReadinessInput, HouseSystemReadinessInput, HousePlacementStabilityInput, AspectPolicyStabilityPoint, AspectPolicyStabilityPolicy, AspectPolicyStabilityInput, HouseBoundaryProximityPoint, HouseBoundaryProximityInput, LocationPrecisionAuditPoint, LocationPrecisionAuditHouseSystem, LocationPrecisionAuditProfile, LocationPrecisionAuditInput,
21
21
  NatalAnalysisAspectName, NatalAnalysisAspectOption, NatalAnalysisInput,
22
22
  AshtakootaInput, AshtakavargaInput, NumerologyInput, PlanetaryHoursInput,
23
23
  FixedStar, FixedStarsInput,
@@ -30,7 +30,7 @@ from .types import (
30
30
  PlaceSearchInput, TimezoneResolveInput, NatalContextInput,
31
31
  )
32
32
 
33
- __version__ = "0.2.9"
33
+ __version__ = "0.2.10"
34
34
  __all__ = [
35
35
  "NumerologyInput", "verify_calculation_receipt",
36
36
  "AstroAPIClient", "AstroAPIError", "ClientBusyError", "HTTPError", "DavisonInput",
@@ -45,7 +45,7 @@ __all__ = [
45
45
  "GeographicLocation", "RelocationChartInput", "AstrocartographyBody", "AstrocartographyInput",
46
46
  "EclipseType", "EclipseGeometryInput", "EclipseObserverSnapshot", "EclipseEvent", "EclipseGeometryResponse", "MoonPhaseSector", "ElectionalAspectFilter",
47
47
  "ElectionalFilters", "ElectionalSearchInput",
48
- "EventRule", "EventRuleSearchInput", "ConventionProfile", "ConventionCompareInput", "ReleaseCompareInput", "ChartRobustnessInput", "CivilTimeAuditInput", "ChartInputReadinessExactTime", "ChartInputReadinessApproximateTime", "ChartInputReadinessUnknownTime", "ChartInputReadinessBirthTime", "ChartInputReadinessInput", "HouseSystemReadinessInput", "HousePlacementStabilityInput", "AspectPolicyStabilityPoint", "AspectPolicyStabilityPolicy", "AspectPolicyStabilityInput", "HouseBoundaryProximityPoint", "HouseBoundaryProximityInput",
48
+ "EventRule", "EventRuleSearchInput", "ConventionProfile", "ConventionCompareInput", "ReleaseCompareInput", "ChartRobustnessInput", "CivilTimeAuditInput", "ChartInputReadinessExactTime", "ChartInputReadinessApproximateTime", "ChartInputReadinessUnknownTime", "ChartInputReadinessBirthTime", "ChartInputReadinessInput", "HouseSystemReadinessInput", "HousePlacementStabilityInput", "AspectPolicyStabilityPoint", "AspectPolicyStabilityPolicy", "AspectPolicyStabilityInput", "HouseBoundaryProximityPoint", "HouseBoundaryProximityInput", "LocationPrecisionAuditPoint", "LocationPrecisionAuditHouseSystem", "LocationPrecisionAuditProfile", "LocationPrecisionAuditInput",
49
49
  "NatalAnalysisAspectName", "NatalAnalysisAspectOption", "NatalAnalysisInput",
50
50
  "AshtakootaInput", "AshtakavargaInput", "PlanetaryHoursInput",
51
51
  "FixedStar", "FixedStarsInput",
@@ -27,6 +27,12 @@ _CONFIGURABLE_ASPECTS = {
27
27
  "conjunction", "semisextile", "semisquare", "sextile", "quintile",
28
28
  "square", "trine", "sesquiquadrate", "biquintile", "quincunx", "opposition",
29
29
  }
30
+ _NATAL_HOUSE_SYSTEMS = {
31
+ "equal", "whole_sign", "placidus", "porphyry", "meridian", "campanus",
32
+ "regiomontanus", "alcabitius", "koch", "morinus", "topocentric", "sripati",
33
+ "vehlow", "horizon", "krusinski", "sunshine", "sunshine_alt", "savard",
34
+ "pullen_sd", "pullen_sr", "carter", "apc", "equal_mc", "natural",
35
+ }
30
36
 
31
37
 
32
38
  def _invalid(message: str = "Request does not match the route's supported input fields.") -> None:
@@ -746,6 +752,22 @@ def encode_request(route: str, payload: Any) -> bytes:
746
752
  or not 0.1 <= threshold <= 10.0
747
753
  or abs(threshold * 10 - round(threshold * 10)) > 1e-9):
748
754
  _invalid("threshold_degrees must be 0.1 through 10.0 in 0.1 degree increments.")
755
+ elif route == "location-precision-audit":
756
+ _object(data, {"birth", "profile", "radius_km", "points"}, {"birth", "profile", "radius_km"})
757
+ birth = _object(data["birth"], {"date", "time", "timezone", "lat", "lon"}, {"date", "time", "timezone", "lat", "lon"})
758
+ _birth(birth)
759
+ profile = _object(data["profile"], {"zodiac", "ayanamsa", "house_system"}, {"zodiac", "house_system"})
760
+ _enum(profile["zodiac"], {"tropical", "sidereal"}, "zodiac must be tropical or sidereal.")
761
+ _enum(profile["house_system"], _NATAL_HOUSE_SYSTEMS, "house_system must be a documented 12-house system.")
762
+ if profile["zodiac"] == "tropical" and "ayanamsa" in profile:
763
+ _invalid("tropical profiles cannot include ayanamsa.")
764
+ if profile["zodiac"] == "sidereal" and ("ayanamsa" not in profile or profile["ayanamsa"] not in _AYANAMSAS):
765
+ _invalid("sidereal profiles require a supported ayanamsa.")
766
+ radius = data["radius_km"]
767
+ if type(radius) not in {int, float} or not math.isfinite(radius) or not 0.1 <= radius <= 500.0:
768
+ _invalid("radius_km must be a finite number from 0.1 through 500.")
769
+ if "points" in data:
770
+ _unique_enum_list(data["points"], _PLANETARY_EVENT_BODIES, 10, "points")
749
771
  elif route in {"house-system-readiness", "house-placement-stability"}:
750
772
  _object(data, {"birth", "profile"}, {"birth", "profile"})
751
773
  birth = _object(data["birth"], {"date", "time", "timezone", "lat", "lon"}, {"date", "time", "timezone", "lat", "lon"})
@@ -32,7 +32,7 @@ from .types import (
32
32
  MoonPhaseInput, MoonPhaseResponse, DavisonInput, PlanetaryEventsInput, PlanetaryEventsResponse,
33
33
  HouseIngressesInput, HouseIngressesResponse,
34
34
  AspectWindowsInput, AspectWindowsResponse,
35
- EventRuleSearchInput, ConventionCompareInput, ReleaseCompareInput, ChartRobustnessInput, CivilTimeAuditInput, ChartInputReadinessInput, HouseSystemReadinessInput, HousePlacementStabilityInput, AspectPolicyStabilityInput, HouseBoundaryProximityInput,
35
+ EventRuleSearchInput, ConventionCompareInput, ReleaseCompareInput, ChartRobustnessInput, CivilTimeAuditInput, ChartInputReadinessInput, HouseSystemReadinessInput, HousePlacementStabilityInput, AspectPolicyStabilityInput, HouseBoundaryProximityInput, LocationPrecisionAuditInput,
36
36
  EventCalendarInput, SynastrySvgInput, TransitSvgInput, NatalReportInput,
37
37
  BirthTimeSensitivityInput, RelocationChartInput, AstrocartographyInput,
38
38
  PlaceSearchInput, TimezoneResolveInput, NatalContextInput,
@@ -181,7 +181,7 @@ def _perform(
181
181
  "Content-Type": "application/json",
182
182
  "Accept": "application/json",
183
183
  "Accept-Encoding": "identity",
184
- "User-Agent": "astroapi-io-client/0.2.9",
184
+ "User-Agent": "astroapi-io-client/0.2.10",
185
185
  "Connection": "close",
186
186
  **({"X-AstroAPI-Receipt": "v1"} if request_receipt else {}),
187
187
  })
@@ -285,7 +285,7 @@ class AstroAPIClient:
285
285
 
286
286
  def _request(self, route: str, payload: object) -> JSONResponse:
287
287
  body = encode_request(route, payload)
288
- timeout = (self._timeline_timeout if route in {"nakshatra-timeline", "birth-time-sensitivity", "chart-robustness", "chart-input-readiness", "house-system-readiness", "house-placement-stability", "house-boundary-proximity"}
288
+ timeout = (self._timeline_timeout if route in {"nakshatra-timeline", "birth-time-sensitivity", "chart-robustness", "chart-input-readiness", "house-system-readiness", "house-placement-stability", "house-boundary-proximity", "location-precision-audit"}
289
289
  else self._planetary_events_timeout if route in {"planetary-events", "house-ingresses", "eclipse-geometry", "electional-search", "event-rule-search"}
290
290
  else self._aspect_windows_timeout if route == "aspect-windows"
291
291
  else self._timeout)
@@ -452,6 +452,10 @@ class AstroAPIClient:
452
452
  """BETA: audit exact two-sided cusp clearance across 12-house systems."""
453
453
  return self._request("house-boundary-proximity", payload)
454
454
 
455
+ def location_precision_audit(self, payload: LocationPrecisionAuditInput) -> JSONResponse:
456
+ """BETA: audit coordinate precision at a center plus eight perimeter samples."""
457
+ return self._request("location-precision-audit", payload)
458
+
455
459
  def synastry_svg(self, payload: SynastrySvgInput) -> JSONResponse:
456
460
  """BETA: original deterministic double-wheel relationship SVG."""
457
461
  return self._request("synastry-svg", payload)
@@ -436,6 +436,34 @@ class HouseBoundaryProximityInput(_HouseBoundaryProximityRequired, total=False):
436
436
  threshold_degrees: float
437
437
 
438
438
 
439
+ LocationPrecisionAuditPoint = HouseBoundaryProximityPoint
440
+ LocationPrecisionAuditHouseSystem = Literal[
441
+ "equal", "whole_sign", "placidus", "porphyry", "meridian", "campanus",
442
+ "regiomontanus", "alcabitius", "koch", "morinus", "topocentric", "sripati",
443
+ "vehlow", "horizon", "krusinski", "sunshine", "sunshine_alt", "savard",
444
+ "pullen_sd", "pullen_sr", "carter", "apc", "equal_mc", "natural",
445
+ ]
446
+
447
+
448
+ class _LocationPrecisionAuditProfileRequired(TypedDict):
449
+ zodiac: Zodiac
450
+ house_system: LocationPrecisionAuditHouseSystem
451
+
452
+
453
+ class LocationPrecisionAuditProfile(_LocationPrecisionAuditProfileRequired, total=False):
454
+ ayanamsa: Ayanamsa
455
+
456
+
457
+ class _LocationPrecisionAuditRequired(TypedDict):
458
+ birth: BirthInput
459
+ profile: LocationPrecisionAuditProfile
460
+ radius_km: float
461
+
462
+
463
+ class LocationPrecisionAuditInput(_LocationPrecisionAuditRequired, total=False):
464
+ points: list[LocationPrecisionAuditPoint]
465
+
466
+
439
467
  class ReleaseCompareInput(TypedDict):
440
468
  releases: list[JSONResponse]
441
469
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astroapi-io-client
3
- Version: 0.2.9
3
+ Version: 0.2.10
4
4
  Summary: Synchronous Python client for the AstroAPI.io calculation gateway
5
5
  License-Expression: ISC
6
6
  Classifier: Programming Language :: Python :: 3
@@ -14,13 +14,13 @@ Dynamic: license-file
14
14
 
15
15
  # AstroAPI.io Python client
16
16
 
17
- The R201 source client `astroapi-io-client==0.2.9` covers all forty-nine calculation routes: forty-eight standard operations plus the separate Pro Nakshatra Timeline. This package version is the verified R201 client publication; service availability still requires R201 promotion. Minor-body calculations are not part of the contract.
17
+ The R202 source client `astroapi-io-client==0.2.10` covers all fifty calculation routes: forty-nine standard operations plus the separate Pro Nakshatra Timeline. This package version is the verified R202 client publication; service availability still requires R202 promotion. Minor-body calculations are not part of the contract.
18
18
 
19
19
  A synchronous client for Python 3.10+, with no runtime dependencies.
20
20
  The package import is `astroapi_client`; the distribution name is
21
- `astroapi-io-client`. Version 0.2.9 is the R201 source client; package availability never implies that source-only R201 API capabilities are deployed.
21
+ `astroapi-io-client`. Version 0.2.10 is the R202 source client; package availability never implies that source-only R202 API capabilities are deployed.
22
22
 
23
- Install from PyPI with `python -m pip install astroapi-io-client==0.2.9`, or install the current source from a local checkout using `python -m pip install ./clients/python`.
23
+ Install from PyPI with `python -m pip install astroapi-io-client==0.2.10`, or install the R202 source from a local checkout using `python -m pip install ./clients/python`.
24
24
  Building needs setuptools and wheel; the installed client uses only the standard
25
25
  library. Keep API credentials in trusted server or command-line environments.
26
26
 
@@ -102,6 +102,7 @@ Type hints describe the server contract and do not perform response validation.
102
102
  | `house_placement_stability` **beta** | `calculateHousePlacementStability` | exact birth and explicit tropical/sidereal profile | exact assignments, unweighted agreement ratios, and deterministic equivalence groups across available 12-house systems |
103
103
  | `aspect_policy_stability` **beta** | `calculateAspectPolicyStability` | exact birth, explicit profile, optional 3–10 points, and 2–4 named aspect policies | admission reasons, signed orb margins, set fingerprints, and deterministic equivalence groups |
104
104
  | `house_boundary_proximity` **beta** | `calculateHouseBoundaryProximity` | exact birth, explicit profile, optional 1–10 points and 0.1–10° threshold | exact two-sided cusp clearance, normalized position, nearest-boundary ties, and explicit no-fallback geometry failures |
105
+ | `location_precision_audit` **beta** | `calculateLocationPrecisionAudit` | exact birth, one explicit 12-house system, 0.1–500 km radius, optional 1–10 points | nine sample rows, planet-house stability, maximum angle/cusp displacement, and explicit no-fallback geometry failures |
105
106
  | `synastry_svg` **beta** | `calculateSynastrySvg` | two births; optional zodiac/houses/theme/aspects/`include_png` | `result["svg"]`, optional `result["png"]` |
106
107
  | `transit_svg` **beta** | `calculateTransitSvg` | birth and transit date; optional display controls/`include_png` | `result["svg"]`, optional `result["png"]` |
107
108
  | `natal_report` **beta** | `calculateNatalReport` | birth; optional zodiac/houses/theme/SVG/download | `result["html"]`, source-linked `result["facts"]`, optional `result["download"]` |
@@ -85,6 +85,7 @@ ROUTES += [
85
85
  ("house_placement_stability", "house-placement-stability", HOUSE_PLACEMENT_STABILITY_INPUT, {"type": "house_placement_stability", "status": "beta", "input": BIRTH, "profile": {}, "systems": [{} for _ in range(25)], "planets": [{} for _ in range(10)], "placement_groups": [], "summary": {}, "fallback": {"performed": False, "selected_system": None}, "metadata": {}}),
86
86
  ("aspect_policy_stability", "aspect-policy-stability", ASPECT_POLICY_STABILITY_INPUT, {"type": "aspect_policy_stability", "status": "beta", "input": {}, "positions": {}, "evaluations": [], "policy_results": [{}, {}], "policy_groups": [{}], "summary": {}, "metadata": {}}),
87
87
  ("house_boundary_proximity", "house-boundary-proximity", {"birth": BIRTH, "profile": {"zodiac": "tropical"}, "points": ["sun", "moon"], "threshold_degrees": 2.0}, {"type": "house_boundary_proximity", "status": "beta", "input": {}, "systems": [{} for _ in range(25)], "point_summaries": [{}, {}], "summary": {}, "fallback": {"performed": False, "selected_system": None}, "metadata": {}}),
88
+ ("location_precision_audit", "location-precision-audit", {"birth": BIRTH, "profile": {"zodiac": "tropical", "house_system": "placidus"}, "radius_km": 25.0, "points": ["sun", "moon"]}, {"type": "location_precision_audit", "status": "beta", "input": {}, "samples": [{} for _ in range(9)], "point_summaries": [{}, {}], "angle_summaries": {}, "cusp_summaries": [{} for _ in range(12)], "summary": {}, "fallback": {"performed": False, "selected_system": None}, "metadata": {}}),
88
89
  ]
89
90
 
90
91
  @contextmanager
@@ -190,6 +191,7 @@ ROUTES += [
190
191
  ("house_placement_stability", "house-placement-stability", HOUSE_PLACEMENT_STABILITY_INPUT, {"type": "house_placement_stability", "status": "beta", "input": BIRTH, "profile": {}, "systems": [{} for _ in range(25)], "planets": [{} for _ in range(10)], "placement_groups": [], "summary": {}, "fallback": {"performed": False, "selected_system": None}, "metadata": {}}),
191
192
  ("aspect_policy_stability", "aspect-policy-stability", ASPECT_POLICY_STABILITY_INPUT, {"type": "aspect_policy_stability", "status": "beta", "input": {}, "positions": {}, "evaluations": [], "policy_results": [{}, {}], "policy_groups": [{}], "summary": {}, "metadata": {}}),
192
193
  ("house_boundary_proximity", "house-boundary-proximity", {"birth": BIRTH, "profile": {"zodiac": "tropical"}, "points": ["sun", "moon"], "threshold_degrees": 2.0}, {"type": "house_boundary_proximity", "status": "beta", "input": {}, "systems": [{} for _ in range(25)], "point_summaries": [{}, {}], "summary": {}, "fallback": {"performed": False, "selected_system": None}, "metadata": {}}),
194
+ ("location_precision_audit", "location-precision-audit", {"birth": BIRTH, "profile": {"zodiac": "tropical", "house_system": "placidus"}, "radius_km": 25.0, "points": ["sun", "moon"]}, {"type": "location_precision_audit", "status": "beta", "input": {}, "samples": [{} for _ in range(9)], "point_summaries": [{}, {}], "angle_summaries": {}, "cusp_summaries": [{} for _ in range(12)], "summary": {}, "fallback": {"performed": False, "selected_system": None}, "metadata": {}}),
193
195
  ]
194
196
 
195
197
  @contextmanager
@@ -449,6 +451,10 @@ class ClientTests(unittest.TestCase):
449
451
  client.civil_time_audit({**CIVIL_TIME_AUDIT_INPUT, "place_id": "geonames:5128581:2020-01-01"})
450
452
  with self.assertRaises(ValidationError):
451
453
  client.chart_input_readiness({**CHART_INPUT_READINESS_INPUT, "birth_time": {"status": "approximate", "date": "2000-01-01", "time": "12:00"}})
454
+ with self.assertRaises(ValidationError):
455
+ client.location_precision_audit({"birth": BIRTH, "profile": {"zodiac": "tropical", "house_system": "placidus"}, "radius_km": 0})
456
+ with self.assertRaises(ValidationError):
457
+ client.location_precision_audit({"birth": BIRTH, "profile": {"zodiac": "tropical", "house_system": "gauquelin"}, "radius_km": 25})
452
458
 
453
459
 
454
460
  def test_request_body_limit(self):