docs: Document video resolution config.
[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
2b4c339d 17import io
cf3b5926
BP
18import os
19import shutil
20
7ec69944 21import six.moves.urllib.parse as urlparse
cf3b5926 22
a2468d18
JW
23from mediagoblin.storage import (
24 StorageInterface,
25 clean_listy_filepath,
26 NoWebServing)
27
2b4c339d
BB
28class FileObjectAwareFile(io.FileIO):
29 def write(self, data):
30 if hasattr(data, 'read'):
31 # We can call data.read(). It means that the data is a file-like
32 # object, which should be saved RAM-friendly way
33 shutil.copyfileobj(data, self)
34 else:
35 super(FileObjectAwareFile, self).write(data)
36
a2468d18
JW
37
38class BasicFileStorage(StorageInterface):
39 """
40 Basic local filesystem implementation of storage API
41 """
42
43 local_storage = True
44
45 def __init__(self, base_dir, base_url=None, **kwargs):
46 """
47 Keyword arguments:
48 - base_dir: Base directory things will be served out of. MUST
49 be an absolute path.
50 - base_url: URL files will be served from
51 """
52 self.base_dir = base_dir
53 self.base_url = base_url
54
55 def _resolve_filepath(self, filepath):
56 """
57 Transform the given filepath into a local filesystem filepath.
58 """
59 return os.path.join(
60 self.base_dir, *clean_listy_filepath(filepath))
61
62 def file_exists(self, filepath):
63 return os.path.exists(self._resolve_filepath(filepath))
64
65 def get_file(self, filepath, mode='r'):
66 # Make directories if necessary
67 if len(filepath) > 1:
68 directory = self._resolve_filepath(filepath[:-1])
69 if not os.path.exists(directory):
70 os.makedirs(directory)
71
72 # Grab and return the file in the mode specified
2b4c339d 73 return FileObjectAwareFile(self._resolve_filepath(filepath), mode)
a2468d18
JW
74
75 def delete_file(self, filepath):
b34d7e1d
SS
76 """Delete file at filepath
77
78 Raises OSError in case filepath is a directory."""
79 #TODO: log error
a2468d18
JW
80 os.remove(self._resolve_filepath(filepath))
81
b34d7e1d
SS
82 def delete_dir(self, dirpath, recursive=False):
83 """returns True on succes, False on failure"""
84
85 dirpath = self._resolve_filepath(dirpath)
86
87 # Shortcut the default and simple case of nonempty=F, recursive=F
88 if recursive:
89 try:
90 shutil.rmtree(dirpath)
91 except OSError as e:
92 #TODO: log something here
93 return False
94 else: # recursively delete everything
95 try:
96 os.rmdir(dirpath)
97 except OSError as e:
98 #TODO: log something here
99 return False
100 return True
101
a2468d18
JW
102 def file_url(self, filepath):
103 if not self.base_url:
104 raise NoWebServing(
105 "base_url not set, cannot provide file urls")
106
107 return urlparse.urljoin(
108 self.base_url,
109 '/'.join(clean_listy_filepath(filepath)))
110
111 def get_local_path(self, filepath):
112 return self._resolve_filepath(filepath)
98f6efb0
CAW
113
114 def copy_local_to_storage(self, filename, filepath):
115 """
116 Copy this file from locally to the storage system.
117 """
118 # Make directories if necessary
119 if len(filepath) > 1:
120 directory = self._resolve_filepath(filepath[:-1])
121 if not os.path.exists(directory):
122 os.makedirs(directory)
99a54c00
SS
123 # This uses chunked copying of 16kb buffers (Py2.7):
124 shutil.copy(filename, self.get_local_path(filepath))
bdd22421
RE
125
126 def get_file_size(self, filepath):
127 return os.stat(self._resolve_filepath(filepath)).st_size