| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 |
- from __future__ import annotations
- from collections import Counter
- from dataclasses import dataclass
- from pathlib import Path
- from .models import Subsystem
- DEFAULT_SRC_ROOT = Path(__file__).resolve().parent
- @dataclass(frozen=True)
- class PortManifest:
- src_root: Path
- total_python_files: int
- top_level_modules: tuple[Subsystem, ...]
- def to_markdown(self) -> str:
- lines = [
- f'Port root: `{self.src_root}`',
- f'Total Python files: **{self.total_python_files}**',
- '',
- 'Top-level Python modules:',
- ]
- for module in self.top_level_modules:
- lines.append(f'- `{module.name}` ({module.file_count} files) — {module.notes}')
- return '\n'.join(lines)
- def build_port_manifest(src_root: Path | None = None) -> PortManifest:
- root = src_root or DEFAULT_SRC_ROOT
- files = [path for path in root.rglob('*.py') if path.is_file()]
- counter = Counter(
- path.relative_to(root).parts[0] if len(path.relative_to(root).parts) > 1 else path.name
- for path in files
- if path.name != '__pycache__'
- )
- notes = {
- '__init__.py': 'package export surface',
- 'main.py': 'CLI entrypoint',
- 'port_manifest.py': 'workspace manifest generation',
- 'query_engine.py': 'port orchestration summary layer',
- 'commands.py': 'command backlog metadata',
- 'tools.py': 'tool backlog metadata',
- 'models.py': 'shared dataclasses',
- 'task.py': 'task-level planning structures',
- }
- modules = tuple(
- Subsystem(name=name, path=f'src/{name}', file_count=count, notes=notes.get(name, 'Python port support module'))
- for name, count in counter.most_common()
- )
- return PortManifest(src_root=root, total_python_files=len(files), top_level_modules=modules)
|