Skip to content

Commit 621da80

Browse files
committed
Fix ruff findings in files touched by artifact-aware generation
CI lints every changed Python file in full, so pre-existing findings in the files this branch touches also fail the check. Apply ruff's safe fixes and formatting (pep585/pep604 annotations, import ordering, regex flag aliases) and resolve the rest by hand without behaviour changes: - blind `except Exception` sites get `# noqa: BLE001` with the reason, as the codebase already does elsewhere; bare `except:` becomes `except Exception` - subprocess.run calls pass `check=False` and use `capture_output=True` - dead assignments removed (`repo_name`, `filtered_folders_path`, `generation_time`, `start_time`, `generation_options`, `current_branch`) along with the imports they kept alive - mutable default arguments in `cluster_modules()` become `None` and are normalised at the top of the function - nested ifs merged, `endswith` tuple, needless-bool return, loop-variable closure in the package.json exports walker takes explicit parameters - shebang removed from the non-executable str_replace_editor module
1 parent aed1c19 commit 621da80

15 files changed

Lines changed: 1208 additions & 747 deletions

File tree

‎codewiki/cli/adapters/doc_generator.py‎

Lines changed: 109 additions & 101 deletions
Large diffs are not rendered by default.

‎codewiki/cli/commands/generate.py‎

Lines changed: 187 additions & 146 deletions
Large diffs are not rendered by default.

‎codewiki/cli/models/config.py‎

Lines changed: 117 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -6,104 +6,108 @@
66
to the backend Config class when running documentation generation.
77
"""
88

9-
from dataclasses import dataclass, asdict, field
10-
from typing import Optional, List
11-
from pathlib import Path
9+
from dataclasses import dataclass, field
1210

1311
from codewiki.cli.utils.validation import (
14-
validate_url,
15-
validate_api_key,
1612
validate_model_name,
13+
validate_url,
1714
)
1815

1916

2017
@dataclass
2118
class AgentInstructions:
2219
"""
2320
Custom instructions for the documentation agent.
24-
21+
2522
Allows users to customize:
2623
- File filtering (include/exclude patterns)
2724
- Module focus (prioritize certain modules)
2825
- Documentation type (API docs, architecture docs, etc.)
2926
- Custom instructions for the LLM
30-
27+
3128
Attributes:
3229
include_patterns: File patterns to include (e.g., ["*.cs", "*.py"])
3330
exclude_patterns: File/directory patterns to exclude (e.g., ["*Tests*", "*test*"])
3431
focus_modules: Modules to document in more detail
3532
doc_type: Type of documentation to generate
3633
custom_instructions: Additional instructions for the documentation agent
3734
"""
38-
include_patterns: Optional[List[str]] = None # e.g., ["*.cs"] for C# projects
39-
exclude_patterns: Optional[List[str]] = None # e.g., ["*Tests*", "*Specs*"]
40-
focus_modules: Optional[List[str]] = None # e.g., ["src/core", "src/api"]
41-
doc_type: Optional[str] = None # e.g., "api", "architecture", "user-guide"
42-
custom_instructions: Optional[str] = None # Free-form instructions
43-
artifact_exclude: Optional[List[str]] = None # e.g., ["docker/data/*"] skipped by artifact analysis
44-
35+
36+
include_patterns: list[str] | None = None # e.g., ["*.cs"] for C# projects
37+
exclude_patterns: list[str] | None = None # e.g., ["*Tests*", "*Specs*"]
38+
focus_modules: list[str] | None = None # e.g., ["src/core", "src/api"]
39+
doc_type: str | None = None # e.g., "api", "architecture", "user-guide"
40+
custom_instructions: str | None = None # Free-form instructions
41+
artifact_exclude: list[str] | None = (
42+
None # e.g., ["docker/data/*"] skipped by artifact analysis
43+
)
44+
4545
def to_dict(self) -> dict:
4646
"""Convert to dictionary, excluding None values."""
4747
result = {}
4848
if self.include_patterns:
49-
result['include_patterns'] = self.include_patterns
49+
result["include_patterns"] = self.include_patterns
5050
if self.exclude_patterns:
51-
result['exclude_patterns'] = self.exclude_patterns
51+
result["exclude_patterns"] = self.exclude_patterns
5252
if self.artifact_exclude:
53-
result['artifact_exclude'] = self.artifact_exclude
53+
result["artifact_exclude"] = self.artifact_exclude
5454
if self.focus_modules:
55-
result['focus_modules'] = self.focus_modules
55+
result["focus_modules"] = self.focus_modules
5656
if self.doc_type:
57-
result['doc_type'] = self.doc_type
57+
result["doc_type"] = self.doc_type
5858
if self.custom_instructions:
59-
result['custom_instructions'] = self.custom_instructions
59+
result["custom_instructions"] = self.custom_instructions
6060
return result
61-
61+
6262
@classmethod
63-
def from_dict(cls, data: dict) -> 'AgentInstructions':
63+
def from_dict(cls, data: dict) -> "AgentInstructions":
6464
"""Create AgentInstructions from dictionary."""
6565
return cls(
66-
include_patterns=data.get('include_patterns'),
67-
exclude_patterns=data.get('exclude_patterns'),
68-
focus_modules=data.get('focus_modules'),
69-
doc_type=data.get('doc_type'),
70-
custom_instructions=data.get('custom_instructions'),
71-
artifact_exclude=data.get('artifact_exclude'),
66+
include_patterns=data.get("include_patterns"),
67+
exclude_patterns=data.get("exclude_patterns"),
68+
focus_modules=data.get("focus_modules"),
69+
doc_type=data.get("doc_type"),
70+
custom_instructions=data.get("custom_instructions"),
71+
artifact_exclude=data.get("artifact_exclude"),
7272
)
73-
73+
7474
def is_empty(self) -> bool:
7575
"""Check if all fields are empty/None."""
76-
return not any([
77-
self.include_patterns,
78-
self.exclude_patterns,
79-
self.artifact_exclude,
80-
self.focus_modules,
81-
self.doc_type,
82-
self.custom_instructions,
83-
])
84-
76+
return not any(
77+
[
78+
self.include_patterns,
79+
self.exclude_patterns,
80+
self.artifact_exclude,
81+
self.focus_modules,
82+
self.doc_type,
83+
self.custom_instructions,
84+
]
85+
)
86+
8587
def get_prompt_addition(self) -> str:
8688
"""Generate prompt additions based on instructions."""
8789
additions = []
88-
90+
8991
if self.doc_type:
9092
doc_type_instructions = {
91-
'api': "Focus on API documentation: endpoints, parameters, return types, and usage examples.",
92-
'architecture': "Focus on architecture documentation: system design, component relationships, and data flow.",
93-
'user-guide': "Focus on user guide documentation: how to use features, step-by-step tutorials.",
94-
'developer': "Focus on developer documentation: code structure, contribution guidelines, and implementation details.",
93+
"api": "Focus on API documentation: endpoints, parameters, return types, and usage examples.",
94+
"architecture": "Focus on architecture documentation: system design, component relationships, and data flow.",
95+
"user-guide": "Focus on user guide documentation: how to use features, step-by-step tutorials.",
96+
"developer": "Focus on developer documentation: code structure, contribution guidelines, and implementation details.",
9597
}
9698
if self.doc_type.lower() in doc_type_instructions:
9799
additions.append(doc_type_instructions[self.doc_type.lower()])
98100
else:
99101
additions.append(f"Focus on generating {self.doc_type} documentation.")
100-
102+
101103
if self.focus_modules:
102-
additions.append(f"Pay special attention to and provide more detailed documentation for these modules: {', '.join(self.focus_modules)}")
103-
104+
additions.append(
105+
f"Pay special attention to and provide more detailed documentation for these modules: {', '.join(self.focus_modules)}"
106+
)
107+
104108
if self.custom_instructions:
105109
additions.append(f"Additional instructions: {self.custom_instructions}")
106-
110+
107111
return "\n".join(additions) if additions else ""
108112

109113

@@ -130,6 +134,7 @@ class Configuration:
130134
prompt_caching: Add prompt-cache breakpoints to agentic LLM calls (default: True)
131135
agent_instructions: Custom agent instructions for documentation generation
132136
"""
137+
133138
base_url: str
134139
main_model: str
135140
cluster_model: str
@@ -146,7 +151,7 @@ class Configuration:
146151
use_gitignore: bool = True
147152
prompt_caching: bool = True
148153
agent_instructions: AgentInstructions = field(default_factory=AgentInstructions)
149-
154+
150155
def validate(self):
151156
"""
152157
Validate all configuration fields.
@@ -158,71 +163,72 @@ def validate(self):
158163
ConfigurationError: If validation fails
159164
"""
160165
from codewiki.src.be.backend import is_caw_provider
166+
161167
if is_caw_provider(self.provider):
162168
validate_model_name(self.main_model)
163169
return
164170
validate_url(self.base_url)
165171
validate_model_name(self.main_model)
166172
validate_model_name(self.cluster_model)
167173
validate_model_name(self.fallback_model)
168-
174+
169175
def to_dict(self) -> dict:
170176
"""Convert to dictionary."""
171177
result = {
172-
'base_url': self.base_url,
173-
'main_model': self.main_model,
174-
'cluster_model': self.cluster_model,
175-
'default_output': self.default_output,
176-
'provider': self.provider,
177-
'aws_region': self.aws_region,
178-
'api_version': self.api_version,
179-
'azure_deployment': self.azure_deployment,
180-
'max_tokens': self.max_tokens,
181-
'max_token_per_module': self.max_token_per_module,
182-
'max_token_per_leaf_module': self.max_token_per_leaf_module,
183-
'max_depth': self.max_depth,
184-
'use_gitignore': self.use_gitignore,
185-
'prompt_caching': self.prompt_caching,
186-
'fallback_model': self.fallback_model,
178+
"base_url": self.base_url,
179+
"main_model": self.main_model,
180+
"cluster_model": self.cluster_model,
181+
"default_output": self.default_output,
182+
"provider": self.provider,
183+
"aws_region": self.aws_region,
184+
"api_version": self.api_version,
185+
"azure_deployment": self.azure_deployment,
186+
"max_tokens": self.max_tokens,
187+
"max_token_per_module": self.max_token_per_module,
188+
"max_token_per_leaf_module": self.max_token_per_leaf_module,
189+
"max_depth": self.max_depth,
190+
"use_gitignore": self.use_gitignore,
191+
"prompt_caching": self.prompt_caching,
192+
"fallback_model": self.fallback_model,
187193
}
188194
if self.agent_instructions and not self.agent_instructions.is_empty():
189-
result['agent_instructions'] = self.agent_instructions.to_dict()
195+
result["agent_instructions"] = self.agent_instructions.to_dict()
190196
return result
191-
197+
192198
@classmethod
193-
def from_dict(cls, data: dict) -> 'Configuration':
199+
def from_dict(cls, data: dict) -> "Configuration":
194200
"""
195201
Create Configuration from dictionary.
196-
202+
197203
Args:
198204
data: Configuration dictionary
199-
205+
200206
Returns:
201207
Configuration instance
202208
"""
203209
agent_instructions = AgentInstructions()
204-
if 'agent_instructions' in data:
205-
agent_instructions = AgentInstructions.from_dict(data['agent_instructions'])
206-
210+
if "agent_instructions" in data:
211+
agent_instructions = AgentInstructions.from_dict(data["agent_instructions"])
212+
207213
return cls(
208-
base_url=data.get('base_url', ''),
209-
main_model=data.get('main_model', ''),
210-
cluster_model=data.get('cluster_model', ''),
211-
fallback_model=data.get('fallback_model', 'glm-4p5'),
212-
default_output=data.get('default_output', 'docs'),
213-
provider=data.get('provider', 'openai-compatible'),
214-
aws_region=data.get('aws_region', 'us-east-1'),
215-
api_version=data.get('api_version', '2024-12-01-preview'),
216-
azure_deployment=data.get('azure_deployment', ''),
217-
max_tokens=data.get('max_tokens', 32768),
218-
max_token_per_module=data.get('max_token_per_module', 36369),
219-
max_token_per_leaf_module=data.get('max_token_per_leaf_module', 16000),
220-
max_depth=data.get('max_depth', 2),
221-
use_gitignore=data.get('use_gitignore', True),
222-
prompt_caching=data.get('prompt_caching', True),
214+
base_url=data.get("base_url", ""),
215+
main_model=data.get("main_model", ""),
216+
cluster_model=data.get("cluster_model", ""),
217+
fallback_model=data.get("fallback_model", "glm-4p5"),
218+
default_output=data.get("default_output", "docs"),
219+
provider=data.get("provider", "openai-compatible"),
220+
aws_region=data.get("aws_region", "us-east-1"),
221+
api_version=data.get("api_version", "2024-12-01-preview"),
222+
azure_deployment=data.get("azure_deployment", ""),
223+
max_tokens=data.get("max_tokens", 32768),
224+
max_token_per_module=data.get("max_token_per_module", 36369),
225+
max_token_per_leaf_module=data.get("max_token_per_leaf_module", 16000),
226+
max_depth=data.get("max_depth", 2),
227+
use_gitignore=data.get("use_gitignore", True),
228+
prompt_caching=data.get("prompt_caching", True),
223229
agent_instructions=agent_instructions,
224230
)
225-
231+
226232
def is_complete(self) -> bool:
227233
"""Check if all required fields are set.
228234
@@ -231,45 +237,53 @@ def is_complete(self) -> bool:
231237
are unused.
232238
"""
233239
from codewiki.src.be.backend import is_caw_provider
240+
234241
if is_caw_provider(self.provider):
235242
return bool(self.main_model)
236243
return bool(
237-
self.base_url and
238-
self.main_model and
239-
self.cluster_model and
240-
self.fallback_model
244+
self.base_url and self.main_model and self.cluster_model and self.fallback_model
241245
)
242-
243-
def to_backend_config(self, repo_path: str, output_dir: str, api_key: str, runtime_instructions: AgentInstructions = None):
246+
247+
def to_backend_config(
248+
self,
249+
repo_path: str,
250+
output_dir: str,
251+
api_key: str,
252+
runtime_instructions: AgentInstructions = None,
253+
):
244254
"""
245255
Convert CLI Configuration to Backend Config.
246-
256+
247257
This method bridges the gap between persistent user settings (CLI Configuration)
248258
and runtime job configuration (Backend Config).
249-
259+
250260
Args:
251261
repo_path: Path to the repository to document
252262
output_dir: Output directory for generated documentation
253263
api_key: LLM API key (from keyring)
254264
runtime_instructions: Runtime agent instructions (override persistent settings)
255-
265+
256266
Returns:
257267
Backend Config instance ready for documentation generation
258268
"""
259269
from codewiki.src.config import Config
260-
270+
261271
# Merge runtime instructions with persistent settings
262272
# Runtime instructions take precedence
263273
final_instructions = self.agent_instructions
264274
if runtime_instructions and not runtime_instructions.is_empty():
265275
final_instructions = AgentInstructions(
266-
include_patterns=runtime_instructions.include_patterns or self.agent_instructions.include_patterns,
267-
exclude_patterns=runtime_instructions.exclude_patterns or self.agent_instructions.exclude_patterns,
268-
focus_modules=runtime_instructions.focus_modules or self.agent_instructions.focus_modules,
276+
include_patterns=runtime_instructions.include_patterns
277+
or self.agent_instructions.include_patterns,
278+
exclude_patterns=runtime_instructions.exclude_patterns
279+
or self.agent_instructions.exclude_patterns,
280+
focus_modules=runtime_instructions.focus_modules
281+
or self.agent_instructions.focus_modules,
269282
doc_type=runtime_instructions.doc_type or self.agent_instructions.doc_type,
270-
custom_instructions=runtime_instructions.custom_instructions or self.agent_instructions.custom_instructions,
283+
custom_instructions=runtime_instructions.custom_instructions
284+
or self.agent_instructions.custom_instructions,
271285
)
272-
286+
273287
return Config.from_cli(
274288
repo_path=repo_path,
275289
output_dir=output_dir,

0 commit comments

Comments
 (0)