Commit | Line | Data |
---|---|---|
41f446f4 | 1 | # GNU MediaGoblin -- federated, autonomous media hosting |
12a100e4 | 2 | # Copyright (C) 2011 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 | ||
2e5ea6b9 | 17 | from celery.task import Task |
41f446f4 | 18 | |
4a477e24 CAW |
19 | from mediagoblin.db.util import ObjectId |
20 | from mediagoblin import mg_globals as mgg | |
8e5f9746 | 21 | |
6506b1e2 | 22 | from mediagoblin.tools.translate import lazy_pass_to_ugettext as _ |
8e5f9746 JW |
23 | |
24 | from mediagoblin.media_types import get_media_manager | |
4b860cb8 | 25 | |
41f446f4 | 26 | |
24eaf0fd | 27 | THUMB_SIZE = 180, 180 |
93214d8e | 28 | MEDIUM_SIZE = 640, 640 |
41f446f4 CAW |
29 | |
30 | ||
180bdbde | 31 | def 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 | ||
4a477e24 | 37 | |
4a477e24 CAW |
38 | ################################ |
39 | # Media processing initial steps | |
40 | ################################ | |
41 | ||
42 | class ProcessMedia(Task): | |
43 | """ | |
8e5f9746 JW |
44 | DEPRECATED -- This now resides in the individual media plugins |
45 | ||
4a477e24 CAW |
46 | Pass this entry off for processing. |
47 | """ | |
48 | def run(self, media_id): | |
49 | """ | |
50 | Pass the media entry off to the appropriate processing function | |
51 | (for now just process_image...) | |
52 | """ | |
53 | entry = mgg.database.MediaEntry.one( | |
54 | {'_id': ObjectId(media_id)}) | |
6788b412 CAW |
55 | |
56 | # Try to process, and handle expected errors. | |
57 | try: | |
f4ee8399 E |
58 | #__import__(entry.media_type) |
59 | manager = get_media_manager(entry.media_type) | |
8e5f9746 | 60 | manager['processor'](entry) |
6788b412 | 61 | except BaseProcessingFail, exc: |
eabe6b67 | 62 | mark_entry_failed(entry._id, exc) |
6788b412 | 63 | return |
a63b640f JW |
64 | except ImportError, exc: |
65 | mark_entry_failed(entry[u'_id'], exc) | |
c2b862d1 | 66 | |
049284b1 | 67 | entry.state = u'processed' |
4a477e24 CAW |
68 | entry.save() |
69 | ||
70 | def on_failure(self, exc, task_id, args, kwargs, einfo): | |
71 | """ | |
72 | If the processing failed we should mark that in the database. | |
73 | ||
243c3843 NY |
74 | Assuming that the exception raised is a subclass of |
75 | BaseProcessingFail, we can use that to get more information | |
76 | about the failure and store that for conveying information to | |
77 | users about the failure, etc. | |
4a477e24 | 78 | """ |
6788b412 CAW |
79 | entry_id = args[0] |
80 | mark_entry_failed(entry_id, exc) | |
4a477e24 | 81 | |
4a477e24 | 82 | |
6788b412 | 83 | def mark_entry_failed(entry_id, exc): |
2e5ea6b9 CAW |
84 | """ |
85 | Mark a media entry as having failed in its conversion. | |
86 | ||
243c3843 NY |
87 | Uses the exception that was raised to mark more information. If |
88 | the exception is a derivative of BaseProcessingFail then we can | |
89 | store extra information that can be useful for users telling them | |
90 | why their media failed to process. | |
2e5ea6b9 CAW |
91 | |
92 | Args: | |
93 | - entry_id: The id of the media entry | |
94 | ||
95 | """ | |
6788b412 CAW |
96 | # Was this a BaseProcessingFail? In other words, was this a |
97 | # type of error that we know how to handle? | |
98 | if isinstance(exc, BaseProcessingFail): | |
99 | # Looks like yes, so record information about that failure and any | |
100 | # metadata the user might have supplied. | |
101 | mgg.database['media_entries'].update( | |
102 | {'_id': entry_id}, | |
103 | {'$set': {u'state': u'failed', | |
104 | u'fail_error': exc.exception_path, | |
105 | u'fail_metadata': exc.metadata}}) | |
106 | else: | |
107 | # Looks like no, so just mark it as failed and don't record a | |
108 | # failure_error (we'll assume it wasn't handled) and don't record | |
109 | # metadata (in fact overwrite it if somehow it had previous info | |
110 | # here) | |
111 | mgg.database['media_entries'].update( | |
112 | {'_id': entry_id}, | |
113 | {'$set': {u'state': u'failed', | |
114 | u'fail_error': None, | |
115 | u'fail_metadata': {}}}) | |
4a477e24 CAW |
116 | |
117 | ||
8e5f9746 JW |
118 | class BaseProcessingFail(Exception): |
119 | """ | |
120 | Base exception that all other processing failure messages should | |
121 | subclass from. | |
122 | ||
123 | You shouldn't call this itself; instead you should subclass it | |
124 | and provid the exception_path and general_message applicable to | |
125 | this error. | |
126 | """ | |
127 | general_message = u'' | |
128 | ||
129 | @property | |
130 | def exception_path(self): | |
131 | return u"%s:%s" % ( | |
132 | self.__class__.__module__, self.__class__.__name__) | |
133 | ||
134 | def __init__(self, **metadata): | |
135 | self.metadata = metadata or {} | |
136 | ||
137 | ||
138 | class BadMediaFail(BaseProcessingFail): | |
4a477e24 | 139 | """ |
8e5f9746 JW |
140 | Error that should be raised when an inappropriate file was given |
141 | for the media type specified. | |
4a477e24 | 142 | """ |
8e5f9746 | 143 | general_message = _(u'Invalid file given for media type.') |