/// script
January 26, 2025 ยท View on GitHub
requires-python = ">=3.12"
dependencies = [
"pyobjc-core",
"pyobjc-framework-CoreLocation",
"click"
]
///
"""Basic geocoding using CoreLocation on macOS."""
import click import objc from CoreLocation import CLGeocoder from Foundation import NSRunLoop, NSDate
def forward_geocode(address: str) -> list[dict]: with objc.autorelease_pool(): geocoder = CLGeocoder.alloc().init() results = {"placemarks": [], "error": None} completed = False
def completion(placemarks, error):
nonlocal completed
if error:
results["error"] = error.localizedDescription()
elif placemarks:
results["placemarks"] = placemarks
completed = True
geocoder.geocodeAddressString_completionHandler_(address, completion)
while not completed:
NSRunLoop.currentRunLoop().runMode_beforeDate_(
"NSDefaultRunLoopMode",
NSDate.dateWithTimeIntervalSinceNow_(0.1)
)
if results["error"]:
raise Exception(f"Geocoding error: {results['error']}")
return [{
"latitude": pm.location().coordinate().latitude,
"longitude": pm.location().coordinate().longitude,
"name": pm.name(),
"locality": pm.locality(),
"country": pm.country()
} for pm in results["placemarks"]]
@click.command() @click.argument('address') def main(address): try: locations = forward_geocode(address) for loc in locations: click.echo("\nLocation found:") for key, value in loc.items(): if value: click.echo(f"{key}: {value}") except Exception as e: click.echo(f"Error: {e}", err=True) raise click.Abort()
if name == "main": main()