OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """The Virtual File System (VFS) volume system interface.""" | 2 """The Virtual File System (VFS) volume system interface.""" |
3 | 3 |
| 4 from __future__ import unicode_literals |
| 5 |
4 import abc | 6 import abc |
5 | 7 |
6 | 8 |
7 class VolumeAttribute(object): | 9 class VolumeAttribute(object): |
8 """The VFS volume attribute object.""" | 10 """The VFS volume attribute.""" |
9 | 11 |
10 def __init__(self, identifier, value): | 12 def __init__(self, identifier, value): |
11 """Initializes the volume attribute object. | 13 """Initializes the volume attribute object. |
12 | 14 |
13 Args: | 15 Args: |
14 identifier: string that uniquely identifies the attribute within the | 16 identifier (str): identifier of the attribute within the volume. |
15 volume. | 17 value (object): value of the attribute. |
16 value: the value of the attribute. | |
17 """ | 18 """ |
18 super(VolumeAttribute, self).__init__() | 19 super(VolumeAttribute, self).__init__() |
19 self.identifier = identifier | 20 self.identifier = identifier |
20 self.value = value | 21 self.value = value |
21 | 22 |
22 | 23 |
23 class VolumeExtent(object): | 24 class VolumeExtent(object): |
24 """The VFS volume extent object.""" | 25 """The VFS volume extent.""" |
25 | 26 |
26 EXTENT_TYPE_DATA = 0 | 27 EXTENT_TYPE_DATA = 0 |
27 EXTENT_TYPE_SPARSE = 1 | 28 EXTENT_TYPE_SPARSE = 1 |
28 | 29 |
29 def __init__(self, offset, size, extent_type=EXTENT_TYPE_DATA): | 30 def __init__(self, offset, size, extent_type=EXTENT_TYPE_DATA): |
30 """Initializes the volume extent object. | 31 """Initializes a volume extent. |
31 | 32 |
32 Args: | 33 Args: |
33 offset: the start offset of the extent, in bytes. | 34 offset (int): start offset of the extent, in bytes. |
34 size: the size of the extent, in bytes. | 35 size (int): size of the extent, in bytes. |
35 extent_type: optional type of extent, the default is | 36 extent_type (Optional[str]): type of extent. |
36 EXTENT_TYPE_DATA. | |
37 """ | 37 """ |
38 super(VolumeExtent, self).__init__() | 38 super(VolumeExtent, self).__init__() |
39 self.offset = offset | 39 self.offset = offset |
40 self.size = size | 40 self.size = size |
41 self.extent_type = extent_type | 41 self.extent_type = extent_type |
42 | 42 |
43 | 43 |
44 class Volume(object): | 44 class Volume(object): |
45 """The VFS volume interface.""" | 45 """The VFS volume interface.""" |
46 | 46 |
47 def __init__(self, identifier): | 47 def __init__(self, identifier): |
48 """Initializes the volume extent object. | 48 """Initializes a volume. |
49 | 49 |
50 Args: | 50 Args: |
51 identifier: string that uniquely identifies the volume within the volume | 51 identifier (str): identifier of the attribute within the volume. |
52 system. | |
53 """ | 52 """ |
54 super(Volume, self).__init__() | 53 super(Volume, self).__init__() |
55 self.identifier = identifier | 54 self.identifier = identifier |
56 self._attributes = {} | 55 self._attributes = {} |
57 self._extents = [] | 56 self._extents = [] |
58 self._is_parsed = False | 57 self._is_parsed = False |
59 | 58 |
60 def _AddAttribute(self, attribute): | 59 def _AddAttribute(self, attribute): |
61 """Adds an attribute. | 60 """Adds an attribute. |
62 | 61 |
63 Args: | 62 Args: |
64 attribute: the volume attribute object (instance of VolumeAttribute). | 63 attribute (VolumeAttribute): a volume attribute. |
65 | 64 |
66 Raises: | 65 Raises: |
67 KeyError: if volume attribute is already set for the corresponding volume | 66 KeyError: if volume attribute is already set for the corresponding volume |
68 attribute identifier. | 67 attribute identifier. |
69 """ | 68 """ |
70 if attribute.identifier in self._attributes: | 69 if attribute.identifier in self._attributes: |
71 raise KeyError(( | 70 raise KeyError(( |
72 u'Volume attribute object already set for volume attribute ' | 71 'Volume attribute object already set for volume attribute ' |
73 u'identifier: {0:s}.').format(attribute.identifier)) | 72 'identifier: {0:s}.').format(attribute.identifier)) |
74 | 73 |
75 self._attributes[attribute.identifier] = attribute | 74 self._attributes[attribute.identifier] = attribute |
76 | 75 |
77 @abc.abstractmethod | 76 @abc.abstractmethod |
78 def _Parse(self): | 77 def _Parse(self): |
79 """Extracts attributes and extents from the volume.""" | 78 """Extracts attributes and extents from the volume.""" |
80 | 79 |
81 @property | 80 @property |
82 def attributes(self): | 81 def attributes(self): |
83 """The attributes.""" | 82 """generator[VolumeAttribute]: volume attributes generator.""" |
84 if not self._is_parsed: | 83 if not self._is_parsed: |
85 self._Parse() | 84 self._Parse() |
86 self._is_parsed = True | 85 self._is_parsed = True |
87 | 86 |
88 return iter(self._attributes.values()) | 87 return iter(self._attributes.values()) |
89 | 88 |
90 @property | 89 @property |
91 def extents(self): | 90 def extents(self): |
92 """The extents.""" | 91 """list[VolumeExtent]: volume extents.""" |
93 if not self._is_parsed: | 92 if not self._is_parsed: |
94 self._Parse() | 93 self._Parse() |
95 self._is_parsed = True | 94 self._is_parsed = True |
96 | 95 |
97 return self._extents | 96 return self._extents |
98 | 97 |
99 @property | 98 @property |
100 def number_of_attributes(self): | 99 def number_of_attributes(self): |
101 """The number of attributes.""" | 100 """int: number of attributes.""" |
102 if not self._is_parsed: | 101 if not self._is_parsed: |
103 self._Parse() | 102 self._Parse() |
104 self._is_parsed = True | 103 self._is_parsed = True |
105 | 104 |
106 return len(self._attributes) | 105 return len(self._attributes) |
107 | 106 |
108 @property | 107 @property |
109 def number_of_extents(self): | 108 def number_of_extents(self): |
110 """The number of extents.""" | 109 """int: number of extents.""" |
111 if not self._is_parsed: | 110 if not self._is_parsed: |
112 self._Parse() | 111 self._Parse() |
113 self._is_parsed = True | 112 self._is_parsed = True |
114 | 113 |
115 return len(self._extents) | 114 return len(self._extents) |
116 | 115 |
117 def GetAttribute(self, identifier): | 116 def GetAttribute(self, identifier): |
118 """Retrieves a specific attribute. | 117 """Retrieves a specific attribute. |
119 | 118 |
120 Args: | 119 Args: |
121 identifier: the attribute identifier. | 120 identifier (str): identifier of the attribute within the volume. |
122 | 121 |
123 Returns: | 122 Returns: |
124 The volume attribute object (instance of VolumeAttribute) or None. | 123 VolumeAttribute: volume attribute or None if not available. |
125 """ | 124 """ |
126 if not self._is_parsed: | 125 if not self._is_parsed: |
127 self._Parse() | 126 self._Parse() |
128 self._is_parsed = True | 127 self._is_parsed = True |
129 | 128 |
130 if identifier not in self._attributes: | 129 if identifier not in self._attributes: |
131 return | 130 return |
132 | 131 |
133 return self._attributes[identifier] | 132 return self._attributes[identifier] |
134 | 133 |
135 def HasExternalData(self): | 134 def HasExternalData(self): |
136 """Determines if the volume has external stored data. | 135 """Determines if the volume has external stored data. |
137 | 136 |
138 Returns: | 137 Returns: |
139 A boolean to indicate the volume has external stored data. | 138 bool: True if the volume has external stored data. |
140 """ | 139 """ |
141 return False | 140 return False |
142 | 141 |
143 | 142 |
144 class VolumeSystem(object): | 143 class VolumeSystem(object): |
145 """The VFS volume system interface.""" | 144 """The VFS volume system interface.""" |
146 | 145 |
147 def __init__(self): | 146 def __init__(self): |
148 """Initializes the volume system object.""" | 147 """Initializes a volume system.""" |
149 super(VolumeSystem, self).__init__() | 148 super(VolumeSystem, self).__init__() |
150 self._is_parsed = False | 149 self._is_parsed = False |
151 self._sections = [] | 150 self._sections = [] |
152 self._volumes = {} | 151 self._volumes = {} |
153 self._volume_identifiers = [] | 152 self._volume_identifiers = [] |
154 | 153 |
155 def _AddVolume(self, volume): | 154 def _AddVolume(self, volume): |
156 """Adds a volume. | 155 """Adds a volume. |
157 | 156 |
158 Args: | 157 Args: |
159 volume: the volume object (instance of Volume). | 158 volume (Volume): a volume. |
160 | 159 |
161 Raises: | 160 Raises: |
162 KeyError: if volume is already set for the corresponding volume | 161 KeyError: if volume is already set for the corresponding volume |
163 identifier. | 162 identifier. |
164 """ | 163 """ |
165 if volume.identifier in self._volumes: | 164 if volume.identifier in self._volumes: |
166 raise KeyError( | 165 raise KeyError( |
167 u'Volume object already set for volume identifier: {0:s}'.format( | 166 'Volume object already set for volume identifier: {0:s}'.format( |
168 volume.identifier)) | 167 volume.identifier)) |
169 | 168 |
170 self._volumes[volume.identifier] = volume | 169 self._volumes[volume.identifier] = volume |
171 self._volume_identifiers.append(volume.identifier) | 170 self._volume_identifiers.append(volume.identifier) |
172 | 171 |
173 @abc.abstractmethod | 172 @abc.abstractmethod |
174 def _Parse(self): | 173 def _Parse(self): |
175 """Extracts sections and volumes from the volume system.""" | 174 """Extracts sections and volumes from the volume system.""" |
176 | 175 |
177 @property | 176 @property |
178 def number_of_sections(self): | 177 def number_of_sections(self): |
179 """The number of sections.""" | 178 """int: number of sections.""" |
180 if not self._is_parsed: | 179 if not self._is_parsed: |
181 self._Parse() | 180 self._Parse() |
182 self._is_parsed = True | 181 self._is_parsed = True |
183 | 182 |
184 return len(self._sections) | 183 return len(self._sections) |
185 | 184 |
186 @property | 185 @property |
187 def number_of_volumes(self): | 186 def number_of_volumes(self): |
188 """The number of volumes.""" | 187 """int: number of volumes.""" |
189 if not self._is_parsed: | 188 if not self._is_parsed: |
190 self._Parse() | 189 self._Parse() |
191 self._is_parsed = True | 190 self._is_parsed = True |
192 | 191 |
193 return len(self._volumes) | 192 return len(self._volumes) |
194 | 193 |
195 @property | 194 @property |
196 def sections(self): | 195 def sections(self): |
197 """The sections.""" | 196 """list[VolumeExtent]: sections.""" |
198 if not self._is_parsed: | 197 if not self._is_parsed: |
199 self._Parse() | 198 self._Parse() |
200 self._is_parsed = True | 199 self._is_parsed = True |
201 | 200 |
202 return self._sections | 201 return self._sections |
203 | 202 |
204 @property | 203 @property |
205 def volumes(self): | 204 def volumes(self): |
206 """The volumes.""" | 205 """generator(Volume): volumes generator.""" |
207 if not self._is_parsed: | 206 if not self._is_parsed: |
208 self._Parse() | 207 self._Parse() |
209 self._is_parsed = True | 208 self._is_parsed = True |
210 | 209 |
211 return iter(self._volumes.values()) | 210 return iter(self._volumes.values()) |
212 | 211 |
213 def GetSectionByIndex(self, section_index): | 212 def GetSectionByIndex(self, section_index): |
214 """Retrieves a specific section based on the index. | 213 """Retrieves a specific section based on the index. |
215 | 214 |
216 Args: | 215 Args: |
217 section_index: the index of the section. | 216 section_index (int): index of the section. |
| 217 |
| 218 Returns: |
| 219 VolumeExtent: a volume extent or None if not available. |
218 """ | 220 """ |
219 if not self._is_parsed: | 221 if not self._is_parsed: |
220 self._Parse() | 222 self._Parse() |
221 self._is_parsed = True | 223 self._is_parsed = True |
222 | 224 |
223 if section_index < 0 or section_index >= len(self._sections): | 225 if section_index >= 0 and section_index < len(self._sections): |
224 return | 226 return self._sections[section_index] |
225 return self._sections[section_index] | |
226 | 227 |
227 def GetVolumeByIdentifier(self, volume_identifier): | 228 def GetVolumeByIdentifier(self, volume_identifier): |
228 """Retrieves a specific volume based on the identifier. | 229 """Retrieves a specific volume based on the identifier. |
229 | 230 |
230 Args: | 231 Args: |
231 volume_identifier: string that uniquely identifies the volume within the | 232 volume_identifier (str): identifier of the volume within |
232 volume system. | 233 the volume system. |
233 | 234 |
234 Returns: | 235 Returns: |
235 The volume object (instance of Volume). | 236 Volume: a volume. |
236 """ | 237 """ |
237 if not self._is_parsed: | 238 if not self._is_parsed: |
238 self._Parse() | 239 self._Parse() |
239 self._is_parsed = True | 240 self._is_parsed = True |
240 | 241 |
241 return self._volumes[volume_identifier] | 242 return self._volumes[volume_identifier] |
242 | 243 |
243 def GetVolumeByIndex(self, volume_index): | 244 def GetVolumeByIndex(self, volume_index): |
244 """Retrieves a specific volume based on the index. | 245 """Retrieves a specific volume based on the index. |
245 | 246 |
246 Args: | 247 Args: |
247 volume_index: the index of the volume. | 248 volume_index (int): index of the volume. |
248 | 249 |
249 Returns: | 250 Returns: |
250 The volume object (instance of Volume). | 251 Volume: a volume or None if not available. |
251 """ | 252 """ |
252 if not self._is_parsed: | 253 if not self._is_parsed: |
253 self._Parse() | 254 self._Parse() |
254 self._is_parsed = True | 255 self._is_parsed = True |
255 | 256 |
256 if volume_index < 0 or volume_index >= len(self._volume_identifiers): | 257 if volume_index >= 0 and volume_index < len(self._volume_identifiers): |
257 return | 258 volume_identifier = self._volume_identifiers[volume_index] |
258 volume_identifier = self._volume_identifiers[volume_index] | 259 return self._volumes[volume_identifier] |
259 return self._volumes[volume_identifier] | |
260 | 260 |
261 @abc.abstractmethod | 261 @abc.abstractmethod |
262 def Open(self, path_spec): | 262 def Open(self, path_spec): |
263 """Opens a volume object defined by path specification. | 263 """Opens a volume defined by path specification. |
264 | 264 |
265 Args: | 265 Args: |
266 path_spec: the path specification (instance of PathSpec). | 266 path_spec (PathSpec): a path specification. |
267 """ | 267 """ |
OLD | NEW |