diff options
| author | Chris McDonough <chrism@plope.com> | 2012-11-20 22:47:52 -0500 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2012-11-20 22:47:52 -0500 |
| commit | c6a575052ae14e515c288e77a452440030c1cdcd (patch) | |
| tree | 7bf6dc6f2b929e5a206aae6d751b0cda5d96aefd | |
| parent | 8f4fcc47c9405f20cfed3a40931f12534b3b7193 (diff) | |
| parent | b5e4443dd28f3d4ed6e767e06d658838575d159e (diff) | |
| download | pyramid-c6a575052ae14e515c288e77a452440030c1cdcd.tar.gz pyramid-c6a575052ae14e515c288e77a452440030c1cdcd.tar.bz2 pyramid-c6a575052ae14e515c288e77a452440030c1cdcd.zip | |
Merge branch 'master' into sontek-fix_commands
56 files changed, 649 insertions, 172 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 16e3d8586..51266d15f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -4,9 +4,35 @@ Next release Features -------- +- Small microspeed enhancement which anticipates that a + ``pyramid.response.Response`` object is likely to be returned from a view. + Some code is shortcut if the class of the object returned by a view is this + class. A similar microoptimization was done to + ``pyramid.request.Request.is_response``. + +Bug Fixes +--------- + +- A failure when trying to locate the attribute ``__text__`` on route and view + predicates existed when the ``debug_routematch`` setting was true or when the + ``pviews`` command was used. See https://github.com/Pylons/pyramid/pull/727 + +Documentation +------------- + +- Sync up tutorial source files with the files that are rendered by the + scaffold that each uses. + +1.4a4 (2012-11-14) +================== + +Features +-------- + - ``pyramid.authentication.AuthTktAuthenticationPolicy`` has been updated to support newer hashing algorithms such as ``sha512``. Existing applications - should consider updating if possible. + should consider updating if possible for improved security over the default + md5 hashing. - Added an ``effective_principals`` route and view predicate. @@ -21,18 +47,11 @@ Features - Slightly better debug logging from ``pyramid.authentication.RepozeWho1AuthenticationPolicy``. -- ``pyramid.security.view_execution_permitted`` used to return `True` if no +- ``pyramid.security.view_execution_permitted`` used to return ``True`` if no view could be found. It now raises a ``TypeError`` exception in that case, as it doesn't make sense to assert that a nonexistent view is execution-permitted. See https://github.com/Pylons/pyramid/issues/299. -- Get rid of shady monkeypatching of ``pyramid.request.Request`` and - ``pyramid.response.Response`` done within the ``__init__.py`` of Pyramid. - Webob no longer relies on this being done. Instead, the ResponseClass - attribute of the Pyramid Request class is assigned to the Pyramid response - class; that's enough to satisfy WebOb and behave as it did before with the - monkeypatching. - - Allow a ``_depth`` argument to ``pyramid.view.view_config``, which will permit limited composition reuse of the decorator by other software that wants to provide custom decorators that are much like view_config. @@ -61,18 +80,26 @@ Bug Fixes ``physical_path`` predicate implementations; instead of raising an exception, return False. -- :func:`pyramid.view.render_view` was not functioning properly under - Python 3.x due to a byte/unicode discrepancy. See +- ``pyramid.view.render_view`` was not functioning properly under Python 3.x + due to a byte/unicode discrepancy. See http://github.com/Pylons/pyramid/issues/721 Deprecations ------------ -- ``pyramid.authentication.AuthTktAuthenticationPolicy`` will emit a warning - if an application is using the policy without explicitly setting the - ``hashalg``. This is because the default is "md5" which is considered - insecure. If you really want "md5" then you must specify it explicitly to - get rid of the warning. +- ``pyramid.authentication.AuthTktAuthenticationPolicy`` will emit a warning if + an application is using the policy without explicitly passing a ``hashalg`` + argument. This is because the default is "md5" which is considered + theoretically subject to collision attacks. If you really want "md5" then you + must specify it explicitly to get rid of the warning. + +Documentation +------------- + +- All of the tutorials that use + ``pyramid.authentication.AuthTktAuthenticationPolicy`` now explicitly pass + ``sha512`` as a ``hashalg`` argument. + Internals --------- @@ -85,6 +112,13 @@ Internals because that package should never be imported from non-Pyramid code. TopologicalSorter is still not an API, but may become one. +- Get rid of shady monkeypatching of ``pyramid.request.Request`` and + ``pyramid.response.Response`` done within the ``__init__.py`` of Pyramid. + Webob no longer relies on this being done. Instead, the ResponseClass + attribute of the Pyramid Request class is assigned to the Pyramid response + class; that's enough to satisfy WebOb and behave as it did before with the + monkeypatching. + 1.4a3 (2012-10-26) ================== diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 34d904d0f..971c172f8 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -190,3 +190,5 @@ Contributors - David Gay, 2012/09/16 - Robert Jackiewicz, 2012/11/12 + +- John Anderson, 2012/11/14 diff --git a/docs/conf.py b/docs/conf.py index 9bda4c798..5e17de18a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -81,7 +81,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year # other places throughout the built documents. # # The short X.Y version. -version = '1.4a3' +version = '1.4a4' # The full version, including alpha/beta/rc tags. release = version diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst index f6050f391..033dcb28c 100644 --- a/docs/tutorials/wiki/basiclayout.rst +++ b/docs/tutorials/wiki/basiclayout.rst @@ -165,7 +165,7 @@ Configuration in ``development.ini`` The ``development.ini`` (in the tutorial :term:`project` directory, as opposed to the tutorial :term:`package` directory) looks like this: -.. literalinclude:: src/views/development.ini +.. literalinclude:: src/basiclayout/development.ini :language: ini Note the existence of an ``[app:main]`` section which specifies our WSGI diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini index 996caa741..72bd22e54 100644 --- a/docs/tutorials/wiki/src/authorization/development.ini +++ b/docs/tutorials/wiki/src/authorization/development.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -13,15 +19,26 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] -keys = root +keys = root, tutorial [handlers] keys = console @@ -33,6 +50,11 @@ keys = generic level = INFO handlers = console +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + [handler_console] class = StreamHandler args = (sys.stderr,) @@ -41,5 +63,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/authorization/production.ini b/docs/tutorials/wiki/src/authorization/production.ini index ca8107802..d9bf27c42 100644 --- a/docs/tutorials/wiki/src/authorization/production.ini +++ b/docs/tutorials/wiki/src/authorization/production.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = false pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -12,12 +18,19 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +### +# wsgi server configuration +### + [server:main] use = egg:waitress#main host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial @@ -45,5 +58,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py index 31c51dbcf..ac8cdf2d5 100644 --- a/docs/tutorials/wiki/src/authorization/setup.py +++ b/docs/tutorials/wiki/src/authorization/setup.py @@ -21,9 +21,8 @@ setup(name='tutorial', description='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ - "Intended Audience :: Developers", - "Framework :: Pylons", "Programming Language :: Python", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -34,8 +33,8 @@ setup(name='tutorial', packages=find_packages(), include_package_data=True, zip_safe=False, - install_requires=requires, - tests_require=requires, + install_requires = requires, + tests_require= requires, test_suite="tutorial", entry_points = """\ [paste.app_factory] diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt index 3597c679b..84824f605 100644 --- a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt @@ -6,9 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="/static/favicon.ico" /> + <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> - <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="/static/ie6.css" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -41,7 +41,7 @@ <h2>Pyramid links</h2> <ul class="links"> <li> - <a href="http://pylonsproject.org">Pylons Website</a> + <a href="http://pylonsproject.org/">Pylons Website</a> </li> <li> <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> @@ -70,7 +70,7 @@ </div> </div> <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> </div> </body> </html> diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini index f637ebaa6..72bd22e54 100644 --- a/docs/tutorials/wiki/src/basiclayout/development.ini +++ b/docs/tutorials/wiki/src/basiclayout/development.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -13,15 +19,26 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] -keys = root +keys = root, tutorial [handlers] keys = console @@ -33,6 +50,11 @@ keys = generic level = INFO handlers = console +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + [handler_console] class = StreamHandler args = (sys.stderr,) @@ -40,6 +62,4 @@ level = NOTSET formatter = generic [formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s - -# End logging configuration +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s diff --git a/docs/tutorials/wiki/src/basiclayout/production.ini b/docs/tutorials/wiki/src/basiclayout/production.ini index ca8107802..d9bf27c42 100644 --- a/docs/tutorials/wiki/src/basiclayout/production.ini +++ b/docs/tutorials/wiki/src/basiclayout/production.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = false pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -12,12 +18,19 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +### +# wsgi server configuration +### + [server:main] use = egg:waitress#main host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial @@ -45,5 +58,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py index 43600e239..c4a9067b6 100644 --- a/docs/tutorials/wiki/src/basiclayout/setup.py +++ b/docs/tutorials/wiki/src/basiclayout/setup.py @@ -21,7 +21,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt index 557e071ed..84824f605 100644 --- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt @@ -6,9 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="/static/favicon.ico" /> + <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> - <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="/static/ie6.css" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -70,7 +70,7 @@ </div> </div> <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> </div> </body> </html> diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini index 996caa741..72bd22e54 100644 --- a/docs/tutorials/wiki/src/models/development.ini +++ b/docs/tutorials/wiki/src/models/development.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -13,15 +19,26 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] -keys = root +keys = root, tutorial [handlers] keys = console @@ -33,6 +50,11 @@ keys = generic level = INFO handlers = console +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + [handler_console] class = StreamHandler args = (sys.stderr,) @@ -41,5 +63,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/models/production.ini b/docs/tutorials/wiki/src/models/production.ini index ca8107802..d9bf27c42 100644 --- a/docs/tutorials/wiki/src/models/production.ini +++ b/docs/tutorials/wiki/src/models/production.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = false pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -12,12 +18,19 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +### +# wsgi server configuration +### + [server:main] use = egg:waitress#main host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial @@ -45,5 +58,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py index 43600e239..c4a9067b6 100644 --- a/docs/tutorials/wiki/src/models/setup.py +++ b/docs/tutorials/wiki/src/models/setup.py @@ -21,7 +21,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt index 3597c679b..84824f605 100644 --- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt @@ -6,9 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="/static/favicon.ico" /> + <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> - <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="/static/ie6.css" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -41,7 +41,7 @@ <h2>Pyramid links</h2> <ul class="links"> <li> - <a href="http://pylonsproject.org">Pylons Website</a> + <a href="http://pylonsproject.org/">Pylons Website</a> </li> <li> <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> @@ -70,7 +70,7 @@ </div> </div> <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> </div> </body> </html> diff --git a/docs/tutorials/wiki/src/tests/development.ini b/docs/tutorials/wiki/src/tests/development.ini index 996caa741..72bd22e54 100644 --- a/docs/tutorials/wiki/src/tests/development.ini +++ b/docs/tutorials/wiki/src/tests/development.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -13,15 +19,26 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] -keys = root +keys = root, tutorial [handlers] keys = console @@ -33,6 +50,11 @@ keys = generic level = INFO handlers = console +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + [handler_console] class = StreamHandler args = (sys.stderr,) @@ -41,5 +63,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/tests/production.ini b/docs/tutorials/wiki/src/tests/production.ini index ca8107802..d9bf27c42 100644 --- a/docs/tutorials/wiki/src/tests/production.ini +++ b/docs/tutorials/wiki/src/tests/production.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = false pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -12,12 +18,19 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +### +# wsgi server configuration +### + [server:main] use = egg:waitress#main host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial @@ -45,5 +58,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py index a7ad7317c..b7e0a8935 100644 --- a/docs/tutorials/wiki/src/tests/setup.py +++ b/docs/tutorials/wiki/src/tests/setup.py @@ -22,9 +22,8 @@ setup(name='tutorial', description='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ - "Intended Audience :: Developers", - "Framework :: Pylons", "Programming Language :: Python", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -35,8 +34,8 @@ setup(name='tutorial', packages=find_packages(), include_package_data=True, zip_safe=False, - install_requires=requires, - tests_require=requires, + install_requires = requires, + tests_require= requires, test_suite="tutorial", entry_points = """\ [paste.app_factory] diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt index 3597c679b..84824f605 100644 --- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt @@ -6,9 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="/static/favicon.ico" /> + <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> - <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="/static/ie6.css" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -41,7 +41,7 @@ <h2>Pyramid links</h2> <ul class="links"> <li> - <a href="http://pylonsproject.org">Pylons Website</a> + <a href="http://pylonsproject.org/">Pylons Website</a> </li> <li> <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> @@ -70,7 +70,7 @@ </div> </div> <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> </div> </body> </html> diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini index f637ebaa6..72bd22e54 100644 --- a/docs/tutorials/wiki/src/views/development.ini +++ b/docs/tutorials/wiki/src/views/development.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -13,15 +19,26 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] -keys = root +keys = root, tutorial [handlers] keys = console @@ -33,6 +50,11 @@ keys = generic level = INFO handlers = console +[logger_tutorial] +level = DEBUG +handlers = +qualname = tutorial + [handler_console] class = StreamHandler args = (sys.stderr,) @@ -40,6 +62,4 @@ level = NOTSET formatter = generic [formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s] %(message)s - -# End logging configuration +format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s diff --git a/docs/tutorials/wiki/src/views/production.ini b/docs/tutorials/wiki/src/views/production.ini index ca8107802..d9bf27c42 100644 --- a/docs/tutorials/wiki/src/views/production.ini +++ b/docs/tutorials/wiki/src/views/production.ini @@ -1,5 +1,11 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial + pyramid.reload_templates = false pyramid.debug_authorization = false pyramid.debug_notfound = false @@ -12,12 +18,19 @@ pyramid.includes = tm.attempts = 3 zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000 +### +# wsgi server configuration +### + [server:main] use = egg:waitress#main host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial @@ -45,5 +58,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py index a6be89b2e..ac8cdf2d5 100644 --- a/docs/tutorials/wiki/src/views/setup.py +++ b/docs/tutorials/wiki/src/views/setup.py @@ -21,9 +21,8 @@ setup(name='tutorial', description='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ - "Intended Audience :: Developers", - "Framework :: Pylons", "Programming Language :: Python", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -34,11 +33,12 @@ setup(name='tutorial', packages=find_packages(), include_package_data=True, zip_safe=False, - install_requires=requires, - tests_require=requires, + install_requires = requires, + tests_require= requires, test_suite="tutorial", entry_points = """\ [paste.app_factory] main = tutorial:main """, ) + diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt index 3597c679b..84824f605 100644 --- a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt @@ -6,9 +6,9 @@ <meta name="keywords" content="python web application" /> <meta name="description" content="pyramid web application" /> <link rel="shortcut icon" href="/static/favicon.ico" /> + <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" /> <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" /> - <link rel="stylesheet" href="/static/pylons.css" type="text/css" media="screen" charset="utf-8" /> <!--[if lte IE 6]> <link rel="stylesheet" href="/static/ie6.css" type="text/css" media="screen" charset="utf-8" /> <![endif]--> @@ -41,7 +41,7 @@ <h2>Pyramid links</h2> <ul class="links"> <li> - <a href="http://pylonsproject.org">Pylons Website</a> + <a href="http://pylonsproject.org/">Pylons Website</a> </li> <li> <a href="http://docs.pylonsproject.org/projects/pyramid/current/#narrative-documentation">Narrative Documentation</a> @@ -70,7 +70,7 @@ </div> </div> <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> </div> </body> </html> diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index dbd130c36..4f73dc914 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -171,6 +171,12 @@ application. Without being processed by ``scan``, the decorator effectively does nothing. ``@view_config`` is inert without being detected via a :term:`scan`. +The sample ``my_view()`` created by the scaffold uses a ``try:`` and ``except:`` +clause, to detect if there is a problem accessing the project database and +provide an alternate error response. That response will include the text +shown at the end of the file, which will be displayed in the browser to +inform the user about possible actions to take to solve the problem. + Content Models with ``models.py`` --------------------------------- diff --git a/docs/tutorials/wiki2/src/authorization/README.txt b/docs/tutorials/wiki2/src/authorization/README.txt index 6f851e9b7..141851285 100644 --- a/docs/tutorials/wiki2/src/authorization/README.txt +++ b/docs/tutorials/wiki2/src/authorization/README.txt @@ -1 +1,14 @@ tutorial README +================== + +Getting Started +--------------- + +- cd <directory containing this file> + +- $venv/bin/python setup.py develop + +- $venv/bin/initialize_tutorial_db development.ini + +- $venv/bin/pserve development.ini + diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini index eb2f878c5..a9d53b296 100644 --- a/docs/tutorials/wiki2/src/authorization/development.ini +++ b/docs/tutorials/wiki2/src/authorization/development.ini @@ -1,3 +1,8 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial @@ -12,12 +17,23 @@ pyramid.includes = sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial, sqlalchemy @@ -53,5 +69,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py index 2fd051927..d658cae93 100644 --- a/docs/tutorials/wiki2/src/authorization/setup.py +++ b/docs/tutorials/wiki2/src/authorization/setup.py @@ -13,8 +13,8 @@ requires = [ 'pyramid_tm', 'pyramid_debugtoolbar', 'zope.sqlalchemy', - 'docutils', 'waitress', + 'docutils', ] setup(name='tutorial', @@ -23,7 +23,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -35,11 +35,12 @@ setup(name='tutorial', include_package_data=True, zip_safe=False, test_suite='tutorial', - install_requires = requires, - entry_points = """\ + install_requires=requires, + entry_points="""\ [paste.app_factory] main = tutorial:main [console_scripts] initialize_tutorial_db = tutorial.scripts.initializedb:main """, ) + diff --git a/docs/tutorials/wiki2/src/basiclayout/README.txt b/docs/tutorials/wiki2/src/basiclayout/README.txt index 6f851e9b7..141851285 100644 --- a/docs/tutorials/wiki2/src/basiclayout/README.txt +++ b/docs/tutorials/wiki2/src/basiclayout/README.txt @@ -1 +1,14 @@ tutorial README +================== + +Getting Started +--------------- + +- cd <directory containing this file> + +- $venv/bin/python setup.py develop + +- $venv/bin/initialize_tutorial_db development.ini + +- $venv/bin/pserve development.ini + diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini index eb2f878c5..a9d53b296 100644 --- a/docs/tutorials/wiki2/src/basiclayout/development.ini +++ b/docs/tutorials/wiki2/src/basiclayout/development.ini @@ -1,3 +1,8 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial @@ -12,12 +17,23 @@ pyramid.includes = sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial, sqlalchemy @@ -53,5 +69,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini index 4684d2f7a..fa94c1b3e 100644 --- a/docs/tutorials/wiki2/src/basiclayout/production.ini +++ b/docs/tutorials/wiki2/src/basiclayout/production.ini @@ -1,3 +1,8 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial @@ -16,7 +21,10 @@ use = egg:waitress#main host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial, sqlalchemy @@ -52,5 +60,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py index 050de7299..1a1ad78aa 100644 --- a/docs/tutorials/wiki2/src/basiclayout/setup.py +++ b/docs/tutorials/wiki2/src/basiclayout/setup.py @@ -22,7 +22,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -34,8 +34,8 @@ setup(name='tutorial', include_package_data=True, zip_safe=False, test_suite='tutorial', - install_requires = requires, - entry_points = """\ + install_requires=requires, + entry_points="""\ [paste.app_factory] main = tutorial:main [console_scripts] diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt index fbfa9870b..15ea6614f 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt @@ -70,7 +70,7 @@ </div> </div> <div id="footer"> - <div class="footer">© Copyright 2008-2011, Agendaless Consulting.</div> + <div class="footer">© Copyright 2008-2012, Agendaless Consulting.</div> </div> </body> </html> diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py index 3e6abf2c2..daf21bb7b 100644 --- a/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py +++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/views.py @@ -1,5 +1,8 @@ +from pyramid.response import Response from pyramid.view import view_config +from sqlalchemy.exc import DBAPIError + from .models import ( DBSession, MyModel, @@ -7,5 +10,25 @@ from .models import ( @view_config(route_name='home', renderer='templates/mytemplate.pt') def my_view(request): - one = DBSession.query(MyModel).filter(MyModel.name=='one').first() + try: + one = DBSession.query(MyModel).filter(MyModel.name=='one').first() + except DBAPIError: + return Response(conn_err_msg, content_type='text/plain', status_int=500) return {'one':one, 'project':'tutorial'} + +conn_err_msg = """\ +Pyramid is having a problem using your SQL database. The problem +might be caused by one of the following things: + +1. You may need to run the "initialize_tutorial_db" script + to initialize your database tables. Check your virtual + environment's "bin" directory for this script and try to run it. + +2. Your database server may not be running. Check that the + database server referred to by the "sqlalchemy.url" setting in + your "development.ini" file is running. + +After you fix the problem, please restart the Pyramid application to +try it again. +""" + diff --git a/docs/tutorials/wiki2/src/models/README.txt b/docs/tutorials/wiki2/src/models/README.txt index 6f851e9b7..141851285 100644 --- a/docs/tutorials/wiki2/src/models/README.txt +++ b/docs/tutorials/wiki2/src/models/README.txt @@ -1 +1,14 @@ tutorial README +================== + +Getting Started +--------------- + +- cd <directory containing this file> + +- $venv/bin/python setup.py develop + +- $venv/bin/initialize_tutorial_db development.ini + +- $venv/bin/pserve development.ini + diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini index eb2f878c5..a9d53b296 100644 --- a/docs/tutorials/wiki2/src/models/development.ini +++ b/docs/tutorials/wiki2/src/models/development.ini @@ -1,3 +1,8 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial @@ -12,12 +17,23 @@ pyramid.includes = sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial, sqlalchemy @@ -53,5 +69,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py index 050de7299..1a1ad78aa 100644 --- a/docs/tutorials/wiki2/src/models/setup.py +++ b/docs/tutorials/wiki2/src/models/setup.py @@ -22,7 +22,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -34,8 +34,8 @@ setup(name='tutorial', include_package_data=True, zip_safe=False, test_suite='tutorial', - install_requires = requires, - entry_points = """\ + install_requires=requires, + entry_points="""\ [paste.app_factory] main = tutorial:main [console_scripts] diff --git a/docs/tutorials/wiki2/src/models/tutorial/views.py b/docs/tutorials/wiki2/src/models/tutorial/views.py index 3e6abf2c2..daf21bb7b 100644 --- a/docs/tutorials/wiki2/src/models/tutorial/views.py +++ b/docs/tutorials/wiki2/src/models/tutorial/views.py @@ -1,5 +1,8 @@ +from pyramid.response import Response from pyramid.view import view_config +from sqlalchemy.exc import DBAPIError + from .models import ( DBSession, MyModel, @@ -7,5 +10,25 @@ from .models import ( @view_config(route_name='home', renderer='templates/mytemplate.pt') def my_view(request): - one = DBSession.query(MyModel).filter(MyModel.name=='one').first() + try: + one = DBSession.query(MyModel).filter(MyModel.name=='one').first() + except DBAPIError: + return Response(conn_err_msg, content_type='text/plain', status_int=500) return {'one':one, 'project':'tutorial'} + +conn_err_msg = """\ +Pyramid is having a problem using your SQL database. The problem +might be caused by one of the following things: + +1. You may need to run the "initialize_tutorial_db" script + to initialize your database tables. Check your virtual + environment's "bin" directory for this script and try to run it. + +2. Your database server may not be running. Check that the + database server referred to by the "sqlalchemy.url" setting in + your "development.ini" file is running. + +After you fix the problem, please restart the Pyramid application to +try it again. +""" + diff --git a/docs/tutorials/wiki2/src/tests/README.txt b/docs/tutorials/wiki2/src/tests/README.txt index 6f851e9b7..141851285 100644 --- a/docs/tutorials/wiki2/src/tests/README.txt +++ b/docs/tutorials/wiki2/src/tests/README.txt @@ -1 +1,14 @@ tutorial README +================== + +Getting Started +--------------- + +- cd <directory containing this file> + +- $venv/bin/python setup.py develop + +- $venv/bin/initialize_tutorial_db development.ini + +- $venv/bin/pserve development.ini + diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini index eb2f878c5..a9d53b296 100644 --- a/docs/tutorials/wiki2/src/tests/development.ini +++ b/docs/tutorials/wiki2/src/tests/development.ini @@ -1,3 +1,8 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial @@ -12,12 +17,23 @@ pyramid.includes = sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial, sqlalchemy @@ -53,5 +69,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki2/src/tests/setup.py b/docs/tutorials/wiki2/src/tests/setup.py index 0f58d8a18..8a619d27b 100644 --- a/docs/tutorials/wiki2/src/tests/setup.py +++ b/docs/tutorials/wiki2/src/tests/setup.py @@ -24,7 +24,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -36,11 +36,12 @@ setup(name='tutorial', include_package_data=True, zip_safe=False, test_suite='tutorial', - install_requires = requires, - entry_points = """\ + install_requires=requires, + entry_points="""\ [paste.app_factory] main = tutorial:main [console_scripts] initialize_tutorial_db = tutorial.scripts.initializedb:main """, ) + diff --git a/docs/tutorials/wiki2/src/tests/tutorial/views.py b/docs/tutorials/wiki2/src/tests/tutorial/views.py index 42ac0eb7f..0d085b0e2 100644 --- a/docs/tutorials/wiki2/src/tests/tutorial/views.py +++ b/docs/tutorials/wiki2/src/tests/tutorial/views.py @@ -37,14 +37,13 @@ def view_wiki(request): permission='view') def view_page(request): pagename = request.matchdict['pagename'] - session = DBSession() - page = session.query(Page).filter_by(name=pagename).first() + page = DBSession.query(Page).filter_by(name=pagename).first() if page is None: return HTTPNotFound('No such page') def check(match): word = match.group(1) - exists = session.query(Page).filter_by(name=word).all() + exists = DBSession.query(Page).filter_by(name=word).all() if exists: view_url = request.route_url('view_page', pagename=word) return '<a href="%s">%s</a>' % (view_url, word) @@ -63,10 +62,9 @@ def view_page(request): def add_page(request): pagename = request.matchdict['pagename'] if 'form.submitted' in request.params: - session = DBSession() body = request.params['body'] page = Page(pagename, body) - session.add(page) + DBSession.add(page) return HTTPFound(location = request.route_url('view_page', pagename=pagename)) save_url = request.route_url('add_page', pagename=pagename) @@ -78,11 +76,10 @@ def add_page(request): permission='edit') def edit_page(request): pagename = request.matchdict['pagename'] - session = DBSession() - page = session.query(Page).filter_by(name=pagename).one() + page = DBSession.query(Page).filter_by(name=pagename).one() if 'form.submitted' in request.params: page.data = request.params['body'] - session.add(page) + DBSession.add(page) return HTTPFound(location = request.route_url('view_page', pagename=pagename)) return dict( diff --git a/docs/tutorials/wiki2/src/views/README.txt b/docs/tutorials/wiki2/src/views/README.txt index 6f851e9b7..141851285 100644 --- a/docs/tutorials/wiki2/src/views/README.txt +++ b/docs/tutorials/wiki2/src/views/README.txt @@ -1 +1,14 @@ tutorial README +================== + +Getting Started +--------------- + +- cd <directory containing this file> + +- $venv/bin/python setup.py develop + +- $venv/bin/initialize_tutorial_db development.ini + +- $venv/bin/pserve development.ini + diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini index eb2f878c5..a9d53b296 100644 --- a/docs/tutorials/wiki2/src/views/development.ini +++ b/docs/tutorials/wiki2/src/views/development.ini @@ -1,3 +1,8 @@ +### +# app configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html +### + [app:main] use = egg:tutorial @@ -12,12 +17,23 @@ pyramid.includes = sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite +# 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 host = 0.0.0.0 port = 6543 -# Begin logging configuration +### +# logging configuration +# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html +### [loggers] keys = root, tutorial, sqlalchemy @@ -53,5 +69,3 @@ formatter = generic [formatter_generic] format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s - -# End logging configuration diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py index 34b578e21..d658cae93 100644 --- a/docs/tutorials/wiki2/src/views/setup.py +++ b/docs/tutorials/wiki2/src/views/setup.py @@ -23,7 +23,7 @@ setup(name='tutorial', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", - "Framework :: Pylons", + "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], @@ -35,8 +35,8 @@ setup(name='tutorial', include_package_data=True, zip_safe=False, test_suite='tutorial', - install_requires = requires, - entry_points = """\ + install_requires=requires, + entry_points="""\ [paste.app_factory] main = tutorial:main [console_scripts] diff --git a/docs/whatsnew-1.4.rst b/docs/whatsnew-1.4.rst index 59e1f7a96..5da28bb03 100644 --- a/docs/whatsnew-1.4.rst +++ b/docs/whatsnew-1.4.rst @@ -77,6 +77,11 @@ Subrequest Support Minor Feature Additions ----------------------- +- :class:`pyramid.authentication.AuthTktAuthenticationPolicy` has been updated + to support newer hashing algorithms such as ``sha512``. Existing applications + should consider updating if possible for improved security over the default + md5 hashing. + - :meth:`pyramid.config.Configurator.add_directive` now accepts arbitrary callables like partials or objects implementing ``__call__`` which don't have ``__name__`` and ``__doc__`` attributes. See @@ -182,7 +187,6 @@ Minor Feature Additions :meth:`pyramid.config.testing_securitypolicy` now sets a ``forgotten`` value on the policy (the value ``True``) when its ``forget`` method is called. - - The DummySecurityPolicy created by :meth:`pyramid.config.testing_securitypolicy` now sets a ``remembered`` value on the policy, which is the value of the ``principal`` @@ -196,6 +200,31 @@ Minor Feature Additions view when some object is traversed to, but you can't be sure about what kind of object it will be, so you can't use the ``context`` predicate. +- Added an ``effective_principals`` route and view predicate. + +- Do not allow the userid returned from the + :func:`pyramid.security.authenticated_userid` or the userid that is one of the + list of principals returned by :func:`pyramid.security.effective_principals` + to be either of the strings ``system.Everyone`` or ``system.Authenticated`` + when any of the built-in authorization policies that live in + :mod:`pyramid.authentication` are in use. These two strings are reserved for + internal usage by Pyramid and they will no longer be accepted as valid + userids. + +- Allow a ``_depth`` argument to :class:`pyramid.view.view_config`, which will + permit limited composition reuse of the decorator by other software that + wants to provide custom decorators that are much like view_config. + +- Allow an iterable of decorators to be passed to + :meth:`pyramid.config.Configurator.add_view`. This allows views to be wrapped + by more than one decorator without requiring combining the decorators + yourself. + +- :func:`pyramid.security.view_execution_permitted` used to return `True` if no + view could be found. It now raises a :exc:`TypeError` exception in that case, + as it doesn't make sense to assert that a nonexistent view is + execution-permitted. See https://github.com/Pylons/pyramid/issues/299. + Backwards Incompatibilities --------------------------- @@ -289,6 +318,12 @@ Deprecations used in its place (it has all of the same capabilities but can also extend the request object with methods). +- :class:`pyramid.authentication.AuthTktAuthenticationPolicy` will emit a + deprecation warning if an application is using the policy without explicitly + passing a ``hashalg`` argument. This is because the default is "md5" which is + considered theoretically subject to collision attacks. If you really want + "md5" then you must specify it explicitly to get rid of the warning. + Documentation Enhancements -------------------------- @@ -299,6 +334,10 @@ Documentation Enhancements - Added a :ref:`subrequest_chapter` chapter to the narrative documentation. +- All of the tutorials that use + :class:`pyramid.authentication.AuthTktAuthenticationPolicy` now explicitly + pass ``sha512`` as a ``hashalg`` argument. + - Many cleanups and improvements to narrative and API docs. Dependency Changes diff --git a/pyramid/config/util.py b/pyramid/config/util.py index c16755a75..a83e23798 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -42,8 +42,12 @@ class PredicateList(object): ## weighs_more_than = self.last_added or FIRST ## weighs_less_than = LAST self.last_added = name - self.sorter.add(name, factory, after=weighs_more_than, - before=weighs_less_than) + self.sorter.add( + name, + factory, + after=weighs_more_than, + before=weighs_less_than, + ) def make(self, config, **kw): # Given a configurator and a list of keywords, a predicate list is diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 745b6f810..4e5af480d 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -59,6 +59,8 @@ from pyramid.registry import ( Deferred, ) +from pyramid.response import Response + from pyramid.security import NO_PERMISSION_REQUIRED from pyramid.static import static_view from pyramid.threadlocal import get_current_registry @@ -341,25 +343,28 @@ class ViewDeriver(object): def rendered_view(context, request): renderer = view_renderer result = view(context, request) - registry = self.registry - # this must adapt, it can't do a simple interface check - # (avoid trying to render webob responses) - response = registry.queryAdapterOrSelf(result, IResponse) - if response is None: - attrs = getattr(request, '__dict__', {}) - if 'override_renderer' in attrs: - # renderer overridden by newrequest event or other - renderer_name = attrs.pop('override_renderer') - renderer = renderers.RendererHelper( - name=renderer_name, - package=self.kw.get('package'), - registry = registry) - if '__view__' in attrs: - view_inst = attrs.pop('__view__') - else: - view_inst = getattr(view, '__original_view__', view) - response = renderer.render_view(request, result, view_inst, - context) + if result.__class__ is Response: # potential common case + response = result + else: + registry = self.registry + # this must adapt, it can't do a simple interface check + # (avoid trying to render webob responses) + response = registry.queryAdapterOrSelf(result, IResponse) + if response is None: + attrs = getattr(request, '__dict__', {}) + if 'override_renderer' in attrs: + # renderer overridden by newrequest event or other + renderer_name = attrs.pop('override_renderer') + renderer = renderers.RendererHelper( + name=renderer_name, + package=self.kw.get('package'), + registry = registry) + if '__view__' in attrs: + view_inst = attrs.pop('__view__') + else: + view_inst = getattr(view, '__original_view__', view) + response = renderer.render_view(request, result, view_inst, + context) return response return rendered_view @@ -368,21 +373,26 @@ class ViewDeriver(object): registry = self.registry def viewresult_to_response(context, request): result = view(context, request) - response = registry.queryAdapterOrSelf(result, IResponse) - if response is None: - if result is None: - append = (' You may have forgotten to return a value from ' - 'the view callable.') - elif isinstance(result, dict): - append = (' You may have forgotten to define a renderer in ' - 'the view configuration.') - else: - append = '' - msg = ('Could not convert return value of the view callable %s ' - 'into a response object. ' - 'The value returned was %r.' + append) - - raise ValueError(msg % (view_description(view), result)) + if result.__class__ is Response: # common case + response = result + else: + response = registry.queryAdapterOrSelf(result, IResponse) + if response is None: + if result is None: + append = (' You may have forgotten to return a value ' + 'from the view callable.') + elif isinstance(result, dict): + append = (' You may have forgotten to define a ' + 'renderer in the view configuration.') + else: + append = '' + + msg = ('Could not convert return value of the view ' + 'callable %s into a response object. ' + 'The value returned was %r.' + append) + + raise ValueError(msg % (view_description(view), result)) + return response return viewresult_to_response diff --git a/pyramid/request.py b/pyramid/request.py index 9e275c2c0..27ab337de 100644 --- a/pyramid/request.py +++ b/pyramid/request.py @@ -372,6 +372,8 @@ class Request(BaseRequest, DeprecatedRequestMethodsMixin, URLMethodsMixin, def is_response(self, ob): """ Return ``True`` if the object passed as ``ob`` is a valid response object, ``False`` otherwise.""" + if ob.__class__ is Response: + return True registry = self.registry adapted = registry.queryAdapterOrSelf(ob, IResponse) if adapted is None: diff --git a/pyramid/router.py b/pyramid/router.py index 0c7f61071..9b6138ea9 100644 --- a/pyramid/router.py +++ b/pyramid/router.py @@ -103,7 +103,7 @@ class Router(object): request.path_info, route.pattern, match, - ', '.join([p.__text__ for p in route.predicates])) + ', '.join([p.text() for p in route.predicates])) ) logger and logger.debug(msg) diff --git a/pyramid/scripts/pviews.py b/pyramid/scripts/pviews.py index 1bb4f2227..081c13e9d 100644 --- a/pyramid/scripts/pviews.py +++ b/pyramid/scripts/pviews.py @@ -188,7 +188,7 @@ class PViewsCommand(object): self.out("%sroute pattern: %s" % (indent, route.pattern)) self.out("%sroute path: %s" % (indent, route.path)) self.out("%ssubpath: %s" % (indent, '/'.join(attrs['subpath']))) - predicates = ', '.join([p.__text__ for p in route.predicates]) + predicates = ', '.join([p.text() for p in route.predicates]) if predicates != '': self.out("%sroute predicates (%s)" % (indent, predicates)) diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 8324eb2b9..bb4c5d519 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -2483,6 +2483,29 @@ class TestViewDeriver(unittest.TestCase): else: # pragma: no cover raise AssertionError + def test_function_returns_true_Response_no_renderer(self): + from pyramid.response import Response + r = Response('Hello') + def view(request): + return r + deriver = self._makeOne() + result = deriver(view) + self.assertFalse(result is view) + response = result(None, None) + self.assertEqual(response, r) + + def test_function_returns_true_Response_with_renderer(self): + from pyramid.response import Response + r = Response('Hello') + def view(request): + return r + renderer = object() + deriver = self._makeOne(renderer=renderer) + result = deriver(view) + self.assertFalse(result is view) + response = result(None, None) + self.assertEqual(response, r) + def test_requestonly_default_method_returns_non_adaptable(self): request = DummyRequest() class AView(object): diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py index 945e36a7f..565c6377e 100644 --- a/pyramid/tests/test_request.py +++ b/pyramid/tests/test_request.py @@ -230,6 +230,13 @@ class TestRequest(unittest.TestCase): request.registry = self.config.registry self.assertEqual(request.is_response('abc'), False) + def test_is_response_true_ob_is_pyramid_response(self): + from pyramid.response import Response + r = Response('hello') + request = self._makeOne() + request.registry = self.config.registry + self.assertEqual(request.is_response(r), True) + def test_is_response_false_adapter_is_not_self(self): from pyramid.interfaces import IResponse request = self._makeOne() diff --git a/pyramid/tests/test_router.py b/pyramid/tests/test_router.py index 778b27473..65152ca05 100644 --- a/pyramid/tests/test_router.py +++ b/pyramid/tests/test_router.py @@ -24,7 +24,7 @@ class TestRouter(unittest.TestCase): if mapper is None: mapper = RoutesMapper() self.registry.registerUtility(mapper, IRoutesMapper) - mapper.connect(name, path, factory) + return mapper.connect(name, path, factory) def _registerLogger(self): from pyramid.interfaces import IDebugLogger @@ -657,7 +657,8 @@ class TestRouter(unittest.TestCase): root = object() def factory(request): return root - self._connectRoute('foo', 'archives/:action/:article', factory) + route = self._connectRoute('foo', 'archives/:action/:article', factory) + route.predicates = [DummyPredicate()] context = DummyContext() self._registerTraverserFactory(context) response = DummyResponse() @@ -686,7 +687,11 @@ class TestRouter(unittest.TestCase): "route matched for url http://localhost:8080" "/archives/action1/article1; " "route_name: 'foo', " - "path_info: ")) + "path_info: ") + ) + self.assertTrue( + "predicates: 'predicate'" in logger.messages[0] + ) def test_call_route_match_miss_debug_routematch(self): from pyramid.httpexceptions import HTTPNotFound @@ -1159,6 +1164,12 @@ class TestRouter(unittest.TestCase): start_response = DummyStartResponse() self.assertRaises(RuntimeError, router, environ, start_response) +class DummyPredicate(object): + def __call__(self, info, request): + return True + def text(self): + return 'predicate' + class DummyContext: pass diff --git a/pyramid/tests/test_scripts/test_pviews.py b/pyramid/tests/test_scripts/test_pviews.py index 6a919c31b..266d1ec90 100644 --- a/pyramid/tests/test_scripts/test_pviews.py +++ b/pyramid/tests/test_scripts/test_pviews.py @@ -379,7 +379,7 @@ class TestPViewsCommand(unittest.TestCase): L = [] command.out = L.append def predicate(): pass - predicate.__text__ = "predicate = x" + predicate.text = lambda *arg: "predicate = x" route = dummy.DummyRoute('a', '/a', matchdict={}, predicate=predicate) view = dummy.DummyView(context='context', view_name='a', matched_route=route, subpath='') @@ -68,7 +68,7 @@ testing_extras = tests_require + [ ] setup(name='pyramid', - version='1.4a3', + version='1.4a4', description=('The Pyramid web application development framework, a ' 'Pylons project'), long_description=README + '\n\n' + CHANGES, |
