redup 0.3.23__tar.gz → 0.3.24__tar.gz

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.
Files changed (61) hide show
  1. {redup-0.3.23 → redup-0.3.24}/PKG-INFO +2 -2
  2. {redup-0.3.23 → redup-0.3.24}/README.md +1 -1
  3. {redup-0.3.23 → redup-0.3.24}/pyproject.toml +1 -1
  4. {redup-0.3.23 → redup-0.3.24}/src/redup/__init__.py +1 -1
  5. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/config_builder.py +2 -2
  6. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/scan_commands.py +4 -4
  7. {redup-0.3.23 → redup-0.3.24}/src/redup/core/pipeline.py +28 -32
  8. redup-0.3.24/src/redup/core/scanner.py +647 -0
  9. {redup-0.3.23 → redup-0.3.24}/src/redup.egg-info/PKG-INFO +2 -2
  10. {redup-0.3.23 → redup-0.3.24}/src/redup.egg-info/SOURCES.txt +0 -3
  11. redup-0.3.23/src/redup/core/memory_scanner.py +0 -285
  12. redup-0.3.23/src/redup/core/parallel_scanner.py +0 -234
  13. redup-0.3.23/src/redup/core/scanner.py +0 -373
  14. redup-0.3.23/src/redup/core/ultra_fast_scanner.py +0 -358
  15. {redup-0.3.23 → redup-0.3.24}/LICENSE +0 -0
  16. {redup-0.3.23 → redup-0.3.24}/setup.cfg +0 -0
  17. {redup-0.3.23 → redup-0.3.24}/src/redup/__main__.py +0 -0
  18. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/__init__.py +0 -0
  19. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/fuzzy_similarity.py +0 -0
  20. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/main.py +0 -0
  21. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/output_writer.py +0 -0
  22. {redup-0.3.23 → redup-0.3.24}/src/redup/cli_app/scan_helpers.py +0 -0
  23. {redup-0.3.23 → redup-0.3.24}/src/redup/core/__init__.py +0 -0
  24. {redup-0.3.23 → redup-0.3.24}/src/redup/core/cache.py +0 -0
  25. {redup-0.3.23 → redup-0.3.24}/src/redup/core/config.py +0 -0
  26. {redup-0.3.23 → redup-0.3.24}/src/redup/core/differ.py +0 -0
  27. {redup-0.3.23 → redup-0.3.24}/src/redup/core/fuzzy_similarity.py +0 -0
  28. {redup-0.3.23 → redup-0.3.24}/src/redup/core/hash_cache.py +0 -0
  29. {redup-0.3.23 → redup-0.3.24}/src/redup/core/hasher.py +0 -0
  30. {redup-0.3.23 → redup-0.3.24}/src/redup/core/lazy_grouper.py +0 -0
  31. {redup-0.3.23 → redup-0.3.24}/src/redup/core/lsh_matcher.py +0 -0
  32. {redup-0.3.23 → redup-0.3.24}/src/redup/core/matcher.py +0 -0
  33. {redup-0.3.23 → redup-0.3.24}/src/redup/core/models.py +0 -0
  34. {redup-0.3.23 → redup-0.3.24}/src/redup/core/planner.py +0 -0
  35. {redup-0.3.23 → redup-0.3.24}/src/redup/core/ts_extractor.py +0 -0
  36. {redup-0.3.23 → redup-0.3.24}/src/redup/core/universal_fuzzy.py +0 -0
  37. {redup-0.3.23 → redup-0.3.24}/src/redup/core/utils/__init__.py +0 -0
  38. {redup-0.3.23 → redup-0.3.24}/src/redup/core/utils/duplicate_finders.py +0 -0
  39. {redup-0.3.23 → redup-0.3.24}/src/redup/core/utils/function_extractor.py +0 -0
  40. {redup-0.3.23 → redup-0.3.24}/src/redup/core/utils/hash_utils.py +0 -0
  41. {redup-0.3.23 → redup-0.3.24}/src/redup/core/utils/language_dispatcher.py +0 -0
  42. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/__init__.py +0 -0
  43. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/code2llm_reporter.py +0 -0
  44. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/enhanced_reporter.py +0 -0
  45. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/json_reporter.py +0 -0
  46. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/markdown_reporter.py +0 -0
  47. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/toon_reporter.py +0 -0
  48. {redup-0.3.23 → redup-0.3.24}/src/redup/reporters/yaml_reporter.py +0 -0
  49. {redup-0.3.23 → redup-0.3.24}/src/redup.egg-info/dependency_links.txt +0 -0
  50. {redup-0.3.23 → redup-0.3.24}/src/redup.egg-info/entry_points.txt +0 -0
  51. {redup-0.3.23 → redup-0.3.24}/src/redup.egg-info/requires.txt +0 -0
  52. {redup-0.3.23 → redup-0.3.24}/src/redup.egg-info/top_level.txt +0 -0
  53. {redup-0.3.23 → redup-0.3.24}/tests/test_e2e.py +0 -0
  54. {redup-0.3.23 → redup-0.3.24}/tests/test_hasher.py +0 -0
  55. {redup-0.3.23 → redup-0.3.24}/tests/test_matcher.py +0 -0
  56. {redup-0.3.23 → redup-0.3.24}/tests/test_models.py +0 -0
  57. {redup-0.3.23 → redup-0.3.24}/tests/test_pipeline.py +0 -0
  58. {redup-0.3.23 → redup-0.3.24}/tests/test_planner.py +0 -0
  59. {redup-0.3.23 → redup-0.3.24}/tests/test_reporters.py +0 -0
  60. {redup-0.3.23 → redup-0.3.24}/tests/test_scanner.py +0 -0
  61. {redup-0.3.23 → redup-0.3.24}/tests/test_ts_extractor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: redup
3
- Version: 0.3.23
3
+ Version: 0.3.24
4
4
  Summary: Code duplication analyzer and refactoring planner for LLMs
5
5
  Author-email: Tom Sapletta <tom@sapletta.com>
6
6
  License-Expression: Apache-2.0
@@ -84,7 +84,7 @@ Dynamic: license-file
84
84
  [![PyPI](https://img.shields.io/pypi/v/redup)](https://pypi.org/project/redup/)
85
85
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
86
86
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://python.org)
87
- [![Version](https://img.shields.io/badge/version-0.3.23-green.svg)](https://pypi.org/project/redup/)
87
+ [![Version](https://img.shields.io/badge/version-0.3.24-green.svg)](https://pypi.org/project/redup/)
88
88
 
89
89
  reDUP scans codebases for duplicated functions, blocks, and structural patterns — then builds a prioritized refactoring map that LLMs can consume to eliminate redundancy systematically.
90
90
 
@@ -5,7 +5,7 @@
5
5
  [![PyPI](https://img.shields.io/pypi/v/redup)](https://pypi.org/project/redup/)
6
6
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
7
  [![Python](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://python.org)
8
- [![Version](https://img.shields.io/badge/version-0.3.23-green.svg)](https://pypi.org/project/redup/)
8
+ [![Version](https://img.shields.io/badge/version-0.3.24-green.svg)](https://pypi.org/project/redup/)
9
9
 
10
10
  reDUP scans codebases for duplicated functions, blocks, and structural patterns — then builds a prioritized refactoring map that LLMs can consume to eliminate redundancy systematically.
11
11
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "redup"
7
- version = "0.3.23"
7
+ version = "0.3.24"
8
8
  description = "Code duplication analyzer and refactoring planner for LLMs"
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
@@ -2,7 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.3.23"
5
+ __version__ = "0.3.24"
6
6
 
7
7
  from redup.core.models import (
8
8
  DuplicateFragment,
@@ -42,13 +42,13 @@ def build_config_with_file_support(
42
42
  if extensions is not None:
43
43
  scan_config.extensions = [e.strip() for e in extensions.split(',')]
44
44
  if min_lines is not None:
45
- scan_config.min_lines = min_lines
45
+ scan_config.min_block_lines = min_lines
46
46
  if min_similarity is not None:
47
47
  scan_config.min_similarity = min_similarity
48
48
  if include_tests is not None:
49
49
  scan_config.include_tests = include_tests
50
50
  if functions_only:
51
- scan_config.function_level_only = functions_only
51
+ scan_config.functions_only = functions_only
52
52
 
53
53
  # Add fuzzy support
54
54
  scan_config.fuzzy_enabled = fuzzy
@@ -33,16 +33,16 @@ def scan_command(
33
33
  """Scan a project for code duplicates."""
34
34
 
35
35
  # Build configuration
36
- if any([extensions, min_lines, min_similarity, include_tests, functions_only, parallel, max_workers, incremental, memory_cache, max_cache_mb]):
36
+ if any([extensions, min_lines, min_similarity, include_tests, functions_only, parallel, max_workers, incremental, memory_cache, max_cache_mb, fuzzy]):
37
37
  config = build_config_with_file_support(
38
38
  path, extensions, min_lines, min_similarity, include_tests,
39
- parallel, max_workers, incremental, memory_cache, max_cache_mb, functions_only
39
+ parallel, max_workers, incremental, memory_cache, max_cache_mb, functions_only, fuzzy, fuzzy_threshold
40
40
  )
41
41
  else:
42
42
  config = build_config(path, extensions, min_lines, min_similarity, include_tests)
43
43
 
44
44
  # Print scan header
45
- print_scan_header(path, config.extensions, config.min_lines, config.min_similarity)
45
+ print_scan_header(path, config.extensions, config.min_block_lines, config.min_similarity)
46
46
 
47
47
  # Run analysis
48
48
  if parallel and max_workers and max_workers > 1:
@@ -92,7 +92,7 @@ def check_command(
92
92
  path, extensions, min_lines, min_similarity, include_tests
93
93
  )
94
94
 
95
- print_scan_header(path, config.extensions, config.min_lines, config.min_similarity)
95
+ print_scan_header(path, config.extensions, config.min_block_lines, config.min_similarity)
96
96
 
97
97
  dup_map = analyze(config)
98
98
  print_scan_summary(dup_map)
@@ -16,7 +16,7 @@ from redup.core.hasher import (
16
16
  )
17
17
  from redup.core.lsh_matcher import find_near_duplicates
18
18
  from redup.core.matcher import MatchResult, refine_structural_matches
19
- from redup.core.parallel_scanner import scan_project_parallel
19
+ from redup.core.scanner import scan_project, ScanStrategy
20
20
  from redup.core.models import (
21
21
  DuplicateFragment,
22
22
  DuplicateGroup,
@@ -26,10 +26,9 @@ from redup.core.models import (
26
26
  ScanStats,
27
27
  )
28
28
  from redup.core.planner import generate_suggestions
29
- from redup.core.scanner import CodeBlock, ScannedFile, scan_project
29
+ from redup.core.scanner import CodeBlock, ScannedFile
30
30
  from redup.core.cache import HashCache, build_hash_index_with_cache
31
31
  from redup.core.lazy_grouper import find_all_duplicates_lazy, DuplicateGroupCollector
32
- from redup.core.memory_scanner import scan_project_memory_optimized, scan_project_parallel_memory_optimized
33
32
 
34
33
 
35
34
  def _blocks_to_group(
@@ -184,26 +183,29 @@ def analyze_optimized(
184
183
  # Phase 1: Optimized scanning with memory cache
185
184
  if config.parallel_workers and config.parallel_workers > 1:
186
185
  # Explicit worker count specified
187
- if use_memory_cache:
188
- scanned_files, stats = scan_project_parallel_memory_optimized(
189
- config, config.parallel_workers, max_cache_mb
190
- )
191
- else:
192
- scanned_files, stats = _scan_phase_parallel(config, config.parallel_workers)
186
+ strategy = ScanStrategy(
187
+ parallel=True,
188
+ max_workers=config.parallel_workers,
189
+ memory_cache=use_memory_cache,
190
+ max_cache_mb=max_cache_mb if use_memory_cache else 256
191
+ )
192
+ scanned_files, stats = scan_project(config, strategy, function_level_only=True)
193
193
  elif config.parallel_workers is None and (getattr(config, '_parallel_enabled', False) or config.parallel_workers is None):
194
194
  # Auto-detect CPU count when parallel_workers is None (default behavior)
195
195
  import multiprocessing as mp
196
196
  auto_workers = mp.cpu_count()
197
- if use_memory_cache:
198
- scanned_files, stats = scan_project_parallel_memory_optimized(
199
- config, auto_workers, max_cache_mb
200
- )
201
- else:
202
- scanned_files, stats = _scan_phase_parallel(config, auto_workers)
197
+ strategy = ScanStrategy(
198
+ parallel=True,
199
+ max_workers=auto_workers,
200
+ memory_cache=use_memory_cache,
201
+ max_cache_mb=max_cache_mb if use_memory_cache else 256
202
+ )
203
+ scanned_files, stats = scan_project(config, strategy, function_level_only=True)
203
204
  elif use_memory_cache:
204
- scanned_files, stats = scan_project_memory_optimized(config, max_cache_mb)
205
+ strategy = ScanStrategy(memory_cache=True, max_cache_mb=max_cache_mb)
206
+ scanned_files, stats = scan_project(config, strategy, function_level_only=True)
205
207
  else:
206
- scanned_files, stats = _scan_phase(config)
208
+ scanned_files, stats = scan_project(config, function_level_only=True)
207
209
 
208
210
  # Phase 2: Process blocks
209
211
  all_blocks = _process_blocks(scanned_files, function_level_only)
@@ -260,15 +262,8 @@ def _scan_phase(config: ScanConfig, function_level_only: bool = False) -> tuple[
260
262
 
261
263
  def _scan_phase_parallel(config: ScanConfig, max_workers: int | None = None) -> tuple[list[ScannedFile], ScanStats]:
262
264
  """Phase 1: Scan project files in parallel."""
263
- return scan_project_parallel(
264
- root=config.root,
265
- extensions=config.extensions,
266
- exclude_patterns=config.exclude_patterns,
267
- include_tests=config.include_tests,
268
- function_level_only=True, # Always function-level for parallel
269
- max_file_size=config.max_file_size_kb,
270
- max_workers=max_workers,
271
- )
265
+ strategy = ScanStrategy(parallel=True, max_workers=max_workers or 4)
266
+ return scan_project(config, strategy, function_level_only=True)
272
267
 
273
268
 
274
269
  def _process_blocks(
@@ -552,12 +547,13 @@ def analyze_optimized(
552
547
 
553
548
  try:
554
549
  # Phase 1: Optimized Scan (parallel + memory cache)
555
- if use_memory_cache:
556
- scanned_files, stats = scan_project_parallel_memory_optimized(
557
- config, max_workers=None, max_cache_mb=max_cache_mb
558
- )
559
- else:
560
- scanned_files, stats = scan_project_parallel(config)
550
+ strategy = ScanStrategy(
551
+ parallel=True,
552
+ max_workers=None, # Auto-detect
553
+ memory_cache=use_memory_cache,
554
+ max_cache_mb=max_cache_mb
555
+ )
556
+ scanned_files, stats = scan_project(config, strategy, function_level_only=True)
561
557
 
562
558
  # Phase 2: Process blocks
563
559
  all_blocks = _process_blocks(scanned_files, function_level_only)