1import os
2from typing import Any
3
4from parso import file_io
5
6
7class AbstractFolderIO:
8 def __init__(self, path):
9 self.path = path
10
11 def get_base_name(self):
12 raise NotImplementedError
13
14 def list(self):
15 raise NotImplementedError
16
17 def get_file_io(self, name):
18 raise NotImplementedError
19
20 def get_parent_folder(self):
21 raise NotImplementedError
22
23 def __repr__(self):
24 return '<%s: %s>' % (self.__class__.__name__, self.path)
25
26
27class FolderIO(AbstractFolderIO):
28 def get_base_name(self):
29 return os.path.basename(self.path)
30
31 def list(self):
32 return os.listdir(self.path)
33
34 def get_file_io(self, name):
35 return FileIO(os.path.join(self.path, name))
36
37 def get_parent_folder(self):
38 return FolderIO(os.path.dirname(self.path))
39
40 def walk(self):
41 for root, dirs, files in os.walk(self.path):
42 root_folder_io = FolderIO(root)
43 original_folder_ios = [FolderIO(os.path.join(root, d)) for d in dirs]
44 modified_folder_ios = list(original_folder_ios)
45 yield (
46 root_folder_io,
47 modified_folder_ios,
48 [FileIO(os.path.join(root, f)) for f in files],
49 )
50 modified_iterator = iter(reversed(modified_folder_ios))
51 current = next(modified_iterator, None)
52 i = len(original_folder_ios)
53 for folder_io in reversed(original_folder_ios):
54 i -= 1 # Basically enumerate but reversed
55 if current is folder_io:
56 current = next(modified_iterator, None)
57 else:
58 del dirs[i]
59
60
61class FileIOFolderMixin:
62 path: Any
63
64 def get_parent_folder(self):
65 return FolderIO(os.path.dirname(self.path))
66
67
68class ZipFileIO(file_io.KnownContentFileIO, FileIOFolderMixin):
69 """For .zip and .egg archives"""
70 def __init__(self, path, code, zip_path):
71 super().__init__(path, code)
72 self._zip_path = zip_path
73
74 def get_last_modified(self):
75 try:
76 return os.path.getmtime(self._zip_path)
77 except (FileNotFoundError, PermissionError, NotADirectoryError):
78 return None
79
80
81class FileIO(file_io.FileIO, FileIOFolderMixin):
82 pass
83
84
85class KnownContentFileIO(file_io.KnownContentFileIO, FileIOFolderMixin):
86 pass