Coverage for src/prosemark/cli/init.py: 100%
45 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-24 18:08 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-09-24 18:08 +0000
1"""CLI command for initializing a new prosemark project."""
3from pathlib import Path
4from typing import Any
6import click
8from prosemark.adapters.binder_repo_fs import BinderRepoFs
9from prosemark.adapters.clock_system import ClockSystem
10from prosemark.adapters.console_pretty import ConsolePretty
11from prosemark.adapters.logger_stdout import LoggerStdout
12from prosemark.app.use_cases import InitProject
13from prosemark.exceptions import BinderIntegrityError, FileSystemError
14from prosemark.ports.config_port import ConfigPort, ProsemarkConfig
17class FileSystemConfigPort(ConfigPort):
18 """Temporary config port implementation."""
20 def create_default_config(self, config_path: Path) -> None:
21 """Create default configuration file."""
22 # For MVP, we don't need a config file
24 @staticmethod
25 def config_exists(config_path: Path) -> bool:
26 """Check if configuration file already exists."""
27 return config_path.exists()
29 @staticmethod
30 def get_default_config_values() -> ProsemarkConfig:
31 """Return default configuration values as dictionary."""
32 return {}
34 @staticmethod
35 def load_config(_config_path: Path | None = None) -> dict[str, Any]:
36 """Load configuration from file."""
37 return {}
40@click.command()
41@click.option('--title', '-t', required=True, help='Project title')
42@click.option('--path', '-p', type=click.Path(path_type=Path), help='Project directory')
43def init_command(title: str, path: Path | None) -> None:
44 """Initialize a new prosemark project."""
45 try:
46 project_path = path or Path.cwd()
48 # Wire up dependencies
49 binder_repo = BinderRepoFs(project_path)
50 config_port = FileSystemConfigPort()
51 console_port = ConsolePretty()
52 logger = LoggerStdout()
53 clock = ClockSystem()
55 # Execute use case
56 interactor = InitProject(
57 binder_repo=binder_repo,
58 config_port=config_port,
59 console_port=console_port,
60 logger=logger,
61 clock=clock,
62 )
63 interactor.execute(project_path)
65 # Success output matching test expectations
66 click.echo(f'Project "{title}" initialized successfully')
67 click.echo('Created _binder.md with project structure')
69 except BinderIntegrityError:
70 click.echo('Error: Directory already contains a prosemark project', file=click.get_text_stream('stderr'))
71 raise SystemExit(1) from None
72 except FileSystemError as err:
73 click.echo(f'Error: {err}', file=click.get_text_stream('stderr'))
74 raise SystemExit(2) from err
75 except Exception as err:
76 click.echo(f'Unexpected error: {err}', file=click.get_text_stream('stderr'))
77 raise SystemExit(3) from err