- Migrate from SQLite to PostgreSQL with normalized schema - Add 11 lookup tables (fuel_type, body_type, drivetrain, transmission, materials, position_part, manufacture_type, quality_tier, countries, reference_type, shapes) - Rewrite dashboard/server.py (76 routes) using SQLAlchemy text() queries - Rewrite console/db.py (27 methods) using SQLAlchemy ORM - Add models.py with 27 SQLAlchemy model definitions - Add config.py for centralized DB_URL configuration - Add migrate_to_postgres.py migration script - Add docs/METABASE_GUIDE.md with complete data entry guide - Rebrand from "AUTOPARTS DB" to "NEXUS AUTOPARTS" - Fill vehicle data gaps via NHTSA API + heuristics: engines (cylinders, power, torque), brands (country, founded_year), models (body_type, production years), MYE (drivetrain, transmission, trim) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
96 lines
2.5 KiB
Python
96 lines
2.5 KiB
Python
"""
|
|
Entry point for the NEXUS AUTOPARTS Pick/VT220-style console application.
|
|
|
|
Usage:
|
|
python -m console # via package
|
|
python -m console.main # via module
|
|
python console/main.py # direct
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
|
|
from console.config import VERSION, APP_NAME, APP_SUBTITLE, DB_PATH
|
|
|
|
|
|
def parse_args(argv=None):
|
|
"""Parse command-line arguments."""
|
|
parser = argparse.ArgumentParser(
|
|
prog=APP_NAME.lower(),
|
|
description=f"{APP_NAME} - {APP_SUBTITLE}",
|
|
)
|
|
parser.add_argument(
|
|
"--version",
|
|
action="version",
|
|
version=f"{APP_NAME} {VERSION}",
|
|
)
|
|
parser.add_argument(
|
|
"--db",
|
|
default=DB_PATH,
|
|
help="Path to the vehicle database (default: auto-detected)",
|
|
)
|
|
return parser.parse_args(argv)
|
|
|
|
|
|
def _print_banner(db_path):
|
|
"""Print a startup banner before entering terminal mode."""
|
|
border = "=" * 58
|
|
print(border)
|
|
print(f" {APP_NAME} v{VERSION}")
|
|
print(f" {APP_SUBTITLE}")
|
|
print(border)
|
|
print(f" DB : {db_path}")
|
|
print(border)
|
|
print()
|
|
|
|
|
|
def main(argv=None):
|
|
"""Main entry point: parse args, set up renderer, DB, and launch the app."""
|
|
args = parse_args(argv)
|
|
|
|
db_path = args.db
|
|
|
|
# Verify the database file exists before proceeding
|
|
if not os.path.isfile(db_path):
|
|
print(
|
|
f"Error: Database not found at '{db_path}'.\n"
|
|
f"\n"
|
|
f"Make sure the vehicle database exists. You can specify a\n"
|
|
f"custom path with the --db flag:\n"
|
|
f"\n"
|
|
f" python -m console --db /path/to/vehicle_database.db\n",
|
|
file=sys.stderr,
|
|
)
|
|
sys.exit(1)
|
|
|
|
# Lazy imports so the module can be loaded without curses available
|
|
# (e.g. during tests or when just checking --version).
|
|
from console.db import Database
|
|
from console.renderers.curses_renderer import CursesRenderer
|
|
from console.core.app import App
|
|
|
|
# Print startup banner
|
|
_print_banner(db_path)
|
|
|
|
db = Database(db_path)
|
|
renderer = CursesRenderer()
|
|
app = App(renderer=renderer, db=db)
|
|
|
|
try:
|
|
app.run()
|
|
except KeyboardInterrupt:
|
|
pass
|
|
except Exception as e:
|
|
# Ensure terminal is restored before printing the traceback
|
|
try:
|
|
renderer.cleanup()
|
|
except Exception:
|
|
pass
|
|
print(f"\nError: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|