quick_tour - "Logging" updates for cookiecutter
- fix line numbering
- add new src files that were never included
16 files added
1 files modified
| | |
| | | development we might need to collect some output. In production we might need |
| | | to detect situations when other people use the site. We need *logging*. |
| | | |
| | | Fortunately Pyramid uses the normal Python approach to logging. The scaffold |
| | | generated in your ``development.ini`` has a number of lines that configure the |
| | | Fortunately Pyramid uses the normal Python approach to logging. The ``development.ini`` file for your project has a number of lines that configure the |
| | | logging for you to some reasonable defaults. You then see messages sent by |
| | | Pyramid (for example, when a new request comes in). |
| | | |
| | | Maybe you would like to log messages in your code? In your Python module, |
| | | import and set up the logging: |
| | | import and set up the logging in your ``views.py``: |
| | | |
| | | .. literalinclude:: quick_tour/package/hello_world/views.py |
| | | .. literalinclude:: quick_tour/logging/hello_world/views.py |
| | | :language: python |
| | | :linenos: |
| | | :lineno-start: 3 |
| | | :lineno-match: |
| | | :lines: 3-4 |
| | | |
| | | You can now, in your code, log messages: |
| | | |
| | | .. literalinclude:: quick_tour/package/hello_world/views.py |
| | | .. literalinclude:: quick_tour/logging/hello_world/views.py |
| | | :language: python |
| | | :linenos: |
| | | :lineno-start: 9 |
| | | :lines: 9-10 |
| | | :lineno-match: |
| | | :lines: 7-8 |
| | | :emphasize-lines: 2 |
| | | |
| | | This will log ``Some Message`` at a ``debug`` log level to the |
| | | This will log ``Some Message`` at a ``DEBUG`` log level to the |
| | | application-configured logger in your ``development.ini``. What controls that? |
| | | These emphasized sections in the configuration file: |
| | | |
| | | .. literalinclude:: quick_tour/package/development.ini |
| | | .. literalinclude:: quick_tour/logging/development.ini |
| | | :language: ini |
| | | :linenos: |
| | | :lineno-start: 36 |
| | | :lines: 36-52 |
| | | :lineno-match: |
| | | :lines: 34-50 |
| | | :emphasize-lines: 1-2,14-17 |
| | | |
| | | Our application, a package named ``hello_world``, is set up as a logger and |
| | |
| | | |
| | | .. code-block:: text |
| | | |
| | | 2016-01-18 13:55:55,040 DEBUG [hello_world.views:10][waitress] Some Message |
| | | 2016-12-25 03:03:57,059 DEBUG [hello_world.views:8][waitress] Some Message |
| | | |
| | | .. seealso:: See also: |
| | | :ref:`Quick Tutorial Logging <qtut_logging>` and :ref:`logging_chapter`. |
New file |
| | |
| | | [run] |
| | | source = hello_world |
| | | omit = hello_world/test* |
New file |
| | |
| | | 0.0 |
| | | --- |
| | | |
| | | - Initial version. |
New file |
| | |
| | | include *.txt *.ini *.cfg *.rst |
| | | recursive-include hello_world *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2 |
New file |
| | |
| | | hello_world |
| | | =============================== |
| | | |
| | | Getting Started |
| | | --------------- |
| | | |
| | | - Change directory into your newly created project. |
| | | |
| | | cd hello_world |
| | | |
| | | - Create a Python virtual environment. |
| | | |
| | | python3 -m venv env |
| | | |
| | | - Upgrade packaging tools. |
| | | |
| | | env/bin/pip install --upgrade pip setuptools |
| | | |
| | | - Install the project in editable mode with its testing requirements. |
| | | |
| | | env/bin/pip install -e ".[testing]" |
| | | |
| | | - Run your project's tests. |
| | | |
| | | env/bin/pytest |
| | | |
| | | - Run your project. |
| | | |
| | | env/bin/pserve development.ini |
New file |
| | |
| | | ### |
| | | # app configuration |
| | | # http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html |
| | | ### |
| | | |
| | | [app:main] |
| | | use = egg:hello_world |
| | | |
| | | pyramid.reload_templates = true |
| | | pyramid.debug_authorization = false |
| | | pyramid.debug_notfound = false |
| | | pyramid.debug_routematch = false |
| | | pyramid.default_locale_name = en |
| | | pyramid.includes = |
| | | pyramid_debugtoolbar |
| | | |
| | | # By default, the toolbar only appears for clients from IP addresses |
| | | # '127.0.0.1' and '::1'. |
| | | # debugtoolbar.hosts = 127.0.0.1 ::1 |
| | | |
| | | ### |
| | | # wsgi server configuration |
| | | ### |
| | | |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | listen = 127.0.0.1:6543 [::1]:6543 |
| | | |
| | | ### |
| | | # logging configuration |
| | | # http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html |
| | | ### |
| | | |
| | | [loggers] |
| | | keys = root, hello_world |
| | | |
| | | [handlers] |
| | | keys = console |
| | | |
| | | [formatters] |
| | | keys = generic |
| | | |
| | | [logger_root] |
| | | level = INFO |
| | | handlers = console |
| | | |
| | | [logger_hello_world] |
| | | level = DEBUG |
| | | handlers = |
| | | qualname = hello_world |
| | | |
| | | [handler_console] |
| | | class = StreamHandler |
| | | args = (sys.stderr,) |
| | | level = NOTSET |
| | | formatter = generic |
| | | |
| | | [formatter_generic] |
| | | format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s |
New file |
| | |
| | | from pyramid.config import Configurator |
| | | |
| | | |
| | | def main(global_config, **settings): |
| | | """ This function returns a Pyramid WSGI application. |
| | | """ |
| | | config = Configurator(settings=settings) |
| | | config.include('pyramid_jinja2') |
| | | config.add_static_view('static', 'static', cache_max_age=3600) |
| | | config.add_route('home', '/') |
| | | config.scan() |
| | | return config.make_wsgi_app() |
New file |
| | |
| | | @import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700); |
| | | body { |
| | | font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; |
| | | font-weight: 300; |
| | | color: #ffffff; |
| | | background: #bc2131; |
| | | } |
| | | h1, |
| | | h2, |
| | | h3, |
| | | h4, |
| | | h5, |
| | | h6 { |
| | | font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; |
| | | font-weight: 300; |
| | | } |
| | | p { |
| | | font-weight: 300; |
| | | } |
| | | .font-normal { |
| | | font-weight: 400; |
| | | } |
| | | .font-semi-bold { |
| | | font-weight: 600; |
| | | } |
| | | .font-bold { |
| | | font-weight: 700; |
| | | } |
| | | .starter-template { |
| | | margin-top: 250px; |
| | | } |
| | | .starter-template .content { |
| | | margin-left: 10px; |
| | | } |
| | | .starter-template .content h1 { |
| | | margin-top: 10px; |
| | | font-size: 60px; |
| | | } |
| | | .starter-template .content h1 .smaller { |
| | | font-size: 40px; |
| | | color: #f2b7bd; |
| | | } |
| | | .starter-template .content .lead { |
| | | font-size: 25px; |
| | | color: #f2b7bd; |
| | | } |
| | | .starter-template .content .lead .font-normal { |
| | | color: #ffffff; |
| | | } |
| | | .starter-template .links { |
| | | float: right; |
| | | right: 0; |
| | | margin-top: 125px; |
| | | } |
| | | .starter-template .links ul { |
| | | display: block; |
| | | padding: 0; |
| | | margin: 0; |
| | | } |
| | | .starter-template .links ul li { |
| | | list-style: none; |
| | | display: inline; |
| | | margin: 0 10px; |
| | | } |
| | | .starter-template .links ul li:first-child { |
| | | margin-left: 0; |
| | | } |
| | | .starter-template .links ul li:last-child { |
| | | margin-right: 0; |
| | | } |
| | | .starter-template .links ul li.current-version { |
| | | color: #f2b7bd; |
| | | font-weight: 400; |
| | | } |
| | | .starter-template .links ul li a, a { |
| | | color: #f2b7bd; |
| | | text-decoration: underline; |
| | | } |
| | | .starter-template .links ul li a:hover, a:hover { |
| | | color: #ffffff; |
| | | text-decoration: underline; |
| | | } |
| | | .starter-template .links ul li .icon-muted { |
| | | color: #eb8b95; |
| | | margin-right: 5px; |
| | | } |
| | | .starter-template .links ul li:hover .icon-muted { |
| | | color: #ffffff; |
| | | } |
| | | .starter-template .copyright { |
| | | margin-top: 10px; |
| | | font-size: 0.9em; |
| | | color: #f2b7bd; |
| | | text-transform: lowercase; |
| | | float: right; |
| | | right: 0; |
| | | } |
| | | @media (max-width: 1199px) { |
| | | .starter-template .content h1 { |
| | | font-size: 45px; |
| | | } |
| | | .starter-template .content h1 .smaller { |
| | | font-size: 30px; |
| | | } |
| | | .starter-template .content .lead { |
| | | font-size: 20px; |
| | | } |
| | | } |
| | | @media (max-width: 991px) { |
| | | .starter-template { |
| | | margin-top: 0; |
| | | } |
| | | .starter-template .logo { |
| | | margin: 40px auto; |
| | | } |
| | | .starter-template .content { |
| | | margin-left: 0; |
| | | text-align: center; |
| | | } |
| | | .starter-template .content h1 { |
| | | margin-bottom: 20px; |
| | | } |
| | | .starter-template .links { |
| | | float: none; |
| | | text-align: center; |
| | | margin-top: 60px; |
| | | } |
| | | .starter-template .copyright { |
| | | float: none; |
| | | text-align: center; |
| | | } |
| | | } |
| | | @media (max-width: 767px) { |
| | | .starter-template .content h1 .smaller { |
| | | font-size: 25px; |
| | | display: block; |
| | | } |
| | | .starter-template .content .lead { |
| | | font-size: 16px; |
| | | } |
| | | .starter-template .links { |
| | | margin-top: 40px; |
| | | } |
| | | .starter-template .links ul li { |
| | | display: block; |
| | | margin: 0; |
| | | } |
| | | .starter-template .links ul li .icon-muted { |
| | | display: none; |
| | | } |
| | | .starter-template .copyright { |
| | | margin-top: 20px; |
| | | } |
| | | } |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="{{request.locale_name}}"> |
| | | <head> |
| | | <meta charset="utf-8"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| | | <meta name="description" content="pyramid web application"> |
| | | <meta name="author" content="Pylons Project"> |
| | | <link rel="shortcut icon" href="{{request.static_url('hello_world:static/pyramid-16x16.png')}}"> |
| | | |
| | | <title>Cookiecutter Starter project for the Pyramid Web Framework</title> |
| | | |
| | | <!-- Bootstrap core CSS --> |
| | | <link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet"> |
| | | |
| | | <!-- Custom styles for this scaffold --> |
| | | <link href="{{request.static_url('hello_world:static/theme.css')}}" rel="stylesheet"> |
| | | |
| | | <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> |
| | | <!--[if lt IE 9]> |
| | | <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> |
| | | <script src="//oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script> |
| | | <![endif]--> |
| | | </head> |
| | | |
| | | <body> |
| | | |
| | | <div class="starter-template"> |
| | | <div class="container"> |
| | | <div class="row"> |
| | | <div class="col-md-2"> |
| | | <img class="logo img-responsive" src="{{request.static_url('hello_world:static/pyramid.png') }}" alt="pyramid web framework"> |
| | | </div> |
| | | <div class="col-md-10"> |
| | | {% block content %} |
| | | <p>No content</p> |
| | | {% endblock content %} |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
| | | <div class="links"> |
| | | <ul> |
| | | <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li> |
| | | <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li> |
| | | <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li> |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
| | | <div class="copyright"> |
| | | Copyright © Pylons Project |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <!-- Bootstrap core JavaScript |
| | | ================================================== --> |
| | | <!-- Placed at the end of the document so the pages load faster --> |
| | | <script src="//oss.maxcdn.com/libs/jquery/1.10.2/jquery.min.js"></script> |
| | | <script src="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/js/bootstrap.min.js"></script> |
| | | </body> |
| | | </html> |
New file |
| | |
| | | {% extends "layout.jinja2" %} |
| | | |
| | | {% block content %} |
| | | <div class="content"> |
| | | <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1> |
| | | <p class="lead">Welcome to <span class="font-normal">hello_world</span>, a Pyramid application generated by<br><span class="font-normal">Cookiecutter</span>.</p> |
| | | </div> |
| | | {% endblock content %} |
New file |
| | |
| | | import unittest |
| | | |
| | | from pyramid import testing |
| | | |
| | | |
| | | class ViewTests(unittest.TestCase): |
| | | def setUp(self): |
| | | self.config = testing.setUp() |
| | | |
| | | def tearDown(self): |
| | | testing.tearDown() |
| | | |
| | | def test_my_view(self): |
| | | from .views import my_view |
| | | request = testing.DummyRequest() |
| | | info = my_view(request) |
| | | self.assertEqual(info['project'], 'hello_world') |
| | | |
| | | |
| | | class FunctionalTests(unittest.TestCase): |
| | | def setUp(self): |
| | | from hello_world import main |
| | | app = main({}) |
| | | from webtest import TestApp |
| | | self.testapp = TestApp(app) |
| | | |
| | | def test_root(self): |
| | | res = self.testapp.get('/', status=200) |
| | | self.assertTrue(b'Pyramid' in res.body) |
New file |
| | |
| | | from pyramid.view import view_config |
| | | |
| | | import logging |
| | | log = logging.getLogger(__name__) |
| | | |
| | | @view_config(route_name='home', renderer='templates/mytemplate.jinja2') |
| | | def my_view(request): |
| | | log.debug('Some Message') |
| | | return {'project': 'hello_world'} |
New file |
| | |
| | | ### |
| | | # app configuration |
| | | # http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html |
| | | ### |
| | | |
| | | [app:main] |
| | | use = egg:hello_world |
| | | |
| | | pyramid.reload_templates = false |
| | | pyramid.debug_authorization = false |
| | | pyramid.debug_notfound = false |
| | | pyramid.debug_routematch = false |
| | | pyramid.default_locale_name = en |
| | | |
| | | ### |
| | | # wsgi server configuration |
| | | ### |
| | | |
| | | [server:main] |
| | | use = egg:waitress#main |
| | | listen = *:6543 |
| | | |
| | | ### |
| | | # logging configuration |
| | | # http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html |
| | | ### |
| | | |
| | | [loggers] |
| | | keys = root, hello_world |
| | | |
| | | [handlers] |
| | | keys = console |
| | | |
| | | [formatters] |
| | | keys = generic |
| | | |
| | | [logger_root] |
| | | level = WARN |
| | | handlers = console |
| | | |
| | | [logger_hello_world] |
| | | level = WARN |
| | | handlers = |
| | | qualname = hello_world |
| | | |
| | | [handler_console] |
| | | class = StreamHandler |
| | | args = (sys.stderr,) |
| | | level = NOTSET |
| | | formatter = generic |
| | | |
| | | [formatter_generic] |
| | | format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s |
New file |
| | |
| | | [pytest] |
| | | testpaths = hello_world |
| | | python_files = *.py |
New file |
| | |
| | | import os |
| | | |
| | | from setuptools import setup, find_packages |
| | | |
| | | here = os.path.abspath(os.path.dirname(__file__)) |
| | | with open(os.path.join(here, 'README.txt')) as f: |
| | | README = f.read() |
| | | with open(os.path.join(here, 'CHANGES.txt')) as f: |
| | | CHANGES = f.read() |
| | | |
| | | requires = [ |
| | | 'pyramid', |
| | | 'pyramid_jinja2', |
| | | 'pyramid_debugtoolbar', |
| | | 'waitress', |
| | | ] |
| | | |
| | | tests_require = [ |
| | | 'WebTest >= 1.3.1', # py3 compat |
| | | 'pytest', |
| | | 'pytest-cov', |
| | | ] |
| | | |
| | | setup( |
| | | name='hello_world', |
| | | version='0.0', |
| | | description='hello_world', |
| | | long_description=README + '\n\n' + CHANGES, |
| | | classifiers=[ |
| | | 'Programming Language :: Python', |
| | | 'Framework :: Pyramid', |
| | | 'Topic :: Internet :: WWW/HTTP', |
| | | 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application', |
| | | ], |
| | | author='', |
| | | author_email='', |
| | | url='', |
| | | keywords='web pyramid pylons', |
| | | packages=find_packages(), |
| | | include_package_data=True, |
| | | zip_safe=False, |
| | | extras_require={ |
| | | 'testing': tests_require, |
| | | }, |
| | | install_requires=requires, |
| | | entry_points={ |
| | | 'paste.app_factory': [ |
| | | 'main = hello_world:main', |
| | | ], |
| | | }, |
| | | ) |