Repository: GoogleCloudPlatform/appengine-flask-skeleton Branch: master Commit: 8c25461d003a Files: 194 Total size: 2.0 MB Directory structure: gitextract_vdmaijab/ ├── .gitignore ├── .playground ├── CONTRIB.md ├── LICENSE ├── README.md ├── app.yaml ├── appengine_config.py ├── lib/ │ ├── Flask-0.10.dist-info/ │ │ ├── DESCRIPTION.rst │ │ ├── METADATA │ │ ├── RECORD │ │ ├── WHEEL │ │ ├── metadata.json │ │ └── top_level.txt │ ├── Jinja2-2.8.dist-info/ │ │ ├── DESCRIPTION.rst │ │ ├── METADATA │ │ ├── RECORD │ │ ├── WHEEL │ │ ├── entry_points.txt │ │ ├── metadata.json │ │ └── top_level.txt │ ├── MarkupSafe-0.23.dist-info/ │ │ ├── DESCRIPTION.rst │ │ ├── METADATA │ │ ├── RECORD │ │ ├── WHEEL │ │ ├── metadata.json │ │ └── top_level.txt │ ├── README.md │ ├── Werkzeug-0.11.dist-info/ │ │ ├── DESCRIPTION.rst │ │ ├── METADATA │ │ ├── RECORD │ │ ├── WHEEL │ │ ├── metadata.json │ │ └── top_level.txt │ ├── flask/ │ │ ├── __init__.py │ │ ├── _compat.py │ │ ├── app.py │ │ ├── blueprints.py │ │ ├── config.py │ │ ├── ctx.py │ │ ├── debughelpers.py │ │ ├── ext/ │ │ │ └── __init__.py │ │ ├── exthook.py │ │ ├── globals.py │ │ ├── helpers.py │ │ ├── json.py │ │ ├── logging.py │ │ ├── module.py │ │ ├── sessions.py │ │ ├── signals.py │ │ ├── templating.py │ │ ├── testing.py │ │ ├── testsuite/ │ │ │ ├── __init__.py │ │ │ ├── appctx.py │ │ │ ├── basic.py │ │ │ ├── blueprints.py │ │ │ ├── config.py │ │ │ ├── deprecations.py │ │ │ ├── examples.py │ │ │ ├── ext.py │ │ │ ├── helpers.py │ │ │ ├── regression.py │ │ │ ├── reqctx.py │ │ │ ├── signals.py │ │ │ ├── static/ │ │ │ │ └── index.html │ │ │ ├── subclassing.py │ │ │ ├── templates/ │ │ │ │ ├── _macro.html │ │ │ │ ├── context_template.html │ │ │ │ ├── escaping_template.html │ │ │ │ ├── mail.txt │ │ │ │ ├── nested/ │ │ │ │ │ └── nested.txt │ │ │ │ ├── simple_template.html │ │ │ │ ├── template_filter.html │ │ │ │ └── template_test.html │ │ │ ├── templating.py │ │ │ ├── test_apps/ │ │ │ │ ├── blueprintapp/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── apps/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── admin/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── static/ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ └── test.css │ │ │ │ │ │ │ └── test.txt │ │ │ │ │ │ └── templates/ │ │ │ │ │ │ └── admin/ │ │ │ │ │ │ └── index.html │ │ │ │ │ └── frontend/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── templates/ │ │ │ │ │ └── frontend/ │ │ │ │ │ └── index.html │ │ │ │ ├── config_module_app.py │ │ │ │ ├── config_package_app/ │ │ │ │ │ └── __init__.py │ │ │ │ ├── flask_broken/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── b.py │ │ │ │ ├── flask_newext_package/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── submodule.py │ │ │ │ ├── flask_newext_simple.py │ │ │ │ ├── flaskext/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── oldext_package/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ └── submodule.py │ │ │ │ │ └── oldext_simple.py │ │ │ │ ├── importerror.py │ │ │ │ ├── lib/ │ │ │ │ │ └── python2.5/ │ │ │ │ │ └── site-packages/ │ │ │ │ │ ├── SiteEgg.egg │ │ │ │ │ ├── site_app.py │ │ │ │ │ └── site_package/ │ │ │ │ │ └── __init__.py │ │ │ │ ├── main_app.py │ │ │ │ ├── moduleapp/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── apps/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── admin/ │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── static/ │ │ │ │ │ │ │ ├── css/ │ │ │ │ │ │ │ │ └── test.css │ │ │ │ │ │ │ └── test.txt │ │ │ │ │ │ └── templates/ │ │ │ │ │ │ └── index.html │ │ │ │ │ └── frontend/ │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── templates/ │ │ │ │ │ └── index.html │ │ │ │ ├── path/ │ │ │ │ │ └── installed_package/ │ │ │ │ │ └── __init__.py │ │ │ │ └── subdomaintestmodule/ │ │ │ │ ├── __init__.py │ │ │ │ └── static/ │ │ │ │ └── hello.txt │ │ │ ├── testing.py │ │ │ └── views.py │ │ ├── views.py │ │ └── wrappers.py │ ├── itsdangerous-0.24.dist-info/ │ │ ├── DESCRIPTION.rst │ │ ├── METADATA │ │ ├── RECORD │ │ ├── WHEEL │ │ ├── metadata.json │ │ └── top_level.txt │ ├── itsdangerous.py │ ├── jinja2/ │ │ ├── __init__.py │ │ ├── _compat.py │ │ ├── _stringdefs.py │ │ ├── bccache.py │ │ ├── compiler.py │ │ ├── constants.py │ │ ├── debug.py │ │ ├── defaults.py │ │ ├── environment.py │ │ ├── exceptions.py │ │ ├── ext.py │ │ ├── filters.py │ │ ├── lexer.py │ │ ├── loaders.py │ │ ├── meta.py │ │ ├── nodes.py │ │ ├── optimizer.py │ │ ├── parser.py │ │ ├── runtime.py │ │ ├── sandbox.py │ │ ├── tests.py │ │ ├── utils.py │ │ └── visitor.py │ ├── markupsafe/ │ │ ├── __init__.py │ │ ├── _compat.py │ │ ├── _constants.py │ │ ├── _native.py │ │ ├── _speedups.c │ │ └── tests.py │ └── werkzeug/ │ ├── __init__.py │ ├── _compat.py │ ├── _internal.py │ ├── _reloader.py │ ├── contrib/ │ │ ├── __init__.py │ │ ├── atom.py │ │ ├── cache.py │ │ ├── fixers.py │ │ ├── iterio.py │ │ ├── jsrouting.py │ │ ├── limiter.py │ │ ├── lint.py │ │ ├── profiler.py │ │ ├── securecookie.py │ │ ├── sessions.py │ │ ├── testtools.py │ │ └── wrappers.py │ ├── datastructures.py │ ├── debug/ │ │ ├── __init__.py │ │ ├── console.py │ │ ├── repr.py │ │ ├── shared/ │ │ │ ├── FONT_LICENSE │ │ │ ├── debugger.js │ │ │ ├── jquery.js │ │ │ └── style.css │ │ └── tbtools.py │ ├── exceptions.py │ ├── filesystem.py │ ├── formparser.py │ ├── http.py │ ├── local.py │ ├── posixemulation.py │ ├── routing.py │ ├── script.py │ ├── security.py │ ├── serving.py │ ├── test.py │ ├── testapp.py │ ├── urls.py │ ├── useragents.py │ ├── utils.py │ ├── wrappers.py │ └── wsgi.py ├── main.py └── requirements.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.pyc # don't include third-party dependencies. !lib/README.md .DS_Store ================================================ FILE: .playground ================================================ { "template_name" : "Flask web framework", "template_description" : "Skeleton app based on Flask microframework (http://flask.pocoo.org/)", "open_files": ["main.py"] } ================================================ FILE: CONTRIB.md ================================================ # How to become a contributor and submit your own code ## Contributor License Agreements We'd love to accept your sample apps and patches! Before we can take them, we have to jump a couple of legal hurdles. Please fill out either the individual or corporate Contributor License Agreement (CLA). * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html). * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html). Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to accept your pull requests. ## Contributing A Patch 1. Submit an issue describing your proposed change to the repo in question. 1. The repo owner will respond to your issue promptly. 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 1. Fork the desired repo, develop and test your code changes. 1. Ensure that your code adheres to the existing style in the sample to which you are contributing. Refer to the [Google Cloud Platform Samples Style Guide](https://github.com/GoogleCloudPlatform/Template/wiki/style.html) for the recommended coding standards for this organization. 1. Ensure that your code has an appropriate set of unit tests which all pass. 1. Submit a pull request. ## Contributing A New Sample App 1. Submit an issue to the GoogleCloudPlatform/Template repo describing your proposed sample app. 1. The Template repo owner will respond to your enhancement issue promptly. Instructional value is the top priority when evaluating new app proposals for this collection of repos. 1. If your proposal is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 1. Create your own repo for your app following this naming convention: * {product}-{app-name}-{language} * products: appengine, compute, storage, bigquery, prediction, cloudsql * example: appengine-guestbook-python * For multi-product apps, concatenate the primary products, like this: compute-appengine-demo-suite-python. * For multi-language apps, concatenate the primary languages like this: appengine-sockets-python-java-go. 1. Clone the README.md, CONTRIB.md and LICENSE files from the GoogleCloudPlatform/Template repo. 1. Ensure that your code adheres to the existing style in the sample to which you are contributing. Refer to the [Google Cloud Platform Samples Style Guide](https://github.com/GoogleCloudPlatform/Template/wiki/style.html) for the recommended coding standards for this organization. 1. Ensure that your code has an appropriate set of unit tests which all pass. 1. Submit a request to fork your repo in GoogleCloudPlatform organizationt via your proposal issue. ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ ![status: inactive](https://img.shields.io/badge/status-inactive-red.svg) This project is no longer actively developed or maintained. For new work on this check out [flask Hello World](https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/appengine/standard/flask/hello_world). ## Python Flask Skeleton for Google App Engine A skeleton for building Python applications on Google App Engine with the [Flask micro framework](http://flask.pocoo.org). See our other [Google Cloud Platform github repos](https://github.com/GoogleCloudPlatform) for sample applications and scaffolding for other python frameworks and use cases. ## Run Locally 1. Install the [App Engine Python SDK](https://developers.google.com/appengine/downloads). See the README file for directions. You'll need python 2.7 and [pip 1.4 or later](http://www.pip-installer.org/en/latest/installing.html) installed too. 2. Clone this repo with ``` git clone https://github.com/GoogleCloudPlatform/appengine-flask-skeleton.git ``` 3. Install dependencies in the project's lib directory. Note: App Engine can only import libraries from inside your project directory. ``` cd appengine-flask-skeleton pip install -r requirements.txt -t lib ``` 4. Run this project locally from the command line: ``` dev_appserver.py . ``` Visit the application [http://localhost:8080](http://localhost:8080) See [the development server documentation](https://developers.google.com/appengine/docs/python/tools/devserver) for options when running dev_appserver. ## Deploy To deploy the application: 1. Use the [Admin Console](https://appengine.google.com) to create a project/app id. (App id and project id are identical) 1. [Deploy the application](https://developers.google.com/appengine/docs/python/tools/uploadinganapp) with ``` appcfg.py update -A -V v1 . ``` If this isn't your first deployment, you will need to set the new version as the default version with ``` appcfg.py set_default_version -V v1 -A ``` 1. Congratulations! Your application is now live at your-app-id.appspot.com ## Next Steps This skeleton includes `TODO` markers to help you find basic areas you will want to customize. ### Relational Databases and Datastore To add persistence to your models, use [NDB](https://developers.google.com/appengine/docs/python/ndb/) for scale. Consider [CloudSQL](https://developers.google.com/appengine/docs/python/cloud-sql) if you need a relational database. ### Installing Libraries See the [Third party libraries](https://developers.google.com/appengine/docs/python/tools/libraries27) page for libraries that are already included in the SDK. To include SDK libraries, add them in your app.yaml file. Other than libraries included in the SDK, only pure python libraries may be added to an App Engine project. ### Feedback Star this repo if you found it useful. Use the github issue tracker to give feedback on this repo. ## Contributing changes See [CONTRIB.md](CONTRIB.md) ## Licensing See [LICENSE](LICENSE) ## Author Logan Henriquez and Johan Euphrosine ================================================ FILE: app.yaml ================================================ # This file specifies your Python application's runtime configuration # including URL routing, versions, static file uploads, etc. See # https://developers.google.com/appengine/docs/python/config/appconfig # for details. runtime: python27 api_version: 1 threadsafe: yes # Handlers define how to route requests to your application. handlers: # App Engine serves and caches static files contained in the listed directories # (and subdirectories). Uncomment and set the directory as needed. #- url: /client # static_dir: client # This handler tells app engine how to route requests to a WSGI application. # The script value is in the format . # where is a WSGI application object. - url: .* # This regex directs all routes to main.app script: main.app # Third party libraries that are included in the App Engine SDK must be listed # here if you want to use them. See # https://developers.google.com/appengine/docs/python/tools/libraries27 for # a list of libraries included in the SDK. Third party libs that are *not* part # of the App Engine SDK don't need to be listed here, instead add them to your # project directory, either as a git submodule or as a plain subdirectory. # TODO: List any other App Engine SDK libs you may need here. #libraries: #- name: jinja2 # version: latest ================================================ FILE: appengine_config.py ================================================ """ `appengine_config.py` is automatically loaded when Google App Engine starts a new instance of your application. This runs before any WSGI applications specified in app.yaml are loaded. """ from google.appengine.ext import vendor # Third-party libraries are stored in "lib", vendoring will make # sure that they are importable by the application. vendor.add('lib') ================================================ FILE: lib/Flask-0.10.dist-info/DESCRIPTION.rst ================================================ 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 `_ ================================================ FILE: lib/Flask-0.10.dist-info/METADATA ================================================ Metadata-Version: 2.0 Name: Flask Version: 0.10 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 :: 2.6 Classifier: Programming Language :: Python :: 2.7 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 `_ ================================================ FILE: lib/Flask-0.10.dist-info/RECORD ================================================ flask/__init__.py,sha256=Hmok7MXSW0QTF-6TCFPfRqpHlVq1zOihqSMnHfXysvo,1672 flask/_compat.py,sha256=ug9fCmzhMFE1ecCpZLvbHSTXluYCcLXt3_8SNwGNZyg,2164 flask/app.py,sha256=U7K6oLEhv59ZrIJEzfVfVcB33PYKRQQN2CYLalOaNSA,76786 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=qPIc18Pd2jj3EDJMan1BmkYxhJKYKpBw4oPp8Z6b2uo,7530 flask/logging.py,sha256=EkiNIJbQyeUb8nipAURO8CQJwC4BESjkM_snQIRCeIc,1398 flask/module.py,sha256=2J_pmW7jaFye1FtNTn5jfX-HxBqMc9EZzSLUXxiV-7c,1363 flask/sessions.py,sha256=X0yDRq4cpKluFlDupBDFAouQxJWP09sSES8pKnXpcPg,12882 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=EX66aNjBKOt5I8PWcpstzTCsy2O1M29kSDxAwLeySPg,42765 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=nSZ1xuJeOJWcK6_wSv_L3tl8OAe_zcaRT_IoPpZPcvg,21657 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/site_app.py,sha256=yObUTJgzGrSHwp-eLsE-bMbGmKLogUdE6bCn7jQPR6A,42 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_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.dist-info/DESCRIPTION.rst,sha256=YsWE_jM8p5TWeiY2cuesAHH5JUW95FFaHKvruzGCg5o,694 Flask-0.10.dist-info/METADATA,sha256=pqbqQzdvCFKHyFRIFyxq9hyctjcYvH9MGStkHlbfBqk,1557 Flask-0.10.dist-info/metadata.json,sha256=nWJBE8_HRpsHM1zLFJsfFrxuzec2njoS7UDgZMpCiFE,1011 Flask-0.10.dist-info/RECORD,, Flask-0.10.dist-info/top_level.txt,sha256=dvi65F6AeGWVU0TBpYiC04yM60-FX1gJFkK31IKQr5c,6 Flask-0.10.dist-info/WHEEL,sha256=54bVun1KfEBTJ68SHUmbxNPj80VxlQ0sHi4gZdGZXEY,92 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/module.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/apps/__init__.pyc,, flask/sessions.pyc,, flask/logging.pyc,, flask/testsuite/test_apps/path/installed_package/__init__.pyc,, flask/testsuite/test_apps/flask_broken/__init__.pyc,, flask/__init__.pyc,, flask/testsuite/config.pyc,, flask/testsuite/test_apps/importerror.pyc,, flask/testsuite/test_apps/flaskext/oldext_simple.pyc,, flask/testsuite/subclassing.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/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/ctx.pyc,, flask/testsuite/test_apps/moduleapp/apps/admin/__init__.pyc,, flask/testsuite/test_apps/moduleapp/__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/test_apps/moduleapp/apps/frontend/__init__.pyc,, flask/testsuite/views.pyc,, flask/signals.pyc,, flask/testsuite/test_apps/flask_newext_package/submodule.pyc,, flask/testsuite/basic.pyc,, flask/templating.pyc,, flask/testsuite/test_apps/blueprintapp/apps/admin/__init__.pyc,, flask/testsuite/reqctx.pyc,, flask/testsuite/ext.pyc,, flask/testsuite/test_apps/config_package_app/__init__.pyc,, ================================================ FILE: lib/Flask-0.10.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.24.0) Root-Is-Purelib: true Tag: py2-none-any ================================================ FILE: lib/Flask-0.10.dist-info/metadata.json ================================================ {"license": "BSD", "name": "Flask", "metadata_version": "2.0", "generator": "bdist_wheel (0.24.0)", "summary": "A microframework based on Werkzeug, Jinja2 and good intentions", "platform": "any", "run_requires": [{"requires": ["Werkzeug (>=0.7)", "Jinja2 (>=2.4)", "itsdangerous (>=0.21)"]}], "version": "0.10", "extensions": {"python.details": {"project_urls": {"Home": "http://github.com/mitsuhiko/flask/"}, "document_names": {"description": "DESCRIPTION.rst"}, "contacts": [{"role": "author", "email": "armin.ronacher@active-4.com", "name": "Armin Ronacher"}]}}, "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 :: 2.6", "Programming Language :: Python :: 2.7", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules"], "extras": []} ================================================ FILE: lib/Flask-0.10.dist-info/top_level.txt ================================================ flask ================================================ FILE: lib/Jinja2-2.8.dist-info/DESCRIPTION.rst ================================================ 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/ ================================================ FILE: lib/Jinja2-2.8.dist-info/METADATA ================================================ 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/ ================================================ FILE: lib/Jinja2-2.8.dist-info/RECORD ================================================ 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/_compat.pyc,, jinja2/sandbox.pyc,, jinja2/_stringdefs.pyc,, jinja2/bccache.pyc,, jinja2/runtime.pyc,, jinja2/utils.pyc,, jinja2/debug.pyc,, jinja2/parser.pyc,, jinja2/defaults.pyc,, jinja2/visitor.pyc,, jinja2/ext.pyc,, jinja2/lexer.pyc,, jinja2/nodes.pyc,, jinja2/environment.pyc,, jinja2/compiler.pyc,, jinja2/exceptions.pyc,, jinja2/__init__.pyc,, jinja2/meta.pyc,, jinja2/loaders.pyc,, jinja2/optimizer.pyc,, jinja2/filters.pyc,, jinja2/tests.pyc,, jinja2/constants.pyc,, ================================================ FILE: lib/Jinja2-2.8.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.24.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: lib/Jinja2-2.8.dist-info/entry_points.txt ================================================ [babel.extractors] jinja2 = jinja2.ext:babel_extract[i18n] ================================================ FILE: lib/Jinja2-2.8.dist-info/metadata.json ================================================ {"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"]} ================================================ FILE: lib/Jinja2-2.8.dist-info/top_level.txt ================================================ jinja2 ================================================ FILE: lib/MarkupSafe-0.23.dist-info/DESCRIPTION.rst ================================================ 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') ================================================ FILE: lib/MarkupSafe-0.23.dist-info/METADATA ================================================ 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') ================================================ FILE: lib/MarkupSafe-0.23.dist-info/RECORD ================================================ 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=5LwzbsIbi6XRYL1cFO-TEF5szplVD406i-FXsWCgcPU,26724 markupsafe/tests.py,sha256=RLI4eYI0ICNZwkoN638VHXf_fDu4d_jnvbGr22j58Ng,6107 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/metadata.json,sha256=jNrdilCdPfPmCPCQj9EVQSAebHgG8jCtlhqsPMggI4s,901 MarkupSafe-0.23.dist-info/RECORD,, MarkupSafe-0.23.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11 MarkupSafe-0.23.dist-info/WHEEL,sha256=xNbhRJkOYpM8X1K1ysQX8xjULvydXjcUxM96PNX_KQ8,109 markupsafe/_native.pyc,, markupsafe/_constants.pyc,, markupsafe/_compat.pyc,, markupsafe/tests.pyc,, markupsafe/__init__.pyc,, ================================================ FILE: lib/MarkupSafe-0.23.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.24.0) Root-Is-Purelib: false Tag: cp27-none-macosx_10_10_intel ================================================ FILE: lib/MarkupSafe-0.23.dist-info/metadata.json ================================================ {"summary": "Implements a XML/HTML/XHTML Markup safe string for Python", "metadata_version": "2.0", "license": "BSD", "extensions": {"python.details": {"project_urls": {"Home": "http://github.com/mitsuhiko/markupsafe"}, "contacts": [{"role": "author", "email": "armin.ronacher@active-4.com", "name": "Armin Ronacher"}], "document_names": {"description": "DESCRIPTION.rst"}}}, "generator": "bdist_wheel (0.24.0)", "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"], "version": "0.23", "name": "MarkupSafe"} ================================================ FILE: lib/MarkupSafe-0.23.dist-info/top_level.txt ================================================ markupsafe ================================================ FILE: lib/README.md ================================================ This directory contains third-party dependencies installed with `pip`. ================================================ FILE: lib/Werkzeug-0.11.dist-info/DESCRIPTION.rst ================================================ 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 ================================================ FILE: lib/Werkzeug-0.11.dist-info/METADATA ================================================ Metadata-Version: 2.0 Name: Werkzeug Version: 0.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 ================================================ FILE: lib/Werkzeug-0.11.dist-info/RECORD ================================================ Werkzeug-0.11.dist-info/DESCRIPTION.rst,sha256=5sTwZ_Sj5aeEN8mlcOdNJ_ng40HiGazGmILLyTMX8o0,1595 Werkzeug-0.11.dist-info/METADATA,sha256=QX9osuhRKD2M0jRKGyVmOASL5y3INKSLtA4d0GSpsbM,2597 Werkzeug-0.11.dist-info/RECORD,, Werkzeug-0.11.dist-info/WHEEL,sha256=GrqQvamwgBV4nLoJe0vhYRSWzWsx7xjlt74FT0SWYfE,110 Werkzeug-0.11.dist-info/metadata.json,sha256=3rlxBTLVZ6cqm8wuS4n6ZgpoywLEfrpXWVahLNaFoVM,1093 Werkzeug-0.11.dist-info/top_level.txt,sha256=QRyj2VjwJoQkrwjwFIOlB8Xg3r9un0NtqVHQF-15xaw,9 werkzeug/__init__.py,sha256=Nf_xs5zUQajNujPuiuiFWoGok3W9fmC-7BHJy8-2pok,6917 werkzeug/_compat.py,sha256=8c4U9o6A_TR9nKCcTbpZNxpqCXcXDVIbFawwKM2s92c,6311 werkzeug/_internal.py,sha256=IEScSoFtQ8KqFH_2ubdfscNAdQ2RIysyVupI5BR9W2U,13709 werkzeug/_reloader.py,sha256=glTJPAR6qz3hLYw7xsANeNlEvgEf_WeU2cTz66rUqK8,8548 werkzeug/datastructures.py,sha256=iQ4TqWXdHSXtL5srpP8t-6bEJEiKDkfiI8lHOl_A_kU,87447 werkzeug/exceptions.py,sha256=X7D6bNqLmXfftc-6kuifVGFaxngHbMm8QD4DSZ7K5vA,18609 werkzeug/filesystem.py,sha256=0_gjAftvnRBxoD6ZCssJDJztUjprsLC97eC_k4YRdXs,2174 werkzeug/formparser.py,sha256=ndLQxfmq-IeNUlee30WHfxq1YggzSO1l7QGeeFVr99M,21207 werkzeug/http.py,sha256=I4yzJHGnsaMW7kZQcWzNW9H7ijXT_iPR16jbN3jejVY,35031 werkzeug/local.py,sha256=vWF4ECvkbXoOWM4BThsU5qEzC2LwdiEn7WA-qEt8pvg,14123 werkzeug/posixemulation.py,sha256=xEF2Bxc-vUCPkiu4IbfWVd3LW7DROYAT-ExW6THqyzw,3519 werkzeug/routing.py,sha256=U6d5l9iRrntZXkhr-GFQUmz9KBM_YKSr1oVSB9Ppv5k,66260 werkzeug/script.py,sha256=DwaVDcXdaOTffdNvlBdLitxWXjKaRVT32VbhDtljFPY,11365 werkzeug/security.py,sha256=tuVc22OqoHV5K-TrYJmynCJJa12aUt9BQ3wR_vEPQ34,8971 werkzeug/serving.py,sha256=Jf2GLYlXLkVBShH4x3rHKdNBGNjT2pZHStSP0-1wF5Y,27228 werkzeug/test.py,sha256=nan0aDi3g5hyUzWCtaN3XL9HrbIsNNNgMNjwpfM6qMc,34152 werkzeug/testapp.py,sha256=3HQRW1sHZKXuAjCvFMet4KXtQG3loYTFnvn6LWt-4zI,9396 werkzeug/urls.py,sha256=xhJoL81fOOWH2W0MReJKW2-KoR0b3p4zYkcvqylw254,36634 werkzeug/useragents.py,sha256=uqpgPcJ5BfcCVh9nPIIl2r3duIrIuENmrbRqbAMmPDk,5418 werkzeug/utils.py,sha256=lkybtv_mq35zV1qhelvEcILTzrMUwZ9yon6E8XwapJE,22972 werkzeug/wrappers.py,sha256=lKYevpKD1-quk9Cop7bsFxt1eWJxU3h33HCnOI_YzSU,77011 werkzeug/wsgi.py,sha256=CP-hCwH8te4cFz1bzWJoITJ5j-7E4j55fBkmuyp8xvc,37881 werkzeug/contrib/__init__.py,sha256=f7PfttZhbrImqpr5Ezre8CXgwvcGUJK7zWNpO34WWrw,623 werkzeug/contrib/atom.py,sha256=rvijBrphjMzVObfuCR6ddu6aLwI_SiNiudu64OSTh4Q,15588 werkzeug/contrib/cache.py,sha256=4W2WCT9Hw6HEU8yME9GuU4Xf8e50r2K84ASMxhLb6tY,27983 werkzeug/contrib/fixers.py,sha256=MtN_YmENxoTsGvXGGERmtbQ62LaeFc5I2d1YifXNENA,10183 werkzeug/contrib/iterio.py,sha256=pTX36rYCKO_9IEoB5sIN5cFSYszI9zdx6YhquWovcPY,10814 werkzeug/contrib/jsrouting.py,sha256=QTmgeDoKXvNK02KzXgx9lr3cAH6fAzpwF5bBdPNvJPs,8564 werkzeug/contrib/limiter.py,sha256=iS8-ahPZ-JLRnmfIBzxpm7O_s3lPsiDMVWv7llAIDCI,1334 werkzeug/contrib/lint.py,sha256=UxVVvYwnKa5BqYJdgfAzNc2w834OKgguvN-wg8E1Dhc,12322 werkzeug/contrib/profiler.py,sha256=ISwCWvwVyGpDLRBRpLjo_qUWma6GXYBrTAco4PEQSHY,5151 werkzeug/contrib/securecookie.py,sha256=X-Ao_0NRDveW6K1Fhe4U42hHWBW8esCpA3VcBDpzWIk,12206 werkzeug/contrib/sessions.py,sha256=uAPcnyxaxEla-bUA13gKc3KK4mwSagdzbCZzyKl3PeE,12577 werkzeug/contrib/testtools.py,sha256=G9xN-qeihJlhExrIZMCahvQOIDxdL9NiX874jiiHFMs,2453 werkzeug/contrib/wrappers.py,sha256=Uv5FRO5OqKwOsNgkW2-FRcw0vUDe3uiaivjPNYWNfAk,10337 werkzeug/debug/__init__.py,sha256=GDFrgOvwQ5wXQ2q5EeVBKh6JUQS8zLFFkgY6UOWeKrs,13126 werkzeug/debug/console.py,sha256=B7uAu9Rk60siDnGlEt-A_q1ZR4zCtmxx5itg3X-BOxo,5599 werkzeug/debug/repr.py,sha256=NaoB89aHb0vuvdSWels-GWdeGDZp76uE4uSNZPX1jAM,9354 werkzeug/debug/tbtools.py,sha256=L5P5TkGEHc_Bc5duNosP6D4CNe7ieTo1oiPX8nKQdek,18402 werkzeug/debug/shared/FONT_LICENSE,sha256=LwAVEI1oYnvXiNMT9SnCH_TaLCxCpeHziDrMg0gPkAI,4673 werkzeug/debug/shared/console.png,sha256=bxax6RXXlvOij_KeqvSNX0ojJf83YbnZ7my-3Gx9w2A,507 werkzeug/debug/shared/debugger.js,sha256=PEMBoNuD6fUaNou8Km_ZvVmFcIA3z3k3jSEMWLW-cA0,6187 werkzeug/debug/shared/jquery.js,sha256=7LkWEzqTdpEfELxcZZlS6wAx5Ff13zZ83lYO2_ujj7g,95957 werkzeug/debug/shared/less.png,sha256=-4-kNRaXJSONVLahrQKUxMwXGm9R4OnZ9SxDGpHlIR4,191 werkzeug/debug/shared/more.png,sha256=GngN7CioHQoV58rH6ojnkYi8c_qED2Aka5FO5UXrReY,200 werkzeug/debug/shared/source.png,sha256=RoGcBTE4CyCB85GBuDGTFlAnUqxwTBiIfDqW15EpnUQ,818 werkzeug/debug/shared/style.css,sha256=7x1s8olZO1XHalqD4M9MWn9vRqQkA635S9_6zRoe220,6231 werkzeug/debug/shared/ubuntu.ttf,sha256=1eaHFyepmy4FyDvjLVzpITrGEBu_CZYY94jE0nED1c0,70220 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/datastructures.pyc,, werkzeug/__init__.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/test.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/testapp.pyc,, werkzeug/debug/repr.pyc,, ================================================ FILE: lib/Werkzeug-0.11.dist-info/WHEEL ================================================ Wheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any ================================================ FILE: lib/Werkzeug-0.11.dist-info/metadata.json ================================================ {"generator": "bdist_wheel (0.26.0)", "summary": "The Swiss Army knife of Python web development", "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"], "extensions": {"python.details": {"project_urls": {"Home": "http://werkzeug.pocoo.org/"}, "contacts": [{"email": "armin.ronacher@active-4.com", "name": "Armin Ronacher", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}}}, "license": "BSD", "metadata_version": "2.0", "name": "Werkzeug", "platform": "any", "version": "0.11"} ================================================ FILE: lib/Werkzeug-0.11.dist-info/top_level.txt ================================================ werkzeug ================================================ FILE: lib/flask/__init__.py ================================================ # -*- 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' # 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 ================================================ FILE: lib/flask/_compat.py ================================================ # -*- 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, {}) ================================================ FILE: lib/flask/app.py ================================================ # -*- 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 is not 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, ) ================================================ FILE: lib/flask/blueprints.py ================================================ # -*- 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 ================================================ FILE: lib/flask/config.py ================================================ # -*- 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)) ================================================ FILE: lib/flask/ctx.py ================================================ # -*- 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, ) ================================================ FILE: lib/flask/debughelpers.py ================================================ # -*- 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 ================================================ FILE: lib/flask/ext/__init__.py ================================================ # -*- 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 ================================================ FILE: lib/flask/exthook.py ================================================ # -*- 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 ================================================ FILE: lib/flask/globals.py ================================================ # -*- 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')) ================================================ FILE: lib/flask/helpers.py ================================================ # -*- 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) ================================================ FILE: lib/flask/json.py ================================================ # -*- 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 ================================================ FILE: lib/jinja2/defaults.py ================================================ # -*- 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()) ================================================ FILE: lib/jinja2/environment.py ================================================ # -*- 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 = '