codeecho 1.2.2__tar.gz → 1.2.3__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.
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.3 - 2026-10-01
4
+
5
+ ### Changed
6
+
7
+ - `--min-tokens` (default `10`, unchanged) now measures a fragment's **line count** instead of its
8
+ raw token count: a fragment must span at least this many lines to be considered. Annotations,
9
+ braces, and semicolons could previously inflate a trivial one-line getter/override's token count
10
+ enough to slip past `--min-tokens` and surface as a noisy Type-1 clone group; line count is a
11
+ more reliable measure of fragment size.
12
+
3
13
  ## 1.2.2 - 2026-09-23
4
14
 
5
15
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeecho
3
- Version: 1.2.2
3
+ Version: 1.2.3
4
4
  Summary: A developer tool that scans your codebase to detect and highlight ECHOES of duplicated or near-duplicated code so you can refactor toward cleaner, more maintainable designs.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -37,7 +37,7 @@ Description-Content-Type: text/markdown
37
37
 
38
38
  # codeecho
39
39
 
40
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/rcw3bb/codeecho/blob/main/LICENSE) [![Version](https://img.shields.io/badge/Version-1.2.2-green.svg)](https://github.com/rcw3bb/codeecho/blob/main/CHANGELOG.md) [![Python](https://img.shields.io/badge/Python-3.14%2B-blue)](https://www.python.org/) [![PyPI](https://img.shields.io/badge/PyPI-codeecho-orange)](https://pypi.org/project/codeecho/)
40
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/rcw3bb/codeecho/blob/main/LICENSE) [![Version](https://img.shields.io/badge/Version-1.2.3-green.svg)](https://github.com/rcw3bb/codeecho/blob/main/CHANGELOG.md) [![Python](https://img.shields.io/badge/Python-3.14%2B-blue)](https://www.python.org/) [![PyPI](https://img.shields.io/badge/PyPI-codeecho-orange)](https://pypi.org/project/codeecho/)
41
41
 
42
42
  > A developer tool that scans your codebase to detect and highlight **echoes** of duplicated or near-duplicated code, so you can refactor toward cleaner, more maintainable designs.
43
43
 
@@ -92,7 +92,7 @@ python -m codeecho <path> [options]
92
92
  | `--output-dir <dir>` | `<cwd>/reports` | Directory where output file(s) will be written. |
93
93
  | `--db-dir <dir>` | `~/.codeecho` | Directory for the SQLite scratch database (`codeecho.db`). Session records are removed after the report is written. |
94
94
  | `--format <fmt>` | `both` | Output format: `json`, `html`, or `both`. |
95
- | `--min-tokens <n>` | `10` | Minimum token count for a code fragment to be included. |
95
+ | `--min-tokens <n>` | `10` | Minimum line count for a code fragment to be included. |
96
96
  | `--exclude <pattern>` | _(none)_ | Glob pattern(s) to exclude from scanning (repeatable). |
97
97
  | `--target-list` | `false` | Treat `PATH` as a single existing file listing target paths (files and/or directories), one per line, instead of individual `PATH` arguments. Blank lines and lines starting with `#` are skipped. |
98
98
  | `--basis <file>` | _(none)_ | File listing basis target paths, one per line — same format as `--target-list`. Absolute file/directory entries are merged into the scan automatically and matched exactly; relative entries (e.g. a bare filename like `Foo.gs`) are matched by filename/suffix against any file discovered in the scan. The report is filtered to only clone groups touching at least one basis file, and groups duplicated purely among basis files are flagged (`basis_internal` in JSON, a "Basis-to-Basis" badge in HTML). |
@@ -1,6 +1,6 @@
1
1
  # codeecho
2
2
 
3
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/rcw3bb/codeecho/blob/main/LICENSE) [![Version](https://img.shields.io/badge/Version-1.2.2-green.svg)](https://github.com/rcw3bb/codeecho/blob/main/CHANGELOG.md) [![Python](https://img.shields.io/badge/Python-3.14%2B-blue)](https://www.python.org/) [![PyPI](https://img.shields.io/badge/PyPI-codeecho-orange)](https://pypi.org/project/codeecho/)
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/rcw3bb/codeecho/blob/main/LICENSE) [![Version](https://img.shields.io/badge/Version-1.2.3-green.svg)](https://github.com/rcw3bb/codeecho/blob/main/CHANGELOG.md) [![Python](https://img.shields.io/badge/Python-3.14%2B-blue)](https://www.python.org/) [![PyPI](https://img.shields.io/badge/PyPI-codeecho-orange)](https://pypi.org/project/codeecho/)
4
4
 
5
5
  > A developer tool that scans your codebase to detect and highlight **echoes** of duplicated or near-duplicated code, so you can refactor toward cleaner, more maintainable designs.
6
6
 
@@ -55,7 +55,7 @@ python -m codeecho <path> [options]
55
55
  | `--output-dir <dir>` | `<cwd>/reports` | Directory where output file(s) will be written. |
56
56
  | `--db-dir <dir>` | `~/.codeecho` | Directory for the SQLite scratch database (`codeecho.db`). Session records are removed after the report is written. |
57
57
  | `--format <fmt>` | `both` | Output format: `json`, `html`, or `both`. |
58
- | `--min-tokens <n>` | `10` | Minimum token count for a code fragment to be included. |
58
+ | `--min-tokens <n>` | `10` | Minimum line count for a code fragment to be included. |
59
59
  | `--exclude <pattern>` | _(none)_ | Glob pattern(s) to exclude from scanning (repeatable). |
60
60
  | `--target-list` | `false` | Treat `PATH` as a single existing file listing target paths (files and/or directories), one per line, instead of individual `PATH` arguments. Blank lines and lines starting with `#` are skipped. |
61
61
  | `--basis <file>` | _(none)_ | File listing basis target paths, one per line — same format as `--target-list`. Absolute file/directory entries are merged into the scan automatically and matched exactly; relative entries (e.g. a bare filename like `Foo.gs`) are matched by filename/suffix against any file discovered in the scan. The report is filtered to only clone groups touching at least one basis file, and groups duplicated purely among basis files are flagged (`basis_internal` in JSON, a "Basis-to-Basis" badge in HTML). |
@@ -10,7 +10,7 @@ maintainable designs.
10
10
  from env_dir_bootstrap import EnvDirBootstrap
11
11
  from logenrich import setup_logger
12
12
 
13
- __version__ = "1.2.2"
13
+ __version__ = "1.2.3"
14
14
 
15
15
  _bootstrapper = EnvDirBootstrap(
16
16
  env_var="CODEECHO_CONFIG_DIR",
@@ -237,7 +237,7 @@ def _discover_files(
237
237
  default=10,
238
238
  show_default=True,
239
239
  type=click.IntRange(1),
240
- help="Minimum token count for a fragment to be considered.",
240
+ help="Minimum line count for a fragment to be considered.",
241
241
  )
242
242
  @click.option(
243
243
  "--exclude",
@@ -91,7 +91,7 @@ def extract_fragments( # pylint: disable=too-many-arguments,too-many-positional
91
91
  :param file_path: Absolute path of the source file.
92
92
  :param language_name: Language name (e.g. ``"Python"``).
93
93
  :param session_id: UUID of the current scan session.
94
- :param min_tokens: Fragments with fewer raw tokens are discarded.
94
+ :param min_tokens: Fragments spanning fewer lines than this are discarded.
95
95
  :returns: List of fully-populated :class:`Fragment` objects.
96
96
  :since: 1.0.0
97
97
  """
@@ -118,14 +118,14 @@ def extract_fragments( # pylint: disable=too-many-arguments,too-many-positional
118
118
  ]
119
119
  del cursor, captures # free tree-sitter objects before processing
120
120
  for start_b, end_b in node_ranges:
121
+ start_ln = bisect_left(newline_offsets, start_b) + 1
122
+ end_ln = bisect_left(newline_offsets, end_b) + 1
123
+ if end_ln - start_ln + 1 < min_tokens:
124
+ continue
121
125
  src_text = source_bytes[start_b:end_b].decode("utf-8", errors="replace")
122
126
  raw_tokens, norm_tokens = normalizer.tokenise_and_normalise(
123
127
  src_text, language_name
124
128
  )
125
- if len(raw_tokens) < min_tokens:
126
- continue
127
- start_ln = bisect_left(newline_offsets, start_b) + 1
128
- end_ln = bisect_left(newline_offsets, end_b) + 1
129
129
  fragments.append(
130
130
  Fragment(
131
131
  fragment_id=str(uuid.uuid4()),
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codeecho"
3
- version = "1.2.2"
3
+ version = "1.2.3"
4
4
  description = "A developer tool that scans your codebase to detect and highlight ECHOES of duplicated or near-duplicated code so you can refactor toward cleaner, more maintainable designs."
5
5
  authors = [
6
6
  {name = "Ron Webb"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes