# geoelevation/__main__.py """ Main entry point for the GeoElevation package. Can be run as a CLI to get point elevation or to launch the GUI. - CLI mode: python -m geoelevation --lat --lon [--show-progress] - GUI mode: python -m geoelevation """ import argparse import sys import logging # Configure basic logging for CLI and GUI startup logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) logger = logging.getLogger("geoelevation.main") def main_cli(): """Handles Command Line Interface or launches GUI.""" parser = argparse.ArgumentParser( description="GeoElevation Tool: Get point elevation or launch GUI.", formatter_class=argparse.RawTextHelpFormatter ) parser.add_argument( "--lat", type=float, help="Latitude of the point (e.g., 45.0)" ) parser.add_argument( "--lon", type=float, help="Longitude of the point (e.g., 7.0)" ) parser.add_argument( "--show-progress", action="store_true", help="Display a progress dialog during data retrieval (for CLI point elevation)." ) parser.add_argument( "--verbose", "-v", action="store_true", help="Enable verbose logging output." ) parser.add_argument( "--gui", action="store_true", help="Force launch the GUI application (overrides lat/lon arguments)." ) args = parser.parse_args() if args.verbose: logging.getLogger("geoelevation").setLevel(logging.DEBUG) # Set root logger for package logger.debug("Verbose logging enabled.") # Import the main functions from the package's __init__ # This structure allows __init__.py to be the central point for library functions try: from geoelevation import get_point_elevation, run_gui_application except ImportError as e: logger.critical( f"Failed to import core GeoElevation functions. Package might be corrupted or not installed correctly: {e}", exc_info=True ) # Try to give a hint if run from the wrong directory during development import os if "geoelevation" not in os.getcwd().lower() and os.path.exists("geoelevation"): logger.info("Hint: Try running `python -m geoelevation ...` from the directory *above* the 'geoelevation' package folder.") sys.exit(1) if args.gui: logger.info("Launching GeoElevation GUI (forced by --gui argument)...") run_gui_application() elif args.lat is not None and args.lon is not None: # CLI mode: Get point elevation logger.info(f"CLI mode: Requesting elevation for Latitude: {args.lat}, Longitude: {args.lon}") try: elevation = get_point_elevation( args.lat, args.lon, show_progress_dialog=args.show_progress ) if elevation is None: print("Elevation: UNAVAILABLE (Data could not be retrieved or error occurred. Check logs.)") sys.exit(1) # Exit with error for scripting elif isinstance(elevation, float) and elevation != elevation: # Check for NaN print("Elevation: NODATA (Point is on a NoData area within the tile)") else: print(f"Elevation: {elevation:.2f} meters") except RuntimeError as e_rt: # Catch errors from _get_library_manager or Rasterio not found print(f"ERROR: {e_rt}", file=sys.stderr) logger.error(f"Runtime error during CLI elevation retrieval: {e_rt}", exc_info=True) sys.exit(1) except Exception as e: print(f"An unexpected error occurred: {e}", file=sys.stderr) logger.error(f"Unexpected error during CLI elevation retrieval: {e}", exc_info=True) sys.exit(1) else: # Default mode: Launch GUI if no specific CLI elevation request # (and --gui wasn't used, though that case is handled above) if args.lat is None and args.lon is None: # Ensure no partial lat/lon args logger.info("No specific CLI arguments for point elevation. Launching GeoElevation GUI...") run_gui_application() else: parser.print_help() print("\nError: Both --lat and --lon must be specified for point elevation.", file=sys.stderr) sys.exit(1) if __name__ == "__main__": # This ensures that when running `python -m geoelevation`, the CLI/GUI logic is executed. # For PyInstaller, this __main__.py (inside the geoelevation package) # can now be the entry point. # multiprocessing.freeze_support() is now called inside run_gui_application if GUI runs. main_cli()