-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdirectory.py
More file actions
157 lines (142 loc) · 6.19 KB
/
Copy pathdirectory.py
File metadata and controls
157 lines (142 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from typing import Iterable
import os
from .fs_tree_node import FsTreeNode
from .file import File
class Directory(FsTreeNode):
ROOT = None
NULL = None
def __init__(self, dirname: str, parent_dir , children = None,dry = False,allow_hidden=False,dry_files=False):
super(Directory,self).__init__(dirname,parent_dir,allow_hidden)
self.dry=dry
self.children : dict[str,Directory] = dict()
self.dry_files=dry_files
if self.dry!=True:
self.readFs(dry_files=dry_files,allow_hidden=allow_hidden)
if isinstance(children,Iterable):
self.children.clear()
if isinstance(children,dict):
for _child in children.values():
self.add_child(_child)
else:
for _child in children:
self.add_child(_child)
def add_child(self,fs_object,type_hint = None):
if isinstance(fs_object,FsTreeNode):
fs_object.set_parent(self)
elif isinstance(fs_object,str):
FsTreeNode.from_path(fs_object,type_hint=type_hint).set_parent(self)
else:
raise Exception("Invalid child type")
def rem_child(self,child_name,update_fs=False):
_child=self.get_child(child_name)
if update_fs==True:
_child.deleteFs()
self.children.pop(_child.name)
@staticmethod
def from_path(path,children = None,dry = False,allow_hidden=False,dry_files=False):
return(FsTreeNode.from_path(path,type_hint=Directory,children=children,dry=dry,allow_hidden=allow_hidden,dry_files=dry_files))
def get_grandchild(self,relative_path,type_hint=None):
if isinstance(relative_path,str):
relative_path = FsTreeNode.from_path(relative_path,type_hint=type_hint)
if not isinstance(relative_path,FsTreeNode):
raise Exception("invalid path type")
if relative_path.is_absolute:
raise Exception("the path should be relative to fetch a grandchild")
_relative_ancestors = relative_path.ancestor_list
if len(_relative_ancestors)==0:
return self.get_child(relative_path.name)
highest_parent : Directory = _relative_ancestors.pop()
new_relative_path = relative_path.get_relative_to(highest_parent)
return self.get_child(highest_parent.name).get_grandchild(new_relative_path,type_hint=type_hint)
def copyTo(self,dir,name=None, update_fs=False,allow_hidden=False,ignore_files = [],ignore_dirs = []):
if isinstance(name,type(None)):
name=self.name
cp_dir=Directory(name,dir,allow_hidden=allow_hidden)
for _child in self.children.values():
cp_dir.add_child(_child)
for _i in ignore_files:
try:
_gc=cp_dir.get_grandchild(_i,type_hint=File)
_gc.parent_dir.rem_child(_gc.name)
except:
pass
for _i in ignore_dirs:
try:
_gc=cp_dir.get_grandchild(_i,type_hint=Directory)
_gc.parent_dir.rem_child(_gc.name)
except:
pass
if update_fs==True:
cp_dir.updateFs(update_children=True)
return cp_dir
def list_children(self):
return list(self.children.keys())
def list_files(self):
file_list=[]
for _child in self.children.values():
if isinstance(_child,File):
file_list.append(_child.name)
return file_list
def list_dirs(self):
dir_list=[]
for _child in self.children.values():
if isinstance(_child,Directory):
dir_list.append(_child.name)
return dir_list
def get_child(self,child_name :str) ->FsTreeNode:
if self.dry:
raise Exception("Cannot fetch children from dry directory")
if child_name in self.children.keys():
return self.children[child_name]
raise Exception(f"Directory at {self.path} has no child {child_name}.")
def __getitem__(self,_key : str):
return self.get_child(_key)
@property
def in_fs(self):
return(os.path.isdir(self.path))
def readFs(self,allow_hidden=False,dry=None,dry_files=False,update_obj=True):
if isinstance(dry,bool):
self.dry=dry
_children=self.children
_parent=self
if update_obj == False:
_children=dict()
_parent = Directory.NULL
else:
_children.clear()
if (self.dry!=True) and (self.in_fs==True):
listdir = os.listdir(self.path)
for elem in listdir:
elem_path=os.path.join(self.path,elem)
if os.path.isfile(elem_path) and not (not allow_hidden and elem.startswith(".")):
_children[elem]=File(elem,_parent,dry=dry_files)
if os.path.isdir(elem_path) and not (not allow_hidden and elem.startswith(".")):
_children[elem]=Directory(elem,_parent,allow_hidden=allow_hidden,dry_files=dry_files)
return _children
def updateFs(self,update_children = False,allow_hidden=False):
if self.is_same_path(Directory.NULL):
return
self.parent_dir.updateFs()
if (not self.dry):
if (not self.in_fs) :
os.mkdir(self.path)
if not update_children:
return
fs_children=self.readFs(update_obj=False,dry_files=True)
fs_childset = set(fs_children.keys())
for del_child_name in fs_childset-set(self.children.keys()):
self.add_child(del_child_name)
self.rem_child(del_child_name,update_fs=True)
for _child in self.children.values():
if(isinstance(_child,File)):
_child.updateFs()
elif(isinstance(_child,Directory)):
_child.updateFs(update_children)
def deleteFs(self):
if not self.dry:
for _child in self.children.values():
_child.deleteFs()
if self.in_fs:
os.removedirs(self.path)
Directory.NULL=Directory("",None,dry=True)
Directory.ROOT=Directory("/",Directory.NULL,dry=True)