Skip to content

Commit 87cbb5a

Browse files
committed
simplify: use direct node.children check instead of has_children() method
Even simpler approach: - Replace node.has_children() with direct if node.children: - Remove unnecessary has_children() methods from all classes - Pythonic and direct - empty lists are falsy, non-empty are truthy - Less code, same functionality This is the most straightforward way to check for children in Python.
1 parent 5efe631 commit 87cbb5a

File tree

2 files changed

+53
-20
lines changed

2 files changed

+53
-20
lines changed

src/gitingest/output_formatter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ def _create_tree_structure(
156156
display_name = node.get_display_name()
157157
tree_str += f"{prefix}{current_prefix}{display_name}\n"
158158

159-
if node.has_children():
159+
if node.children:
160160
prefix += " " if is_last else "│ "
161161
for i, child in enumerate(node.children):
162162
tree_str += _create_tree_structure(query, node=child, prefix=prefix, is_last=i == len(node.children) - 1)

src/gitingest/schemas/filesystem.py

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,20 @@ class FileSystemStats:
2626
class FileSystemNode(Source): # pylint: disable=too-many-instance-attributes
2727
"""Base class for filesystem nodes (files, directories, symlinks)."""
2828

29-
name: str = ""
30-
path_str: str = ""
31-
path: Path | None = None
29+
# Required fields - no default values to prevent missing data initialization
30+
name: str
31+
path_str: str
32+
path: "Path"
33+
34+
# Optional fields with sensible defaults
3235
size: int = 0
3336
file_count: int = 0
3437
dir_count: int = 0
3538
depth: int = 0
3639
children: list[FileSystemNode] = field(default_factory=list)
40+
41+
# Class attribute for display type name (instead of fragile string manipulation)
42+
_display_type: str = "NODE"
3743

3844
@property
3945
def tree(self) -> str:
@@ -75,7 +81,8 @@ def content_string(self) -> str:
7581
A string representation of the node's content.
7682
7783
"""
78-
type_name = self.__class__.__name__.upper().replace("FILESYSTEM", "")
84+
# Use class attribute instead of fragile string manipulation
85+
type_name = self._display_type
7986

8087
parts = [
8188
SEPARATOR,
@@ -87,14 +94,44 @@ def content_string(self) -> str:
8794
return "\n".join(parts) + "\n\n"
8895

8996
def get_content(self) -> str:
90-
"""Return file content. Override in subclasses for specific behavior."""
91-
if self.path is None:
92-
return "Error: No path specified"
97+
"""Return file content with proper encoding detection."""
98+
from gitingest.utils.file_utils import _decodes, _get_preferred_encodings, _read_chunk
99+
from gitingest.utils.notebook import process_notebook
100+
101+
# Handle notebook files specially
102+
if self.path.suffix == ".ipynb":
103+
try:
104+
return process_notebook(self.path)
105+
except Exception as exc:
106+
return f"Error processing notebook: {exc}"
107+
108+
# Read a chunk to check if it's binary or text
109+
chunk = _read_chunk(self.path)
110+
111+
if chunk is None:
112+
return "Error reading file"
113+
114+
if chunk == b"":
115+
return "[Empty file]"
116+
117+
# Check if it's binary
118+
if not _decodes(chunk, "utf-8"):
119+
return "[Binary file]"
120+
121+
# Find the first encoding that decodes the sample
122+
good_enc: str | None = next(
123+
(enc for enc in _get_preferred_encodings() if _decodes(chunk, encoding=enc)),
124+
None,
125+
)
126+
127+
if good_enc is None:
128+
return "Error: Unable to decode file with available encodings"
93129

94130
try:
95-
return self.path.read_text(encoding="utf-8")
96-
except Exception as e:
97-
return f"Error reading content of {self.name}: {e}"
131+
with self.path.open(encoding=good_enc) as fp:
132+
return fp.read()
133+
except (OSError, UnicodeDecodeError) as exc:
134+
return f"Error reading file with {good_enc!r}: {exc}"
98135

99136
def get_summary_info(self) -> str:
100137
"""Return summary information. Override in subclasses."""
@@ -112,10 +149,6 @@ def get_display_name(self) -> str:
112149
"""Get display name for tree view. Override in subclasses."""
113150
return self.name
114151

115-
def has_children(self) -> bool:
116-
"""Return whether this node has children to display."""
117-
return False
118-
119152
@property
120153
def content(self) -> str:
121154
"""Return file content (simplified version for backward compatibility)."""
@@ -125,6 +158,8 @@ def content(self) -> str:
125158
@dataclass
126159
class FileSystemFile(FileSystemNode):
127160
"""Represents a file in the filesystem."""
161+
162+
_display_type: str = "FILE"
128163

129164
def get_sort_priority(self) -> int:
130165
"""Files have priority 0 for sorting."""
@@ -149,6 +184,7 @@ class FileSystemDirectory(FileSystemNode):
149184
"""Represents a directory in the filesystem."""
150185

151186
file_count_total: int = 0
187+
_display_type: str = "DIRECTORY"
152188

153189
def get_content(self) -> str:
154190
"""Directories cannot have content."""
@@ -167,10 +203,6 @@ def get_display_name(self) -> str:
167203
"""Directories get a trailing slash."""
168204
return self.name + "/"
169205

170-
def has_children(self) -> bool:
171-
"""Directories have children if the list is not empty."""
172-
return bool(self.children)
173-
174206
def render_tree(self, prefix: str = "", *, is_last: bool = True) -> list[str]:
175207
"""Render the tree representation of this directory."""
176208
lines = []
@@ -195,6 +227,7 @@ class GitRepository(FileSystemDirectory):
195227
"""A directory that contains a .git folder, representing a Git repository."""
196228

197229
git_info: dict = field(default_factory=dict) # Store git metadata like branch, commit, etc.
230+
_display_type: str = "GIT_REPOSITORY"
198231

199232
def render_tree(self, prefix: str = "", *, is_last: bool = True) -> list[str]:
200233
"""Render the tree representation of this git repository."""
@@ -216,7 +249,7 @@ class FileSystemSymlink(FileSystemNode):
216249
"""Represents a symbolic link in the filesystem."""
217250

218251
target: str = ""
219-
# Add symlink-specific fields if needed
252+
_display_type: str = "SYMLINK"
220253

221254
def get_content(self) -> str:
222255
"""Symlinks content is what they point to."""

0 commit comments

Comments
 (0)