Skip to content

Commit a38cac3

Browse files
tomcodgentkfoss
andauthored
Use case: Ensure files are not imported directly outside specified folder (#576)
# Motivation We want to assert that all files from certain folder are NOT imported directly outside the folder. # Content <!-- Please include a summary of the change --> # Testing <!-- How was the change tested? --> # Please check the following before marking your PR as ready for review - [ ] I have added tests for my changes - [ ] I have updated the documentation or added new documentation as needed --------- Co-authored-by: tomcodgen <[email protected]>
1 parent cb11419 commit a38cac3

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

src/codegen/sdk/core/directory.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,28 @@ def __init__(self, path: Path, dirpath: str, parent: Self | None):
5050
def __iter__(self):
5151
return iter(self.items.values())
5252

53+
def _is_a_subdirectory_of(self, target_directory: "Directory"):
54+
"""Checks whether this directory is a subdirectory of another directory"""
55+
if self.parent == target_directory:
56+
return True
57+
if self.parent is None:
58+
return False
59+
return self.parent._is_a_subdirectory_of(target_directory=target_directory)
60+
5361
def __contains__(self, item: str | TFile | Self) -> bool:
5462
if isinstance(item, str):
5563
return item in self.items
64+
elif isinstance(item, Directory):
65+
return item._is_a_subdirectory_of(self)
5666
else:
57-
return item in self.items.values()
67+
# It could only ever be a file here, at least according to item's types...
68+
match item.directory:
69+
case None:
70+
return False
71+
case _ if item.directory == self:
72+
return True
73+
case _:
74+
return item.directory._is_a_subdirectory_of(self)
5875

5976
def __len__(self) -> int:
6077
return len(self.items)

tests/unit/codegen/sdk/core/test_directory.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,107 @@ def test_unicode_in_filename(tmpdir) -> None:
234234
file = codebase.get_file("test/我很喜欢冰激淋/test-file 12'3_🍦.py")
235235
assert file is not None
236236
assert file.content == "print('Hello, world!')"
237+
238+
239+
def test_contains_dirs_and_files(tmpdir) -> None:
240+
# language=python
241+
with get_codebase_session(
242+
tmpdir=tmpdir,
243+
files={
244+
"file0.py": "",
245+
"main_dir/file1.py": "",
246+
"main_dir/file2.py": "",
247+
"main_dir/sub_dir/file3.py": "",
248+
"main_dir/sub_dir/sub_sub_dir/file4.py": "",
249+
"main_dir/sub_dir/sub_sub_dir/file5.py": "",
250+
"main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir/file6.py": "",
251+
"main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir/sub_sub_sub_sub_dir/sub_sub_sub_sub_sub_dir/file7.py": "",
252+
"lonely_dir/file_lonely.py": "",
253+
},
254+
) as codebase:
255+
file0 = codebase.get_file("file0.py")
256+
main_dir = codebase.get_directory("main_dir")
257+
file1 = codebase.get_file("main_dir/file1.py")
258+
file2 = codebase.get_file("main_dir/file2.py")
259+
sub_dir = codebase.get_directory("main_dir/sub_dir")
260+
file3 = codebase.get_file("main_dir/sub_dir/file3.py")
261+
sub_sub_dir = codebase.get_directory("main_dir/sub_dir/sub_sub_dir")
262+
file4 = codebase.get_file("main_dir/sub_dir/sub_sub_dir/file4.py")
263+
file5 = codebase.get_file("main_dir/sub_dir/sub_sub_dir/file5.py")
264+
sub_sub_sub_dir = codebase.get_directory("main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir")
265+
file6 = codebase.get_file("main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir/file6.py")
266+
sub_sub_sub_sub_dir = codebase.get_directory("main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir/sub_sub_sub_sub_dir")
267+
sub_sub_sub_sub_sub_dir = codebase.get_directory("main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir/sub_sub_sub_sub_dir/sub_sub_sub_sub_sub_dir")
268+
file7 = codebase.get_file("main_dir/sub_dir/sub_sub_dir/sub_sub_sub_dir/sub_sub_sub_sub_dir/sub_sub_sub_sub_sub_dir/file7.py")
269+
directory_stack = main_dir.subdirectories
270+
directory_stack.append(main_dir)
271+
main_directory_stack_no_root = directory_stack
272+
file_stack = [file7]
273+
for directory in directory_stack:
274+
# ignore self
275+
if directory != sub_sub_sub_sub_sub_dir:
276+
assert sub_sub_sub_sub_sub_dir in directory
277+
else:
278+
# A dir is not in itself!
279+
assert sub_sub_sub_sub_sub_dir not in directory
280+
for file in file_stack:
281+
assert file in directory
282+
283+
directory_stack.remove(sub_sub_sub_sub_sub_dir)
284+
285+
for directory in directory_stack:
286+
if directory != sub_sub_sub_sub_dir:
287+
assert sub_sub_sub_sub_dir in directory
288+
289+
for file in file_stack:
290+
assert file in directory
291+
292+
directory_stack.remove(sub_sub_sub_sub_dir)
293+
file_stack.append(file6)
294+
295+
for directory in directory_stack:
296+
if directory != sub_sub_sub_dir:
297+
assert sub_sub_sub_dir in directory
298+
299+
for file in file_stack:
300+
assert file in directory
301+
302+
directory_stack.remove(sub_sub_sub_dir)
303+
file_stack.append(file5)
304+
file_stack.append(file4)
305+
306+
for directory in directory_stack:
307+
if directory != sub_sub_dir:
308+
assert sub_sub_dir in directory
309+
310+
for file in file_stack:
311+
assert file in directory
312+
313+
directory_stack.remove(sub_sub_dir)
314+
file_stack.append(file3)
315+
316+
for directory in directory_stack:
317+
if directory != sub_dir:
318+
assert sub_dir in directory
319+
for file in file_stack:
320+
assert file in directory
321+
322+
directory_stack.remove(sub_dir)
323+
file_stack.append(file2)
324+
file_stack.append(file1)
325+
326+
for directory in directory_stack:
327+
if directory != main_dir:
328+
assert main_dir in directory
329+
for file in file_stack:
330+
assert file in directory
331+
332+
lonely_dir = codebase.get_directory("lonely_dir")
333+
lonely_file = codebase.get_file("lonely_dir/file_lonely.py")
334+
335+
for directory in main_directory_stack_no_root:
336+
assert file0 not in directory
337+
assert lonely_dir not in directory
338+
assert lonely_file not in directory
339+
340+
assert lonely_file in lonely_dir

0 commit comments

Comments
 (0)