diff options
-rw-r--r-- | MANIFEST.in | 10 | ||||
-rw-r--r-- | mediagoblin/db/models.py | 1 | ||||
-rw-r--r-- | mediagoblin/media_types/video/transcoders.py | 37 | ||||
-rw-r--r-- | mediagoblin/plugins/api/tools.py | 3 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/base.html | 25 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/gallery.html | 26 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/user_pages/media_collect.html | 11 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/utils/tags.html | 16 | ||||
-rw-r--r-- | mediagoblin/templates/mediagoblin/utils/wtforms.html | 2 | ||||
-rw-r--r-- | mediagoblin/tests/test_misc.py | 15 | ||||
-rw-r--r-- | mediagoblin/tools/files.py | 2 | ||||
-rw-r--r-- | mediagoblin/tools/template.py | 2 | ||||
-rw-r--r-- | mediagoblin/user_pages/routing.py | 5 | ||||
-rw-r--r-- | mediagoblin/user_pages/views.py | 38 |
14 files changed, 136 insertions, 57 deletions
diff --git a/MANIFEST.in b/MANIFEST.in index b3ae7b75..0a39ce84 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,7 +1,11 @@ recursive-include mediagoblin/i18n *.mo -recursive-include mediagoblin/templates *.html *.txt *.xml -recursive-include mediagoblin/static *.js *.css *.png *.svg *.ico -recursive-include mediagoblin/tests *.ini +recursive-include mediagoblin *.js *.css *.png *.svg *.ico +recursive-include mediagoblin *.ini +recursive-include mediagoblin *.html *.txt recursive-include docs *.rst *.html +include mediagoblin.ini mediagoblin/config_spec.ini paste.ini include mediagoblin/config_spec.ini graft extlib +graft licenses +include COPYING AUTHORS +include lazyserver.sh lazystarter.sh lazycelery.sh diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py index 10e0c33f..2f58503f 100644 --- a/mediagoblin/db/models.py +++ b/mediagoblin/db/models.py @@ -145,6 +145,7 @@ class MediaEntry(Base, MediaEntryMixin): ) attachment_files_helper = relationship("MediaAttachmentFile", + cascade="all, delete-orphan", order_by="MediaAttachmentFile.created" ) attachment_files = association_proxy("attachment_files_helper", "dict_view", diff --git a/mediagoblin/media_types/video/transcoders.py b/mediagoblin/media_types/video/transcoders.py index 152de288..3a6a1c4d 100644 --- a/mediagoblin/media_types/video/transcoders.py +++ b/mediagoblin/media_types/video/transcoders.py @@ -477,8 +477,8 @@ from playbin') _log.debug('thumbnail message: {0}'.format(message)) if message.type == gst.MESSAGE_ERROR: - _log.error('thumbnail error: {0}'.format(message)) - gobject.idle_add(self.on_thumbnail_error) + _log.error('thumbnail error: {0}'.format(message.parse_error())) + gobject.idle_add(self.on_thumbnail_error, message) if message.type == gst.MESSAGE_STATE_CHANGED: prev_state, cur_state, pending_state = \ @@ -570,10 +570,37 @@ pending: {2}'.format( return False - def on_thumbnail_error(self): - _log.error('Thumbnailing failed.') + def on_thumbnail_error(self, message): + scaling_failed = False + + if 'Error calculating the output scaled size - integer overflow' \ + in message.parse_error()[1]: + # GStreamer videoscale sometimes fails to calculate the dimensions + # given only one of the destination dimensions and the source + # dimensions. This is a workaround in case videoscale returns an + # error that indicates this has happened. + scaling_failed = True + _log.error('Thumbnailing failed because of videoscale integer' + ' overflow. Will retry with fallback.') + else: + _log.error('Thumbnailing failed: {0}'.format(message.parse_error())) + + # Kill the current mainloop self.disconnect() + if scaling_failed: + # Manually scale the destination dimensions + _log.info('Retrying with manually set sizes...') + + info = VideoTranscoder().discover(self.source_path) + + h = info['videoheight'] + w = info['videowidth'] + ratio = 180 / int(w) + h = int(h * ratio) + + self.__init__(self.source_path, self.dest_path, 180, h) + def disconnect(self): self.state = self.STATE_HALTING @@ -1007,4 +1034,4 @@ if __name__ == '__main__': print('I\'m a callback!') transcoder.transcode(*args, progress_callback=cb) elif options.action == 'discover': - print transcoder.discover(*args).__dict__ + print transcoder.discover(*args) diff --git a/mediagoblin/plugins/api/tools.py b/mediagoblin/plugins/api/tools.py index e5878258..92411f4b 100644 --- a/mediagoblin/plugins/api/tools.py +++ b/mediagoblin/plugins/api/tools.py @@ -69,7 +69,8 @@ def json_response(serializable, _disable_cors=False, *args, **kw): 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With'} - (response.headers.set(key, value) for key, value in cors_headers) + for key, value in cors_headers.iteritems(): + response.headers.set(key, value) return response diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html index 34986fdb..5db8bf0f 100644 --- a/mediagoblin/templates/mediagoblin/base.html +++ b/mediagoblin/templates/mediagoblin/base.html @@ -48,7 +48,7 @@ {%- include "mediagoblin/bits/logo.html" -%} {% block mediagoblin_header_title %}{% endblock %} <div class="header_right"> - {% if request.user %} + {%- if request.user %} {% if request.user and request.user.status == 'active' %} <div class="button_action header_dropdown_down">▼</div> <div class="button_action header_dropdown_up">▲</div> @@ -60,11 +60,12 @@ {% trans %}Verify your email!{% endtrans %}</a> or <a href="{{ request.urlgen('mediagoblin.auth.logout') }}">{% trans %}log out{% endtrans %}</a> {% endif %} - {% else %} + {%- else %} <a href="{{ request.urlgen('mediagoblin.auth.login') }}?next={{ request.base_url|urlencode }}"> - {% trans %}Log in{% endtrans %}</a> - {% endif %} + {%- trans %}Log in{% endtrans -%} + </a> + {%- endif %} </div> <div class="clear"></div> {% if request.user and request.user.status == 'active' %} @@ -107,23 +108,23 @@ {% endif %} </header> {% endblock %} - <div class="container"> - <div class="mediagoblin_content"> + <div class="container"> + <div class="mediagoblin_content"> {% include "mediagoblin/utils/messages.html" %} {% block mediagoblin_content %} {% endblock mediagoblin_content %} - </div> - {% block mediagoblin_footer %} + </div> + {%- block mediagoblin_footer %} <footer> {% trans -%} - Powered by <a href="http://mediagoblin.org">MediaGoblin</a>, a <a href="http://gnu.org/">GNU</a> project. + Powered by <a href="http://mediagoblin.org/" title='Version {{ version }}'>MediaGoblin</a>, a <a href="http://gnu.org/">GNU</a> project. {%- endtrans %} {% trans source_link=app_config['source_link'] -%} Released under the <a href="http://www.fsf.org/licensing/licenses/agpl-3.0.html">AGPL</a>. <a href="{{ source_link }}">Source code</a> available. {%- endtrans %} </footer> - {% endblock mediagoblin_footer %} - {% endblock mediagoblin_body %} - </div> + {%- endblock mediagoblin_footer %} + </div> + {%- endblock mediagoblin_body %} </body> </html> diff --git a/mediagoblin/templates/mediagoblin/user_pages/gallery.html b/mediagoblin/templates/mediagoblin/user_pages/gallery.html index e234914f..f23bb156 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/gallery.html +++ b/mediagoblin/templates/mediagoblin/user_pages/gallery.html @@ -34,16 +34,28 @@ {% block mediagoblin_content -%} <h1> - {%- trans username=user.username, - user_url=request.urlgen( - 'mediagoblin.user_pages.user_home', - user=user.username) -%} - <a href="{{ user_url }}">{{ username }}</a>'s media - {%- endtrans %} + {% if tag %} + {%- trans username=user.username, + user_url=request.urlgen( + 'mediagoblin.user_pages.user_home', + user=user.username), + tag_url=request.urlgen( + 'mediagoblin.listings.tags_listing', + tag=tag) -%} + <a href="{{ user_url }}">{{ username }}</a>'s media with tag <a href="{{ tag_url }}">{{ tag }}</a> + {%- endtrans %} + {% else %} + {%- trans username=user.username, + user_url=request.urlgen( + 'mediagoblin.user_pages.user_home', + user=user.username) -%} + <a href="{{ user_url }}">{{ username }}</a>'s media + {%- endtrans %} + {% endif %} </h1> {{ object_gallery(request, media_entries, pagination) }} - + {% set feed_url = request.urlgen('mediagoblin.user_pages.atom_feed', user=user.username) %} {% include "mediagoblin/utils/feed_link.html" %} diff --git a/mediagoblin/templates/mediagoblin/user_pages/media_collect.html b/mediagoblin/templates/mediagoblin/user_pages/media_collect.html index 8cdb64fe..8b19e8c0 100644 --- a/mediagoblin/templates/mediagoblin/user_pages/media_collect.html +++ b/mediagoblin/templates/mediagoblin/user_pages/media_collect.html @@ -57,8 +57,7 @@ </div> <div id="new_collection" class="subform"> - - <h3>{% trans %}Add a new collection{% endtrans %}</h3> + <h3>{% trans %}Add a new collection{% endtrans %}</h3> <p class="form_field_label"> <label for="{{ (form.collection_title.name) }}">{{ _(form.collection_title.label.text) }}</label> @@ -66,13 +65,7 @@ <div class="form_field_input"> {{ form.collection_title }} </div> - <p class="form_field_label"> - <label for="{{ (form.collection_description.name) }}">{{ _(form.collection_description.label.text) }}</label> - </p> - <div class="form_field_input"> - {{ form.collection_description }} - </div> - + {{- wtforms_util.render_field_div(form.collection_description) }} </div> <p class="form_field_label"> <label for="{{ (form.note.name) }}">{{ _(form.note.label.text) }}</label> diff --git a/mediagoblin/templates/mediagoblin/utils/tags.html b/mediagoblin/templates/mediagoblin/utils/tags.html index 0127035c..bb4bd1a5 100644 --- a/mediagoblin/templates/mediagoblin/utils/tags.html +++ b/mediagoblin/templates/mediagoblin/utils/tags.html @@ -26,16 +26,20 @@ · {% endif %} <a href="{{ request.urlgen( - 'mediagoblin.listings.tags_listing', - tag=tag['slug']) }}">{{ tag['name'] }}</a> + 'mediagoblin.user_pages.user_tag_gallery', + tag=tag['slug'], + user=media.get_uploader.username) }}">{{ tag['name'] }}</a> {% elif loop.revindex == 2 %} <a href="{{ request.urlgen( - 'mediagoblin.listings.tags_listing', - tag=tag['slug']) }}">{{ tag['name'] }}</a> + 'mediagoblin.user_pages.user_tag_gallery', + tag=tag['slug'], + user=media.get_uploader.username) }}">{{ tag['name'] }}</a> {% else %} <a href="{{ request.urlgen( - 'mediagoblin.listings.tags_listing', - tag=tag['slug']) }}">{{ tag['name'] }}</a> · + 'mediagoblin.user_pages.user_tag_gallery', + tag=tag['slug'], + user=media.get_uploader.username) }}">{{ tag['name'] }}</a> + · {% endif %} {% endfor %} </p> diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html index 58ecb8e0..df2354ed 100644 --- a/mediagoblin/templates/mediagoblin/utils/wtforms.html +++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html @@ -28,7 +28,7 @@ <p class="form_field_error">{{ _(error) }}</p> {% endfor %} {%- endif %} - {% if field.description -%} + {%- if field.description %} <p class="form_field_description">{{ _(field.description)|safe }}</p> {%- endif %} </div> diff --git a/mediagoblin/tests/test_misc.py b/mediagoblin/tests/test_misc.py index b48b8762..776affc6 100644 --- a/mediagoblin/tests/test_misc.py +++ b/mediagoblin/tests/test_misc.py @@ -78,3 +78,18 @@ def test_user_deletes_other_comments(): assert_equal(med_cnt2, med_cnt1 - 2) # All comments gone assert_equal(cmt_cnt2, cmt_cnt1 - 4) + + +def test_media_deletes_broken_attachment(): + user_a = fixture_add_user(u"chris_a") + + media = fixture_media_entry(uploader=user_a.id, save=False) + media.attachment_files.append(dict( + name=u"some name", + filepath=[u"does", u"not", u"exist"], + )) + Session.add(media) + Session.flush() + + MediaEntry.query.get(media.id).delete() + User.query.get(user_a.id).delete() diff --git a/mediagoblin/tools/files.py b/mediagoblin/tools/files.py index fd38f05e..848c86f2 100644 --- a/mediagoblin/tools/files.py +++ b/mediagoblin/tools/files.py @@ -37,7 +37,7 @@ def delete_media_files(media): mg_globals.public_store.delete_file( attachment['filepath']) except OSError: - no_such_files.append("/".join(attachment)) + no_such_files.append("/".join(attachment['filepath'])) if no_such_files: raise OSError(", ".join(no_such_files)) diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py index a58dd2ca..74d811eb 100644 --- a/mediagoblin/tools/template.py +++ b/mediagoblin/tools/template.py @@ -25,6 +25,7 @@ from werkzeug.urls import url_quote_plus from mediagoblin import mg_globals from mediagoblin import messages +from mediagoblin import _version from mediagoblin.tools import common from mediagoblin.tools.translate import get_gettext_translation from mediagoblin.tools.pluginapi import get_hook_templates @@ -68,6 +69,7 @@ def get_jinja_env(template_loader, locale): template_env.globals['fetch_messages'] = messages.fetch_messages template_env.globals['app_config'] = mg_globals.app_config template_env.globals['global_config'] = mg_globals.global_config + template_env.globals['version'] = _version.__version__ template_env.filters['urlencode'] = url_quote_plus diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py index 2b228355..6ea3c3e2 100644 --- a/mediagoblin/user_pages/routing.py +++ b/mediagoblin/user_pages/routing.py @@ -40,6 +40,11 @@ add_route('mediagoblin.user_pages.media_home.view_comment', '/u/<string:user>/m/<string:media>/c/<int:comment>/', 'mediagoblin.user_pages.views:media_home') +# User's tags gallery +add_route('mediagoblin.user_pages.user_tag_gallery', + '/u/<string:user>/tag/<string:tag>/', + 'mediagoblin.user_pages.views:user_gallery') + add_route('mediagoblin.user_pages.atom_feed', '/u/<string:user>/atom/', 'mediagoblin.user_pages.views:atom_feed') diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py index dea47fbf..601eef17 100644 --- a/mediagoblin/user_pages/views.py +++ b/mediagoblin/user_pages/views.py @@ -18,8 +18,8 @@ import logging import datetime from mediagoblin import messages, mg_globals -from mediagoblin.db.models import (MediaEntry, Collection, CollectionItem, - User) +from mediagoblin.db.models import (MediaEntry, MediaTag, Collection, + CollectionItem, User) from mediagoblin.tools.response import render_to_response, render_404, redirect from mediagoblin.tools.translate import pass_to_ugettext as _ from mediagoblin.tools.pagination import Pagination @@ -81,10 +81,17 @@ def user_home(request, page): @uses_pagination def user_gallery(request, page, url_user=None): """'Gallery' of a User()""" + tag = request.matchdict.get('tag', None) cursor = MediaEntry.query.filter_by( uploader=url_user.id, state=u'processed').order_by(MediaEntry.created.desc()) + # Filter potentially by tag too: + if tag: + cursor = cursor.filter( + MediaEntry.tags_helper.any( + MediaTag.slug == request.matchdict['tag'])) + # Paginate gallery pagination = Pagination(page, cursor) media_entries = pagination() @@ -97,7 +104,7 @@ def user_gallery(request, page, url_user=None): return render_to_response( request, 'mediagoblin/user_pages/gallery.html', - {'user': url_user, + {'user': url_user, 'tag': tag, 'media_entries': media_entries, 'pagination': pagination}) @@ -205,7 +212,7 @@ def media_collect(request, media): if existing_collection: messages.add_message(request, messages.ERROR, _('You already have a collection called "%s"!' - % collection.title)) + % existing_collection.title)) return redirect(request, "mediagoblin.user_pages.media_home", user=request.user.username, media=media.id) @@ -309,6 +316,9 @@ def user_collection(request, page, url_user=None): get_creator=url_user, slug=request.matchdict['collection']).first() + if not collection: + return render_404(request) + cursor = collection.get_collection_items() pagination = Pagination(page, cursor) @@ -515,6 +525,8 @@ def collection_atom_feed(request): collection = Collection.query.filter_by( creator=user.id, slug=request.matchdict['collection']).first() + if not collection: + return render_404(request) cursor = CollectionItem.query.filter_by( collection=collection.id) \ @@ -539,14 +551,16 @@ def collection_atom_feed(request): 'href': push_url}) feed = AtomFeed( - "MediaGoblin: Feed for %s's collection %s" % (request.matchdict['user'], collection.title), - feed_url=request.url, - id='tag:{host},{year}:collection.user-{user}.title-{title}'.format( - host=request.host, - year=datetime.datetime.today().strftime('%Y'), - user=request.matchdict['user'], - title=collection.title), - links=atomlinks) + "MediaGoblin: Feed for %s's collection %s" % + (request.matchdict['user'], collection.title), + feed_url=request.url, + id=u'tag:{host},{year}:gnu-mediagoblin.{user}.collection.{slug}'\ + .format( + host=request.host, + year=collection.created.strftime('%Y'), + user=request.matchdict['user'], + slug=collection.slug), + links=atomlinks) for item in cursor: entry = item.get_media_entry |