#!/usr/bin/env python3 """Robot Framework helper for domain analyzer integration tests.""" from __future__ import annotations import sys from collections.abc import Callable from pathlib import Path # Ensure worktree src is *first* on sys.path so it shadows any installed copy. _SRC = str(Path(__file__).resolve().parents[1] / "src") if _SRC in sys.path: sys.path.remove(_SRC) sys.path.insert(0, _SRC) # Clear cached cleveragents modules so our worktree src is used. for _key in list(sys.modules): if _key.startswith("cleveragents"): del sys.modules[_key] from cleveragents.domain.models.acms.analyzers import ( # noqa: E402 AnalyzerProtocol, AnalyzerRegistry, ) from cleveragents.domain.models.acms.docker_compose_analyzer import ( # noqa: E402 DockerComposeAnalyzer, ) from cleveragents.domain.models.acms.markdown_analyzer import ( # noqa: E402 MarkdownAnalyzer, ) from cleveragents.domain.models.acms.postgresql_analyzer import ( # noqa: E402 PostgreSQLAnalyzer, ) from cleveragents.domain.models.acms.python_analyzer import ( # noqa: E402 PythonAnalyzer, ) # --------------------------------------------------------------------------- # Sample content # --------------------------------------------------------------------------- _SAMPLE_PYTHON = '''\ """User authentication service for the application.""" from __future__ import annotations import hashlib import logging from dataclasses import dataclass, field from typing import Optional logger = logging.getLogger(__name__) @dataclass class Credentials: """Holds user login credentials.""" username: str password_hash: str is_active: bool = True roles: list[str] = field(default_factory=list) class AuthenticationService: """Service responsible for authenticating users against the store.""" def __init__(self, secret_key: str) -> None: self._secret_key = secret_key self._sessions: dict[str, Credentials] = {} def authenticate(self, username: str, password: str) -> Optional[str]: """Authenticate a user and return a session token. Args: username: The login name. password: The plaintext password to verify. Returns: A session token string on success, or None on failure. """ pw_hash = hashlib.sha256( (password + self._secret_key).encode() ).hexdigest() logger.info("Authentication attempt for user=%s", username) return pw_hash if username else None def revoke_session(self, token: str) -> bool: """Revoke an active session by its token.""" if token in self._sessions: del self._sessions[token] return True return False def create_default_service() -> AuthenticationService: """Factory function to create a service with default settings.""" return AuthenticationService(secret_key="default-dev-key") ''' _SAMPLE_MARKDOWN = """\ # Architecture Overview This document describes the high-level architecture of our platform. ## Core Components The system is composed of several key services: - **API Gateway** — routes external traffic - **Auth Service** — handles user authentication - **Data Pipeline** — processes incoming events For more details see [the design doc](https://wiki.example.com/design). ### API Gateway The gateway is built on [Envoy](https://envoyproxy.io) and handles TLS termination, rate limiting, and request routing. ```yaml listeners: - address: 0.0.0.0 port: 8443 tls: true ``` ### Auth Service Token-based authentication using JWT. See [RFC 7519](https://tools.ietf.org/html/rfc7519). ```python def verify_token(token: str) -> Claims: return jwt.decode(token, key=SECRET) ``` ## Deployment The platform runs on Kubernetes with Helm charts managed in the `infra/` directory. Refer to [ops runbook](./runbook.md) for details. """ _SAMPLE_POSTGRESQL = """\ CREATE SCHEMA IF NOT EXISTS app; CREATE TABLE app.users ( id SERIAL PRIMARY KEY, username VARCHAR(120) NOT NULL, email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE TABLE app.roles ( id SERIAL PRIMARY KEY, name VARCHAR(80) NOT NULL, description TEXT ); CREATE TABLE app.user_roles ( user_id INTEGER NOT NULL, role_id INTEGER NOT NULL, granted_at TIMESTAMP DEFAULT NOW(), PRIMARY KEY (user_id, role_id), FOREIGN KEY (user_id) REFERENCES app.users (id), FOREIGN KEY (role_id) REFERENCES app.roles (id) ); CREATE OR REPLACE VIEW app.active_users AS SELECT u.id, u.username, u.email FROM app.users u WHERE u.is_active = TRUE; """ _SAMPLE_DOCKER_COMPOSE = """\ services: web: image: myapp/web:latest ports: - "8080:80" - "8443:443" environment: DATABASE_URL: postgres://db:5432/app REDIS_URL: redis://cache:6379 LOG_LEVEL: info depends_on: - db - cache volumes: - ./config:/app/config:ro db: image: postgres:16-alpine ports: - "5432:5432" environment: POSTGRES_DB: app POSTGRES_USER: appuser POSTGRES_PASSWORD: secret volumes: - pgdata:/var/lib/postgresql/data cache: image: redis:7-alpine ports: - "6379:6379" worker: image: myapp/worker:latest environment: DATABASE_URL: postgres://db:5432/app REDIS_URL: redis://cache:6379 depends_on: - db - cache """ # --------------------------------------------------------------------------- # Helper utilities # --------------------------------------------------------------------------- def _has_object_uri(triples: list, uri_fragment: str) -> bool: """Return True if any triple has *uri_fragment* in its object_uri.""" return any(uri_fragment in t.object_uri for t in triples) # --------------------------------------------------------------------------- # Commands # --------------------------------------------------------------------------- def _cmd_analyze_python() -> int: """Create a PythonAnalyzer, analyze sample Python, verify triple types.""" analyzer = PythonAnalyzer() triples = analyzer.analyze(_SAMPLE_PYTHON, "src/auth/service.py") if not triples: print("analyze-python-fail: no triples produced") return 1 has_module = _has_object_uri(triples, "uko-code:Module") has_class = _has_object_uri(triples, "uko-py:Class") has_function = _has_object_uri(triples, "uko-py:Function") if not has_module: print("analyze-python-fail: missing Module type") return 1 if not has_class: print("analyze-python-fail: missing Class type") return 1 if not has_function: print("analyze-python-fail: missing Function type") return 1 print(f"analyze-python-ok: {len(triples)} triples (Module+Class+Function found)") return 0 def _cmd_analyze_markdown() -> int: """Create a MarkdownAnalyzer, analyze sample markdown, verify triple types.""" analyzer = MarkdownAnalyzer() triples = analyzer.analyze(_SAMPLE_MARKDOWN, "docs/architecture.md") if not triples: print("analyze-markdown-fail: no triples produced") return 1 has_document = _has_object_uri(triples, "uko-doc:Document") has_section = _has_object_uri(triples, "uko-doc:Section") if not has_document: print("analyze-markdown-fail: missing Document type") return 1 if not has_section: print("analyze-markdown-fail: missing Section type") return 1 print(f"analyze-markdown-ok: {len(triples)} triples (Document+Section found)") return 0 def _cmd_analyze_postgresql() -> int: """Create a PostgreSQLAnalyzer, analyze sample DDL, verify triple types.""" analyzer = PostgreSQLAnalyzer() triples = analyzer.analyze(_SAMPLE_POSTGRESQL, "db/migrations/001_init.sql") if not triples: print("analyze-postgresql-fail: no triples produced") return 1 has_table = _has_object_uri(triples, "uko-data:Table") has_column = _has_object_uri(triples, "uko-data:Column") if not has_table: print("analyze-postgresql-fail: missing Table type") return 1 if not has_column: print("analyze-postgresql-fail: missing Column type") return 1 print(f"analyze-postgresql-ok: {len(triples)} triples (Table+Column found)") return 0 def _cmd_analyze_docker_compose() -> int: """Analyze sample compose YAML, verify triple types.""" analyzer = DockerComposeAnalyzer() triples = analyzer.analyze(_SAMPLE_DOCKER_COMPOSE, "infra/docker-compose.yml") if not triples: print("analyze-docker-compose-fail: no triples produced") return 1 has_service = _has_object_uri(triples, "uko-infra:Service") has_deployment = _has_object_uri(triples, "uko-infra:DeploymentUnit") if not has_service: print("analyze-docker-compose-fail: missing Service type") return 1 if not has_deployment: print("analyze-docker-compose-fail: missing DeploymentUnit type") return 1 print( f"analyze-docker-compose-ok: {len(triples)} triples" " (Service+DeploymentUnit found)" ) return 0 def _cmd_protocol_check() -> int: """Verify all 4 analyzers satisfy AnalyzerProtocol.""" analyzer_classes = [ PythonAnalyzer, MarkdownAnalyzer, PostgreSQLAnalyzer, DockerComposeAnalyzer, ] for cls in analyzer_classes: inst = cls() if not isinstance(inst, AnalyzerProtocol): print( f"protocol-check-fail: {cls.__name__} doesn't satisfy AnalyzerProtocol" ) return 1 if not inst.domain: print(f"protocol-check-fail: {cls.__name__} has empty domain") return 1 if not inst.supported_extensions: print(f"protocol-check-fail: {cls.__name__} has no supported extensions") return 1 print( f"protocol-check: {cls.__name__} ok" f" (domain={inst.domain}, extensions={sorted(inst.supported_extensions)})" ) print("protocol-check-ok") return 0 def _cmd_registry_check() -> int: """Create AnalyzerRegistry, register all 4 analyzers, verify lookup by extension.""" registry = AnalyzerRegistry() analyzers = [ PythonAnalyzer(), MarkdownAnalyzer(), PostgreSQLAnalyzer(), DockerComposeAnalyzer(), ] for analyzer in analyzers: registry.register(analyzer) if len(registry) != 4: print(f"registry-check-fail: expected 4 analyzers, got {len(registry)}") return 1 # Verify extension lookup for each analyzer extension_checks = { ".py": "python", ".pyi": "python", ".md": "markdown", ".markdown": "markdown", ".sql": "postgresql", ".ddl": "postgresql", ".yml": "docker-compose", ".yaml": "docker-compose", } for ext, expected_domain in extension_checks.items(): found = registry.get_for_extension(ext) if found is None: print(f"registry-check-fail: no analyzer found for '{ext}'") return 1 if found.domain != expected_domain: print( f"registry-check-fail: expected domain '{expected_domain}'" f" for '{ext}', got '{found.domain}'" ) return 1 print(f"registry-check: '{ext}' -> {found.domain}") # Verify unknown extension returns None if registry.get_for_extension(".unknown") is not None: print("registry-check-fail: expected None for unknown extension") return 1 print(f"registry-check-ok: {len(registry)} analyzers, all extensions verified") return 0 # --------------------------------------------------------------------------- # Main # --------------------------------------------------------------------------- _COMMANDS: dict[str, Callable[[], int]] = { "analyze-python": _cmd_analyze_python, "analyze-markdown": _cmd_analyze_markdown, "analyze-postgresql": _cmd_analyze_postgresql, "analyze-docker-compose": _cmd_analyze_docker_compose, "protocol-check": _cmd_protocol_check, "registry-check": _cmd_registry_check, } def main() -> int: """Run the specified command.""" if len(sys.argv) < 2 or sys.argv[1] not in _COMMANDS: print(f"Usage: {sys.argv[0]} <{'|'.join(_COMMANDS)}>") return 2 return _COMMANDS[sys.argv[1]]() if __name__ == "__main__": sys.exit(main())