Add a modify_request hook
[mediagoblin.git] / mediagoblin / storage / filestorage.py
CommitLineData
a2468d18 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
a2468d18
JW
3#
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.
8#
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.
13#
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/>.
16
17from mediagoblin.storage import (
18 StorageInterface,
19 clean_listy_filepath,
20 NoWebServing)
21
22import os
98f6efb0 23import shutil
a2468d18
JW
24import urlparse
25
26
27class BasicFileStorage(StorageInterface):
28 """
29 Basic local filesystem implementation of storage API
30 """
31
32 local_storage = True
33
34 def __init__(self, base_dir, base_url=None, **kwargs):
35 """
36 Keyword arguments:
37 - base_dir: Base directory things will be served out of. MUST
38 be an absolute path.
39 - base_url: URL files will be served from
40 """
41 self.base_dir = base_dir
42 self.base_url = base_url
43
44 def _resolve_filepath(self, filepath):
45 """
46 Transform the given filepath into a local filesystem filepath.
47 """
48 return os.path.join(
49 self.base_dir, *clean_listy_filepath(filepath))
50
51 def file_exists(self, filepath):
52 return os.path.exists(self._resolve_filepath(filepath))
53
54 def get_file(self, filepath, mode='r'):
55 # Make directories if necessary
56 if len(filepath) > 1:
57 directory = self._resolve_filepath(filepath[:-1])
58 if not os.path.exists(directory):
59 os.makedirs(directory)
60
61 # Grab and return the file in the mode specified
62 return open(self._resolve_filepath(filepath), mode)
63
64 def delete_file(self, filepath):
b34d7e1d
SS
65 """Delete file at filepath
66
67 Raises OSError in case filepath is a directory."""
68 #TODO: log error
a2468d18
JW
69 os.remove(self._resolve_filepath(filepath))
70
b34d7e1d
SS
71 def delete_dir(self, dirpath, recursive=False):
72 """returns True on succes, False on failure"""
73
74 dirpath = self._resolve_filepath(dirpath)
75
76 # Shortcut the default and simple case of nonempty=F, recursive=F
77 if recursive:
78 try:
79 shutil.rmtree(dirpath)
80 except OSError as e:
81 #TODO: log something here
82 return False
83 else: # recursively delete everything
84 try:
85 os.rmdir(dirpath)
86 except OSError as e:
87 #TODO: log something here
88 return False
89 return True
90
a2468d18
JW
91 def file_url(self, filepath):
92 if not self.base_url:
93 raise NoWebServing(
94 "base_url not set, cannot provide file urls")
95
96 return urlparse.urljoin(
97 self.base_url,
98 '/'.join(clean_listy_filepath(filepath)))
99
100 def get_local_path(self, filepath):
101 return self._resolve_filepath(filepath)
98f6efb0
CAW
102
103 def copy_local_to_storage(self, filename, filepath):
104 """
105 Copy this file from locally to the storage system.
106 """
107 # Make directories if necessary
108 if len(filepath) > 1:
109 directory = self._resolve_filepath(filepath[:-1])
110 if not os.path.exists(directory):
111 os.makedirs(directory)
99a54c00
SS
112 # This uses chunked copying of 16kb buffers (Py2.7):
113 shutil.copy(filename, self.get_local_path(filepath))
bdd22421
RE
114
115 def get_file_size(self, filepath):
116 return os.stat(self._resolve_filepath(filepath)).st_size