auto-coder 0.1.314__py3-none-any.whl → 0.1.316__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

@@ -0,0 +1,243 @@
1
+ """
2
+ Module providing a factory for creating language-specific linters.
3
+ """
4
+
5
+ import os
6
+ from typing import Optional, Dict, Any, List
7
+
8
+ from autocoder.linters.base_linter import BaseLinter
9
+ from autocoder.linters.code_linter import FrontendLinter
10
+ from autocoder.linters.python_linter import PythonLinter
11
+
12
+ class LinterFactory:
13
+ """
14
+ Factory class for creating appropriate linter instances based on file type or language.
15
+ """
16
+
17
+ @classmethod
18
+ def create_linter(cls, language: Optional[str] = None, file_path: Optional[str] = None, verbose: bool = False) -> BaseLinter:
19
+ """
20
+ Create and return an appropriate linter instance based on language or file path.
21
+
22
+ Args:
23
+ language (Optional[str]): Language identifier ('python', 'javascript', 'typescript', etc.).
24
+ file_path (Optional[str]): Path to a file to infer the language from.
25
+ verbose (bool): Whether to enable verbose output in the linter.
26
+
27
+ Returns:
28
+ BaseLinter: An instance of a linter appropriate for the language.
29
+
30
+ Raises:
31
+ ValueError: If no language could be determined or if the language is not supported.
32
+ """
33
+ if language is None and file_path is None:
34
+ raise ValueError("Either language or file_path must be provided")
35
+
36
+ # If language is not provided, try to infer from file path
37
+ if language is None and file_path is not None:
38
+ language = cls._detect_language_from_file(file_path)
39
+
40
+ # Map language to linter class
41
+ linter_map = {
42
+ 'python': PythonLinter,
43
+ 'javascript': FrontendLinter,
44
+ 'typescript': FrontendLinter,
45
+ 'js': FrontendLinter,
46
+ 'ts': FrontendLinter,
47
+ 'jsx': FrontendLinter,
48
+ 'tsx': FrontendLinter,
49
+ 'react': FrontendLinter,
50
+ 'vue': FrontendLinter,
51
+ }
52
+
53
+ linter_class = linter_map.get(language.lower() if language else None)
54
+
55
+ if linter_class is None:
56
+ raise ValueError(f"Unsupported language: {language}")
57
+
58
+ return linter_class(verbose=verbose)
59
+
60
+ @classmethod
61
+ def _detect_language_from_file(cls, file_path: str) -> str:
62
+ """
63
+ Detect the programming language based on file extension.
64
+
65
+ Args:
66
+ file_path (str): Path to the file.
67
+
68
+ Returns:
69
+ str: Language identifier.
70
+
71
+ Raises:
72
+ ValueError: If the file extension is not recognized.
73
+ """
74
+ if not os.path.exists(file_path):
75
+ raise ValueError(f"File does not exist: {file_path}")
76
+
77
+ _, ext = os.path.splitext(file_path)
78
+ ext = ext.lower()
79
+
80
+ # Map extensions to languages
81
+ extension_map = {
82
+ '.py': 'python',
83
+ '.js': 'javascript',
84
+ '.ts': 'typescript',
85
+ '.jsx': 'react',
86
+ '.tsx': 'react',
87
+ '.vue': 'vue',
88
+ }
89
+
90
+ language = extension_map.get(ext)
91
+ if language is None:
92
+ raise ValueError(f"Unsupported file extension: {ext}")
93
+
94
+ return language
95
+
96
+ @classmethod
97
+ def get_supported_languages(cls) -> List[str]:
98
+ """
99
+ Get a list of supported programming languages.
100
+
101
+ Returns:
102
+ List[str]: List of supported language identifiers.
103
+ """
104
+ return ['python', 'javascript', 'typescript', 'react', 'vue']
105
+
106
+ @classmethod
107
+ def lint_file(cls, file_path: str, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
108
+ """
109
+ Lint a single file using the appropriate linter.
110
+
111
+ Args:
112
+ file_path (str): Path to the file to lint.
113
+ fix (bool): Whether to automatically fix fixable issues.
114
+ verbose (bool): Whether to enable verbose output.
115
+
116
+ Returns:
117
+ Dict[str, Any]: Lint results.
118
+ """
119
+ linter = cls.create_linter(file_path=file_path, verbose=verbose)
120
+ return linter.lint_file(file_path, fix=fix)
121
+
122
+ @classmethod
123
+ def lint_project(cls, project_path: str, language: Optional[str] = None, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
124
+ """
125
+ Lint a project using the appropriate linter.
126
+
127
+ Args:
128
+ project_path (str): Path to the project directory.
129
+ language (Optional[str]): Language identifier to specify which linter to use.
130
+ If not provided, will try to auto-detect.
131
+ fix (bool): Whether to automatically fix fixable issues.
132
+ verbose (bool): Whether to enable verbose output.
133
+
134
+ Returns:
135
+ Dict[str, Any]: Lint results.
136
+ """
137
+ # If language not specified, try to detect from project contents
138
+ if language is None:
139
+ # First check for package.json (JavaScript/TypeScript)
140
+ if os.path.exists(os.path.join(project_path, 'package.json')):
141
+ linter = cls.create_linter(language='javascript', verbose=verbose)
142
+ # Check for setup.py or requirements.txt (Python)
143
+ elif (os.path.exists(os.path.join(project_path, 'setup.py')) or
144
+ os.path.exists(os.path.join(project_path, 'requirements.txt'))):
145
+ linter = cls.create_linter(language='python', verbose=verbose)
146
+ else:
147
+ # Count file extensions to guess the dominant language
148
+ language_counts = {}
149
+ for root, _, files in os.walk(project_path):
150
+ for file in files:
151
+ _, ext = os.path.splitext(file)
152
+ ext = ext.lower()
153
+ language_counts[ext] = language_counts.get(ext, 0) + 1
154
+
155
+ # Find the most common relevant extension
156
+ relevant_extensions = {'.py', '.js', '.ts', '.jsx', '.tsx', '.vue'}
157
+ most_common = None
158
+ max_count = 0
159
+
160
+ for ext, count in language_counts.items():
161
+ if ext in relevant_extensions and count > max_count:
162
+ most_common = ext
163
+ max_count = count
164
+
165
+ if most_common is None:
166
+ raise ValueError(f"Could not detect project language in {project_path}")
167
+
168
+ language = cls._detect_language_from_file(f"dummy{most_common}")
169
+ linter = cls.create_linter(language=language, verbose=verbose)
170
+ else:
171
+ linter = cls.create_linter(language=language, verbose=verbose)
172
+
173
+ return linter.lint_project(project_path, fix=fix)
174
+
175
+ @classmethod
176
+ def format_lint_result(cls, lint_result: Dict[str, Any], language: Optional[str] = None) -> str:
177
+ """
178
+ Format lint results into a human-readable string.
179
+
180
+ Args:
181
+ lint_result (Dict[str, Any]): The lint result dictionary.
182
+ language (Optional[str]): Language identifier to specify which formatter to use.
183
+ If not provided, will try to infer from lint_result.
184
+
185
+ Returns:
186
+ str: A formatted string representation of the lint results.
187
+ """
188
+ # Try to infer language from lint_result
189
+ if language is None:
190
+ if 'language' in lint_result:
191
+ language = lint_result['language']
192
+ elif 'project_type' in lint_result:
193
+ language = lint_result['project_type']
194
+ elif 'file_type' in lint_result:
195
+ language = lint_result['file_type']
196
+ else:
197
+ # Default to Python as a fallback
198
+ language = 'python'
199
+
200
+ linter = cls.create_linter(language=language)
201
+ return linter.format_lint_result(lint_result)
202
+
203
+ def lint_file(file_path: str, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
204
+ """
205
+ Utility function to lint a single file.
206
+
207
+ Args:
208
+ file_path (str): Path to the file to lint.
209
+ fix (bool): Whether to automatically fix fixable issues.
210
+ verbose (bool): Whether to display verbose output.
211
+
212
+ Returns:
213
+ Dict[str, Any]: A dictionary containing lint results.
214
+ """
215
+ return LinterFactory.lint_file(file_path, fix=fix, verbose=verbose)
216
+
217
+ def lint_project(project_path: str, language: Optional[str] = None, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
218
+ """
219
+ Utility function to lint a project.
220
+
221
+ Args:
222
+ project_path (str): Path to the project directory.
223
+ language (Optional[str]): Language identifier to specify which linter to use.
224
+ fix (bool): Whether to automatically fix fixable issues.
225
+ verbose (bool): Whether to display verbose output.
226
+
227
+ Returns:
228
+ Dict[str, Any]: A dictionary containing lint results.
229
+ """
230
+ return LinterFactory.lint_project(project_path, language=language, fix=fix, verbose=verbose)
231
+
232
+ def format_lint_result(lint_result: Dict[str, Any], language: Optional[str] = None) -> str:
233
+ """
234
+ Format lint results into a human-readable string.
235
+
236
+ Args:
237
+ lint_result (Dict): The lint result dictionary.
238
+ language (Optional[str]): Language identifier to specify which formatter to use.
239
+
240
+ Returns:
241
+ str: A formatted string representation of the lint results.
242
+ """
243
+ return LinterFactory.format_lint_result(lint_result, language=language)