aboutsummaryrefslogtreecommitdiffstats
path: root/mediagoblin/tools
diff options
context:
space:
mode:
Diffstat (limited to 'mediagoblin/tools')
-rw-r--r--mediagoblin/tools/common.py1
-rw-r--r--mediagoblin/tools/exif.py47
-rw-r--r--mediagoblin/tools/files.py2
-rw-r--r--mediagoblin/tools/pluginapi.py64
-rw-r--r--mediagoblin/tools/request.py3
-rw-r--r--mediagoblin/tools/template.py43
-rw-r--r--mediagoblin/tools/translate.py2
-rw-r--r--mediagoblin/tools/url.py2
8 files changed, 127 insertions, 37 deletions
diff --git a/mediagoblin/tools/common.py b/mediagoblin/tools/common.py
index c9f9d032..34586611 100644
--- a/mediagoblin/tools/common.py
+++ b/mediagoblin/tools/common.py
@@ -16,7 +16,6 @@
import sys
-DISPLAY_IMAGE_FETCHING_ORDER = [u'medium', u'original', u'thumb']
global TESTS_ENABLED
TESTS_ENABLED = False
diff --git a/mediagoblin/tools/exif.py b/mediagoblin/tools/exif.py
index 4a1afb0f..d0f9d0a6 100644
--- a/mediagoblin/tools/exif.py
+++ b/mediagoblin/tools/exif.py
@@ -14,7 +14,11 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from mediagoblin.tools.extlib.EXIF import process_file, Ratio
+try:
+ from EXIF import process_file, Ratio
+except ImportError:
+ from mediagoblin.tools.extlib.EXIF import process_file, Ratio
+
from mediagoblin.processing import BadMediaFail
from mediagoblin.tools.translate import pass_to_ugettext as _
@@ -46,7 +50,10 @@ def exif_fix_image_orientation(im, exif_tags):
Translate any EXIF orientation to raw orientation
Cons:
- - REDUCES IMAGE QUALITY by recompressig it
+ - Well, it changes the image, which means we'll recompress
+ it... not a problem if scaling it down already anyway. We might
+ lose some quality in recompressing if it's at the same-size
+ though
Pros:
- Prevents neck pain
@@ -58,7 +65,7 @@ def exif_fix_image_orientation(im, exif_tags):
6: 270,
8: 90}
orientation = exif_tags['Image Orientation'].values[0]
- if orientation in rotation_map.keys():
+ if orientation in rotation_map:
im = im.rotate(
rotation_map[orientation])
@@ -69,16 +76,12 @@ def extract_exif(filename):
"""
Returns EXIF tags found in file at ``filename``
"""
- exif_tags = {}
-
try:
- image = open(filename)
- exif_tags = process_file(image, details=False)
+ with file(filename) as image:
+ return process_file(image, details=False)
except IOError:
raise BadMediaFail(_('Could not read the image file.'))
- return exif_tags
-
def clean_exif(exif):
'''
@@ -92,12 +95,8 @@ def clean_exif(exif):
'JPEGThumbnail',
'Thumbnail JPEGInterchangeFormat']
- clean_exif = {}
-
- for key, value in exif.items():
- if not key in disabled_tags:
- clean_exif[key] = _ifd_tag_to_dict(value)
- return clean_exif
+ return dict((key, _ifd_tag_to_dict(value)) for (key, value)
+ in exif.iteritems() if key not in disabled_tags)
def _ifd_tag_to_dict(tag):
@@ -118,13 +117,8 @@ def _ifd_tag_to_dict(tag):
data['printable'] = tag.printable.decode('utf8', 'replace')
if type(tag.values) == list:
- data['values'] = []
- for val in tag.values:
- if isinstance(val, Ratio):
- data['values'].append(
- _ratio_to_list(val))
- else:
- data['values'].append(val)
+ data['values'] = [_ratio_to_list(val) if isinstance(val, Ratio) else val
+ for val in tag.values]
else:
if isinstance(tag.values, str):
# Force UTF-8, so that it fits into the DB
@@ -140,12 +134,7 @@ def _ratio_to_list(ratio):
def get_useful(tags):
- useful = {}
- for key, tag in tags.items():
- if key in USEFUL_TAGS:
- useful[key] = tag
-
- return useful
+ return dict((key, tag) for (key, tag) in tags.iteritems() if key in USEFUL_TAGS)
def get_gps_data(tags):
@@ -162,7 +151,7 @@ def get_gps_data(tags):
'latitude': tags['GPS GPSLatitude'],
'longitude': tags['GPS GPSLongitude']}
- for key, dat in dms_data.items():
+ for key, dat in dms_data.iteritems():
gps_data[key] = (
lambda v:
float(v[0].num) / float(v[0].den) \
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/pluginapi.py b/mediagoblin/tools/pluginapi.py
index 38ab631b..784bede9 100644
--- a/mediagoblin/tools/pluginapi.py
+++ b/mediagoblin/tools/pluginapi.py
@@ -83,6 +83,9 @@ class PluginManager(object):
# list of registered template paths
"template_paths": set(),
+ # list of template hooks
+ "template_hooks": {},
+
# list of registered routes
"routes": [],
}
@@ -131,6 +134,18 @@ class PluginManager(object):
def get_routes(self):
return tuple(self.routes)
+ def register_template_hooks(self, template_hooks):
+ for hook, templates in template_hooks.items():
+ if isinstance(templates, (list, tuple)):
+ self.template_hooks.setdefault(hook, []).extend(list(templates))
+ else:
+ # In this case, it's actually a single callable---not a
+ # list of callables.
+ self.template_hooks.setdefault(hook, []).append(templates)
+
+ def get_template_hooks(self, hook_name):
+ return self.template_hooks.get(hook_name, [])
+
def register_routes(routes):
"""Registers one or more routes
@@ -208,3 +223,52 @@ def get_config(key):
return plugin_section.get(key, {})
+def register_template_hooks(template_hooks):
+ """
+ Register a dict of template hooks.
+
+ Takes template_hooks as an argument, which is a dictionary of
+ template hook names/keys to the templates they should provide.
+ (The value can either be a single template path or an iterable
+ of paths.)
+
+ Example:
+
+ .. code-block:: python
+
+ {"media_sidebar": "/plugin/sidemess/mess_up_the_side.html",
+ "media_descriptionbox": ["/plugin/sidemess/even_more_mess.html",
+ "/plugin/sidemess/so_much_mess.html"]}
+ """
+ PluginManager().register_template_hooks(template_hooks)
+
+
+def get_hook_templates(hook_name):
+ """
+ Get a list of hook templates for this hook_name.
+
+ Note: for the most part, you access this via a template tag, not
+ this method directly, like so:
+
+ .. code-block:: html+jinja
+
+ {% template_hook "media_sidebar" %}
+
+ ... which will include all templates for you, partly using this
+ method.
+
+ However, this method is exposed to templates, and if you wish, you
+ can iterate over templates in a template hook manually like so:
+
+ .. code-block:: html+jinja
+
+ {% for template_path in get_hook_templates("media_sidebar") %}
+ <div class="extra_structure">
+ {% include template_path %}
+ </div>
+ {% endfor %}
+
+ Returns:
+ A list of strings representing template paths.
+ """
+ return PluginManager().get_template_hooks(hook_name)
diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py
index f7311fac..bc67b96f 100644
--- a/mediagoblin/tools/request.py
+++ b/mediagoblin/tools/request.py
@@ -25,7 +25,7 @@ def setup_user_in_request(request):
Examine a request and tack on a request.user parameter if that's
appropriate.
"""
- if not request.session.has_key('user_id'):
+ if 'user_id' not in request.session:
request.user = None
return
@@ -36,4 +36,3 @@ def setup_user_in_request(request):
# this session.
_log.warn("Killing session for user id %r", request.session['user_id'])
request.session.invalidate()
-
diff --git a/mediagoblin/tools/template.py b/mediagoblin/tools/template.py
index d9c6e654..74d811eb 100644
--- a/mediagoblin/tools/template.py
+++ b/mediagoblin/tools/template.py
@@ -15,14 +15,20 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from math import ceil
+
import jinja2
+from jinja2.ext import Extension
+from jinja2.nodes import Include, Const
+
from babel.localedata import exists
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
from mediagoblin.meddleware.csrf import render_csrf_form_token
@@ -40,7 +46,7 @@ def get_jinja_env(template_loader, locale):
# If we have a jinja environment set up with this locale, just
# return that one.
- if SETUP_JINJA_ENVS.has_key(locale):
+ if locale in SETUP_JINJA_ENVS:
return SETUP_JINJA_ENVS[locale]
# jinja2.StrictUndefined will give exceptions on references
@@ -48,7 +54,9 @@ def get_jinja_env(template_loader, locale):
template_env = jinja2.Environment(
loader=template_loader, autoescape=True,
undefined=jinja2.StrictUndefined,
- extensions=['jinja2.ext.i18n', 'jinja2.ext.autoescape'])
+ extensions=[
+ 'jinja2.ext.i18n', 'jinja2.ext.autoescape',
+ TemplateHookExtension])
template_env.install_gettext_callables(
mg_globals.thread_scope.translations.ugettext,
@@ -61,9 +69,13 @@ 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
+ # allow for hooking up plugin templates
+ template_env.globals['get_hook_templates'] = get_hook_templates
+
if exists(locale):
SETUP_JINJA_ENVS[locale] = template_env
@@ -98,3 +110,30 @@ def render_template(request, template_path, context):
def clear_test_template_context():
global TEMPLATE_TEST_CONTEXT
TEMPLATE_TEST_CONTEXT = {}
+
+
+class TemplateHookExtension(Extension):
+ """
+ Easily loop through a bunch of templates from a template hook.
+
+ Use:
+ {% template_hook("comment_extras") %}
+
+ ... will include all templates hooked into the comment_extras section.
+ """
+
+ tags = set(["template_hook"])
+
+ def parse(self, parser):
+ includes = []
+ expr = parser.parse_expression()
+ lineno = expr.lineno
+ hook_name = expr.args[0].value
+
+ for template_name in get_hook_templates(hook_name):
+ includes.append(
+ parser.parse_import_context(
+ Include(Const(template_name), True, False, lineno=lineno),
+ True))
+
+ return includes
diff --git a/mediagoblin/tools/translate.py b/mediagoblin/tools/translate.py
index 96144538..1d37c4de 100644
--- a/mediagoblin/tools/translate.py
+++ b/mediagoblin/tools/translate.py
@@ -73,7 +73,7 @@ def get_locale_from_request(request):
"""
request_args = (request.args, request.form)[request.method=='POST']
- if request_args.has_key('lang'):
+ if 'lang' in request_args:
# User explicitely demanded a language, normalize lower_uppercase
target_lang = locale_to_lower_upper(request_args['lang'])
diff --git a/mediagoblin/tools/url.py b/mediagoblin/tools/url.py
index 8604ad5f..d9179f9e 100644
--- a/mediagoblin/tools/url.py
+++ b/mediagoblin/tools/url.py
@@ -25,7 +25,7 @@ except ImportError:
USING_TRANSLITCODEC = False
-_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
+_punct_re = re.compile(r'[\t !"#:$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
def slugify(text, delim=u'-'):