summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2017-04-30 18:43:40 -0500
committerGitHub <noreply@github.com>2017-04-30 18:43:40 -0500
commite78aa24cda85368c3507c145e1e604e7335778dc (patch)
treee5c26bf68ff50158818e769df7eef2d33462f7ab
parentab04b7be473d0145d9f306583c4d529ee8abbe02 (diff)
parentf454b80b0f6e6442fa27e48b7e1e38c5a7cbef03 (diff)
downloadpyramid-e78aa24cda85368c3507c145e1e604e7335778dc.tar.gz
pyramid-e78aa24cda85368c3507c145e1e604e7335778dc.tar.bz2
pyramid-e78aa24cda85368c3507c145e1e604e7335778dc.zip
Merge pull request #2985 from mmerickel/plaster
migrate pyramid to use plaster
-rw-r--r--CHANGES.txt28
-rw-r--r--docs/api/paster.rst6
-rw-r--r--docs/glossary.rst8
-rw-r--r--docs/narr/paste.rst12
-rw-r--r--docs/narr/startup.rst9
-rw-r--r--pyramid/paster.py59
-rw-r--r--pyramid/scripts/common.py27
-rw-r--r--pyramid/scripts/prequest.py19
-rw-r--r--pyramid/scripts/proutes.py35
-rw-r--r--pyramid/scripts/pserve.py103
-rw-r--r--pyramid/scripts/pshell.py31
-rw-r--r--pyramid/scripts/ptweens.py8
-rw-r--r--pyramid/scripts/pviews.py10
-rw-r--r--pyramid/tests/test_paster.py190
-rw-r--r--pyramid/tests/test_scripts/dummy.py70
-rw-r--r--pyramid/tests/test_scripts/test_prequest.py62
-rw-r--r--pyramid/tests/test_scripts/test_proutes.py74
-rw-r--r--pyramid/tests/test_scripts/test_pserve.py69
-rw-r--r--pyramid/tests/test_scripts/test_pshell.py55
-rw-r--r--pyramid/tests/test_scripts/test_ptweens.py3
-rw-r--r--pyramid/tests/test_scripts/test_pviews.py3
-rw-r--r--setup.py2
22 files changed, 366 insertions, 517 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index a2e2d6db1..075d3ffd9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,14 +1,32 @@
unreleased
==========
-Features
---------
+Major Features
+--------------
+
+- The file format used by all ``p*`` command line scripts such as ``pserve``
+ and ``pshell``, as well as the ``pyramid.paster.bootstrap`` function
+ is now replaceable thanks to a new dependency on
+ `plaster <http://docs.pylonsproject.org/projects/plaster/en/latest/>`_.
+
+ For now, Pyramid is still shipping with integrated support for the
+ PasteDeploy INI format by depending on the ``plaster_pastedeploy`` binding.
+
+ See https://github.com/Pylons/pyramid/pull/2985
- Added an execution policy hook to the request pipeline. An execution
policy has the ability to control creation and execution of the request
- objects before they enter rest of the pipeline. This means for a given
- request that the policy may create more than one request for retry
- purposes. See https://github.com/Pylons/pyramid/pull/2964
+ objects before they enter the rest of the pipeline. This means for a single
+ request environ the policy may create more than one request object.
+
+ The first library to use this feature is
+ `pyramid_retry
+ <http://docs.pylonsproject.org/projects/pyramid-retry/en/latest/>`_.
+
+ See https://github.com/Pylons/pyramid/pull/2964
+
+Features
+--------
- Support an ``open_url`` config setting in the ``pserve`` section of the
config file. This url is used to open a web browser when ``pserve --browser``
diff --git a/docs/api/paster.rst b/docs/api/paster.rst
index 27bc81a1f..f0784d0f8 100644
--- a/docs/api/paster.rst
+++ b/docs/api/paster.rst
@@ -7,8 +7,8 @@
.. autofunction:: bootstrap
- .. autofunction:: get_app(config_uri, name=None, options=None)
+ .. autofunction:: get_app
- .. autofunction:: get_appsettings(config_uri, name=None, options=None)
+ .. autofunction:: get_appsettings
- .. autofunction:: setup_logging(config_uri, global_conf=None)
+ .. autofunction:: setup_logging
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 0cf96f488..2e5276554 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -366,6 +366,14 @@ Glossary
:term:`WSGI` components together declaratively within an ``.ini``
file. It was developed by Ian Bicking.
+ plaster
+ `plaster <http://docs.pylonsproject.org/projects/plaster/en/latest/>`_ is
+ a library used by :app:`Pyramid` which acts as an abstraction between
+ command-line scripts and the file format used to load the :term:`WSGI`
+ components and application settings. By default :app:`Pyramid` ships
+ with the ``plaster_pastedeploy`` library installed which provides
+ integrated support for loading a :term:`PasteDeploy` INI file.
+
Chameleon
`chameleon <https://chameleon.readthedocs.org/en/latest/>`_ is an
attribute language template compiler which supports the :term:`ZPT`
diff --git a/docs/narr/paste.rst b/docs/narr/paste.rst
index 2d4e76e24..26cb1bfa5 100644
--- a/docs/narr/paste.rst
+++ b/docs/narr/paste.rst
@@ -26,12 +26,7 @@ documentation, see http://pythonpaste.org/deploy/.
PasteDeploy
-----------
-:term:`PasteDeploy` is the system that Pyramid uses to allow :term:`deployment
-settings` to be specified using an ``.ini`` configuration file format. It also
-allows the ``pserve`` command to work. Its configuration format provides a
-convenient place to define application :term:`deployment settings` and WSGI
-server settings, and its server runner allows you to stop and start a Pyramid
-application easily.
+:term:`plaster` is the system that Pyramid uses to load settings from configuration files. The most common format for these files is an ``.ini`` format structured in a way defined by :term:`PasteDeploy`. The format supports mechanisms to define WSGI app :term:`deployment settings`, WSGI server settings and logging. This allows the ``pserve`` command to work, allowing you to stop and start a Pyramid application easily.
.. _pastedeploy_entry_points:
@@ -96,3 +91,8 @@ applications, servers, and :term:`middleware` defined within the configuration
file. The values in a ``[DEFAULT]`` section will be passed to your
application's ``main`` function as ``global_config`` (see the reference to the
``main`` function in :ref:`init_py`).
+
+Alternative Configuration File Formats
+--------------------------------------
+
+It is possible to use different file formats with :app:`Pyramid` if you do not like :term:`PasteDeploy`. Under the hood all command-line scripts such as ``pserve`` and ``pshell`` pass the ``config_uri`` (e.g. ``development.ini`` or ``production.ini``) to the :term:`plaster` library which performs a lookup for an appropriate parser. For ``.ini`` files it uses PasteDeploy but you can register your own configuration formats that plaster will find instead.
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index cf4612602..29a75cba2 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -38,7 +38,14 @@ Here's a high-level time-ordered overview of what happens when you press
begin to run and serve an application using the information contained
within the ``development.ini`` file.
-#. The framework finds a section named either ``[app:main]``,
+#. ``pserve`` passes the ``development.ini`` path to :term:`plaster` which
+ finds an available configuration loader that recognizes the ``ini`` format.
+
+#. :term:`plaster` finds the ``plaster_pastedeploy`` library which binds
+ the :term:`PasteDeploy` library and returns a parser that can understand
+ the format.
+
+#. The :term:`PasteDeploy` finds a section named either ``[app:main]``,
``[pipeline:main]``, or ``[composite:main]`` in the ``.ini`` file. This
section represents the configuration of a :term:`WSGI` application that will
be served. If you're using a simple application (e.g., ``[app:main]``), the
diff --git a/pyramid/paster.py b/pyramid/paster.py
index 5429a7860..f7544f0c5 100644
--- a/pyramid/paster.py
+++ b/pyramid/paster.py
@@ -1,14 +1,17 @@
-import os
+from pyramid.scripting import prepare
+from pyramid.scripts.common import get_config_loader
-from paste.deploy import (
- loadapp,
- appconfig,
- )
+def setup_logging(config_uri, global_conf=None):
+ """
+ Set up Python logging with the filename specified via ``config_uri``
+ (a string in the form ``filename#sectionname``).
-from pyramid.scripting import prepare
-from pyramid.scripts.common import setup_logging # noqa, api
+ Extra defaults can optionally be specified as a dict in ``global_conf``.
+ """
+ loader = get_config_loader(config_uri)
+ loader.setup_logging(global_conf)
-def get_app(config_uri, name=None, options=None, loadapp=loadapp):
+def get_app(config_uri, name=None, options=None):
""" Return the WSGI application named ``name`` in the PasteDeploy
config file specified by ``config_uri``.
@@ -18,20 +21,13 @@ def get_app(config_uri, name=None, options=None, loadapp=loadapp):
If the ``name`` is None, this will attempt to parse the name from
the ``config_uri`` string expecting the format ``inifile#name``.
- If no name is found, the name will default to "main"."""
- path, section = _getpathsec(config_uri, name)
- config_name = 'config:%s' % path
- here_dir = os.getcwd()
+ If no name is found, the name will default to "main".
- app = loadapp(
- config_name,
- name=section,
- relative_to=here_dir,
- global_conf=options)
-
- return app
+ """
+ loader = get_config_loader(config_uri)
+ return loader.get_wsgi_app(name, options)
-def get_appsettings(config_uri, name=None, options=None, appconfig=appconfig):
+def get_appsettings(config_uri, name=None, options=None):
""" Return a dictionary representing the key/value pairs in an ``app``
section within the file represented by ``config_uri``.
@@ -41,24 +37,11 @@ def get_appsettings(config_uri, name=None, options=None, appconfig=appconfig):
If the ``name`` is None, this will attempt to parse the name from
the ``config_uri`` string expecting the format ``inifile#name``.
- If no name is found, the name will default to "main"."""
- path, section = _getpathsec(config_uri, name)
- config_name = 'config:%s' % path
- here_dir = os.getcwd()
- return appconfig(
- config_name,
- name=section,
- relative_to=here_dir,
- global_conf=options)
-
-def _getpathsec(config_uri, name):
- if '#' in config_uri:
- path, section = config_uri.split('#', 1)
- else:
- path, section = config_uri, 'main'
- if name:
- section = name
- return path, section
+ If no name is found, the name will default to "main".
+
+ """
+ loader = get_config_loader(config_uri)
+ return loader.get_wsgi_app_settings(name, options)
def bootstrap(config_uri, request=None, options=None):
""" Load a WSGI application from the PasteDeploy config file specified
diff --git a/pyramid/scripts/common.py b/pyramid/scripts/common.py
index fc141f6e2..f4b8027db 100644
--- a/pyramid/scripts/common.py
+++ b/pyramid/scripts/common.py
@@ -1,6 +1,4 @@
-import os
-from pyramid.compat import configparser
-from logging.config import fileConfig
+import plaster
def parse_vars(args):
"""
@@ -17,26 +15,9 @@ def parse_vars(args):
result[name] = value
return result
-def setup_logging(config_uri, global_conf=None,
- fileConfig=fileConfig,
- configparser=configparser):
+def get_config_loader(config_uri):
"""
- Set up logging via :func:`logging.config.fileConfig` with the filename
- specified via ``config_uri`` (a string in the form
- ``filename#sectionname``).
+ Find a ``plaster.ILoader`` object supporting the "wsgi" protocol.
- ConfigParser defaults are specified for the special ``__file__``
- and ``here`` variables, similar to PasteDeploy config loading.
- Extra defaults can optionally be specified as a dict in ``global_conf``.
"""
- path = config_uri.split('#', 1)[0]
- parser = configparser.ConfigParser()
- parser.read([path])
- if parser.has_section('loggers'):
- config_file = os.path.abspath(path)
- full_global_conf = dict(
- __file__=config_file,
- here=os.path.dirname(config_file))
- if global_conf:
- full_global_conf.update(global_conf)
- return fileConfig(config_file, full_global_conf)
+ return plaster.get_loader(config_uri, protocols=['wsgi'])
diff --git a/pyramid/scripts/prequest.py b/pyramid/scripts/prequest.py
index 66feff624..f0681afd7 100644
--- a/pyramid/scripts/prequest.py
+++ b/pyramid/scripts/prequest.py
@@ -5,9 +5,8 @@ import textwrap
from pyramid.compat import url_unquote
from pyramid.request import Request
-from pyramid.paster import get_app
+from pyramid.scripts.common import get_config_loader
from pyramid.scripts.common import parse_vars
-from pyramid.scripts.common import setup_logging
def main(argv=sys.argv, quiet=False):
command = PRequestCommand(argv, quiet)
@@ -110,7 +109,7 @@ class PRequestCommand(object):
"passed here.",
)
- get_app = staticmethod(get_app)
+ _get_config_loader = staticmethod(get_config_loader)
stdin = sys.stdin
def __init__(self, argv, quiet=False):
@@ -121,17 +120,18 @@ class PRequestCommand(object):
if not self.quiet:
print(msg)
- def configure_logging(self, app_spec):
- setup_logging(app_spec)
-
def run(self):
if not self.args.config_uri or not self.args.path_info:
self.out('You must provide at least two arguments')
return 2
- app_spec = self.args.config_uri
+ config_uri = self.args.config_uri
+ config_vars = parse_vars(self.args.config_vars)
path = self.args.path_info
- self.configure_logging(app_spec)
+ loader = self._get_config_loader(config_uri)
+ loader.setup_logging(config_vars)
+
+ app = loader.get_wsgi_app(self.args.app_name, config_vars)
if not path.startswith('/'):
path = '/' + path
@@ -158,9 +158,6 @@ class PRequestCommand(object):
name, value = item.split(':', 1)
headers[name] = value.strip()
- app = self.get_app(app_spec, self.args.app_name,
- options=parse_vars(self.args.config_vars))
-
request_method = (self.args.method or 'GET').upper()
environ = {
diff --git a/pyramid/scripts/proutes.py b/pyramid/scripts/proutes.py
index 80c8238a2..69d61ae8f 100644
--- a/pyramid/scripts/proutes.py
+++ b/pyramid/scripts/proutes.py
@@ -7,10 +7,11 @@ import re
from zope.interface import Interface
from pyramid.paster import bootstrap
-from pyramid.compat import (string_types, configparser)
+from pyramid.compat import string_types
from pyramid.interfaces import IRouteRequest
from pyramid.config import not_
+from pyramid.scripts.common import get_config_loader
from pyramid.scripts.common import parse_vars
from pyramid.static import static_view
from pyramid.view import _find_views
@@ -175,7 +176,6 @@ def get_route_data(route, registry):
(route.name, route_intr['external_url'], UNKNOWN_KEY, ANY_KEY)
]
-
route_request_methods = route_intr['request_methods']
view_intr = registry.introspector.related(route_intr)
@@ -245,9 +245,9 @@ class PRoutesCommand(object):
will be assumed. Example: 'proutes myapp.ini'.
"""
- bootstrap = (bootstrap,)
+ bootstrap = staticmethod(bootstrap) # testing
+ get_config_loader = staticmethod(get_config_loader) # testing
stdout = sys.stdout
- ConfigParser = configparser.ConfigParser # testing
parser = argparse.ArgumentParser(
description=textwrap.dedent(description),
formatter_class=argparse.RawDescriptionHelpFormatter,
@@ -308,18 +308,12 @@ class PRoutesCommand(object):
return True
- def proutes_file_config(self, filename):
- config = self.ConfigParser()
- config.read(filename)
- try:
- items = config.items('proutes')
- for k, v in items:
- if 'format' == k:
- cols = re.split(r'[,|\s\n]+', v)
- self.column_format = [x.strip() for x in cols]
-
- except configparser.NoSectionError:
- return
+ def proutes_file_config(self, loader, global_conf=None):
+ settings = loader.get_settings('proutes', global_conf)
+ format = settings.get('format')
+ if format:
+ cols = re.split(r'[,|\s\n]+', format)
+ self.column_format = [x.strip() for x in cols]
def out(self, msg): # pragma: no cover
if not self.quiet:
@@ -336,12 +330,15 @@ class PRoutesCommand(object):
return 2
config_uri = self.args.config_uri
- env = self.bootstrap[0](config_uri, options=parse_vars(self.args.config_vars))
+ config_vars = parse_vars(self.args.config_vars)
+ loader = self.get_config_loader(config_uri)
+ loader.setup_logging(config_vars)
+ self.proutes_file_config(loader, config_vars)
+
+ env = self.bootstrap(config_uri, options=config_vars)
registry = env['registry']
mapper = self._get_mapper(registry)
- self.proutes_file_config(config_uri)
-
if self.args.format:
columns = self.args.format.split(',')
self.column_format = [x.strip() for x in columns]
diff --git a/pyramid/scripts/pserve.py b/pyramid/scripts/pserve.py
index c469dde04..f7d094980 100644
--- a/pyramid/scripts/pserve.py
+++ b/pyramid/scripts/pserve.py
@@ -18,16 +18,11 @@ import time
import webbrowser
import hupper
-from paste.deploy import (
- loadapp,
- loadserver,
-)
from pyramid.compat import PY2
-from pyramid.compat import configparser
+from pyramid.scripts.common import get_config_loader
from pyramid.scripts.common import parse_vars
-from pyramid.scripts.common import setup_logging
from pyramid.path import AssetResolver
from pyramid.settings import aslist
@@ -113,9 +108,7 @@ class PServeCommand(object):
"passed here.",
)
- ConfigParser = configparser.ConfigParser # testing
- loadapp = staticmethod(loadapp) # testing
- loadserver = staticmethod(loadserver) # testing
+ _get_config_loader = staticmethod(get_config_loader) # for testing
open_url = None
@@ -133,26 +126,14 @@ class PServeCommand(object):
if self.args.verbose > 0:
print(msg)
- def get_config_vars(self):
- restvars = self.args.config_vars
- return parse_vars(restvars)
+ def get_config_path(self, loader):
+ return os.path.abspath(loader.uri.path)
- def pserve_file_config(self, filename, global_conf=None):
- here = os.path.abspath(os.path.dirname(filename))
- defaults = {}
- if global_conf:
- defaults.update(global_conf)
- defaults['here'] = here
-
- config = self.ConfigParser(defaults=defaults)
- config.optionxform = str
- config.read(filename)
- try:
- items = dict(config.items('pserve'))
- except configparser.NoSectionError:
- return
-
- watch_files = aslist(items.get('watch_files', ''), flatten=False)
+ def pserve_file_config(self, loader, global_conf=None):
+ settings = loader.get_settings('pserve', global_conf)
+ config_path = self.get_config_path(loader)
+ here = os.path.dirname(config_path)
+ watch_files = aslist(settings.get('watch_files', ''), flatten=False)
# track file paths relative to the ini file
resolver = AssetResolver(package=None)
@@ -164,45 +145,30 @@ class PServeCommand(object):
self.watch_files.add(os.path.abspath(file))
# attempt to determine the url of the server
- open_url = items.get('open_url')
+ open_url = settings.get('open_url')
if open_url:
self.open_url = open_url
- def _guess_server_url(self, filename, server_name,
- global_conf=None): # pragma: no cover
+ def guess_server_url(self, loader, server_name, global_conf=None):
server_name = server_name or 'main'
- here = os.path.abspath(os.path.dirname(filename))
- defaults = {}
- if global_conf:
- defaults.update(global_conf)
- defaults['here'] = here
-
- config = self.ConfigParser(defaults=defaults)
- config.optionxform = str
- config.read(filename)
- try:
- items = dict(config.items('server:' + server_name))
- except configparser.NoSectionError:
- return
-
- if 'port' in items:
- return 'http://127.0.0.1:{port}'.format(**items)
+ settings = loader.get_settings('server:' + server_name, global_conf)
+ if 'port' in settings:
+ return 'http://127.0.0.1:{port}'.format(**settings)
def run(self): # pragma: no cover
if not self.args.config_uri:
self.out('You must give a config file')
return 2
+ config_uri = self.args.config_uri
+ config_vars = parse_vars(self.args.config_vars)
app_spec = self.args.config_uri
-
- vars = self.get_config_vars()
app_name = self.args.app_name
- base = os.getcwd()
- if not self._scheme_re.search(app_spec):
- config_path = os.path.join(base, app_spec)
- app_spec = 'config:' + app_spec
- else:
- config_path = None
+ loader = self._get_config_loader(config_uri)
+ loader.setup_logging(config_vars)
+
+ self.pserve_file_config(loader, global_conf=config_vars)
+
server_name = self.args.server_name
if self.args.server:
server_spec = 'egg:pyramid'
@@ -211,15 +177,17 @@ class PServeCommand(object):
else:
server_spec = app_spec
+ server_loader = loader
+ if server_spec != app_spec:
+ server_loader = self.get_config_loader(server_spec)
+
# do not open the browser on each reload so check hupper first
if self.args.browser and not hupper.is_active():
- self.pserve_file_config(config_path, global_conf=vars)
url = self.open_url
- # do not guess the url if the server is sourced from a different
- # location than the config_path
- if not url and server_spec == app_spec:
- url = self._guess_server_url(config_path, server_name, vars)
+ if not url:
+ url = self.guess_server_url(
+ server_loader, server_name, config_vars)
if not url:
self.out('WARNING: could not determine the server\'s url to '
@@ -246,20 +214,19 @@ class PServeCommand(object):
)
return 0
- if config_path:
- setup_logging(config_path, global_conf=vars)
- self.pserve_file_config(config_path, global_conf=vars)
- self.watch_files.add(config_path)
+ config_path = self.get_config_path(loader)
+ self.watch_files.add(config_path)
+
+ server_path = self.get_config_path(server_loader)
+ self.watch_files.add(server_path)
if hupper.is_active():
reloader = hupper.get_reloader()
reloader.watch_files(list(self.watch_files))
- server = self.loadserver(
- server_spec, name=server_name, relative_to=base, global_conf=vars)
+ server = server_loader.get_wsgi_server(server_name, config_vars)
- app = self.loadapp(
- app_spec, name=app_name, relative_to=base, global_conf=vars)
+ app = loader.get_wsgi_app(app_name, config_vars)
if self.args.verbose > 0:
if hasattr(os, 'getpid'):
diff --git a/pyramid/scripts/pshell.py b/pyramid/scripts/pshell.py
index 83e640c32..bb201dbc2 100644
--- a/pyramid/scripts/pshell.py
+++ b/pyramid/scripts/pshell.py
@@ -5,15 +5,14 @@ import sys
import textwrap
import pkg_resources
-from pyramid.compat import configparser
from pyramid.compat import exec_
from pyramid.util import DottedNameResolver
from pyramid.paster import bootstrap
from pyramid.settings import aslist
+from pyramid.scripts.common import get_config_loader
from pyramid.scripts.common import parse_vars
-from pyramid.scripts.common import setup_logging
def main(argv=sys.argv, quiet=False):
command = PShellCommand(argv, quiet)
@@ -41,7 +40,8 @@ class PShellCommand(object):
than one Pyramid application within it, the loader will use the
last one.
"""
- bootstrap = (bootstrap,) # for testing
+ bootstrap = staticmethod(bootstrap) # for testing
+ get_config_loader = staticmethod(get_config_loader) # for testing
pkg_resources = pkg_resources # for testing
parser = argparse.ArgumentParser(
@@ -78,7 +78,6 @@ class PShellCommand(object):
"passed here.",
)
- ConfigParser = configparser.ConfigParser # testing
default_runner = python_shell_runner # testing
loaded_objects = {}
@@ -91,20 +90,13 @@ class PShellCommand(object):
self.quiet = quiet
self.args = self.parser.parse_args(argv[1:])
- def pshell_file_config(self, filename):
- config = self.ConfigParser()
- config.optionxform = str
- config.read(filename)
- try:
- items = config.items('pshell')
- except configparser.NoSectionError:
- return
-
+ def pshell_file_config(self, loader, defaults):
+ settings = loader.get_settings('pshell', defaults)
resolver = DottedNameResolver(None)
self.loaded_objects = {}
self.object_help = {}
self.setup = None
- for k, v in items:
+ for k, v in settings.items():
if k == 'setup':
self.setup = v
elif k == 'default_shell':
@@ -124,13 +116,12 @@ class PShellCommand(object):
self.out('Requires a config file argument')
return 2
config_uri = self.args.config_uri
- config_file = config_uri.split('#', 1)[0]
- setup_logging(config_file)
- self.pshell_file_config(config_file)
+ config_vars = parse_vars(self.args.config_vars)
+ loader = self.get_config_loader(config_uri)
+ loader.setup_logging(config_vars)
+ self.pshell_file_config(loader, config_vars)
- # bootstrap the environ
- env = self.bootstrap[0](config_uri,
- options=parse_vars(self.args.config_vars))
+ env = self.bootstrap(config_uri, options=config_vars)
# remove the closer from the env
self.closer = env.pop('closer')
diff --git a/pyramid/scripts/ptweens.py b/pyramid/scripts/ptweens.py
index 5ca77e52a..d5cbebe12 100644
--- a/pyramid/scripts/ptweens.py
+++ b/pyramid/scripts/ptweens.py
@@ -7,6 +7,7 @@ from pyramid.interfaces import ITweens
from pyramid.tweens import MAIN
from pyramid.tweens import INGRESS
from pyramid.paster import bootstrap
+from pyramid.paster import setup_logging
from pyramid.scripts.common import parse_vars
def main(argv=sys.argv, quiet=False):
@@ -47,7 +48,8 @@ class PTweensCommand(object):
)
stdout = sys.stdout
- bootstrap = (bootstrap,) # testing
+ bootstrap = staticmethod(bootstrap) # testing
+ setup_logging = staticmethod(setup_logging) # testing
def __init__(self, argv, quiet=False):
self.quiet = quiet
@@ -76,7 +78,9 @@ class PTweensCommand(object):
self.out('Requires a config file argument')
return 2
config_uri = self.args.config_uri
- env = self.bootstrap[0](config_uri, options=parse_vars(self.args.config_vars))
+ config_vars = parse_vars(self.args.config_vars)
+ self.setup_logging(config_uri, global_conf=config_vars)
+ env = self.bootstrap(config_uri, options=config_vars)
registry = env['registry']
tweens = self._get_tweens(registry)
if tweens is not None:
diff --git a/pyramid/scripts/pviews.py b/pyramid/scripts/pviews.py
index 4d3312917..c0df2f078 100644
--- a/pyramid/scripts/pviews.py
+++ b/pyramid/scripts/pviews.py
@@ -4,6 +4,7 @@ import textwrap
from pyramid.interfaces import IMultiView
from pyramid.paster import bootstrap
+from pyramid.paster import setup_logging
from pyramid.request import Request
from pyramid.scripts.common import parse_vars
from pyramid.view import _find_views
@@ -51,7 +52,8 @@ class PViewsCommand(object):
)
- bootstrap = (bootstrap,) # testing
+ bootstrap = staticmethod(bootstrap) # testing
+ setup_logging = staticmethod(setup_logging) # testing
def __init__(self, argv, quiet=False):
self.quiet = quiet
@@ -252,13 +254,15 @@ class PViewsCommand(object):
self.out('Command requires a config file arg and a url arg')
return 2
config_uri = self.args.config_uri
+ config_vars = parse_vars(self.args.config_vars)
url = self.args.url
+ self.setup_logging(config_uri, global_conf=config_vars)
+
if not url.startswith('/'):
url = '/%s' % url
request = Request.blank(url)
- env = self.bootstrap[0](config_uri, options=parse_vars(self.args.config_vars),
- request=request)
+ env = self.bootstrap(config_uri, options=config_vars, request=request)
view = self._find_view(request)
self.out('')
self.out("URL = %s" % url)
diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py
index 22a5cde3d..784458647 100644
--- a/pyramid/tests/test_paster.py
+++ b/pyramid/tests/test_paster.py
@@ -1,58 +1,32 @@
import os
import unittest
+from pyramid.tests.test_scripts.dummy import DummyLoader
here = os.path.dirname(__file__)
class Test_get_app(unittest.TestCase):
- def _callFUT(self, config_file, section_name, **kw):
- from pyramid.paster import get_app
- return get_app(config_file, section_name, **kw)
+ def _callFUT(self, config_file, section_name, options=None, _loader=None):
+ import pyramid.paster
+ old_loader = pyramid.paster.get_config_loader
+ try:
+ if _loader is not None:
+ pyramid.paster.get_config_loader = _loader
+ return pyramid.paster.get_app(config_file, section_name,
+ options=options)
+ finally:
+ pyramid.paster.get_config_loader = old_loader
def test_it(self):
app = DummyApp()
- loadapp = DummyLoadWSGI(app)
- result = self._callFUT('/foo/bar/myapp.ini', 'myapp', loadapp=loadapp)
- self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(loadapp.section_name, 'myapp')
- self.assertEqual(loadapp.relative_to, os.getcwd())
- self.assertEqual(result, app)
-
- def test_it_with_hash(self):
- app = DummyApp()
- loadapp = DummyLoadWSGI(app)
+ loader = DummyLoader(app=app)
result = self._callFUT(
- '/foo/bar/myapp.ini#myapp', None, loadapp=loadapp
- )
- self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(loadapp.section_name, 'myapp')
- self.assertEqual(loadapp.relative_to, os.getcwd())
- self.assertEqual(result, app)
-
- def test_it_with_hash_and_name_override(self):
- app = DummyApp()
- loadapp = DummyLoadWSGI(app)
- result = self._callFUT(
- '/foo/bar/myapp.ini#myapp', 'yourapp', loadapp=loadapp
- )
- self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(loadapp.section_name, 'yourapp')
- self.assertEqual(loadapp.relative_to, os.getcwd())
- self.assertEqual(result, app)
-
- def test_it_with_options(self):
- app = DummyApp()
- loadapp = DummyLoadWSGI(app)
- options = {'a':1}
- result = self._callFUT(
- '/foo/bar/myapp.ini#myapp',
- 'yourapp',
- loadapp=loadapp,
- options=options,
- )
- self.assertEqual(loadapp.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(loadapp.section_name, 'yourapp')
- self.assertEqual(loadapp.relative_to, os.getcwd())
- self.assertEqual(loadapp.kw, {'global_conf':options})
+ '/foo/bar/myapp.ini', 'myapp', options={'a': 'b'},
+ _loader=loader)
+ self.assertEqual(loader.uri.path, '/foo/bar/myapp.ini')
+ self.assertEqual(len(loader.calls), 1)
+ self.assertEqual(loader.calls[0]['op'], 'app')
+ self.assertEqual(loader.calls[0]['name'], 'myapp')
+ self.assertEqual(loader.calls[0]['defaults'], {'a': 'b'})
self.assertEqual(result, app)
def test_it_with_dummyapp_requiring_options(self):
@@ -63,38 +37,28 @@ class Test_get_app(unittest.TestCase):
self.assertEqual(app.settings['foo'], 'baz')
class Test_get_appsettings(unittest.TestCase):
- def _callFUT(self, config_file, section_name, **kw):
- from pyramid.paster import get_appsettings
- return get_appsettings(config_file, section_name, **kw)
+ def _callFUT(self, config_file, section_name, options=None, _loader=None):
+ import pyramid.paster
+ old_loader = pyramid.paster.get_config_loader
+ try:
+ if _loader is not None:
+ pyramid.paster.get_config_loader = _loader
+ return pyramid.paster.get_appsettings(config_file, section_name,
+ options=options)
+ finally:
+ pyramid.paster.get_config_loader = old_loader
def test_it(self):
- values = {'a':1}
- appconfig = DummyLoadWSGI(values)
- result = self._callFUT('/foo/bar/myapp.ini', 'myapp',
- appconfig=appconfig)
- self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(appconfig.section_name, 'myapp')
- self.assertEqual(appconfig.relative_to, os.getcwd())
- self.assertEqual(result, values)
-
- def test_it_with_hash(self):
- values = {'a':1}
- appconfig = DummyLoadWSGI(values)
- result = self._callFUT('/foo/bar/myapp.ini#myapp', None,
- appconfig=appconfig)
- self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(appconfig.section_name, 'myapp')
- self.assertEqual(appconfig.relative_to, os.getcwd())
- self.assertEqual(result, values)
-
- def test_it_with_hash_and_name_override(self):
- values = {'a':1}
- appconfig = DummyLoadWSGI(values)
- result = self._callFUT('/foo/bar/myapp.ini#myapp', 'yourapp',
- appconfig=appconfig)
- self.assertEqual(appconfig.config_name, 'config:/foo/bar/myapp.ini')
- self.assertEqual(appconfig.section_name, 'yourapp')
- self.assertEqual(appconfig.relative_to, os.getcwd())
+ values = {'a': 1}
+ loader = DummyLoader(app_settings=values)
+ result = self._callFUT(
+ '/foo/bar/myapp.ini', 'myapp', options={'a': 'b'},
+ _loader=loader)
+ self.assertEqual(loader.uri.path, '/foo/bar/myapp.ini')
+ self.assertEqual(len(loader.calls), 1)
+ self.assertEqual(loader.calls[0]['op'], 'app_settings')
+ self.assertEqual(loader.calls[0]['name'], 'myapp')
+ self.assertEqual(loader.calls[0]['defaults'], {'a': 'b'})
self.assertEqual(result, values)
def test_it_with_dummyapp_requiring_options(self):
@@ -105,40 +69,39 @@ class Test_get_appsettings(unittest.TestCase):
self.assertEqual(result['foo'], 'baz')
class Test_setup_logging(unittest.TestCase):
- def _callFUT(self, config_file, global_conf=None):
- from pyramid.paster import setup_logging
- dummy_cp = DummyConfigParserModule
- return setup_logging(
- config_uri=config_file,
- global_conf=global_conf,
- fileConfig=self.fileConfig,
- configparser=dummy_cp,
- )
+ def _callFUT(self, config_file, global_conf=None, _loader=None):
+ import pyramid.paster
+ old_loader = pyramid.paster.get_config_loader
+ try:
+ if _loader is not None:
+ pyramid.paster.get_config_loader = _loader
+ return pyramid.paster.setup_logging(config_file, global_conf)
+ finally:
+ pyramid.paster.get_config_loader = old_loader
def test_it_no_global_conf(self):
- config_file, dict = self._callFUT('/abc')
- # os.path.abspath is a sop to Windows
- self.assertEqual(config_file, os.path.abspath('/abc'))
- self.assertEqual(dict['__file__'], os.path.abspath('/abc'))
- self.assertEqual(dict['here'], os.path.abspath('/'))
+ loader = DummyLoader()
+ self._callFUT('/abc.ini', _loader=loader)
+ self.assertEqual(loader.uri.path, '/abc.ini')
+ self.assertEqual(len(loader.calls), 1)
+ self.assertEqual(loader.calls[0]['op'], 'logging')
+ self.assertEqual(loader.calls[0]['defaults'], None)
def test_it_global_conf_empty(self):
- config_file, dict = self._callFUT('/abc', global_conf={})
- # os.path.abspath is a sop to Windows
- self.assertEqual(config_file, os.path.abspath('/abc'))
- self.assertEqual(dict['__file__'], os.path.abspath('/abc'))
- self.assertEqual(dict['here'], os.path.abspath('/'))
+ loader = DummyLoader()
+ self._callFUT('/abc.ini', global_conf={}, _loader=loader)
+ self.assertEqual(loader.uri.path, '/abc.ini')
+ self.assertEqual(len(loader.calls), 1)
+ self.assertEqual(loader.calls[0]['op'], 'logging')
+ self.assertEqual(loader.calls[0]['defaults'], {})
def test_it_global_conf_not_empty(self):
- config_file, dict = self._callFUT('/abc', global_conf={'key': 'val'})
- # os.path.abspath is a sop to Windows
- self.assertEqual(config_file, os.path.abspath('/abc'))
- self.assertEqual(dict['__file__'], os.path.abspath('/abc'))
- self.assertEqual(dict['here'], os.path.abspath('/'))
- self.assertEqual(dict['key'], 'val')
-
- def fileConfig(self, config_file, dict):
- return config_file, dict
+ loader = DummyLoader()
+ self._callFUT('/abc.ini', global_conf={'key': 'val'}, _loader=loader)
+ self.assertEqual(loader.uri.path, '/abc.ini')
+ self.assertEqual(len(loader.calls), 1)
+ self.assertEqual(loader.calls[0]['op'], 'logging')
+ self.assertEqual(loader.calls[0]['defaults'], {'key': 'val'})
class Test_bootstrap(unittest.TestCase):
def _callFUT(self, config_uri, request=None):
@@ -187,17 +150,6 @@ class DummyRegistry(object):
dummy_registry = DummyRegistry()
-class DummyLoadWSGI:
- def __init__(self, result):
- self.result = result
-
- def __call__(self, config_name, name=None, relative_to=None, **kw):
- self.config_name = config_name
- self.section_name = name
- self.relative_to = relative_to
- self.kw = kw
- return self.result
-
class DummyApp:
def __init__(self):
self.registry = dummy_registry
@@ -214,13 +166,3 @@ class DummyRequest:
def __init__(self, environ):
self.environ = environ
self.matchdict = {}
-
-class DummyConfigParser(object):
- def read(self, x):
- pass
-
- def has_section(self, name):
- return True
-
-class DummyConfigParserModule(object):
- ConfigParser = DummyConfigParser
diff --git a/pyramid/tests/test_scripts/dummy.py b/pyramid/tests/test_scripts/dummy.py
index ced09d0b0..2d2b0549f 100644
--- a/pyramid/tests/test_scripts/dummy.py
+++ b/pyramid/tests/test_scripts/dummy.py
@@ -81,29 +81,6 @@ class DummyMultiView(object):
self.views = [(None, view, None) for view in views]
self.__request_attrs__ = attrs
-class DummyConfigParser(object):
- def __init__(self, result, defaults=None):
- self.result = result
- self.defaults = defaults
-
- def read(self, filename):
- self.filename = filename
-
- def items(self, section):
- self.section = section
- if self.result is None:
- from pyramid.compat import configparser
- raise configparser.NoSectionError(section)
- return self.result
-
-class DummyConfigParserFactory(object):
- items = None
-
- def __call__(self, defaults=None):
- self.defaults = defaults
- self.parser = DummyConfigParser(self.items, defaults)
- return self.parser
-
class DummyCloser(object):
def __call__(self):
self.called = True
@@ -162,3 +139,50 @@ class DummyPkgResources(object):
def iter_entry_points(self, name):
return self.entry_points
+
+
+class dummy_setup_logging(object):
+ def __call__(self, config_uri, global_conf):
+ self.config_uri = config_uri
+ self.defaults = global_conf
+
+
+class DummyLoader(object):
+ def __init__(self, settings=None, app_settings=None, app=None, server=None):
+ if not settings:
+ settings = {}
+ if not app_settings:
+ app_settings = {}
+ self.settings = settings
+ self.app_settings = app_settings
+ self.app = app
+ self.server = server
+ self.calls = []
+
+ def __call__(self, uri):
+ import plaster
+ self.uri = plaster.parse_uri(uri)
+ return self
+
+ def add_call(self, op, name, defaults):
+ self.calls.append({'op': op, 'name': name, 'defaults': defaults})
+
+ def get_settings(self, name=None, defaults=None):
+ self.add_call('settings', name, defaults)
+ return self.settings.get(name, {})
+
+ def get_wsgi_app(self, name=None, defaults=None):
+ self.add_call('app', name, defaults)
+ return self.app
+
+ def get_wsgi_app_settings(self, name=None, defaults=None):
+ self.add_call('app_settings', name, defaults)
+ return self.app_settings
+
+ def get_wsgi_server(self, name=None, defaults=None):
+ self.add_call('server', name, defaults)
+ return self.server
+
+ def setup_logging(self, defaults):
+ self.add_call('logging', None, defaults)
+ self.defaults = defaults
diff --git a/pyramid/tests/test_scripts/test_prequest.py b/pyramid/tests/test_scripts/test_prequest.py
index 45db0dbaf..75d5cc198 100644
--- a/pyramid/tests/test_scripts/test_prequest.py
+++ b/pyramid/tests/test_scripts/test_prequest.py
@@ -1,4 +1,5 @@
import unittest
+from pyramid.tests.test_scripts import dummy
class TestPRequestCommand(unittest.TestCase):
def _getTargetClass(self):
@@ -7,23 +8,17 @@ class TestPRequestCommand(unittest.TestCase):
def _makeOne(self, argv, headers=None):
cmd = self._getTargetClass()(argv)
- cmd.get_app = self.get_app
- self._headers = headers or []
- self._out = []
- cmd.out = self.out
- return cmd
-
- def get_app(self, spec, app_name=None, options=None):
- self._spec = spec
- self._app_name = app_name
- self._options = options or {}
def helloworld(environ, start_request):
self._environ = environ
self._path_info = environ['PATH_INFO']
- start_request('200 OK', self._headers)
+ start_request('200 OK', headers or [])
return [b'abc']
- return helloworld
+ self.loader = dummy.DummyLoader(app=helloworld)
+ self._out = []
+ cmd._get_config_loader = self.loader
+ cmd.out = self.out
+ return cmd
def out(self, msg):
self._out.append(msg)
@@ -38,8 +33,10 @@ class TestPRequestCommand(unittest.TestCase):
[('Content-Type', 'text/html; charset=UTF-8')])
command.run()
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
+ self.assertEqual(self.loader.uri.path, 'development.ini')
+ self.assertEqual(self.loader.calls[0]['op'], 'logging')
+ self.assertEqual(self.loader.calls[1]['op'], 'app')
+ self.assertEqual(self.loader.calls[1]['name'], None)
self.assertEqual(self._out, ['abc'])
def test_command_path_doesnt_start_with_slash(self):
@@ -47,8 +44,7 @@ class TestPRequestCommand(unittest.TestCase):
[('Content-Type', 'text/html; charset=UTF-8')])
command.run()
self.assertEqual(self._path_info, '/abc')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
+ self.assertEqual(self.loader.uri.path, 'development.ini')
self.assertEqual(self._out, ['abc'])
def test_command_has_bad_config_header(self):
@@ -67,8 +63,6 @@ class TestPRequestCommand(unittest.TestCase):
command.run()
self.assertEqual(self._environ['HTTP_NAME'], 'value')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_w_basic_auth(self):
@@ -81,8 +75,6 @@ class TestPRequestCommand(unittest.TestCase):
self.assertEqual(self._environ['HTTP_AUTHORIZATION'],
'Basic dXNlcjpwYXNzd29yZA==')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_has_content_type_header_var(self):
@@ -92,8 +84,6 @@ class TestPRequestCommand(unittest.TestCase):
command.run()
self.assertEqual(self._environ['CONTENT_TYPE'], 'app/foo')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_has_multiple_header_vars(self):
@@ -109,8 +99,6 @@ class TestPRequestCommand(unittest.TestCase):
self.assertEqual(self._environ['HTTP_NAME'], 'value')
self.assertEqual(self._environ['HTTP_NAME2'], 'value2')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_method_get(self):
@@ -119,8 +107,6 @@ class TestPRequestCommand(unittest.TestCase):
command.run()
self.assertEqual(self._environ['REQUEST_METHOD'], 'GET')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_method_post(self):
@@ -134,8 +120,6 @@ class TestPRequestCommand(unittest.TestCase):
self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')
self.assertEqual(self._environ['wsgi.input'], stdin)
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_method_put(self):
@@ -149,8 +133,6 @@ class TestPRequestCommand(unittest.TestCase):
self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')
self.assertEqual(self._environ['wsgi.input'], stdin)
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_method_patch(self):
@@ -164,8 +146,6 @@ class TestPRequestCommand(unittest.TestCase):
self.assertEqual(self._environ['CONTENT_LENGTH'], '-1')
self.assertEqual(self._environ['wsgi.input'], stdin)
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_method_propfind(self):
@@ -178,8 +158,6 @@ class TestPRequestCommand(unittest.TestCase):
command.run()
self.assertEqual(self._environ['REQUEST_METHOD'], 'PROPFIND')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_method_options(self):
@@ -192,8 +170,6 @@ class TestPRequestCommand(unittest.TestCase):
command.run()
self.assertEqual(self._environ['REQUEST_METHOD'], 'OPTIONS')
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_with_query_string(self):
@@ -202,8 +178,6 @@ class TestPRequestCommand(unittest.TestCase):
command.run()
self.assertEqual(self._environ['QUERY_STRING'], 'a=1&b=2&c')
self.assertEqual(self._path_info, '/abc')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, ['abc'])
def test_command_display_headers(self):
@@ -212,8 +186,6 @@ class TestPRequestCommand(unittest.TestCase):
[('Content-Type', 'text/html; charset=UTF-8')])
command.run()
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(
self._out,
['200 OK', 'Content-Type: text/html; charset=UTF-8', 'abc'])
@@ -223,21 +195,13 @@ class TestPRequestCommand(unittest.TestCase):
headers=[('Content-Type', 'image/jpeg')])
command.run()
self.assertEqual(self._path_info, '/')
- self.assertEqual(self._spec, 'development.ini')
- self.assertEqual(self._app_name, None)
self.assertEqual(self._out, [b'abc'])
def test_command_method_configures_logging(self):
command = self._makeOne(['', 'development.ini', '/'])
- called_args = []
-
- def configure_logging(app_spec):
- called_args.append(app_spec)
-
- command.configure_logging = configure_logging
command.run()
- self.assertEqual(called_args, ['development.ini'])
+ self.assertEqual(self.loader.calls[0]['op'], 'logging')
class Test_main(unittest.TestCase):
diff --git a/pyramid/tests/test_scripts/test_proutes.py b/pyramid/tests/test_scripts/test_proutes.py
index 74293a112..fab5e163e 100644
--- a/pyramid/tests/test_scripts/test_proutes.py
+++ b/pyramid/tests/test_scripts/test_proutes.py
@@ -19,7 +19,8 @@ class TestPRoutesCommand(unittest.TestCase):
def _makeOne(self):
cmd = self._getTargetClass()([])
- cmd.bootstrap = (dummy.DummyBootstrap(),)
+ cmd.bootstrap = dummy.DummyBootstrap()
+ cmd.get_config_loader = dummy.DummyLoader()
cmd.args.config_uri = '/foo/bar/myapp.ini#myapp'
return cmd
@@ -37,14 +38,15 @@ class TestPRoutesCommand(unittest.TestCase):
def test_good_args(self):
cmd = self._getTargetClass()([])
- cmd.bootstrap = (dummy.DummyBootstrap(),)
+ cmd.bootstrap = dummy.DummyBootstrap()
+ cmd.get_config_loader = dummy.DummyLoader()
cmd.args.config_uri = '/foo/bar/myapp.ini#myapp'
cmd.args.config_args = ('a=1',)
route = dummy.DummyRoute('a', '/a')
mapper = dummy.DummyMapper(route)
cmd._get_mapper = lambda *arg: mapper
registry = self._makeRegistry()
- cmd.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ cmd.bootstrap = dummy.DummyBootstrap(registry=registry)
L = []
cmd.out = lambda msg: L.append(msg)
cmd.run()
@@ -52,7 +54,8 @@ class TestPRoutesCommand(unittest.TestCase):
def test_bad_args(self):
cmd = self._getTargetClass()([])
- cmd.bootstrap = (dummy.DummyBootstrap(),)
+ cmd.bootstrap = dummy.DummyBootstrap()
+ cmd.get_config_loader = dummy.DummyLoader()
cmd.args.config_uri = '/foo/bar/myapp.ini#myapp'
cmd.args.config_vars = ('a',)
route = dummy.DummyRoute('a', '/a')
@@ -86,7 +89,7 @@ class TestPRoutesCommand(unittest.TestCase):
mapper = dummy.DummyMapper(route)
command._get_mapper = lambda *arg: mapper
registry = self._makeRegistry()
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
L = []
command.out = L.append
@@ -103,7 +106,7 @@ class TestPRoutesCommand(unittest.TestCase):
L = []
command.out = L.append
registry = self._makeRegistry()
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -124,7 +127,7 @@ class TestPRoutesCommand(unittest.TestCase):
command._get_mapper = lambda *arg: mapper
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -150,7 +153,7 @@ class TestPRoutesCommand(unittest.TestCase):
command._get_mapper = lambda *arg: mapper
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -190,7 +193,7 @@ class TestPRoutesCommand(unittest.TestCase):
command._get_mapper = lambda *arg: mapper
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -218,7 +221,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -252,7 +255,7 @@ class TestPRoutesCommand(unittest.TestCase):
command._get_mapper = lambda *arg: mapper
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -288,7 +291,7 @@ class TestPRoutesCommand(unittest.TestCase):
command._get_mapper = lambda *arg: mapper
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -327,7 +330,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -354,7 +357,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -382,7 +385,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -410,7 +413,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -436,7 +439,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 5)
@@ -461,7 +464,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -491,7 +494,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config2.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config2.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -521,7 +524,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -551,7 +554,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -592,7 +595,7 @@ class TestPRoutesCommand(unittest.TestCase):
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -624,7 +627,7 @@ class TestPRoutesCommand(unittest.TestCase):
command.args.format = 'method,name'
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
@@ -654,7 +657,7 @@ class TestPRoutesCommand(unittest.TestCase):
command.args.format = 'predicates,name,pattern'
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
expected = (
"You provided invalid formats ['predicates'], "
"Available formats are ['name', 'pattern', 'view', 'method']"
@@ -682,10 +685,9 @@ class TestPRoutesCommand(unittest.TestCase):
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
- config_factory = dummy.DummyConfigParserFactory()
- command.ConfigParser = config_factory
- config_factory.items = [('format', 'method\nname')]
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
+ command.get_config_loader = dummy.DummyLoader(
+ {'proutes': {'format': 'method\nname'}})
result = command.run()
self.assertEqual(result, 0)
@@ -715,10 +717,9 @@ class TestPRoutesCommand(unittest.TestCase):
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
- config_factory = dummy.DummyConfigParserFactory()
- command.ConfigParser = config_factory
- config_factory.items = [('format', 'method name')]
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
+ command.get_config_loader = dummy.DummyLoader(
+ {'proutes': {'format': 'method name'}})
result = command.run()
self.assertEqual(result, 0)
@@ -748,10 +749,9 @@ class TestPRoutesCommand(unittest.TestCase):
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
- config_factory = dummy.DummyConfigParserFactory()
- command.ConfigParser = config_factory
- config_factory.items = [('format', 'method,name')]
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
+ command.get_config_loader = dummy.DummyLoader(
+ {'proutes': {'format': 'method,name'}})
result = command.run()
self.assertEqual(result, 0)
@@ -771,7 +771,7 @@ class TestPRoutesCommand(unittest.TestCase):
command = self._makeOne()
L = []
command.out = L.append
- command.bootstrap = (dummy.DummyBootstrap(registry=config.registry),)
+ command.bootstrap = dummy.DummyBootstrap(registry=config.registry)
result = command.run()
self.assertEqual(result, 0)
self.assertEqual(len(L), 3)
diff --git a/pyramid/tests/test_scripts/test_pserve.py b/pyramid/tests/test_scripts/test_pserve.py
index d5578b3ea..485cf38cb 100644
--- a/pyramid/tests/test_scripts/test_pserve.py
+++ b/pyramid/tests/test_scripts/test_pserve.py
@@ -10,16 +10,10 @@ class TestPServeCommand(unittest.TestCase):
def setUp(self):
from pyramid.compat import NativeIO
self.out_ = NativeIO()
- self.config_factory = dummy.DummyConfigParserFactory()
def out(self, msg):
self.out_.write(msg)
- def _get_server(*args, **kwargs):
- def server(app):
- return ''
- return server
-
def _getTargetClass(self):
from pyramid.scripts.pserve import PServeCommand
return PServeCommand
@@ -29,7 +23,8 @@ class TestPServeCommand(unittest.TestCase):
effargs.extend(args)
cmd = self._getTargetClass()(effargs)
cmd.out = self.out
- cmd.ConfigParser = self.config_factory
+ self.loader = dummy.DummyLoader()
+ cmd._get_config_loader = self.loader
return cmd
def test_run_no_args(self):
@@ -38,41 +33,33 @@ class TestPServeCommand(unittest.TestCase):
self.assertEqual(result, 2)
self.assertEqual(self.out_.getvalue(), 'You must give a config file')
- def test_config_vars_no_command(self):
- inst = self._makeOne()
- inst.args.config_uri = 'foo'
- inst.args.config_vars = ['a=1', 'b=2']
- result = inst.get_config_vars()
- self.assertEqual(result, {'a': '1', 'b': '2'})
-
def test_parse_vars_good(self):
inst = self._makeOne('development.ini', 'a=1', 'b=2')
- inst.loadserver = self._get_server
-
app = dummy.DummyApp()
- def get_app(*args, **kwargs):
- app.global_conf = kwargs.get('global_conf', None)
+ def get_app(name, global_conf):
+ app.name = name
+ app.global_conf = global_conf
+ return app
+ self.loader.get_wsgi_app = get_app
+ self.loader.server = lambda x: x
- inst.loadapp = get_app
inst.run()
self.assertEqual(app.global_conf, {'a': '1', 'b': '2'})
def test_parse_vars_bad(self):
inst = self._makeOne('development.ini', 'a')
- inst.loadserver = self._get_server
self.assertRaises(ValueError, inst.run)
def test_config_file_finds_watch_files(self):
inst = self._makeOne('development.ini')
- self.config_factory.items = [(
- 'watch_files',
- 'foo\n/baz\npyramid.tests.test_scripts:*.py',
- )]
- inst.pserve_file_config('/base/path.ini', global_conf={'a': '1'})
- self.assertEqual(self.config_factory.defaults, {
+ loader = self.loader('/base/path.ini')
+ loader.settings = {'pserve': {
+ 'watch_files': 'foo\n/baz\npyramid.tests.test_scripts:*.py',
+ }}
+ inst.pserve_file_config(loader, global_conf={'a': '1'})
+ self.assertEqual(loader.calls[0]['defaults'], {
'a': '1',
- 'here': os.path.abspath('/base'),
})
self.assertEqual(inst.watch_files, set([
os.path.abspath('/base/foo'),
@@ -82,28 +69,26 @@ class TestPServeCommand(unittest.TestCase):
def test_config_file_finds_open_url(self):
inst = self._makeOne('development.ini')
- self.config_factory.items = [(
- 'open_url', 'http://127.0.0.1:8080/',
- )]
- inst.pserve_file_config('/base/path.ini', global_conf={'a': '1'})
- self.assertEqual(self.config_factory.defaults, {
+ loader = self.loader('/base/path.ini')
+ loader.settings = {'pserve': {
+ 'open_url': 'http://127.0.0.1:8080/',
+ }}
+ inst.pserve_file_config(loader, global_conf={'a': '1'})
+ self.assertEqual(loader.calls[0]['defaults'], {
'a': '1',
- 'here': os.path.abspath('/base'),
})
self.assertEqual(inst.open_url, 'http://127.0.0.1:8080/')
- def test__guess_server_url(self):
+ def test_guess_server_url(self):
inst = self._makeOne('development.ini')
- self.config_factory.items = [(
- 'port', '8080',
- )]
- url = inst._guess_server_url(
- '/base/path.ini', 'main', global_conf={'a': '1'})
- self.assertEqual(self.config_factory.defaults, {
+ loader = self.loader('/base/path.ini')
+ loader.settings = {'server:foo': {
+ 'port': '8080',
+ }}
+ url = inst.guess_server_url(loader, 'foo', global_conf={'a': '1'})
+ self.assertEqual(loader.calls[0]['defaults'], {
'a': '1',
- 'here': os.path.abspath('/base'),
})
- self.assertEqual(self.config_factory.parser.section, 'server:main')
self.assertEqual(url, 'http://127.0.0.1:8080')
def test_reload_call_hupper_with_correct_args(self):
diff --git a/pyramid/tests/test_scripts/test_pshell.py b/pyramid/tests/test_scripts/test_pshell.py
index 303964b2b..ca9eb7af2 100644
--- a/pyramid/tests/test_scripts/test_pshell.py
+++ b/pyramid/tests/test_scripts/test_pshell.py
@@ -8,16 +8,16 @@ class TestPShellCommand(unittest.TestCase):
from pyramid.scripts.pshell import PShellCommand
return PShellCommand
- def _makeOne(self, patch_bootstrap=True, patch_config=True,
+ def _makeOne(self, patch_bootstrap=True, patch_loader=True,
patch_args=True, patch_options=True):
cmd = self._getTargetClass()([])
if patch_bootstrap:
self.bootstrap = dummy.DummyBootstrap()
- cmd.bootstrap = (self.bootstrap,)
- if patch_config:
- self.config_factory = dummy.DummyConfigParserFactory()
- cmd.ConfigParser = self.config_factory
+ cmd.bootstrap = self.bootstrap
+ if patch_loader:
+ self.loader = dummy.DummyLoader()
+ cmd.get_config_loader = self.loader
if patch_args:
class Args(object): pass
self.args = Args()
@@ -46,9 +46,6 @@ class TestPShellCommand(unittest.TestCase):
command.default_runner = shell
command.run()
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':self.bootstrap.app, 'root':self.bootstrap.root,
@@ -79,9 +76,6 @@ class TestPShellCommand(unittest.TestCase):
self.assertEqual(
out_calls, ['could not find a shell named "unknown_python_shell"']
)
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertTrue(self.bootstrap.closer.called)
@@ -100,9 +94,6 @@ class TestPShellCommand(unittest.TestCase):
command.args.python_shell = 'ipython'
command.run()
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':self.bootstrap.app, 'root':self.bootstrap.root,
@@ -199,12 +190,9 @@ class TestPShellCommand(unittest.TestCase):
command = self._makeOne()
model = dummy.Dummy()
user = dummy.Dummy()
- self.config_factory.items = [('m', model), ('User', user)]
+ self.loader.settings = {'pshell': {'m': model, 'User': user}}
shell = dummy.DummyShell()
command.run(shell)
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':self.bootstrap.app, 'root':self.bootstrap.root,
@@ -223,12 +211,9 @@ class TestPShellCommand(unittest.TestCase):
env['a'] = 1
env['root'] = 'root override'
env['none'] = None
- self.config_factory.items = [('setup', setup)]
+ self.loader.settings = {'pshell': {'setup': setup}}
shell = dummy.DummyShell()
command.run(shell)
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':self.bootstrap.app, 'root':'root override',
@@ -252,12 +237,9 @@ class TestPShellCommand(unittest.TestCase):
'python': dshell,
}
)
- self.config_factory.items = [
- ('default_shell', 'bpython python\nipython')]
+ self.loader.settings = {'pshell': {
+ 'default_shell': 'bpython python\nipython'}}
command.run()
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertTrue(dshell.called)
@@ -268,12 +250,9 @@ class TestPShellCommand(unittest.TestCase):
env['a'] = 1
env['m'] = 'model override'
env['root'] = 'root override'
- self.config_factory.items = [('setup', setup), ('m', model)]
+ self.loader.settings = {'pshell': {'setup': setup, 'm': model}}
shell = dummy.DummyShell()
command.run(shell)
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':self.bootstrap.app, 'root':'root override',
@@ -291,14 +270,10 @@ class TestPShellCommand(unittest.TestCase):
env['a'] = 1
env['root'] = 'root override'
model = dummy.Dummy()
- self.config_factory.items = [('setup', 'abc'),
- ('m', model)]
+ self.loader.settings = {'pshell': {'setup': 'abc', 'm': model}}
command.args.setup = setup
shell = dummy.DummyShell()
command.run(shell)
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':self.bootstrap.app, 'root':'root override',
@@ -313,13 +288,11 @@ class TestPShellCommand(unittest.TestCase):
def test_command_custom_section_override(self):
command = self._makeOne()
dummy_ = dummy.Dummy()
- self.config_factory.items = [('app', dummy_), ('root', dummy_),
- ('registry', dummy_), ('request', dummy_)]
+ self.loader.settings = {'pshell': {
+ 'app': dummy_, 'root': dummy_, 'registry': dummy_,
+ 'request': dummy_}}
shell = dummy.DummyShell()
command.run(shell)
- self.assertTrue(self.config_factory.parser)
- self.assertEqual(self.config_factory.parser.filename,
- '/foo/bar/myapp.ini')
self.assertEqual(self.bootstrap.a[0], '/foo/bar/myapp.ini#myapp')
self.assertEqual(shell.env, {
'app':dummy_, 'root':dummy_, 'registry':dummy_, 'request':dummy_,
diff --git a/pyramid/tests/test_scripts/test_ptweens.py b/pyramid/tests/test_scripts/test_ptweens.py
index f63069fed..6907b858d 100644
--- a/pyramid/tests/test_scripts/test_ptweens.py
+++ b/pyramid/tests/test_scripts/test_ptweens.py
@@ -8,7 +8,8 @@ class TestPTweensCommand(unittest.TestCase):
def _makeOne(self):
cmd = self._getTargetClass()([])
- cmd.bootstrap = (dummy.DummyBootstrap(),)
+ cmd.bootstrap = dummy.DummyBootstrap()
+ cmd.setup_logging = dummy.dummy_setup_logging()
cmd.args.config_uri = '/foo/bar/myapp.ini#myapp'
return cmd
diff --git a/pyramid/tests/test_scripts/test_pviews.py b/pyramid/tests/test_scripts/test_pviews.py
index 7bdab5804..6ec9defbd 100644
--- a/pyramid/tests/test_scripts/test_pviews.py
+++ b/pyramid/tests/test_scripts/test_pviews.py
@@ -8,7 +8,8 @@ class TestPViewsCommand(unittest.TestCase):
def _makeOne(self, registry=None):
cmd = self._getTargetClass()([])
- cmd.bootstrap = (dummy.DummyBootstrap(registry=registry),)
+ cmd.bootstrap = dummy.DummyBootstrap(registry=registry)
+ cmd.setup_logging = dummy.dummy_setup_logging()
cmd.args.config_uri = '/foo/bar/myapp.ini#myapp'
return cmd
diff --git a/setup.py b/setup.py
index ff3e38874..3048428aa 100644
--- a/setup.py
+++ b/setup.py
@@ -34,6 +34,8 @@ install_requires = [
'venusian >= 1.0a3', # ``ignore``
'translationstring >= 0.4', # py3 compat
'PasteDeploy >= 1.5.0', # py3 compat
+ 'plaster',
+ 'plaster_pastedeploy',
'hupper',
]