diff options
Diffstat (limited to 'mediagoblin/tools')
-rw-r--r-- | mediagoblin/tools/common.py | 1 | ||||
-rw-r--r-- | mediagoblin/tools/exif.py | 47 | ||||
-rw-r--r-- | mediagoblin/tools/files.py | 2 | ||||
-rw-r--r-- | mediagoblin/tools/pluginapi.py | 64 | ||||
-rw-r--r-- | mediagoblin/tools/request.py | 3 | ||||
-rw-r--r-- | mediagoblin/tools/template.py | 43 | ||||
-rw-r--r-- | mediagoblin/tools/translate.py | 2 | ||||
-rw-r--r-- | mediagoblin/tools/url.py | 2 |
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'-'): |