-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathinventory.py
154 lines (124 loc) · 4.84 KB
/
inventory.py
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
from enum import Enum
# import cli
import json
import os
class Inventory:
_FILENAME = u'pyback_inventory.json'
def __init__(self, dir_path):
self.dir_path = dir_path = unicode(dir_path)
self.file_path = os.path.join(dir_path, Inventory._FILENAME)
self._entries = {}
if os.path.isfile(self.file_path):
with open(self.file_path, 'r') as infile:
deserialized = json.load(infile,
object_hook=EnumEncoder.as_enum)
for key, obj in deserialized.iteritems():
self._entries[key] = InventoryEntry.deserialize(
self, key, obj)
else:
self._add_new_file(Inventory._FILENAME)
contents_list = os.listdir(dir_path)
for name in contents_list:
if (os.path.isfile(os.path.join(dir_path, name))
and name not in self._entries):
self._add_new_file(name)
def save(self):
with open(self.file_path, 'w') as outfile:
outfile.write("{")
for index, key in enumerate(self._entries):
if index:
outfile.write(",")
outfile.write("\"%s\": " % key)
self._entries[key].serialize(outfile)
outfile.write("}")
def get_by_state(self, state):
for key, entry in self._entries.iteritems():
if (entry.get_state() == state
and key != Inventory._FILENAME):
yield entry
def get_inventory_file_entry(self):
return self._entries[Inventory._FILENAME]
def get_full_path(self, filename):
return os.path.join(self.dir_path, filename)
def _add_new_file(self, filename):
self._entries[filename] = InventoryEntry(
self, filename, FileState.NEW)
class InventoryEntry:
_in_progress_attrs = ('_uploadId', '_partSize',
'_partsUploaded')
def __init__(self, inventory, fileName, state=None):
self._inventory = inventory
self._fileName = fileName
if state is None:
state = FileState.NEW
self._state = state
self._uploads = []
def get_state(self):
return self._state
def get_fileName(self):
return self._fileName
def get_filePath(self):
return self._inventory.get_full_path(self._fileName)
def get_part_size(self):
return self._partSize
def get_upload_id(self):
return self._uploadId
def get_parts_uploaded(self):
return self._partsUploaded
def set_state_from_upload(self, file_upload, state):
if state == FileState.IN_PROGRESS:
self._uploadId = file_upload.get_upload_id()
self._partSize = file_upload.get_part_size()
self._partsUploaded = file_upload.get_parts_uploaded()
self._state = FileState.IN_PROGRESS
elif state == FileState.UPLOADED:
self._add_upload(file_upload)
for attr_name in self._in_progress_attrs:
del self.__dict__[attr_name]
self._state = FileState.UPLOADED
else:
raise Exception("Unhandled file state: " + file_upload.get_state())
self._inventory.save()
def serialize(self, outfile):
me = self.__dict__.copy()
del me['_inventory']
del me['_fileName']
if len(self._uploads) == 0:
del me['_uploads']
json.dump(me, outfile, cls=EnumEncoder)
@classmethod
def deserialize(cls, inventory, fileName, obj):
me = cls(inventory, fileName, obj['_state'])
if '_uploads' in obj and len(obj['_uploads']):
me._uploads = obj['_uploads']
for attr_name in cls._in_progress_attrs:
if attr_name in obj:
setattr(me, attr_name, obj[attr_name])
return me
def _add_upload(self, file_upload):
self._uploads.append({
'end_time': file_upload.get_end_time(),
'checksum': file_upload.get_checksum(),
'archiveId': file_upload.get_archive_id(),
'location': file_upload.get_upload_location()
})
class FileState(Enum):
MISSING = -1 # uploaded but now missing from local dir
NEW = 0 # in local dir but not uploaded
IN_PROGRESS = 1
UPLOADED = 2
MODIFIED = 3 # modified locally since uploading
# Stolen from
# http://stackoverflow.com/questions/24481852/serialising-an-enum-member-to-json
class EnumEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Enum):
return {"__enum__": str(obj)}
return json.JSONEncoder.default(self, obj)
@staticmethod
def as_enum(d):
if "__enum__" in d:
name, member = d["__enum__"].split(".")
return getattr(globals()[name], member)
else:
return d