mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-05 20:51:49 +02:00
Add compatibility with flask extensions for flask versions > 0.7
This commit is contained in:
parent
800dcba2c8
commit
8c966705e5
6 changed files with 157 additions and 8 deletions
|
@ -1,6 +1,11 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# activate flask.ext compatibility module
|
||||||
|
import flaskext_compat
|
||||||
|
flaskext_compat.activate()
|
||||||
|
|
||||||
from flask import Blueprint, request
|
from flask import Blueprint, request
|
||||||
from flask_rest import RESTResource, need_auth
|
from flask.ext.rest import RESTResource, need_auth
|
||||||
|
|
||||||
from models import db, Project, Person, Bill
|
from models import db, Project, Person, Bill
|
||||||
from forms import (ProjectForm, EditProjectForm, MemberForm,
|
from forms import (ProjectForm, EditProjectForm, MemberForm,
|
||||||
|
|
127
budget/flaskext_compat.py
Normal file
127
budget/flaskext_compat.py
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
flaskext_compat
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Implements the ``flask.ext`` virtual package for versions of Flask
|
||||||
|
older than 0.7. This module is a noop if Flask 0.8 was detected.
|
||||||
|
|
||||||
|
Usage::
|
||||||
|
|
||||||
|
import flaskext_compat
|
||||||
|
flaskext_compat.activate()
|
||||||
|
from flask.ext import foo
|
||||||
|
|
||||||
|
:copyright: (c) 2011 by Armin Ronacher.
|
||||||
|
:license: BSD, see LICENSE for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import imp
|
||||||
|
|
||||||
|
|
||||||
|
class ExtensionImporter(object):
|
||||||
|
"""This importer redirects imports from this submodule to other locations.
|
||||||
|
This makes it possible to transition from the old flaskext.name to the
|
||||||
|
newer flask_name without people having a hard time.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, module_choices, wrapper_module):
|
||||||
|
self.module_choices = module_choices
|
||||||
|
self.wrapper_module = wrapper_module
|
||||||
|
self.prefix = wrapper_module + '.'
|
||||||
|
self.prefix_cutoff = wrapper_module.count('.') + 1
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.__class__.__module__ == other.__class__.__module__ and \
|
||||||
|
self.__class__.__name__ == other.__class__.__name__ and \
|
||||||
|
self.wrapper_module == other.wrapper_module and \
|
||||||
|
self.module_choices == other.module_choices
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return not self.__eq__(other)
|
||||||
|
|
||||||
|
def install(self):
|
||||||
|
sys.meta_path[:] = [x for x in sys.meta_path if self != x] + [self]
|
||||||
|
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
if fullname.startswith(self.prefix):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def load_module(self, fullname):
|
||||||
|
if fullname in sys.modules:
|
||||||
|
return sys.modules[fullname]
|
||||||
|
modname = fullname.split('.', self.prefix_cutoff)[self.prefix_cutoff]
|
||||||
|
for path in self.module_choices:
|
||||||
|
realname = path % modname
|
||||||
|
try:
|
||||||
|
__import__(realname)
|
||||||
|
except ImportError:
|
||||||
|
exc_type, exc_value, tb = sys.exc_info()
|
||||||
|
# since we only establish the entry in sys.modules at the
|
||||||
|
# end this seems to be redundant, but if recursive imports
|
||||||
|
# happen we will call into the move import a second time.
|
||||||
|
# On the second invocation we still don't have an entry for
|
||||||
|
# fullname in sys.modules, but we will end up with the same
|
||||||
|
# fake module name and that import will succeed since this
|
||||||
|
# one already has a temporary entry in the modules dict.
|
||||||
|
# Since this one "succeeded" temporarily that second
|
||||||
|
# invocation now will have created a fullname entry in
|
||||||
|
# sys.modules which we have to kill.
|
||||||
|
sys.modules.pop(fullname, None)
|
||||||
|
|
||||||
|
# If it's an important traceback we reraise it, otherwise
|
||||||
|
# we swallow it and try the next choice. The skipped frame
|
||||||
|
# is the one from __import__ above which we don't care about.
|
||||||
|
if self.is_important_traceback(realname, tb):
|
||||||
|
raise exc_type, exc_value, tb.tb_next
|
||||||
|
continue
|
||||||
|
module = sys.modules[fullname] = sys.modules[realname]
|
||||||
|
if '.' not in modname:
|
||||||
|
setattr(sys.modules[self.wrapper_module], modname, module)
|
||||||
|
return module
|
||||||
|
raise ImportError('No module named %s' % fullname)
|
||||||
|
|
||||||
|
def is_important_traceback(self, important_module, tb):
|
||||||
|
"""Walks a traceback's frames and checks if any of the frames
|
||||||
|
originated in the given important module. If that is the case then we
|
||||||
|
were able to import the module itself but apparently something went
|
||||||
|
wrong when the module was imported. (Eg: import of an import failed).
|
||||||
|
"""
|
||||||
|
while tb is not None:
|
||||||
|
if self.is_important_frame(important_module, tb):
|
||||||
|
return True
|
||||||
|
tb = tb.tb_next
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_important_frame(self, important_module, tb):
|
||||||
|
"""Checks a single frame if it's important."""
|
||||||
|
g = tb.tb_frame.f_globals
|
||||||
|
if '__name__' not in g:
|
||||||
|
return False
|
||||||
|
|
||||||
|
module_name = g['__name__']
|
||||||
|
|
||||||
|
# Python 2.7 Behavior. Modules are cleaned up late so the
|
||||||
|
# name shows up properly here. Success!
|
||||||
|
if module_name == important_module:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Some python versions will clean up modules so early that the
|
||||||
|
# module name at that point is no longer set. Try guessing from
|
||||||
|
# the filename then.
|
||||||
|
filename = os.path.abspath(tb.tb_frame.f_code.co_filename)
|
||||||
|
test_string = os.path.sep + important_module.replace('.', os.path.sep)
|
||||||
|
return test_string + '.py' in filename or \
|
||||||
|
test_string + os.path.sep + '__init__.py' in filename
|
||||||
|
|
||||||
|
|
||||||
|
def activate():
|
||||||
|
import flask
|
||||||
|
ext_module = imp.new_module('flask.ext')
|
||||||
|
ext_module.__path__ = []
|
||||||
|
flask.ext = sys.modules['flask.ext'] = ext_module
|
||||||
|
importer = ExtensionImporter(['flask_%s', 'flaskext.%s'], 'flask.ext')
|
||||||
|
importer.install()
|
|
@ -1,7 +1,11 @@
|
||||||
from flaskext.wtf import DateField, DecimalField, Email, Form, PasswordField, \
|
# load flask.ext compatibility module
|
||||||
|
import flaskext_compat
|
||||||
|
flaskext_compat.activate()
|
||||||
|
|
||||||
|
from flask.ext.wtf import DateField, DecimalField, Email, Form, PasswordField, \
|
||||||
Required, SelectField, SelectMultipleField, SubmitField, TextAreaField, \
|
Required, SelectField, SelectMultipleField, SubmitField, TextAreaField, \
|
||||||
TextField, ValidationError
|
TextField, ValidationError
|
||||||
from flaskext.babel import lazy_gettext as _
|
from flask.ext.babel import lazy_gettext as _
|
||||||
from flask import request
|
from flask import request
|
||||||
|
|
||||||
from wtforms.widgets import html_params
|
from wtforms.widgets import html_params
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
from collections import defaultdict
|
# activate flask.ext compatibility module
|
||||||
|
import flaskext_compat
|
||||||
|
flaskext_compat.activate()
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask_sqlalchemy import SQLAlchemy, BaseQuery
|
from flask.ext.sqlalchemy import SQLAlchemy, BaseQuery
|
||||||
from flask import g
|
from flask import g
|
||||||
|
|
||||||
from sqlalchemy import orm
|
from sqlalchemy import orm
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
from flask import Flask, g, request, session
|
from flask import Flask, g, request, session
|
||||||
from flaskext.babel import Babel
|
|
||||||
|
# load flask.ext compatibility module
|
||||||
|
import flaskext_compat
|
||||||
|
flaskext_compat.activate()
|
||||||
|
|
||||||
|
from flask.ext.babel import Babel
|
||||||
from raven.contrib.flask import Sentry
|
from raven.contrib.flask import Sentry
|
||||||
|
|
||||||
from web import main, db, mail
|
from web import main, db, mail
|
||||||
|
|
|
@ -11,8 +11,13 @@ and `add_project_id` for a quick overview)
|
||||||
|
|
||||||
from flask import Blueprint, current_app, flash, g, redirect, \
|
from flask import Blueprint, current_app, flash, g, redirect, \
|
||||||
render_template, request, session, url_for
|
render_template, request, session, url_for
|
||||||
from flaskext.mail import Mail, Message
|
|
||||||
from flaskext.babel import get_locale, gettext as _
|
# activate flask.ext compatibility module
|
||||||
|
import flaskext_compat
|
||||||
|
flaskext_compat.activate()
|
||||||
|
|
||||||
|
from flask.ext.mail import Message, Mail
|
||||||
|
from flask.ext.babel import get_locale, gettext as _
|
||||||
from smtplib import SMTPRecipientsRefused
|
from smtplib import SMTPRecipientsRefused
|
||||||
import werkzeug
|
import werkzeug
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue