diff --git a/app.py b/app.py index 3ad96f1..db035f3 100644 --- a/app.py +++ b/app.py @@ -1,9 +1,15 @@ import uuid import yaml -from flask import Flask, flash, request, render_template +from flask_wtf import Form +from flask_wtf.csrf import CSRFProtect +from wtforms import IntegerField, StringField, SelectField, validators, ValidationError, DecimalField +from flask import Flask, request, flash, render_template +import time + app = Flask(__name__) app.secret_key = 'life is pointless' +csrf = CSRFProtect(app) with open('products.yml') as _f: PRODUCTS = yaml.load(_f) @@ -11,15 +17,36 @@ with open('denominations.yml') as _f: DENOMINATIONS = yaml.load(_f) - ORDER_DB = 'orders.yml' +pChoices = [] + +for product in PRODUCTS: + for key, value in product.items(): + if key == 'name': + pChoices.append(tuple((value, value))) + + + -def record_order(product_id): +class paymentForm(Form): # class to define validation rules for the form fields + # productF = SelectField('productF', [validators.input_required("Please choose a product.")], choices=[pChoices]) + buyer_id = StringField('buyer', [validators.input_required("Please enter your name.")]) + paid = DecimalField('paid', [validators.input_required("please enter payment amount")]) + price = StringField('price') + + + + +def record_order(data): order_id = str(uuid.uuid4()).split('-', 1)[0] orders = { order_id: { - 'product_id': product_id, + 'buyer_id': data['buyer_id'].decode('unicode_escape').encode('ascii', 'ignore'), + 'Paid': data['paid'], + 'price': data['price'], + # 'product': data['productF'], + 'date_ordered': (time.strftime("%H:%M:%S %d/%m/%Y")) } } with open(ORDER_DB, 'a') as f: @@ -29,23 +56,36 @@ def record_order(product_id): @app.route('/', methods=['POST', 'GET']) def index(): context = {} - if request.method == 'POST': + form = paymentForm() + if form.validate_on_submit(): flash('Order Placed Successfully', 'success') - # TODO - return render_template('index.jinja', products=PRODUCTS, title='Order Form', **context) + data = form.data + record_order(data) + print(data['price']) + return render_template('confirmation.jinja', + products=PRODUCTS, + title='Confirmation Page', + form=form, error=form.errors, + ** context) + elif not form.validate_on_submit: + flash('Submission error, please check the form', 'success') + return render_template('index.jinja', + products=PRODUCTS, + title='Order Form', + form=form, + error=form.errors, + **context) @app.route('/confirmation/') -def confirmation(order_id): +def confirmation(data): with open(ORDER_DB) as f: orders = yaml.load(f) or {} - - order = orders.get(order_id) + order = orders.get(data.buyer_id) if order is None: pass # TODO what do we do here? - # TODO other stuff has to be calculated here. - return render_template('confirmation.jinja', order_id=order_id, title='Order Confirmation') + return render_template('confirmation.jinja', order=order, title='Order Confirmation') if __name__ == '__main__': app.run(debug=True, use_reloader=True) diff --git a/change.py b/change.py new file mode 100644 index 0000000..28c76b5 --- /dev/null +++ b/change.py @@ -0,0 +1,33 @@ +import yaml + +with open('denominations.yml') as _f: + DENOMINATIONS = yaml.load(_f) + +denVal = [] + +for i in DENOMINATIONS: #create denomination value list + for key, value in i.items(): + if key == 'value': + denVal.append(value) + +def get_min_coins(paid): + change_list = [] + + for change_val in sorted(denVal, reverse=True): #work out the minimum amount of change denominations + change_count = paid / change_val + change_list += [change_val, ] * change_count + paid -= change_val * change_count + + return change_list + + pounds = change_list + + pounds[:] = [str(x).strip("00") for x in change_list if len(str(x)) >= 3] # makes large values 'pound sign' ready + + print pounds # bug - currently these two list comp's overwrite change_list value, need to be run seperately + + pennies[:] = [''.join([str(x), 'p']) for x in change_list if len(str(x)) <= 2] # gives coins a 'p' + print pennies + +paid = 565 +get_min_coins(paid) diff --git a/env/bin/activate b/env/bin/activate new file mode 100644 index 0000000..e1c8830 --- /dev/null +++ b/env/bin/activate @@ -0,0 +1,78 @@ +# This file must be used with "source bin/activate" *from bash* +# you cannot run it directly + +deactivate () { + unset -f pydoc >/dev/null 2>&1 + + # reset old environment variables + # ! [ -z ${VAR+_} ] returns true if VAR is declared at all + if ! [ -z "${_OLD_VIRTUAL_PATH+_}" ] ; then + PATH="$_OLD_VIRTUAL_PATH" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then + PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # This should detect bash and zsh, which have a hash command that must + # be called to get it to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null + fi + + if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then + PS1="$_OLD_VIRTUAL_PS1" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + if [ ! "${1-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +VIRTUAL_ENV="/home/tom/intern-test/env" +export VIRTUAL_ENV + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +if ! [ -z "${PYTHONHOME+_}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then + _OLD_VIRTUAL_PS1="$PS1" + if [ "x" != x ] ; then + PS1="$PS1" + else + PS1="(`basename \"$VIRTUAL_ENV\"`) $PS1" + fi + export PS1 +fi + +# Make sure to unalias pydoc if it's already there +alias pydoc 2>/dev/null >/dev/null && unalias pydoc + +pydoc () { + python -m pydoc "$@" +} + +# This should detect bash and zsh, which have a hash command that must +# be called to get it to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then + hash -r 2>/dev/null +fi diff --git a/env/bin/activate.csh b/env/bin/activate.csh new file mode 100644 index 0000000..756a02f --- /dev/null +++ b/env/bin/activate.csh @@ -0,0 +1,36 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. +# Created by Davide Di Blasi . + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate && unalias pydoc' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/home/tom/intern-test/env" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + + +if ("" != "") then + set env_name = "" +else + set env_name = `basename "$VIRTUAL_ENV"` +endif + +# Could be in a non-interactive environment, +# in which case, $prompt is undefined and we wouldn't +# care about the prompt anyway. +if ( $?prompt ) then + set _OLD_VIRTUAL_PROMPT="$prompt" + set prompt = "[$env_name] $prompt" +endif + +unset env_name + +alias pydoc python -m pydoc + +rehash + diff --git a/env/bin/activate.fish b/env/bin/activate.fish new file mode 100644 index 0000000..dbfe11a --- /dev/null +++ b/env/bin/activate.fish @@ -0,0 +1,76 @@ +# This file must be used using `. bin/activate.fish` *within a running fish ( http://fishshell.com ) session*. +# Do not run it directly. + +function deactivate -d 'Exit virtualenv mode and return to the normal environment.' + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + # Set an empty local `$fish_function_path` to allow the removal of `fish_prompt` using `functions -e`. + set -l fish_function_path + + # Erase virtualenv's `fish_prompt` and restore the original. + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + set -e _OLD_FISH_PROMPT_OVERRIDE + end + + set -e VIRTUAL_ENV + + if test "$argv[1]" != 'nondestructive' + # Self-destruct! + functions -e pydoc + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/home/tom/intern-test/env" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset `$PYTHONHOME` if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +function pydoc + python -m pydoc $argv +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # Copy the current `fish_prompt` function as `_old_fish_prompt`. + functions -c fish_prompt _old_fish_prompt + + function fish_prompt + # Save the current $status, for fish_prompts that display it. + set -l old_status $status + + # Prompt override provided? + # If not, just prepend the environment name. + if test -n "" + printf '%s%s' "" (set_color normal) + else + printf '%s(%s) ' (set_color normal) (basename "$VIRTUAL_ENV") + end + + # Restore the original $status + echo "exit $old_status" | source + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" +end diff --git a/env/bin/activate_this.py b/env/bin/activate_this.py new file mode 100644 index 0000000..f18193b --- /dev/null +++ b/env/bin/activate_this.py @@ -0,0 +1,34 @@ +"""By using execfile(this_file, dict(__file__=this_file)) you will +activate this virtualenv environment. + +This can be used when you must use an existing Python interpreter, not +the virtualenv bin/python +""" + +try: + __file__ +except NameError: + raise AssertionError( + "You must run this like execfile('path/to/activate_this.py', dict(__file__='path/to/activate_this.py'))") +import sys +import os + +old_os_path = os.environ.get('PATH', '') +os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + os.pathsep + old_os_path +base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if sys.platform == 'win32': + site_packages = os.path.join(base, 'Lib', 'site-packages') +else: + site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages') +prev_sys_path = list(sys.path) +import site +site.addsitedir(site_packages) +sys.real_prefix = sys.prefix +sys.prefix = base +# Move the added items to the front of the path: +new_sys_path = [] +for item in list(sys.path): + if item not in prev_sys_path: + new_sys_path.append(item) + sys.path.remove(item) +sys.path[:0] = new_sys_path diff --git a/env/bin/easy_install b/env/bin/easy_install new file mode 100755 index 0000000..446397e --- /dev/null +++ b/env/bin/easy_install @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from setuptools.command.easy_install import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/easy_install-2.7 b/env/bin/easy_install-2.7 new file mode 100755 index 0000000..446397e --- /dev/null +++ b/env/bin/easy_install-2.7 @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from setuptools.command.easy_install import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/flake8 b/env/bin/flake8 new file mode 100755 index 0000000..1a2850e --- /dev/null +++ b/env/bin/flake8 @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from flake8.main import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/pep8 b/env/bin/pep8 new file mode 100755 index 0000000..d42e30f --- /dev/null +++ b/env/bin/pep8 @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from pep8 import _main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(_main()) diff --git a/env/bin/pip b/env/bin/pip new file mode 100755 index 0000000..6ddc60d --- /dev/null +++ b/env/bin/pip @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from pip import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/pip2 b/env/bin/pip2 new file mode 100755 index 0000000..6ddc60d --- /dev/null +++ b/env/bin/pip2 @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from pip import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/pip2.7 b/env/bin/pip2.7 new file mode 100755 index 0000000..6ddc60d --- /dev/null +++ b/env/bin/pip2.7 @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from pip import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/pyflakes b/env/bin/pyflakes new file mode 100755 index 0000000..3fa4f25 --- /dev/null +++ b/env/bin/pyflakes @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from pyflakes.api import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/bin/python b/env/bin/python new file mode 100755 index 0000000..68c7d2a Binary files /dev/null and b/env/bin/python differ diff --git a/env/bin/python-config b/env/bin/python-config new file mode 100755 index 0000000..90ceba4 --- /dev/null +++ b/env/bin/python-config @@ -0,0 +1,78 @@ +#!/home/tom/intern-test/env/bin/python + +import sys +import getopt +import sysconfig + +valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', + 'ldflags', 'help'] + +if sys.version_info >= (3, 2): + valid_opts.insert(-1, 'extension-suffix') + valid_opts.append('abiflags') +if sys.version_info >= (3, 3): + valid_opts.append('configdir') + + +def exit_with_usage(code=1): + sys.stderr.write("Usage: {0} [{1}]\n".format( + sys.argv[0], '|'.join('--'+opt for opt in valid_opts))) + sys.exit(code) + +try: + opts, args = getopt.getopt(sys.argv[1:], '', valid_opts) +except getopt.error: + exit_with_usage() + +if not opts: + exit_with_usage() + +pyver = sysconfig.get_config_var('VERSION') +getvar = sysconfig.get_config_var + +opt_flags = [flag for (flag, val) in opts] + +if '--help' in opt_flags: + exit_with_usage(code=0) + +for opt in opt_flags: + if opt == '--prefix': + print(sysconfig.get_config_var('prefix')) + + elif opt == '--exec-prefix': + print(sysconfig.get_config_var('exec_prefix')) + + elif opt in ('--includes', '--cflags'): + flags = ['-I' + sysconfig.get_path('include'), + '-I' + sysconfig.get_path('platinclude')] + if opt == '--cflags': + flags.extend(getvar('CFLAGS').split()) + print(' '.join(flags)) + + elif opt in ('--libs', '--ldflags'): + abiflags = getattr(sys, 'abiflags', '') + libs = ['-lpython' + pyver + abiflags] + libs += getvar('LIBS').split() + libs += getvar('SYSLIBS').split() + # add the prefix/lib/pythonX.Y/config dir, but only if there is no + # shared library in prefix/lib/. + if opt == '--ldflags': + if not getvar('Py_ENABLE_SHARED'): + libs.insert(0, '-L' + getvar('LIBPL')) + if not getvar('PYTHONFRAMEWORK'): + libs.extend(getvar('LINKFORSHARED').split()) + print(' '.join(libs)) + + elif opt == '--extension-suffix': + ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') + if ext_suffix is None: + ext_suffix = sysconfig.get_config_var('SO') + print(ext_suffix) + + elif opt == '--abiflags': + if not getattr(sys, 'abiflags', None): + exit_with_usage() + print(sys.abiflags) + + elif opt == '--configdir': + print(sysconfig.get_config_var('LIBPL')) diff --git a/env/bin/python2 b/env/bin/python2 new file mode 120000 index 0000000..d8654aa --- /dev/null +++ b/env/bin/python2 @@ -0,0 +1 @@ +python \ No newline at end of file diff --git a/env/bin/python2.7 b/env/bin/python2.7 new file mode 120000 index 0000000..d8654aa --- /dev/null +++ b/env/bin/python2.7 @@ -0,0 +1 @@ +python \ No newline at end of file diff --git a/env/bin/wheel b/env/bin/wheel new file mode 100755 index 0000000..67e4eae --- /dev/null +++ b/env/bin/wheel @@ -0,0 +1,11 @@ +#!/home/tom/intern-test/env/bin/python + +# -*- coding: utf-8 -*- +import re +import sys + +from wheel.tool import main + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/env/include/python2.7 b/env/include/python2.7 new file mode 120000 index 0000000..ad4ca80 --- /dev/null +++ b/env/include/python2.7 @@ -0,0 +1 @@ +/usr/include/python2.7 \ No newline at end of file diff --git a/env/lib/python2.7/UserDict.py b/env/lib/python2.7/UserDict.py new file mode 120000 index 0000000..1dcde33 --- /dev/null +++ b/env/lib/python2.7/UserDict.py @@ -0,0 +1 @@ +/usr/lib/python2.7/UserDict.py \ No newline at end of file diff --git a/env/lib/python2.7/UserDict.pyc b/env/lib/python2.7/UserDict.pyc new file mode 100644 index 0000000..c9ed8ee Binary files /dev/null and b/env/lib/python2.7/UserDict.pyc differ diff --git a/env/lib/python2.7/_abcoll.py b/env/lib/python2.7/_abcoll.py new file mode 120000 index 0000000..e39c38d --- /dev/null +++ b/env/lib/python2.7/_abcoll.py @@ -0,0 +1 @@ +/usr/lib/python2.7/_abcoll.py \ No newline at end of file diff --git a/env/lib/python2.7/_abcoll.pyc b/env/lib/python2.7/_abcoll.pyc new file mode 100644 index 0000000..87a322a Binary files /dev/null and b/env/lib/python2.7/_abcoll.pyc differ diff --git a/env/lib/python2.7/_weakrefset.py b/env/lib/python2.7/_weakrefset.py new file mode 120000 index 0000000..a3c1cd4 --- /dev/null +++ b/env/lib/python2.7/_weakrefset.py @@ -0,0 +1 @@ +/usr/lib/python2.7/_weakrefset.py \ No newline at end of file diff --git a/env/lib/python2.7/_weakrefset.pyc b/env/lib/python2.7/_weakrefset.pyc new file mode 100644 index 0000000..b4caa3a Binary files /dev/null and b/env/lib/python2.7/_weakrefset.pyc differ diff --git a/env/lib/python2.7/abc.py b/env/lib/python2.7/abc.py new file mode 120000 index 0000000..cb3e5d1 --- /dev/null +++ b/env/lib/python2.7/abc.py @@ -0,0 +1 @@ +/usr/lib/python2.7/abc.py \ No newline at end of file diff --git a/env/lib/python2.7/abc.pyc b/env/lib/python2.7/abc.pyc new file mode 100644 index 0000000..a476be6 Binary files /dev/null and b/env/lib/python2.7/abc.pyc differ diff --git a/env/lib/python2.7/codecs.py b/env/lib/python2.7/codecs.py new file mode 120000 index 0000000..50169dc --- /dev/null +++ b/env/lib/python2.7/codecs.py @@ -0,0 +1 @@ +/usr/lib/python2.7/codecs.py \ No newline at end of file diff --git a/env/lib/python2.7/codecs.pyc b/env/lib/python2.7/codecs.pyc new file mode 100644 index 0000000..59e8dd0 Binary files /dev/null and b/env/lib/python2.7/codecs.pyc differ diff --git a/env/lib/python2.7/copy_reg.py b/env/lib/python2.7/copy_reg.py new file mode 120000 index 0000000..5dc0af3 --- /dev/null +++ b/env/lib/python2.7/copy_reg.py @@ -0,0 +1 @@ +/usr/lib/python2.7/copy_reg.py \ No newline at end of file diff --git a/env/lib/python2.7/copy_reg.pyc b/env/lib/python2.7/copy_reg.pyc new file mode 100644 index 0000000..c4b5fdc Binary files /dev/null and b/env/lib/python2.7/copy_reg.pyc differ diff --git a/env/lib/python2.7/distutils/__init__.py b/env/lib/python2.7/distutils/__init__.py new file mode 100644 index 0000000..29fc1da --- /dev/null +++ b/env/lib/python2.7/distutils/__init__.py @@ -0,0 +1,101 @@ +import os +import sys +import warnings +import imp +import opcode # opcode is not a virtualenv module, so we can use it to find the stdlib + # Important! To work on pypy, this must be a module that resides in the + # lib-python/modified-x.y.z directory + +dirname = os.path.dirname + +distutils_path = os.path.join(os.path.dirname(opcode.__file__), 'distutils') +if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)): + warnings.warn( + "The virtualenv distutils package at %s appears to be in the same location as the system distutils?") +else: + __path__.insert(0, distutils_path) + real_distutils = imp.load_module("_virtualenv_distutils", None, distutils_path, ('', '', imp.PKG_DIRECTORY)) + # Copy the relevant attributes + try: + __revision__ = real_distutils.__revision__ + except AttributeError: + pass + __version__ = real_distutils.__version__ + +from distutils import dist, sysconfig + +try: + basestring +except NameError: + basestring = str + +## patch build_ext (distutils doesn't know how to get the libs directory +## path on windows - it hardcodes the paths around the patched sys.prefix) + +if sys.platform == 'win32': + from distutils.command.build_ext import build_ext as old_build_ext + class build_ext(old_build_ext): + def finalize_options (self): + if self.library_dirs is None: + self.library_dirs = [] + elif isinstance(self.library_dirs, basestring): + self.library_dirs = self.library_dirs.split(os.pathsep) + + self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs")) + old_build_ext.finalize_options(self) + + from distutils.command import build_ext as build_ext_module + build_ext_module.build_ext = build_ext + +## distutils.dist patches: + +old_find_config_files = dist.Distribution.find_config_files +def find_config_files(self): + found = old_find_config_files(self) + system_distutils = os.path.join(distutils_path, 'distutils.cfg') + #if os.path.exists(system_distutils): + # found.insert(0, system_distutils) + # What to call the per-user config file + if os.name == 'posix': + user_filename = ".pydistutils.cfg" + else: + user_filename = "pydistutils.cfg" + user_filename = os.path.join(sys.prefix, user_filename) + if os.path.isfile(user_filename): + for item in list(found): + if item.endswith('pydistutils.cfg'): + found.remove(item) + found.append(user_filename) + return found +dist.Distribution.find_config_files = find_config_files + +## distutils.sysconfig patches: + +old_get_python_inc = sysconfig.get_python_inc +def sysconfig_get_python_inc(plat_specific=0, prefix=None): + if prefix is None: + prefix = sys.real_prefix + return old_get_python_inc(plat_specific, prefix) +sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__ +sysconfig.get_python_inc = sysconfig_get_python_inc + +old_get_python_lib = sysconfig.get_python_lib +def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None): + if standard_lib and prefix is None: + prefix = sys.real_prefix + return old_get_python_lib(plat_specific, standard_lib, prefix) +sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__ +sysconfig.get_python_lib = sysconfig_get_python_lib + +old_get_config_vars = sysconfig.get_config_vars +def sysconfig_get_config_vars(*args): + real_vars = old_get_config_vars(*args) + if sys.platform == 'win32': + lib_dir = os.path.join(sys.real_prefix, "libs") + if isinstance(real_vars, dict) and 'LIBDIR' not in real_vars: + real_vars['LIBDIR'] = lib_dir # asked for all + elif isinstance(real_vars, list) and 'LIBDIR' in args: + real_vars = real_vars + [lib_dir] # asked for list + return real_vars +sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__ +sysconfig.get_config_vars = sysconfig_get_config_vars diff --git a/env/lib/python2.7/distutils/__init__.pyc b/env/lib/python2.7/distutils/__init__.pyc new file mode 100644 index 0000000..f2f94b1 Binary files /dev/null and b/env/lib/python2.7/distutils/__init__.pyc differ diff --git a/env/lib/python2.7/distutils/distutils.cfg b/env/lib/python2.7/distutils/distutils.cfg new file mode 100644 index 0000000..1af230e --- /dev/null +++ b/env/lib/python2.7/distutils/distutils.cfg @@ -0,0 +1,6 @@ +# This is a config file local to this virtualenv installation +# You may include options that will be used by all distutils commands, +# and by easy_install. For instance: +# +# [easy_install] +# find_links = http://mylocalsite diff --git a/env/lib/python2.7/encodings b/env/lib/python2.7/encodings new file mode 120000 index 0000000..1250ad8 --- /dev/null +++ b/env/lib/python2.7/encodings @@ -0,0 +1 @@ +/usr/lib/python2.7/encodings \ No newline at end of file diff --git a/env/lib/python2.7/fnmatch.py b/env/lib/python2.7/fnmatch.py new file mode 120000 index 0000000..ec3e10c --- /dev/null +++ b/env/lib/python2.7/fnmatch.py @@ -0,0 +1 @@ +/usr/lib/python2.7/fnmatch.py \ No newline at end of file diff --git a/env/lib/python2.7/fnmatch.pyc b/env/lib/python2.7/fnmatch.pyc new file mode 100644 index 0000000..3152fdf Binary files /dev/null and b/env/lib/python2.7/fnmatch.pyc differ diff --git a/env/lib/python2.7/genericpath.py b/env/lib/python2.7/genericpath.py new file mode 120000 index 0000000..cb8897c --- /dev/null +++ b/env/lib/python2.7/genericpath.py @@ -0,0 +1 @@ +/usr/lib/python2.7/genericpath.py \ No newline at end of file diff --git a/env/lib/python2.7/genericpath.pyc b/env/lib/python2.7/genericpath.pyc new file mode 100644 index 0000000..0d1e519 Binary files /dev/null and b/env/lib/python2.7/genericpath.pyc differ diff --git a/env/lib/python2.7/lib-dynload b/env/lib/python2.7/lib-dynload new file mode 120000 index 0000000..c706a1e --- /dev/null +++ b/env/lib/python2.7/lib-dynload @@ -0,0 +1 @@ +/usr/lib/python2.7/lib-dynload \ No newline at end of file diff --git a/env/lib/python2.7/linecache.py b/env/lib/python2.7/linecache.py new file mode 120000 index 0000000..943c429 --- /dev/null +++ b/env/lib/python2.7/linecache.py @@ -0,0 +1 @@ +/usr/lib/python2.7/linecache.py \ No newline at end of file diff --git a/env/lib/python2.7/linecache.pyc b/env/lib/python2.7/linecache.pyc new file mode 100644 index 0000000..cb8716a Binary files /dev/null and b/env/lib/python2.7/linecache.pyc differ diff --git a/env/lib/python2.7/locale.py b/env/lib/python2.7/locale.py new file mode 120000 index 0000000..92c243c --- /dev/null +++ b/env/lib/python2.7/locale.py @@ -0,0 +1 @@ +/usr/lib/python2.7/locale.py \ No newline at end of file diff --git a/env/lib/python2.7/locale.pyc b/env/lib/python2.7/locale.pyc new file mode 100644 index 0000000..5986d25 Binary files /dev/null and b/env/lib/python2.7/locale.pyc differ diff --git a/env/lib/python2.7/no-global-site-packages.txt b/env/lib/python2.7/no-global-site-packages.txt new file mode 100644 index 0000000..e69de29 diff --git a/env/lib/python2.7/ntpath.py b/env/lib/python2.7/ntpath.py new file mode 120000 index 0000000..5659ae1 --- /dev/null +++ b/env/lib/python2.7/ntpath.py @@ -0,0 +1 @@ +/usr/lib/python2.7/ntpath.py \ No newline at end of file diff --git a/env/lib/python2.7/orig-prefix.txt b/env/lib/python2.7/orig-prefix.txt new file mode 100644 index 0000000..e25db58 --- /dev/null +++ b/env/lib/python2.7/orig-prefix.txt @@ -0,0 +1 @@ +/usr \ No newline at end of file diff --git a/env/lib/python2.7/os.py b/env/lib/python2.7/os.py new file mode 120000 index 0000000..950fc8d --- /dev/null +++ b/env/lib/python2.7/os.py @@ -0,0 +1 @@ +/usr/lib/python2.7/os.py \ No newline at end of file diff --git a/env/lib/python2.7/os.pyc b/env/lib/python2.7/os.pyc new file mode 100644 index 0000000..f894a44 Binary files /dev/null and b/env/lib/python2.7/os.pyc differ diff --git a/env/lib/python2.7/posixpath.py b/env/lib/python2.7/posixpath.py new file mode 120000 index 0000000..30cb8ca --- /dev/null +++ b/env/lib/python2.7/posixpath.py @@ -0,0 +1 @@ +/usr/lib/python2.7/posixpath.py \ No newline at end of file diff --git a/env/lib/python2.7/posixpath.pyc b/env/lib/python2.7/posixpath.pyc new file mode 100644 index 0000000..5ceaf05 Binary files /dev/null and b/env/lib/python2.7/posixpath.pyc differ diff --git a/env/lib/python2.7/re.py b/env/lib/python2.7/re.py new file mode 120000 index 0000000..56a0731 --- /dev/null +++ b/env/lib/python2.7/re.py @@ -0,0 +1 @@ +/usr/lib/python2.7/re.py \ No newline at end of file diff --git a/env/lib/python2.7/re.pyc b/env/lib/python2.7/re.pyc new file mode 100644 index 0000000..927e838 Binary files /dev/null and b/env/lib/python2.7/re.pyc differ diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/DESCRIPTION.rst b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..cfe1e6d --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/DESCRIPTION.rst @@ -0,0 +1,40 @@ +Flask +----- + +Flask is a microframework for Python based on Werkzeug, Jinja 2 and good +intentions. And before you ask: It's BSD licensed! + +Flask is Fun +```````````` + +.. code:: python + + from flask import Flask + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello World!" + + if __name__ == "__main__": + app.run() + +And Easy to Setup +````````````````` + +.. code:: bash + + $ pip install Flask + $ python hello.py + * Running on http://localhost:5000/ + +Links +````` + +* `website `_ +* `documentation `_ +* `development version + `_ + + + diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/INSTALLER b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/METADATA b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/METADATA new file mode 100644 index 0000000..a129f6d --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/METADATA @@ -0,0 +1,62 @@ +Metadata-Version: 2.0 +Name: Flask +Version: 0.10.1 +Summary: A microframework based on Werkzeug, Jinja2 and good intentions +Home-page: http://github.com/mitsuhiko/flask/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Platform: any +Classifier: Development Status :: 4 - Beta +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Requires-Dist: Werkzeug (>=0.7) +Requires-Dist: Jinja2 (>=2.4) +Requires-Dist: itsdangerous (>=0.21) + +Flask +----- + +Flask is a microframework for Python based on Werkzeug, Jinja 2 and good +intentions. And before you ask: It's BSD licensed! + +Flask is Fun +```````````` + +.. code:: python + + from flask import Flask + app = Flask(__name__) + + @app.route("/") + def hello(): + return "Hello World!" + + if __name__ == "__main__": + app.run() + +And Easy to Setup +````````````````` + +.. code:: bash + + $ pip install Flask + $ python hello.py + * Running on http://localhost:5000/ + +Links +````` + +* `website `_ +* `documentation `_ +* `development version + `_ + + + diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/RECORD b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/RECORD new file mode 100644 index 0000000..990d045 --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/RECORD @@ -0,0 +1,148 @@ +Flask-0.10.1.dist-info/DESCRIPTION.rst,sha256=YsWE_jM8p5TWeiY2cuesAHH5JUW95FFaHKvruzGCg5o,694 +Flask-0.10.1.dist-info/METADATA,sha256=R0Epx982RlWRzCkkSHWbqD7n9XaqCt-etgGGrwAixNQ,1507 +Flask-0.10.1.dist-info/RECORD,, +Flask-0.10.1.dist-info/WHEEL,sha256=siaGhHNH1IivIQO0_6mMI-08XttA7Qr2K9-kq5rC0zk,96 +Flask-0.10.1.dist-info/metadata.json,sha256=O6IXOh9JYAwPP15bGNxo_YGPplzd_i4Yr8CTGsa_8LM,973 +Flask-0.10.1.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 +flask/__init__.py,sha256=f2QCGRK-AATcoOyDoSGPJJgnSHvNr-qdII-aqJpicYY,1674 +flask/_compat.py,sha256=ug9fCmzhMFE1ecCpZLvbHSTXluYCcLXt3_8SNwGNZyg,2164 +flask/app.py,sha256=Tr9IRAwdYmUQc6vMNE3ccpavtxQx2cmFXhzU7KSba7I,76782 +flask/blueprints.py,sha256=OBo5Mkl_y54l0xPuLptXz54CDvvRX5tApMKIXyvykTk,16320 +flask/config.py,sha256=NhTkQX2yFgPDZD-t3phxcS2kw6i2kA7RHgX0fDoHXbQ,6234 +flask/ctx.py,sha256=Ka_Ql-ZgRU7z9aVkET0_WwwTKguaUozg3ezDcm-tUKY,14266 +flask/debughelpers.py,sha256=iyJC--eX8ANvci4MsFbtwc_PkwVlbCrZGHCOnQsOHFs,3508 +flask/exthook.py,sha256=dfW3DBBI8LyPrwacwZN8q0u0Q8gBBCXtocJ7wBnvgAs,5087 +flask/globals.py,sha256=kNGf5b05C8AjTzZJhBUbbtgufgumOnAPk9g_LYh0Rv0,1137 +flask/helpers.py,sha256=roTv_nwOjhAhUWvW-Uz_Ex9SLA32mEx_7vfZagZjizA,33793 +flask/json.py,sha256=5d-FWvZfzun2JKpapE_fwk_-db0cYvrc5OO-MJsAdgk,8113 +flask/logging.py,sha256=EkiNIJbQyeUb8nipAURO8CQJwC4BESjkM_snQIRCeIc,1398 +flask/module.py,sha256=2J_pmW7jaFye1FtNTn5jfX-HxBqMc9EZzSLUXxiV-7c,1363 +flask/sessions.py,sha256=JU7E5KolMOyItlNNREwGv3RKBnmQW1vd4gHghrQwULI,13107 +flask/signals.py,sha256=DmcQfKzlPdLoY00fxf2BsH3SsDFiFSppCbX9Yfdv_ng,2140 +flask/templating.py,sha256=joMsvkTasZUJxdipA0BnrbfIMidzzBzPug-dIaW0Tzo,4707 +flask/testing.py,sha256=C8b-44Ro9hsFH5-eBksgjBWLrPznESmX9rdMFBkIbp4,5003 +flask/views.py,sha256=S2fRXcRsyy6FUKJ9tZh39LLH22vOeZvYMLZQKT1pc6Y,5642 +flask/wrappers.py,sha256=67pssdNN3I4dKSVUVru5HNUteAeF2V6_7qpLZoVwmiI,6709 +flask/ext/__init__.py,sha256=M97BrvCtJFgcWpt8Jo1qg2nLkQaGd-4whLkdHfi-rE8,842 +flask/testsuite/__init__.py,sha256=zCtem4AVtj6_GSTxCFUHElbH3g6LYY9ApIr7NVUWmGU,7022 +flask/testsuite/appctx.py,sha256=vt0c0gfqcUYXfJ7t2IRd3Gg0BzSaLKO2bx9d5Id7m6M,3116 +flask/testsuite/basic.py,sha256=zw2tDp2g3ptgUWfjwISAcnp5hBXGCj3Wu3jwAgMBRbI,43777 +flask/testsuite/blueprints.py,sha256=uLsqDu1AyTPeQJ6Ab1RHKPcYbo5s-7adSW5XSE1Fa0o,28089 +flask/testsuite/config.py,sha256=h64-JdPdlU6a7O8YfwAEriYZ30yAD1c_vjjYgyJ-JzA,11820 +flask/testsuite/deprecations.py,sha256=tsvmOrjcG1tV6vV4ySL5a7V4o77Tnf4wd_-yqVhUXIc,511 +flask/testsuite/examples.py,sha256=KyCnXuKNFfBEAyPl12a-etPF_PRufrJGwP09zTvl714,942 +flask/testsuite/ext.py,sha256=5jOofZijgqi5OmRV7YxB7RS-RY7HuSj3L90316yH_IY,5156 +flask/testsuite/helpers.py,sha256=O_pZrLMqnltQczhsvr2zf9doCz9Nc9Fp-H51Ktx7-hY,21973 +flask/testsuite/regression.py,sha256=QDMe2hkgu3lV8RaUhHsICciKWhSC6L2TaYe9qITlyL8,3198 +flask/testsuite/reqctx.py,sha256=EriP7GP23zt3zWKabTvEzldvp0EqRe--v8W-ZKwCz9k,5960 +flask/testsuite/signals.py,sha256=jclEzgHqRhPgM3uoxRbgmXIiFm_HWlrkqT5M0hBv5xw,4807 +flask/testsuite/subclassing.py,sha256=TT-nltJBy1Xi1BxcdztGZ3hmMq9h_nk1CVeSy9qBrXQ,1214 +flask/testsuite/templating.py,sha256=2lg2-MPMGkmlKap9M711uVXC08iZU8w3EtmTI2la_N8,11237 +flask/testsuite/testing.py,sha256=ihNMpcAxZ3wArSjUvFuCaHSREgjQNV5UAS2W1vYSNt4,7411 +flask/testsuite/views.py,sha256=2ThDMtk1zoMvuXzRuP1Wh3e_hgDwPtyu76TXycVyhqc,5068 +flask/testsuite/static/index.html,sha256=f28C_muYEAWoHyfaubxti-TLB0wMjFZHII3e9TRsmsI,22 +flask/testsuite/templates/_macro.html,sha256=XA2qnwpJpO3auSjZlKXODzeU4Fcnim12ie5lMXeL8ms,55 +flask/testsuite/templates/context_template.html,sha256=hXvHzdggsqqO2eXRlb6EhGDTTzPIQicaMk2EibzagDQ,36 +flask/testsuite/templates/escaping_template.html,sha256=ORPM3QIOIu_lWv9M101bPHZt-bmy8Biu2663aAoO50g,147 +flask/testsuite/templates/mail.txt,sha256=8f9j1PxUo_deGbrpJuDdrii16qE-xtV9RU6mYPVE_64,14 +flask/testsuite/templates/simple_template.html,sha256=d0akkxWQ1UQkDiL45b8nUvCE0KpL579DhioYlv713bE,23 +flask/testsuite/templates/template_filter.html,sha256=ZIk3H4Oa8fDn62Ij6jDzdHukLj3RXGtmBnkEtgTUmQ0,25 +flask/testsuite/templates/template_test.html,sha256=g3ZgUQN0PaOiz289_AxNeP3ICfR29ogzbQl3fCvxK_8,51 +flask/testsuite/templates/nested/nested.txt,sha256=76PlNDtwDVWjZMPHRlBqSX95jY52e_RWZCJKZfRWkAU,11 +flask/testsuite/test_apps/config_module_app.py,sha256=BaBJCCI4TcOc9Kc5OvlgmaCtfQH8D31xVZMLZ3FmyRE,101 +flask/testsuite/test_apps/flask_newext_simple.py,sha256=IIsV29nQ37pV2Z3O8GQ5a33YkIlII8B0rbOqz5k4ZxQ,25 +flask/testsuite/test_apps/importerror.py,sha256=gA8IjK673B4Rit7pYYnkspF2k9_zpztPmiMYgrwgzdk,46 +flask/testsuite/test_apps/main_app.py,sha256=mah5bd5ObZV6bl4YbnJEEdQcr5NqgMFmZqcaAITIReE,90 +flask/testsuite/test_apps/blueprintapp/__init__.py,sha256=OeOuAvS6IghuIekcXqfgPuoACL6JSxKw_xOpvgTx7lE,200 +flask/testsuite/test_apps/blueprintapp/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/testsuite/test_apps/blueprintapp/apps/admin/__init__.py,sha256=L5kSKkfOewREXLveDLogxtGyF2UrkIczxo4PZrjYCl8,362 +flask/testsuite/test_apps/blueprintapp/apps/admin/static/test.txt,sha256=lcPiuni6LR_rw5mxyjRmz8iMcifiSSNqPFlIrmLKzjY,11 +flask/testsuite/test_apps/blueprintapp/apps/admin/static/css/test.css,sha256=F1DG-ABW3o6yAD9Nc6IzV9iYefZeOHhn59009LMJboY,18 +flask/testsuite/test_apps/blueprintapp/apps/admin/templates/admin/index.html,sha256=2OWS6QYqxaarnZAWkLvam0P2QSodRNkA6M05eEOVLw4,21 +flask/testsuite/test_apps/blueprintapp/apps/frontend/__init__.py,sha256=djItvU0fqQg-MOlVoJR3--6cYf4VT1SI0WFsQyjQk4o,204 +flask/testsuite/test_apps/blueprintapp/apps/frontend/templates/frontend/index.html,sha256=hcC7DORSYxGNK5DAICVx1BeFVlzaanxcIhODQwm9rwg,24 +flask/testsuite/test_apps/config_package_app/__init__.py,sha256=BaBJCCI4TcOc9Kc5OvlgmaCtfQH8D31xVZMLZ3FmyRE,101 +flask/testsuite/test_apps/flask_broken/__init__.py,sha256=CDC0TTkjrjeLs7ZXzLwdjS0yFiE2DM9uZ65q927Xx-c,48 +flask/testsuite/test_apps/flask_broken/b.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/testsuite/test_apps/flask_newext_package/__init__.py,sha256=UX_8L5rL7scxeUhXbUklOXDzE16eQ0eSdykHJvCe9O4,26 +flask/testsuite/test_apps/flask_newext_package/submodule.py,sha256=VBKM2Msdeq6F7ziaPiwTbcu9c4wAH4kKZH6FDUPi6zg,35 +flask/testsuite/test_apps/flaskext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/testsuite/test_apps/flaskext/oldext_simple.py,sha256=fuHRIiStUQIS-JoiE_Vwkc_nRX3qkMETN1yBtEDQyck,25 +flask/testsuite/test_apps/flaskext/oldext_package/__init__.py,sha256=u6W0k3--q15e2nTlDWvTA0gvu1EuvaJQGIb-y9gPe8A,26 +flask/testsuite/test_apps/flaskext/oldext_package/submodule.py,sha256=VBKM2Msdeq6F7ziaPiwTbcu9c4wAH4kKZH6FDUPi6zg,35 +flask/testsuite/test_apps/lib/python2.5/site-packages/SiteEgg.egg,sha256=fVBqIK3Yab7f_mM6B5dZO2zN1N9abqQKS1xRIbKNsgc,1218 +flask/testsuite/test_apps/lib/python2.5/site-packages/site_app.py,sha256=yObUTJgzGrSHwp-eLsE-bMbGmKLogUdE6bCn7jQPR6A,42 +flask/testsuite/test_apps/lib/python2.5/site-packages/site_package/__init__.py,sha256=yObUTJgzGrSHwp-eLsE-bMbGmKLogUdE6bCn7jQPR6A,42 +flask/testsuite/test_apps/moduleapp/__init__.py,sha256=x5mMfvASdMFFNFp0tq2Fwpp_-9DxNlRwHIFxj_bhbnQ,188 +flask/testsuite/test_apps/moduleapp/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 +flask/testsuite/test_apps/moduleapp/apps/admin/__init__.py,sha256=ESnyU_sz54kX22RJUOyciuHlGz0_c9d1qGxrzke9V7E,259 +flask/testsuite/test_apps/moduleapp/apps/admin/static/test.txt,sha256=lcPiuni6LR_rw5mxyjRmz8iMcifiSSNqPFlIrmLKzjY,11 +flask/testsuite/test_apps/moduleapp/apps/admin/static/css/test.css,sha256=F1DG-ABW3o6yAD9Nc6IzV9iYefZeOHhn59009LMJboY,18 +flask/testsuite/test_apps/moduleapp/apps/admin/templates/index.html,sha256=2OWS6QYqxaarnZAWkLvam0P2QSodRNkA6M05eEOVLw4,21 +flask/testsuite/test_apps/moduleapp/apps/frontend/__init__.py,sha256=qtVGS_XzTw3uxAyEcOi49uXB4o-u4ZEZLQrhwIUkEME,158 +flask/testsuite/test_apps/moduleapp/apps/frontend/templates/index.html,sha256=hcC7DORSYxGNK5DAICVx1BeFVlzaanxcIhODQwm9rwg,24 +flask/testsuite/test_apps/path/installed_package/__init__.py,sha256=yObUTJgzGrSHwp-eLsE-bMbGmKLogUdE6bCn7jQPR6A,42 +flask/testsuite/test_apps/subdomaintestmodule/__init__.py,sha256=o7W5jKRXGVqfjwYKWjI3QX8WUztGxuVnGiZ-wSGd1Fk,74 +flask/testsuite/test_apps/subdomaintestmodule/static/hello.txt,sha256=5PvE5WQoKT9dXkOTZ63vfG9F0iAysyTmSTX0dA4uiQI,16 +Flask-0.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flask/config.pyc,, +flask/testsuite/deprecations.pyc,, +flask/testsuite/test_apps/flaskext/oldext_package/__init__.pyc,, +flask/testsuite/test_apps/blueprintapp/__init__.pyc,, +flask/testsuite/regression.pyc,, +flask/__init__.pyc,, +flask/debughelpers.pyc,, +flask/testsuite/signals.pyc,, +flask/testsuite/examples.pyc,, +flask/testsuite/test_apps/blueprintapp/apps/frontend/__init__.pyc,, +flask/testsuite/test_apps/moduleapp/__init__.pyc,, +flask/testsuite/test_apps/moduleapp/apps/__init__.pyc,, +flask/sessions.pyc,, +flask/logging.pyc,, +flask/testsuite/subclassing.pyc,, +flask/testsuite/test_apps/path/installed_package/__init__.pyc,, +flask/testsuite/basic.pyc,, +flask/testsuite/test_apps/flask_broken/__init__.pyc,, +flask/module.pyc,, +flask/testsuite/config.pyc,, +flask/testsuite/test_apps/importerror.pyc,, +flask/testsuite/test_apps/flaskext/oldext_simple.pyc,, +flask/testsuite/__init__.pyc,, +flask/testsuite/test_apps/lib/python2.5/site-packages/site_package/__init__.pyc,, +flask/globals.pyc,, +flask/testsuite/test_apps/config_package_app/__init__.pyc,, +flask/testsuite/test_apps/moduleapp/apps/frontend/__init__.pyc,, +flask/testsuite/test_apps/lib/python2.5/site-packages/site_app.pyc,, +flask/testsuite/test_apps/subdomaintestmodule/__init__.pyc,, +flask/views.pyc,, +flask/json.pyc,, +flask/testsuite/test_apps/flask_newext_simple.pyc,, +flask/testsuite/test_apps/flask_broken/b.pyc,, +flask/testsuite/test_apps/flask_newext_package/__init__.pyc,, +flask/testsuite/test_apps/config_module_app.pyc,, +flask/testsuite/blueprints.pyc,, +flask/testsuite/test_apps/flaskext/oldext_package/submodule.pyc,, +flask/blueprints.pyc,, +flask/testsuite/test_apps/flaskext/__init__.pyc,, +flask/exthook.pyc,, +flask/testsuite/test_apps/blueprintapp/apps/__init__.pyc,, +flask/testsuite/templating.pyc,, +flask/testsuite/test_apps/main_app.pyc,, +flask/testsuite/testing.pyc,, +flask/_compat.pyc,, +flask/testsuite/test_apps/moduleapp/apps/admin/__init__.pyc,, +flask/testsuite/appctx.pyc,, +flask/app.pyc,, +flask/ext/__init__.pyc,, +flask/testing.pyc,, +flask/wrappers.pyc,, +flask/testsuite/helpers.pyc,, +flask/helpers.pyc,, +flask/testsuite/views.pyc,, +flask/signals.pyc,, +flask/testsuite/test_apps/flask_newext_package/submodule.pyc,, +flask/templating.pyc,, +flask/testsuite/test_apps/blueprintapp/apps/admin/__init__.pyc,, +flask/testsuite/reqctx.pyc,, +flask/ctx.pyc,, +flask/testsuite/ext.pyc,, diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/WHEEL b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/WHEEL new file mode 100644 index 0000000..79e7cc9 --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.30.0.a0) +Root-Is-Purelib: true +Tag: cp27-none-any + diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/metadata.json b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/metadata.json new file mode 100644 index 0000000..d26fb9b --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules"], "extensions": {"python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/mitsuhiko/flask/"}}}, "extras": [], "generator": "bdist_wheel (0.30.0.a0)", "license": "BSD", "metadata_version": "2.0", "name": "Flask", "platform": "any", "run_requires": [{"requires": ["Jinja2 (>=2.4)", "Werkzeug (>=0.7)", "itsdangerous (>=0.21)"]}], "summary": "A microframework based on Werkzeug, Jinja2 and good intentions", "version": "0.10.1"} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/top_level.txt b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/top_level.txt new file mode 100644 index 0000000..7e10602 --- /dev/null +++ b/env/lib/python2.7/site-packages/Flask-0.10.1.dist-info/top_level.txt @@ -0,0 +1 @@ +flask diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/DESCRIPTION.rst b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..4421f04 --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/DESCRIPTION.rst @@ -0,0 +1,36 @@ +Jinja2 +~~~~~~ + +Jinja2 is a template engine written in pure Python. It provides a +`Django`_ inspired non-XML syntax but supports inline expressions and +an optional `sandboxed`_ environment. + +Nutshell +-------- + +Here a small example of a Jinja template:: + + {% extends 'base.html' %} + {% block title %}Memberlist{% endblock %} + {% block content %} + + {% endblock %} + +Philosophy +---------- + +Application logic is for the controller but don't try to make the life +for the template designer too hard by giving him too few functionality. + +For more informations visit the new `Jinja2 webpage`_ and `documentation`_. + +.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security) +.. _Django: http://www.djangoproject.com/ +.. _Jinja2 webpage: http://jinja.pocoo.org/ +.. _documentation: http://jinja.pocoo.org/2/documentation/ + + diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/INSTALLER b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/METADATA b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/METADATA new file mode 100644 index 0000000..304d7c9 --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/METADATA @@ -0,0 +1,63 @@ +Metadata-Version: 2.0 +Name: Jinja2 +Version: 2.8 +Summary: A small but fast and easy to use stand-alone template engine written in pure python. +Home-page: http://jinja.pocoo.org/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML +Requires-Dist: MarkupSafe +Provides-Extra: i18n +Requires-Dist: Babel (>=0.8); extra == 'i18n' + +Jinja2 +~~~~~~ + +Jinja2 is a template engine written in pure Python. It provides a +`Django`_ inspired non-XML syntax but supports inline expressions and +an optional `sandboxed`_ environment. + +Nutshell +-------- + +Here a small example of a Jinja template:: + + {% extends 'base.html' %} + {% block title %}Memberlist{% endblock %} + {% block content %} + + {% endblock %} + +Philosophy +---------- + +Application logic is for the controller but don't try to make the life +for the template designer too hard by giving him too few functionality. + +For more informations visit the new `Jinja2 webpage`_ and `documentation`_. + +.. _sandboxed: http://en.wikipedia.org/wiki/Sandbox_(computer_security) +.. _Django: http://www.djangoproject.com/ +.. _Jinja2 webpage: http://jinja.pocoo.org/ +.. _documentation: http://jinja.pocoo.org/2/documentation/ + + diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/RECORD b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/RECORD new file mode 100644 index 0000000..b81a609 --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/RECORD @@ -0,0 +1,54 @@ +jinja2/__init__.py,sha256=c59bnaAFo63I7lYUZlO2UKHj8LPG3JACKnCrwWgvjGY,2326 +jinja2/_compat.py,sha256=O4FnYOMi4HRBfoCKkX137tt3sR6HvpnQNcwqg8ARYog,3109 +jinja2/_stringdefs.py,sha256=SFObWX5vSMeGNc_aSO3_B2EEmScCstFWtjS4K0YFBXk,404291 +jinja2/bccache.py,sha256=EMN9fsvOpwK3DfxQ9F1lmWoxU2Qlo6AnNhPXTsMrw84,12793 +jinja2/compiler.py,sha256=nQmoS6HpGwgDIC8UXkSdjPYiAjbVqZ-Gf4odO-SAR6E,63846 +jinja2/constants.py,sha256=DCr-oKC2xQO-fkOQO3kXRJW7rEYgmcsMRNpPnM66YSU,1626 +jinja2/debug.py,sha256=GEGHM8vFsNFF-kGc0_fwyj1ftMtuyaH4r0nyG-XA9Z8,11553 +jinja2/defaults.py,sha256=eLMOE7JC52QwZBu5Gz4TPZqzoJy9IgV5EynL_pW7MUw,1057 +jinja2/environment.py,sha256=jzJmujSFtxb1HvITO4TdUCOOA-hSZx0gHrxeDZ2VE-M,48120 +jinja2/exceptions.py,sha256=Q9yZOUif-lhVj5BRw0ELjfBvEdBsB7xZobgOvC2qGy4,4428 +jinja2/ext.py,sha256=X-1zCiut1cuxIteKPkJr3jb6odlVE1jciO8RnrMniPE,25072 +jinja2/filters.py,sha256=R4x2flPfyzIjrtItzpGpK4LzBvx-NOlEXH9wD-ZBWtU,30115 +jinja2/lexer.py,sha256=QyiQwAQVEE2YREZJLcA04F3yqv0XOwBbSlWaFW4xJ20,28425 +jinja2/loaders.py,sha256=BgDCvmiB0gH_zPMf-6TMemqtJdrck3IyJ8g0kWUvFa0,17380 +jinja2/meta.py,sha256=cxAOtMuSWWSQX2H8zhYsAtjNwRcNB8Zvs06Y-JlWnbk,4198 +jinja2/nodes.py,sha256=YN6hfFa0WlfToG2r-Q-yhUkAUp0O9l8KulK53mOAVUo,28954 +jinja2/optimizer.py,sha256=bNNKbo5SC5FBUm9dvP-I3GkiXZYBYIER7_g9hK77ZVI,2302 +jinja2/parser.py,sha256=pjLfkZDg2IKJKt_ixNosV-RzwAja5GWYuVeBQumIRns,35442 +jinja2/runtime.py,sha256=Ct36Q9-gVmKer45syS4j3thQ15T_DnLDh6CqvTcnPwQ,22530 +jinja2/sandbox.py,sha256=qgH4CoBsF5NwGj0krqsCOw8sg2mXmfpZKnvmZEE-da4,13327 +jinja2/tests.py,sha256=znB0L_k6wdKp_lQJvxboXwUXDy1HhFe5SSA888tHt_w,4131 +jinja2/utils.py,sha256=pjbOhQJ5NYexu2MbjA66nBibudUkYcQRZbxvbYE0tFk,16560 +jinja2/visitor.py,sha256=3hEAYD26xS_JiJBf4RfcqYPpiuR6efOH8Hh6om59eU8,3316 +Jinja2-2.8.dist-info/DESCRIPTION.rst,sha256=CXIS1UnPSk5_lZBS6Lb8ko-3lqGfjsiUwNBLXCTj2lc,975 +Jinja2-2.8.dist-info/entry_points.txt,sha256=NdzVcOrqyNyKDxD09aERj__3bFx2paZhizFDsKmVhiA,72 +Jinja2-2.8.dist-info/METADATA,sha256=Vio5F8qaEVcGzaCV1rl8tIWEKsHUFSSSAfL0u9oMmGk,2061 +Jinja2-2.8.dist-info/metadata.json,sha256=4TsqsSBwGwy0C2xF_uRZHYsRn2W5Lv4NUMBjTnXPldM,1275 +Jinja2-2.8.dist-info/RECORD,, +Jinja2-2.8.dist-info/top_level.txt,sha256=PkeVWtLb3-CqjWi1fO29OCbj55EhX_chhKrCdrVe_zs,7 +Jinja2-2.8.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 +Jinja2-2.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +jinja2/_compat.pyc,, +jinja2/defaults.pyc,, +jinja2/sandbox.pyc,, +jinja2/_stringdefs.pyc,, +jinja2/ext.pyc,, +jinja2/runtime.pyc,, +jinja2/utils.pyc,, +jinja2/parser.pyc,, +jinja2/debug.pyc,, +jinja2/lexer.pyc,, +jinja2/bccache.pyc,, +jinja2/visitor.pyc,, +jinja2/nodes.pyc,, +jinja2/environment.pyc,, +jinja2/compiler.pyc,, +jinja2/exceptions.pyc,, +jinja2/__init__.pyc,, +jinja2/constants.pyc,, +jinja2/meta.pyc,, +jinja2/optimizer.pyc,, +jinja2/tests.pyc,, +jinja2/loaders.pyc,, +jinja2/filters.pyc,, diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/WHEEL b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/WHEEL new file mode 100644 index 0000000..9dff69d --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.24.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/entry_points.txt b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/entry_points.txt new file mode 100644 index 0000000..32e6b75 --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/entry_points.txt @@ -0,0 +1,4 @@ + + [babel.extractors] + jinja2 = jinja2.ext:babel_extract[i18n] + \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/metadata.json b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/metadata.json new file mode 100644 index 0000000..f5b1ffa --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/metadata.json @@ -0,0 +1 @@ +{"license": "BSD", "name": "Jinja2", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "A small but fast and easy to use stand-alone template engine written in pure python.", "run_requires": [{"requires": ["Babel (>=0.8)"], "extra": "i18n"}, {"requires": ["MarkupSafe"]}], "version": "2.8", "extensions": {"python.details": {"project_urls": {"Home": "http://jinja.pocoo.org/"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "armin.ronacher@active-4.com", "name": "Armin Ronacher"}]}, "python.exports": {"babel.extractors": {"jinja2": "jinja2.ext:babel_extract [i18n]"}}}, "classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup :: HTML"], "extras": ["i18n"]} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/top_level.txt b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/top_level.txt new file mode 100644 index 0000000..7f7afbf --- /dev/null +++ b/env/lib/python2.7/site-packages/Jinja2-2.8.dist-info/top_level.txt @@ -0,0 +1 @@ +jinja2 diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/DESCRIPTION.rst b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..67256b9 --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/DESCRIPTION.rst @@ -0,0 +1,101 @@ +MarkupSafe +========== + +Implements a unicode subclass that supports HTML strings: + +>>> from markupsafe import Markup, escape +>>> escape("") +Markup(u'<script>alert(document.cookie);</script>') +>>> tmpl = Markup("%s") +>>> tmpl % "Peter > Lustig" +Markup(u'Peter > Lustig') + +If you want to make an object unicode that is not yet unicode +but don't want to lose the taint information, you can use the +`soft_unicode` function. (On Python 3 you can also use `soft_str` which +is a different name for the same function). + +>>> from markupsafe import soft_unicode +>>> soft_unicode(42) +u'42' +>>> soft_unicode(Markup('foo')) +Markup(u'foo') + +HTML Representations +-------------------- + +Objects can customize their HTML markup equivalent by overriding +the `__html__` function: + +>>> class Foo(object): +... def __html__(self): +... return 'Nice' +... +>>> escape(Foo()) +Markup(u'Nice') +>>> Markup(Foo()) +Markup(u'Nice') + +Silent Escapes +-------------- + +Since MarkupSafe 0.10 there is now also a separate escape function +called `escape_silent` that returns an empty string for `None` for +consistency with other systems that return empty strings for `None` +when escaping (for instance Pylons' webhelpers). + +If you also want to use this for the escape method of the Markup +object, you can create your own subclass that does that:: + + from markupsafe import Markup, escape_silent as escape + + class SilentMarkup(Markup): + __slots__ = () + + @classmethod + def escape(cls, s): + return cls(escape(s)) + +New-Style String Formatting +--------------------------- + +Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and +3.x are now fully supported. Previously the escape behavior of those +functions was spotty at best. The new implementations operates under the +following algorithm: + +1. if an object has an ``__html_format__`` method it is called as + replacement for ``__format__`` with the format specifier. It either + has to return a string or markup object. +2. if an object has an ``__html__`` method it is called. +3. otherwise the default format system of Python kicks in and the result + is HTML escaped. + +Here is how you can implement your own formatting:: + + class User(object): + + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + + def __html__(self): + return Markup('{0}').format(self.username) + +And to format that user: + +>>> user = User(1, 'foo') +>>> Markup('

User: {0:link}').format(user) +Markup(u'

User: foo') + + diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/INSTALLER b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/METADATA b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/METADATA new file mode 100644 index 0000000..d06751b --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/METADATA @@ -0,0 +1,121 @@ +Metadata-Version: 2.0 +Name: MarkupSafe +Version: 0.23 +Summary: Implements a XML/HTML/XHTML Markup safe string for Python +Home-page: http://github.com/mitsuhiko/markupsafe +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup :: HTML + +MarkupSafe +========== + +Implements a unicode subclass that supports HTML strings: + +>>> from markupsafe import Markup, escape +>>> escape("") +Markup(u'<script>alert(document.cookie);</script>') +>>> tmpl = Markup("%s") +>>> tmpl % "Peter > Lustig" +Markup(u'Peter > Lustig') + +If you want to make an object unicode that is not yet unicode +but don't want to lose the taint information, you can use the +`soft_unicode` function. (On Python 3 you can also use `soft_str` which +is a different name for the same function). + +>>> from markupsafe import soft_unicode +>>> soft_unicode(42) +u'42' +>>> soft_unicode(Markup('foo')) +Markup(u'foo') + +HTML Representations +-------------------- + +Objects can customize their HTML markup equivalent by overriding +the `__html__` function: + +>>> class Foo(object): +... def __html__(self): +... return 'Nice' +... +>>> escape(Foo()) +Markup(u'Nice') +>>> Markup(Foo()) +Markup(u'Nice') + +Silent Escapes +-------------- + +Since MarkupSafe 0.10 there is now also a separate escape function +called `escape_silent` that returns an empty string for `None` for +consistency with other systems that return empty strings for `None` +when escaping (for instance Pylons' webhelpers). + +If you also want to use this for the escape method of the Markup +object, you can create your own subclass that does that:: + + from markupsafe import Markup, escape_silent as escape + + class SilentMarkup(Markup): + __slots__ = () + + @classmethod + def escape(cls, s): + return cls(escape(s)) + +New-Style String Formatting +--------------------------- + +Starting with MarkupSafe 0.21 new style string formats from Python 2.6 and +3.x are now fully supported. Previously the escape behavior of those +functions was spotty at best. The new implementations operates under the +following algorithm: + +1. if an object has an ``__html_format__`` method it is called as + replacement for ``__format__`` with the format specifier. It either + has to return a string or markup object. +2. if an object has an ``__html__`` method it is called. +3. otherwise the default format system of Python kicks in and the result + is HTML escaped. + +Here is how you can implement your own formatting:: + + class User(object): + + def __init__(self, id, username): + self.id = id + self.username = username + + def __html_format__(self, format_spec): + if format_spec == 'link': + return Markup('{1}').format( + self.id, + self.__html__(), + ) + elif format_spec: + raise ValueError('Invalid format spec') + return self.__html__() + + def __html__(self): + return Markup('{0}').format(self.username) + +And to format that user: + +>>> user = User(1, 'foo') +>>> Markup('

User: {0:link}').format(user) +Markup(u'

User: foo') + + diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/RECORD b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/RECORD new file mode 100644 index 0000000..0d5f3ef --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/RECORD @@ -0,0 +1,19 @@ +MarkupSafe-0.23.dist-info/DESCRIPTION.rst,sha256=VnEbwPneiOkqh-nzxb0DUiGlcVGHuaDQjsNBLi-yNYw,3091 +MarkupSafe-0.23.dist-info/METADATA,sha256=g-KikeSr9J7vagkJoCt0ViT2ORy9O4NYV7XtRu1Pni8,3879 +MarkupSafe-0.23.dist-info/RECORD,, +MarkupSafe-0.23.dist-info/WHEEL,sha256=LgENoDL_AkiRWbJ7HCJLnTXVvHl9ZtXZ7UZmjmcCeN0,105 +MarkupSafe-0.23.dist-info/metadata.json,sha256=y9yFyMJYU3UIRc5KfHIY6A3Z6nvJ2lXva5-7Ts2lsvY,901 +MarkupSafe-0.23.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 +markupsafe/__init__.py,sha256=zFQpANILi3mCCALiPd6ZJdlW6ibu_hTKzikMXKXVtaM,10338 +markupsafe/_compat.py,sha256=r1HE0CpcAZeb-AiTV9wITR91PeLHn0CzZ_XHkYoozpI,565 +markupsafe/_constants.py,sha256=U_xybFQsyXKCgHSfranJnFzo-z9nn9fuBeSk243sE5Q,4795 +markupsafe/_native.py,sha256=E2Un1ysOf-w45d18YCj8UelT5UP7Vt__IuFPYJ7YRIs,1187 +markupsafe/_speedups.c,sha256=gZwPEM_0zcbAzJjPuPYXk97R67QR1uUGtDvOPsvirCA,5939 +markupsafe/_speedups.so,sha256=sgKXWN9UyR7Q8Ny4a5vbhRs9BNBdMlDQMSzuG7wmgos,28296 +markupsafe/tests.py,sha256=RLI4eYI0ICNZwkoN638VHXf_fDu4d_jnvbGr22j58Ng,6107 +MarkupSafe-0.23.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +markupsafe/_constants.pyc,, +markupsafe/__init__.pyc,, +markupsafe/_native.pyc,, +markupsafe/_compat.pyc,, +markupsafe/tests.pyc,, diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/WHEEL b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/WHEEL new file mode 100644 index 0000000..d15279d --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: false +Tag: cp27-cp27mu-linux_x86_64 + diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/metadata.json b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/metadata.json new file mode 100644 index 0000000..21fcd69 --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup :: HTML"], "extensions": {"python.details": {"contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/mitsuhiko/markupsafe"}}}, "generator": "bdist_wheel (0.29.0)", "license": "BSD", "metadata_version": "2.0", "name": "MarkupSafe", "summary": "Implements a XML/HTML/XHTML Markup safe string for Python", "version": "0.23"} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/top_level.txt b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/top_level.txt new file mode 100644 index 0000000..75bf729 --- /dev/null +++ b/env/lib/python2.7/site-packages/MarkupSafe-0.23.dist-info/top_level.txt @@ -0,0 +1 @@ +markupsafe diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/DESCRIPTION.rst b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..94d55d3 --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/DESCRIPTION.rst @@ -0,0 +1,12 @@ +YAML is a data serialization format designed for human readability +and interaction with scripting languages. PyYAML is a YAML parser +and emitter for Python. + +PyYAML features a complete YAML 1.1 parser, Unicode support, pickle +support, capable extension API, and sensible error messages. PyYAML +supports standard YAML tags and provides Python-specific tags that +allow to represent an arbitrary Python object. + +PyYAML is applicable for a broad range of tasks from complex +configuration files to object serialization and persistance. + diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/INSTALLER b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/METADATA b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/METADATA new file mode 100644 index 0000000..bce5c26 --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/METADATA @@ -0,0 +1,38 @@ +Metadata-Version: 2.0 +Name: PyYAML +Version: 3.11 +Summary: YAML parser and emitter for Python +Home-page: http://pyyaml.org/wiki/PyYAML +Author: Kirill Simonov +Author-email: xi@resolvent.net +License: MIT +Download-URL: http://pyyaml.org/download/pyyaml/PyYAML-3.11.tar.gz +Platform: Any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.5 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.0 +Classifier: Programming Language :: Python :: 3.1 +Classifier: Programming Language :: Python :: 3.2 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Text Processing :: Markup + +YAML is a data serialization format designed for human readability +and interaction with scripting languages. PyYAML is a YAML parser +and emitter for Python. + +PyYAML features a complete YAML 1.1 parser, Unicode support, pickle +support, capable extension API, and sensible error messages. PyYAML +supports standard YAML tags and provides Python-specific tags that +allow to represent an arbitrary Python object. + +PyYAML is applicable for a broad range of tasks from complex +configuration files to object serialization and persistance. + diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/RECORD b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/RECORD new file mode 100644 index 0000000..7547577 --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/RECORD @@ -0,0 +1,41 @@ +PyYAML-3.11.dist-info/DESCRIPTION.rst,sha256=4nzkrOwMTYfusIfdRz4-dl_9Blan5axHPKMiVJEOV-4,534 +PyYAML-3.11.dist-info/METADATA,sha256=msEAVWeRV0j1Gl4qjq1bVVnbBOKaK_JgwuTQaB3J3kw,1574 +PyYAML-3.11.dist-info/RECORD,, +PyYAML-3.11.dist-info/WHEEL,sha256=LgENoDL_AkiRWbJ7HCJLnTXVvHl9ZtXZ7UZmjmcCeN0,105 +PyYAML-3.11.dist-info/metadata.json,sha256=lS05dnUMGmQx6-D6WhHSHCdcrngZcRxUAlSkcdT7hLk,1136 +PyYAML-3.11.dist-info/top_level.txt,sha256=rpj0IVMTisAjh_1vG3Ccf9v5jpCQwAz6cD1IVU5ZdhQ,11 +yaml/__init__.py,sha256=sv5xZ_JLSYpES18MopfMSlmWZZf-9tLGXNf8MTYUcag,9776 +yaml/composer.py,sha256=pOjZ5afqNfH22WXyS6xlQCB2PbSrFPjK-qFPOEI76fw,4921 +yaml/constructor.py,sha256=S_Pux76-hgmgtJeJVtSvQ9ynmtEIR2jAx2ljAochKU0,25145 +yaml/cyaml.py,sha256=xK_IxkrRcetZeNwB_wzDAHYCWsumOFfsTlk3CeoM5kQ,3290 +yaml/dumper.py,sha256=ONPYNHirnLm-qCm-h9swnMWzZhncilexboIPRoNdcq4,2719 +yaml/emitter.py,sha256=Xya7zhTX3ykxMAdAgDIedejmLb1Q71W2G4yt4nTSMIM,43298 +yaml/error.py,sha256=7K-NdIv0qNKPKbnXxEg0L_b9K7nYDORr3rzm8_b-iBY,2559 +yaml/events.py,sha256=50_TksgQiE4up-lKo_V-nBy-tAIxkIPQxY5qDhKCeHw,2445 +yaml/loader.py,sha256=t_WLbw1-iWQ4KT_FUppJu30cFIU-l8NCb7bjoXJoV6A,1132 +yaml/nodes.py,sha256=gPKNj8pKCdh2d4gr3gIYINnPOaOxGhJAUiYhGRnPE84,1440 +yaml/parser.py,sha256=sgXahZA3DkySYnaC4D_zcl3l2y4Y5R40icWtdwkF_NE,25542 +yaml/reader.py,sha256=hKuxSbid1rSlfKBsshf5qaPwVduaCJA5t5S9Jum6CAA,6746 +yaml/representer.py,sha256=7rgnnP7ta7rwfCQowrAV36KqK4yG1gNTfMmh0FTG7-Y,17642 +yaml/resolver.py,sha256=CVCRdhrxrLVSCW9PCgVvdo1qsB4nxrFx2aSelgNTjDs,8972 +yaml/scanner.py,sha256=7QIQuHqeecR4u4Rv4YXtAz_3EPczJZMz9s5I2XqcxWA,52630 +yaml/serializer.py,sha256=tRsRwfu5E9fpLU7LY3vBQf2prt77hwnYlMt5dnBJLig,4171 +yaml/tokens.py,sha256=lTQIzSVw8Mg9wv459-TjiOQe6wVziqaRlqX2_89rp54,2573 +PyYAML-3.11.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +yaml/loader.pyc,, +yaml/__init__.pyc,, +yaml/reader.pyc,, +yaml/cyaml.pyc,, +yaml/resolver.pyc,, +yaml/constructor.pyc,, +yaml/composer.pyc,, +yaml/dumper.pyc,, +yaml/emitter.pyc,, +yaml/serializer.pyc,, +yaml/events.pyc,, +yaml/representer.pyc,, +yaml/error.pyc,, +yaml/tokens.pyc,, +yaml/parser.pyc,, +yaml/scanner.pyc,, +yaml/nodes.pyc,, diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/WHEEL b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/WHEEL new file mode 100644 index 0000000..d15279d --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.29.0) +Root-Is-Purelib: false +Tag: cp27-cp27mu-linux_x86_64 + diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/metadata.json b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/metadata.json new file mode 100644 index 0000000..9857905 --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/metadata.json @@ -0,0 +1 @@ +{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.5", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.0", "Programming Language :: Python :: 3.1", "Programming Language :: Python :: 3.2", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Markup"], "download_url": "http://pyyaml.org/download/pyyaml/PyYAML-3.11.tar.gz", "extensions": {"python.details": {"contacts": [{"email": "xi@resolvent.net", "name": "Kirill Simonov", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://pyyaml.org/wiki/PyYAML"}}}, "generator": "bdist_wheel (0.29.0)", "license": "MIT", "metadata_version": "2.0", "name": "PyYAML", "platform": "Any", "summary": "YAML parser and emitter for Python", "version": "3.11"} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/top_level.txt b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/top_level.txt new file mode 100644 index 0000000..e6475e9 --- /dev/null +++ b/env/lib/python2.7/site-packages/PyYAML-3.11.dist-info/top_level.txt @@ -0,0 +1,2 @@ +_yaml +yaml diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/DESCRIPTION.rst b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..2a6e8bb --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/DESCRIPTION.rst @@ -0,0 +1,54 @@ +Werkzeug +======== + +Werkzeug started as simple collection of various utilities for WSGI +applications and has become one of the most advanced WSGI utility +modules. It includes a powerful debugger, full featured request and +response objects, HTTP utilities to handle entity tags, cache control +headers, HTTP dates, cookie handling, file uploads, a powerful URL +routing system and a bunch of community contributed addon modules. + +Werkzeug is unicode aware and doesn't enforce a specific template +engine, database adapter or anything else. It doesn't even enforce +a specific way of handling requests and leaves all that up to the +developer. It's most useful for end user applications which should work +on as many server environments as possible (such as blogs, wikis, +bulletin boards, etc.). + +Details and example applications are available on the +`Werkzeug website `_. + + +Features +-------- + +- unicode awareness + +- request and response objects + +- various utility functions for dealing with HTTP headers such as + `Accept` and `Cache-Control` headers. + +- thread local objects with proper cleanup at request end + +- an interactive debugger + +- A simple WSGI server with support for threading and forking + with an automatic reloader. + +- a flexible URL routing system with REST support. + +- fully WSGI compatible + + +Development Version +------------------- + +The Werkzeug development version can be installed by cloning the git +repository from `github`_:: + + git clone git@github.com:mitsuhiko/werkzeug.git + +.. _github: http://github.com/mitsuhiko/werkzeug + + diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/INSTALLER b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/METADATA b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/METADATA new file mode 100644 index 0000000..be3420f --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/METADATA @@ -0,0 +1,79 @@ +Metadata-Version: 2.0 +Name: Werkzeug +Version: 0.11.11 +Summary: The Swiss Army knife of Python web development +Home-page: http://werkzeug.pocoo.org/ +Author: Armin Ronacher +Author-email: armin.ronacher@active-4.com +License: BSD +Platform: any +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Classifier: Topic :: Software Development :: Libraries :: Python Modules + +Werkzeug +======== + +Werkzeug started as simple collection of various utilities for WSGI +applications and has become one of the most advanced WSGI utility +modules. It includes a powerful debugger, full featured request and +response objects, HTTP utilities to handle entity tags, cache control +headers, HTTP dates, cookie handling, file uploads, a powerful URL +routing system and a bunch of community contributed addon modules. + +Werkzeug is unicode aware and doesn't enforce a specific template +engine, database adapter or anything else. It doesn't even enforce +a specific way of handling requests and leaves all that up to the +developer. It's most useful for end user applications which should work +on as many server environments as possible (such as blogs, wikis, +bulletin boards, etc.). + +Details and example applications are available on the +`Werkzeug website `_. + + +Features +-------- + +- unicode awareness + +- request and response objects + +- various utility functions for dealing with HTTP headers such as + `Accept` and `Cache-Control` headers. + +- thread local objects with proper cleanup at request end + +- an interactive debugger + +- A simple WSGI server with support for threading and forking + with an automatic reloader. + +- a flexible URL routing system with REST support. + +- fully WSGI compatible + + +Development Version +------------------- + +The Werkzeug development version can be installed by cloning the git +repository from `github`_:: + + git clone git@github.com:mitsuhiko/werkzeug.git + +.. _github: http://github.com/mitsuhiko/werkzeug + + diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/RECORD b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/RECORD new file mode 100644 index 0000000..16e2bfc --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/RECORD @@ -0,0 +1,94 @@ +werkzeug/posixemulation.py,sha256=xEF2Bxc-vUCPkiu4IbfWVd3LW7DROYAT-ExW6THqyzw,3519 +werkzeug/security.py,sha256=tuVc22OqoHV5K-TrYJmynCJJa12aUt9BQ3wR_vEPQ34,8971 +werkzeug/__init__.py,sha256=7sfvCWELBhe774-fzDoL1EU8GHsNG7iuxOkF0OnE5cc,6920 +werkzeug/testapp.py,sha256=3HQRW1sHZKXuAjCvFMet4KXtQG3loYTFnvn6LWt-4zI,9396 +werkzeug/http.py,sha256=i9tuTlN8sOy9car-esVsHET6AfNCnObbu1pRBjqExvs,35287 +werkzeug/routing.py,sha256=TqiZD5HkwdLBnKBUjC5PlytzXmpczQC5dz54VfQzMOw,66350 +werkzeug/utils.py,sha256=lkybtv_mq35zV1qhelvEcILTzrMUwZ9yon6E8XwapJE,22972 +werkzeug/exceptions.py,sha256=c-3fKHItsPvC52X_NwBNLcmGXR30h0WP5ynPSwCqPiw,18733 +werkzeug/_reloader.py,sha256=YQykMSQW7AlojJQ7qOlgNaXw5_CNjf9yzxplwzVdL7Q,8336 +werkzeug/formparser.py,sha256=90D5Urp8Ghrzw32kAs090G0nXPYlU73NeAzPlQFMVrY,21296 +werkzeug/_compat.py,sha256=8c4U9o6A_TR9nKCcTbpZNxpqCXcXDVIbFawwKM2s92c,6311 +werkzeug/datastructures.py,sha256=-W9uZXQ-HSAy_lGDh5oO6cPUE8bNtXoNQ6BaFG8B2Vs,87575 +werkzeug/wrappers.py,sha256=lKYevpKD1-quk9Cop7bsFxt1eWJxU3h33HCnOI_YzSU,77011 +werkzeug/test.py,sha256=pQMDJjKdjZVWd_BJfnXExE3NH5Ykr-LG5YT4giptWyw,34127 +werkzeug/urls.py,sha256=fSbI4Gb29_p02Zk21VAZQRN1QdOVY9CNTgpb2rbajNQ,36710 +werkzeug/script.py,sha256=DwaVDcXdaOTffdNvlBdLitxWXjKaRVT32VbhDtljFPY,11365 +werkzeug/useragents.py,sha256=uqpgPcJ5BfcCVh9nPIIl2r3duIrIuENmrbRqbAMmPDk,5418 +werkzeug/local.py,sha256=4Q5gwHQJhfhZFqTR8iQDs2VHohpR1OEsP4YTwn7rt7w,14275 +werkzeug/serving.py,sha256=uRUqXuA-Dw2MRA-d232cK_034-taldoj66fEFrtin7k,27736 +werkzeug/filesystem.py,sha256=hHWeWo_gqLMzTRfYt8-7n2wWcWUNTnDyudQDLOBEICE,2175 +werkzeug/wsgi.py,sha256=S8R3pBGPlBK67s-d6Wa93nhzG27WjfcHs_ZBGIAQCxM,39573 +werkzeug/_internal.py,sha256=IEScSoFtQ8KqFH_2ubdfscNAdQ2RIysyVupI5BR9W2U,13709 +werkzeug/contrib/fixers.py,sha256=MtN_YmENxoTsGvXGGERmtbQ62LaeFc5I2d1YifXNENA,10183 +werkzeug/contrib/limiter.py,sha256=iS8-ahPZ-JLRnmfIBzxpm7O_s3lPsiDMVWv7llAIDCI,1334 +werkzeug/contrib/__init__.py,sha256=f7PfttZhbrImqpr5Ezre8CXgwvcGUJK7zWNpO34WWrw,623 +werkzeug/contrib/testtools.py,sha256=G9xN-qeihJlhExrIZMCahvQOIDxdL9NiX874jiiHFMs,2453 +werkzeug/contrib/iterio.py,sha256=pTX36rYCKO_9IEoB5sIN5cFSYszI9zdx6YhquWovcPY,10814 +werkzeug/contrib/cache.py,sha256=4W2WCT9Hw6HEU8yME9GuU4Xf8e50r2K84ASMxhLb6tY,27983 +werkzeug/contrib/securecookie.py,sha256=X-Ao_0NRDveW6K1Fhe4U42hHWBW8esCpA3VcBDpzWIk,12206 +werkzeug/contrib/lint.py,sha256=XDKYx0ELn9k18xRn4SiAsCgltCuN4yLjzxnCN8tG_eM,12490 +werkzeug/contrib/profiler.py,sha256=ISwCWvwVyGpDLRBRpLjo_qUWma6GXYBrTAco4PEQSHY,5151 +werkzeug/contrib/wrappers.py,sha256=zcd-1yC-kZQOLnn8Bs2SzKUNn7z2H9f0DpcVYS5Ty8s,10380 +werkzeug/contrib/atom.py,sha256=rvijBrphjMzVObfuCR6ddu6aLwI_SiNiudu64OSTh4Q,15588 +werkzeug/contrib/jsrouting.py,sha256=QTmgeDoKXvNK02KzXgx9lr3cAH6fAzpwF5bBdPNvJPs,8564 +werkzeug/contrib/sessions.py,sha256=uAPcnyxaxEla-bUA13gKc3KK4mwSagdzbCZzyKl3PeE,12577 +werkzeug/debug/console.py,sha256=B7uAu9Rk60siDnGlEt-A_q1ZR4zCtmxx5itg3X-BOxo,5599 +werkzeug/debug/repr.py,sha256=NaoB89aHb0vuvdSWels-GWdeGDZp76uE4uSNZPX1jAM,9354 +werkzeug/debug/__init__.py,sha256=qQT5YnOv9Eov9Jt5eLtP6MOqwpmo-tORJ6HcQmmnvro,17271 +werkzeug/debug/tbtools.py,sha256=-BeFH40ISiF5DFn9RfHMQzCGzmFBovZnREyj-lLzptM,18410 +werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 +werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818 +werkzeug/debug/shared/debugger.js,sha256=PEMBoNuD6fUaNou8Km_ZvVmFcIA3z3k3jSEMWLW-cA0,6187 +werkzeug/debug/shared/style.css,sha256=7x1s8olZO1XHalqD4M9MWn9vRqQkA635S9_6zRoe220,6231 +werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 +werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673 +werkzeug/debug/shared/jquery.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957 +werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220 +werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 +Werkzeug-0.11.11.dist-info/DESCRIPTION.rst,sha256=5sTwZ_Sj5aeEN8mlcOdNJ_ng40HiGazGmILLyTMX8o0,1595 +Werkzeug-0.11.11.dist-info/metadata.json,sha256=aFs0-WetLKLo-qWj4IIgXNtkOaDtX5H6YtZKJuHJVBc,1096 +Werkzeug-0.11.11.dist-info/RECORD,, +Werkzeug-0.11.11.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 +Werkzeug-0.11.11.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 +Werkzeug-0.11.11.dist-info/METADATA,sha256=yIzL70I-ZF_FswTj-dMsH_HvVIlmG8iqrq_lMsqp8WU,2600 +Werkzeug-0.11.11.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +werkzeug/_reloader.pyc,, +werkzeug/filesystem.pyc,, +werkzeug/contrib/testtools.pyc,, +werkzeug/formparser.pyc,, +werkzeug/_compat.pyc,, +werkzeug/posixemulation.pyc,, +werkzeug/serving.pyc,, +werkzeug/contrib/__init__.pyc,, +werkzeug/contrib/iterio.pyc,, +werkzeug/test.pyc,, +werkzeug/contrib/limiter.pyc,, +werkzeug/debug/tbtools.pyc,, +werkzeug/contrib/sessions.pyc,, +werkzeug/local.pyc,, +werkzeug/utils.pyc,, +werkzeug/contrib/lint.pyc,, +werkzeug/security.pyc,, +werkzeug/contrib/cache.pyc,, +werkzeug/contrib/securecookie.pyc,, +werkzeug/script.pyc,, +werkzeug/routing.pyc,, +werkzeug/wrappers.pyc,, +werkzeug/contrib/jsrouting.pyc,, +werkzeug/contrib/fixers.pyc,, +werkzeug/contrib/profiler.pyc,, +werkzeug/debug/console.pyc,, +werkzeug/debug/__init__.pyc,, +werkzeug/wsgi.pyc,, +werkzeug/datastructures.pyc,, +werkzeug/http.pyc,, +werkzeug/urls.pyc,, +werkzeug/useragents.pyc,, +werkzeug/_internal.pyc,, +werkzeug/contrib/wrappers.pyc,, +werkzeug/exceptions.pyc,, +werkzeug/contrib/atom.pyc,, +werkzeug/__init__.pyc,, +werkzeug/testapp.pyc,, +werkzeug/debug/repr.pyc,, diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/WHEEL b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/WHEEL new file mode 100644 index 0000000..9dff69d --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.24.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/metadata.json b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/metadata.json new file mode 100644 index 0000000..27f2dbe --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/metadata.json @@ -0,0 +1 @@ +{"license": "BSD", "name": "Werkzeug", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "The Swiss Army knife of Python web development", "platform": "any", "version": "0.11.11", "extensions": {"python.details": {"project_urls": {"Home": "http://werkzeug.pocoo.org/"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "armin.ronacher@active-4.com", "name": "Armin Ronacher"}]}}, "classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules"]} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/top_level.txt b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/top_level.txt new file mode 100644 index 0000000..6fe8da8 --- /dev/null +++ b/env/lib/python2.7/site-packages/Werkzeug-0.11.11.dist-info/top_level.txt @@ -0,0 +1 @@ +werkzeug diff --git a/env/lib/python2.7/site-packages/easy_install.py b/env/lib/python2.7/site-packages/easy_install.py new file mode 100644 index 0000000..d87e984 --- /dev/null +++ b/env/lib/python2.7/site-packages/easy_install.py @@ -0,0 +1,5 @@ +"""Run the EasyInstall command""" + +if __name__ == '__main__': + from setuptools.command.easy_install import main + main() diff --git a/env/lib/python2.7/site-packages/easy_install.pyc b/env/lib/python2.7/site-packages/easy_install.pyc new file mode 100644 index 0000000..cd6d4e2 Binary files /dev/null and b/env/lib/python2.7/site-packages/easy_install.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/DESCRIPTION.rst b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/DESCRIPTION.rst new file mode 100644 index 0000000..e875510 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/DESCRIPTION.rst @@ -0,0 +1,391 @@ +====== +Flake8 +====== + +Flake8 is a wrapper around these tools: + +- PyFlakes +- pep8 +- Ned Batchelder's McCabe script + +Flake8 runs all the tools by launching the single ``flake8`` script. +It displays the warnings in a per-file, merged output. + +It also adds a few features: + +- files that contain this line are skipped:: + + # flake8: noqa + +- lines that contain a ``# noqa`` comment at the end will not issue warnings. +- a Git and a Mercurial hook. +- a McCabe complexity checker. +- extendable through ``flake8.extension`` entry points. + + +QuickStart +========== + +:: + + pip install flake8 + +To run flake8 just invoke it against any directory or Python module:: + + $ flake8 coolproject + coolproject/mod.py:97:1: F401 'shutil' imported but unused + coolproject/mod.py:625:17: E225 missing whitespace around operato + coolproject/mod.py:729:1: F811 redefinition of function 'readlines' from line 723 + coolproject/mod.py:1028:1: F841 local variable 'errors' is assigned to but never used + +The outputs of PyFlakes *and* pep8 (and the optional plugins) are merged +and returned. + +flake8 offers an extra option: --max-complexity, which will emit a warning if +the McCabe complexity of a function is higher than the value. By default it's +deactivated:: + + $ flake8 --max-complexity 12 coolproject + coolproject/mod.py:97:1: F401 'shutil' imported but unused + coolproject/mod.py:625:17: E225 missing whitespace around operator + coolproject/mod.py:729:1: F811 redefinition of unused 'readlines' from line 723 + coolproject/mod.py:939:1: C901 'Checker.check_all' is too complex (12) + coolproject/mod.py:1028:1: F841 local variable 'errors' is assigned to but never used + coolproject/mod.py:1204:1: C901 'selftest' is too complex (14) + +This feature is quite useful to detect over-complex code. According to McCabe, +anything that goes beyond 10 is too complex. +See https://en.wikipedia.org/wiki/Cyclomatic_complexity. + +Questions or Feedback +===================== + +If you have questions you'd like to ask the developers, or feedback you'd like +to provide, feel free to use the mailing list: code-quality@python.org We +would love to hear from you. Additionally, if you have a feature you'd like to +suggest, the mailing list would be the best place for it. + +.. _links: + +Links +===== + +* `flake8 documentation `_ + +* `pep8 documentation `_ + + +CHANGES +======= + +2.5.1 - 2015-12-15 +------------------ + +- **Bug** Properly look for ``.flake8`` in current working directory + (`GitLab#103`_) + +- **Bug** Monkey-patch ``pep8.stdin_get_value`` to cache the actual value in + stdin. This helps plugins relying on the function when run with + multiprocessing. (`GitLab#105`_, `GitLab#107`_) + +.. _GitLab#103: https://gitlab.com/pycqa/flake8/issues/103 +.. _GitLab#105: https://gitlab.com/pycqa/flake8/issues/105 +.. _GitLab#107: https://gitlab.com/pycqa/flake8/issues/107 + +2.5.0 - 2015-10-26 +------------------ + +- **Improvement** Raise cap on PyFlakes for Python 3.5 support + +- **Improvement** Avoid deprecation warnings when loading extensions + (`GitLab#59`_, `GitLab#90`_) + +- **Improvement** Separate logic to enable "off-by-default" extensions + (`GitLab#67`_) + +- **Bug** Properly parse options to setuptools Flake8 command (`GitLab!41`_) + +- **Bug** Fix exceptions when output on stdout is truncated before Flake8 + finishes writing the output (`GitLab#69`_) + +- **Bug** Fix error on OS X where Flake8 can no longer acquire or create new + semaphores (`GitLab#74`_) + +.. _GitLab!41: https://gitlab.com/pycqa/flake8/merge_requests/41 +.. _GitLab#59: https://gitlab.com/pycqa/flake8/issues/59 +.. _GitLab#67: https://gitlab.com/pycqa/flake8/issues/67 +.. _GitLab#69: https://gitlab.com/pycqa/flake8/issues/69 +.. _GitLab#74: https://gitlab.com/pycqa/flake8/issues/74 +.. _GitLab#90: https://gitlab.com/pycqa/flake8/issues/90 + +2.4.1 - 2015-05-18 +------------------ + +- **Bug** Do not raise a ``SystemError`` unless there were errors in the + setuptools command. (`GitLab#39`_, `GitLab!23`_) + +- **Bug** Do not verify dependencies of extensions loaded via entry-points. + +- **Improvement** Blacklist versions of pep8 we know are broken + +.. _GitLab#39: https://gitlab.com/pycqa/flake8/issues/39 +.. _GitLab!23: https://gitlab.com/pycqa/flake8/merge_requests/23 + +2.4.0 - 2015-03-07 +------------------ + +- **Bug** Print filenames when using multiprocessing and ``-q`` option. + (`GitLab#31`_) + +- **Bug** Put upper cap on dependencies. The caps for 2.4.0 are: + + - ``pep8 < 1.6`` (Related to `GitLab#35`_) + + - ``mccabe < 0.4`` + + - ``pyflakes < 0.9`` + + See also `GitLab#32`_ + +- **Bug** Files excluded in a config file were not being excluded when flake8 + was run from a git hook. (`GitHub#2`_) + +- **Improvement** Print warnings for users who are providing mutually + exclusive options to flake8. (`GitLab#8`_, `GitLab!18`_) + +- **Feature** Allow git hook configuration to live in ``.git/config``. + See the updated `VCS hooks docs`_ for more details. (`GitLab!20`_) + +.. _GitHub#2: https://github.com/pycqa/flake8/pull/2 +.. _GitLab#8: https://gitlab.com/pycqa/flake8/issues/8 +.. _GitLab#31: https://gitlab.com/pycqa/flake8/issues/31 +.. _GitLab#32: https://gitlab.com/pycqa/flake8/issues/32 +.. _GitLab#35: https://gitlab.com/pycqa/flake8/issues/35 +.. _GitLab!18: https://gitlab.com/pycqa/flake8/merge_requests/18 +.. _GitLab!20: https://gitlab.com/pycqa/flake8/merge_requests/20 +.. _VCS hooks docs: https://flake8.readthedocs.org/en/latest/vcs.html + +2.3.0 - 2015-01-04 +------------------ + +- **Feature**: Add ``--output-file`` option to specify a file to write to + instead of ``stdout``. + +- **Bug** Fix interleaving of output while using multiprocessing + (`GitLab#17`_) + +.. _GitLab#17: https://gitlab.com/pycqa/flake8/issues/17 + +2.2.5 - 2014-10-19 +------------------ + +- Flush standard out when using multiprocessing + +- Make the check for "# flake8: noqa" more strict + +2.2.4 - 2014-10-09 +------------------ + +- Fix bugs triggered by turning multiprocessing on by default (again) + + Multiprocessing is forcibly disabled in the following cases: + + - Passing something in via stdin + + - Analyzing a diff + + - Using windows + +- Fix --install-hook when there are no config files present for pep8 or + flake8. + +- Fix how the setuptools command parses excludes in config files + +- Fix how the git hook determines which files to analyze (Thanks Chris + Buccella!) + +2.2.3 - 2014-08-25 +------------------ + +- Actually turn multiprocessing on by default + +2.2.2 - 2014-07-04 +------------------ + +- Re-enable multiprocessing by default while fixing the issue Windows users + were seeing. + +2.2.1 - 2014-06-30 +------------------ + +- Turn off multiple jobs by default. To enable automatic use of all CPUs, use + ``--jobs=auto``. Fixes #155 and #154. + +2.2.0 - 2014-06-22 +------------------ + +- New option ``doctests`` to run Pyflakes checks on doctests too +- New option ``jobs`` to launch multiple jobs in parallel +- Turn on using multiple jobs by default using the CPU count +- Add support for ``python -m flake8`` on Python 2.7 and Python 3 +- Fix Git and Mercurial hooks: issues #88, #133, #148 and #149 +- Fix crashes with Python 3.4 by upgrading dependencies +- Fix traceback when running tests with Python 2.6 +- Fix the setuptools command ``python setup.py flake8`` to read + the project configuration + + +2.1.0 - 2013-10-26 +------------------ + +- Add FLAKE8_LAZY and FLAKE8_IGNORE environment variable support to git and + mercurial hooks +- Force git and mercurial hooks to repsect configuration in setup.cfg +- Only check staged files if that is specified +- Fix hook file permissions +- Fix the git hook on python 3 +- Ignore non-python files when running the git hook +- Ignore .tox directories by default +- Flake8 now reports the column number for PyFlakes messages + + +2.0.0 - 2013-02-23 +------------------ + +- Pyflakes errors are prefixed by an ``F`` instead of an ``E`` +- McCabe complexity warnings are prefixed by a ``C`` instead of a ``W`` +- Flake8 supports extensions through entry points +- Due to the above support, we **require** setuptools +- We publish the `documentation `_ +- Fixes #13: pep8, pyflakes and mccabe become external dependencies +- Split run.py into main.py, engine.py and hooks.py for better logic +- Expose our parser for our users +- New feature: Install git and hg hooks automagically +- By relying on pyflakes (0.6.1), we also fixed #45 and #35 + + +1.7.0 - 2012-12-21 +------------------ + +- Fixes part of #35: Exception for no WITHITEM being an attribute of Checker + for Python 3.3 +- Support stdin +- Incorporate @phd's builtins pull request +- Fix the git hook +- Update pep8.py to the latest version + + +1.6.2 - 2012-11-25 +------------------ + +- fixed the NameError: global name 'message' is not defined (#46) + + +1.6.1 - 2012-11-24 +------------------ + +- fixed the mercurial hook, a change from a previous patch was not properly + applied +- fixed an assumption about warnings/error messages that caused an exception + to be thrown when McCabe is used + + +1.6 - 2012-11-16 +---------------- + +- changed the signatures of the ``check_file`` function in flake8/run.py, + ``skip_warning`` in flake8/util.py and the ``check``, ``checkPath`` + functions in flake8/pyflakes.py. +- fix ``--exclude`` and ``--ignore`` command flags (#14, #19) +- fix the git hook that wasn't catching files not already added to the index + (#29) +- pre-emptively includes the addition to pep8 to ignore certain lines. + Add ``# nopep8`` to the end of a line to ignore it. (#37) +- ``check_file`` can now be used without any special prior setup (#21) +- unpacking exceptions will no longer cause an exception (#20) +- fixed crash on non-existent file (#38) + + +1.5 - 2012-10-13 +---------------- + +- fixed the stdin +- make sure mccabe catches the syntax errors as warnings +- pep8 upgrade +- added max_line_length default value +- added Flake8Command and entry points if setuptools is around +- using the setuptools console wrapper when available + + +1.4 - 2012-07-12 +---------------- + +- git_hook: Only check staged changes for compliance +- use pep8 1.2 + + +1.3.1 - 2012-05-19 +------------------ + +- fixed support for Python 2.5 + + +1.3 - 2012-03-12 +---------------- + +- fixed false W402 warning on exception blocks. + + +1.2 - 2012-02-12 +---------------- + +- added a git hook +- now Python 3 compatible +- mccabe and pyflakes have warning codes like pep8 now + + +1.1 - 2012-02-14 +---------------- + +- fixed the value returned by --version +- allow the flake8: header to be more generic +- fixed the "hg hook raises 'physical lines'" bug +- allow three argument form of raise +- now uses setuptools if available, for 'develop' command + + +1.0 - 2011-11-29 +---------------- + +- Deactivates by default the complexity checker +- Introduces the complexity option in the HG hook and the command line. + + +0.9 - 2011-11-09 +---------------- + +- update pep8 version to 0.6.1 +- mccabe check: gracefully handle compile failure + + +0.8 - 2011-02-27 +---------------- + +- fixed hg hook +- discard unexisting files on hook check + + +0.7 - 2010-02-18 +---------------- + +- Fix pep8 initialization when run through Hg +- Make pep8 short options work when run through the command line +- Skip duplicates when controlling files via Hg + + +0.6 - 2010-02-15 +---------------- + +- Fix the McCabe metric on some loops + + diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/INSTALLER b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/INSTALLER new file mode 100644 index 0000000..a1b589e --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/METADATA b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/METADATA new file mode 100644 index 0000000..68a3a43 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/METADATA @@ -0,0 +1,412 @@ +Metadata-Version: 2.0 +Name: flake8 +Version: 2.5.1 +Summary: the modular source code checker: pep8, pyflakes and co +Home-page: https://gitlab.com/pycqa/flake8 +Author: Ian Cordasco +Author-email: graffatcolmingov@gmail.com +License: MIT +Platform: UNKNOWN +Classifier: Environment :: Console +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: MIT License +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Software Development :: Quality Assurance +Requires-Dist: pyflakes (>=0.8.1,<1.1) +Requires-Dist: pep8 (>=1.5.7,!=1.6.0,!=1.6.1,!=1.6.2) +Requires-Dist: mccabe (>=0.2.1,<0.4) + +====== +Flake8 +====== + +Flake8 is a wrapper around these tools: + +- PyFlakes +- pep8 +- Ned Batchelder's McCabe script + +Flake8 runs all the tools by launching the single ``flake8`` script. +It displays the warnings in a per-file, merged output. + +It also adds a few features: + +- files that contain this line are skipped:: + + # flake8: noqa + +- lines that contain a ``# noqa`` comment at the end will not issue warnings. +- a Git and a Mercurial hook. +- a McCabe complexity checker. +- extendable through ``flake8.extension`` entry points. + + +QuickStart +========== + +:: + + pip install flake8 + +To run flake8 just invoke it against any directory or Python module:: + + $ flake8 coolproject + coolproject/mod.py:97:1: F401 'shutil' imported but unused + coolproject/mod.py:625:17: E225 missing whitespace around operato + coolproject/mod.py:729:1: F811 redefinition of function 'readlines' from line 723 + coolproject/mod.py:1028:1: F841 local variable 'errors' is assigned to but never used + +The outputs of PyFlakes *and* pep8 (and the optional plugins) are merged +and returned. + +flake8 offers an extra option: --max-complexity, which will emit a warning if +the McCabe complexity of a function is higher than the value. By default it's +deactivated:: + + $ flake8 --max-complexity 12 coolproject + coolproject/mod.py:97:1: F401 'shutil' imported but unused + coolproject/mod.py:625:17: E225 missing whitespace around operator + coolproject/mod.py:729:1: F811 redefinition of unused 'readlines' from line 723 + coolproject/mod.py:939:1: C901 'Checker.check_all' is too complex (12) + coolproject/mod.py:1028:1: F841 local variable 'errors' is assigned to but never used + coolproject/mod.py:1204:1: C901 'selftest' is too complex (14) + +This feature is quite useful to detect over-complex code. According to McCabe, +anything that goes beyond 10 is too complex. +See https://en.wikipedia.org/wiki/Cyclomatic_complexity. + +Questions or Feedback +===================== + +If you have questions you'd like to ask the developers, or feedback you'd like +to provide, feel free to use the mailing list: code-quality@python.org We +would love to hear from you. Additionally, if you have a feature you'd like to +suggest, the mailing list would be the best place for it. + +.. _links: + +Links +===== + +* `flake8 documentation `_ + +* `pep8 documentation `_ + + +CHANGES +======= + +2.5.1 - 2015-12-15 +------------------ + +- **Bug** Properly look for ``.flake8`` in current working directory + (`GitLab#103`_) + +- **Bug** Monkey-patch ``pep8.stdin_get_value`` to cache the actual value in + stdin. This helps plugins relying on the function when run with + multiprocessing. (`GitLab#105`_, `GitLab#107`_) + +.. _GitLab#103: https://gitlab.com/pycqa/flake8/issues/103 +.. _GitLab#105: https://gitlab.com/pycqa/flake8/issues/105 +.. _GitLab#107: https://gitlab.com/pycqa/flake8/issues/107 + +2.5.0 - 2015-10-26 +------------------ + +- **Improvement** Raise cap on PyFlakes for Python 3.5 support + +- **Improvement** Avoid deprecation warnings when loading extensions + (`GitLab#59`_, `GitLab#90`_) + +- **Improvement** Separate logic to enable "off-by-default" extensions + (`GitLab#67`_) + +- **Bug** Properly parse options to setuptools Flake8 command (`GitLab!41`_) + +- **Bug** Fix exceptions when output on stdout is truncated before Flake8 + finishes writing the output (`GitLab#69`_) + +- **Bug** Fix error on OS X where Flake8 can no longer acquire or create new + semaphores (`GitLab#74`_) + +.. _GitLab!41: https://gitlab.com/pycqa/flake8/merge_requests/41 +.. _GitLab#59: https://gitlab.com/pycqa/flake8/issues/59 +.. _GitLab#67: https://gitlab.com/pycqa/flake8/issues/67 +.. _GitLab#69: https://gitlab.com/pycqa/flake8/issues/69 +.. _GitLab#74: https://gitlab.com/pycqa/flake8/issues/74 +.. _GitLab#90: https://gitlab.com/pycqa/flake8/issues/90 + +2.4.1 - 2015-05-18 +------------------ + +- **Bug** Do not raise a ``SystemError`` unless there were errors in the + setuptools command. (`GitLab#39`_, `GitLab!23`_) + +- **Bug** Do not verify dependencies of extensions loaded via entry-points. + +- **Improvement** Blacklist versions of pep8 we know are broken + +.. _GitLab#39: https://gitlab.com/pycqa/flake8/issues/39 +.. _GitLab!23: https://gitlab.com/pycqa/flake8/merge_requests/23 + +2.4.0 - 2015-03-07 +------------------ + +- **Bug** Print filenames when using multiprocessing and ``-q`` option. + (`GitLab#31`_) + +- **Bug** Put upper cap on dependencies. The caps for 2.4.0 are: + + - ``pep8 < 1.6`` (Related to `GitLab#35`_) + + - ``mccabe < 0.4`` + + - ``pyflakes < 0.9`` + + See also `GitLab#32`_ + +- **Bug** Files excluded in a config file were not being excluded when flake8 + was run from a git hook. (`GitHub#2`_) + +- **Improvement** Print warnings for users who are providing mutually + exclusive options to flake8. (`GitLab#8`_, `GitLab!18`_) + +- **Feature** Allow git hook configuration to live in ``.git/config``. + See the updated `VCS hooks docs`_ for more details. (`GitLab!20`_) + +.. _GitHub#2: https://github.com/pycqa/flake8/pull/2 +.. _GitLab#8: https://gitlab.com/pycqa/flake8/issues/8 +.. _GitLab#31: https://gitlab.com/pycqa/flake8/issues/31 +.. _GitLab#32: https://gitlab.com/pycqa/flake8/issues/32 +.. _GitLab#35: https://gitlab.com/pycqa/flake8/issues/35 +.. _GitLab!18: https://gitlab.com/pycqa/flake8/merge_requests/18 +.. _GitLab!20: https://gitlab.com/pycqa/flake8/merge_requests/20 +.. _VCS hooks docs: https://flake8.readthedocs.org/en/latest/vcs.html + +2.3.0 - 2015-01-04 +------------------ + +- **Feature**: Add ``--output-file`` option to specify a file to write to + instead of ``stdout``. + +- **Bug** Fix interleaving of output while using multiprocessing + (`GitLab#17`_) + +.. _GitLab#17: https://gitlab.com/pycqa/flake8/issues/17 + +2.2.5 - 2014-10-19 +------------------ + +- Flush standard out when using multiprocessing + +- Make the check for "# flake8: noqa" more strict + +2.2.4 - 2014-10-09 +------------------ + +- Fix bugs triggered by turning multiprocessing on by default (again) + + Multiprocessing is forcibly disabled in the following cases: + + - Passing something in via stdin + + - Analyzing a diff + + - Using windows + +- Fix --install-hook when there are no config files present for pep8 or + flake8. + +- Fix how the setuptools command parses excludes in config files + +- Fix how the git hook determines which files to analyze (Thanks Chris + Buccella!) + +2.2.3 - 2014-08-25 +------------------ + +- Actually turn multiprocessing on by default + +2.2.2 - 2014-07-04 +------------------ + +- Re-enable multiprocessing by default while fixing the issue Windows users + were seeing. + +2.2.1 - 2014-06-30 +------------------ + +- Turn off multiple jobs by default. To enable automatic use of all CPUs, use + ``--jobs=auto``. Fixes #155 and #154. + +2.2.0 - 2014-06-22 +------------------ + +- New option ``doctests`` to run Pyflakes checks on doctests too +- New option ``jobs`` to launch multiple jobs in parallel +- Turn on using multiple jobs by default using the CPU count +- Add support for ``python -m flake8`` on Python 2.7 and Python 3 +- Fix Git and Mercurial hooks: issues #88, #133, #148 and #149 +- Fix crashes with Python 3.4 by upgrading dependencies +- Fix traceback when running tests with Python 2.6 +- Fix the setuptools command ``python setup.py flake8`` to read + the project configuration + + +2.1.0 - 2013-10-26 +------------------ + +- Add FLAKE8_LAZY and FLAKE8_IGNORE environment variable support to git and + mercurial hooks +- Force git and mercurial hooks to repsect configuration in setup.cfg +- Only check staged files if that is specified +- Fix hook file permissions +- Fix the git hook on python 3 +- Ignore non-python files when running the git hook +- Ignore .tox directories by default +- Flake8 now reports the column number for PyFlakes messages + + +2.0.0 - 2013-02-23 +------------------ + +- Pyflakes errors are prefixed by an ``F`` instead of an ``E`` +- McCabe complexity warnings are prefixed by a ``C`` instead of a ``W`` +- Flake8 supports extensions through entry points +- Due to the above support, we **require** setuptools +- We publish the `documentation `_ +- Fixes #13: pep8, pyflakes and mccabe become external dependencies +- Split run.py into main.py, engine.py and hooks.py for better logic +- Expose our parser for our users +- New feature: Install git and hg hooks automagically +- By relying on pyflakes (0.6.1), we also fixed #45 and #35 + + +1.7.0 - 2012-12-21 +------------------ + +- Fixes part of #35: Exception for no WITHITEM being an attribute of Checker + for Python 3.3 +- Support stdin +- Incorporate @phd's builtins pull request +- Fix the git hook +- Update pep8.py to the latest version + + +1.6.2 - 2012-11-25 +------------------ + +- fixed the NameError: global name 'message' is not defined (#46) + + +1.6.1 - 2012-11-24 +------------------ + +- fixed the mercurial hook, a change from a previous patch was not properly + applied +- fixed an assumption about warnings/error messages that caused an exception + to be thrown when McCabe is used + + +1.6 - 2012-11-16 +---------------- + +- changed the signatures of the ``check_file`` function in flake8/run.py, + ``skip_warning`` in flake8/util.py and the ``check``, ``checkPath`` + functions in flake8/pyflakes.py. +- fix ``--exclude`` and ``--ignore`` command flags (#14, #19) +- fix the git hook that wasn't catching files not already added to the index + (#29) +- pre-emptively includes the addition to pep8 to ignore certain lines. + Add ``# nopep8`` to the end of a line to ignore it. (#37) +- ``check_file`` can now be used without any special prior setup (#21) +- unpacking exceptions will no longer cause an exception (#20) +- fixed crash on non-existent file (#38) + + +1.5 - 2012-10-13 +---------------- + +- fixed the stdin +- make sure mccabe catches the syntax errors as warnings +- pep8 upgrade +- added max_line_length default value +- added Flake8Command and entry points if setuptools is around +- using the setuptools console wrapper when available + + +1.4 - 2012-07-12 +---------------- + +- git_hook: Only check staged changes for compliance +- use pep8 1.2 + + +1.3.1 - 2012-05-19 +------------------ + +- fixed support for Python 2.5 + + +1.3 - 2012-03-12 +---------------- + +- fixed false W402 warning on exception blocks. + + +1.2 - 2012-02-12 +---------------- + +- added a git hook +- now Python 3 compatible +- mccabe and pyflakes have warning codes like pep8 now + + +1.1 - 2012-02-14 +---------------- + +- fixed the value returned by --version +- allow the flake8: header to be more generic +- fixed the "hg hook raises 'physical lines'" bug +- allow three argument form of raise +- now uses setuptools if available, for 'develop' command + + +1.0 - 2011-11-29 +---------------- + +- Deactivates by default the complexity checker +- Introduces the complexity option in the HG hook and the command line. + + +0.9 - 2011-11-09 +---------------- + +- update pep8 version to 0.6.1 +- mccabe check: gracefully handle compile failure + + +0.8 - 2011-02-27 +---------------- + +- fixed hg hook +- discard unexisting files on hook check + + +0.7 - 2010-02-18 +---------------- + +- Fix pep8 initialization when run through Hg +- Make pep8 short options work when run through the command line +- Skip duplicates when controlling files via Hg + + +0.6 - 2010-02-15 +---------------- + +- Fix the McCabe metric on some loops + + diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/RECORD b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/RECORD new file mode 100644 index 0000000..460ceed --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/RECORD @@ -0,0 +1,50 @@ +flake8/__init__.py,sha256=wKgbOOmlKOzeNoJAuzHTH_Z_9ka3BXj-a4tGYEh92Rk,22 +flake8/__main__.py,sha256=VgRVSyXXGxGLjhhMS-3Gs_xMKoHoneoPK2yERe3X43k,77 +flake8/_pyflakes.py,sha256=3aU5yXHLtqjbbQNkkay8yzG7e0dEznTDCVCqFqodBo0,2070 +flake8/callbacks.py,sha256=4W6BbHZ8uEfE3-up4YN29DdqUyCa4qSozJE7rIv1m64,943 +flake8/compat.py,sha256=2yqIiGwkwti31ZifpClF5CDNx2S9RTfgc6BdkmkrDdI,347 +flake8/engine.py,sha256=Z32A4tIdAVQkIObE8ljXdYqCp_TZzOgvab-gYBQGY24,11435 +flake8/hooks.py,sha256=lmD2ecjZAcY69uylD1U_x8sV3kRYpKVljM4fV2Q9CaM,9900 +flake8/main.py,sha256=dSthJt4Y5Gj0l3SctiBvdH3SIvQhTc_CH125-WkMLhY,4756 +flake8/reporter.py,sha256=4eC1YQdMR1M-D1yHiqWwfRyMe4kQ8RqLXfG7yLd8xyc,5265 +flake8/run.py,sha256=3vCNw2NRaXpY_ycyrT6EkXN_KyTIo3BW2Ivve_jWrZk,271 +flake8/util.py,sha256=imxv-2OTlUi4YNW_0h9kzWPfLpQH2Sl7TANAd7Ek9VY,1863 +flake8/tests/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2 +flake8/tests/_test_warnings.py,sha256=YGuEpYyMZFZ3MWJNx0HnhwCfA8A5D2-cxhGzCbYnfok,11188 +flake8/tests/test_engine.py,sha256=u_Z3g7MI7PyaCXilFY7nTcGramQUb_tAKMfrZT_bXVc,8944 +flake8/tests/test_hooks.py,sha256=da1eMnKiaPl8wcJ6uRgYCfMWKJb5kPK_grZMkrcoA_E,2184 +flake8/tests/test_integration.py,sha256=_uOYbfZjdPh-b4i_mo_DMHGWZVt0rfX0XI41LKR_4o8,2799 +flake8/tests/test_main.py,sha256=LqE9BF4BkPKVNscAGFgKr0m35xd-Is6np2A39zJrvuQ,368 +flake8/tests/test_reporter.py,sha256=IWmxkLmyrmaKZneXuYGbIW9HPdulQlX_HuSm-IKbUto,1125 +flake8/tests/test_util.py,sha256=p4yfULMjyFP-GUzUPDLoQNHfcAkdStiHOJ75p1rFfiI,2216 +flake8/tests/test_warnings.py,sha256=XcUj_V5yNOKBYHUvt-XVZ6iZ4uH6vpH7vuqWkCA-_mo,7635 +flake8-2.5.1.dist-info/DESCRIPTION.rst,sha256=sv4-wobLTVmBAq4FOz4viEkdtcJ37RA8rE8uFfITDHg,11285 +flake8-2.5.1.dist-info/entry_points.txt,sha256=Bp5943BUpVO-imc8SoIT9en_oW0BMz6Ve2Z2LQgvBJU,157 +flake8-2.5.1.dist-info/METADATA,sha256=Tf5zHpwn8qidnq9ol9w3cd5qPQwup5cXf7xCZrxqKK8,12071 +flake8-2.5.1.dist-info/metadata.json,sha256=b0vW2m3y4W7QMmtJbqgeQqRQ8rEHiDCKq3oahvD_2dU,1244 +flake8-2.5.1.dist-info/pbr.json,sha256=hxMvQyNilY8J8E1TrUfKuqOveVXbtMzXQyYEZvyLmjw,47 +flake8-2.5.1.dist-info/RECORD,, +flake8-2.5.1.dist-info/top_level.txt,sha256=6Tlo_i7chAhjqQkybdwPfClaqi0-dkJh_2o1PSn1aBM,7 +flake8-2.5.1.dist-info/WHEEL,sha256=AvR0WeTpDaxT645bl5FQxUK6NPsTls2ttpcGJg3j1Xg,110 +../../../bin/flake8,sha256=lUKwGUfr61nwvrWyrFp6h7ojPPYuePd_V--XKtdauIM,234 +flake8-2.5.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +flake8/tests/test_warnings.pyc,, +flake8/run.pyc,, +flake8/engine.pyc,, +flake8/main.pyc,, +flake8/callbacks.pyc,, +flake8/tests/test_hooks.pyc,, +flake8/tests/__init__.pyc,, +flake8/tests/test_reporter.pyc,, +flake8/tests/_test_warnings.pyc,, +flake8/tests/test_main.pyc,, +flake8/tests/test_engine.pyc,, +flake8/compat.pyc,, +flake8/__main__.pyc,, +flake8/util.pyc,, +flake8/_pyflakes.pyc,, +flake8/tests/test_integration.pyc,, +flake8/hooks.pyc,, +flake8/reporter.pyc,, +flake8/tests/test_util.pyc,, +flake8/__init__.pyc,, diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/WHEEL b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/WHEEL new file mode 100644 index 0000000..9dff69d --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/WHEEL @@ -0,0 +1,6 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.24.0) +Root-Is-Purelib: true +Tag: py2-none-any +Tag: py3-none-any + diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/entry_points.txt b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/entry_points.txt new file mode 100644 index 0000000..3ad195b --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/entry_points.txt @@ -0,0 +1,9 @@ +[console_scripts] +flake8 = flake8.main:main + +[distutils.commands] +flake8 = flake8.main:Flake8Command + +[flake8.extension] +F = flake8._pyflakes:FlakesChecker + diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/metadata.json b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/metadata.json new file mode 100644 index 0000000..85136d5 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/metadata.json @@ -0,0 +1 @@ +{"test_requires": [{"requires": ["nose", "mock"]}], "extras": [], "extensions": {"python.details": {"project_urls": {"Home": "https://gitlab.com/pycqa/flake8"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "graffatcolmingov@gmail.com", "name": "Ian Cordasco"}]}, "python.commands": {"wrap_console": {"flake8": "flake8.main:main"}}, "python.exports": {"flake8.extension": {"F": "flake8._pyflakes:FlakesChecker"}, "console_scripts": {"flake8": "flake8.main:main"}, "distutils.commands": {"flake8": "flake8.main:Flake8Command"}}}, "name": "flake8", "metadata_version": "2.0", "version": "2.5.1", "generator": "bdist_wheel (0.24.0)", "run_requires": [{"requires": ["pyflakes (>=0.8.1,<1.1)", "pep8 (>=1.5.7,!=1.6.0,!=1.6.1,!=1.6.2)", "mccabe (>=0.2.1,<0.4)"]}], "license": "MIT", "summary": "the modular source code checker: pep8, pyflakes and co", "classifiers": ["Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Quality Assurance"]} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/pbr.json b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/pbr.json new file mode 100644 index 0000000..5f2c3e5 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/pbr.json @@ -0,0 +1 @@ +{"git_version": "0cc12e2", "is_release": false} \ No newline at end of file diff --git a/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/top_level.txt b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/top_level.txt new file mode 100644 index 0000000..3930480 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8-2.5.1.dist-info/top_level.txt @@ -0,0 +1 @@ +flake8 diff --git a/env/lib/python2.7/site-packages/flake8/__init__.py b/env/lib/python2.7/site-packages/flake8/__init__.py new file mode 100644 index 0000000..b8c5494 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/__init__.py @@ -0,0 +1 @@ +__version__ = '2.5.1' diff --git a/env/lib/python2.7/site-packages/flake8/__init__.pyc b/env/lib/python2.7/site-packages/flake8/__init__.pyc new file mode 100644 index 0000000..5ac9250 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/__init__.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/__main__.py b/env/lib/python2.7/site-packages/flake8/__main__.py new file mode 100644 index 0000000..aaa497b --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/__main__.py @@ -0,0 +1,4 @@ +from flake8.main import main + +# python -m flake8 (with Python >= 2.7) +main() diff --git a/env/lib/python2.7/site-packages/flake8/__main__.pyc b/env/lib/python2.7/site-packages/flake8/__main__.pyc new file mode 100644 index 0000000..4a4599c Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/__main__.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/_pyflakes.py b/env/lib/python2.7/site-packages/flake8/_pyflakes.py new file mode 100644 index 0000000..12a8344 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/_pyflakes.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +try: + # The 'demandimport' breaks pyflakes and flake8._pyflakes + from mercurial import demandimport +except ImportError: + pass +else: + demandimport.disable() +import pyflakes +import pyflakes.checker + + +def patch_pyflakes(): + """Add error codes to Pyflakes messages.""" + codes = dict([line.split()[::-1] for line in ( + 'F401 UnusedImport', + 'F402 ImportShadowedByLoopVar', + 'F403 ImportStarUsed', + 'F404 LateFutureImport', + 'F810 Redefined', # XXX Obsolete? + 'F811 RedefinedWhileUnused', + 'F812 RedefinedInListComp', + 'F821 UndefinedName', + 'F822 UndefinedExport', + 'F823 UndefinedLocal', + 'F831 DuplicateArgument', + 'F841 UnusedVariable', + )]) + + for name, obj in vars(pyflakes.messages).items(): + if name[0].isupper() and obj.message: + obj.flake8_msg = '%s %s' % (codes.get(name, 'F999'), obj.message) +patch_pyflakes() + + +class FlakesChecker(pyflakes.checker.Checker): + """Subclass the Pyflakes checker to conform with the flake8 API.""" + name = 'pyflakes' + version = pyflakes.__version__ + + def __init__(self, tree, filename): + super(FlakesChecker, self).__init__(tree, filename, + withDoctest=self.withDoctest) + + @classmethod + def add_options(cls, parser): + parser.add_option('--builtins', + help="define more built-ins, comma separated") + parser.add_option('--doctests', default=False, action='store_true', + help="check syntax of the doctests") + parser.config_options.extend(['builtins', 'doctests']) + + @classmethod + def parse_options(cls, options): + if options.builtins: + cls.builtIns = cls.builtIns.union(options.builtins.split(',')) + cls.withDoctest = options.doctests + + def run(self): + for m in self.messages: + col = getattr(m, 'col', 0) + yield m.lineno, col, (m.flake8_msg % m.message_args), m.__class__ diff --git a/env/lib/python2.7/site-packages/flake8/_pyflakes.pyc b/env/lib/python2.7/site-packages/flake8/_pyflakes.pyc new file mode 100644 index 0000000..ff9c740 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/_pyflakes.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/callbacks.py b/env/lib/python2.7/site-packages/flake8/callbacks.py new file mode 100644 index 0000000..3767f30 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/callbacks.py @@ -0,0 +1,27 @@ +import atexit +import sys + + +def install_vcs_hook(option, option_str, value, parser): + # For now, there's no way to affect a change in how pep8 processes + # options. If no args are provided and there's no config file present, + # it will error out because no input was provided. To get around this, + # when we're using --install-hook, we'll say that there were arguments so + # we can actually attempt to install the hook. + # See: https://gitlab.com/pycqa/flake8/issues/2 and + # https://github.com/jcrocholl/pep8/blob/4c5bf00cb613be617c7f48d3b2b82a1c7b895ac1/pep8.py#L1912 + # for more context. + parser.values.install_hook = True + parser.rargs.append('.') + + +def restore_stdout(old_stdout): + sys.stdout.close() + sys.stdout = old_stdout + + +def redirect_stdout(option, option_str, value, parser): + fd = open(value, 'w') + old_stdout, sys.stdout = sys.stdout, fd + + atexit.register(restore_stdout, old_stdout) diff --git a/env/lib/python2.7/site-packages/flake8/callbacks.pyc b/env/lib/python2.7/site-packages/flake8/callbacks.pyc new file mode 100644 index 0000000..33ecace Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/callbacks.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/compat.py b/env/lib/python2.7/site-packages/flake8/compat.py new file mode 100644 index 0000000..9bd00a7 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/compat.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +"""Compatibility shims for Flake8.""" +import os.path +import sys + + +def relpath(path, start='.'): + """Wallpaper over the differences between 2.6 and newer versions.""" + if sys.version_info < (2, 7) and path.startswith(start): + return path[len(start):] + else: + return os.path.relpath(path, start=start) diff --git a/env/lib/python2.7/site-packages/flake8/compat.pyc b/env/lib/python2.7/site-packages/flake8/compat.pyc new file mode 100644 index 0000000..150e69a Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/compat.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/engine.py b/env/lib/python2.7/site-packages/flake8/engine.py new file mode 100644 index 0000000..d929f83 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/engine.py @@ -0,0 +1,316 @@ +# -*- coding: utf-8 -*- +import errno +import io +import platform +import re +import sys +import warnings + +import pep8 + +from flake8 import __version__ +from flake8 import callbacks +from flake8.reporter import (multiprocessing, BaseQReport, FileQReport, + QueueReport) +from flake8 import util + +_flake8_noqa = re.compile(r'\s*# flake8[:=]\s*noqa', re.I).search + +EXTRA_EXCLUDE = ['.tox', '.eggs', '*.egg'] + +pep8.PROJECT_CONFIG += ('.flake8',) + + +def _load_entry_point(entry_point, verify_requirements): + """Based on the version of setuptools load an entry-point correctly. + + setuptools 11.3 deprecated `require=False` in the call to EntryPoint.load. + To load entry points correctly after that without requiring all + dependencies be present, the proper way is to call EntryPoint.resolve. + + This function will provide backwards compatibility for older versions of + setuptools while also ensuring we do the right thing for the future. + """ + if hasattr(entry_point, 'resolve') and hasattr(entry_point, 'require'): + if verify_requirements: + entry_point.require() + plugin = entry_point.resolve() + else: + plugin = entry_point.load(require=verify_requirements) + + return plugin + + +def _register_extensions(): + """Register all the extensions.""" + extensions = util.OrderedSet() + extensions.add(('pep8', pep8.__version__)) + parser_hooks = [] + options_hooks = [] + ignored_hooks = [] + try: + from pkg_resources import iter_entry_points + except ImportError: + pass + else: + for entry in iter_entry_points('flake8.extension'): + # Do not verify that the requirements versions are valid + checker = _load_entry_point(entry, verify_requirements=False) + pep8.register_check(checker, codes=[entry.name]) + extensions.add((checker.name, checker.version)) + if hasattr(checker, 'add_options'): + parser_hooks.append(checker.add_options) + if hasattr(checker, 'parse_options'): + options_hooks.append(checker.parse_options) + if getattr(checker, 'off_by_default', False) is True: + ignored_hooks.append(entry.name) + return extensions, parser_hooks, options_hooks, ignored_hooks + + +def get_parser(): + """This returns an instance of optparse.OptionParser with all the + extensions registered and options set. This wraps ``pep8.get_parser``. + """ + (extensions, parser_hooks, options_hooks, ignored) = _register_extensions() + details = ', '.join('%s: %s' % ext for ext in extensions) + python_version = get_python_version() + parser = pep8.get_parser('flake8', '%s (%s) %s' % ( + __version__, details, python_version + )) + for opt in ('--repeat', '--testsuite', '--doctest'): + try: + parser.remove_option(opt) + except ValueError: + pass + + if multiprocessing: + parser.config_options.append('jobs') + parser.add_option('-j', '--jobs', type='string', default='auto', + help="number of jobs to run simultaneously, " + "or 'auto'. This is ignored on Windows.") + + parser.add_option('--exit-zero', action='store_true', + help="exit with code 0 even if there are errors") + for parser_hook in parser_hooks: + parser_hook(parser) + # See comment above regarding why this has to be a callback. + parser.add_option('--install-hook', default=False, dest='install_hook', + help='Install the appropriate hook for this ' + 'repository.', action='callback', + callback=callbacks.install_vcs_hook) + parser.add_option('--output-file', default=None, + help='Redirect report to a file.', + type='string', nargs=1, action='callback', + callback=callbacks.redirect_stdout) + parser.add_option('--enable-extensions', default='', + dest='enabled_extensions', + help='Enable plugins and extensions that are disabled ' + 'by default', + type='string') + parser.ignored_extensions = ignored + return parser, options_hooks + + +class NoQAStyleGuide(pep8.StyleGuide): + + def input_file(self, filename, lines=None, expected=None, line_offset=0): + """Run all checks on a Python source file.""" + if self.options.verbose: + print('checking %s' % filename) + fchecker = self.checker_class( + filename, lines=lines, options=self.options) + # Any "flake8: noqa" comments to ignore the entire file? + if any(_flake8_noqa(line) for line in fchecker.lines): + return 0 + return fchecker.check_all(expected=expected, line_offset=line_offset) + + +class StyleGuide(object): + """A wrapper StyleGuide object for Flake8 usage. + + This allows for OSErrors to be caught in the styleguide and special logic + to be used to handle those errors. + """ + + # Reasoning for error numbers is in-line below + serial_retry_errors = set([ + # ENOSPC: Added by sigmavirus24 + # > On some operating systems (OSX), multiprocessing may cause an + # > ENOSPC error while trying to trying to create a Semaphore. + # > In those cases, we should replace the customized Queue Report + # > class with pep8's StandardReport class to ensure users don't run + # > into this problem. + # > (See also: https://gitlab.com/pycqa/flake8/issues/74) + errno.ENOSPC, + # NOTE(sigmavirus24): When adding to this list, include the reasoning + # on the lines before the error code and always append your error + # code. Further, please always add a trailing `,` to reduce the visual + # noise in diffs. + ]) + + def __init__(self, **kwargs): + # This allows us to inject a mocked StyleGuide in the tests. + self._styleguide = kwargs.pop('styleguide', NoQAStyleGuide(**kwargs)) + + @property + def options(self): + return self._styleguide.options + + @property + def paths(self): + return self._styleguide.paths + + def _retry_serial(self, func, *args, **kwargs): + """This will retry the passed function in serial if necessary. + + In the event that we encounter an OSError with an errno in + :attr:`serial_retry_errors`, this function will retry this function + using pep8's default Report class which operates in serial. + """ + try: + return func(*args, **kwargs) + except OSError as oserr: + if oserr.errno in self.serial_retry_errors: + self.init_report(pep8.StandardReport) + else: + raise + return func(*args, **kwargs) + + def check_files(self, paths=None): + return self._retry_serial(self._styleguide.check_files, paths=paths) + + def excluded(self, filename, parent=None): + return self._styleguide.excluded(filename, parent=parent) + + def init_report(self, reporter=None): + return self._styleguide.init_report(reporter) + + def input_file(self, filename, lines=None, expected=None, line_offset=0): + return self._retry_serial( + self._styleguide.input_file, + filename=filename, + lines=lines, + expected=expected, + line_offset=line_offset, + ) + + +def _parse_multi_options(options, split_token=','): + r"""Split and strip and discard empties. + + Turns the following: + + A, + B, + + into ["A", "B"]. + + Credit: Kristian Glass as contributed to pep8 + """ + if options: + return [o.strip() for o in options.split(split_token) if o.strip()] + else: + return options + + +def _disable_extensions(parser, options): + ignored_extensions = set(getattr(parser, 'ignored_extensions', [])) + enabled = set(_parse_multi_options(options.enabled_extensions)) + + # Remove any of the selected extensions from the extensions ignored by + # default. + ignored_extensions -= enabled + + # Whatever is left afterwards should be unioned with options.ignore and + # options.ignore should be updated with that. + options.ignore = tuple(ignored_extensions.union(options.ignore)) + + +def get_style_guide(**kwargs): + """Parse the options and configure the checker. This returns a sub-class + of ``pep8.StyleGuide``.""" + kwargs['parser'], options_hooks = get_parser() + styleguide = StyleGuide(**kwargs) + options = styleguide.options + + _disable_extensions(kwargs['parser'], options) + + if options.exclude and not isinstance(options.exclude, list): + options.exclude = pep8.normalize_paths(options.exclude) + elif not options.exclude: + options.exclude = [] + + # Add patterns in EXTRA_EXCLUDE to the list of excluded patterns + options.exclude.extend(pep8.normalize_paths(EXTRA_EXCLUDE)) + + for options_hook in options_hooks: + options_hook(options) + + if util.warn_when_using_jobs(options): + if not multiprocessing: + warnings.warn("The multiprocessing module is not available. " + "Ignoring --jobs arguments.") + if util.is_windows(): + warnings.warn("The --jobs option is not available on Windows. " + "Ignoring --jobs arguments.") + if util.is_using_stdin(styleguide.paths): + warnings.warn("The --jobs option is not compatible with supplying " + "input using - . Ignoring --jobs arguments.") + if options.diff: + warnings.warn("The --diff option was specified with --jobs but " + "they are not compatible. Ignoring --jobs arguments." + ) + + if options.diff: + options.jobs = None + + force_disable_jobs = util.force_disable_jobs(styleguide) + + if multiprocessing and options.jobs and not force_disable_jobs: + if options.jobs.isdigit(): + n_jobs = int(options.jobs) + else: + try: + n_jobs = multiprocessing.cpu_count() + except NotImplementedError: + n_jobs = 1 + if n_jobs > 1: + options.jobs = n_jobs + reporter = QueueReport + if options.quiet: + reporter = BaseQReport + if options.quiet == 1: + reporter = FileQReport + report = styleguide.init_report(reporter) + report.input_file = styleguide.input_file + styleguide.runner = report.task_queue.put + + return styleguide + + +def get_python_version(): + # The implementation isn't all that important. + try: + impl = platform.python_implementation() + " " + except AttributeError: # Python 2.5 + impl = '' + return '%s%s on %s' % (impl, platform.python_version(), platform.system()) + + +def make_stdin_get_value(original): + def stdin_get_value(): + if not hasattr(stdin_get_value, 'cached_stdin'): + value = original() + if sys.version_info < (3, 0): + stdin = io.BytesIO(value) + else: + stdin = io.StringIO(value) + stdin_get_value.cached_stdin = stdin + else: + stdin = stdin_get_value.cached_stdin + return stdin.getvalue() + + return stdin_get_value + + +pep8.stdin_get_value = make_stdin_get_value(pep8.stdin_get_value) diff --git a/env/lib/python2.7/site-packages/flake8/engine.pyc b/env/lib/python2.7/site-packages/flake8/engine.pyc new file mode 100644 index 0000000..3f2109a Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/engine.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/hooks.py b/env/lib/python2.7/site-packages/flake8/hooks.py new file mode 100644 index 0000000..2d1db8d --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/hooks.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- +from __future__ import with_statement +import os +import pep8 +import sys +import stat +from subprocess import Popen, PIPE +import shutil +import tempfile +try: + from configparser import ConfigParser +except ImportError: # Python 2 + from ConfigParser import ConfigParser + +from flake8 import compat +from flake8.engine import get_parser, get_style_guide +from flake8.main import DEFAULT_CONFIG + + +def git_hook(complexity=-1, strict=False, ignore=None, lazy=False): + """This is the function used by the git hook. + + :param int complexity: (optional), any value > 0 enables complexity + checking with mccabe + :param bool strict: (optional), if True, this returns the total number of + errors which will cause the hook to fail + :param str ignore: (optional), a comma-separated list of errors and + warnings to ignore + :param bool lazy: (optional), allows for the instances where you don't add + the files to the index before running a commit, e.g., git commit -a + :returns: total number of errors if strict is True, otherwise 0 + """ + gitcmd = "git diff-index --cached --name-only --diff-filter=ACMRTUXB HEAD" + if lazy: + # Catch all files, including those not added to the index + gitcmd = gitcmd.replace('--cached ', '') + + if hasattr(ignore, 'split'): + ignore = ignore.split(',') + + # Returns the exit code, list of files modified, list of error messages + _, files_modified, _ = run(gitcmd) + + # We only want to pass ignore and max_complexity if they differ from the + # defaults so that we don't override a local configuration file + options = {} + if ignore: + options['ignore'] = ignore + if complexity > -1: + options['max_complexity'] = complexity + + tmpdir = tempfile.mkdtemp() + + flake8_style = get_style_guide(config_file=DEFAULT_CONFIG, paths=['.'], + **options) + filepatterns = flake8_style.options.filename + + # Copy staged versions to temporary directory + files_to_check = [] + try: + for file_ in files_modified: + # get the staged version of the file + gitcmd_getstaged = "git show :%s" % file_ + _, out, _ = run(gitcmd_getstaged, raw_output=True, decode=False) + # write the staged version to temp dir with its full path to + # avoid overwriting files with the same name + dirname, filename = os.path.split(os.path.abspath(file_)) + prefix = os.path.commonprefix([dirname, tmpdir]) + dirname = compat.relpath(dirname, start=prefix) + dirname = os.path.join(tmpdir, dirname) + if not os.path.isdir(dirname): + os.makedirs(dirname) + + # check_files() only does this check if passed a dir; so we do it + if ((pep8.filename_match(file_, filepatterns) and + not flake8_style.excluded(file_))): + + filename = os.path.join(dirname, filename) + files_to_check.append(filename) + # write staged version of file to temporary directory + with open(filename, "wb") as fh: + fh.write(out) + + # Run the checks + report = flake8_style.check_files(files_to_check) + # remove temporary directory + finally: + shutil.rmtree(tmpdir, ignore_errors=True) + + if strict: + return report.total_errors + + return 0 + + +def hg_hook(ui, repo, **kwargs): + """This is the function executed directly by Mercurial as part of the + hook. This is never called directly by the user, so the parameters are + undocumented. If you would like to learn more about them, please feel free + to read the official Mercurial documentation. + """ + complexity = ui.config('flake8', 'complexity', default=-1) + strict = ui.configbool('flake8', 'strict', default=True) + ignore = ui.config('flake8', 'ignore', default=None) + config = ui.config('flake8', 'config', default=DEFAULT_CONFIG) + + paths = _get_files(repo, **kwargs) + + # We only want to pass ignore and max_complexity if they differ from the + # defaults so that we don't override a local configuration file + options = {} + if ignore: + options['ignore'] = ignore + if complexity > -1: + options['max_complexity'] = complexity + + flake8_style = get_style_guide(config_file=config, paths=['.'], + **options) + report = flake8_style.check_files(paths) + + if strict: + return report.total_errors + + return 0 + + +def run(command, raw_output=False, decode=True): + p = Popen(command.split(), stdout=PIPE, stderr=PIPE) + (stdout, stderr) = p.communicate() + # On python 3, subprocess.Popen returns bytes objects which expect + # endswith to be given a bytes object or a tuple of bytes but not native + # string objects. This is simply less mysterious than using b'.py' in the + # endswith method. That should work but might still fail horribly. + if decode: + if hasattr(stdout, 'decode'): + stdout = stdout.decode('utf-8') + if hasattr(stderr, 'decode'): + stderr = stderr.decode('utf-8') + if not raw_output: + stdout = [line.strip() for line in stdout.splitlines()] + stderr = [line.strip() for line in stderr.splitlines()] + return (p.returncode, stdout, stderr) + + +def _get_files(repo, **kwargs): + seen = set() + for rev in range(repo[kwargs['node']], len(repo)): + for file_ in repo[rev].files(): + file_ = os.path.join(repo.root, file_) + if file_ in seen or not os.path.exists(file_): + continue + seen.add(file_) + if file_.endswith('.py'): + yield file_ + + +def find_vcs(): + _, git_dir, _ = run('git rev-parse --git-dir') + if git_dir and os.path.isdir(git_dir[0]): + if not os.path.isdir(os.path.join(git_dir[0], 'hooks')): + os.mkdir(os.path.join(git_dir[0], 'hooks')) + return os.path.join(git_dir[0], 'hooks', 'pre-commit') + _, hg_dir, _ = run('hg root') + if hg_dir and os.path.isdir(hg_dir[0]): + return os.path.join(hg_dir[0], '.hg', 'hgrc') + return '' + + +def get_git_config(option, opt_type='', convert_type=True): + # type can be --bool, --int or an empty string + _, git_cfg_value, _ = run('git config --get %s %s' % (opt_type, option), + raw_output=True) + git_cfg_value = git_cfg_value.strip() + if not convert_type: + return git_cfg_value + if opt_type == '--bool': + git_cfg_value = git_cfg_value.lower() == 'true' + elif git_cfg_value and opt_type == '--int': + git_cfg_value = int(git_cfg_value) + return git_cfg_value + + +_params = { + 'FLAKE8_COMPLEXITY': '--int', + 'FLAKE8_STRICT': '--bool', + 'FLAKE8_IGNORE': '', + 'FLAKE8_LAZY': '--bool', +} + + +def get_git_param(option, default=''): + global _params + opt_type = _params[option] + param_value = get_git_config(option.lower().replace('_', '.'), + opt_type=opt_type, convert_type=False) + if param_value == '': + param_value = os.environ.get(option, default) + if opt_type == '--bool' and not isinstance(param_value, bool): + param_value = param_value.lower() == 'true' + elif param_value and opt_type == '--int': + param_value = int(param_value) + return param_value + + +git_hook_file = """#!/usr/bin/env python +import sys +from flake8.hooks import git_hook, get_git_param + +# `get_git_param` will retrieve configuration from your local git config and +# then fall back to using the environment variables that the hook has always +# supported. +# For example, to set the complexity, you'll need to do: +# git config flake8.complexity 10 +COMPLEXITY = get_git_param('FLAKE8_COMPLEXITY', 10) +STRICT = get_git_param('FLAKE8_STRICT', False) +IGNORE = get_git_param('FLAKE8_IGNORE', None) +LAZY = get_git_param('FLAKE8_LAZY', False) + +if __name__ == '__main__': + sys.exit(git_hook( + complexity=COMPLEXITY, + strict=STRICT, + ignore=IGNORE, + lazy=LAZY, + )) +""" + + +def _install_hg_hook(path): + getenv = os.environ.get + if not os.path.isfile(path): + # Make the file so we can avoid IOError's + open(path, 'w').close() + + c = ConfigParser() + c.readfp(open(path, 'r')) + if not c.has_section('hooks'): + c.add_section('hooks') + + if not c.has_option('hooks', 'commit'): + c.set('hooks', 'commit', 'python:flake8.hooks.hg_hook') + + if not c.has_option('hooks', 'qrefresh'): + c.set('hooks', 'qrefresh', 'python:flake8.hooks.hg_hook') + + if not c.has_section('flake8'): + c.add_section('flake8') + + if not c.has_option('flake8', 'complexity'): + c.set('flake8', 'complexity', str(getenv('FLAKE8_COMPLEXITY', 10))) + + if not c.has_option('flake8', 'strict'): + c.set('flake8', 'strict', getenv('FLAKE8_STRICT', False)) + + if not c.has_option('flake8', 'ignore'): + c.set('flake8', 'ignore', getenv('FLAKE8_IGNORE', '')) + + if not c.has_option('flake8', 'lazy'): + c.set('flake8', 'lazy', getenv('FLAKE8_LAZY', False)) + + with open(path, 'w') as fd: + c.write(fd) + + +def install_hook(): + vcs = find_vcs() + + if not vcs: + p = get_parser()[0] + sys.stderr.write('Error: could not find either a git or mercurial ' + 'directory. Please re-run this in a proper ' + 'repository.') + p.print_help() + sys.exit(1) + + status = 0 + if 'git' in vcs: + if os.path.exists(vcs): + sys.exit('Error: hook already exists (%s)' % vcs) + with open(vcs, 'w') as fd: + fd.write(git_hook_file) + # rwxr--r-- + os.chmod(vcs, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH) + elif 'hg' in vcs: + _install_hg_hook(vcs) + else: + status = 1 + + sys.exit(status) diff --git a/env/lib/python2.7/site-packages/flake8/hooks.pyc b/env/lib/python2.7/site-packages/flake8/hooks.pyc new file mode 100644 index 0000000..16ea071 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/hooks.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/main.py b/env/lib/python2.7/site-packages/flake8/main.py new file mode 100644 index 0000000..297618a --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/main.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +import os +import re +import sys + +import setuptools + +from flake8.engine import get_parser, get_style_guide +from flake8.util import option_normalizer + +if sys.platform.startswith('win'): + DEFAULT_CONFIG = os.path.expanduser(r'~\.flake8') +else: + DEFAULT_CONFIG = os.path.join( + os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config'), + 'flake8' + ) + +EXTRA_IGNORE = [] + + +def main(): + """Parse options and run checks on Python source.""" + # Prepare + flake8_style = get_style_guide(parse_argv=True, config_file=DEFAULT_CONFIG) + options = flake8_style.options + + if options.install_hook: + from flake8.hooks import install_hook + install_hook() + + # Run the checkers + report = flake8_style.check_files() + + exit_code = print_report(report, flake8_style) + if exit_code > 0: + raise SystemExit(exit_code > 0) + + +def print_report(report, flake8_style): + # Print the final report + options = flake8_style.options + if options.statistics: + report.print_statistics() + if options.benchmark: + report.print_benchmark() + if report.total_errors: + if options.count: + sys.stderr.write(str(report.total_errors) + '\n') + if not options.exit_zero: + return 1 + return 0 + + +def check_file(path, ignore=(), complexity=-1): + """Checks a file using pep8 and pyflakes by default and mccabe + optionally. + + :param str path: path to the file to be checked + :param tuple ignore: (optional), error and warning codes to be ignored + :param int complexity: (optional), enables the mccabe check for values > 0 + """ + ignore = set(ignore).union(EXTRA_IGNORE) + flake8_style = get_style_guide( + config_file=DEFAULT_CONFIG, ignore=ignore, max_complexity=complexity) + return flake8_style.input_file(path) + + +def check_code(code, ignore=(), complexity=-1): + """Checks code using pep8 and pyflakes by default and mccabe optionally. + + :param str code: code to be checked + :param tuple ignore: (optional), error and warning codes to be ignored + :param int complexity: (optional), enables the mccabe check for values > 0 + """ + ignore = set(ignore).union(EXTRA_IGNORE) + flake8_style = get_style_guide( + config_file=DEFAULT_CONFIG, ignore=ignore, max_complexity=complexity) + return flake8_style.input_file(None, lines=code.splitlines(True)) + + +class Flake8Command(setuptools.Command): + """The :class:`Flake8Command` class is used by setuptools to perform + checks on registered modules. + """ + + description = "Run flake8 on modules registered in setuptools" + user_options = [] + + def initialize_options(self): + self.option_to_cmds = {} + parser = get_parser()[0] + for opt in parser.option_list: + cmd_name = opt._long_opts[0][2:] + option_name = cmd_name.replace('-', '_') + self.option_to_cmds[option_name] = cmd_name + setattr(self, option_name, None) + + def finalize_options(self): + self.options_dict = {} + for (option_name, cmd_name) in self.option_to_cmds.items(): + if option_name in ['help', 'verbose']: + continue + value = getattr(self, option_name) + if value is None: + continue + value = option_normalizer(value) + # Check if there's any values that need to be fixed. + if option_name == "include" and isinstance(value, str): + value = re.findall('[^,;\s]+', value) + + self.options_dict[option_name] = value + + def distribution_files(self): + if self.distribution.packages: + package_dirs = self.distribution.package_dir or {} + for package in self.distribution.packages: + pkg_dir = package + if package in package_dirs: + pkg_dir = package_dirs[package] + elif '' in package_dirs: + pkg_dir = package_dirs[''] + os.path.sep + pkg_dir + yield pkg_dir.replace('.', os.path.sep) + + if self.distribution.py_modules: + for filename in self.distribution.py_modules: + yield "%s.py" % filename + # Don't miss the setup.py file itself + yield "setup.py" + + def run(self): + # Prepare + paths = list(self.distribution_files()) + flake8_style = get_style_guide(config_file=DEFAULT_CONFIG, + paths=paths, + **self.options_dict) + + # Run the checkers + report = flake8_style.check_files() + exit_code = print_report(report, flake8_style) + if exit_code > 0: + raise SystemExit(exit_code > 0) diff --git a/env/lib/python2.7/site-packages/flake8/main.pyc b/env/lib/python2.7/site-packages/flake8/main.pyc new file mode 100644 index 0000000..0e74505 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/main.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/reporter.py b/env/lib/python2.7/site-packages/flake8/reporter.py new file mode 100644 index 0000000..1df3d9e --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/reporter.py @@ -0,0 +1,152 @@ +# -*- coding: utf-8 -*- +# Adapted from a contribution of Johan Dahlin + +import collections +import errno +import re +import sys +try: + import multiprocessing +except ImportError: # Python 2.5 + multiprocessing = None + +import pep8 + +__all__ = ['multiprocessing', 'BaseQReport', 'QueueReport'] + + +class BaseQReport(pep8.BaseReport): + """Base Queue Report.""" + _loaded = False # Windows support + + # Reasoning for ignored error numbers is in-line below + ignored_errors = set([ + # EPIPE: Added by sigmavirus24 + # > If output during processing is piped to something that may close + # > its own stdin before we've finished printing results, we need to + # > catch a Broken pipe error and continue on. + # > (See also: https://gitlab.com/pycqa/flake8/issues/69) + errno.EPIPE, + # NOTE(sigmavirus24): When adding to this list, include the reasoning + # on the lines before the error code and always append your error + # code. Further, please always add a trailing `,` to reduce the visual + # noise in diffs. + ]) + + def __init__(self, options): + assert options.jobs > 0 + super(BaseQReport, self).__init__(options) + self.counters = collections.defaultdict(int) + self.n_jobs = options.jobs + + # init queues + self.task_queue = multiprocessing.Queue() + self.result_queue = multiprocessing.Queue() + if sys.platform == 'win32': + # Work around http://bugs.python.org/issue10845 + sys.modules['__main__'].__file__ = __file__ + + def _cleanup_queue(self, queue): + while not queue.empty(): + queue.get_nowait() + + def _put_done(self): + # collect queues + for i in range(self.n_jobs): + self.task_queue.put('DONE') + self.update_state(self.result_queue.get()) + + def _process_main(self): + if not self._loaded: + # Windows needs to parse again the configuration + from flake8.main import get_style_guide, DEFAULT_CONFIG + get_style_guide(parse_argv=True, config_file=DEFAULT_CONFIG) + for filename in iter(self.task_queue.get, 'DONE'): + self.input_file(filename) + + def start(self): + super(BaseQReport, self).start() + self.__class__._loaded = True + # spawn processes + for i in range(self.n_jobs): + p = multiprocessing.Process(target=self.process_main) + p.daemon = True + p.start() + + def stop(self): + try: + self._put_done() + except KeyboardInterrupt: + pass + finally: + # cleanup queues to unlock threads + self._cleanup_queue(self.result_queue) + self._cleanup_queue(self.task_queue) + super(BaseQReport, self).stop() + + def process_main(self): + try: + self._process_main() + except KeyboardInterrupt: + pass + except IOError as ioerr: + # If we happen across an IOError that we aren't certain can/should + # be ignored, we should re-raise the exception. + if ioerr.errno not in self.ignored_errors: + raise + finally: + # ensure all output is flushed before main process continues + sys.stdout.flush() + sys.stderr.flush() + self.result_queue.put(self.get_state()) + + def get_state(self): + return {'total_errors': self.total_errors, + 'counters': self.counters, + 'messages': self.messages} + + def update_state(self, state): + self.total_errors += state['total_errors'] + for key, value in state['counters'].items(): + self.counters[key] += value + self.messages.update(state['messages']) + + +class FileQReport(BaseQReport): + """File Queue Report.""" + print_filename = True + + +class QueueReport(pep8.StandardReport, BaseQReport): + """Standard Queue Report.""" + + def get_file_results(self): + """Print the result and return the overall count for this file.""" + self._deferred_print.sort() + + for line_number, offset, code, text, doc in self._deferred_print: + print(self._fmt % { + 'path': self.filename, + 'row': self.line_offset + line_number, 'col': offset + 1, + 'code': code, 'text': text, + }) + # stdout is block buffered when not stdout.isatty(). + # line can be broken where buffer boundary since other processes + # write to same file. + # flush() after print() to avoid buffer boundary. + # Typical buffer size is 8192. line written safely when + # len(line) < 8192. + sys.stdout.flush() + if self._show_source: + if line_number > len(self.lines): + line = '' + else: + line = self.lines[line_number - 1] + print(line.rstrip()) + sys.stdout.flush() + print(re.sub(r'\S', ' ', line[:offset]) + '^') + sys.stdout.flush() + if self._show_pep8 and doc: + print(' ' + doc.strip()) + sys.stdout.flush() + return self.file_errors diff --git a/env/lib/python2.7/site-packages/flake8/reporter.pyc b/env/lib/python2.7/site-packages/flake8/reporter.pyc new file mode 100644 index 0000000..5e8ae52 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/reporter.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/run.py b/env/lib/python2.7/site-packages/flake8/run.py new file mode 100644 index 0000000..aca929e --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/run.py @@ -0,0 +1,11 @@ + +""" +Implementation of the command-line I{flake8} tool. +""" +from flake8.hooks import git_hook, hg_hook # noqa +from flake8.main import check_code, check_file, Flake8Command # noqa +from flake8.main import main + + +if __name__ == '__main__': + main() diff --git a/env/lib/python2.7/site-packages/flake8/run.pyc b/env/lib/python2.7/site-packages/flake8/run.pyc new file mode 100644 index 0000000..9f2f18d Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/run.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/__init__.py b/env/lib/python2.7/site-packages/flake8/tests/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/__init__.py @@ -0,0 +1 @@ +# diff --git a/env/lib/python2.7/site-packages/flake8/tests/__init__.pyc b/env/lib/python2.7/site-packages/flake8/tests/__init__.pyc new file mode 100644 index 0000000..10f60e8 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/__init__.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/_test_warnings.py b/env/lib/python2.7/site-packages/flake8/tests/_test_warnings.py new file mode 100644 index 0000000..004a597 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/_test_warnings.py @@ -0,0 +1,309 @@ +""" + _test_warnings.py + + Tests for the warnings that are emitted by flake8. + + This module is named _test_warnings instead of test_warnings so that a + normal nosetests run does not collect it. The tests in this module pass + when they are run alone, but they fail when they are run along with other + tests (nosetests --with-isolation doesn't help). + + In tox.ini, these tests are run separately. + +""" + +from __future__ import with_statement + +import os +import warnings +import unittest +try: + from unittest import mock +except ImportError: + import mock # < PY33 + +from flake8 import engine +from flake8.util import is_windows + +# The Problem +# ------------ +# +# Some of the tests in this module pass when this module is run on its own, but +# they fail when this module is run as part of the whole test suite. These are +# the problematic tests: +# +# test_jobs_verbose +# test_stdin_jobs_warning +# +# On some platforms, the warnings.capture_warnings function doesn't work +# properly when run with the other flake8 tests. It drops some warnings, even +# though the warnings filter is set to 'always'. However, when run separately, +# these tests pass. +# +# This problem only occurs on Windows, with Python 3.3 and older. Maybe it's +# related to PEP 446 - Inheritable file descriptors? +# +# +# +# +# Things that didn't work +# ------------ +# +# Nose --attr +# I tried using the nosetests --attr feature to run the tests separately. I +# put the following in setup.cfg +# +# [nosetests] +# atttr=!run_alone +# +# Then I added a tox section thst did this +# +# nosetests --attr=run_alone +# +# However, the command line --attr would not override the config file --attr, +# so the special tox section wound up runing all the tests, and failing. +# +# +# +# Nose --with-isolation +# The nosetests --with-isolation flag did not help. +# +# +# +# unittest.skipIf +# I tried decorating the problematic tests with the unittest.skipIf +# decorator. +# +# @unittest.skipIf(is_windows() and sys.version_info < (3, 4), +# "Fails on Windows with Python < 3.4 when run with other" +# " tests.") +# +# The idea is, skip the tests in the main test run, on affected platforms. +# Then, only on those platforms, come back in later and run the tests +# separately. +# +# I added a new stanza to tox.ini, to run the tests separately on the +# affected platforms. +# +# nosetests --no-skip +# +# I ran in to a bug in the nosetests skip plugin. It would report the test as +# having been run, but it would not actually run the test. So, when run with +# --no-skip, the following test would be reported as having run and passed! +# +# @unittest.skip("This passes o_o") +# def test_should_fail(self): +# assert 0 +# +# This bug has been reported here: +# "--no-skip broken with Python 2.7" +# https://github.com/nose-devs/nose/issues/512 +# +# +# +# py.test +# +# I tried using py.test, and its @pytest.mark.xfail decorator. I added some +# separate stanzas in tox, and useing the pytest --runxfail option to run the +# tests separately. This allows us to run all the tests together, on +# platforms that allow it. On platforms that don't allow us to run the tests +# all together, this still runs all the tests, but in two separate steps. +# +# This is the same solution as the nosetests --no-skip solution I described +# above, but --runxfail does not have the same bug as --no-skip. +# +# This has the advantage that all tests are discoverable by default, outside +# of tox. However, nose does not recognize the pytest.mark.xfail decorator. +# So, if a user runs nosetests, it still tries to run the problematic tests +# together with the rest of the test suite, causing them to fail. +# +# +# +# +# +# +# Solution +# ------------ +# Move the problematic tests to _test_warnings.py, so nose.collector will not +# find them. Set up a separate section in tox.ini that runs this: +# +# nosetests flake8.tests._test_warnings +# +# This allows all tests to pass on all platforms, when run through tox. +# However, it means that, even on unaffected platforms, the problematic tests +# are not discovered and run outside of tox (if the user just runs nosetests +# manually, for example). + + +class IntegrationTestCaseWarnings(unittest.TestCase): + """Integration style tests to check that warnings are issued properly for + different command line options.""" + + windows_warning_text = ("The --jobs option is not available on Windows." + " Ignoring --jobs arguments.") + stdin_warning_text = ("The --jobs option is not compatible with" + " supplying input using - . Ignoring --jobs" + " arguments.") + + def this_file(self): + """Return the real path of this file.""" + this_file = os.path.realpath(__file__) + if this_file.endswith("pyc"): + this_file = this_file[:-1] + return this_file + + @staticmethod + def get_style_guide_with_warnings(engine, *args, **kwargs): + """ + Return a style guide object (obtained by calling + engine.get_style_guide) and a list of the warnings that were raised in + the process. + + Note: not threadsafe + """ + + # Note + # https://docs.python.org/2/library/warnings.html + # + # The catch_warnings manager works by replacing and then later + # restoring the module's showwarning() function and internal list of + # filter specifications. This means the context manager is modifying + # global state and therefore is not thread-safe + + with warnings.catch_warnings(record=True) as collected_warnings: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + # Get the style guide + style_guide = engine.get_style_guide(*args, **kwargs) + + # Now that the warnings have been collected, return the style guide and + # the warnings. + return (style_guide, collected_warnings) + + def verify_warnings(self, collected_warnings, expected_warnings): + """ + Verifies that collected_warnings is a sequence that contains user + warnings that match the sequence of string values passed in as + expected_warnings. + """ + if expected_warnings is None: + expected_warnings = [] + + collected_user_warnings = [w for w in collected_warnings + if issubclass(w.category, UserWarning)] + + self.assertEqual(len(collected_user_warnings), + len(expected_warnings)) + + collected_warnings_set = set(str(warning.message) + for warning + in collected_user_warnings) + expected_warnings_set = set(expected_warnings) + self.assertEqual(collected_warnings_set, expected_warnings_set) + + def check_files_collect_warnings(self, + arglist=[], + explicit_stdin=False, + count=0, + verbose=False): + """Call check_files and collect any warnings that are issued.""" + if verbose: + arglist.append('--verbose') + if explicit_stdin: + target_file = "-" + else: + target_file = self.this_file() + argv = ['flake8'] + arglist + [target_file] + with mock.patch("sys.argv", argv): + (style_guide, + collected_warnings, + ) = self.get_style_guide_with_warnings(engine, + parse_argv=True) + report = style_guide.check_files() + self.assertEqual(report.total_errors, count) + return style_guide, report, collected_warnings + + def check_files_no_warnings_allowed(self, + arglist=[], + explicit_stdin=False, + count=0, + verbose=False): + """Call check_files, and assert that there were no warnings issued.""" + (style_guide, + report, + collected_warnings, + ) = self.check_files_collect_warnings(arglist=arglist, + explicit_stdin=explicit_stdin, + count=count, + verbose=verbose) + self.verify_warnings(collected_warnings, expected_warnings=None) + return style_guide, report + + def _job_tester(self, jobs, verbose=False): + # mock stdout.flush so we can count the number of jobs created + with mock.patch('sys.stdout.flush') as mocked: + (guide, + report, + collected_warnings, + ) = self.check_files_collect_warnings( + arglist=['--jobs=%s' % jobs], + verbose=verbose) + + if is_windows(): + # The code path where guide.options.jobs gets converted to an + # int is not run on windows. So, do the int conversion here. + self.assertEqual(int(guide.options.jobs), jobs) + # On windows, call count is always zero. + self.assertEqual(mocked.call_count, 0) + else: + self.assertEqual(guide.options.jobs, jobs) + self.assertEqual(mocked.call_count, jobs) + + expected_warings = [] + if verbose and is_windows(): + expected_warings.append(self.windows_warning_text) + self.verify_warnings(collected_warnings, expected_warings) + + def test_jobs(self, verbose=False): + self._job_tester(2, verbose=verbose) + self._job_tester(10, verbose=verbose) + + def test_no_args_no_warnings(self, verbose=False): + self.check_files_no_warnings_allowed(verbose=verbose) + + def test_stdin_jobs_warning(self, verbose=False): + self.count = 0 + + def fake_stdin(): + self.count += 1 + with open(self.this_file(), "r") as f: + return f.read() + + with mock.patch("pep8.stdin_get_value", fake_stdin): + (style_guide, + report, + collected_warnings, + ) = self.check_files_collect_warnings(arglist=['--jobs=4'], + explicit_stdin=True, + verbose=verbose) + expected_warings = [] + if verbose: + expected_warings.append(self.stdin_warning_text) + if is_windows(): + expected_warings.append(self.windows_warning_text) + self.verify_warnings(collected_warnings, expected_warings) + self.assertEqual(self.count, 1) + + def test_jobs_verbose(self): + self.test_jobs(verbose=True) + + def test_no_args_no_warnings_verbose(self): + self.test_no_args_no_warnings(verbose=True) + + def test_stdin_jobs_warning_verbose(self): + self.test_stdin_jobs_warning(verbose=True) + + +if __name__ == '__main__': + unittest.main() diff --git a/env/lib/python2.7/site-packages/flake8/tests/_test_warnings.pyc b/env/lib/python2.7/site-packages/flake8/tests/_test_warnings.pyc new file mode 100644 index 0000000..64c223f Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/_test_warnings.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_engine.py b/env/lib/python2.7/site-packages/flake8/tests/test_engine.py new file mode 100644 index 0000000..2afabbb --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_engine.py @@ -0,0 +1,236 @@ +from __future__ import with_statement + +import errno +import unittest +try: + from unittest import mock +except ImportError: + import mock # < PY33 + +from flake8 import engine, util, __version__, reporter +import pep8 + + +class TestEngine(unittest.TestCase): + def setUp(self): + self.patches = {} + + def tearDown(self): + assert len(self.patches.items()) == 0 + + def start_patch(self, patch): + self.patches[patch] = mock.patch(patch) + return self.patches[patch].start() + + def stop_patches(self): + patches = self.patches.copy() + for k, v in patches.items(): + v.stop() + del(self.patches[k]) + + def test_get_style_guide(self): + with mock.patch('flake8.engine._register_extensions') as reg_ext: + reg_ext.return_value = ([], [], [], []) + g = engine.get_style_guide() + self.assertTrue(isinstance(g, engine.StyleGuide)) + reg_ext.assert_called_once_with() + + def test_get_style_guide_kwargs(self): + m = mock.Mock() + with mock.patch('flake8.engine.StyleGuide') as StyleGuide: + with mock.patch('flake8.engine.get_parser') as get_parser: + m.ignored_extensions = [] + StyleGuide.return_value.options.jobs = '42' + StyleGuide.return_value.options.diff = False + get_parser.return_value = (m, []) + engine.get_style_guide(foo='bar') + get_parser.assert_called_once_with() + StyleGuide.assert_called_once_with(**{'parser': m, 'foo': 'bar'}) + + def test_register_extensions(self): + with mock.patch('pep8.register_check') as register_check: + registered_exts = engine._register_extensions() + self.assertTrue(isinstance(registered_exts[0], util.OrderedSet)) + self.assertTrue(len(registered_exts[0]) > 0) + for i in registered_exts[1:]: + self.assertTrue(isinstance(i, list)) + self.assertTrue(register_check.called) + + def test_disable_extensions(self): + parser = mock.MagicMock() + options = mock.MagicMock() + + parser.ignored_extensions = ['I123', 'I345', 'I678', 'I910'] + + options.enabled_extensions = 'I345,\nI678,I910' + options.ignore = ('E121', 'E123') + + engine._disable_extensions(parser, options) + self.assertEqual(set(options.ignore), set(['E121', 'E123', 'I123'])) + + def test_get_parser(self): + # setup + re = self.start_patch('flake8.engine._register_extensions') + gpv = self.start_patch('flake8.engine.get_python_version') + pgp = self.start_patch('pep8.get_parser') + m = mock.Mock() + re.return_value = ([('pyflakes', '0.7'), ('mccabe', '0.2')], [], [], + []) + gpv.return_value = 'Python Version' + pgp.return_value = m + # actual call we're testing + parser, hooks = engine.get_parser() + # assertions + self.assertTrue(re.called) + self.assertTrue(gpv.called) + pgp.assert_called_once_with( + 'flake8', + '%s (pyflakes: 0.7, mccabe: 0.2) Python Version' % __version__) + self.assertTrue(m.remove_option.called) + self.assertTrue(m.add_option.called) + self.assertEqual(parser, m) + self.assertEqual(hooks, []) + # clean-up + self.stop_patches() + + def test_get_python_version(self): + self.assertTrue('on' in engine.get_python_version()) + # Silly test but it will provide 100% test coverage + # Also we can never be sure (without reconstructing the string + # ourselves) what system we may be testing on. + + def test_windows_disables_jobs(self): + with mock.patch('flake8.util.is_windows') as is_windows: + is_windows.return_value = True + guide = engine.get_style_guide() + assert isinstance(guide, reporter.BaseQReport) is False + + def test_stdin_disables_jobs(self): + with mock.patch('flake8.util.is_using_stdin') as is_using_stdin: + is_using_stdin.return_value = True + guide = engine.get_style_guide() + assert isinstance(guide, reporter.BaseQReport) is False + + def test_disables_extensions_that_are_not_selected(self): + with mock.patch('flake8.engine._register_extensions') as re: + re.return_value = ([('fake_ext', '0.1a1')], [], [], ['X']) + sg = engine.get_style_guide() + assert 'X' in sg.options.ignore + + def test_enables_off_by_default_extensions(self): + with mock.patch('flake8.engine._register_extensions') as re: + re.return_value = ([('fake_ext', '0.1a1')], [], [], ['X']) + parser, options = engine.get_parser() + parser.parse_args(['--select=X']) + sg = engine.StyleGuide(parser=parser) + assert 'X' not in sg.options.ignore + + def test_load_entry_point_verifies_requirements(self): + entry_point = mock.Mock(spec=['require', 'resolve', 'load']) + + engine._load_entry_point(entry_point, verify_requirements=True) + entry_point.require.assert_called_once_with() + entry_point.resolve.assert_called_once_with() + + def test_load_entry_point_does_not_verify_requirements(self): + entry_point = mock.Mock(spec=['require', 'resolve', 'load']) + + engine._load_entry_point(entry_point, verify_requirements=False) + self.assertFalse(entry_point.require.called) + entry_point.resolve.assert_called_once_with() + + def test_load_entry_point_passes_require_argument_to_load(self): + entry_point = mock.Mock(spec=['load']) + + engine._load_entry_point(entry_point, verify_requirements=True) + entry_point.load.assert_called_once_with(require=True) + entry_point.reset_mock() + + engine._load_entry_point(entry_point, verify_requirements=False) + entry_point.load.assert_called_once_with(require=False) + + +def oserror_generator(error_number, message='Ominous OSError message'): + def oserror_side_effect(*args, **kwargs): + if hasattr(oserror_side_effect, 'used'): + return + + oserror_side_effect.used = True + raise OSError(error_number, message) + + return oserror_side_effect + + +class TestStyleGuide(unittest.TestCase): + def setUp(self): + mocked_styleguide = mock.Mock(spec=engine.NoQAStyleGuide) + self.styleguide = engine.StyleGuide(styleguide=mocked_styleguide) + self.mocked_sg = mocked_styleguide + + def test_proxies_excluded(self): + self.styleguide.excluded('file.py', parent='.') + + self.mocked_sg.excluded.assert_called_once_with('file.py', parent='.') + + def test_proxies_init_report(self): + reporter = object() + self.styleguide.init_report(reporter) + + self.mocked_sg.init_report.assert_called_once_with(reporter) + + def test_proxies_check_files(self): + self.styleguide.check_files(['foo', 'bar']) + + self.mocked_sg.check_files.assert_called_once_with( + paths=['foo', 'bar'] + ) + + def test_proxies_input_file(self): + self.styleguide.input_file('file.py', + lines=[9, 10], + expected='foo', + line_offset=20) + + self.mocked_sg.input_file.assert_called_once_with(filename='file.py', + lines=[9, 10], + expected='foo', + line_offset=20) + + def test_check_files_retries_on_specific_OSErrors(self): + self.mocked_sg.check_files.side_effect = oserror_generator( + errno.ENOSPC, 'No space left on device' + ) + + self.styleguide.check_files(['foo', 'bar']) + + self.mocked_sg.init_report.assert_called_once_with(pep8.StandardReport) + + def test_input_file_retries_on_specific_OSErrors(self): + self.mocked_sg.input_file.side_effect = oserror_generator( + errno.ENOSPC, 'No space left on device' + ) + + self.styleguide.input_file('file.py') + + self.mocked_sg.init_report.assert_called_once_with(pep8.StandardReport) + + def test_check_files_reraises_unknown_OSErrors(self): + self.mocked_sg.check_files.side_effect = oserror_generator( + errno.EADDRINUSE, + 'lol why are we talking about binding to sockets' + ) + + self.assertRaises(OSError, self.styleguide.check_files, + ['foo', 'bar']) + + def test_input_file_reraises_unknown_OSErrors(self): + self.mocked_sg.input_file.side_effect = oserror_generator( + errno.EADDRINUSE, + 'lol why are we talking about binding to sockets' + ) + + self.assertRaises(OSError, self.styleguide.input_file, + ['foo', 'bar']) + +if __name__ == '__main__': + unittest.main() diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_engine.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_engine.pyc new file mode 100644 index 0000000..e225911 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_engine.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_hooks.py b/env/lib/python2.7/site-packages/flake8/tests/test_hooks.py new file mode 100644 index 0000000..ba46794 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_hooks.py @@ -0,0 +1,59 @@ +"""Module containing the tests for flake8.hooks.""" +import os +import unittest + +try: + from unittest import mock +except ImportError: + import mock + +import flake8.hooks +from flake8.util import is_windows + + +def excluded(filename): + return filename.endswith('afile.py') + + +class TestGitHook(unittest.TestCase): + if is_windows: + # On Windows, absolute paths start with a drive letter, for example C: + # Here we build a fake absolute path starting with the current drive + # letter, for example C:\fake\temp + current_drive, ignore_tail = os.path.splitdrive(os.getcwd()) + fake_abs_path = os.path.join(current_drive, os.path.sep, 'fake', 'tmp') + else: + fake_abs_path = os.path.join(os.path.sep, 'fake', 'tmp') + + @mock.patch('os.makedirs') + @mock.patch('flake8.hooks.open', create=True) + @mock.patch('shutil.rmtree') + @mock.patch('tempfile.mkdtemp', return_value=fake_abs_path) + @mock.patch('flake8.hooks.run', + return_value=(None, + [os.path.join('foo', 'afile.py'), + os.path.join('foo', 'bfile.py')], + None)) + @mock.patch('flake8.hooks.get_style_guide') + def test_prepends_tmp_directory_to_exclude(self, get_style_guide, run, + *args): + style_guide = get_style_guide.return_value = mock.Mock() + style_guide.options.exclude = [os.path.join('foo', 'afile.py')] + style_guide.options.filename = [os.path.join('foo', '*')] + style_guide.excluded = excluded + + flake8.hooks.git_hook() + + dirname, filename = os.path.split( + os.path.abspath(os.path.join('foo', 'bfile.py'))) + if is_windows: + # In Windows, the absolute path in dirname will start with a drive + # letter. Here, we discad the drive letter. + ignore_drive, dirname = os.path.splitdrive(dirname) + tmpdir = os.path.join(self.fake_abs_path, dirname[1:]) + tmpfile = os.path.join(tmpdir, 'bfile.py') + style_guide.check_files.assert_called_once_with([tmpfile]) + + +if __name__ == '__main__': + unittest.main() diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_hooks.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_hooks.pyc new file mode 100644 index 0000000..fc9c7c6 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_hooks.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_integration.py b/env/lib/python2.7/site-packages/flake8/tests/test_integration.py new file mode 100644 index 0000000..d1417c6 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_integration.py @@ -0,0 +1,79 @@ +from __future__ import with_statement + +import os +import unittest +try: + from unittest import mock +except ImportError: + import mock # < PY33 + +from flake8 import engine +from flake8.util import is_windows + + +class IntegrationTestCase(unittest.TestCase): + """Integration style tests to exercise different command line options.""" + + def this_file(self): + """Return the real path of this file.""" + this_file = os.path.realpath(__file__) + if this_file.endswith("pyc"): + this_file = this_file[:-1] + return this_file + + def check_files(self, arglist=[], explicit_stdin=False, count=0): + """Call check_files.""" + if explicit_stdin: + target_file = "-" + else: + target_file = self.this_file() + argv = ['flake8'] + arglist + [target_file] + with mock.patch("sys.argv", argv): + style_guide = engine.get_style_guide(parse_argv=True) + report = style_guide.check_files() + self.assertEqual(report.total_errors, count) + return style_guide, report + + def test_no_args(self): + # assert there are no reported errors + self.check_files() + + def _job_tester(self, jobs): + # mock stdout.flush so we can count the number of jobs created + with mock.patch('sys.stdout.flush') as mocked: + guide, report = self.check_files(arglist=['--jobs=%s' % jobs]) + if is_windows(): + # The code path where guide.options.jobs gets converted to an + # int is not run on windows. So, do the int conversion here. + self.assertEqual(int(guide.options.jobs), jobs) + # On windows, call count is always zero. + self.assertEqual(mocked.call_count, 0) + else: + self.assertEqual(guide.options.jobs, jobs) + self.assertEqual(mocked.call_count, jobs) + + def test_jobs(self): + self._job_tester(2) + self._job_tester(10) + + def test_stdin(self): + self.count = 0 + + def fake_stdin(): + self.count += 1 + with open(self.this_file(), "r") as f: + return f.read() + + with mock.patch("pep8.stdin_get_value", fake_stdin): + guide, report = self.check_files(arglist=['--jobs=4'], + explicit_stdin=True) + self.assertEqual(self.count, 1) + + def test_stdin_fail(self): + def fake_stdin(): + return "notathing\n" + with mock.patch("pep8.stdin_get_value", fake_stdin): + # only assert needed is in check_files + guide, report = self.check_files(arglist=['--jobs=4'], + explicit_stdin=True, + count=1) diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_integration.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_integration.pyc new file mode 100644 index 0000000..5853794 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_integration.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_main.py b/env/lib/python2.7/site-packages/flake8/tests/test_main.py new file mode 100644 index 0000000..af08093 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_main.py @@ -0,0 +1,18 @@ +from __future__ import with_statement + +import unittest + +import setuptools +from flake8 import main + + +class TestMain(unittest.TestCase): + def test_issue_39_regression(self): + distribution = setuptools.Distribution() + cmd = main.Flake8Command(distribution) + cmd.options_dict = {} + cmd.run() + + +if __name__ == '__main__': + unittest.main() diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_main.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_main.pyc new file mode 100644 index 0000000..64f0675 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_main.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_reporter.py b/env/lib/python2.7/site-packages/flake8/tests/test_reporter.py new file mode 100644 index 0000000..f91bb52 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_reporter.py @@ -0,0 +1,36 @@ +from __future__ import with_statement + +import errno +import unittest +try: + from unittest import mock +except ImportError: + import mock # < PY33 + +from flake8 import reporter + + +def ioerror_report_factory(errno_code): + class IOErrorBaseQReport(reporter.BaseQReport): + def _process_main(self): + raise IOError(errno_code, 'Fake bad pipe exception') + + options = mock.MagicMock() + options.jobs = 2 + return IOErrorBaseQReport(options) + + +class TestBaseQReport(unittest.TestCase): + def test_does_not_raise_a_bad_pipe_ioerror(self): + """Test that no EPIPE IOError exception is re-raised or leaked.""" + report = ioerror_report_factory(errno.EPIPE) + try: + report.process_main() + except IOError: + self.fail('BaseQReport.process_main raised an IOError for EPIPE' + ' but it should have caught this exception.') + + def test_raises_a_enoent_ioerror(self): + """Test that an ENOENT IOError exception is re-raised.""" + report = ioerror_report_factory(errno.ENOENT) + self.assertRaises(IOError, report.process_main) diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_reporter.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_reporter.pyc new file mode 100644 index 0000000..2bb2697 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_reporter.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_util.py b/env/lib/python2.7/site-packages/flake8/tests/test_util.py new file mode 100644 index 0000000..32a1d44 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_util.py @@ -0,0 +1,86 @@ +import unittest + +from flake8.util import option_normalizer + + +class TestOptionSerializer(unittest.TestCase): + + def test_1_is_true(self): + option = option_normalizer('1') + self.assertTrue(option) + + def test_T_is_true(self): + option = option_normalizer('T') + self.assertTrue(option) + + def test_TRUE_is_true(self): + option = option_normalizer('TRUE') + self.assertTrue(option, True) + + def test_ON_is_true(self): + option = option_normalizer('ON') + self.assertTrue(option) + + def test_t_is_true(self): + option = option_normalizer('t') + self.assertTrue(option) + + def test_true_is_true(self): + option = option_normalizer('true') + self.assertTrue(option) + + def test_on_is_true(self): + option = option_normalizer('on') + self.assertTrue(option) + + def test_0_is_false(self): + option = option_normalizer('0') + self.assertFalse(option) + + def test_F_is_false(self): + option = option_normalizer('F') + self.assertFalse(option) + + def test_FALSE_is_false(self): + option = option_normalizer('FALSE') + self.assertFalse(option) + + def test_OFF_is_false(self): + option = option_normalizer('OFF') + self.assertFalse(option) + + def test_f_is_false(self): + option = option_normalizer('f') + self.assertFalse(option) + + def test_false_is_false(self): + option = option_normalizer('false') + self.assertFalse(option) + + def test_off_is_false(self): + option = option_normalizer('off') + self.assertFalse(option) + + def test_parses_lists(self): + answer = ['F401', 'F402', 'F403', 'F404'] + + option = option_normalizer('F401,F402,F403,F404') + self.assertEqual(option, answer) + + option = option_normalizer('F401 ,F402 ,F403 ,F404') + self.assertEqual(option, answer) + + option = option_normalizer('F401, F402, F403, F404') + self.assertEqual(option, answer) + + option = option_normalizer('''\ + F401, + F402, + F403, + F404, + ''') + self.assertEqual(option, answer) + + +if __name__ == '__main__': + unittest.main() diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_util.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_util.pyc new file mode 100644 index 0000000..6c9eef2 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_util.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_warnings.py b/env/lib/python2.7/site-packages/flake8/tests/test_warnings.py new file mode 100644 index 0000000..9dca44b --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/tests/test_warnings.py @@ -0,0 +1,200 @@ +""" + _test_warnings.py + + Tests for the warnings that are emitted by flake8. + + This module is named _test_warnings instead of test_warnings so that a + normal nosetests run does not collect it. The tests in this module pass + when they are run alone, but they fail when they are run along with other + tests (nosetests --with-isolation doesn't help). + + In tox.ini, these tests are run separately. +""" + +from __future__ import with_statement + +import os +import warnings +import unittest +try: + from unittest import mock +except ImportError: + import mock # < PY33 + +from flake8 import engine +from flake8.util import is_windows + + +class IntegrationTestCaseWarnings(unittest.TestCase): + """Integration style tests to check that warnings are issued properly for + different command line options.""" + + windows_warning_text = ("The --jobs option is not available on Windows." + " Ignoring --jobs arguments.") + stdin_warning_text = ("The --jobs option is not compatible with" + " supplying input using - . Ignoring --jobs" + " arguments.") + + def this_file(self): + """Return the real path of this file.""" + this_file = os.path.realpath(__file__) + if this_file.endswith("pyc"): + this_file = this_file[:-1] + return this_file + + @staticmethod + def get_style_guide_with_warnings(engine, *args, **kwargs): + """ + Return a style guide object (obtained by calling + engine.get_style_guide) and a list of the warnings that were raised in + the process. + + Note: not threadsafe + """ + + # Note + # https://docs.python.org/2/library/warnings.html + # + # The catch_warnings manager works by replacing and then later + # restoring the module's showwarning() function and internal list of + # filter specifications. This means the context manager is modifying + # global state and therefore is not thread-safe + + with warnings.catch_warnings(record=True) as collected_warnings: + # Cause all warnings to always be triggered. + warnings.simplefilter("always") + + # Get the style guide + style_guide = engine.get_style_guide(*args, **kwargs) + + # Now that the warnings have been collected, return the style guide and + # the + # warnings. + return (style_guide, collected_warnings) + + def verify_warnings(self, collected_warnings, expected_warnings): + """ + Verifies that collected_warnings is a sequence that contains user + warnings that match the sequence of string values passed in as + expected_warnings. + """ + if expected_warnings is None: + expected_warnings = [] + + collected_user_warnings = [w for w in collected_warnings + if issubclass(w.category, UserWarning)] + + self.assertEqual(len(collected_user_warnings), + len(expected_warnings)) + + collected_warnings_set = set(str(warning.message) + for warning + in collected_user_warnings) + expected_warnings_set = set(expected_warnings) + self.assertEqual(collected_warnings_set, expected_warnings_set) + + def check_files_collect_warnings(self, + arglist=[], + explicit_stdin=False, + count=0, + verbose=False): + """Call check_files and collect any warnings that are issued.""" + if verbose: + arglist.append('--verbose') + if explicit_stdin: + target_file = "-" + else: + target_file = self.this_file() + argv = ['flake8'] + arglist + [target_file] + with mock.patch("sys.argv", argv): + (style_guide, + collected_warnings, + ) = self.get_style_guide_with_warnings(engine, + parse_argv=True) + report = style_guide.check_files() + self.assertEqual(report.total_errors, count) + return style_guide, report, collected_warnings + + def check_files_no_warnings_allowed(self, + arglist=[], + explicit_stdin=False, + count=0, + verbose=False): + """Call check_files, and assert that there were no warnings issued.""" + (style_guide, + report, + collected_warnings, + ) = self.check_files_collect_warnings(arglist=arglist, + explicit_stdin=explicit_stdin, + count=count, + verbose=verbose) + self.verify_warnings(collected_warnings, expected_warnings=None) + return style_guide, report + + def _job_tester(self, jobs, verbose=False): + # mock stdout.flush so we can count the number of jobs created + with mock.patch('sys.stdout.flush') as mocked: + (guide, + report, + collected_warnings, + ) = self.check_files_collect_warnings( + arglist=['--jobs=%s' % jobs], + verbose=verbose) + + if is_windows(): + # The code path where guide.options.jobs gets converted to an + # int is not run on windows. So, do the int conversion here. + self.assertEqual(int(guide.options.jobs), jobs) + # On windows, call count is always zero. + self.assertEqual(mocked.call_count, 0) + else: + self.assertEqual(guide.options.jobs, jobs) + self.assertEqual(mocked.call_count, jobs) + + expected_warings = [] + if verbose and is_windows(): + expected_warings.append(self.windows_warning_text) + self.verify_warnings(collected_warnings, expected_warings) + + def test_jobs(self, verbose=False): + self._job_tester(2, verbose=verbose) + self._job_tester(10, verbose=verbose) + + def test_no_args_no_warnings(self, verbose=False): + self.check_files_no_warnings_allowed(verbose=verbose) + + def test_stdin_jobs_warning(self, verbose=False): + self.count = 0 + + def fake_stdin(): + self.count += 1 + with open(self.this_file(), "r") as f: + return f.read() + + with mock.patch("pep8.stdin_get_value", fake_stdin): + (style_guide, + report, + collected_warnings, + ) = self.check_files_collect_warnings(arglist=['--jobs=4'], + explicit_stdin=True, + verbose=verbose) + expected_warings = [] + if verbose: + expected_warings.append(self.stdin_warning_text) + if is_windows(): + expected_warings.append(self.windows_warning_text) + self.verify_warnings(collected_warnings, expected_warings) + self.assertEqual(self.count, 1) + + def test_jobs_verbose(self): + self.test_jobs(verbose=True) + + def test_no_args_no_warnings_verbose(self): + self.test_no_args_no_warnings(verbose=True) + + def test_stdin_jobs_warning_verbose(self): + self.test_stdin_jobs_warning(verbose=True) + + +if __name__ == '__main__': + unittest.main() diff --git a/env/lib/python2.7/site-packages/flake8/tests/test_warnings.pyc b/env/lib/python2.7/site-packages/flake8/tests/test_warnings.pyc new file mode 100644 index 0000000..e38e588 Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/tests/test_warnings.pyc differ diff --git a/env/lib/python2.7/site-packages/flake8/util.py b/env/lib/python2.7/site-packages/flake8/util.py new file mode 100644 index 0000000..da33f42 --- /dev/null +++ b/env/lib/python2.7/site-packages/flake8/util.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +import os + +try: + import ast + iter_child_nodes = ast.iter_child_nodes +except ImportError: # Python 2.5 + import _ast as ast + + if 'decorator_list' not in ast.ClassDef._fields: + # Patch the missing attribute 'decorator_list' + ast.ClassDef.decorator_list = () + ast.FunctionDef.decorator_list = property(lambda s: s.decorators) + + def iter_child_nodes(node): + """ + Yield all direct child nodes of *node*, that is, all fields that + are nodes and all items of fields that are lists of nodes. + """ + if not node._fields: + return + for name in node._fields: + field = getattr(node, name, None) + if isinstance(field, ast.AST): + yield field + elif isinstance(field, list): + for item in field: + if isinstance(item, ast.AST): + yield item + + +class OrderedSet(list): + """List without duplicates.""" + __slots__ = () + + def add(self, value): + if value not in self: + self.append(value) + + +def is_windows(): + """Determine if the system is Windows.""" + return os.name == 'nt' + + +def is_using_stdin(paths): + """Determine if we're running checks on stdin.""" + return '-' in paths + + +def warn_when_using_jobs(options): + return (options.verbose and options.jobs and options.jobs.isdigit() and + int(options.jobs) > 1) + + +def force_disable_jobs(styleguide): + return is_windows() or is_using_stdin(styleguide.paths) + + +def option_normalizer(value): + if str(value).upper() in ('1', 'T', 'TRUE', 'ON'): + value = True + if str(value).upper() in ('0', 'F', 'FALSE', 'OFF'): + value = False + + if isinstance(value, str): + value = [opt.strip() for opt in value.split(',') if opt.strip()] + + return value diff --git a/env/lib/python2.7/site-packages/flake8/util.pyc b/env/lib/python2.7/site-packages/flake8/util.pyc new file mode 100644 index 0000000..93601ac Binary files /dev/null and b/env/lib/python2.7/site-packages/flake8/util.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/__init__.py b/env/lib/python2.7/site-packages/flask/__init__.py new file mode 100644 index 0000000..3fd8908 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/__init__.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +""" + flask + ~~~~~ + + A microframework based on Werkzeug. It's extensively documented + and follows best practice patterns. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +__version__ = '0.10.1' + +# utilities we import from Werkzeug and Jinja2 that are unused +# in the module but are exported as public interface. +from werkzeug.exceptions import abort +from werkzeug.utils import redirect +from jinja2 import Markup, escape + +from .app import Flask, Request, Response +from .config import Config +from .helpers import url_for, flash, send_file, send_from_directory, \ + get_flashed_messages, get_template_attribute, make_response, safe_join, \ + stream_with_context +from .globals import current_app, g, request, session, _request_ctx_stack, \ + _app_ctx_stack +from .ctx import has_request_context, has_app_context, \ + after_this_request, copy_current_request_context +from .module import Module +from .blueprints import Blueprint +from .templating import render_template, render_template_string + +# the signals +from .signals import signals_available, template_rendered, request_started, \ + request_finished, got_request_exception, request_tearing_down, \ + appcontext_tearing_down, appcontext_pushed, \ + appcontext_popped, message_flashed + +# We're not exposing the actual json module but a convenient wrapper around +# it. +from . import json + +# This was the only thing that flask used to export at one point and it had +# a more generic name. +jsonify = json.jsonify + +# backwards compat, goes away in 1.0 +from .sessions import SecureCookieSession as Session +json_available = True diff --git a/env/lib/python2.7/site-packages/flask/__init__.pyc b/env/lib/python2.7/site-packages/flask/__init__.pyc new file mode 100644 index 0000000..3998236 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/__init__.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/_compat.py b/env/lib/python2.7/site-packages/flask/_compat.py new file mode 100644 index 0000000..c342884 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/_compat.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +""" + flask._compat + ~~~~~~~~~~~~~ + + Some py2/py3 compatibility support based on a stripped down + version of six so we don't have to depend on a specific version + of it. + + :copyright: (c) 2013 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import sys + +PY2 = sys.version_info[0] == 2 +_identity = lambda x: x + + +if not PY2: + text_type = str + string_types = (str,) + integer_types = (int, ) + + iterkeys = lambda d: iter(d.keys()) + itervalues = lambda d: iter(d.values()) + iteritems = lambda d: iter(d.items()) + + from io import StringIO + + def reraise(tp, value, tb=None): + if value.__traceback__ is not tb: + raise value.with_traceback(tb) + raise value + + implements_to_string = _identity + +else: + text_type = unicode + string_types = (str, unicode) + integer_types = (int, long) + + iterkeys = lambda d: d.iterkeys() + itervalues = lambda d: d.itervalues() + iteritems = lambda d: d.iteritems() + + from cStringIO import StringIO + + exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') + + def implements_to_string(cls): + cls.__unicode__ = cls.__str__ + cls.__str__ = lambda x: x.__unicode__().encode('utf-8') + return cls + + +def with_metaclass(meta, *bases): + # This requires a bit of explanation: the basic idea is to make a + # dummy metaclass for one level of class instantiation that replaces + # itself with the actual metaclass. Because of internal type checks + # we also need to make sure that we downgrade the custom metaclass + # for one level to something closer to type (that's why __call__ and + # __init__ comes back from type etc.). + # + # This has the advantage over six.with_metaclass in that it does not + # introduce dummy classes into the final MRO. + class metaclass(meta): + __call__ = type.__call__ + __init__ = type.__init__ + def __new__(cls, name, this_bases, d): + if this_bases is None: + return type.__new__(cls, name, (), d) + return meta(name, bases, d) + return metaclass('temporary_class', None, {}) diff --git a/env/lib/python2.7/site-packages/flask/_compat.pyc b/env/lib/python2.7/site-packages/flask/_compat.pyc new file mode 100644 index 0000000..eec9949 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/_compat.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/app.py b/env/lib/python2.7/site-packages/flask/app.py new file mode 100644 index 0000000..addc40b --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/app.py @@ -0,0 +1,1842 @@ +# -*- coding: utf-8 -*- +""" + flask.app + ~~~~~~~~~ + + This module implements the central WSGI application object. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import os +import sys +from threading import Lock +from datetime import timedelta +from itertools import chain +from functools import update_wrapper + +from werkzeug.datastructures import ImmutableDict +from werkzeug.routing import Map, Rule, RequestRedirect, BuildError +from werkzeug.exceptions import HTTPException, InternalServerError, \ + MethodNotAllowed, BadRequest + +from .helpers import _PackageBoundObject, url_for, get_flashed_messages, \ + locked_cached_property, _endpoint_from_view_func, find_package +from . import json +from .wrappers import Request, Response +from .config import ConfigAttribute, Config +from .ctx import RequestContext, AppContext, _AppCtxGlobals +from .globals import _request_ctx_stack, request, session, g +from .sessions import SecureCookieSessionInterface +from .module import blueprint_is_module +from .templating import DispatchingJinjaLoader, Environment, \ + _default_template_ctx_processor +from .signals import request_started, request_finished, got_request_exception, \ + request_tearing_down, appcontext_tearing_down +from ._compat import reraise, string_types, text_type, integer_types + +# a lock used for logger initialization +_logger_lock = Lock() + + +def _make_timedelta(value): + if not isinstance(value, timedelta): + return timedelta(seconds=value) + return value + + +def setupmethod(f): + """Wraps a method so that it performs a check in debug mode if the + first request was already handled. + """ + def wrapper_func(self, *args, **kwargs): + if self.debug and self._got_first_request: + raise AssertionError('A setup function was called after the ' + 'first request was handled. This usually indicates a bug ' + 'in the application where a module was not imported ' + 'and decorators or other functionality was called too late.\n' + 'To fix this make sure to import all your view modules, ' + 'database models and everything related at a central place ' + 'before the application starts serving requests.') + return f(self, *args, **kwargs) + return update_wrapper(wrapper_func, f) + + +class Flask(_PackageBoundObject): + """The flask object implements a WSGI application and acts as the central + object. It is passed the name of the module or package of the + application. Once it is created it will act as a central registry for + the view functions, the URL rules, template configuration and much more. + + The name of the package is used to resolve resources from inside the + package or the folder the module is contained in depending on if the + package parameter resolves to an actual python package (a folder with + an `__init__.py` file inside) or a standard module (just a `.py` file). + + For more information about resource loading, see :func:`open_resource`. + + Usually you create a :class:`Flask` instance in your main module or + in the `__init__.py` file of your package like this:: + + from flask import Flask + app = Flask(__name__) + + .. admonition:: About the First Parameter + + The idea of the first parameter is to give Flask an idea what + belongs to your application. This name is used to find resources + on the file system, can be used by extensions to improve debugging + information and a lot more. + + So it's important what you provide there. If you are using a single + module, `__name__` is always the correct value. If you however are + using a package, it's usually recommended to hardcode the name of + your package there. + + For example if your application is defined in `yourapplication/app.py` + you should create it with one of the two versions below:: + + app = Flask('yourapplication') + app = Flask(__name__.split('.')[0]) + + Why is that? The application will work even with `__name__`, thanks + to how resources are looked up. However it will make debugging more + painful. Certain extensions can make assumptions based on the + import name of your application. For example the Flask-SQLAlchemy + extension will look for the code in your application that triggered + an SQL query in debug mode. If the import name is not properly set + up, that debugging information is lost. (For example it would only + pick up SQL queries in `yourapplication.app` and not + `yourapplication.views.frontend`) + + .. versionadded:: 0.7 + The `static_url_path`, `static_folder`, and `template_folder` + parameters were added. + + .. versionadded:: 0.8 + The `instance_path` and `instance_relative_config` parameters were + added. + + :param import_name: the name of the application package + :param static_url_path: can be used to specify a different path for the + static files on the web. Defaults to the name + of the `static_folder` folder. + :param static_folder: the folder with static files that should be served + at `static_url_path`. Defaults to the ``'static'`` + folder in the root path of the application. + :param template_folder: the folder that contains the templates that should + be used by the application. Defaults to + ``'templates'`` folder in the root path of the + application. + :param instance_path: An alternative instance path for the application. + By default the folder ``'instance'`` next to the + package or module is assumed to be the instance + path. + :param instance_relative_config: if set to `True` relative filenames + for loading the config are assumed to + be relative to the instance path instead + of the application root. + """ + + #: The class that is used for request objects. See :class:`~flask.Request` + #: for more information. + request_class = Request + + #: The class that is used for response objects. See + #: :class:`~flask.Response` for more information. + response_class = Response + + #: The class that is used for the :data:`~flask.g` instance. + #: + #: Example use cases for a custom class: + #: + #: 1. Store arbitrary attributes on flask.g. + #: 2. Add a property for lazy per-request database connectors. + #: 3. Return None instead of AttributeError on expected attributes. + #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. + #: + #: In Flask 0.9 this property was called `request_globals_class` but it + #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the + #: flask.g object is not application context scoped. + #: + #: .. versionadded:: 0.10 + app_ctx_globals_class = _AppCtxGlobals + + # Backwards compatibility support + def _get_request_globals_class(self): + return self.app_ctx_globals_class + def _set_request_globals_class(self, value): + from warnings import warn + warn(DeprecationWarning('request_globals_class attribute is now ' + 'called app_ctx_globals_class')) + self.app_ctx_globals_class = value + request_globals_class = property(_get_request_globals_class, + _set_request_globals_class) + del _get_request_globals_class, _set_request_globals_class + + #: The debug flag. Set this to `True` to enable debugging of the + #: application. In debug mode the debugger will kick in when an unhandled + #: exception occurs and the integrated server will automatically reload + #: the application if changes in the code are detected. + #: + #: This attribute can also be configured from the config with the `DEBUG` + #: configuration key. Defaults to `False`. + debug = ConfigAttribute('DEBUG') + + #: The testing flag. Set this to `True` to enable the test mode of + #: Flask extensions (and in the future probably also Flask itself). + #: For example this might activate unittest helpers that have an + #: additional runtime cost which should not be enabled by default. + #: + #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the + #: default it's implicitly enabled. + #: + #: This attribute can also be configured from the config with the + #: `TESTING` configuration key. Defaults to `False`. + testing = ConfigAttribute('TESTING') + + #: If a secret key is set, cryptographic components can use this to + #: sign cookies and other things. Set this to a complex random value + #: when you want to use the secure cookie for instance. + #: + #: This attribute can also be configured from the config with the + #: `SECRET_KEY` configuration key. Defaults to `None`. + secret_key = ConfigAttribute('SECRET_KEY') + + #: The secure cookie uses this for the name of the session cookie. + #: + #: This attribute can also be configured from the config with the + #: `SESSION_COOKIE_NAME` configuration key. Defaults to ``'session'`` + session_cookie_name = ConfigAttribute('SESSION_COOKIE_NAME') + + #: A :class:`~datetime.timedelta` which is used to set the expiration + #: date of a permanent session. The default is 31 days which makes a + #: permanent session survive for roughly one month. + #: + #: This attribute can also be configured from the config with the + #: `PERMANENT_SESSION_LIFETIME` configuration key. Defaults to + #: ``timedelta(days=31)`` + permanent_session_lifetime = ConfigAttribute('PERMANENT_SESSION_LIFETIME', + get_converter=_make_timedelta) + + #: Enable this if you want to use the X-Sendfile feature. Keep in + #: mind that the server has to support this. This only affects files + #: sent with the :func:`send_file` method. + #: + #: .. versionadded:: 0.2 + #: + #: This attribute can also be configured from the config with the + #: `USE_X_SENDFILE` configuration key. Defaults to `False`. + use_x_sendfile = ConfigAttribute('USE_X_SENDFILE') + + #: The name of the logger to use. By default the logger name is the + #: package name passed to the constructor. + #: + #: .. versionadded:: 0.4 + logger_name = ConfigAttribute('LOGGER_NAME') + + #: Enable the deprecated module support? This is active by default + #: in 0.7 but will be changed to False in 0.8. With Flask 1.0 modules + #: will be removed in favor of Blueprints + enable_modules = True + + #: The logging format used for the debug logger. This is only used when + #: the application is in debug mode, otherwise the attached logging + #: handler does the formatting. + #: + #: .. versionadded:: 0.3 + debug_log_format = ( + '-' * 80 + '\n' + + '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:\n' + + '%(message)s\n' + + '-' * 80 + ) + + #: The JSON encoder class to use. Defaults to :class:`~flask.json.JSONEncoder`. + #: + #: .. versionadded:: 0.10 + json_encoder = json.JSONEncoder + + #: The JSON decoder class to use. Defaults to :class:`~flask.json.JSONDecoder`. + #: + #: .. versionadded:: 0.10 + json_decoder = json.JSONDecoder + + #: Options that are passed directly to the Jinja2 environment. + jinja_options = ImmutableDict( + extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'] + ) + + #: Default configuration parameters. + default_config = ImmutableDict({ + 'DEBUG': False, + 'TESTING': False, + 'PROPAGATE_EXCEPTIONS': None, + 'PRESERVE_CONTEXT_ON_EXCEPTION': None, + 'SECRET_KEY': None, + 'PERMANENT_SESSION_LIFETIME': timedelta(days=31), + 'USE_X_SENDFILE': False, + 'LOGGER_NAME': None, + 'SERVER_NAME': None, + 'APPLICATION_ROOT': None, + 'SESSION_COOKIE_NAME': 'session', + 'SESSION_COOKIE_DOMAIN': None, + 'SESSION_COOKIE_PATH': None, + 'SESSION_COOKIE_HTTPONLY': True, + 'SESSION_COOKIE_SECURE': False, + 'MAX_CONTENT_LENGTH': None, + 'SEND_FILE_MAX_AGE_DEFAULT': 12 * 60 * 60, # 12 hours + 'TRAP_BAD_REQUEST_ERRORS': False, + 'TRAP_HTTP_EXCEPTIONS': False, + 'PREFERRED_URL_SCHEME': 'http', + 'JSON_AS_ASCII': True, + 'JSON_SORT_KEYS': True, + 'JSONIFY_PRETTYPRINT_REGULAR': True, + }) + + #: The rule object to use for URL rules created. This is used by + #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. + #: + #: .. versionadded:: 0.7 + url_rule_class = Rule + + #: the test client that is used with when `test_client` is used. + #: + #: .. versionadded:: 0.7 + test_client_class = None + + #: the session interface to use. By default an instance of + #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. + #: + #: .. versionadded:: 0.8 + session_interface = SecureCookieSessionInterface() + + def __init__(self, import_name, static_path=None, static_url_path=None, + static_folder='static', template_folder='templates', + instance_path=None, instance_relative_config=False): + _PackageBoundObject.__init__(self, import_name, + template_folder=template_folder) + if static_path is not None: + from warnings import warn + warn(DeprecationWarning('static_path is now called ' + 'static_url_path'), stacklevel=2) + static_url_path = static_path + + if static_url_path is not None: + self.static_url_path = static_url_path + if static_folder is not None: + self.static_folder = static_folder + if instance_path is None: + instance_path = self.auto_find_instance_path() + elif not os.path.isabs(instance_path): + raise ValueError('If an instance path is provided it must be ' + 'absolute. A relative path was given instead.') + + #: Holds the path to the instance folder. + #: + #: .. versionadded:: 0.8 + self.instance_path = instance_path + + #: The configuration dictionary as :class:`Config`. This behaves + #: exactly like a regular dictionary but supports additional methods + #: to load a config from files. + self.config = self.make_config(instance_relative_config) + + # Prepare the deferred setup of the logger. + self._logger = None + self.logger_name = self.import_name + + #: A dictionary of all view functions registered. The keys will + #: be function names which are also used to generate URLs and + #: the values are the function objects themselves. + #: To register a view function, use the :meth:`route` decorator. + self.view_functions = {} + + # support for the now deprecated `error_handlers` attribute. The + # :attr:`error_handler_spec` shall be used now. + self._error_handlers = {} + + #: A dictionary of all registered error handlers. The key is `None` + #: for error handlers active on the application, otherwise the key is + #: the name of the blueprint. Each key points to another dictionary + #: where they key is the status code of the http exception. The + #: special key `None` points to a list of tuples where the first item + #: is the class for the instance check and the second the error handler + #: function. + #: + #: To register a error handler, use the :meth:`errorhandler` + #: decorator. + self.error_handler_spec = {None: self._error_handlers} + + #: A list of functions that are called when :meth:`url_for` raises a + #: :exc:`~werkzeug.routing.BuildError`. Each function registered here + #: is called with `error`, `endpoint` and `values`. If a function + #: returns `None` or raises a `BuildError` the next function is + #: tried. + #: + #: .. versionadded:: 0.9 + self.url_build_error_handlers = [] + + #: A dictionary with lists of functions that should be called at the + #: beginning of the request. The key of the dictionary is the name of + #: the blueprint this function is active for, `None` for all requests. + #: This can for example be used to open database connections or + #: getting hold of the currently logged in user. To register a + #: function here, use the :meth:`before_request` decorator. + self.before_request_funcs = {} + + #: A lists of functions that should be called at the beginning of the + #: first request to this instance. To register a function here, use + #: the :meth:`before_first_request` decorator. + #: + #: .. versionadded:: 0.8 + self.before_first_request_funcs = [] + + #: A dictionary with lists of functions that should be called after + #: each request. The key of the dictionary is the name of the blueprint + #: this function is active for, `None` for all requests. This can for + #: example be used to open database connections or getting hold of the + #: currently logged in user. To register a function here, use the + #: :meth:`after_request` decorator. + self.after_request_funcs = {} + + #: A dictionary with lists of functions that are called after + #: each request, even if an exception has occurred. The key of the + #: dictionary is the name of the blueprint this function is active for, + #: `None` for all requests. These functions are not allowed to modify + #: the request, and their return values are ignored. If an exception + #: occurred while processing the request, it gets passed to each + #: teardown_request function. To register a function here, use the + #: :meth:`teardown_request` decorator. + #: + #: .. versionadded:: 0.7 + self.teardown_request_funcs = {} + + #: A list of functions that are called when the application context + #: is destroyed. Since the application context is also torn down + #: if the request ends this is the place to store code that disconnects + #: from databases. + #: + #: .. versionadded:: 0.9 + self.teardown_appcontext_funcs = [] + + #: A dictionary with lists of functions that can be used as URL + #: value processor functions. Whenever a URL is built these functions + #: are called to modify the dictionary of values in place. The key + #: `None` here is used for application wide + #: callbacks, otherwise the key is the name of the blueprint. + #: Each of these functions has the chance to modify the dictionary + #: + #: .. versionadded:: 0.7 + self.url_value_preprocessors = {} + + #: A dictionary with lists of functions that can be used as URL value + #: preprocessors. The key `None` here is used for application wide + #: callbacks, otherwise the key is the name of the blueprint. + #: Each of these functions has the chance to modify the dictionary + #: of URL values before they are used as the keyword arguments of the + #: view function. For each function registered this one should also + #: provide a :meth:`url_defaults` function that adds the parameters + #: automatically again that were removed that way. + #: + #: .. versionadded:: 0.7 + self.url_default_functions = {} + + #: A dictionary with list of functions that are called without argument + #: to populate the template context. The key of the dictionary is the + #: name of the blueprint this function is active for, `None` for all + #: requests. Each returns a dictionary that the template context is + #: updated with. To register a function here, use the + #: :meth:`context_processor` decorator. + self.template_context_processors = { + None: [_default_template_ctx_processor] + } + + #: all the attached blueprints in a dictionary by name. Blueprints + #: can be attached multiple times so this dictionary does not tell + #: you how often they got attached. + #: + #: .. versionadded:: 0.7 + self.blueprints = {} + + #: a place where extensions can store application specific state. For + #: example this is where an extension could store database engines and + #: similar things. For backwards compatibility extensions should register + #: themselves like this:: + #: + #: if not hasattr(app, 'extensions'): + #: app.extensions = {} + #: app.extensions['extensionname'] = SomeObject() + #: + #: The key must match the name of the `flaskext` module. For example in + #: case of a "Flask-Foo" extension in `flaskext.foo`, the key would be + #: ``'foo'``. + #: + #: .. versionadded:: 0.7 + self.extensions = {} + + #: The :class:`~werkzeug.routing.Map` for this instance. You can use + #: this to change the routing converters after the class was created + #: but before any routes are connected. Example:: + #: + #: from werkzeug.routing import BaseConverter + #: + #: class ListConverter(BaseConverter): + #: def to_python(self, value): + #: return value.split(',') + #: def to_url(self, values): + #: return ','.join(BaseConverter.to_url(value) + #: for value in values) + #: + #: app = Flask(__name__) + #: app.url_map.converters['list'] = ListConverter + self.url_map = Map() + + # tracks internally if the application already handled at least one + # request. + self._got_first_request = False + self._before_request_lock = Lock() + + # register the static folder for the application. Do that even + # if the folder does not exist. First of all it might be created + # while the server is running (usually happens during development) + # but also because google appengine stores static files somewhere + # else when mapped with the .yml file. + if self.has_static_folder: + self.add_url_rule(self.static_url_path + '/', + endpoint='static', + view_func=self.send_static_file) + + def _get_error_handlers(self): + from warnings import warn + warn(DeprecationWarning('error_handlers is deprecated, use the ' + 'new error_handler_spec attribute instead.'), stacklevel=1) + return self._error_handlers + def _set_error_handlers(self, value): + self._error_handlers = value + self.error_handler_spec[None] = value + error_handlers = property(_get_error_handlers, _set_error_handlers) + del _get_error_handlers, _set_error_handlers + + @locked_cached_property + def name(self): + """The name of the application. This is usually the import name + with the difference that it's guessed from the run file if the + import name is main. This name is used as a display name when + Flask needs the name of the application. It can be set and overridden + to change the value. + + .. versionadded:: 0.8 + """ + if self.import_name == '__main__': + fn = getattr(sys.modules['__main__'], '__file__', None) + if fn is None: + return '__main__' + return os.path.splitext(os.path.basename(fn))[0] + return self.import_name + + @property + def propagate_exceptions(self): + """Returns the value of the `PROPAGATE_EXCEPTIONS` configuration + value in case it's set, otherwise a sensible default is returned. + + .. versionadded:: 0.7 + """ + rv = self.config['PROPAGATE_EXCEPTIONS'] + if rv is not None: + return rv + return self.testing or self.debug + + @property + def preserve_context_on_exception(self): + """Returns the value of the `PRESERVE_CONTEXT_ON_EXCEPTION` + configuration value in case it's set, otherwise a sensible default + is returned. + + .. versionadded:: 0.7 + """ + rv = self.config['PRESERVE_CONTEXT_ON_EXCEPTION'] + if rv is not None: + return rv + return self.debug + + @property + def logger(self): + """A :class:`logging.Logger` object for this application. The + default configuration is to log to stderr if the application is + in debug mode. This logger can be used to (surprise) log messages. + Here some examples:: + + app.logger.debug('A value for debugging') + app.logger.warning('A warning occurred (%d apples)', 42) + app.logger.error('An error occurred') + + .. versionadded:: 0.3 + """ + if self._logger and self._logger.name == self.logger_name: + return self._logger + with _logger_lock: + if self._logger and self._logger.name == self.logger_name: + return self._logger + from flask.logging import create_logger + self._logger = rv = create_logger(self) + return rv + + @locked_cached_property + def jinja_env(self): + """The Jinja2 environment used to load templates.""" + return self.create_jinja_environment() + + @property + def got_first_request(self): + """This attribute is set to `True` if the application started + handling the first request. + + .. versionadded:: 0.8 + """ + return self._got_first_request + + def make_config(self, instance_relative=False): + """Used to create the config attribute by the Flask constructor. + The `instance_relative` parameter is passed in from the constructor + of Flask (there named `instance_relative_config`) and indicates if + the config should be relative to the instance path or the root path + of the application. + + .. versionadded:: 0.8 + """ + root_path = self.root_path + if instance_relative: + root_path = self.instance_path + return Config(root_path, self.default_config) + + def auto_find_instance_path(self): + """Tries to locate the instance path if it was not provided to the + constructor of the application class. It will basically calculate + the path to a folder named ``instance`` next to your main file or + the package. + + .. versionadded:: 0.8 + """ + prefix, package_path = find_package(self.import_name) + if prefix is None: + return os.path.join(package_path, 'instance') + return os.path.join(prefix, 'var', self.name + '-instance') + + def open_instance_resource(self, resource, mode='rb'): + """Opens a resource from the application's instance folder + (:attr:`instance_path`). Otherwise works like + :meth:`open_resource`. Instance resources can also be opened for + writing. + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + return open(os.path.join(self.instance_path, resource), mode) + + def create_jinja_environment(self): + """Creates the Jinja2 environment based on :attr:`jinja_options` + and :meth:`select_jinja_autoescape`. Since 0.7 this also adds + the Jinja2 globals and filters after initialization. Override + this function to customize the behavior. + + .. versionadded:: 0.5 + """ + options = dict(self.jinja_options) + if 'autoescape' not in options: + options['autoescape'] = self.select_jinja_autoescape + rv = Environment(self, **options) + rv.globals.update( + url_for=url_for, + get_flashed_messages=get_flashed_messages, + config=self.config, + # request, session and g are normally added with the + # context processor for efficiency reasons but for imported + # templates we also want the proxies in there. + request=request, + session=session, + g=g + ) + rv.filters['tojson'] = json.tojson_filter + return rv + + def create_global_jinja_loader(self): + """Creates the loader for the Jinja2 environment. Can be used to + override just the loader and keeping the rest unchanged. It's + discouraged to override this function. Instead one should override + the :meth:`jinja_loader` function instead. + + The global loader dispatches between the loaders of the application + and the individual blueprints. + + .. versionadded:: 0.7 + """ + return DispatchingJinjaLoader(self) + + def init_jinja_globals(self): + """Deprecated. Used to initialize the Jinja2 globals. + + .. versionadded:: 0.5 + .. versionchanged:: 0.7 + This method is deprecated with 0.7. Override + :meth:`create_jinja_environment` instead. + """ + + def select_jinja_autoescape(self, filename): + """Returns `True` if autoescaping should be active for the given + template name. + + .. versionadded:: 0.5 + """ + if filename is None: + return False + return filename.endswith(('.html', '.htm', '.xml', '.xhtml')) + + def update_template_context(self, context): + """Update the template context with some commonly used variables. + This injects request, session, config and g into the template + context as well as everything template context processors want + to inject. Note that the as of Flask 0.6, the original values + in the context will not be overridden if a context processor + decides to return a value with the same key. + + :param context: the context as a dictionary that is updated in place + to add extra variables. + """ + funcs = self.template_context_processors[None] + reqctx = _request_ctx_stack.top + if reqctx is not None: + bp = reqctx.request.blueprint + if bp is not None and bp in self.template_context_processors: + funcs = chain(funcs, self.template_context_processors[bp]) + orig_ctx = context.copy() + for func in funcs: + context.update(func()) + # make sure the original values win. This makes it possible to + # easier add new variables in context processors without breaking + # existing views. + context.update(orig_ctx) + + def run(self, host=None, port=None, debug=None, **options): + """Runs the application on a local development server. If the + :attr:`debug` flag is set the server will automatically reload + for code changes and show a debugger in case an exception happened. + + If you want to run the application in debug mode, but disable the + code execution on the interactive debugger, you can pass + ``use_evalex=False`` as parameter. This will keep the debugger's + traceback screen active, but disable code execution. + + .. admonition:: Keep in Mind + + Flask will suppress any server error with a generic error page + unless it is in debug mode. As such to enable just the + interactive debugger without the code reloading, you have to + invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. + Setting ``use_debugger`` to `True` without being in debug mode + won't catch any exceptions because there won't be any to + catch. + + .. versionchanged:: 0.10 + The default port is now picked from the ``SERVER_NAME`` variable. + + :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to + have the server available externally as well. Defaults to + ``'127.0.0.1'``. + :param port: the port of the webserver. Defaults to ``5000`` or the + port defined in the ``SERVER_NAME`` config variable if + present. + :param debug: if given, enable or disable debug mode. + See :attr:`debug`. + :param options: the options to be forwarded to the underlying + Werkzeug server. See + :func:`werkzeug.serving.run_simple` for more + information. + """ + from werkzeug.serving import run_simple + if host is None: + host = '127.0.0.1' + if port is None: + server_name = self.config['SERVER_NAME'] + if server_name and ':' in server_name: + port = int(server_name.rsplit(':', 1)[1]) + else: + port = 5000 + if debug is not None: + self.debug = bool(debug) + options.setdefault('use_reloader', self.debug) + options.setdefault('use_debugger', self.debug) + try: + run_simple(host, port, self, **options) + finally: + # reset the first request information if the development server + # resetted normally. This makes it possible to restart the server + # without reloader and that stuff from an interactive shell. + self._got_first_request = False + + def test_client(self, use_cookies=True): + """Creates a test client for this application. For information + about unit testing head over to :ref:`testing`. + + Note that if you are testing for assertions or exceptions in your + application code, you must set ``app.testing = True`` in order for the + exceptions to propagate to the test client. Otherwise, the exception + will be handled by the application (not visible to the test client) and + the only indication of an AssertionError or other exception will be a + 500 status code response to the test client. See the :attr:`testing` + attribute. For example:: + + app.testing = True + client = app.test_client() + + The test client can be used in a `with` block to defer the closing down + of the context until the end of the `with` block. This is useful if + you want to access the context locals for testing:: + + with app.test_client() as c: + rv = c.get('/?vodka=42') + assert request.args['vodka'] == '42' + + See :class:`~flask.testing.FlaskClient` for more information. + + .. versionchanged:: 0.4 + added support for `with` block usage for the client. + + .. versionadded:: 0.7 + The `use_cookies` parameter was added as well as the ability + to override the client to be used by setting the + :attr:`test_client_class` attribute. + """ + cls = self.test_client_class + if cls is None: + from flask.testing import FlaskClient as cls + return cls(self, self.response_class, use_cookies=use_cookies) + + def open_session(self, request): + """Creates or opens a new session. Default implementation stores all + session data in a signed cookie. This requires that the + :attr:`secret_key` is set. Instead of overriding this method + we recommend replacing the :class:`session_interface`. + + :param request: an instance of :attr:`request_class`. + """ + return self.session_interface.open_session(self, request) + + def save_session(self, session, response): + """Saves the session if it needs updates. For the default + implementation, check :meth:`open_session`. Instead of overriding this + method we recommend replacing the :class:`session_interface`. + + :param session: the session to be saved (a + :class:`~werkzeug.contrib.securecookie.SecureCookie` + object) + :param response: an instance of :attr:`response_class` + """ + return self.session_interface.save_session(self, session, response) + + def make_null_session(self): + """Creates a new instance of a missing session. Instead of overriding + this method we recommend replacing the :class:`session_interface`. + + .. versionadded:: 0.7 + """ + return self.session_interface.make_null_session(self) + + def register_module(self, module, **options): + """Registers a module with this application. The keyword argument + of this function are the same as the ones for the constructor of the + :class:`Module` class and will override the values of the module if + provided. + + .. versionchanged:: 0.7 + The module system was deprecated in favor for the blueprint + system. + """ + assert blueprint_is_module(module), 'register_module requires ' \ + 'actual module objects. Please upgrade to blueprints though.' + if not self.enable_modules: + raise RuntimeError('Module support was disabled but code ' + 'attempted to register a module named %r' % module) + else: + from warnings import warn + warn(DeprecationWarning('Modules are deprecated. Upgrade to ' + 'using blueprints. Have a look into the documentation for ' + 'more information. If this module was registered by a ' + 'Flask-Extension upgrade the extension or contact the author ' + 'of that extension instead. (Registered %r)' % module), + stacklevel=2) + + self.register_blueprint(module, **options) + + @setupmethod + def register_blueprint(self, blueprint, **options): + """Registers a blueprint on the application. + + .. versionadded:: 0.7 + """ + first_registration = False + if blueprint.name in self.blueprints: + assert self.blueprints[blueprint.name] is blueprint, \ + 'A blueprint\'s name collision occurred between %r and ' \ + '%r. Both share the same name "%s". Blueprints that ' \ + 'are created on the fly need unique names.' % \ + (blueprint, self.blueprints[blueprint.name], blueprint.name) + else: + self.blueprints[blueprint.name] = blueprint + first_registration = True + blueprint.register(self, options, first_registration) + + @setupmethod + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + """Connects a URL rule. Works exactly like the :meth:`route` + decorator. If a view_func is provided it will be registered with the + endpoint. + + Basically this example:: + + @app.route('/') + def index(): + pass + + Is equivalent to the following:: + + def index(): + pass + app.add_url_rule('/', 'index', index) + + If the view_func is not provided you will need to connect the endpoint + to a view function like so:: + + app.view_functions['index'] = index + + Internally :meth:`route` invokes :meth:`add_url_rule` so if you want + to customize the behavior via subclassing you only need to change + this method. + + For more information refer to :ref:`url-route-registrations`. + + .. versionchanged:: 0.2 + `view_func` parameter added. + + .. versionchanged:: 0.6 + `OPTIONS` is added automatically as method. + + :param rule: the URL rule as string + :param endpoint: the endpoint for the registered URL rule. Flask + itself assumes the name of the view function as + endpoint + :param view_func: the function to call when serving a request to the + provided endpoint + :param options: the options to be forwarded to the underlying + :class:`~werkzeug.routing.Rule` object. A change + to Werkzeug is handling of method options. methods + is a list of methods this rule should be limited + to (`GET`, `POST` etc.). By default a rule + just listens for `GET` (and implicitly `HEAD`). + Starting with Flask 0.6, `OPTIONS` is implicitly + added and handled by the standard request handling. + """ + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) + options['endpoint'] = endpoint + methods = options.pop('methods', None) + + # if the methods are not given and the view_func object knows its + # methods we can use that instead. If neither exists, we go with + # a tuple of only `GET` as default. + if methods is None: + methods = getattr(view_func, 'methods', None) or ('GET',) + methods = set(methods) + + # Methods that should always be added + required_methods = set(getattr(view_func, 'required_methods', ())) + + # starting with Flask 0.8 the view_func object can disable and + # force-enable the automatic options handling. + provide_automatic_options = getattr(view_func, + 'provide_automatic_options', None) + + if provide_automatic_options is None: + if 'OPTIONS' not in methods: + provide_automatic_options = True + required_methods.add('OPTIONS') + else: + provide_automatic_options = False + + # Add the required methods now. + methods |= required_methods + + # due to a werkzeug bug we need to make sure that the defaults are + # None if they are an empty dictionary. This should not be necessary + # with Werkzeug 0.7 + options['defaults'] = options.get('defaults') or None + + rule = self.url_rule_class(rule, methods=methods, **options) + rule.provide_automatic_options = provide_automatic_options + + self.url_map.add(rule) + if view_func is not None: + old_func = self.view_functions.get(endpoint) + if old_func is not None and old_func != view_func: + raise AssertionError('View function mapping is overwriting an ' + 'existing endpoint function: %s' % endpoint) + self.view_functions[endpoint] = view_func + + def route(self, rule, **options): + """A decorator that is used to register a view function for a + given URL rule. This does the same thing as :meth:`add_url_rule` + but is intended for decorator usage:: + + @app.route('/') + def index(): + return 'Hello World' + + For more information refer to :ref:`url-route-registrations`. + + :param rule: the URL rule as string + :param endpoint: the endpoint for the registered URL rule. Flask + itself assumes the name of the view function as + endpoint + :param options: the options to be forwarded to the underlying + :class:`~werkzeug.routing.Rule` object. A change + to Werkzeug is handling of method options. methods + is a list of methods this rule should be limited + to (`GET`, `POST` etc.). By default a rule + just listens for `GET` (and implicitly `HEAD`). + Starting with Flask 0.6, `OPTIONS` is implicitly + added and handled by the standard request handling. + """ + def decorator(f): + endpoint = options.pop('endpoint', None) + self.add_url_rule(rule, endpoint, f, **options) + return f + return decorator + + @setupmethod + def endpoint(self, endpoint): + """A decorator to register a function as an endpoint. + Example:: + + @app.endpoint('example.endpoint') + def example(): + return "example" + + :param endpoint: the name of the endpoint + """ + def decorator(f): + self.view_functions[endpoint] = f + return f + return decorator + + @setupmethod + def errorhandler(self, code_or_exception): + """A decorator that is used to register a function give a given + error code. Example:: + + @app.errorhandler(404) + def page_not_found(error): + return 'This page does not exist', 404 + + You can also register handlers for arbitrary exceptions:: + + @app.errorhandler(DatabaseError) + def special_exception_handler(error): + return 'Database connection failed', 500 + + You can also register a function as error handler without using + the :meth:`errorhandler` decorator. The following example is + equivalent to the one above:: + + def page_not_found(error): + return 'This page does not exist', 404 + app.error_handler_spec[None][404] = page_not_found + + Setting error handlers via assignments to :attr:`error_handler_spec` + however is discouraged as it requires fiddling with nested dictionaries + and the special case for arbitrary exception types. + + The first `None` refers to the active blueprint. If the error + handler should be application wide `None` shall be used. + + .. versionadded:: 0.7 + One can now additionally also register custom exception types + that do not necessarily have to be a subclass of the + :class:`~werkzeug.exceptions.HTTPException` class. + + :param code: the code as integer for the handler + """ + def decorator(f): + self._register_error_handler(None, code_or_exception, f) + return f + return decorator + + def register_error_handler(self, code_or_exception, f): + """Alternative error attach function to the :meth:`errorhandler` + decorator that is more straightforward to use for non decorator + usage. + + .. versionadded:: 0.7 + """ + self._register_error_handler(None, code_or_exception, f) + + @setupmethod + def _register_error_handler(self, key, code_or_exception, f): + if isinstance(code_or_exception, HTTPException): + code_or_exception = code_or_exception.code + if isinstance(code_or_exception, integer_types): + assert code_or_exception != 500 or key is None, \ + 'It is currently not possible to register a 500 internal ' \ + 'server error on a per-blueprint level.' + self.error_handler_spec.setdefault(key, {})[code_or_exception] = f + else: + self.error_handler_spec.setdefault(key, {}).setdefault(None, []) \ + .append((code_or_exception, f)) + + @setupmethod + def template_filter(self, name=None): + """A decorator that is used to register custom template filter. + You can specify a name for the filter, otherwise the function + name will be used. Example:: + + @app.template_filter() + def reverse(s): + return s[::-1] + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + def decorator(f): + self.add_template_filter(f, name=name) + return f + return decorator + + @setupmethod + def add_template_filter(self, f, name=None): + """Register a custom template filter. Works exactly like the + :meth:`template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + self.jinja_env.filters[name or f.__name__] = f + + @setupmethod + def template_test(self, name=None): + """A decorator that is used to register custom template test. + You can specify a name for the test, otherwise the function + name will be used. Example:: + + @app.template_test() + def is_prime(n): + if n == 2: + return True + for i in range(2, int(math.ceil(math.sqrt(n))) + 1): + if n % i == 0: + return False + return True + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + def decorator(f): + self.add_template_test(f, name=name) + return f + return decorator + + @setupmethod + def add_template_test(self, f, name=None): + """Register a custom template test. Works exactly like the + :meth:`template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + self.jinja_env.tests[name or f.__name__] = f + + + @setupmethod + def template_global(self, name=None): + """A decorator that is used to register a custom template global function. + You can specify a name for the global function, otherwise the function + name will be used. Example:: + + @app.template_global() + def double(n): + return 2 * n + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + def decorator(f): + self.add_template_global(f, name=name) + return f + return decorator + + @setupmethod + def add_template_global(self, f, name=None): + """Register a custom template global function. Works exactly like the + :meth:`template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global function, otherwise the + function name will be used. + """ + self.jinja_env.globals[name or f.__name__] = f + + @setupmethod + def before_request(self, f): + """Registers a function to run before each request.""" + self.before_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def before_first_request(self, f): + """Registers a function to be run before the first request to this + instance of the application. + + .. versionadded:: 0.8 + """ + self.before_first_request_funcs.append(f) + + @setupmethod + def after_request(self, f): + """Register a function to be run after each request. Your function + must take one parameter, a :attr:`response_class` object and return + a new response object or the same (see :meth:`process_response`). + + As of Flask 0.7 this function might not be executed at the end of the + request in case an unhandled exception occurred. + """ + self.after_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_request(self, f): + """Register a function to be run at the end of each request, + regardless of whether there was an exception or not. These functions + are executed when the request context is popped, even if not an + actual request was performed. + + Example:: + + ctx = app.test_request_context() + ctx.push() + ... + ctx.pop() + + When ``ctx.pop()`` is executed in the above example, the teardown + functions are called just before the request context moves from the + stack of active contexts. This becomes relevant if you are using + such constructs in tests. + + Generally teardown functions must take every necessary step to avoid + that they will fail. If they do execute code that might fail they + will have to surround the execution of these code by try/except + statements and log occurring errors. + + When a teardown function was called because of a exception it will + be passed an error object. + + .. admonition:: Debug Note + + In debug mode Flask will not tear down a request on an exception + immediately. Instead if will keep it alive so that the interactive + debugger can still access it. This behavior can be controlled + by the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable. + """ + self.teardown_request_funcs.setdefault(None, []).append(f) + return f + + @setupmethod + def teardown_appcontext(self, f): + """Registers a function to be called when the application context + ends. These functions are typically also called when the request + context is popped. + + Example:: + + ctx = app.app_context() + ctx.push() + ... + ctx.pop() + + When ``ctx.pop()`` is executed in the above example, the teardown + functions are called just before the app context moves from the + stack of active contexts. This becomes relevant if you are using + such constructs in tests. + + Since a request context typically also manages an application + context it would also be called when you pop a request context. + + When a teardown function was called because of an exception it will + be passed an error object. + + .. versionadded:: 0.9 + """ + self.teardown_appcontext_funcs.append(f) + return f + + @setupmethod + def context_processor(self, f): + """Registers a template context processor function.""" + self.template_context_processors[None].append(f) + return f + + @setupmethod + def url_value_preprocessor(self, f): + """Registers a function as URL value preprocessor for all view + functions of the application. It's called before the view functions + are called and can modify the url values provided. + """ + self.url_value_preprocessors.setdefault(None, []).append(f) + return f + + @setupmethod + def url_defaults(self, f): + """Callback function for URL defaults for all view functions of the + application. It's called with the endpoint and values and should + update the values passed in place. + """ + self.url_default_functions.setdefault(None, []).append(f) + return f + + def handle_http_exception(self, e): + """Handles an HTTP exception. By default this will invoke the + registered error handlers and fall back to returning the + exception as response. + + .. versionadded:: 0.3 + """ + handlers = self.error_handler_spec.get(request.blueprint) + # Proxy exceptions don't have error codes. We want to always return + # those unchanged as errors + if e.code is None: + return e + if handlers and e.code in handlers: + handler = handlers[e.code] + else: + handler = self.error_handler_spec[None].get(e.code) + if handler is None: + return e + return handler(e) + + def trap_http_exception(self, e): + """Checks if an HTTP exception should be trapped or not. By default + this will return `False` for all exceptions except for a bad request + key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to `True`. It + also returns `True` if ``TRAP_HTTP_EXCEPTIONS`` is set to `True`. + + This is called for all HTTP exceptions raised by a view function. + If it returns `True` for any exception the error handler for this + exception is not called and it shows up as regular exception in the + traceback. This is helpful for debugging implicitly raised HTTP + exceptions. + + .. versionadded:: 0.8 + """ + if self.config['TRAP_HTTP_EXCEPTIONS']: + return True + if self.config['TRAP_BAD_REQUEST_ERRORS']: + return isinstance(e, BadRequest) + return False + + def handle_user_exception(self, e): + """This method is called whenever an exception occurs that should be + handled. A special case are + :class:`~werkzeug.exception.HTTPException`\s which are forwarded by + this function to the :meth:`handle_http_exception` method. This + function will either return a response value or reraise the + exception with the same traceback. + + .. versionadded:: 0.7 + """ + exc_type, exc_value, tb = sys.exc_info() + assert exc_value is e + + # ensure not to trash sys.exc_info() at that point in case someone + # wants the traceback preserved in handle_http_exception. Of course + # we cannot prevent users from trashing it themselves in a custom + # trap_http_exception method so that's their fault then. + if isinstance(e, HTTPException) and not self.trap_http_exception(e): + return self.handle_http_exception(e) + + blueprint_handlers = () + handlers = self.error_handler_spec.get(request.blueprint) + if handlers is not None: + blueprint_handlers = handlers.get(None, ()) + app_handlers = self.error_handler_spec[None].get(None, ()) + for typecheck, handler in chain(blueprint_handlers, app_handlers): + if isinstance(e, typecheck): + return handler(e) + + reraise(exc_type, exc_value, tb) + + def handle_exception(self, e): + """Default exception handling that kicks in when an exception + occurs that is not caught. In debug mode the exception will + be re-raised immediately, otherwise it is logged and the handler + for a 500 internal server error is used. If no such handler + exists, a default 500 internal server error message is displayed. + + .. versionadded:: 0.3 + """ + exc_type, exc_value, tb = sys.exc_info() + + got_request_exception.send(self, exception=e) + handler = self.error_handler_spec[None].get(500) + + if self.propagate_exceptions: + # if we want to repropagate the exception, we can attempt to + # raise it with the whole traceback in case we can do that + # (the function was actually called from the except part) + # otherwise, we just raise the error again + if exc_value is e: + reraise(exc_type, exc_value, tb) + else: + raise e + + self.log_exception((exc_type, exc_value, tb)) + if handler is None: + return InternalServerError() + return handler(e) + + def log_exception(self, exc_info): + """Logs an exception. This is called by :meth:`handle_exception` + if debugging is disabled and right before the handler is called. + The default implementation logs the exception as error on the + :attr:`logger`. + + .. versionadded:: 0.8 + """ + self.logger.error('Exception on %s [%s]' % ( + request.path, + request.method + ), exc_info=exc_info) + + def raise_routing_exception(self, request): + """Exceptions that are recording during routing are reraised with + this method. During debug we are not reraising redirect requests + for non ``GET``, ``HEAD``, or ``OPTIONS`` requests and we're raising + a different error instead to help debug situations. + + :internal: + """ + if not self.debug \ + or not isinstance(request.routing_exception, RequestRedirect) \ + or request.method in ('GET', 'HEAD', 'OPTIONS'): + raise request.routing_exception + + from .debughelpers import FormDataRoutingRedirect + raise FormDataRoutingRedirect(request) + + def dispatch_request(self): + """Does the request dispatching. Matches the URL and returns the + return value of the view or error handler. This does not have to + be a response object. In order to convert the return value to a + proper response object, call :func:`make_response`. + + .. versionchanged:: 0.7 + This no longer does the exception handling, this code was + moved to the new :meth:`full_dispatch_request`. + """ + req = _request_ctx_stack.top.request + if req.routing_exception is not None: + self.raise_routing_exception(req) + rule = req.url_rule + # if we provide automatic options for this URL and the + # request came with the OPTIONS method, reply automatically + if getattr(rule, 'provide_automatic_options', False) \ + and req.method == 'OPTIONS': + return self.make_default_options_response() + # otherwise dispatch to the handler for that endpoint + return self.view_functions[rule.endpoint](**req.view_args) + + def full_dispatch_request(self): + """Dispatches the request and on top of that performs request + pre and postprocessing as well as HTTP exception catching and + error handling. + + .. versionadded:: 0.7 + """ + self.try_trigger_before_first_request_functions() + try: + request_started.send(self) + rv = self.preprocess_request() + if rv is None: + rv = self.dispatch_request() + except Exception as e: + rv = self.handle_user_exception(e) + response = self.make_response(rv) + response = self.process_response(response) + request_finished.send(self, response=response) + return response + + def try_trigger_before_first_request_functions(self): + """Called before each request and will ensure that it triggers + the :attr:`before_first_request_funcs` and only exactly once per + application instance (which means process usually). + + :internal: + """ + if self._got_first_request: + return + with self._before_request_lock: + if self._got_first_request: + return + self._got_first_request = True + for func in self.before_first_request_funcs: + func() + + def make_default_options_response(self): + """This method is called to create the default `OPTIONS` response. + This can be changed through subclassing to change the default + behavior of `OPTIONS` responses. + + .. versionadded:: 0.7 + """ + adapter = _request_ctx_stack.top.url_adapter + if hasattr(adapter, 'allowed_methods'): + methods = adapter.allowed_methods() + else: + # fallback for Werkzeug < 0.7 + methods = [] + try: + adapter.match(method='--') + except MethodNotAllowed as e: + methods = e.valid_methods + except HTTPException as e: + pass + rv = self.response_class() + rv.allow.update(methods) + return rv + + def should_ignore_error(self, error): + """This is called to figure out if an error should be ignored + or not as far as the teardown system is concerned. If this + function returns `True` then the teardown handlers will not be + passed the error. + + .. versionadded:: 0.10 + """ + return False + + def make_response(self, rv): + """Converts the return value from a view function to a real + response object that is an instance of :attr:`response_class`. + + The following types are allowed for `rv`: + + .. tabularcolumns:: |p{3.5cm}|p{9.5cm}| + + ======================= =========================================== + :attr:`response_class` the object is returned unchanged + :class:`str` a response object is created with the + string as body + :class:`unicode` a response object is created with the + string encoded to utf-8 as body + a WSGI function the function is called as WSGI application + and buffered as response object + :class:`tuple` A tuple in the form ``(response, status, + headers)`` where `response` is any of the + types defined here, `status` is a string + or an integer and `headers` is a list of + a dictionary with header values. + ======================= =========================================== + + :param rv: the return value from the view function + + .. versionchanged:: 0.9 + Previously a tuple was interpreted as the arguments for the + response object. + """ + status = headers = None + if isinstance(rv, tuple): + rv, status, headers = rv + (None,) * (3 - len(rv)) + + if rv is None: + raise ValueError('View function did not return a response') + + if not isinstance(rv, self.response_class): + # When we create a response object directly, we let the constructor + # set the headers and status. We do this because there can be + # some extra logic involved when creating these objects with + # specific values (like default content type selection). + if isinstance(rv, (text_type, bytes, bytearray)): + rv = self.response_class(rv, headers=headers, status=status) + headers = status = None + else: + rv = self.response_class.force_type(rv, request.environ) + + if status is not None: + if isinstance(status, string_types): + rv.status = status + else: + rv.status_code = status + if headers: + rv.headers.extend(headers) + + return rv + + def create_url_adapter(self, request): + """Creates a URL adapter for the given request. The URL adapter + is created at a point where the request context is not yet set up + so the request is passed explicitly. + + .. versionadded:: 0.6 + + .. versionchanged:: 0.9 + This can now also be called without a request object when the + URL adapter is created for the application context. + """ + if request is not None: + return self.url_map.bind_to_environ(request.environ, + server_name=self.config['SERVER_NAME']) + # We need at the very least the server name to be set for this + # to work. + if self.config['SERVER_NAME'] is not None: + return self.url_map.bind( + self.config['SERVER_NAME'], + script_name=self.config['APPLICATION_ROOT'] or '/', + url_scheme=self.config['PREFERRED_URL_SCHEME']) + + def inject_url_defaults(self, endpoint, values): + """Injects the URL defaults for the given endpoint directly into + the values dictionary passed. This is used internally and + automatically called on URL building. + + .. versionadded:: 0.7 + """ + funcs = self.url_default_functions.get(None, ()) + if '.' in endpoint: + bp = endpoint.rsplit('.', 1)[0] + funcs = chain(funcs, self.url_default_functions.get(bp, ())) + for func in funcs: + func(endpoint, values) + + def handle_url_build_error(self, error, endpoint, values): + """Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`. + """ + exc_type, exc_value, tb = sys.exc_info() + for handler in self.url_build_error_handlers: + try: + rv = handler(error, endpoint, values) + if rv is not None: + return rv + except BuildError as error: + pass + + # At this point we want to reraise the exception. If the error is + # still the same one we can reraise it with the original traceback, + # otherwise we raise it from here. + if error is exc_value: + reraise(exc_type, exc_value, tb) + raise error + + def preprocess_request(self): + """Called before the actual request dispatching and will + call every as :meth:`before_request` decorated function. + If any of these function returns a value it's handled as + if it was the return value from the view and further + request handling is stopped. + + This also triggers the :meth:`url_value_processor` functions before + the actual :meth:`before_request` functions are called. + """ + bp = _request_ctx_stack.top.request.blueprint + + funcs = self.url_value_preprocessors.get(None, ()) + if bp is not None and bp in self.url_value_preprocessors: + funcs = chain(funcs, self.url_value_preprocessors[bp]) + for func in funcs: + func(request.endpoint, request.view_args) + + funcs = self.before_request_funcs.get(None, ()) + if bp is not None and bp in self.before_request_funcs: + funcs = chain(funcs, self.before_request_funcs[bp]) + for func in funcs: + rv = func() + if rv is not None: + return rv + + def process_response(self, response): + """Can be overridden in order to modify the response object + before it's sent to the WSGI server. By default this will + call all the :meth:`after_request` decorated functions. + + .. versionchanged:: 0.5 + As of Flask 0.5 the functions registered for after request + execution are called in reverse order of registration. + + :param response: a :attr:`response_class` object. + :return: a new response object or the same, has to be an + instance of :attr:`response_class`. + """ + ctx = _request_ctx_stack.top + bp = ctx.request.blueprint + funcs = ctx._after_request_functions + if bp is not None and bp in self.after_request_funcs: + funcs = chain(funcs, reversed(self.after_request_funcs[bp])) + if None in self.after_request_funcs: + funcs = chain(funcs, reversed(self.after_request_funcs[None])) + for handler in funcs: + response = handler(response) + if not self.session_interface.is_null_session(ctx.session): + self.save_session(ctx.session, response) + return response + + def do_teardown_request(self, exc=None): + """Called after the actual request dispatching and will + call every as :meth:`teardown_request` decorated function. This is + not actually called by the :class:`Flask` object itself but is always + triggered when the request context is popped. That way we have a + tighter control over certain resources under testing environments. + + .. versionchanged:: 0.9 + Added the `exc` argument. Previously this was always using the + current exception information. + """ + if exc is None: + exc = sys.exc_info()[1] + funcs = reversed(self.teardown_request_funcs.get(None, ())) + bp = _request_ctx_stack.top.request.blueprint + if bp is not None and bp in self.teardown_request_funcs: + funcs = chain(funcs, reversed(self.teardown_request_funcs[bp])) + for func in funcs: + rv = func(exc) + request_tearing_down.send(self, exc=exc) + + def do_teardown_appcontext(self, exc=None): + """Called when an application context is popped. This works pretty + much the same as :meth:`do_teardown_request` but for the application + context. + + .. versionadded:: 0.9 + """ + if exc is None: + exc = sys.exc_info()[1] + for func in reversed(self.teardown_appcontext_funcs): + func(exc) + appcontext_tearing_down.send(self, exc=exc) + + def app_context(self): + """Binds the application only. For as long as the application is bound + to the current context the :data:`flask.current_app` points to that + application. An application context is automatically created when a + request context is pushed if necessary. + + Example usage:: + + with app.app_context(): + ... + + .. versionadded:: 0.9 + """ + return AppContext(self) + + def request_context(self, environ): + """Creates a :class:`~flask.ctx.RequestContext` from the given + environment and binds it to the current context. This must be used in + combination with the `with` statement because the request is only bound + to the current context for the duration of the `with` block. + + Example usage:: + + with app.request_context(environ): + do_something_with(request) + + The object returned can also be used without the `with` statement + which is useful for working in the shell. The example above is + doing exactly the same as this code:: + + ctx = app.request_context(environ) + ctx.push() + try: + do_something_with(request) + finally: + ctx.pop() + + .. versionchanged:: 0.3 + Added support for non-with statement usage and `with` statement + is now passed the ctx object. + + :param environ: a WSGI environment + """ + return RequestContext(self, environ) + + def test_request_context(self, *args, **kwargs): + """Creates a WSGI environment from the given values (see + :func:`werkzeug.test.EnvironBuilder` for more information, this + function accepts the same arguments). + """ + from flask.testing import make_test_environ_builder + builder = make_test_environ_builder(self, *args, **kwargs) + try: + return self.request_context(builder.get_environ()) + finally: + builder.close() + + def wsgi_app(self, environ, start_response): + """The actual WSGI application. This is not implemented in + `__call__` so that middlewares can be applied without losing a + reference to the class. So instead of doing this:: + + app = MyMiddleware(app) + + It's a better idea to do this instead:: + + app.wsgi_app = MyMiddleware(app.wsgi_app) + + Then you still have the original application object around and + can continue to call methods on it. + + .. versionchanged:: 0.7 + The behavior of the before and after request callbacks was changed + under error conditions and a new callback was added that will + always execute at the end of the request, independent on if an + error occurred or not. See :ref:`callbacks-and-errors`. + + :param environ: a WSGI environment + :param start_response: a callable accepting a status code, + a list of headers and an optional + exception context to start the response + """ + ctx = self.request_context(environ) + ctx.push() + error = None + try: + try: + response = self.full_dispatch_request() + except Exception as e: + error = e + response = self.make_response(self.handle_exception(e)) + return response(environ, start_response) + finally: + if self.should_ignore_error(error): + error = None + ctx.auto_pop(error) + + @property + def modules(self): + from warnings import warn + warn(DeprecationWarning('Flask.modules is deprecated, use ' + 'Flask.blueprints instead'), stacklevel=2) + return self.blueprints + + def __call__(self, environ, start_response): + """Shortcut for :attr:`wsgi_app`.""" + return self.wsgi_app(environ, start_response) + + def __repr__(self): + return '<%s %r>' % ( + self.__class__.__name__, + self.name, + ) diff --git a/env/lib/python2.7/site-packages/flask/app.pyc b/env/lib/python2.7/site-packages/flask/app.pyc new file mode 100644 index 0000000..480c4ab Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/app.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/blueprints.py b/env/lib/python2.7/site-packages/flask/blueprints.py new file mode 100644 index 0000000..4575ec9 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/blueprints.py @@ -0,0 +1,401 @@ +# -*- coding: utf-8 -*- +""" + flask.blueprints + ~~~~~~~~~~~~~~~~ + + Blueprints are the recommended way to implement larger or more + pluggable applications in Flask 0.7 and later. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +from functools import update_wrapper + +from .helpers import _PackageBoundObject, _endpoint_from_view_func + + +class BlueprintSetupState(object): + """Temporary holder object for registering a blueprint with the + application. An instance of this class is created by the + :meth:`~flask.Blueprint.make_setup_state` method and later passed + to all register callback functions. + """ + + def __init__(self, blueprint, app, options, first_registration): + #: a reference to the current application + self.app = app + + #: a reference to the blueprint that created this setup state. + self.blueprint = blueprint + + #: a dictionary with all options that were passed to the + #: :meth:`~flask.Flask.register_blueprint` method. + self.options = options + + #: as blueprints can be registered multiple times with the + #: application and not everything wants to be registered + #: multiple times on it, this attribute can be used to figure + #: out if the blueprint was registered in the past already. + self.first_registration = first_registration + + subdomain = self.options.get('subdomain') + if subdomain is None: + subdomain = self.blueprint.subdomain + + #: The subdomain that the blueprint should be active for, `None` + #: otherwise. + self.subdomain = subdomain + + url_prefix = self.options.get('url_prefix') + if url_prefix is None: + url_prefix = self.blueprint.url_prefix + + #: The prefix that should be used for all URLs defined on the + #: blueprint. + self.url_prefix = url_prefix + + #: A dictionary with URL defaults that is added to each and every + #: URL that was defined with the blueprint. + self.url_defaults = dict(self.blueprint.url_values_defaults) + self.url_defaults.update(self.options.get('url_defaults', ())) + + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + """A helper method to register a rule (and optionally a view function) + to the application. The endpoint is automatically prefixed with the + blueprint's name. + """ + if self.url_prefix: + rule = self.url_prefix + rule + options.setdefault('subdomain', self.subdomain) + if endpoint is None: + endpoint = _endpoint_from_view_func(view_func) + defaults = self.url_defaults + if 'defaults' in options: + defaults = dict(defaults, **options.pop('defaults')) + self.app.add_url_rule(rule, '%s.%s' % (self.blueprint.name, endpoint), + view_func, defaults=defaults, **options) + + +class Blueprint(_PackageBoundObject): + """Represents a blueprint. A blueprint is an object that records + functions that will be called with the + :class:`~flask.blueprint.BlueprintSetupState` later to register functions + or other things on the main application. See :ref:`blueprints` for more + information. + + .. versionadded:: 0.7 + """ + + warn_on_modifications = False + _got_registered_once = False + + def __init__(self, name, import_name, static_folder=None, + static_url_path=None, template_folder=None, + url_prefix=None, subdomain=None, url_defaults=None): + _PackageBoundObject.__init__(self, import_name, template_folder) + self.name = name + self.url_prefix = url_prefix + self.subdomain = subdomain + self.static_folder = static_folder + self.static_url_path = static_url_path + self.deferred_functions = [] + self.view_functions = {} + if url_defaults is None: + url_defaults = {} + self.url_values_defaults = url_defaults + + def record(self, func): + """Registers a function that is called when the blueprint is + registered on the application. This function is called with the + state as argument as returned by the :meth:`make_setup_state` + method. + """ + if self._got_registered_once and self.warn_on_modifications: + from warnings import warn + warn(Warning('The blueprint was already registered once ' + 'but is getting modified now. These changes ' + 'will not show up.')) + self.deferred_functions.append(func) + + def record_once(self, func): + """Works like :meth:`record` but wraps the function in another + function that will ensure the function is only called once. If the + blueprint is registered a second time on the application, the + function passed is not called. + """ + def wrapper(state): + if state.first_registration: + func(state) + return self.record(update_wrapper(wrapper, func)) + + def make_setup_state(self, app, options, first_registration=False): + """Creates an instance of :meth:`~flask.blueprints.BlueprintSetupState` + object that is later passed to the register callback functions. + Subclasses can override this to return a subclass of the setup state. + """ + return BlueprintSetupState(self, app, options, first_registration) + + def register(self, app, options, first_registration=False): + """Called by :meth:`Flask.register_blueprint` to register a blueprint + on the application. This can be overridden to customize the register + behavior. Keyword arguments from + :func:`~flask.Flask.register_blueprint` are directly forwarded to this + method in the `options` dictionary. + """ + self._got_registered_once = True + state = self.make_setup_state(app, options, first_registration) + if self.has_static_folder: + state.add_url_rule(self.static_url_path + '/', + view_func=self.send_static_file, + endpoint='static') + + for deferred in self.deferred_functions: + deferred(state) + + def route(self, rule, **options): + """Like :meth:`Flask.route` but for a blueprint. The endpoint for the + :func:`url_for` function is prefixed with the name of the blueprint. + """ + def decorator(f): + endpoint = options.pop("endpoint", f.__name__) + self.add_url_rule(rule, endpoint, f, **options) + return f + return decorator + + def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + """Like :meth:`Flask.add_url_rule` but for a blueprint. The endpoint for + the :func:`url_for` function is prefixed with the name of the blueprint. + """ + if endpoint: + assert '.' not in endpoint, "Blueprint endpoint's should not contain dot's" + self.record(lambda s: + s.add_url_rule(rule, endpoint, view_func, **options)) + + def endpoint(self, endpoint): + """Like :meth:`Flask.endpoint` but for a blueprint. This does not + prefix the endpoint with the blueprint name, this has to be done + explicitly by the user of this method. If the endpoint is prefixed + with a `.` it will be registered to the current blueprint, otherwise + it's an application independent endpoint. + """ + def decorator(f): + def register_endpoint(state): + state.app.view_functions[endpoint] = f + self.record_once(register_endpoint) + return f + return decorator + + def app_template_filter(self, name=None): + """Register a custom template filter, available application wide. Like + :meth:`Flask.template_filter` but for a blueprint. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + def decorator(f): + self.add_app_template_filter(f, name=name) + return f + return decorator + + def add_app_template_filter(self, f, name=None): + """Register a custom template filter, available application wide. Like + :meth:`Flask.add_template_filter` but for a blueprint. Works exactly + like the :meth:`app_template_filter` decorator. + + :param name: the optional name of the filter, otherwise the + function name will be used. + """ + def register_template(state): + state.app.jinja_env.filters[name or f.__name__] = f + self.record_once(register_template) + + def app_template_test(self, name=None): + """Register a custom template test, available application wide. Like + :meth:`Flask.template_test` but for a blueprint. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + def decorator(f): + self.add_app_template_test(f, name=name) + return f + return decorator + + def add_app_template_test(self, f, name=None): + """Register a custom template test, available application wide. Like + :meth:`Flask.add_template_test` but for a blueprint. Works exactly + like the :meth:`app_template_test` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the test, otherwise the + function name will be used. + """ + def register_template(state): + state.app.jinja_env.tests[name or f.__name__] = f + self.record_once(register_template) + + def app_template_global(self, name=None): + """Register a custom template global, available application wide. Like + :meth:`Flask.template_global` but for a blueprint. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + def decorator(f): + self.add_app_template_global(f, name=name) + return f + return decorator + + def add_app_template_global(self, f, name=None): + """Register a custom template global, available application wide. Like + :meth:`Flask.add_template_global` but for a blueprint. Works exactly + like the :meth:`app_template_global` decorator. + + .. versionadded:: 0.10 + + :param name: the optional name of the global, otherwise the + function name will be used. + """ + def register_template(state): + state.app.jinja_env.globals[name or f.__name__] = f + self.record_once(register_template) + + def before_request(self, f): + """Like :meth:`Flask.before_request` but for a blueprint. This function + is only executed before each request that is handled by a function of + that blueprint. + """ + self.record_once(lambda s: s.app.before_request_funcs + .setdefault(self.name, []).append(f)) + return f + + def before_app_request(self, f): + """Like :meth:`Flask.before_request`. Such a function is executed + before each request, even if outside of a blueprint. + """ + self.record_once(lambda s: s.app.before_request_funcs + .setdefault(None, []).append(f)) + return f + + def before_app_first_request(self, f): + """Like :meth:`Flask.before_first_request`. Such a function is + executed before the first request to the application. + """ + self.record_once(lambda s: s.app.before_first_request_funcs.append(f)) + return f + + def after_request(self, f): + """Like :meth:`Flask.after_request` but for a blueprint. This function + is only executed after each request that is handled by a function of + that blueprint. + """ + self.record_once(lambda s: s.app.after_request_funcs + .setdefault(self.name, []).append(f)) + return f + + def after_app_request(self, f): + """Like :meth:`Flask.after_request` but for a blueprint. Such a function + is executed after each request, even if outside of the blueprint. + """ + self.record_once(lambda s: s.app.after_request_funcs + .setdefault(None, []).append(f)) + return f + + def teardown_request(self, f): + """Like :meth:`Flask.teardown_request` but for a blueprint. This + function is only executed when tearing down requests handled by a + function of that blueprint. Teardown request functions are executed + when the request context is popped, even when no actual request was + performed. + """ + self.record_once(lambda s: s.app.teardown_request_funcs + .setdefault(self.name, []).append(f)) + return f + + def teardown_app_request(self, f): + """Like :meth:`Flask.teardown_request` but for a blueprint. Such a + function is executed when tearing down each request, even if outside of + the blueprint. + """ + self.record_once(lambda s: s.app.teardown_request_funcs + .setdefault(None, []).append(f)) + return f + + def context_processor(self, f): + """Like :meth:`Flask.context_processor` but for a blueprint. This + function is only executed for requests handled by a blueprint. + """ + self.record_once(lambda s: s.app.template_context_processors + .setdefault(self.name, []).append(f)) + return f + + def app_context_processor(self, f): + """Like :meth:`Flask.context_processor` but for a blueprint. Such a + function is executed each request, even if outside of the blueprint. + """ + self.record_once(lambda s: s.app.template_context_processors + .setdefault(None, []).append(f)) + return f + + def app_errorhandler(self, code): + """Like :meth:`Flask.errorhandler` but for a blueprint. This + handler is used for all requests, even if outside of the blueprint. + """ + def decorator(f): + self.record_once(lambda s: s.app.errorhandler(code)(f)) + return f + return decorator + + def url_value_preprocessor(self, f): + """Registers a function as URL value preprocessor for this + blueprint. It's called before the view functions are called and + can modify the url values provided. + """ + self.record_once(lambda s: s.app.url_value_preprocessors + .setdefault(self.name, []).append(f)) + return f + + def url_defaults(self, f): + """Callback function for URL defaults for this blueprint. It's called + with the endpoint and values and should update the values passed + in place. + """ + self.record_once(lambda s: s.app.url_default_functions + .setdefault(self.name, []).append(f)) + return f + + def app_url_value_preprocessor(self, f): + """Same as :meth:`url_value_preprocessor` but application wide. + """ + self.record_once(lambda s: s.app.url_value_preprocessors + .setdefault(None, []).append(f)) + return f + + def app_url_defaults(self, f): + """Same as :meth:`url_defaults` but application wide. + """ + self.record_once(lambda s: s.app.url_default_functions + .setdefault(None, []).append(f)) + return f + + def errorhandler(self, code_or_exception): + """Registers an error handler that becomes active for this blueprint + only. Please be aware that routing does not happen local to a + blueprint so an error handler for 404 usually is not handled by + a blueprint unless it is caused inside a view function. Another + special case is the 500 internal server error which is always looked + up from the application. + + Otherwise works as the :meth:`~flask.Flask.errorhandler` decorator + of the :class:`~flask.Flask` object. + """ + def decorator(f): + self.record_once(lambda s: s.app._register_error_handler( + self.name, code_or_exception, f)) + return f + return decorator diff --git a/env/lib/python2.7/site-packages/flask/blueprints.pyc b/env/lib/python2.7/site-packages/flask/blueprints.pyc new file mode 100644 index 0000000..42d5ca0 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/blueprints.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/config.py b/env/lib/python2.7/site-packages/flask/config.py new file mode 100644 index 0000000..155afa2 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/config.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +""" + flask.config + ~~~~~~~~~~~~ + + Implements the configuration related objects. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import imp +import os +import errno + +from werkzeug.utils import import_string +from ._compat import string_types + + +class ConfigAttribute(object): + """Makes an attribute forward to the config""" + + def __init__(self, name, get_converter=None): + self.__name__ = name + self.get_converter = get_converter + + def __get__(self, obj, type=None): + if obj is None: + return self + rv = obj.config[self.__name__] + if self.get_converter is not None: + rv = self.get_converter(rv) + return rv + + def __set__(self, obj, value): + obj.config[self.__name__] = value + + +class Config(dict): + """Works exactly like a dict but provides ways to fill it from files + or special dictionaries. There are two common patterns to populate the + config. + + Either you can fill the config from a config file:: + + app.config.from_pyfile('yourconfig.cfg') + + Or alternatively you can define the configuration options in the + module that calls :meth:`from_object` or provide an import path to + a module that should be loaded. It is also possible to tell it to + use the same module and with that provide the configuration values + just before the call:: + + DEBUG = True + SECRET_KEY = 'development key' + app.config.from_object(__name__) + + In both cases (loading from any Python file or loading from modules), + only uppercase keys are added to the config. This makes it possible to use + lowercase values in the config file for temporary values that are not added + to the config or to define the config keys in the same file that implements + the application. + + Probably the most interesting way to load configurations is from an + environment variable pointing to a file:: + + app.config.from_envvar('YOURAPPLICATION_SETTINGS') + + In this case before launching the application you have to set this + environment variable to the file you want to use. On Linux and OS X + use the export statement:: + + export YOURAPPLICATION_SETTINGS='/path/to/config/file' + + On windows use `set` instead. + + :param root_path: path to which files are read relative from. When the + config object is created by the application, this is + the application's :attr:`~flask.Flask.root_path`. + :param defaults: an optional dictionary of default values + """ + + def __init__(self, root_path, defaults=None): + dict.__init__(self, defaults or {}) + self.root_path = root_path + + def from_envvar(self, variable_name, silent=False): + """Loads a configuration from an environment variable pointing to + a configuration file. This is basically just a shortcut with nicer + error messages for this line of code:: + + app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS']) + + :param variable_name: name of the environment variable + :param silent: set to `True` if you want silent failure for missing + files. + :return: bool. `True` if able to load config, `False` otherwise. + """ + rv = os.environ.get(variable_name) + if not rv: + if silent: + return False + raise RuntimeError('The environment variable %r is not set ' + 'and as such configuration could not be ' + 'loaded. Set this variable and make it ' + 'point to a configuration file' % + variable_name) + return self.from_pyfile(rv, silent=silent) + + def from_pyfile(self, filename, silent=False): + """Updates the values in the config from a Python file. This function + behaves as if the file was imported as module with the + :meth:`from_object` function. + + :param filename: the filename of the config. This can either be an + absolute filename or a filename relative to the + root path. + :param silent: set to `True` if you want silent failure for missing + files. + + .. versionadded:: 0.7 + `silent` parameter. + """ + filename = os.path.join(self.root_path, filename) + d = imp.new_module('config') + d.__file__ = filename + try: + with open(filename) as config_file: + exec(compile(config_file.read(), filename, 'exec'), d.__dict__) + except IOError as e: + if silent and e.errno in (errno.ENOENT, errno.EISDIR): + return False + e.strerror = 'Unable to load configuration file (%s)' % e.strerror + raise + self.from_object(d) + return True + + def from_object(self, obj): + """Updates the values from the given object. An object can be of one + of the following two types: + + - a string: in this case the object with that name will be imported + - an actual object reference: that object is used directly + + Objects are usually either modules or classes. + + Just the uppercase variables in that object are stored in the config. + Example usage:: + + app.config.from_object('yourapplication.default_config') + from yourapplication import default_config + app.config.from_object(default_config) + + You should not use this function to load the actual configuration but + rather configuration defaults. The actual config should be loaded + with :meth:`from_pyfile` and ideally from a location not within the + package because the package might be installed system wide. + + :param obj: an import name or object + """ + if isinstance(obj, string_types): + obj = import_string(obj) + for key in dir(obj): + if key.isupper(): + self[key] = getattr(obj, key) + + def __repr__(self): + return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self)) diff --git a/env/lib/python2.7/site-packages/flask/config.pyc b/env/lib/python2.7/site-packages/flask/config.pyc new file mode 100644 index 0000000..286a94f Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/config.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/ctx.py b/env/lib/python2.7/site-packages/flask/ctx.py new file mode 100644 index 0000000..f134237 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/ctx.py @@ -0,0 +1,394 @@ +# -*- coding: utf-8 -*- +""" + flask.ctx + ~~~~~~~~~ + + Implements the objects required to keep the context. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +from __future__ import with_statement + +import sys +from functools import update_wrapper + +from werkzeug.exceptions import HTTPException + +from .globals import _request_ctx_stack, _app_ctx_stack +from .module import blueprint_is_module +from .signals import appcontext_pushed, appcontext_popped + + +class _AppCtxGlobals(object): + """A plain object.""" + + def get(self, name, default=None): + return self.__dict__.get(name, default) + + def __contains__(self, item): + return item in self.__dict__ + + def __iter__(self): + return iter(self.__dict__) + + def __repr__(self): + top = _app_ctx_stack.top + if top is not None: + return '' % top.app.name + return object.__repr__(self) + + +def after_this_request(f): + """Executes a function after this request. This is useful to modify + response objects. The function is passed the response object and has + to return the same or a new one. + + Example:: + + @app.route('/') + def index(): + @after_this_request + def add_header(response): + response.headers['X-Foo'] = 'Parachute' + return response + return 'Hello World!' + + This is more useful if a function other than the view function wants to + modify a response. For instance think of a decorator that wants to add + some headers without converting the return value into a response object. + + .. versionadded:: 0.9 + """ + _request_ctx_stack.top._after_request_functions.append(f) + return f + + +def copy_current_request_context(f): + """A helper function that decorates a function to retain the current + request context. This is useful when working with greenlets. The moment + the function is decorated a copy of the request context is created and + then pushed when the function is called. + + Example:: + + import gevent + from flask import copy_current_request_context + + @app.route('/') + def index(): + @copy_current_request_context + def do_some_work(): + # do some work here, it can access flask.request like you + # would otherwise in the view function. + ... + gevent.spawn(do_some_work) + return 'Regular response' + + .. versionadded:: 0.10 + """ + top = _request_ctx_stack.top + if top is None: + raise RuntimeError('This decorator can only be used at local scopes ' + 'when a request context is on the stack. For instance within ' + 'view functions.') + reqctx = top.copy() + def wrapper(*args, **kwargs): + with reqctx: + return f(*args, **kwargs) + return update_wrapper(wrapper, f) + + +def has_request_context(): + """If you have code that wants to test if a request context is there or + not this function can be used. For instance, you may want to take advantage + of request information if the request object is available, but fail + silently if it is unavailable. + + :: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and has_request_context(): + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + Alternatively you can also just test any of the context bound objects + (such as :class:`request` or :class:`g` for truthness):: + + class User(db.Model): + + def __init__(self, username, remote_addr=None): + self.username = username + if remote_addr is None and request: + remote_addr = request.remote_addr + self.remote_addr = remote_addr + + .. versionadded:: 0.7 + """ + return _request_ctx_stack.top is not None + + +def has_app_context(): + """Works like :func:`has_request_context` but for the application + context. You can also just do a boolean check on the + :data:`current_app` object instead. + + .. versionadded:: 0.9 + """ + return _app_ctx_stack.top is not None + + +class AppContext(object): + """The application context binds an application object implicitly + to the current thread or greenlet, similar to how the + :class:`RequestContext` binds request information. The application + context is also implicitly created if a request context is created + but the application is not on top of the individual application + context. + """ + + def __init__(self, app): + self.app = app + self.url_adapter = app.create_url_adapter(None) + self.g = app.app_ctx_globals_class() + + # Like request context, app contexts can be pushed multiple times + # but there a basic "refcount" is enough to track them. + self._refcnt = 0 + + def push(self): + """Binds the app context to the current context.""" + self._refcnt += 1 + _app_ctx_stack.push(self) + appcontext_pushed.send(self.app) + + def pop(self, exc=None): + """Pops the app context.""" + self._refcnt -= 1 + if self._refcnt <= 0: + if exc is None: + exc = sys.exc_info()[1] + self.app.do_teardown_appcontext(exc) + rv = _app_ctx_stack.pop() + assert rv is self, 'Popped wrong app context. (%r instead of %r)' \ + % (rv, self) + appcontext_popped.send(self.app) + + def __enter__(self): + self.push() + return self + + def __exit__(self, exc_type, exc_value, tb): + self.pop(exc_value) + + +class RequestContext(object): + """The request context contains all request relevant information. It is + created at the beginning of the request and pushed to the + `_request_ctx_stack` and removed at the end of it. It will create the + URL adapter and request object for the WSGI environment provided. + + Do not attempt to use this class directly, instead use + :meth:`~flask.Flask.test_request_context` and + :meth:`~flask.Flask.request_context` to create this object. + + When the request context is popped, it will evaluate all the + functions registered on the application for teardown execution + (:meth:`~flask.Flask.teardown_request`). + + The request context is automatically popped at the end of the request + for you. In debug mode the request context is kept around if + exceptions happen so that interactive debuggers have a chance to + introspect the data. With 0.4 this can also be forced for requests + that did not fail and outside of `DEBUG` mode. By setting + ``'flask._preserve_context'`` to `True` on the WSGI environment the + context will not pop itself at the end of the request. This is used by + the :meth:`~flask.Flask.test_client` for example to implement the + deferred cleanup functionality. + + You might find this helpful for unittests where you need the + information from the context local around for a little longer. Make + sure to properly :meth:`~werkzeug.LocalStack.pop` the stack yourself in + that situation, otherwise your unittests will leak memory. + """ + + def __init__(self, app, environ, request=None): + self.app = app + if request is None: + request = app.request_class(environ) + self.request = request + self.url_adapter = app.create_url_adapter(self.request) + self.flashes = None + self.session = None + + # Request contexts can be pushed multiple times and interleaved with + # other request contexts. Now only if the last level is popped we + # get rid of them. Additionally if an application context is missing + # one is created implicitly so for each level we add this information + self._implicit_app_ctx_stack = [] + + # indicator if the context was preserved. Next time another context + # is pushed the preserved context is popped. + self.preserved = False + + # remembers the exception for pop if there is one in case the context + # preservation kicks in. + self._preserved_exc = None + + # Functions that should be executed after the request on the response + # object. These will be called before the regular "after_request" + # functions. + self._after_request_functions = [] + + self.match_request() + + # XXX: Support for deprecated functionality. This is going away with + # Flask 1.0 + blueprint = self.request.blueprint + if blueprint is not None: + # better safe than sorry, we don't want to break code that + # already worked + bp = app.blueprints.get(blueprint) + if bp is not None and blueprint_is_module(bp): + self.request._is_old_module = True + + def _get_g(self): + return _app_ctx_stack.top.g + def _set_g(self, value): + _app_ctx_stack.top.g = value + g = property(_get_g, _set_g) + del _get_g, _set_g + + def copy(self): + """Creates a copy of this request context with the same request object. + This can be used to move a request context to a different greenlet. + Because the actual request object is the same this cannot be used to + move a request context to a different thread unless access to the + request object is locked. + + .. versionadded:: 0.10 + """ + return self.__class__(self.app, + environ=self.request.environ, + request=self.request + ) + + def match_request(self): + """Can be overridden by a subclass to hook into the matching + of the request. + """ + try: + url_rule, self.request.view_args = \ + self.url_adapter.match(return_rule=True) + self.request.url_rule = url_rule + except HTTPException as e: + self.request.routing_exception = e + + def push(self): + """Binds the request context to the current context.""" + # If an exception occurs in debug mode or if context preservation is + # activated under exception situations exactly one context stays + # on the stack. The rationale is that you want to access that + # information under debug situations. However if someone forgets to + # pop that context again we want to make sure that on the next push + # it's invalidated, otherwise we run at risk that something leaks + # memory. This is usually only a problem in testsuite since this + # functionality is not active in production environments. + top = _request_ctx_stack.top + if top is not None and top.preserved: + top.pop(top._preserved_exc) + + # Before we push the request context we have to ensure that there + # is an application context. + app_ctx = _app_ctx_stack.top + if app_ctx is None or app_ctx.app != self.app: + app_ctx = self.app.app_context() + app_ctx.push() + self._implicit_app_ctx_stack.append(app_ctx) + else: + self._implicit_app_ctx_stack.append(None) + + _request_ctx_stack.push(self) + + # Open the session at the moment that the request context is + # available. This allows a custom open_session method to use the + # request context (e.g. code that access database information + # stored on `g` instead of the appcontext). + self.session = self.app.open_session(self.request) + if self.session is None: + self.session = self.app.make_null_session() + + def pop(self, exc=None): + """Pops the request context and unbinds it by doing that. This will + also trigger the execution of functions registered by the + :meth:`~flask.Flask.teardown_request` decorator. + + .. versionchanged:: 0.9 + Added the `exc` argument. + """ + app_ctx = self._implicit_app_ctx_stack.pop() + + clear_request = False + if not self._implicit_app_ctx_stack: + self.preserved = False + self._preserved_exc = None + if exc is None: + exc = sys.exc_info()[1] + self.app.do_teardown_request(exc) + + # If this interpreter supports clearing the exception information + # we do that now. This will only go into effect on Python 2.x, + # on 3.x it disappears automatically at the end of the exception + # stack. + if hasattr(sys, 'exc_clear'): + sys.exc_clear() + + request_close = getattr(self.request, 'close', None) + if request_close is not None: + request_close() + clear_request = True + + rv = _request_ctx_stack.pop() + assert rv is self, 'Popped wrong request context. (%r instead of %r)' \ + % (rv, self) + + # get rid of circular dependencies at the end of the request + # so that we don't require the GC to be active. + if clear_request: + rv.request.environ['werkzeug.request'] = None + + # Get rid of the app as well if necessary. + if app_ctx is not None: + app_ctx.pop(exc) + + def auto_pop(self, exc): + if self.request.environ.get('flask._preserve_context') or \ + (exc is not None and self.app.preserve_context_on_exception): + self.preserved = True + self._preserved_exc = exc + else: + self.pop(exc) + + def __enter__(self): + self.push() + return self + + def __exit__(self, exc_type, exc_value, tb): + # do not pop the request stack if we are in debug mode and an + # exception happened. This will allow the debugger to still + # access the request object in the interactive shell. Furthermore + # the context can be force kept alive for the test client. + # See flask.testing for how this works. + self.auto_pop(exc_value) + + def __repr__(self): + return '<%s \'%s\' [%s] of %s>' % ( + self.__class__.__name__, + self.request.url, + self.request.method, + self.app.name, + ) diff --git a/env/lib/python2.7/site-packages/flask/ctx.pyc b/env/lib/python2.7/site-packages/flask/ctx.pyc new file mode 100644 index 0000000..b3b9def Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/ctx.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/debughelpers.py b/env/lib/python2.7/site-packages/flask/debughelpers.py new file mode 100644 index 0000000..2f8510f --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/debughelpers.py @@ -0,0 +1,87 @@ +# -*- coding: utf-8 -*- +""" + flask.debughelpers + ~~~~~~~~~~~~~~~~~~ + + Various helpers to make the development experience better. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +from ._compat import implements_to_string + + +class UnexpectedUnicodeError(AssertionError, UnicodeError): + """Raised in places where we want some better error reporting for + unexpected unicode or binary data. + """ + + +@implements_to_string +class DebugFilesKeyError(KeyError, AssertionError): + """Raised from request.files during debugging. The idea is that it can + provide a better error message than just a generic KeyError/BadRequest. + """ + + def __init__(self, request, key): + form_matches = request.form.getlist(key) + buf = ['You tried to access the file "%s" in the request.files ' + 'dictionary but it does not exist. The mimetype for the request ' + 'is "%s" instead of "multipart/form-data" which means that no ' + 'file contents were transmitted. To fix this error you should ' + 'provide enctype="multipart/form-data" in your form.' % + (key, request.mimetype)] + if form_matches: + buf.append('\n\nThe browser instead transmitted some file names. ' + 'This was submitted: %s' % ', '.join('"%s"' % x + for x in form_matches)) + self.msg = ''.join(buf) + + def __str__(self): + return self.msg + + +class FormDataRoutingRedirect(AssertionError): + """This exception is raised by Flask in debug mode if it detects a + redirect caused by the routing system when the request method is not + GET, HEAD or OPTIONS. Reasoning: form data will be dropped. + """ + + def __init__(self, request): + exc = request.routing_exception + buf = ['A request was sent to this URL (%s) but a redirect was ' + 'issued automatically by the routing system to "%s".' + % (request.url, exc.new_url)] + + # In case just a slash was appended we can be extra helpful + if request.base_url + '/' == exc.new_url.split('?')[0]: + buf.append(' The URL was defined with a trailing slash so ' + 'Flask will automatically redirect to the URL ' + 'with the trailing slash if it was accessed ' + 'without one.') + + buf.append(' Make sure to directly send your %s-request to this URL ' + 'since we can\'t make browsers or HTTP clients redirect ' + 'with form data reliably or without user interaction.' % + request.method) + buf.append('\n\nNote: this exception is only raised in debug mode') + AssertionError.__init__(self, ''.join(buf).encode('utf-8')) + + +def attach_enctype_error_multidict(request): + """Since Flask 0.8 we're monkeypatching the files object in case a + request is detected that does not use multipart form data but the files + object is accessed. + """ + oldcls = request.files.__class__ + class newcls(oldcls): + def __getitem__(self, key): + try: + return oldcls.__getitem__(self, key) + except KeyError as e: + if key not in request.form: + raise + raise DebugFilesKeyError(request, key) + newcls.__name__ = oldcls.__name__ + newcls.__module__ = oldcls.__module__ + request.files.__class__ = newcls diff --git a/env/lib/python2.7/site-packages/flask/debughelpers.pyc b/env/lib/python2.7/site-packages/flask/debughelpers.pyc new file mode 100644 index 0000000..fdcd565 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/debughelpers.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/ext/__init__.py b/env/lib/python2.7/site-packages/flask/ext/__init__.py new file mode 100644 index 0000000..f29958a --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/ext/__init__.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +""" + flask.ext + ~~~~~~~~~ + + Redirect imports for extensions. This module basically makes it possible + for us to transition from flaskext.foo to flask_foo without having to + force all extensions to upgrade at the same time. + + When a user does ``from flask.ext.foo import bar`` it will attempt to + import ``from flask_foo import bar`` first and when that fails it will + try to import ``from flaskext.foo import bar``. + + We're switching from namespace packages because it was just too painful for + everybody involved. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + + +def setup(): + from ..exthook import ExtensionImporter + importer = ExtensionImporter(['flask_%s', 'flaskext.%s'], __name__) + importer.install() + + +setup() +del setup diff --git a/env/lib/python2.7/site-packages/flask/ext/__init__.pyc b/env/lib/python2.7/site-packages/flask/ext/__init__.pyc new file mode 100644 index 0000000..8e23a71 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/ext/__init__.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/exthook.py b/env/lib/python2.7/site-packages/flask/exthook.py new file mode 100644 index 0000000..d0d814c --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/exthook.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +""" + flask.exthook + ~~~~~~~~~~~~~ + + Redirect imports for extensions. This module basically makes it possible + for us to transition from flaskext.foo to flask_foo without having to + force all extensions to upgrade at the same time. + + When a user does ``from flask.ext.foo import bar`` it will attempt to + import ``from flask_foo import bar`` first and when that fails it will + try to import ``from flaskext.foo import bar``. + + We're switching from namespace packages because it was just too painful for + everybody involved. + + This is used by `flask.ext`. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import sys +import os +from ._compat import reraise + + +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 + # very 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): + reraise(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 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 diff --git a/env/lib/python2.7/site-packages/flask/exthook.pyc b/env/lib/python2.7/site-packages/flask/exthook.pyc new file mode 100644 index 0000000..5d060bd Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/exthook.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/globals.py b/env/lib/python2.7/site-packages/flask/globals.py new file mode 100644 index 0000000..67d41f5 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/globals.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +""" + flask.globals + ~~~~~~~~~~~~~ + + Defines all the global objects that are proxies to the current + active context. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +from functools import partial +from werkzeug.local import LocalStack, LocalProxy + + +def _lookup_req_object(name): + top = _request_ctx_stack.top + if top is None: + raise RuntimeError('working outside of request context') + return getattr(top, name) + + +def _lookup_app_object(name): + top = _app_ctx_stack.top + if top is None: + raise RuntimeError('working outside of application context') + return getattr(top, name) + + +def _find_app(): + top = _app_ctx_stack.top + if top is None: + raise RuntimeError('working outside of application context') + return top.app + + +# context locals +_request_ctx_stack = LocalStack() +_app_ctx_stack = LocalStack() +current_app = LocalProxy(_find_app) +request = LocalProxy(partial(_lookup_req_object, 'request')) +session = LocalProxy(partial(_lookup_req_object, 'session')) +g = LocalProxy(partial(_lookup_app_object, 'g')) diff --git a/env/lib/python2.7/site-packages/flask/globals.pyc b/env/lib/python2.7/site-packages/flask/globals.pyc new file mode 100644 index 0000000..93c6910 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/globals.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/helpers.py b/env/lib/python2.7/site-packages/flask/helpers.py new file mode 100644 index 0000000..1e7c87f --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/helpers.py @@ -0,0 +1,849 @@ +# -*- coding: utf-8 -*- +""" + flask.helpers + ~~~~~~~~~~~~~ + + Implements various helpers. + + :copyright: (c) 2011 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +import os +import sys +import pkgutil +import posixpath +import mimetypes +from time import time +from zlib import adler32 +from threading import RLock +from werkzeug.routing import BuildError +from functools import update_wrapper + +try: + from werkzeug.urls import url_quote +except ImportError: + from urlparse import quote as url_quote + +from werkzeug.datastructures import Headers +from werkzeug.exceptions import NotFound + +# this was moved in 0.7 +try: + from werkzeug.wsgi import wrap_file +except ImportError: + from werkzeug.utils import wrap_file + +from jinja2 import FileSystemLoader + +from .signals import message_flashed +from .globals import session, _request_ctx_stack, _app_ctx_stack, \ + current_app, request +from ._compat import string_types, text_type + + +# sentinel +_missing = object() + + +# what separators does this operating system provide that are not a slash? +# this is used by the send_from_directory function to ensure that nobody is +# able to access files from outside the filesystem. +_os_alt_seps = list(sep for sep in [os.path.sep, os.path.altsep] + if sep not in (None, '/')) + + +def _endpoint_from_view_func(view_func): + """Internal helper that returns the default endpoint for a given + function. This always is the function name. + """ + assert view_func is not None, 'expected view func if endpoint ' \ + 'is not provided.' + return view_func.__name__ + + +def stream_with_context(generator_or_function): + """Request contexts disappear when the response is started on the server. + This is done for efficiency reasons and to make it less likely to encounter + memory leaks with badly written WSGI middlewares. The downside is that if + you are using streamed responses, the generator cannot access request bound + information any more. + + This function however can help you keep the context around for longer:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + @stream_with_context + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(generate()) + + Alternatively it can also be used around a specific generator:: + + from flask import stream_with_context, request, Response + + @app.route('/stream') + def streamed_response(): + def generate(): + yield 'Hello ' + yield request.args['name'] + yield '!' + return Response(stream_with_context(generate())) + + .. versionadded:: 0.9 + """ + try: + gen = iter(generator_or_function) + except TypeError: + def decorator(*args, **kwargs): + gen = generator_or_function() + return stream_with_context(gen) + return update_wrapper(decorator, generator_or_function) + + def generator(): + ctx = _request_ctx_stack.top + if ctx is None: + raise RuntimeError('Attempted to stream with context but ' + 'there was no context in the first place to keep around.') + with ctx: + # Dummy sentinel. Has to be inside the context block or we're + # not actually keeping the context around. + yield None + + # The try/finally is here so that if someone passes a WSGI level + # iterator in we're still running the cleanup logic. Generators + # don't need that because they are closed on their destruction + # automatically. + try: + for item in gen: + yield item + finally: + if hasattr(gen, 'close'): + gen.close() + + # The trick is to start the generator. Then the code execution runs until + # the first dummy None is yielded at which point the context was already + # pushed. This item is discarded. Then when the iteration continues the + # real generator is executed. + wrapped_g = generator() + next(wrapped_g) + return wrapped_g + + +def make_response(*args): + """Sometimes it is necessary to set additional headers in a view. Because + views do not have to return response objects but can return a value that + is converted into a response object by Flask itself, it becomes tricky to + add headers to it. This function can be called instead of using a return + and you will get a response object which you can use to attach headers. + + If view looked like this and you want to add a new header:: + + def index(): + return render_template('index.html', foo=42) + + You can now do something like this:: + + def index(): + response = make_response(render_template('index.html', foo=42)) + response.headers['X-Parachutes'] = 'parachutes are cool' + return response + + This function accepts the very same arguments you can return from a + view function. This for example creates a response with a 404 error + code:: + + response = make_response(render_template('not_found.html'), 404) + + The other use case of this function is to force the return value of a + view function into a response which is helpful with view + decorators:: + + response = make_response(view_function()) + response.headers['X-Parachutes'] = 'parachutes are cool' + + Internally this function does the following things: + + - if no arguments are passed, it creates a new response argument + - if one argument is passed, :meth:`flask.Flask.make_response` + is invoked with it. + - if more than one argument is passed, the arguments are passed + to the :meth:`flask.Flask.make_response` function as tuple. + + .. versionadded:: 0.6 + """ + if not args: + return current_app.response_class() + if len(args) == 1: + args = args[0] + return current_app.make_response(args) + + +def url_for(endpoint, **values): + """Generates a URL to the given endpoint with the method provided. + + Variable arguments that are unknown to the target endpoint are appended + to the generated URL as query arguments. If the value of a query argument + is `None`, the whole pair is skipped. In case blueprints are active + you can shortcut references to the same blueprint by prefixing the + local endpoint with a dot (``.``). + + This will reference the index function local to the current blueprint:: + + url_for('.index') + + For more information, head over to the :ref:`Quickstart `. + + To integrate applications, :class:`Flask` has a hook to intercept URL build + errors through :attr:`Flask.build_error_handler`. The `url_for` function + results in a :exc:`~werkzeug.routing.BuildError` when the current app does + not have a URL for the given endpoint and values. When it does, the + :data:`~flask.current_app` calls its :attr:`~Flask.build_error_handler` if + it is not `None`, which can return a string to use as the result of + `url_for` (instead of `url_for`'s default to raise the + :exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception. + An example:: + + def external_url_handler(error, endpoint, **values): + "Looks up an external URL when `url_for` cannot build a URL." + # This is an example of hooking the build_error_handler. + # Here, lookup_url is some utility function you've built + # which looks up the endpoint in some external URL registry. + url = lookup_url(endpoint, **values) + if url is None: + # External lookup did not have a URL. + # Re-raise the BuildError, in context of original traceback. + exc_type, exc_value, tb = sys.exc_info() + if exc_value is error: + raise exc_type, exc_value, tb + else: + raise error + # url_for will use this result, instead of raising BuildError. + return url + + app.build_error_handler = external_url_handler + + Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and + `endpoint` and `**values` are the arguments passed into `url_for`. Note + that this is for building URLs outside the current application, and not for + handling 404 NotFound errors. + + .. versionadded:: 0.10 + The `_scheme` parameter was added. + + .. versionadded:: 0.9 + The `_anchor` and `_method` parameters were added. + + .. versionadded:: 0.9 + Calls :meth:`Flask.handle_build_error` on + :exc:`~werkzeug.routing.BuildError`. + + :param endpoint: the endpoint of the URL (name of the function) + :param values: the variable arguments of the URL rule + :param _external: if set to `True`, an absolute URL is generated. Server + address can be changed via `SERVER_NAME` configuration variable which + defaults to `localhost`. + :param _scheme: a string specifying the desired URL scheme. The `_external` + parameter must be set to `True` or a `ValueError` is raised. + :param _anchor: if provided this is added as anchor to the URL. + :param _method: if provided this explicitly specifies an HTTP method. + """ + appctx = _app_ctx_stack.top + reqctx = _request_ctx_stack.top + if appctx is None: + raise RuntimeError('Attempted to generate a URL without the ' + 'application context being pushed. This has to be ' + 'executed when application context is available.') + + # If request specific information is available we have some extra + # features that support "relative" urls. + if reqctx is not None: + url_adapter = reqctx.url_adapter + blueprint_name = request.blueprint + if not reqctx.request._is_old_module: + if endpoint[:1] == '.': + if blueprint_name is not None: + endpoint = blueprint_name + endpoint + else: + endpoint = endpoint[1:] + else: + # TODO: get rid of this deprecated functionality in 1.0 + if '.' not in endpoint: + if blueprint_name is not None: + endpoint = blueprint_name + '.' + endpoint + elif endpoint.startswith('.'): + endpoint = endpoint[1:] + external = values.pop('_external', False) + + # Otherwise go with the url adapter from the appctx and make + # the urls external by default. + else: + url_adapter = appctx.url_adapter + if url_adapter is None: + raise RuntimeError('Application was not able to create a URL ' + 'adapter for request independent URL generation. ' + 'You might be able to fix this by setting ' + 'the SERVER_NAME config variable.') + external = values.pop('_external', True) + + anchor = values.pop('_anchor', None) + method = values.pop('_method', None) + scheme = values.pop('_scheme', None) + appctx.app.inject_url_defaults(endpoint, values) + + if scheme is not None: + if not external: + raise ValueError('When specifying _scheme, _external must be True') + url_adapter.url_scheme = scheme + + try: + rv = url_adapter.build(endpoint, values, method=method, + force_external=external) + except BuildError as error: + # We need to inject the values again so that the app callback can + # deal with that sort of stuff. + values['_external'] = external + values['_anchor'] = anchor + values['_method'] = method + return appctx.app.handle_url_build_error(error, endpoint, values) + + if anchor is not None: + rv += '#' + url_quote(anchor) + return rv + + +def get_template_attribute(template_name, attribute): + """Loads a macro (or variable) a template exports. This can be used to + invoke a macro from within Python code. If you for example have a + template named `_cider.html` with the following contents: + + .. sourcecode:: html+jinja + + {% macro hello(name) %}Hello {{ name }}!{% endmacro %} + + You can access this from Python code like this:: + + hello = get_template_attribute('_cider.html', 'hello') + return hello('World') + + .. versionadded:: 0.2 + + :param template_name: the name of the template + :param attribute: the name of the variable of macro to access + """ + return getattr(current_app.jinja_env.get_template(template_name).module, + attribute) + + +def flash(message, category='message'): + """Flashes a message to the next request. In order to remove the + flashed message from the session and to display it to the user, + the template has to call :func:`get_flashed_messages`. + + .. versionchanged:: 0.3 + `category` parameter added. + + :param message: the message to be flashed. + :param category: the category for the message. The following values + are recommended: ``'message'`` for any kind of message, + ``'error'`` for errors, ``'info'`` for information + messages and ``'warning'`` for warnings. However any + kind of string can be used as category. + """ + # Original implementation: + # + # session.setdefault('_flashes', []).append((category, message)) + # + # This assumed that changes made to mutable structures in the session are + # are always in sync with the sess on object, which is not true for session + # implementations that use external storage for keeping their keys/values. + flashes = session.get('_flashes', []) + flashes.append((category, message)) + session['_flashes'] = flashes + message_flashed.send(current_app._get_current_object(), + message=message, category=category) + + +def get_flashed_messages(with_categories=False, category_filter=[]): + """Pulls all flashed messages from the session and returns them. + Further calls in the same request to the function will return + the same messages. By default just the messages are returned, + but when `with_categories` is set to `True`, the return value will + be a list of tuples in the form ``(category, message)`` instead. + + Filter the flashed messages to one or more categories by providing those + categories in `category_filter`. This allows rendering categories in + separate html blocks. The `with_categories` and `category_filter` + arguments are distinct: + + * `with_categories` controls whether categories are returned with message + text (`True` gives a tuple, where `False` gives just the message text). + * `category_filter` filters the messages down to only those matching the + provided categories. + + See :ref:`message-flashing-pattern` for examples. + + .. versionchanged:: 0.3 + `with_categories` parameter added. + + .. versionchanged:: 0.9 + `category_filter` parameter added. + + :param with_categories: set to `True` to also receive categories. + :param category_filter: whitelist of categories to limit return values + """ + flashes = _request_ctx_stack.top.flashes + if flashes is None: + _request_ctx_stack.top.flashes = flashes = session.pop('_flashes') \ + if '_flashes' in session else [] + if category_filter: + flashes = list(filter(lambda f: f[0] in category_filter, flashes)) + if not with_categories: + return [x[1] for x in flashes] + return flashes + + +def send_file(filename_or_fp, mimetype=None, as_attachment=False, + attachment_filename=None, add_etags=True, + cache_timeout=None, conditional=False): + """Sends the contents of a file to the client. This will use the + most efficient method available and configured. By default it will + try to use the WSGI server's file_wrapper support. Alternatively + you can set the application's :attr:`~Flask.use_x_sendfile` attribute + to ``True`` to directly emit an `X-Sendfile` header. This however + requires support of the underlying webserver for `X-Sendfile`. + + By default it will try to guess the mimetype for you, but you can + also explicitly provide one. For extra security you probably want + to send certain files as attachment (HTML for instance). The mimetype + guessing requires a `filename` or an `attachment_filename` to be + provided. + + Please never pass filenames to this function from user sources without + checking them first. Something like this is usually sufficient to + avoid security problems:: + + if '..' in filename or filename.startswith('/'): + abort(404) + + .. versionadded:: 0.2 + + .. versionadded:: 0.5 + The `add_etags`, `cache_timeout` and `conditional` parameters were + added. The default behavior is now to attach etags. + + .. versionchanged:: 0.7 + mimetype guessing and etag support for file objects was + deprecated because it was unreliable. Pass a filename if you are + able to, otherwise attach an etag yourself. This functionality + will be removed in Flask 1.0 + + .. versionchanged:: 0.9 + cache_timeout pulls its default from application config, when None. + + :param filename_or_fp: the filename of the file to send. This is + relative to the :attr:`~Flask.root_path` if a + relative path is specified. + Alternatively a file object might be provided + in which case `X-Sendfile` might not work and + fall back to the traditional method. Make sure + that the file pointer is positioned at the start + of data to send before calling :func:`send_file`. + :param mimetype: the mimetype of the file if provided, otherwise + auto detection happens. + :param as_attachment: set to `True` if you want to send this file with + a ``Content-Disposition: attachment`` header. + :param attachment_filename: the filename for the attachment if it + differs from the file's filename. + :param add_etags: set to `False` to disable attaching of etags. + :param conditional: set to `True` to enable conditional responses. + + :param cache_timeout: the timeout in seconds for the headers. When `None` + (default), this value is set by + :meth:`~Flask.get_send_file_max_age` of + :data:`~flask.current_app`. + """ + mtime = None + if isinstance(filename_or_fp, string_types): + filename = filename_or_fp + file = None + else: + from warnings import warn + file = filename_or_fp + filename = getattr(file, 'name', None) + + # XXX: this behavior is now deprecated because it was unreliable. + # removed in Flask 1.0 + if not attachment_filename and not mimetype \ + and isinstance(filename, string_types): + warn(DeprecationWarning('The filename support for file objects ' + 'passed to send_file is now deprecated. Pass an ' + 'attach_filename if you want mimetypes to be guessed.'), + stacklevel=2) + if add_etags: + warn(DeprecationWarning('In future flask releases etags will no ' + 'longer be generated for file objects passed to the send_file ' + 'function because this behavior was unreliable. Pass ' + 'filenames instead if possible, otherwise attach an etag ' + 'yourself based on another value'), stacklevel=2) + + if filename is not None: + if not os.path.isabs(filename): + filename = os.path.join(current_app.root_path, filename) + if mimetype is None and (filename or attachment_filename): + mimetype = mimetypes.guess_type(filename or attachment_filename)[0] + if mimetype is None: + mimetype = 'application/octet-stream' + + headers = Headers() + if as_attachment: + if attachment_filename is None: + if filename is None: + raise TypeError('filename unavailable, required for ' + 'sending as attachment') + attachment_filename = os.path.basename(filename) + headers.add('Content-Disposition', 'attachment', + filename=attachment_filename) + + if current_app.use_x_sendfile and filename: + if file is not None: + file.close() + headers['X-Sendfile'] = filename + headers['Content-Length'] = os.path.getsize(filename) + data = None + else: + if file is None: + file = open(filename, 'rb') + mtime = os.path.getmtime(filename) + headers['Content-Length'] = os.path.getsize(filename) + data = wrap_file(request.environ, file) + + rv = current_app.response_class(data, mimetype=mimetype, headers=headers, + direct_passthrough=True) + + # if we know the file modification date, we can store it as the + # the time of the last modification. + if mtime is not None: + rv.last_modified = int(mtime) + + rv.cache_control.public = True + if cache_timeout is None: + cache_timeout = current_app.get_send_file_max_age(filename) + if cache_timeout is not None: + rv.cache_control.max_age = cache_timeout + rv.expires = int(time() + cache_timeout) + + if add_etags and filename is not None: + rv.set_etag('flask-%s-%s-%s' % ( + os.path.getmtime(filename), + os.path.getsize(filename), + adler32( + filename.encode('utf-8') if isinstance(filename, text_type) + else filename + ) & 0xffffffff + )) + if conditional: + rv = rv.make_conditional(request) + # make sure we don't send x-sendfile for servers that + # ignore the 304 status code for x-sendfile. + if rv.status_code == 304: + rv.headers.pop('x-sendfile', None) + return rv + + +def safe_join(directory, filename): + """Safely join `directory` and `filename`. + + Example usage:: + + @app.route('/wiki/') + def wiki_page(filename): + filename = safe_join(app.config['WIKI_FOLDER'], filename) + with open(filename, 'rb') as fd: + content = fd.read() # Read and process the file content... + + :param directory: the base directory. + :param filename: the untrusted filename relative to that directory. + :raises: :class:`~werkzeug.exceptions.NotFound` if the resulting path + would fall out of `directory`. + """ + filename = posixpath.normpath(filename) + for sep in _os_alt_seps: + if sep in filename: + raise NotFound() + if os.path.isabs(filename) or \ + filename == '..' or \ + filename.startswith('../'): + raise NotFound() + return os.path.join(directory, filename) + + +def send_from_directory(directory, filename, **options): + """Send a file from a given directory with :func:`send_file`. This + is a secure way to quickly expose static files from an upload folder + or something similar. + + Example usage:: + + @app.route('/uploads/') + def download_file(filename): + return send_from_directory(app.config['UPLOAD_FOLDER'], + filename, as_attachment=True) + + .. admonition:: Sending files and Performance + + It is strongly recommended to activate either `X-Sendfile` support in + your webserver or (if no authentication happens) to tell the webserver + to serve files for the given path on its own without calling into the + web application for improved performance. + + .. versionadded:: 0.5 + + :param directory: the directory where all the files are stored. + :param filename: the filename relative to that directory to + download. + :param options: optional keyword arguments that are directly + forwarded to :func:`send_file`. + """ + filename = safe_join(directory, filename) + if not os.path.isfile(filename): + raise NotFound() + options.setdefault('conditional', True) + return send_file(filename, **options) + + +def get_root_path(import_name): + """Returns the path to a package or cwd if that cannot be found. This + returns the path of a package or the folder that contains a module. + + Not to be confused with the package path returned by :func:`find_package`. + """ + # Module already imported and has a file attribute. Use that first. + mod = sys.modules.get(import_name) + if mod is not None and hasattr(mod, '__file__'): + return os.path.dirname(os.path.abspath(mod.__file__)) + + # Next attempt: check the loader. + loader = pkgutil.get_loader(import_name) + + # Loader does not exist or we're referring to an unloaded main module + # or a main module without path (interactive sessions), go with the + # current working directory. + if loader is None or import_name == '__main__': + return os.getcwd() + + # For .egg, zipimporter does not have get_filename until Python 2.7. + # Some other loaders might exhibit the same behavior. + if hasattr(loader, 'get_filename'): + filepath = loader.get_filename(import_name) + else: + # Fall back to imports. + __import__(import_name) + filepath = sys.modules[import_name].__file__ + + # filepath is import_name.py for a module, or __init__.py for a package. + return os.path.dirname(os.path.abspath(filepath)) + + +def find_package(import_name): + """Finds a package and returns the prefix (or None if the package is + not installed) as well as the folder that contains the package or + module as a tuple. The package path returned is the module that would + have to be added to the pythonpath in order to make it possible to + import the module. The prefix is the path below which a UNIX like + folder structure exists (lib, share etc.). + """ + root_mod_name = import_name.split('.')[0] + loader = pkgutil.get_loader(root_mod_name) + if loader is None or import_name == '__main__': + # import name is not found, or interactive/main module + package_path = os.getcwd() + else: + # For .egg, zipimporter does not have get_filename until Python 2.7. + if hasattr(loader, 'get_filename'): + filename = loader.get_filename(root_mod_name) + elif hasattr(loader, 'archive'): + # zipimporter's loader.archive points to the .egg or .zip + # archive filename is dropped in call to dirname below. + filename = loader.archive + else: + # At least one loader is missing both get_filename and archive: + # Google App Engine's HardenedModulesHook + # + # Fall back to imports. + __import__(import_name) + filename = sys.modules[import_name].__file__ + package_path = os.path.abspath(os.path.dirname(filename)) + # package_path ends with __init__.py for a package + if loader.is_package(root_mod_name): + package_path = os.path.dirname(package_path) + + site_parent, site_folder = os.path.split(package_path) + py_prefix = os.path.abspath(sys.prefix) + if package_path.startswith(py_prefix): + return py_prefix, package_path + elif site_folder.lower() == 'site-packages': + parent, folder = os.path.split(site_parent) + # Windows like installations + if folder.lower() == 'lib': + base_dir = parent + # UNIX like installations + elif os.path.basename(parent).lower() == 'lib': + base_dir = os.path.dirname(parent) + else: + base_dir = site_parent + return base_dir, package_path + return None, package_path + + +class locked_cached_property(object): + """A decorator that converts a function into a lazy property. The + function wrapped is called the first time to retrieve the result + and then that calculated result is used the next time you access + the value. Works like the one in Werkzeug but has a lock for + thread safety. + """ + + def __init__(self, func, name=None, doc=None): + self.__name__ = name or func.__name__ + self.__module__ = func.__module__ + self.__doc__ = doc or func.__doc__ + self.func = func + self.lock = RLock() + + def __get__(self, obj, type=None): + if obj is None: + return self + with self.lock: + value = obj.__dict__.get(self.__name__, _missing) + if value is _missing: + value = self.func(obj) + obj.__dict__[self.__name__] = value + return value + + +class _PackageBoundObject(object): + + def __init__(self, import_name, template_folder=None): + #: The name of the package or module. Do not change this once + #: it was set by the constructor. + self.import_name = import_name + + #: location of the templates. `None` if templates should not be + #: exposed. + self.template_folder = template_folder + + #: Where is the app root located? + self.root_path = get_root_path(self.import_name) + + self._static_folder = None + self._static_url_path = None + + def _get_static_folder(self): + if self._static_folder is not None: + return os.path.join(self.root_path, self._static_folder) + def _set_static_folder(self, value): + self._static_folder = value + static_folder = property(_get_static_folder, _set_static_folder) + del _get_static_folder, _set_static_folder + + def _get_static_url_path(self): + if self._static_url_path is None: + if self.static_folder is None: + return None + return '/' + os.path.basename(self.static_folder) + return self._static_url_path + def _set_static_url_path(self, value): + self._static_url_path = value + static_url_path = property(_get_static_url_path, _set_static_url_path) + del _get_static_url_path, _set_static_url_path + + @property + def has_static_folder(self): + """This is `True` if the package bound object's container has a + folder named ``'static'``. + + .. versionadded:: 0.5 + """ + return self.static_folder is not None + + @locked_cached_property + def jinja_loader(self): + """The Jinja loader for this package bound object. + + .. versionadded:: 0.5 + """ + if self.template_folder is not None: + return FileSystemLoader(os.path.join(self.root_path, + self.template_folder)) + + def get_send_file_max_age(self, filename): + """Provides default cache_timeout for the :func:`send_file` functions. + + By default, this function returns ``SEND_FILE_MAX_AGE_DEFAULT`` from + the configuration of :data:`~flask.current_app`. + + Static file functions such as :func:`send_from_directory` use this + function, and :func:`send_file` calls this function on + :data:`~flask.current_app` when the given cache_timeout is `None`. If a + cache_timeout is given in :func:`send_file`, that timeout is used; + otherwise, this method is called. + + This allows subclasses to change the behavior when sending files based + on the filename. For example, to set the cache timeout for .js files + to 60 seconds:: + + class MyFlask(flask.Flask): + def get_send_file_max_age(self, name): + if name.lower().endswith('.js'): + return 60 + return flask.Flask.get_send_file_max_age(self, name) + + .. versionadded:: 0.9 + """ + return current_app.config['SEND_FILE_MAX_AGE_DEFAULT'] + + def send_static_file(self, filename): + """Function used internally to send static files from the static + folder to the browser. + + .. versionadded:: 0.5 + """ + if not self.has_static_folder: + raise RuntimeError('No static folder for this object') + # Ensure get_send_file_max_age is called in all cases. + # Here, we ensure get_send_file_max_age is called for Blueprints. + cache_timeout = self.get_send_file_max_age(filename) + return send_from_directory(self.static_folder, filename, + cache_timeout=cache_timeout) + + def open_resource(self, resource, mode='rb'): + """Opens a resource from the application's resource folder. To see + how this works, consider the following folder structure:: + + /myapplication.py + /schema.sql + /static + /style.css + /templates + /layout.html + /index.html + + If you want to open the `schema.sql` file you would do the + following:: + + with app.open_resource('schema.sql') as f: + contents = f.read() + do_something_with(contents) + + :param resource: the name of the resource. To access resources within + subfolders use forward slashes as separator. + :param mode: resource file opening mode, default is 'rb'. + """ + if mode not in ('r', 'rb'): + raise ValueError('Resources can only be opened for reading') + return open(os.path.join(self.root_path, resource), mode) diff --git a/env/lib/python2.7/site-packages/flask/helpers.pyc b/env/lib/python2.7/site-packages/flask/helpers.pyc new file mode 100644 index 0000000..1acf2d3 Binary files /dev/null and b/env/lib/python2.7/site-packages/flask/helpers.pyc differ diff --git a/env/lib/python2.7/site-packages/flask/json.py b/env/lib/python2.7/site-packages/flask/json.py new file mode 100644 index 0000000..45ba324 --- /dev/null +++ b/env/lib/python2.7/site-packages/flask/json.py @@ -0,0 +1,243 @@ +# -*- coding: utf-8 -*- +""" + flask.jsonimpl + ~~~~~~~~~~~~~~ + + Implementation helpers for the JSON support in Flask. + + :copyright: (c) 2012 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" +import io +import uuid +from datetime import datetime +from .globals import current_app, request +from ._compat import text_type, PY2 + +from werkzeug.http import http_date +from jinja2 import Markup + +# Use the same json implementation as itsdangerous on which we +# depend anyways. +try: + from itsdangerous import simplejson as _json +except ImportError: + from itsdangerous import json as _json + + +# figure out if simplejson escapes slashes. This behavior was changed +# from one version to another without reason. +_slash_escape = '\\/' not in _json.dumps('/') + + +__all__ = ['dump', 'dumps', 'load', 'loads', 'htmlsafe_dump', + 'htmlsafe_dumps', 'JSONDecoder', 'JSONEncoder', + 'jsonify'] + + +def _wrap_reader_for_text(fp, encoding): + if isinstance(fp.read(0), bytes): + fp = io.TextIOWrapper(io.BufferedReader(fp), encoding) + return fp + + +def _wrap_writer_for_text(fp, encoding): + try: + fp.write('') + except TypeError: + fp = io.TextIOWrapper(fp, encoding) + return fp + + +class JSONEncoder(_json.JSONEncoder): + """The default Flask JSON encoder. This one extends the default simplejson + encoder by also supporting ``datetime`` objects, ``UUID`` as well as + ``Markup`` objects which are serialized as RFC 822 datetime strings (same + as the HTTP date format). In order to support more data types override the + :meth:`default` method. + """ + + def default(self, o): + """Implement this method in a subclass such that it returns a + serializable object for ``o``, or calls the base implementation (to + raise a ``TypeError``). + + For example, to support arbitrary iterators, you could implement + default like this:: + + def default(self, o): + try: + iterable = iter(o) + except TypeError: + pass + else: + return list(iterable) + return JSONEncoder.default(self, o) + """ + if isinstance(o, datetime): + return http_date(o) + if isinstance(o, uuid.UUID): + return str(o) + if hasattr(o, '__html__'): + return text_type(o.__html__()) + return _json.JSONEncoder.default(self, o) + + +class JSONDecoder(_json.JSONDecoder): + """The default JSON decoder. This one does not change the behavior from + the default simplejson encoder. Consult the :mod:`json` documentation + for more information. This decoder is not only used for the load + functions of this module but also :attr:`~flask.Request`. + """ + + +def _dump_arg_defaults(kwargs): + """Inject default arguments for dump functions.""" + if current_app: + kwargs.setdefault('cls', current_app.json_encoder) + if not current_app.config['JSON_AS_ASCII']: + kwargs.setdefault('ensure_ascii', False) + kwargs.setdefault('sort_keys', current_app.config['JSON_SORT_KEYS']) + else: + kwargs.setdefault('sort_keys', True) + kwargs.setdefault('cls', JSONEncoder) + + +def _load_arg_defaults(kwargs): + """Inject default arguments for load functions.""" + if current_app: + kwargs.setdefault('cls', current_app.json_decoder) + else: + kwargs.setdefault('cls', JSONDecoder) + + +def dumps(obj, **kwargs): + """Serialize ``obj`` to a JSON formatted ``str`` by using the application's + configured encoder (:attr:`~flask.Flask.json_encoder`) if there is an + application on the stack. + + This function can return ``unicode`` strings or ascii-only bytestrings by + default which coerce into unicode strings automatically. That behavior by + default is controlled by the ``JSON_AS_ASCII`` configuration variable + and can be overriden by the simplejson ``ensure_ascii`` parameter. + """ + _dump_arg_defaults(kwargs) + encoding = kwargs.pop('encoding', None) + rv = _json.dumps(obj, **kwargs) + if encoding is not None and isinstance(rv, text_type): + rv = rv.encode(encoding) + return rv + + +def dump(obj, fp, **kwargs): + """Like :func:`dumps` but writes into a file object.""" + _dump_arg_defaults(kwargs) + encoding = kwargs.pop('encoding', None) + if encoding is not None: + fp = _wrap_writer_for_text(fp, encoding) + _json.dump(obj, fp, **kwargs) + + +def loads(s, **kwargs): + """Unserialize a JSON object from a string ``s`` by using the application's + configured decoder (:attr:`~flask.Flask.json_decoder`) if there is an + application on the stack. + """ + _load_arg_defaults(kwargs) + if isinstance(s, bytes): + s = s.decode(kwargs.pop('encoding', None) or 'utf-8') + return _json.loads(s, **kwargs) + + +def load(fp, **kwargs): + """Like :func:`loads` but reads from a file object. + """ + _load_arg_defaults(kwargs) + if not PY2: + fp = _wrap_reader_for_text(fp, kwargs.pop('encoding', None) or 'utf-8') + return _json.load(fp, **kwargs) + + +def htmlsafe_dumps(obj, **kwargs): + """Works exactly like :func:`dumps` but is safe for use in ``') + self.assert_equal(rv, u'"\\u003c/script\\u003e"') + self.assert_equal(type(rv), text_type) + rv = render('{{ ""|tojson }}') + self.assert_equal(rv, '"\\u003c/script\\u003e"') + rv = render('{{ "<\0/script>"|tojson }}') + self.assert_equal(rv, '"\\u003c\\u0000/script\\u003e"') + rv = render('{{ "' % ( + render_traceback(self, full=full), + self.render_as_text().decode('utf-8', 'replace') + ) + + @property + def is_template_syntax_error(self): + """`True` if this is a template syntax error.""" + return isinstance(self.exc_value, TemplateSyntaxError) + + @property + def exc_info(self): + """Exception info tuple with a proxy around the frame objects.""" + return self.exc_type, self.exc_value, self.frames[0] + + @property + def standard_exc_info(self): + """Standard python exc_info for re-raising""" + tb = self.frames[0] + # the frame will be an actual traceback (or transparent proxy) if + # we are on pypy or a python implementation with support for tproxy + if type(tb) is not TracebackType: + tb = tb.tb + return self.exc_type, self.exc_value, tb + + +def make_traceback(exc_info, source_hint=None): + """Creates a processed traceback object from the exc_info.""" + exc_type, exc_value, tb = exc_info + if isinstance(exc_value, TemplateSyntaxError): + exc_info = translate_syntax_error(exc_value, source_hint) + initial_skip = 0 + else: + initial_skip = 1 + return translate_exception(exc_info, initial_skip) + + +def translate_syntax_error(error, source=None): + """Rewrites a syntax error to please traceback systems.""" + error.source = source + error.translated = True + exc_info = (error.__class__, error, None) + filename = error.filename + if filename is None: + filename = '' + return fake_exc_info(exc_info, filename, error.lineno) + + +def translate_exception(exc_info, initial_skip=0): + """If passed an exc_info it will automatically rewrite the exceptions + all the way down to the correct line numbers and frames. + """ + tb = exc_info[2] + frames = [] + + # skip some internal frames if wanted + for x in range(initial_skip): + if tb is not None: + tb = tb.tb_next + initial_tb = tb + + while tb is not None: + # skip frames decorated with @internalcode. These are internal + # calls we can't avoid and that are useless in template debugging + # output. + if tb.tb_frame.f_code in internal_code: + tb = tb.tb_next + continue + + # save a reference to the next frame if we override the current + # one with a faked one. + next = tb.tb_next + + # fake template exceptions + template = tb.tb_frame.f_globals.get('__jinja_template__') + if template is not None: + lineno = template.get_corresponding_lineno(tb.tb_lineno) + tb = fake_exc_info(exc_info[:2] + (tb,), template.filename, + lineno)[2] + + frames.append(make_frame_proxy(tb)) + tb = next + + # if we don't have any exceptions in the frames left, we have to + # reraise it unchanged. + # XXX: can we backup here? when could this happen? + if not frames: + reraise(exc_info[0], exc_info[1], exc_info[2]) + + return ProcessedTraceback(exc_info[0], exc_info[1], frames) + + +def fake_exc_info(exc_info, filename, lineno): + """Helper for `translate_exception`.""" + exc_type, exc_value, tb = exc_info + + # figure the real context out + if tb is not None: + real_locals = tb.tb_frame.f_locals.copy() + ctx = real_locals.get('context') + if ctx: + locals = ctx.get_all() + else: + locals = {} + for name, value in iteritems(real_locals): + if name.startswith('l_') and value is not missing: + locals[name[2:]] = value + + # if there is a local called __jinja_exception__, we get + # rid of it to not break the debug functionality. + locals.pop('__jinja_exception__', None) + else: + locals = {} + + # assamble fake globals we need + globals = { + '__name__': filename, + '__file__': filename, + '__jinja_exception__': exc_info[:2], + + # we don't want to keep the reference to the template around + # to not cause circular dependencies, but we mark it as Jinja + # frame for the ProcessedTraceback + '__jinja_template__': None + } + + # and fake the exception + code = compile('\n' * (lineno - 1) + raise_helper, filename, 'exec') + + # if it's possible, change the name of the code. This won't work + # on some python environments such as google appengine + try: + if tb is None: + location = 'template' + else: + function = tb.tb_frame.f_code.co_name + if function == 'root': + location = 'top-level template code' + elif function.startswith('block_'): + location = 'block "%s"' % function[6:] + else: + location = 'template' + + if PY2: + code = CodeType(0, code.co_nlocals, code.co_stacksize, + code.co_flags, code.co_code, code.co_consts, + code.co_names, code.co_varnames, filename, + location, code.co_firstlineno, + code.co_lnotab, (), ()) + else: + code = CodeType(0, code.co_kwonlyargcount, + code.co_nlocals, code.co_stacksize, + code.co_flags, code.co_code, code.co_consts, + code.co_names, code.co_varnames, filename, + location, code.co_firstlineno, + code.co_lnotab, (), ()) + except Exception as e: + pass + + # execute the code and catch the new traceback + try: + exec(code, globals, locals) + except: + exc_info = sys.exc_info() + new_tb = exc_info[2].tb_next + + # return without this frame + return exc_info[:2] + (new_tb,) + + +def _init_ugly_crap(): + """This function implements a few ugly things so that we can patch the + traceback objects. The function returned allows resetting `tb_next` on + any python traceback object. Do not attempt to use this on non cpython + interpreters + """ + import ctypes + from types import TracebackType + + if PY2: + # figure out size of _Py_ssize_t for Python 2: + if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'): + _Py_ssize_t = ctypes.c_int64 + else: + _Py_ssize_t = ctypes.c_int + else: + # platform ssize_t on Python 3 + _Py_ssize_t = ctypes.c_ssize_t + + # regular python + class _PyObject(ctypes.Structure): + pass + _PyObject._fields_ = [ + ('ob_refcnt', _Py_ssize_t), + ('ob_type', ctypes.POINTER(_PyObject)) + ] + + # python with trace + if hasattr(sys, 'getobjects'): + class _PyObject(ctypes.Structure): + pass + _PyObject._fields_ = [ + ('_ob_next', ctypes.POINTER(_PyObject)), + ('_ob_prev', ctypes.POINTER(_PyObject)), + ('ob_refcnt', _Py_ssize_t), + ('ob_type', ctypes.POINTER(_PyObject)) + ] + + class _Traceback(_PyObject): + pass + _Traceback._fields_ = [ + ('tb_next', ctypes.POINTER(_Traceback)), + ('tb_frame', ctypes.POINTER(_PyObject)), + ('tb_lasti', ctypes.c_int), + ('tb_lineno', ctypes.c_int) + ] + + def tb_set_next(tb, next): + """Set the tb_next attribute of a traceback object.""" + if not (isinstance(tb, TracebackType) and + (next is None or isinstance(next, TracebackType))): + raise TypeError('tb_set_next arguments must be traceback objects') + obj = _Traceback.from_address(id(tb)) + if tb.tb_next is not None: + old = _Traceback.from_address(id(tb.tb_next)) + old.ob_refcnt -= 1 + if next is None: + obj.tb_next = ctypes.POINTER(_Traceback)() + else: + next = _Traceback.from_address(id(next)) + next.ob_refcnt += 1 + obj.tb_next = ctypes.pointer(next) + + return tb_set_next + + +# try to get a tb_set_next implementation if we don't have transparent +# proxies. +tb_set_next = None +if tproxy is None: + try: + tb_set_next = _init_ugly_crap() + except: + pass + del _init_ugly_crap diff --git a/env/lib/python2.7/site-packages/jinja2/debug.pyc b/env/lib/python2.7/site-packages/jinja2/debug.pyc new file mode 100644 index 0000000..84568f3 Binary files /dev/null and b/env/lib/python2.7/site-packages/jinja2/debug.pyc differ diff --git a/env/lib/python2.7/site-packages/jinja2/defaults.py b/env/lib/python2.7/site-packages/jinja2/defaults.py new file mode 100644 index 0000000..3717a72 --- /dev/null +++ b/env/lib/python2.7/site-packages/jinja2/defaults.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +""" + jinja2.defaults + ~~~~~~~~~~~~~~~ + + Jinja default filters and tags. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +from jinja2._compat import range_type +from jinja2.utils import generate_lorem_ipsum, Cycler, Joiner + + +# defaults for the parser / lexer +BLOCK_START_STRING = '{%' +BLOCK_END_STRING = '%}' +VARIABLE_START_STRING = '{{' +VARIABLE_END_STRING = '}}' +COMMENT_START_STRING = '{#' +COMMENT_END_STRING = '#}' +LINE_STATEMENT_PREFIX = None +LINE_COMMENT_PREFIX = None +TRIM_BLOCKS = False +LSTRIP_BLOCKS = False +NEWLINE_SEQUENCE = '\n' +KEEP_TRAILING_NEWLINE = False + + +# default filters, tests and namespace +from jinja2.filters import FILTERS as DEFAULT_FILTERS +from jinja2.tests import TESTS as DEFAULT_TESTS +DEFAULT_NAMESPACE = { + 'range': range_type, + 'dict': dict, + 'lipsum': generate_lorem_ipsum, + 'cycler': Cycler, + 'joiner': Joiner +} + + +# export all constants +__all__ = tuple(x for x in locals().keys() if x.isupper()) diff --git a/env/lib/python2.7/site-packages/jinja2/defaults.pyc b/env/lib/python2.7/site-packages/jinja2/defaults.pyc new file mode 100644 index 0000000..f3a1678 Binary files /dev/null and b/env/lib/python2.7/site-packages/jinja2/defaults.pyc differ diff --git a/env/lib/python2.7/site-packages/jinja2/environment.py b/env/lib/python2.7/site-packages/jinja2/environment.py new file mode 100644 index 0000000..8b2572b --- /dev/null +++ b/env/lib/python2.7/site-packages/jinja2/environment.py @@ -0,0 +1,1213 @@ +# -*- coding: utf-8 -*- +""" + jinja2.environment + ~~~~~~~~~~~~~~~~~~ + + Provides a class that holds runtime and parsing time options. + + :copyright: (c) 2010 by the Jinja Team. + :license: BSD, see LICENSE for more details. +""" +import os +import sys +from jinja2 import nodes +from jinja2.defaults import BLOCK_START_STRING, \ + BLOCK_END_STRING, VARIABLE_START_STRING, VARIABLE_END_STRING, \ + COMMENT_START_STRING, COMMENT_END_STRING, LINE_STATEMENT_PREFIX, \ + LINE_COMMENT_PREFIX, TRIM_BLOCKS, NEWLINE_SEQUENCE, \ + DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE, \ + KEEP_TRAILING_NEWLINE, LSTRIP_BLOCKS +from jinja2.lexer import get_lexer, TokenStream +from jinja2.parser import Parser +from jinja2.nodes import EvalContext +from jinja2.optimizer import optimize +from jinja2.compiler import generate, CodeGenerator +from jinja2.runtime import Undefined, new_context, Context +from jinja2.exceptions import TemplateSyntaxError, TemplateNotFound, \ + TemplatesNotFound, TemplateRuntimeError +from jinja2.utils import import_string, LRUCache, Markup, missing, \ + concat, consume, internalcode +from jinja2._compat import imap, ifilter, string_types, iteritems, \ + text_type, reraise, implements_iterator, implements_to_string, \ + get_next, encode_filename, PY2, PYPY +from functools import reduce + + +# for direct template usage we have up to ten living environments +_spontaneous_environments = LRUCache(10) + +# the function to create jinja traceback objects. This is dynamically +# imported on the first exception in the exception handler. +_make_traceback = None + + +def get_spontaneous_environment(*args): + """Return a new spontaneous environment. A spontaneous environment is an + unnamed and unaccessible (in theory) environment that is used for + templates generated from a string and not from the file system. + """ + try: + env = _spontaneous_environments.get(args) + except TypeError: + return Environment(*args) + if env is not None: + return env + _spontaneous_environments[args] = env = Environment(*args) + env.shared = True + return env + + +def create_cache(size): + """Return the cache class for the given size.""" + if size == 0: + return None + if size < 0: + return {} + return LRUCache(size) + + +def copy_cache(cache): + """Create an empty copy of the given cache.""" + if cache is None: + return None + elif type(cache) is dict: + return {} + return LRUCache(cache.capacity) + + +def load_extensions(environment, extensions): + """Load the extensions from the list and bind it to the environment. + Returns a dict of instantiated environments. + """ + result = {} + for extension in extensions: + if isinstance(extension, string_types): + extension = import_string(extension) + result[extension.identifier] = extension(environment) + return result + + +def _environment_sanity_check(environment): + """Perform a sanity check on the environment.""" + assert issubclass(environment.undefined, Undefined), 'undefined must ' \ + 'be a subclass of undefined because filters depend on it.' + assert environment.block_start_string != \ + environment.variable_start_string != \ + environment.comment_start_string, 'block, variable and comment ' \ + 'start strings must be different' + assert environment.newline_sequence in ('\r', '\r\n', '\n'), \ + 'newline_sequence set to unknown line ending string.' + return environment + + +class Environment(object): + r"""The core component of Jinja is the `Environment`. It contains + important shared variables like configuration, filters, tests, + globals and others. Instances of this class may be modified if + they are not shared and if no template was loaded so far. + Modifications on environments after the first template was loaded + will lead to surprising effects and undefined behavior. + + Here are the possible initialization parameters: + + `block_start_string` + The string marking the beginning of a block. Defaults to ``'{%'``. + + `block_end_string` + The string marking the end of a block. Defaults to ``'%}'``. + + `variable_start_string` + The string marking the beginning of a print statement. + Defaults to ``'{{'``. + + `variable_end_string` + The string marking the end of a print statement. Defaults to + ``'}}'``. + + `comment_start_string` + The string marking the beginning of a comment. Defaults to ``'{#'``. + + `comment_end_string` + The string marking the end of a comment. Defaults to ``'#}'``. + + `line_statement_prefix` + If given and a string, this will be used as prefix for line based + statements. See also :ref:`line-statements`. + + `line_comment_prefix` + If given and a string, this will be used as prefix for line based + comments. See also :ref:`line-statements`. + + .. versionadded:: 2.2 + + `trim_blocks` + If this is set to ``True`` the first newline after a block is + removed (block, not variable tag!). Defaults to `False`. + + `lstrip_blocks` + If this is set to ``True`` leading spaces and tabs are stripped + from the start of a line to a block. Defaults to `False`. + + `newline_sequence` + The sequence that starts a newline. Must be one of ``'\r'``, + ``'\n'`` or ``'\r\n'``. The default is ``'\n'`` which is a + useful default for Linux and OS X systems as well as web + applications. + + `keep_trailing_newline` + Preserve the trailing newline when rendering templates. + The default is ``False``, which causes a single newline, + if present, to be stripped from the end of the template. + + .. versionadded:: 2.7 + + `extensions` + List of Jinja extensions to use. This can either be import paths + as strings or extension classes. For more information have a + look at :ref:`the extensions documentation `. + + `optimized` + should the optimizer be enabled? Default is `True`. + + `undefined` + :class:`Undefined` or a subclass of it that is used to represent + undefined values in the template. + + `finalize` + A callable that can be used to process the result of a variable + expression before it is output. For example one can convert + `None` implicitly into an empty string here. + + `autoescape` + If set to true the XML/HTML autoescaping feature is enabled by + default. For more details about autoescaping see + :class:`~jinja2.utils.Markup`. As of Jinja 2.4 this can also + be a callable that is passed the template name and has to + return `True` or `False` depending on autoescape should be + enabled by default. + + .. versionchanged:: 2.4 + `autoescape` can now be a function + + `loader` + The template loader for this environment. + + `cache_size` + The size of the cache. Per default this is ``400`` which means + that if more than 400 templates are loaded the loader will clean + out the least recently used template. If the cache size is set to + ``0`` templates are recompiled all the time, if the cache size is + ``-1`` the cache will not be cleaned. + + .. versionchanged:: 2.8 + The cache size was increased to 400 from a low 50. + + `auto_reload` + Some loaders load templates from locations where the template + sources may change (ie: file system or database). If + `auto_reload` is set to `True` (default) every time a template is + requested the loader checks if the source changed and if yes, it + will reload the template. For higher performance it's possible to + disable that. + + `bytecode_cache` + If set to a bytecode cache object, this object will provide a + cache for the internal Jinja bytecode so that templates don't + have to be parsed if they were not changed. + + See :ref:`bytecode-cache` for more information. + """ + + #: if this environment is sandboxed. Modifying this variable won't make + #: the environment sandboxed though. For a real sandboxed environment + #: have a look at jinja2.sandbox. This flag alone controls the code + #: generation by the compiler. + sandboxed = False + + #: True if the environment is just an overlay + overlayed = False + + #: the environment this environment is linked to if it is an overlay + linked_to = None + + #: shared environments have this set to `True`. A shared environment + #: must not be modified + shared = False + + #: these are currently EXPERIMENTAL undocumented features. + exception_handler = None + exception_formatter = None + + #: the class that is used for code generation. See + #: :class:`~jinja2.compiler.CodeGenerator` for more information. + code_generator_class = CodeGenerator + + #: the context class thatis used for templates. See + #: :class:`~jinja2.runtime.Context` for more information. + context_class = Context + + def __init__(self, + block_start_string=BLOCK_START_STRING, + block_end_string=BLOCK_END_STRING, + variable_start_string=VARIABLE_START_STRING, + variable_end_string=VARIABLE_END_STRING, + comment_start_string=COMMENT_START_STRING, + comment_end_string=COMMENT_END_STRING, + line_statement_prefix=LINE_STATEMENT_PREFIX, + line_comment_prefix=LINE_COMMENT_PREFIX, + trim_blocks=TRIM_BLOCKS, + lstrip_blocks=LSTRIP_BLOCKS, + newline_sequence=NEWLINE_SEQUENCE, + keep_trailing_newline=KEEP_TRAILING_NEWLINE, + extensions=(), + optimized=True, + undefined=Undefined, + finalize=None, + autoescape=False, + loader=None, + cache_size=400, + auto_reload=True, + bytecode_cache=None): + # !!Important notice!! + # The constructor accepts quite a few arguments that should be + # passed by keyword rather than position. However it's important to + # not change the order of arguments because it's used at least + # internally in those cases: + # - spontaneous environments (i18n extension and Template) + # - unittests + # If parameter changes are required only add parameters at the end + # and don't change the arguments (or the defaults!) of the arguments + # existing already. + + # lexer / parser information + self.block_start_string = block_start_string + self.block_end_string = block_end_string + self.variable_start_string = variable_start_string + self.variable_end_string = variable_end_string + self.comment_start_string = comment_start_string + self.comment_end_string = comment_end_string + self.line_statement_prefix = line_statement_prefix + self.line_comment_prefix = line_comment_prefix + self.trim_blocks = trim_blocks + self.lstrip_blocks = lstrip_blocks + self.newline_sequence = newline_sequence + self.keep_trailing_newline = keep_trailing_newline + + # runtime information + self.undefined = undefined + self.optimized = optimized + self.finalize = finalize + self.autoescape = autoescape + + # defaults + self.filters = DEFAULT_FILTERS.copy() + self.tests = DEFAULT_TESTS.copy() + self.globals = DEFAULT_NAMESPACE.copy() + + # set the loader provided + self.loader = loader + self.cache = create_cache(cache_size) + self.bytecode_cache = bytecode_cache + self.auto_reload = auto_reload + + # load extensions + self.extensions = load_extensions(self, extensions) + + _environment_sanity_check(self) + + def add_extension(self, extension): + """Adds an extension after the environment was created. + + .. versionadded:: 2.5 + """ + self.extensions.update(load_extensions(self, [extension])) + + def extend(self, **attributes): + """Add the items to the instance of the environment if they do not exist + yet. This is used by :ref:`extensions ` to register + callbacks and configuration values without breaking inheritance. + """ + for key, value in iteritems(attributes): + if not hasattr(self, key): + setattr(self, key, value) + + def overlay(self, block_start_string=missing, block_end_string=missing, + variable_start_string=missing, variable_end_string=missing, + comment_start_string=missing, comment_end_string=missing, + line_statement_prefix=missing, line_comment_prefix=missing, + trim_blocks=missing, lstrip_blocks=missing, + extensions=missing, optimized=missing, + undefined=missing, finalize=missing, autoescape=missing, + loader=missing, cache_size=missing, auto_reload=missing, + bytecode_cache=missing): + """Create a new overlay environment that shares all the data with the + current environment except for cache and the overridden attributes. + Extensions cannot be removed for an overlayed environment. An overlayed + environment automatically gets all the extensions of the environment it + is linked to plus optional extra extensions. + + Creating overlays should happen after the initial environment was set + up completely. Not all attributes are truly linked, some are just + copied over so modifications on the original environment may not shine + through. + """ + args = dict(locals()) + del args['self'], args['cache_size'], args['extensions'] + + rv = object.__new__(self.__class__) + rv.__dict__.update(self.__dict__) + rv.overlayed = True + rv.linked_to = self + + for key, value in iteritems(args): + if value is not missing: + setattr(rv, key, value) + + if cache_size is not missing: + rv.cache = create_cache(cache_size) + else: + rv.cache = copy_cache(self.cache) + + rv.extensions = {} + for key, value in iteritems(self.extensions): + rv.extensions[key] = value.bind(rv) + if extensions is not missing: + rv.extensions.update(load_extensions(rv, extensions)) + + return _environment_sanity_check(rv) + + lexer = property(get_lexer, doc="The lexer for this environment.") + + def iter_extensions(self): + """Iterates over the extensions by priority.""" + return iter(sorted(self.extensions.values(), + key=lambda x: x.priority)) + + def getitem(self, obj, argument): + """Get an item or attribute of an object but prefer the item.""" + try: + return obj[argument] + except (TypeError, LookupError): + if isinstance(argument, string_types): + try: + attr = str(argument) + except Exception: + pass + else: + try: + return getattr(obj, attr) + except AttributeError: + pass + return self.undefined(obj=obj, name=argument) + + def getattr(self, obj, attribute): + """Get an item or attribute of an object but prefer the attribute. + Unlike :meth:`getitem` the attribute *must* be a bytestring. + """ + try: + return getattr(obj, attribute) + except AttributeError: + pass + try: + return obj[attribute] + except (TypeError, LookupError, AttributeError): + return self.undefined(obj=obj, name=attribute) + + def call_filter(self, name, value, args=None, kwargs=None, + context=None, eval_ctx=None): + """Invokes a filter on a value the same way the compiler does it. + + .. versionadded:: 2.7 + """ + func = self.filters.get(name) + if func is None: + raise TemplateRuntimeError('no filter named %r' % name) + args = [value] + list(args or ()) + if getattr(func, 'contextfilter', False): + if context is None: + raise TemplateRuntimeError('Attempted to invoke context ' + 'filter without context') + args.insert(0, context) + elif getattr(func, 'evalcontextfilter', False): + if eval_ctx is None: + if context is not None: + eval_ctx = context.eval_ctx + else: + eval_ctx = EvalContext(self) + args.insert(0, eval_ctx) + elif getattr(func, 'environmentfilter', False): + args.insert(0, self) + return func(*args, **(kwargs or {})) + + def call_test(self, name, value, args=None, kwargs=None): + """Invokes a test on a value the same way the compiler does it. + + .. versionadded:: 2.7 + """ + func = self.tests.get(name) + if func is None: + raise TemplateRuntimeError('no test named %r' % name) + return func(value, *(args or ()), **(kwargs or {})) + + @internalcode + def parse(self, source, name=None, filename=None): + """Parse the sourcecode and return the abstract syntax tree. This + tree of nodes is used by the compiler to convert the template into + executable source- or bytecode. This is useful for debugging or to + extract information from templates. + + If you are :ref:`developing Jinja2 extensions ` + this gives you a good overview of the node tree generated. + """ + try: + return self._parse(source, name, filename) + except TemplateSyntaxError: + exc_info = sys.exc_info() + self.handle_exception(exc_info, source_hint=source) + + def _parse(self, source, name, filename): + """Internal parsing function used by `parse` and `compile`.""" + return Parser(self, source, name, encode_filename(filename)).parse() + + def lex(self, source, name=None, filename=None): + """Lex the given sourcecode and return a generator that yields + tokens as tuples in the form ``(lineno, token_type, value)``. + This can be useful for :ref:`extension development ` + and debugging templates. + + This does not perform preprocessing. If you want the preprocessing + of the extensions to be applied you have to filter source through + the :meth:`preprocess` method. + """ + source = text_type(source) + try: + return self.lexer.tokeniter(source, name, filename) + except TemplateSyntaxError: + exc_info = sys.exc_info() + self.handle_exception(exc_info, source_hint=source) + + def preprocess(self, source, name=None, filename=None): + """Preprocesses the source with all extensions. This is automatically + called for all parsing and compiling methods but *not* for :meth:`lex` + because there you usually only want the actual source tokenized. + """ + return reduce(lambda s, e: e.preprocess(s, name, filename), + self.iter_extensions(), text_type(source)) + + def _tokenize(self, source, name, filename=None, state=None): + """Called by the parser to do the preprocessing and filtering + for all the extensions. Returns a :class:`~jinja2.lexer.TokenStream`. + """ + source = self.preprocess(source, name, filename) + stream = self.lexer.tokenize(source, name, filename, state) + for ext in self.iter_extensions(): + stream = ext.filter_stream(stream) + if not isinstance(stream, TokenStream): + stream = TokenStream(stream, name, filename) + return stream + + def _generate(self, source, name, filename, defer_init=False): + """Internal hook that can be overridden to hook a different generate + method in. + + .. versionadded:: 2.5 + """ + return generate(source, self, name, filename, defer_init=defer_init) + + def _compile(self, source, filename): + """Internal hook that can be overridden to hook a different compile + method in. + + .. versionadded:: 2.5 + """ + return compile(source, filename, 'exec') + + @internalcode + def compile(self, source, name=None, filename=None, raw=False, + defer_init=False): + """Compile a node or template source code. The `name` parameter is + the load name of the template after it was joined using + :meth:`join_path` if necessary, not the filename on the file system. + the `filename` parameter is the estimated filename of the template on + the file system. If the template came from a database or memory this + can be omitted. + + The return value of this method is a python code object. If the `raw` + parameter is `True` the return value will be a string with python + code equivalent to the bytecode returned otherwise. This method is + mainly used internally. + + `defer_init` is use internally to aid the module code generator. This + causes the generated code to be able to import without the global + environment variable to be set. + + .. versionadded:: 2.4 + `defer_init` parameter added. + """ + source_hint = None + try: + if isinstance(source, string_types): + source_hint = source + source = self._parse(source, name, filename) + if self.optimized: + source = optimize(source, self) + source = self._generate(source, name, filename, + defer_init=defer_init) + if raw: + return source + if filename is None: + filename = '