aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in10
-rw-r--r--mediagoblin/db/models.py1
-rw-r--r--mediagoblin/media_types/video/transcoders.py37
-rw-r--r--mediagoblin/plugins/api/tools.py3
-rw-r--r--mediagoblin/templates/mediagoblin/base.html25
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/gallery.html26
-rw-r--r--mediagoblin/templates/mediagoblin/user_pages/media_collect.html11
-rw-r--r--mediagoblin/templates/mediagoblin/utils/tags.html16
-rw-r--r--mediagoblin/templates/mediagoblin/utils/wtforms.html2
-rw-r--r--mediagoblin/tests/test_misc.py15
-rw-r--r--mediagoblin/tools/files.py2
-rw-r--r--mediagoblin/tools/template.py2
-rw-r--r--mediagoblin/user_pages/routing.py5
-rw-r--r--mediagoblin/user_pages/views.py38
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">&#9660;</div>
<div class="button_action header_dropdown_up">&#9650;</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 @@
&middot;
{% 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> &middot;
+ 'mediagoblin.user_pages.user_tag_gallery',
+ tag=tag['slug'],
+ user=media.get_uploader.username) }}">{{ tag['name'] }}</a>
+ &middot;
{% 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