1
+ """
2
+ This module provides API to perform various operations on directory or file(s) based
3
+ on the differences between the snapshots of the two directories.
4
+ """
5
+ import os
6
+ import shutil
7
+ import pickle
8
+
9
+ from os .path import basename , normpath , relpath
10
+ from itertools import starmap #needs-attention
11
+
12
+ from watchdog .utils .dirsnapshot import DirectorySnapshot , DirectorySnapshotDiff
13
+
14
+ class FileSystemManager ():
15
+
16
+ def __init__ (self , directoryPath , backupDirectoryPath ):
17
+ self .directoryPath = directoryPath
18
+ self .backupDirectoryPath = backupDirectoryPath
19
+ self .listdir = lambda path : [
20
+ p for p in os .listdir (path ) if p != basename (normpath (backupDirectoryPath ))] #needs-attention
21
+
22
+ def getDifferencesSinceLastSync (self ):
23
+ """
24
+ Get differences between the current directory and backup directory since last sync.
25
+ """
26
+ oldSnapshot = self .getSnapshotOld ()
27
+ currentSnapshot = self .getSnapshotCurrent ()
28
+ difference = DirectorySnapshotDiff (oldSnapshot , currentSnapshot )
29
+ return self .getDiffDict (difference )
30
+
31
+ def getSnapshotCurrent (self ):
32
+ """
33
+ Get the snapshot of the directory in current state.
34
+ See http://pythonhosted.org/pydica-watchdog/_modules/watchdog/utils/dirsnapshot.html for more details
35
+ """
36
+ return DirectorySnapshot (self .directoryPath , listdir = self .listdir )
37
+
38
+ def getSnapshotOld (self ):
39
+ """
40
+ Get the snapshot of backup directory.
41
+ If backup directory is not present snapshot of current directory
42
+ """
43
+ try :
44
+ with open ('' .join ((self .backupDirectoryPath , '.snapshot' )), 'rb' ) as snapshotFile :
45
+ snapshot = pickle .load (snapshotFile )
46
+ except FileNotFoundError :
47
+ snapshot = DirectorySnapshot (
48
+ self .directoryPath , listdir = lambda _ : []) #needs-attention
49
+ return snapshot
50
+
51
+ def getDiffDict (self , difference ):
52
+ """
53
+ Get the differences between two snapshots in the form of a dictionary
54
+
55
+ param difference: L{watchdog.utils.dirsnapshot.DirectorySnapshotDiff}
56
+ """
57
+ diffDict = {}
58
+ for key , value in difference .__dict__ .items ():
59
+ if key in ('_dirs_moved' , '_files_moved' ):
60
+ diffDict [key [1 :]] = list (starmap (
61
+ lambda p1 , p2 : (relpath (p1 , self .directoryPath ),
62
+ relpath (p2 , self .directoryPath )), value ))
63
+ else :
64
+ diffDict [key [1 :]] = list (map (lambda p : relpath (p , self .directoryPath ), value ))
65
+ return diffDict
66
+
67
+ def syncBackupState (self ):
68
+ """
69
+ Make or sync the backup directory
70
+ """
71
+ currentSnapshot = self .getSnapshotCurrent ()
72
+ try :
73
+ self .deleteDirectory (self .backupDirectoryPath )
74
+ except FileNotFoundError :
75
+ pass
76
+ self .copyDirectory (self .directoryPath , self .backupDirectoryPath )
77
+ with open ('' .join ((self .backupDirectoryPath , '.snapshot' )), 'wb' ) as snapshotFile :
78
+ pickle .dump (currentSnapshot , snapshotFile )
79
+
80
+ def createDirectory (self , path ):
81
+ """
82
+ OS command for making directories
83
+
84
+ param path : path of the directory to create
85
+ """
86
+ os .makedirs (relpath (path , self .directoryPath ), exist_ok = True )
87
+
88
+ def deleteDirectory (self , path ):
89
+ """
90
+ Use shutil for deleting directory
91
+
92
+ param path : path of the directory to delete
93
+ """
94
+ shutil .rmtree (relpath (path , self .directoryPath ))
95
+
96
+ def moveDirectory (self , sourcePath , destinationPath ):
97
+ """
98
+ Use OS module for moving directory
99
+
100
+ param sourcePath: source path of the directory
101
+ param destinationPath : destination path of the directory
102
+ """
103
+ os .renames (relpath (sourcePath , self .directoryPath ), relpath (destinationPath , self .directoryPath ))
104
+
105
+ def copyDirectory (self , sourcePath , destinationPath ):
106
+ """
107
+ use shutil.copytree for copying the contents of the directory
108
+
109
+ param sourcePath: source path of the directory
110
+ param destinationPath : destination path of the directory
111
+ """
112
+ shutil .copytree (relpath (sourcePath , self .directoryPath ), relpath (destinationPath , self .directoryPath ),
113
+ ignore = lambda * _ : [basename (normpath (self .backupDirectoryPath ))]) #needs-attention
114
+
115
+ def deleteFile (self , path ):
116
+ """
117
+ Use OS module to delete file.
118
+
119
+ param path : path of file to delete
120
+ """
121
+ os .remove (relpath (path , self .directoryPath ))
122
+
123
+ def moveFile (self , sourcePath , destinationPath ):
124
+ """
125
+ Use OS module to move file(s)
126
+
127
+ param sourcePath : source path of the file
128
+ param destinationPath : destination path of the file
129
+ """
130
+ os .renames (relpath (sourcePath , self .directoryPath ), relpath (destinationPath , self .directoryPath ))
131
+
132
+ def readFile (self , path ):
133
+ """
134
+ Read the contents of a file
135
+
136
+ paaram path : path of the file to read
137
+ """
138
+ with open (relpath (self .directoryPath + '/' + path ), 'r' ) as readFile :
139
+ return readFile .readlines ()
140
+
141
+ def writeFile (self , path , data ):
142
+ """
143
+ Write the given data to the file
144
+
145
+ param data : contents to be written to the file
146
+ param path : path of the file to be written
147
+ """
148
+ with open (relpath (self .directoryPath + '/' + path ), 'w' ) as writeFile :
149
+ writeFile .writelines (data )
150
+
151
+ def readBackupFile (self , path ):
152
+ """
153
+ Read the contents of the backup file
154
+
155
+ param path : path of the backup file
156
+ """
157
+ try :
158
+ return self .readFile ('' .join ((self .backupDirectoryPath , path )))
159
+ except FileNotFoundError :
160
+ return None
161
+
162
+ def getFilesData (self , files ):
163
+ """
164
+ Return the data of the file(s) provided in the form of a dictionary
165
+
166
+ param files : A python iterable containing the path of the files from which data should be read
167
+ """
168
+ fileDataDictionary = {}
169
+ for file in files :
170
+ try :
171
+ fileDataDictionary [file ] = self .readFile (file )
172
+ except FileNotFoundError :
173
+ fileDataDictionary [file ] = self .readBackupFile (file )
174
+ return fileDataDictionary
0 commit comments