Merge remote-tracking branch 'remotes/bretts/bug261-resized-filenames'
[mediagoblin.git] / mediagoblin / processing / __init__.py
CommitLineData
41f446f4 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
41f446f4
CAW
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
64da09e8 17import logging
095fbdaf 18import os
64da09e8 19
eace050a 20from mediagoblin.db.util import atomic_update
4a477e24 21from mediagoblin import mg_globals as mgg
8e5f9746 22
6506b1e2 23from mediagoblin.tools.translate import lazy_pass_to_ugettext as _
8e5f9746 24
64da09e8 25_log = logging.getLogger(__name__)
41f446f4 26
24eaf0fd 27THUMB_SIZE = 180, 180
93214d8e 28MEDIUM_SIZE = 640, 640
41f446f4
CAW
29
30
180bdbde 31def create_pub_filepath(entry, filename):
48a7ba1e 32 return mgg.public_store.get_unique_filepath(
180bdbde 33 ['media_entries',
eabe6b67 34 unicode(entry._id),
180bdbde
E
35 filename])
36
28f364bd 37class FilenameBuilder(object):
4774cfa3
BS
38 """Easily slice and dice filenames.
39
28f364bd 40 Initialize this class with an original file path, then use the fill()
4774cfa3
BS
41 method to create new filenames based on the original.
42
43 """
44 MAX_FILENAME_LENGTH = 255 # VFAT's maximum filename length
095fbdaf
BS
45
46 def __init__(self, path):
28f364bd 47 """Initialize a builder from an original file path."""
095fbdaf
BS
48 self.dirpath, self.basename = os.path.split(path)
49 self.basename, self.ext = os.path.splitext(self.basename)
50 self.ext = self.ext.lower()
51
28f364bd
BS
52 def fill(self, fmtstr):
53 """Build a new filename based on the original.
4774cfa3 54
28f364bd
BS
55 The fmtstr argument can include the following:
56 {basename} -- the original basename, with the extension removed
57 {ext} -- the original extension, always lowercase
58
59 If necessary, {basename} will be truncated so the filename does not
60 exceed this class' MAX_FILENAME_LENGTH in length.
4774cfa3
BS
61
62 """
095fbdaf
BS
63 basename_len = (self.MAX_FILENAME_LENGTH -
64 len(fmtstr.format(basename='', ext=self.ext)))
65 return fmtstr.format(basename=self.basename[:basename_len],
66 ext=self.ext)
67
68
6788b412 69def mark_entry_failed(entry_id, exc):
2e5ea6b9
CAW
70 """
71 Mark a media entry as having failed in its conversion.
72
243c3843
NY
73 Uses the exception that was raised to mark more information. If
74 the exception is a derivative of BaseProcessingFail then we can
75 store extra information that can be useful for users telling them
76 why their media failed to process.
2e5ea6b9
CAW
77
78 Args:
79 - entry_id: The id of the media entry
80
81 """
6788b412
CAW
82 # Was this a BaseProcessingFail? In other words, was this a
83 # type of error that we know how to handle?
84 if isinstance(exc, BaseProcessingFail):
85 # Looks like yes, so record information about that failure and any
86 # metadata the user might have supplied.
82cd9683 87 atomic_update(mgg.database.MediaEntry,
6788b412 88 {'_id': entry_id},
82cd9683
E
89 {u'state': u'failed',
90 u'fail_error': exc.exception_path,
91 u'fail_metadata': exc.metadata})
6788b412 92 else:
baae1578 93 _log.warn("No idea what happened here, but it failed: %r", exc)
6788b412
CAW
94 # Looks like no, so just mark it as failed and don't record a
95 # failure_error (we'll assume it wasn't handled) and don't record
96 # metadata (in fact overwrite it if somehow it had previous info
97 # here)
82cd9683 98 atomic_update(mgg.database.MediaEntry,
6788b412 99 {'_id': entry_id},
82cd9683
E
100 {u'state': u'failed',
101 u'fail_error': None,
102 u'fail_metadata': {}})
4a477e24
CAW
103
104
8e5f9746
JW
105class BaseProcessingFail(Exception):
106 """
107 Base exception that all other processing failure messages should
108 subclass from.
109
110 You shouldn't call this itself; instead you should subclass it
111 and provid the exception_path and general_message applicable to
112 this error.
113 """
114 general_message = u''
115
116 @property
117 def exception_path(self):
118 return u"%s:%s" % (
119 self.__class__.__module__, self.__class__.__name__)
120
121 def __init__(self, **metadata):
122 self.metadata = metadata or {}
123
124
125class BadMediaFail(BaseProcessingFail):
4a477e24 126 """
8e5f9746
JW
127 Error that should be raised when an inappropriate file was given
128 for the media type specified.
4a477e24 129 """
8e5f9746 130 general_message = _(u'Invalid file given for media type.')