Skip to content

Commit da0629b

Browse files
committed
refactor: drop legacy aliases and flat config files, add lock file ignores
1 parent 1cea472 commit da0629b

9 files changed

Lines changed: 68 additions & 100 deletions

File tree

src/treemapper/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,3 @@ def to_markdown(tree: dict[str, Any]) -> str:
9696
buf = io.StringIO()
9797
write_tree_markdown(buf, tree)
9898
return buf.getvalue()
99-
100-
101-
to_md = to_markdown
102-
to_txt = to_text

src/treemapper/cli.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ def _warn_diff_only_flags(args: argparse.Namespace) -> None:
109109
if args.budget is not None:
110110
used.append("--budget")
111111
if abs(args.alpha - 0.60) > 1e-9:
112-
used.append("--alpha/--context-precision")
112+
used.append("--alpha")
113113
if abs(args.tau - 0.08) > 1e-9:
114-
used.append("--tau/--min-relevance")
114+
used.append("--tau")
115115
if args.full:
116116
used.append("--full")
117117
if used:
@@ -147,6 +147,8 @@ class ParsedArgs:
147147
.git/, .svn/, .hg/ Version control directories
148148
__pycache__/, *.py[cod], *.so, venv/, .venv/, .tox/, .nox/ Python
149149
node_modules/, .npm/ JavaScript/Node
150+
package-lock.json, yarn.lock, pnpm-lock.yaml JS lock files
151+
Pipfile.lock, poetry.lock, Cargo.lock, Gemfile.lock Other lock files
150152
target/, .gradle/ Java/Maven/Gradle
151153
bin/, obj/ .NET
152154
vendor/ Go/PHP
@@ -158,12 +160,10 @@ class ParsedArgs:
158160
159161
Ignore files (hierarchical, like git):
160162
.gitignore Standard git ignore patterns
161-
.treemapper/ignore TreeMapper-specific patterns (preferred)
162-
.treemapperignore TreeMapper-specific patterns (legacy)
163+
.treemapper/ignore TreeMapper-specific patterns
163164
164165
Whitelist files (auto-discovered):
165-
.treemapper/whitelist Include-only filter (preferred)
166-
.treemapperwhitelist Include-only filter (legacy)
166+
.treemapper/whitelist Include-only filter
167167
168168
Examples:
169169
treemapper . Map current directory to YAML
@@ -212,7 +212,7 @@ def parse_args() -> ParsedArgs:
212212
parser.add_argument(
213213
"-f",
214214
"--format",
215-
choices=["yaml", "yml", "json", "txt", "md"],
215+
choices=["yaml", "json", "txt", "md"],
216216
default="yaml",
217217
help="Output format (default: yaml)",
218218
)
@@ -265,15 +265,13 @@ def parse_args() -> ParsedArgs:
265265
)
266266
diff_group.add_argument(
267267
"--alpha",
268-
"--context-precision",
269268
type=float,
270269
default=0.60,
271270
metavar="F",
272271
help="How tightly context clusters around changes, 0-1 (default: 0.60, higher = more focused)",
273272
)
274273
diff_group.add_argument(
275274
"--tau",
276-
"--min-relevance",
277275
type=float,
278276
default=0.08,
279277
metavar="F",
@@ -295,7 +293,7 @@ def parse_args() -> ParsedArgs:
295293
_warn_diff_only_flags(args)
296294

297295
root_dir = _resolve_root_dir(args.directory)
298-
output_format = "yaml" if args.format == "yml" else args.format
296+
output_format = args.format
299297
output_file, force_stdout = _resolve_output_file(args.output_file, args.save, output_format)
300298
ignore_file = _resolve_ignore_file(args.ignore_file)
301299
whitelist_file = _resolve_whitelist_file(args.whitelist_file)

src/treemapper/ignore.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,15 @@ def _collect_parent_ignore_patterns(root: Path, ignore_filenames: list[str]) ->
225225
# JavaScript/Node
226226
"**/node_modules/",
227227
"**/.npm/",
228+
# Lock files (large, auto-generated, low signal for LLM analysis)
229+
"**/package-lock.json",
230+
"**/yarn.lock",
231+
"**/pnpm-lock.yaml",
232+
"**/Pipfile.lock",
233+
"**/poetry.lock",
234+
"**/Cargo.lock",
235+
"**/composer.lock",
236+
"**/Gemfile.lock",
228237
# Java/JVM
229238
"**/target/",
230239
"**/.gradle/",
@@ -247,7 +256,6 @@ def _collect_parent_ignore_patterns(root: Path, ignore_filenames: list[str]) ->
247256
# TreeMapper config and output files
248257
"**/.treemapper/",
249258
"**/tree.yaml",
250-
"**/tree.yml",
251259
"**/tree.json",
252260
"**/tree.md",
253261
"**/tree.txt",
@@ -264,8 +272,8 @@ def get_ignore_specs(
264272

265273
if not no_default_ignores:
266274
patterns.extend(DEFAULT_IGNORE_PATTERNS)
267-
patterns.extend(_collect_parent_ignore_patterns(root_dir, [".gitignore", ".treemapperignore"]))
268-
patterns.extend(_aggregate_all_ignore_patterns(root_dir, [".gitignore", ".treemapperignore"]))
275+
patterns.extend(_collect_parent_ignore_patterns(root_dir, [".gitignore"]))
276+
patterns.extend(_aggregate_all_ignore_patterns(root_dir, [".gitignore"]))
269277

270278
if custom_ignore_file:
271279
patterns.extend(read_ignore_file(custom_ignore_file))
@@ -287,19 +295,12 @@ def should_ignore(relative_path_str: str, combined_spec: pathspec.PathSpec) -> b
287295
return is_ignored
288296

289297

290-
DEFAULT_WHITELIST_FILENAME = ".treemapperwhitelist"
291-
292-
293298
def get_whitelist_spec(whitelist_file: Path | None, root_dir: Path | None = None) -> pathspec.PathSpec | None:
294299
effective_file = whitelist_file
295300
if not effective_file and root_dir:
296301
config_whitelist = root_dir / TREEMAPPER_CONFIG_DIR / TREEMAPPER_DIR_WHITELIST
297302
if config_whitelist.is_file():
298303
effective_file = config_whitelist
299-
else:
300-
default = root_dir / DEFAULT_WHITELIST_FILENAME
301-
if default.is_file():
302-
effective_file = default
303304
if not effective_file:
304305
return None
305306
patterns = read_ignore_file(effective_file)

src/treemapper/writer.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,9 @@
4747

4848
_FORMAT_ALIASES = {
4949
"yaml": "yaml",
50-
"yml": "yaml",
5150
"json": "json",
5251
"txt": "txt",
53-
"text": "txt",
5452
"md": "md",
55-
"markdown": "md",
5653
}
5754

5855
PLACEHOLDER_PATTERNS = [

tests/conftest.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,7 @@ def _verify_no_garbage_in_context(context: dict) -> None:
7070
PROJECT_ROOT = Path(__file__).parent.parent
7171
SRC_DIR = PROJECT_ROOT / "src"
7272

73-
# Constants for ignore file names
7473
GITIGNORE = ".gitignore"
75-
TREEMAPPERIGNORE = ".treemapperignore"
7674

7775
# WSL detection with proper file handle cleanup (shared across test files)
7876
_PROC_VERSION = Path("/proc/version")
@@ -94,7 +92,9 @@ def temp_project(tmp_path):
9492
(temp_dir / ".git").mkdir()
9593
(temp_dir / ".git" / "config").write_text("git config file", encoding="utf-8")
9694
(temp_dir / GITIGNORE).write_text("*.pyc\n__pycache__/\n", encoding="utf-8")
97-
(temp_dir / TREEMAPPERIGNORE).write_text("output/\n.git/\n", encoding="utf-8")
95+
config_dir = temp_dir / ".treemapper"
96+
config_dir.mkdir()
97+
(config_dir / "ignore").write_text("output/\n.git/\n", encoding="utf-8")
9898
yield temp_dir
9999

100100

@@ -241,8 +241,10 @@ def add_gitignore(self, patterns: list[str], subdir: str = "") -> Path:
241241
path.write_text("\n".join(patterns) + "\n", encoding="utf-8")
242242
return path
243243

244-
def add_treemapperignore(self, patterns: list[str]) -> Path:
245-
path = self.root / TREEMAPPERIGNORE
244+
def add_treemapper_ignore(self, patterns: list[str]) -> Path:
245+
config_dir = self.root / ".treemapper"
246+
config_dir.mkdir(exist_ok=True)
247+
path = config_dir / "ignore"
246248
path.write_text("\n".join(patterns) + "\n", encoding="utf-8")
247249
return path
248250

tests/test_basic.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def test_basic_mapping(temp_project, run_mapper):
2323
assert "main.py" in all_files
2424
assert "test.py" in all_files
2525
assert "docs" in all_files
26-
assert ".git" not in all_files, ".git should be ignored by default .treemapperignore"
26+
assert ".git" not in all_files, ".git should be ignored by default .treemapper/ignore"
2727
assert "output" not in all_files
2828
assert "directory_tree.yaml" not in all_files
2929

tests/test_coverage_gaps.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ def test_map_directory_with_no_default_ignores_param(tmp_path):
4646
(project / "__pycache__" / "module.pyc").write_text("bytecode")
4747
(project / "regular.txt").write_text("content")
4848
(project / ".gitignore").write_text("*.pyc\n")
49-
(project / ".treemapperignore").write_text(".git/\n__pycache__/\n")
49+
config_dir = project / ".treemapper"
50+
config_dir.mkdir()
51+
(config_dir / "ignore").write_text(".git/\n__pycache__/\n")
5052

5153
tree_with_defaults = map_directory(project)
5254
names_with_defaults = get_all_files_in_tree(tree_with_defaults)
@@ -73,7 +75,9 @@ def test_no_default_ignores_still_respects_custom_ignore(tmp_path):
7375
(project / "keep.txt").write_text("keep this")
7476
(project / "ignore_me.log").write_text("should be ignored")
7577
(project / ".gitignore").write_text("*.pyc\n")
76-
(project / ".treemapperignore").write_text(".git/\n__pycache__/\n")
78+
config_dir2 = project / ".treemapper"
79+
config_dir2.mkdir()
80+
(config_dir2 / "ignore").write_text(".git/\n__pycache__/\n")
7781

7882
custom_ignore = tmp_path / "custom.ignore"
7983
custom_ignore.write_text("*.log\n")

tests/test_ignore.py

Lines changed: 33 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ def test_symlinks_and_special_files(temp_project, run_mapper):
7171
logging.warning(f"Could not create symlink: {e}, skipping symlink part.")
7272
can_symlink = False
7373

74-
(temp_project / ".treemapperignore").write_text(".*\n!.gitignore\n")
74+
config_dir = temp_project / ".treemapper"
75+
config_dir.mkdir(exist_ok=True)
76+
(config_dir / "ignore").write_text(".*\n!.gitignore\n")
7577
assert run_mapper([".", "-o", "directory_tree.yaml"])
7678
result = load_yaml(temp_project / "directory_tree.yaml")
7779
all_files = get_all_files_in_tree(result)
@@ -85,7 +87,9 @@ def test_symlinks_and_special_files(temp_project, run_mapper):
8587

8688
def test_empty_and_invalid_ignores(temp_project, run_mapper):
8789
(temp_project / ".gitignore").write_text("")
88-
(temp_project / ".treemapperignore").write_text("\n\n# Just comments\n\n")
90+
config_dir = temp_project / ".treemapper"
91+
config_dir.mkdir(exist_ok=True)
92+
(config_dir / "ignore").write_text("\n\n# Just comments\n\n")
8993
(temp_project / "empty.ignore").write_text("")
9094
(temp_project / "invalid.ignore").write_text("[\ninvalid\npattern\n")
9195
assert run_mapper([".", "-o", "out_empty.yaml"])
@@ -204,7 +208,7 @@ def test_no_default_ignores_flag(temp_project, run_mapper):
204208
assert "treemapper_ignored" in all_files, "'treemapper_ignored/' should NOT be ignored with --no-default-ignores"
205209
assert "file.txt" in all_files
206210
assert ".gitignore" in all_files
207-
assert ".treemapperignore" in all_files
211+
assert ".treemapper" in all_files
208212
assert treemapper_ignore.name in all_files
209213
assert custom_ignore.name in all_files
210214
assert (
@@ -217,7 +221,8 @@ def test_no_default_ignores_flag(temp_project, run_mapper):
217221
reason="os.chmod limited on Windows/WSL",
218222
)
219223
def test_unreadable_ignore_file(temp_project, run_mapper, set_perms, caplog):
220-
ignore_file = temp_project / ".treemapperignore"
224+
config_dir = temp_project / ".treemapper"
225+
ignore_file = config_dir / "ignore"
221226
ignore_file.write_text(".git/\n")
222227
set_perms(ignore_file, 0o000)
223228

@@ -232,7 +237,8 @@ def test_unreadable_ignore_file(temp_project, run_mapper, set_perms, caplog):
232237

233238

234239
def test_bad_encoding_ignore_file(temp_project, run_mapper, caplog):
235-
ignore_file = temp_project / ".treemapperignore"
240+
config_dir = temp_project / ".treemapper"
241+
ignore_file = config_dir / "ignore"
236242
try:
237243
# Cyrillic text intentional for CP1251 encoding test
238244
ignore_file.write_text(".git/\nпапка_игнор/\n", encoding="cp1251") # noqa: RUF001
@@ -280,7 +286,9 @@ def test_ignore_precedence_subdir_over_root(temp_project, run_mapper):
280286

281287
def test_ignore_precedence_treemapper_over_git(temp_project, run_mapper):
282288
(temp_project / ".gitignore").write_text("*.pyc\n")
283-
(temp_project / ".treemapperignore").write_text("*.log\n.git/\n")
289+
config_dir = temp_project / ".treemapper"
290+
config_dir.mkdir(exist_ok=True)
291+
(config_dir / "ignore").write_text("*.log\n.git/\n")
284292
(temp_project / "file.pyc").touch()
285293
(temp_project / "file.log").touch()
286294
(temp_project / "file.txt").touch()
@@ -296,7 +304,9 @@ def test_ignore_precedence_treemapper_over_git(temp_project, run_mapper):
296304

297305
def test_ignore_precedence_custom_over_defaults(temp_project, run_mapper):
298306
(temp_project / ".gitignore").write_text("*.pyc\n")
299-
(temp_project / ".treemapperignore").write_text("*.log\n.git/\n")
307+
config_dir = temp_project / ".treemapper"
308+
config_dir.mkdir(exist_ok=True)
309+
(config_dir / "ignore").write_text("*.log\n.git/\n")
300310
custom_ignore = temp_project / "custom.ignore"
301311
custom_ignore.write_text("*.tmp\n")
302312

@@ -422,12 +432,16 @@ def test_combined_patterns(temp_project, run_mapper):
422432
assert find_node_by_path(result, ["subdir", "regular.txt"]) is not None
423433

424434

425-
def test_hierarchical_treemapperignore(temp_project, run_mapper):
435+
def test_hierarchical_dir_ignore(temp_project, run_mapper):
426436
from .utils import find_node_by_path
427437

428-
(temp_project / ".treemapperignore").write_text("*.tmp\n")
438+
config_dir = temp_project / ".treemapper"
439+
config_dir.mkdir(exist_ok=True)
440+
(config_dir / "ignore").write_text("*.tmp\n")
429441
(temp_project / "subdir").mkdir()
430-
(temp_project / "subdir" / ".treemapperignore").write_text("*.bak\n!important.bak\n")
442+
sub_config = temp_project / "subdir" / ".treemapper"
443+
sub_config.mkdir()
444+
(sub_config / "ignore").write_text("*.bak\n!important.bak\n")
431445
(temp_project / "root.tmp").touch()
432446
(temp_project / "root.bak").touch()
433447
(temp_project / "subdir" / "nested.tmp").touch()
@@ -486,7 +500,9 @@ def test_parent_ignore_integration(tmp_path, run_mapper):
486500
subdir = parent / "packages" / "app"
487501
subdir.mkdir(parents=True)
488502

489-
(parent / ".treemapperignore").write_text("packages/app/ignored_dir/\npackages/app/data/\n")
503+
parent_config = parent / ".treemapper"
504+
parent_config.mkdir()
505+
(parent_config / "ignore").write_text("packages/app/ignored_dir/\npackages/app/data/\n")
490506
(subdir / "ignored_dir").mkdir()
491507
(subdir / "ignored_dir" / "secret.txt").write_text("secret")
492508
(subdir / "data").mkdir()
@@ -511,12 +527,16 @@ def test_parent_ignore_stops_at_git_root(tmp_path, run_mapper):
511527

512528
grandparent = tmp_path / "grandparent"
513529
grandparent.mkdir()
514-
(grandparent / ".treemapperignore").write_text("packages/app/beyond_git_root/\n")
530+
grandparent_config = grandparent / ".treemapper"
531+
grandparent_config.mkdir()
532+
(grandparent_config / "ignore").write_text("packages/app/beyond_git_root/\n")
515533

516534
parent = grandparent / "parent"
517535
parent.mkdir()
518536
(parent / ".git").mkdir()
519-
(parent / ".treemapperignore").write_text("packages/app/from_parent/\n")
537+
parent_config = parent / ".treemapper"
538+
parent_config.mkdir()
539+
(parent_config / "ignore").write_text("packages/app/from_parent/\n")
520540

521541
child = parent / "packages" / "app"
522542
child.mkdir(parents=True)
@@ -557,26 +577,6 @@ def test_treemapper_dir_ignore(temp_project, run_mapper):
557577
assert find_node_by_path(result, ["keep.txt"]) is not None
558578

559579

560-
def test_treemapper_dir_ignore_combined_with_legacy(temp_project, run_mapper):
561-
from .utils import find_node_by_path
562-
563-
(temp_project / ".treemapperignore").write_text("*.tmp\n")
564-
config_dir = temp_project / ".treemapper"
565-
config_dir.mkdir(exist_ok=True)
566-
(config_dir / "ignore").write_text("*.bak\n")
567-
(temp_project / "file.tmp").touch()
568-
(temp_project / "file.bak").touch()
569-
(temp_project / "file.txt").touch()
570-
571-
output_path = temp_project / "combined_dir_output.yaml"
572-
assert run_mapper([".", "-o", str(output_path)])
573-
result = load_yaml(output_path)
574-
575-
assert find_node_by_path(result, ["file.tmp"]) is None
576-
assert find_node_by_path(result, ["file.bak"]) is None
577-
assert find_node_by_path(result, ["file.txt"]) is not None
578-
579-
580580
def test_treemapper_dir_ignore_hierarchical(temp_project, run_mapper):
581581
from .utils import find_node_by_path
582582

@@ -654,18 +654,3 @@ def test_treemapper_dir_hidden_from_output(temp_project, run_mapper):
654654
assert ".treemapper" not in all_files
655655
assert "ignore" not in all_files
656656
assert "whitelist" not in all_files
657-
658-
659-
def test_treemapper_dir_whitelist_over_legacy(temp_project, run_mapper):
660-
(temp_project / ".treemapperwhitelist").write_text("docs/**\n")
661-
config_dir = temp_project / ".treemapper"
662-
config_dir.mkdir(exist_ok=True)
663-
(config_dir / "whitelist").write_text("src/**/*.py\n")
664-
665-
output_path = temp_project / "wl_precedence_output.yaml"
666-
assert run_mapper([".", "-o", str(output_path)])
667-
result = load_yaml(output_path)
668-
all_files = get_all_files_in_tree(result)
669-
670-
assert "main.py" in all_files
671-
assert "readme.md" not in all_files

0 commit comments

Comments
 (0)