style: Run black formatter on 16 files
Applied black formatting to files modified in linting fixes: Source files (8): - config_extractor.py - doc_scraper.py - how_to_guide_builder.py - llms_txt_downloader.py - llms_txt_parser.py - pattern_recognizer.py - test_example_extractor.py - unified_codebase_analyzer.py Test files (8): - test_architecture_scenarios.py - test_async_scraping.py - test_github_scraper.py - test_guide_enhancer.py - test_install_agent.py - test_issue_219_e2e.py - test_llms_txt_downloader.py - test_skip_llms_txt.py All formatting issues resolved. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -194,11 +194,15 @@ class PythonTestAnalyzer:
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.ClassDef):
|
||||
if self._is_test_class(node):
|
||||
examples.extend(self._extract_from_test_class(node, file_path, imports))
|
||||
examples.extend(
|
||||
self._extract_from_test_class(node, file_path, imports)
|
||||
)
|
||||
|
||||
# Find test functions (pytest)
|
||||
elif isinstance(node, ast.FunctionDef) and self._is_test_function(node):
|
||||
examples.extend(self._extract_from_test_function(node, file_path, imports))
|
||||
examples.extend(
|
||||
self._extract_from_test_function(node, file_path, imports)
|
||||
)
|
||||
|
||||
return examples
|
||||
|
||||
@@ -232,7 +236,9 @@ class PythonTestAnalyzer:
|
||||
return True
|
||||
# Has @pytest.mark decorator
|
||||
for decorator in node.decorator_list:
|
||||
if isinstance(decorator, ast.Attribute) and "pytest" in ast.unparse(decorator):
|
||||
if isinstance(decorator, ast.Attribute) and "pytest" in ast.unparse(
|
||||
decorator
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -249,7 +255,9 @@ class PythonTestAnalyzer:
|
||||
for node in class_node.body:
|
||||
if isinstance(node, ast.FunctionDef) and node.name.startswith("test_"):
|
||||
examples.extend(
|
||||
self._analyze_test_body(node, file_path, imports, setup_code=setup_code)
|
||||
self._analyze_test_body(
|
||||
node, file_path, imports, setup_code=setup_code
|
||||
)
|
||||
)
|
||||
|
||||
return examples
|
||||
@@ -261,7 +269,9 @@ class PythonTestAnalyzer:
|
||||
# Check for fixture parameters
|
||||
fixture_setup = self._extract_fixtures(func_node)
|
||||
|
||||
return self._analyze_test_body(func_node, file_path, imports, setup_code=fixture_setup)
|
||||
return self._analyze_test_body(
|
||||
func_node, file_path, imports, setup_code=fixture_setup
|
||||
)
|
||||
|
||||
def _extract_setup_method(self, class_node: ast.ClassDef) -> str | None:
|
||||
"""Extract setUp method code"""
|
||||
@@ -318,7 +328,9 @@ class PythonTestAnalyzer:
|
||||
examples.extend(configs)
|
||||
|
||||
# 4. Multi-step workflows (integration tests)
|
||||
workflows = self._find_workflows(func_node, file_path, docstring, setup_code, tags, imports)
|
||||
workflows = self._find_workflows(
|
||||
func_node, file_path, docstring, setup_code, tags, imports
|
||||
)
|
||||
examples.extend(workflows)
|
||||
|
||||
return examples
|
||||
@@ -362,7 +374,11 @@ class PythonTestAnalyzer:
|
||||
|
||||
for node in ast.walk(func_node):
|
||||
# Check if meaningful instantiation
|
||||
if isinstance(node, ast.Assign) and isinstance(node.value, ast.Call) and self._is_meaningful_instantiation(node):
|
||||
if (
|
||||
isinstance(node, ast.Assign)
|
||||
and isinstance(node.value, ast.Call)
|
||||
and self._is_meaningful_instantiation(node)
|
||||
):
|
||||
code = ast.unparse(node)
|
||||
|
||||
# Skip trivial or mock-only
|
||||
@@ -408,7 +424,11 @@ class PythonTestAnalyzer:
|
||||
statements = func_node.body
|
||||
for i, stmt in enumerate(statements):
|
||||
# Look for method calls and check if next statement is an assertion
|
||||
if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call) and i + 1 < len(statements):
|
||||
if (
|
||||
isinstance(stmt, ast.Expr)
|
||||
and isinstance(stmt.value, ast.Call)
|
||||
and i + 1 < len(statements)
|
||||
):
|
||||
next_stmt = statements[i + 1]
|
||||
if self._is_assertion(next_stmt):
|
||||
method_call = ast.unparse(stmt)
|
||||
@@ -455,7 +475,11 @@ class PythonTestAnalyzer:
|
||||
|
||||
for node in ast.walk(func_node):
|
||||
# Must have 2+ keys and be meaningful
|
||||
if isinstance(node, ast.Assign) and isinstance(node.value, ast.Dict) and len(node.value.keys) >= 2:
|
||||
if (
|
||||
isinstance(node, ast.Assign)
|
||||
and isinstance(node.value, ast.Dict)
|
||||
and len(node.value.keys) >= 2
|
||||
):
|
||||
code = ast.unparse(node)
|
||||
|
||||
# Check if looks like configuration
|
||||
@@ -467,7 +491,9 @@ class PythonTestAnalyzer:
|
||||
code=code,
|
||||
language="Python",
|
||||
description=f"Configuration example: {description}",
|
||||
expected_behavior=self._extract_assertion_after(func_node, node),
|
||||
expected_behavior=self._extract_assertion_after(
|
||||
func_node, node
|
||||
),
|
||||
setup_code=setup_code,
|
||||
file_path=file_path,
|
||||
line_start=node.lineno,
|
||||
@@ -568,7 +594,9 @@ class PythonTestAnalyzer:
|
||||
integration_keywords = ["workflow", "integration", "end_to_end", "e2e", "full"]
|
||||
return any(keyword in test_name for keyword in integration_keywords)
|
||||
|
||||
def _extract_assertion_after(self, func_node: ast.FunctionDef, target_node: ast.AST) -> str:
|
||||
def _extract_assertion_after(
|
||||
self, func_node: ast.FunctionDef, target_node: ast.AST
|
||||
) -> str:
|
||||
"""Find assertion that follows the target node"""
|
||||
found_target = False
|
||||
for stmt in func_node.body:
|
||||
@@ -699,7 +727,8 @@ class GenericTestAnalyzer:
|
||||
code=config_match.group(0),
|
||||
language=language,
|
||||
file_path=file_path,
|
||||
line_number=code[: start_pos + config_match.start()].count("\n") + 1,
|
||||
line_number=code[: start_pos + config_match.start()].count("\n")
|
||||
+ 1,
|
||||
)
|
||||
examples.append(example)
|
||||
|
||||
@@ -842,7 +871,9 @@ class TestExampleExtractor:
|
||||
logger.warning(f"⚠️ Failed to initialize AI enhancer: {e}")
|
||||
self.enhance_with_ai = False
|
||||
|
||||
def extract_from_directory(self, directory: Path, recursive: bool = True) -> ExampleReport:
|
||||
def extract_from_directory(
|
||||
self, directory: Path, recursive: bool = True
|
||||
) -> ExampleReport:
|
||||
"""Extract examples from all test files in directory"""
|
||||
directory = Path(directory)
|
||||
|
||||
@@ -896,11 +927,13 @@ class TestExampleExtractor:
|
||||
# Limit per file
|
||||
if len(filtered_examples) > self.max_per_file:
|
||||
# Sort by confidence and take top N
|
||||
filtered_examples = sorted(filtered_examples, key=lambda x: x.confidence, reverse=True)[
|
||||
: self.max_per_file
|
||||
]
|
||||
filtered_examples = sorted(
|
||||
filtered_examples, key=lambda x: x.confidence, reverse=True
|
||||
)[: self.max_per_file]
|
||||
|
||||
logger.info(f"Extracted {len(filtered_examples)} examples from {file_path.name}")
|
||||
logger.info(
|
||||
f"Extracted {len(filtered_examples)} examples from {file_path.name}"
|
||||
)
|
||||
|
||||
return filtered_examples
|
||||
|
||||
@@ -955,7 +988,9 @@ class TestExampleExtractor:
|
||||
|
||||
# Calculate averages
|
||||
avg_complexity = (
|
||||
sum(ex.complexity_score for ex in examples) / len(examples) if examples else 0.0
|
||||
sum(ex.complexity_score for ex in examples) / len(examples)
|
||||
if examples
|
||||
else 0.0
|
||||
)
|
||||
high_value_count = sum(1 for ex in examples if ex.confidence > 0.7)
|
||||
|
||||
@@ -1009,10 +1044,15 @@ Examples:
|
||||
help="Minimum confidence threshold (0.0-1.0, default: 0.5)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--max-per-file", type=int, default=10, help="Maximum examples per file (default: 10)"
|
||||
"--max-per-file",
|
||||
type=int,
|
||||
default=10,
|
||||
help="Maximum examples per file (default: 10)",
|
||||
)
|
||||
parser.add_argument("--json", action="store_true", help="Output JSON format")
|
||||
parser.add_argument("--markdown", action="store_true", help="Output Markdown format")
|
||||
parser.add_argument(
|
||||
"--markdown", action="store_true", help="Output Markdown format"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--recursive",
|
||||
action="store_true",
|
||||
@@ -1029,7 +1069,9 @@ Examples:
|
||||
# Create extractor
|
||||
languages = [args.language] if args.language else None
|
||||
extractor = TestExampleExtractor(
|
||||
min_confidence=args.min_confidence, max_per_file=args.max_per_file, languages=languages
|
||||
min_confidence=args.min_confidence,
|
||||
max_per_file=args.max_per_file,
|
||||
languages=languages,
|
||||
)
|
||||
|
||||
# Extract examples
|
||||
@@ -1037,7 +1079,9 @@ Examples:
|
||||
examples = extractor.extract_from_file(Path(args.file))
|
||||
report = extractor._create_report(examples, file_path=args.file)
|
||||
else:
|
||||
report = extractor.extract_from_directory(Path(args.directory), recursive=args.recursive)
|
||||
report = extractor.extract_from_directory(
|
||||
Path(args.directory), recursive=args.recursive
|
||||
)
|
||||
|
||||
# Output results
|
||||
if args.json:
|
||||
|
||||
Reference in New Issue
Block a user