Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit da716a7

Browse files
cursoragentNicolasIRAGNE
authored andcommitted
feat: introduce Source inheritance hierarchy with pure Python polymorphism
This refactor introduces a clean inheritance architecture using proper Python polymorphism: Architecture: - Add Source base class in dedicated source.py file (common metadata/extra fields) - Refactor FileSystemNode to inherit from Source with full backward compatibility - Create specialized classes: FileSystemFile, FileSystemDirectory, FileSystemSymlink, GitRepository - render_tree() method belongs to FileSystemNode level (tree-specific, not all sources need it) Pure Python Polymorphism: - Each subclass implements its own get_sort_priority() and get_content() methods - NO type property or enum needed - use isinstance() directly - FileSystemFile.get_sort_priority() returns 0 (files first) - FileSystemDirectory.get_content() raises ValueError (directories can't have content) - FileSystemSymlink.get_content() returns target path (what symlink points to) - Clean, extensible design following Python best practices Removed Legacy Type System: - Completely removed FileSystemNodeType enum - No more type property - use isinstance() everywhere - Constructors now use specific classes: FileSystemFile(), FileSystemDirectory(), etc. - Pure polymorphism without any type checking properties Code Changes: - src/gitingest/schemas/source.py: New base Source class - src/gitingest/schemas/filesystem.py: Refactored with polymorphic methods, Path import in TYPE_CHECKING - src/gitingest/ingestion.py: Use specific constructors, populate symlink targets - src/gitingest/output_formatter.py: Use isinstance() instead of enum comparisons - Remove all FileSystemNodeType imports and usage - All pre-commit hooks pass (ruff-check, ruff-format, etc.) Benefits: - True Python polymorphism where each class knows its own behavior - No explicit type checking needed - Python dispatches automatically - More extensible - adding new source types just requires implementing methods - Cleaner code without enum/string type comparisons - Full backward compatibility maintained
1 parent 38e52cd commit da716a7

File tree

6 files changed

+163
-112
lines changed

6 files changed

+163
-112
lines changed

‎.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "debugpy",
66
"request": "launch",
77
"module": "server",
8-
"args": [],
8+
"args": ["--reload"],
99
"cwd": "${workspaceFolder}/src"
1010
}
1111
]

‎src/gitingest/ingestion.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
from gitingest.config import MAX_DIRECTORY_DEPTH, MAX_FILES, MAX_TOTAL_SIZE_BYTES
99
from gitingest.output_formatter import format_node
10-
from gitingest.schemas import FileSystemNode, FileSystemNodeType, FileSystemStats
10+
from gitingest.schemas import FileSystemDirectory, FileSystemFile, FileSystemNode, FileSystemStats, FileSystemSymlink
11+
from gitingest.utils.compat_func import readlink
1112
from gitingest.utils.ingestion_utils import _should_exclude, _should_include
1213
from gitingest.utils.logging_config import get_logger
1314

@@ -70,9 +71,8 @@ def ingest_query(query: IngestionQuery) -> tuple[str, str, str]:
7071

7172
relative_path = path.relative_to(query.local_path)
7273

73-
file_node = FileSystemNode(
74+
file_node = FileSystemFile(
7475
name=path.name,
75-
type=FileSystemNodeType.FILE,
7676
size=path.stat().st_size,
7777
file_count=1,
7878
path_str=str(relative_path),
@@ -95,9 +95,8 @@ def ingest_query(query: IngestionQuery) -> tuple[str, str, str]:
9595

9696
logger.info("Processing directory", extra={"directory_path": str(path)})
9797

98-
root_node = FileSystemNode(
98+
root_node = FileSystemDirectory(
9999
name=path.name,
100-
type=FileSystemNodeType.DIRECTORY,
101100
path_str=str(path.relative_to(query.local_path)),
102101
path=path,
103102
)
@@ -161,9 +160,8 @@ def _process_node(node: FileSystemNode, query: IngestionQuery, stats: FileSystem
161160
continue
162161
_process_file(path=sub_path, parent_node=node, stats=stats, local_path=query.local_path)
163162
elif sub_path.is_dir():
164-
child_directory_node = FileSystemNode(
163+
child_directory_node = FileSystemDirectory(
165164
name=sub_path.name,
166-
type=FileSystemNodeType.DIRECTORY,
167165
path_str=str(sub_path.relative_to(query.local_path)),
168166
path=sub_path,
169167
depth=node.depth + 1,
@@ -201,11 +199,11 @@ def _process_symlink(path: Path, parent_node: FileSystemNode, stats: FileSystemS
201199
The base path of the repository or directory being processed.
202200
203201
"""
204-
child = FileSystemNode(
202+
child = FileSystemSymlink(
205203
name=path.name,
206-
type=FileSystemNodeType.SYMLINK,
207204
path_str=str(path.relative_to(local_path)),
208205
path=path,
206+
target=str(readlink(path)),
209207
depth=parent_node.depth + 1,
210208
)
211209
stats.total_files += 1
@@ -258,9 +256,8 @@ def _process_file(path: Path, parent_node: FileSystemNode, stats: FileSystemStat
258256
stats.total_files += 1
259257
stats.total_size += file_size
260258

261-
child = FileSystemNode(
259+
child = FileSystemFile(
262260
name=path.name,
263-
type=FileSystemNodeType.FILE,
264261
size=file_size,
265262
file_count=1,
266263
path_str=str(path.relative_to(local_path)),

‎src/gitingest/output_formatter.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
import requests.exceptions
99
import tiktoken
1010

11-
from gitingest.schemas import FileSystemNode, FileSystemNodeType
12-
from gitingest.utils.compat_func import readlink
11+
from gitingest.schemas import FileSystemDirectory, FileSystemFile, FileSystemNode, FileSystemSymlink
1312
from gitingest.utils.logging_config import get_logger
1413

1514
if TYPE_CHECKING:
@@ -42,12 +41,12 @@ def format_node(node: FileSystemNode, query: IngestionQuery) -> tuple[str, str,
4241
A tuple containing the summary, directory structure, and file contents.
4342
4443
"""
45-
is_single_file = node.type==FileSystemNodeType.FILE
44+
is_single_file = isinstance(node, FileSystemFile)
4645
summary = _create_summary_prefix(query, single_file=is_single_file)
4746

48-
if node.type==FileSystemNodeType.DIRECTORY:
47+
if isinstance(node, FileSystemDirectory):
4948
summary += f"Files analyzed: {node.file_count}\n"
50-
elif node.type==FileSystemNodeType.FILE:
49+
elif isinstance(node, FileSystemFile):
5150
summary += f"File: {node.name}\n"
5251
summary += f"Lines: {len(node.content.splitlines()):,}\n"
5352

@@ -119,7 +118,7 @@ def _gather_file_contents(node: FileSystemNode) -> str:
119118
The concatenated content of all files under the given node.
120119
121120
"""
122-
if node.type!=FileSystemNodeType.DIRECTORY:
121+
if notisinstance(node, FileSystemDirectory):
123122
return node.content_string
124123

125124
# Recursively gather contents of all files under the current directory
@@ -164,14 +163,14 @@ def _create_tree_structure(
164163

165164
# Indicate directories with a trailing slash
166165
display_name = node.name
167-
if node.type==FileSystemNodeType.DIRECTORY:
166+
if isinstance(node, FileSystemDirectory):
168167
display_name += "/"
169-
elif node.type==FileSystemNodeType.SYMLINK:
170-
display_name += " -> " + readlink(node.path).name
168+
elif isinstance(node, FileSystemSymlink):
169+
display_name += " -> " + node.target
171170

172171
tree_str += f"{prefix}{current_prefix}{display_name}\n"
173172

174-
if node.type==FileSystemNodeType.DIRECTORY and node.children:
173+
if isinstance(node, FileSystemDirectory) and node.children:
175174
prefix += " " if is_last else "│ "
176175
for i, child in enumerate(node.children):
177176
tree_str += _create_tree_structure(query, node=child, prefix=prefix, is_last=i == len(node.children) - 1)

‎src/gitingest/schemas/__init__.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
"""Module containing the schemas for the Gitingest package."""
22

33
from gitingest.schemas.cloning import CloneConfig
4-
from gitingest.schemas.filesystem import FileSystemNode, FileSystemNodeType, FileSystemStats
4+
from gitingest.schemas.filesystem import (
5+
FileSystemDirectory,
6+
FileSystemFile,
7+
FileSystemNode,
8+
FileSystemStats,
9+
FileSystemSymlink,
10+
GitRepository,
11+
)
512
from gitingest.schemas.ingestion import IngestionQuery
13+
from gitingest.schemas.source import Source
614

7-
__all__ = ["CloneConfig", "FileSystemNode", "FileSystemNodeType", "FileSystemStats", "IngestionQuery"]
15+
__all__ = [
16+
"CloneConfig",
17+
"FileSystemDirectory",
18+
"FileSystemFile",
19+
"FileSystemNode",
20+
"FileSystemStats",
21+
"FileSystemSymlink",
22+
"GitRepository",
23+
"IngestionQuery",
24+
"Source",
25+
]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /