/// 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()