Introduce --log-level and --log-file CLI arguments. Add execution time tracking and detailed logs across all modules.
91 lines
3.3 KiB
Python
91 lines
3.3 KiB
Python
from __future__ import annotations
|
|
|
|
from argparse import ArgumentParser
|
|
from pathlib import Path
|
|
import logging
|
|
|
|
from .config import Settings
|
|
from .gemini import GeminiAnalyzer
|
|
from .logging_utils import configure_logging
|
|
from .pipeline import ProjectPipeline
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def build_parser() -> ArgumentParser:
|
|
parser = ArgumentParser(description="Extract and explain UiPath project dependencies.")
|
|
parser.add_argument("project_dir", type=Path, help="UiPath project root directory")
|
|
parser.add_argument(
|
|
"--output-dir",
|
|
type=Path,
|
|
default=Path("workspace"),
|
|
help="Output bundle directory containing separate code/ and docs/ folders",
|
|
)
|
|
parser.add_argument("--entry", default="main.xaml", help="Entry XAML file name")
|
|
parser.add_argument("--env-file", type=Path, default=Path(".env"), help="Environment file for Gemini config")
|
|
parser.add_argument("--model", help="Override GEMINI_MODEL")
|
|
parser.add_argument("--skip-analysis", action="store_true", help="Skip Gemini analysis and only prepare files")
|
|
parser.add_argument("--force", action="store_true", help="Overwrite the output directory if it already exists")
|
|
parser.add_argument(
|
|
"--log-level",
|
|
default="INFO",
|
|
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
help="Logging verbosity",
|
|
)
|
|
parser.add_argument("--log-file", type=Path, help="Optional file path to write logs to")
|
|
return parser
|
|
|
|
|
|
def main(argv: list[str] | None = None) -> int:
|
|
parser = build_parser()
|
|
args = parser.parse_args(argv)
|
|
|
|
project_root = args.project_dir.expanduser().resolve()
|
|
if not project_root.is_dir():
|
|
parser.error(f"Project directory does not exist: {project_root}")
|
|
|
|
output_dir = args.output_dir.expanduser()
|
|
if not output_dir.is_absolute():
|
|
output_dir = Path.cwd() / output_dir
|
|
|
|
log_file = args.log_file.expanduser() if args.log_file else None
|
|
if log_file is not None and not log_file.is_absolute():
|
|
log_file = Path.cwd() / log_file
|
|
configure_logging(level_name=args.log_level, log_file=log_file)
|
|
|
|
logger.info(
|
|
"Starting CLI run: project_root=%s output_dir=%s entry=%s analysis=%s",
|
|
project_root,
|
|
output_dir,
|
|
args.entry,
|
|
not args.skip_analysis,
|
|
)
|
|
|
|
env_file = args.env_file if args.env_file.exists() else None
|
|
if args.env_file and env_file is None:
|
|
logger.warning("Environment file not found, falling back to default dotenv lookup: %s", args.env_file)
|
|
|
|
try:
|
|
settings = Settings.from_env(env_file, model_override=args.model)
|
|
analyzer = None if args.skip_analysis else GeminiAnalyzer(settings)
|
|
|
|
pipeline = ProjectPipeline(
|
|
project_root=project_root,
|
|
output_root=output_dir,
|
|
entry_name=args.entry,
|
|
force=args.force,
|
|
)
|
|
report = pipeline.run(analyzer=analyzer)
|
|
except Exception:
|
|
logger.exception("CLI run failed")
|
|
return 1
|
|
|
|
print(f"Output written to: {report.output_root}")
|
|
print(f"Code written to: {report.code_root}")
|
|
print(f"Docs written to: {report.docs_root}")
|
|
print(f"Final files: {len(report.final_files)}")
|
|
print(f"Pruned files: {len(report.pruned_files)}")
|
|
print(f"Warnings: {len(report.warnings)}")
|
|
return 0
|