1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # Actual workbench stuff
23 # ----------------------
25 class Workbench(object):
27 Represent the directory for the workbench
29 WARNING: DO NOT create Workbench objects on your own,
30 let the WorkbenchManager do that for you!
32 def __init__(self
, dir):
34 WARNING: DO NOT create Workbench objects on your own,
35 let the WorkbenchManager do that for you!
39 def __unicode__(self
):
40 return unicode(self
.dir)
48 except AttributeError:
51 def joinpath(self
, *args
):
52 return os
.path
.join(self
.dir, *args
)
54 def localized_file(self
, storage
, filepath
,
55 filename_if_copying
=None,
56 keep_extension_if_copying
=True):
58 Possibly localize the file from this storage system (for read-only
59 purposes, modifications should be written to a new file.).
61 If the file is already local, just return the absolute filename of that
62 local file. Otherwise, copy the file locally to the workbench, and
63 return the absolute path of the new file.
65 If it is copying locally, we might want to require a filename like
66 "source.jpg" to ensure that we won't conflict with other filenames in
67 our workbench... if that's the case, make sure filename_if_copying is
68 set to something like 'source.jpg'. Relatedly, if you set
69 keep_extension_if_copying, you don't have to set an extension on
70 filename_if_copying yourself, it'll be set for you (assuming such an
71 extension can be extacted from the filename in the filepath).
77 >>> wb_manager.localized_file(
78 ... '/our/workbench/subdir', local_storage,
79 ... ['path', 'to', 'foobar.jpg'])
80 u'/local/storage/path/to/foobar.jpg'
82 >>> wb_manager.localized_file(
83 ... '/our/workbench/subdir', remote_storage,
84 ... ['path', 'to', 'foobar.jpg'])
85 '/our/workbench/subdir/foobar.jpg'
87 >>> wb_manager.localized_file(
88 ... '/our/workbench/subdir', remote_storage,
89 ... ['path', 'to', 'foobar.jpg'], 'source.jpeg', False)
90 '/our/workbench/subdir/foobar.jpeg'
92 >>> wb_manager.localized_file(
93 ... '/our/workbench/subdir', remote_storage,
94 ... ['path', 'to', 'foobar.jpg'], 'source', True)
95 '/our/workbench/subdir/foobar.jpg'
97 if storage
.local_storage
:
98 return storage
.get_local_path(filepath
)
100 if filename_if_copying
is None:
101 dest_filename
= filepath
[-1]
103 orig_filename
, orig_ext
= os
.path
.splitext(filepath
[-1])
104 if keep_extension_if_copying
and orig_ext
:
105 dest_filename
= filename_if_copying
+ orig_ext
107 dest_filename
= filename_if_copying
109 full_dest_filename
= os
.path
.join(
110 self
.dir, dest_filename
)
113 storage
.copy_locally(
114 filepath
, full_dest_filename
)
116 return full_dest_filename
120 Destroy this workbench! Deletes the directory and all its contents!
122 WARNING: Does no checks for a sane value in self.dir!
125 workbench
= os
.path
.abspath(self
.dir)
126 shutil
.rmtree(workbench
)
130 """Make Workbench a context manager so we can use `with Workbench() as bench:`"""
133 def __exit__(self
, *args
):
134 """Clean up context manager, aka ourselves, deleting the workbench"""
138 class WorkbenchManager(object):
140 A system for generating and destroying workbenches.
142 Workbenches are actually just subdirectories of a (local) temporary
143 storage space for during the processing stage. The preferred way to
144 create them is to use:
146 with workbenchmger.create() as workbench:
149 This will automatically clean up all temporary directories even in
150 case of an exceptions. Also check the
151 @mediagoblin.decorators.get_workbench decorator for a convenient
155 def __init__(self
, base_workbench_dir
):
156 self
.base_workbench_dir
= os
.path
.abspath(base_workbench_dir
)
157 if not os
.path
.exists(self
.base_workbench_dir
):
158 os
.makedirs(self
.base_workbench_dir
)
162 Create and return the path to a new workbench (directory).
164 return Workbench(tempfile
.mkdtemp(dir=self
.base_workbench_dir
))