kopipasta 0.33.0__tar.gz → 0.35.0__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.
Potentially problematic release.
This version of kopipasta might be problematic. Click here for more details.
- {kopipasta-0.33.0/kopipasta.egg-info → kopipasta-0.35.0}/PKG-INFO +1 -1
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/tree_selector.py +84 -39
- {kopipasta-0.33.0 → kopipasta-0.35.0/kopipasta.egg-info}/PKG-INFO +1 -1
- {kopipasta-0.33.0 → kopipasta-0.35.0}/setup.py +1 -1
- kopipasta-0.35.0/tests/test_tree_selector.py +112 -0
- kopipasta-0.33.0/tests/test_tree_selector.py +0 -47
- {kopipasta-0.33.0 → kopipasta-0.35.0}/LICENSE +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/MANIFEST.in +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/README.md +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/__init__.py +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/cache.py +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/file.py +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/import_parser.py +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/main.py +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta/prompt.py +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta.egg-info/SOURCES.txt +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta.egg-info/dependency_links.txt +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta.egg-info/entry_points.txt +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta.egg-info/requires.txt +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/kopipasta.egg-info/top_level.txt +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/requirements.txt +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/setup.cfg +0 -0
- {kopipasta-0.33.0 → kopipasta-0.35.0}/tests/test_file.py +0 -0
|
@@ -20,9 +20,12 @@ class FileNode:
|
|
|
20
20
|
self.parent = parent
|
|
21
21
|
self.children: List['FileNode'] = []
|
|
22
22
|
self.expanded = False
|
|
23
|
-
# This flag marks the invisible root of the file tree, which is not meant to be displayed.
|
|
24
23
|
self.is_scan_root = is_scan_root
|
|
24
|
+
# Base size (for files) or initial placeholder (for dirs)
|
|
25
25
|
self.size = 0 if is_dir else os.path.getsize(self.path)
|
|
26
|
+
# New attributes for caching the results of a deep scan
|
|
27
|
+
self.total_size: int = self.size
|
|
28
|
+
self.is_scanned: bool = not self.is_dir
|
|
26
29
|
|
|
27
30
|
@property
|
|
28
31
|
def name(self):
|
|
@@ -48,7 +51,41 @@ class TreeSelector:
|
|
|
48
51
|
self.char_count = 0
|
|
49
52
|
self.quit_selection = False
|
|
50
53
|
self.viewport_offset = 0 # First visible item index
|
|
54
|
+
self._metrics_cache: Dict[str, Tuple[int, int]] = {}
|
|
55
|
+
|
|
56
|
+
def _calculate_directory_metrics(self, node: FileNode) -> Tuple[int, int]:
|
|
57
|
+
"""Recursively calculate total and selected size for a directory."""
|
|
58
|
+
if not node.is_dir:
|
|
59
|
+
return 0, 0
|
|
51
60
|
|
|
61
|
+
# Use instance cache for this render cycle
|
|
62
|
+
if node.path in self._metrics_cache:
|
|
63
|
+
return self._metrics_cache[node.path]
|
|
64
|
+
|
|
65
|
+
total_size = 0
|
|
66
|
+
selected_size = 0
|
|
67
|
+
|
|
68
|
+
# Ensure directory is scanned
|
|
69
|
+
if not node.children:
|
|
70
|
+
self._deep_scan_directory_and_calc_size(node.path, node)
|
|
71
|
+
|
|
72
|
+
for child in node.children:
|
|
73
|
+
if child.is_dir:
|
|
74
|
+
child_total, child_selected = self._calculate_directory_metrics(child)
|
|
75
|
+
total_size += child_total
|
|
76
|
+
selected_size += child_selected
|
|
77
|
+
else: # It's a file
|
|
78
|
+
total_size += child.size
|
|
79
|
+
if child.path in self.selected_files:
|
|
80
|
+
is_snippet, _ = self.selected_files[child.path]
|
|
81
|
+
if is_snippet:
|
|
82
|
+
selected_size += len(get_file_snippet(child.path))
|
|
83
|
+
else:
|
|
84
|
+
selected_size += child.size
|
|
85
|
+
|
|
86
|
+
self._metrics_cache[node.path] = (total_size, selected_size)
|
|
87
|
+
return total_size, selected_size
|
|
88
|
+
|
|
52
89
|
def build_tree(self, paths: List[str]) -> FileNode:
|
|
53
90
|
"""Build tree structure from given paths."""
|
|
54
91
|
# If one directory is given, make its contents the top level of the tree.
|
|
@@ -56,7 +93,7 @@ class TreeSelector:
|
|
|
56
93
|
root_path = os.path.abspath(paths[0])
|
|
57
94
|
root = FileNode(root_path, True, is_scan_root=True)
|
|
58
95
|
root.expanded = True
|
|
59
|
-
self.
|
|
96
|
+
self._deep_scan_directory_and_calc_size(root_path, root)
|
|
60
97
|
return root
|
|
61
98
|
|
|
62
99
|
# Otherwise, create a virtual root to hold multiple items (e.g., `kopipasta file.py dir/`).
|
|
@@ -79,7 +116,7 @@ class TreeSelector:
|
|
|
79
116
|
|
|
80
117
|
return root
|
|
81
118
|
|
|
82
|
-
def
|
|
119
|
+
def _deep_scan_directory_and_calc_size(self, dir_path: str, parent_node: FileNode):
|
|
83
120
|
"""Recursively scan directory and build tree"""
|
|
84
121
|
abs_dir_path = os.path.abspath(dir_path)
|
|
85
122
|
|
|
@@ -138,7 +175,7 @@ class TreeSelector:
|
|
|
138
175
|
result.append((node, level))
|
|
139
176
|
if node.is_dir and node.expanded:
|
|
140
177
|
if not node.children:
|
|
141
|
-
self.
|
|
178
|
+
self._deep_scan_directory_and_calc_size(node.path, node)
|
|
142
179
|
for child in node.children:
|
|
143
180
|
result.extend(self._flatten_tree(child, level + 1))
|
|
144
181
|
|
|
@@ -146,11 +183,13 @@ class TreeSelector:
|
|
|
146
183
|
|
|
147
184
|
def _build_display_tree(self) -> Tree:
|
|
148
185
|
"""Build Rich tree for display with viewport"""
|
|
186
|
+
self._metrics_cache = {} # Clear cache for each new render
|
|
187
|
+
|
|
149
188
|
# Get terminal size
|
|
150
189
|
_, term_height = shutil.get_terminal_size()
|
|
151
190
|
|
|
152
191
|
# Reserve space for header, help panel, and status
|
|
153
|
-
reserved_space =
|
|
192
|
+
reserved_space = 12
|
|
154
193
|
available_height = term_height - reserved_space
|
|
155
194
|
available_height = max(5, available_height) # Minimum height
|
|
156
195
|
|
|
@@ -177,10 +216,9 @@ class TreeSelector:
|
|
|
177
216
|
if self.viewport_offset > 0:
|
|
178
217
|
tree_title += f" ↑ ({self.viewport_offset} more)"
|
|
179
218
|
|
|
180
|
-
tree = Tree(tree_title
|
|
219
|
+
tree = Tree(tree_title)
|
|
181
220
|
|
|
182
221
|
# Build tree structure - only for visible portion
|
|
183
|
-
node_map = {}
|
|
184
222
|
viewport_end = min(len(flat_tree), self.viewport_offset + available_height)
|
|
185
223
|
|
|
186
224
|
# Track what level each visible item is at for proper tree structure
|
|
@@ -193,30 +231,35 @@ class TreeSelector:
|
|
|
193
231
|
is_current = i == self.current_index
|
|
194
232
|
style = "bold cyan" if is_current else ""
|
|
195
233
|
|
|
234
|
+
label = Text()
|
|
235
|
+
|
|
196
236
|
if node.is_dir:
|
|
197
237
|
icon = "📂" if node.expanded else "📁"
|
|
198
|
-
|
|
199
|
-
|
|
238
|
+
total_size, selected_size = self._calculate_directory_metrics(node)
|
|
239
|
+
if total_size > 0:
|
|
240
|
+
size_str = f" ({get_human_readable_size(selected_size)} / {get_human_readable_size(total_size)})"
|
|
241
|
+
else:
|
|
242
|
+
size_str = "" # Don't show size for empty dirs
|
|
243
|
+
|
|
244
|
+
# Omit the selection circle for directories
|
|
245
|
+
label.append(f"{icon} {node.name}{size_str}", style=style)
|
|
246
|
+
|
|
247
|
+
else: # It's a file
|
|
200
248
|
icon = "📄"
|
|
201
249
|
size_str = f" ({get_human_readable_size(node.size)})"
|
|
202
250
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
251
|
+
# File selection indicator
|
|
252
|
+
abs_path = os.path.abspath(node.path)
|
|
253
|
+
if abs_path in self.selected_files:
|
|
254
|
+
is_snippet, _ = self.selected_files[abs_path]
|
|
255
|
+
selection = "◐" if is_snippet else "●"
|
|
256
|
+
style = "green " + style
|
|
209
257
|
else:
|
|
210
|
-
selection = "
|
|
211
|
-
style = "green " + style
|
|
212
|
-
else:
|
|
213
|
-
selection = "○"
|
|
258
|
+
selection = "○"
|
|
214
259
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
label.append(f"{icon} {node.name}{size_str}", style=style)
|
|
219
|
-
|
|
260
|
+
label.append(f"{selection} ", style="dim")
|
|
261
|
+
label.append(f"{icon} {node.name}{size_str}", style=style)
|
|
262
|
+
|
|
220
263
|
# Add to tree at correct level
|
|
221
264
|
if level == 0:
|
|
222
265
|
tree_node = tree.add(label)
|
|
@@ -230,10 +273,17 @@ class TreeSelector:
|
|
|
230
273
|
level_stacks[level] = tree_node
|
|
231
274
|
else:
|
|
232
275
|
# Fallback - add to root with indentation indicator
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
276
|
+
indent_text = " " * level
|
|
277
|
+
if not node.is_dir:
|
|
278
|
+
# Re-add file selection marker for indented fallback
|
|
279
|
+
selection_char = "○"
|
|
280
|
+
if node.path in self.selected_files:
|
|
281
|
+
selection_char = "◐" if self.selected_files[node.path][0] else "●"
|
|
282
|
+
indent_text += f"{selection_char} "
|
|
283
|
+
|
|
284
|
+
# Create a new label with proper indentation for this edge case
|
|
285
|
+
fallback_label_text = f"{indent_text}{label.plain}"
|
|
286
|
+
tree_node = tree.add(Text(fallback_label_text, style=style))
|
|
237
287
|
level_stacks[level] = tree_node
|
|
238
288
|
|
|
239
289
|
# Add scroll indicator at bottom if needed
|
|
@@ -245,14 +295,9 @@ class TreeSelector:
|
|
|
245
295
|
|
|
246
296
|
def _show_help(self) -> Panel:
|
|
247
297
|
"""Create help panel"""
|
|
248
|
-
help_text = """[bold]Navigation:[/bold]
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
[bold]Selection:[/bold]
|
|
252
|
-
Space: Toggle file/dir a: Add all in dir s: Snippet mode
|
|
253
|
-
|
|
254
|
-
[bold]Actions:[/bold]
|
|
255
|
-
r: Reuse last selection g: Grep in directory d: Show dependencies
|
|
298
|
+
help_text = """[bold]Navigation:[/bold] ↑/k: Up ↓/j: Down →/l/Enter: Expand ←/h: Collapse
|
|
299
|
+
[bold]Selection:[/bold] Space: Toggle file/dir a: Add all in dir s: Snippet mode
|
|
300
|
+
[bold]Actions:[/bold] r: Reuse last selection g: Grep in directory d: Show dependencies
|
|
256
301
|
q: Quit and finalize"""
|
|
257
302
|
|
|
258
303
|
return Panel(help_text, title="Keyboard Controls", border_style="dim", expand=False)
|
|
@@ -349,7 +394,7 @@ q: Quit and finalize"""
|
|
|
349
394
|
|
|
350
395
|
# Ensure children are loaded
|
|
351
396
|
if not node.children:
|
|
352
|
-
self.
|
|
397
|
+
self._deep_scan_directory_and_calc_size(node.path, node)
|
|
353
398
|
|
|
354
399
|
# Collect all files recursively
|
|
355
400
|
all_files = []
|
|
@@ -358,7 +403,7 @@ q: Quit and finalize"""
|
|
|
358
403
|
if n.is_dir:
|
|
359
404
|
# CRITICAL FIX: Ensure sub-directory children are loaded before recursing
|
|
360
405
|
if not n.children:
|
|
361
|
-
self.
|
|
406
|
+
self._deep_scan_directory_and_calc_size(n.path, n)
|
|
362
407
|
for child in n.children:
|
|
363
408
|
collect_files(child)
|
|
364
409
|
else:
|
|
@@ -484,7 +529,7 @@ q: Quit and finalize"""
|
|
|
484
529
|
node.expanded = True
|
|
485
530
|
# Ensure children are loaded
|
|
486
531
|
if not node.children:
|
|
487
|
-
self.
|
|
532
|
+
self._deep_scan_directory_and_calc_size(node.path, node)
|
|
488
533
|
found = True
|
|
489
534
|
break
|
|
490
535
|
|
|
@@ -10,7 +10,7 @@ with open("requirements.txt", "r", encoding="utf-8") as f:
|
|
|
10
10
|
|
|
11
11
|
setup(
|
|
12
12
|
name="kopipasta",
|
|
13
|
-
version="0.
|
|
13
|
+
version="0.35.0",
|
|
14
14
|
author="Mikko Korpela",
|
|
15
15
|
author_email="mikko.korpela@gmail.com",
|
|
16
16
|
description="A CLI tool to generate prompts with project structure and file contents",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pytest
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from rich.text import Text
|
|
5
|
+
from kopipasta.file import get_human_readable_size
|
|
6
|
+
from kopipasta.tree_selector import FileNode, TreeSelector
|
|
7
|
+
|
|
8
|
+
@pytest.fixture
|
|
9
|
+
def mock_project(tmp_path: Path) -> Path:
|
|
10
|
+
"""Creates a mock project structure for testing TreeSelector."""
|
|
11
|
+
proj = tmp_path / "selector_project"
|
|
12
|
+
proj.mkdir()
|
|
13
|
+
(proj / "main.py").write_text("a" * 100) # 100 bytes
|
|
14
|
+
(proj / "README.md").write_text("b" * 200) # 200 bytes
|
|
15
|
+
|
|
16
|
+
sub = proj / "src"
|
|
17
|
+
sub.mkdir()
|
|
18
|
+
(sub / "component.js").write_text("c" * 1024) # 1 KB
|
|
19
|
+
|
|
20
|
+
nested_sub = sub / "utils"
|
|
21
|
+
nested_sub.mkdir()
|
|
22
|
+
(nested_sub / "helpers.py").write_text("d" * 2048) # 2 KB
|
|
23
|
+
|
|
24
|
+
# Change CWD into the mock project for the duration of the test
|
|
25
|
+
original_cwd = os.getcwd()
|
|
26
|
+
os.chdir(proj)
|
|
27
|
+
yield proj
|
|
28
|
+
os.chdir(original_cwd)
|
|
29
|
+
|
|
30
|
+
def test_preselects_files_from_command_line(mock_project: Path):
|
|
31
|
+
"""
|
|
32
|
+
Tests that TreeSelector correctly pre-selects files passed to it.
|
|
33
|
+
"""
|
|
34
|
+
main_py_abs = os.path.abspath("main.py")
|
|
35
|
+
component_js_abs = os.path.abspath("src/component.js")
|
|
36
|
+
|
|
37
|
+
files_to_preselect = [main_py_abs, component_js_abs]
|
|
38
|
+
|
|
39
|
+
# Instantiate the selector and manually run the pre-selection logic
|
|
40
|
+
selector = TreeSelector(ignore_patterns=[], project_root_abs=str(mock_project))
|
|
41
|
+
|
|
42
|
+
# We pass all potential paths to build_tree
|
|
43
|
+
selector.root = selector.build_tree(["."])
|
|
44
|
+
selector._preselect_files(files_to_preselect)
|
|
45
|
+
|
|
46
|
+
# Assertions
|
|
47
|
+
assert len(selector.selected_files) == 2
|
|
48
|
+
assert main_py_abs in selector.selected_files
|
|
49
|
+
assert component_js_abs in selector.selected_files
|
|
50
|
+
|
|
51
|
+
assert not selector.selected_files[main_py_abs][0]
|
|
52
|
+
assert not selector.selected_files[component_js_abs][0]
|
|
53
|
+
|
|
54
|
+
expected_char_count = os.path.getsize(main_py_abs) + os.path.getsize(component_js_abs)
|
|
55
|
+
assert selector.char_count == expected_char_count
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_directory_label_shows_recursive_size_metrics(mock_project: Path):
|
|
59
|
+
"""
|
|
60
|
+
Tests that directory labels correctly display the total size of selected files
|
|
61
|
+
and the total size of all files within that directory, recursively.
|
|
62
|
+
It also checks that the directory selector '○' is removed.
|
|
63
|
+
"""
|
|
64
|
+
selector = TreeSelector(ignore_patterns=[], project_root_abs=str(mock_project))
|
|
65
|
+
selector.root = selector.build_tree(["."])
|
|
66
|
+
selector.root.expanded = True # Expand root to see 'src'
|
|
67
|
+
|
|
68
|
+
# Find the 'src' node and expand it
|
|
69
|
+
src_node = next(child for child in selector.root.children if child.name == 'src')
|
|
70
|
+
src_node.expanded = True
|
|
71
|
+
|
|
72
|
+
# Pre-select 'main.py' (at root) and 'helpers.py' (nested in src/utils)
|
|
73
|
+
main_py_abs = os.path.abspath("main.py")
|
|
74
|
+
helpers_py_abs = os.path.abspath("src/utils/helpers.py")
|
|
75
|
+
selector.selected_files = {
|
|
76
|
+
main_py_abs: (False, None),
|
|
77
|
+
helpers_py_abs: (False, None),
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Generate the visible nodes and their labels for testing
|
|
81
|
+
flat_tree = selector._flatten_tree(selector.root)
|
|
82
|
+
visible_nodes = [node for node, _ in flat_tree]
|
|
83
|
+
|
|
84
|
+
def get_node_label(node: FileNode) -> str:
|
|
85
|
+
# This is a simplified version of the label generation logic in _build_display_tree
|
|
86
|
+
# It helps us test the output without a full render cycle.
|
|
87
|
+
if node.is_dir:
|
|
88
|
+
total_size, selected_size = selector._calculate_directory_metrics(node)
|
|
89
|
+
size_str = f" ({get_human_readable_size(selected_size)} / {get_human_readable_size(total_size)})"
|
|
90
|
+
icon = "📂" if node.expanded else "📁"
|
|
91
|
+
label = Text()
|
|
92
|
+
label.append(f"{icon} {node.name}{size_str}")
|
|
93
|
+
return label.plain
|
|
94
|
+
return "" # We only care about directory labels for this test
|
|
95
|
+
|
|
96
|
+
# Find the nodes we want to test
|
|
97
|
+
root_node_proxy = visible_nodes[0] # This will be 'src' since we built tree from '.'
|
|
98
|
+
utils_node = next(n for n in visible_nodes if n.name == 'utils')
|
|
99
|
+
|
|
100
|
+
# Test the 'src' directory label
|
|
101
|
+
# Total: component.js (1024) + helpers.py (2048) = 3072 bytes
|
|
102
|
+
# Selected: helpers.py (2048) = 2048 bytes
|
|
103
|
+
src_label = get_node_label(src_node)
|
|
104
|
+
assert "2.00 KB / 3.00 KB" in src_label
|
|
105
|
+
assert not src_label.startswith("○")
|
|
106
|
+
|
|
107
|
+
# Test the 'utils' directory label
|
|
108
|
+
# Total: helpers.py (2048) = 2048 bytes
|
|
109
|
+
# Selected: helpers.py (2048) = 2048 bytes
|
|
110
|
+
utils_label = get_node_label(utils_node)
|
|
111
|
+
assert "2.00 KB / 2.00 KB" in utils_label
|
|
112
|
+
assert not utils_label.startswith("○")
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import pytest
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from kopipasta.tree_selector import TreeSelector
|
|
5
|
-
|
|
6
|
-
@pytest.fixture
|
|
7
|
-
def mock_project(tmp_path: Path) -> Path:
|
|
8
|
-
"""Creates a mock project structure for testing TreeSelector."""
|
|
9
|
-
proj = tmp_path / "selector_project"
|
|
10
|
-
proj.mkdir()
|
|
11
|
-
(proj / "main.py").write_text("print('hello')")
|
|
12
|
-
(proj / "README.md").write_text("# Test Project")
|
|
13
|
-
sub = proj / "src"
|
|
14
|
-
sub.mkdir()
|
|
15
|
-
(sub / "component.js").write_text("console.log('test');")
|
|
16
|
-
# Change CWD into the mock project for the duration of the test
|
|
17
|
-
original_cwd = os.getcwd()
|
|
18
|
-
os.chdir(proj)
|
|
19
|
-
yield proj
|
|
20
|
-
os.chdir(original_cwd)
|
|
21
|
-
|
|
22
|
-
def test_preselects_files_from_command_line(mock_project: Path):
|
|
23
|
-
"""
|
|
24
|
-
Tests that TreeSelector correctly pre-selects files passed to it.
|
|
25
|
-
"""
|
|
26
|
-
main_py_abs = os.path.abspath("main.py")
|
|
27
|
-
component_js_abs = os.path.abspath("src/component.js")
|
|
28
|
-
|
|
29
|
-
files_to_preselect = [main_py_abs, component_js_abs]
|
|
30
|
-
|
|
31
|
-
# Instantiate the selector and manually run the pre-selection logic
|
|
32
|
-
selector = TreeSelector(ignore_patterns=[], project_root_abs=str(mock_project))
|
|
33
|
-
|
|
34
|
-
# We pass all potential paths to build_tree
|
|
35
|
-
selector.root = selector.build_tree(["."])
|
|
36
|
-
selector._preselect_files(files_to_preselect)
|
|
37
|
-
|
|
38
|
-
# Assertions
|
|
39
|
-
assert len(selector.selected_files) == 2
|
|
40
|
-
assert main_py_abs in selector.selected_files
|
|
41
|
-
assert component_js_abs in selector.selected_files
|
|
42
|
-
|
|
43
|
-
assert not selector.selected_files[main_py_abs][0]
|
|
44
|
-
assert not selector.selected_files[component_js_abs][0]
|
|
45
|
-
|
|
46
|
-
expected_char_count = os.path.getsize(main_py_abs) + os.path.getsize(component_js_abs)
|
|
47
|
-
assert selector.char_count == expected_char_count
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|