From 1bf531cc74ceecc5a9111970162237c5df985bb3 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Fri, 30 Jan 2026 18:57:28 +0000 Subject: [PATCH] Add core source files: main, models, config --- src/codexchange/models.py | 118 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/codexchange/models.py diff --git a/src/codexchange/models.py b/src/codexchange/models.py new file mode 100644 index 0000000..0ee9169 --- /dev/null +++ b/src/codexchange/models.py @@ -0,0 +1,118 @@ +"""Pydantic models for CodeXchange CLI.""" + +from enum import Enum +from typing import Optional + +from pydantic import BaseModel, Field, field_validator + + +class Language(str, Enum): + """Supported programming languages.""" + + JAVASCRIPT = "javascript" + TYPESCRIPT = "typescript" + PYTHON = "python" + JAVA = "java" + + @classmethod + def from_extension(cls, extension: str) -> Optional["Language"]: + """Get language from file extension.""" + extension_map = { + ".js": cls.JAVASCRIPT, + ".jsx": cls.JAVASCRIPT, + ".ts": cls.TYPESCRIPT, + ".tsx": cls.TYPESCRIPT, + ".py": cls.PYTHON, + ".java": cls.JAVA, + } + return extension_map.get(extension.lower()) + + @property + def extension(self) -> str: + """Get file extension for language.""" + extension_map = { + Language.JAVASCRIPT: ".js", + Language.TYPESCRIPT: ".ts", + Language.PYTHON: ".py", + Language.JAVA: ".java", + } + return extension_map[self] + + @property + def syntax_check_command(self) -> Optional[str]: + """Get syntax check command for language.""" + commands = { + Language.PYTHON: "python", + Language.TYPESCRIPT: "npx tsc --noEmit", + Language.JAVASCRIPT: "npx eslint", + Language.JAVA: None, + } + return commands.get(self) + + +VALID_CONVERSIONS = { + (Language.JAVASCRIPT, Language.TYPESCRIPT), + (Language.JAVASCRIPT, Language.PYTHON), + (Language.TYPESCRIPT, Language.JAVASCRIPT), + (Language.TYPESCRIPT, Language.PYTHON), + (Language.PYTHON, Language.JAVASCRIPT), + (Language.PYTHON, Language.TYPESCRIPT), + (Language.JAVA, Language.PYTHON), + (Language.PYTHON, Language.JAVA), + (Language.JAVASCRIPT, Language.JAVA), + (Language.JAVA, Language.JAVASCRIPT), + (Language.TYPESCRIPT, Language.JAVA), + (Language.JAVA, Language.TYPESCRIPT), +} + + +class ConversionRequest(BaseModel): + """Request model for code conversion.""" + + source_code: str = Field(..., description="Source code to convert") + source_language: Language = Field(..., description="Source programming language") + target_language: Language = Field(..., description="Target programming language") + model: str = Field(default="codellama", description="Ollama model to use") + + @field_validator("target_language") + @classmethod + def validate_conversion(cls, v: Language, info) -> Language: + """Validate that the conversion pair is supported.""" + source = info.data.get("source_language") + if source and (source, v) not in VALID_CONVERSIONS: + raise ValueError( + f"Conversion from {source.value} to {v.value} is not supported. " + f"Supported conversions: JS<->TS, JS<->Python, JS<->Java, TS<->Python, TS<->Java, Python<->Java" + ) + return v + + +class ConversionResult(BaseModel): + """Result model for code conversion.""" + + success: bool + converted_code: Optional[str] = None + original_code: str + source_language: Language + target_language: Language + model: str + error_message: Optional[str] = None + syntax_verified: bool = False + syntax_warnings: list[str] = Field(default_factory=list) + + +class ModelInfo(BaseModel): + """Information about an Ollama model.""" + + name: str + size: Optional[str] = None + modified_at: Optional[str] = None + + +class FileConversionResult(BaseModel): + """Result of converting a single file.""" + + input_path: str + output_path: Optional[str] = None + success: bool + error_message: Optional[str] = None