1
2
3 __all__ = ['FilesystemStorage']
4
5 try:
6 from glob import iglob as glob
7 from glob import iglob
8 except ImportError:
9 from glob import glob
10
11 import os, os.path
12 import threading
13
14 from amplee.storage import Storage, StorageResourceInfo
15 from amplee.error import UnknownResource
16 from amplee.utils import safe_path_join
17
19 - def __init__(self, storage_path, enable_lock=False, encoding='utf-8'):
20 """
21 Simple filesystem storage for amplee.
22
23 If storage path does not exist, it is created.
24
25 When the locking is enabled it creates a threading.Lock instance
26 which is used for writing operations (put and remove).
27
28 Keyword arguments
29 storage_path -- absolute path to the top level directory which will contain
30 collections and resources
31 enable_lock -- if True, thread locking will be enabled during write operations
32 encoding -- used to encode the path elements
33 """
34 self.storage_path = storage_path
35 if not os.path.exists(self.storage_path):
36 os.mkdir(self.storage_path)
37 self.encoding = encoding
38 self.enable_lock = enable_lock
39 if enable_lock:
40 self.lock = threading.Lock()
41
43 """
44 Shutdown the storage.
45 Does nothing effectively.
46 """
47 pass
48
50 """
51 Creates a subdirectory within the storage directory
52 If it already exists does nothing.
53
54 Keyword argument
55 collection_name -- name of the directory to create
56 """
57 info = self.info(collection_name)
58 if not os.path.exists(info.key):
59 os.makedirs(info.key)
60
61 - def info(self, collection_name, resource_name=None):
62 """
63 Returns a StorageResourceInfo which ``key``
64 attribute is set to the absolute path to the
65 given resource or, if not provided, to the
66 collection directory.
67 """
68 p = safe_path_join(self.storage_path, collection_name,
69 resource_name)
70 return StorageResourceInfo(resource_name, p, collection_name)
71
72 - def get_content(self, info):
73 """
74 Returns the content as a string of the resource found at 'info.key'.
75 If no resource could be found,
76 an amplee.error.UnknownResource is raised.
77
78 Keyword arguments
79 info -- Path to the resource as returned by info()
80 """
81 if os.path.exists(info.key):
82 resource = file(info.key, 'rb')
83 content = resource.read()
84 resource.close()
85 return content
86
87 raise UnknownResource(info.name)
88
99
100 - def put_content(self, info, content, **kwargs):
101 """
102 Set the content at 'info' of the resource.
103
104 Keyword arguments
105 info -- Path to the resource as returned by info()
106
107 content -- data as a string object or a file object.
108 In the latter case read() MUST return the full content
109 as a byte string.
110 """
111 if hasattr(content, 'read'):
112 content = content.read()
113
114 try:
115 if self.enable_lock:
116 self.lock.acquire()
117 resource = file(info.key, 'wb')
118 resource.write(content)
119 resource.close()
120 finally:
121 if self.enable_lock:
122 self.lock.release()
123
136
137 - def remove_content(self, info):
138 """
139 Remove the resource at 'info'
140
141 Keyword arguments
142 info -- Path to the resource as returned by info()
143 """
144 try:
145 if self.enable_lock:
146 self.lock.acquire()
147 if os.path.exists(info.key):
148 try:
149 os.unlink(info.key)
150 except OSError:
151 pass
152 finally:
153 if self.enable_lock:
154 self.lock.release()
155
164
165 - def persist(self, *args, **kwargs):
166 """
167 Does nothing in the filesystem storage
168 """
169 pass
170
172 """
173 Returns True if the resource at 'info.key' exists. False otherwise.
174
175 Keyword arguments
176 info -- Path to the resource as returned by info()
177 """
178 return os.path.exists(info.key)
179
180 - def ls(self, collection_name, ext=None):
181 """
182 List all the existing resources of a collection
183 Returns a dictionary like this:
184
185 members[basename(abs_path)] = StorageResourceInfo
186
187 Keyword arguments
188 collection_name -- name of the collection
189 """
190 self.create_container(collection_name)
191 info = self.info(collection_name)
192 results = glob('%s/*' % (info.key, ))
193 members = {}
194
195 for result in results:
196 basename = os.path.basename(result).decode('utf-8')
197 if ext:
198 if basename.endswith(ext):
199 members[basename] = StorageResourceInfo(basename, result, collection_name)
200 else:
201 members[basename] = StorageResourceInfo(basename, result, collection_name)
202
203 return members
204
205 - def ils(self, collection_name, ext=None):
206 """
207 Yield members matching the parameters.
208
209 Keyword arguments
210 collection_name -- name of the collection
211 """
212 info = self.info(collection_name)
213 results = iglob('%s/*' % (info.key, ))
214
215 for result in results:
216 basename = os.path.basename(result).decode('utf-8')
217 if ext:
218 if basename.endswith(ext):
219 yield basename, StorageResourceInfo(basename, result, collection_name)
220 else:
221 yield basename, StorageResourceInfo(basename, result, collection_name)
222
223 raise StopIteration()
224