diff options
| author | Steve Piercy <web@stevepiercy.com> | 2013-03-21 13:32:14 -0700 |
|---|---|---|
| committer | Steve Piercy <web@stevepiercy.com> | 2013-03-21 13:32:14 -0700 |
| commit | a17c712f7f836b3506be069f60ee9ed8a8edb42b (patch) | |
| tree | d42a28e8b692fd6da1289c2ca8f99a18a8a3e59f | |
| parent | 124daa3f3de2350ee4079d684736acd10b415046 (diff) | |
| parent | f38126c3214c936f022e68a1cac88c3cd8644879 (diff) | |
| download | pyramid-a17c712f7f836b3506be069f60ee9ed8a8edb42b.tar.gz pyramid-a17c712f7f836b3506be069f60ee9ed8a8edb42b.tar.bz2 pyramid-a17c712f7f836b3506be069f60ee9ed8a8edb42b.zip | |
Merge remote-tracking branch 'upstream/master'
Conflicts:
docs/tutorials/wiki2/installation.rst
| -rw-r--r-- | CHANGES.txt | 8 | ||||
| -rw-r--r-- | CONTRIBUTORS.txt | 2 | ||||
| -rw-r--r-- | docs/api/paster.rst | 2 | ||||
| -rw-r--r-- | docs/conf.py | 11 | ||||
| -rw-r--r-- | docs/narr/router.rst | 2 | ||||
| -rw-r--r-- | docs/narr/urldispatch.rst | 7 | ||||
| -rw-r--r-- | docs/narr/viewconfig.rst | 4 | ||||
| -rw-r--r-- | docs/tutorials/wiki2/basiclayout.rst | 6 | ||||
| -rw-r--r-- | docs/tutorials/wiki2/definingmodels.rst | 11 | ||||
| -rw-r--r-- | docs/tutorials/wiki2/installation.rst | 18 | ||||
| -rw-r--r-- | pyramid/paster.py | 22 | ||||
| -rw-r--r-- | pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py | 9 | ||||
| -rw-r--r-- | pyramid/tests/fixtures/dummy.ini | 4 | ||||
| -rw-r--r-- | pyramid/tests/test_paster.py | 44 |
14 files changed, 107 insertions, 43 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 6ff54884a..2366522df 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -21,6 +21,14 @@ Features define how to properly handle IPv6. See https://github.com/Pylons/pyramid/issues/831. +- Make it possible to use variable arguments via + ``pyramid.paster.get_appsettings``. This also allowed the generated + ``initialize_db`` script from the ``alchemy`` scaffold to grow support + for options in the form ``a=1 b=2`` so you can fill in + values in a parameterized ``.ini`` file, e.g. + ``initialize_myapp_db etc/development.ini a=1 b=2``. + See https://github.com/Pylons/pyramid/pull/911 + Bug Fixes --------- diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 02fb81528..94eee9443 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -194,3 +194,5 @@ Contributors - John Anderson, 2012/11/14 - Bert JW Regeer, 2013/02/01 + +- Georges Dubus, 2013/03/21 diff --git a/docs/api/paster.rst b/docs/api/paster.rst index bde128e05..edc3738fc 100644 --- a/docs/api/paster.rst +++ b/docs/api/paster.rst @@ -9,6 +9,6 @@ .. autofunction:: get_app(config_uri, name=None, options=None) - .. autofunction:: get_appsettings(config_uri, name=None) + .. autofunction:: get_appsettings(config_uri, name=None, options=None) .. autofunction:: setup_logging(config_uri) diff --git a/docs/conf.py b/docs/conf.py index 8d22d4d42..eff6db488 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -55,13 +55,14 @@ extensions = [ # Looks for objects in external projects intersphinx_mapping = { - 'who': ('http://docs.repoze.org/who/2.0', None), - 'python': ('http://docs.python.org', None), - 'python3': ('http://docs.python.org/3', None), - 'tstring': + 'sqla': ('http://docs.sqlalchemy.org/en/latest', None), + 'who': ('http://docs.repoze.org/who/latest', None), + 'python': ('http://docs.python.org', None), + 'python3': ('http://docs.python.org/3', None), + 'tstring': ('http://docs.pylonsproject.org/projects/translationstring/en/latest', None), - 'venusian': + 'venusian': ('http://docs.pylonsproject.org/projects/venusian/en/latest', None), } diff --git a/docs/narr/router.rst b/docs/narr/router.rst index b78362066..ac3deefdc 100644 --- a/docs/narr/router.rst +++ b/docs/narr/router.rst @@ -46,7 +46,7 @@ request enters a :app:`Pyramid` application through to the point that :class:`~pyramid.interfaces.IRoute` object representing the route which matched. The root object associated with the route found is also generated: if the :term:`route configuration` which matched has an - associated a ``factory`` argument, this factory is used to generate the + associated ``factory`` argument, this factory is used to generate the root object, otherwise a default :term:`root factory` is used. #. If a route match was *not* found, and a ``root_factory`` argument was diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 181b07259..0656a1833 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -16,12 +16,13 @@ receives the :term:`request` and returns a :term:`response` object. High-Level Operational Overview ------------------------------- -If route configuration is present in an application, the :app:`Pyramid` +If any route configuration is present in an application, the :app:`Pyramid` :term:`Router` checks every incoming request against an ordered set of URL matching patterns present in a *route map*. If any route pattern matches the information in the :term:`request`, -:app:`Pyramid` will invoke :term:`view lookup` to find a matching view. +:app:`Pyramid` will invoke the :term:`view lookup` process to find a +matching view. If no route pattern in the route map matches the information in the :term:`request` provided in your application, :app:`Pyramid` will fail over @@ -81,7 +82,7 @@ this is a portion of your project's ``__init__.py``: Note that we don't call :meth:`~pyramid.config.Configurator.add_view` in this setup code. However, the above :term:`scan` execution -``config.scan('mypackage')`` will pick up all :term:`configuration +``config.scan('mypackage')`` will pick up each :term:`configuration decoration`, including any objects decorated with the :class:`pyramid.view.view_config` decorator in the ``mypackage`` Python package. For example, if you have a ``views.py`` in your package, a scan will diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst index d3221db3c..e0338c442 100644 --- a/docs/narr/viewconfig.rst +++ b/docs/narr/viewconfig.rst @@ -62,9 +62,9 @@ particular view callable. :term:`View predicate` attributes are an important part of view configuration that enables the :term:`view lookup` subsystem to find and invoke the -appropriate view. The greater number of predicate attributes possessed by a +appropriate view. The greater the number of predicate attributes possessed by a view's configuration, the more specific the circumstances need to be before -the registered view callable will be invoked. The fewer number of predicates +the registered view callable will be invoked. The fewer the number of predicates which are supplied to a particular view configuration, the more likely it is that the associated view callable will be invoked. A view with five predicates will always be found and evaluated before a view with two, for diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst index 86fe97956..eb2445864 100644 --- a/docs/tutorials/wiki2/basiclayout.rst +++ b/docs/tutorials/wiki2/basiclayout.rst @@ -43,9 +43,9 @@ above is executed. It accepts some settings and returns a :term:`WSGI` application. (See :ref:`startup_chapter` for more about ``pserve``.) The main function first creates a :term:`SQLAlchemy` database engine using -``engine_from_config`` from the ``sqlalchemy.`` prefixed settings in the -``development.ini`` file's ``[app:main]`` section. This will be a URI -(something like ``sqlite://``): +:func:`sqlalchemy.engine_from_config` from the ``sqlalchemy.`` prefixed +settings in the ``development.ini`` file's ``[app:main]`` section. +This will be a URI (something like ``sqlite://``): .. literalinclude:: src/basiclayout/tutorial/__init__.py :lines: 13 diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst index bd1cb00d7..60427a911 100644 --- a/docs/tutorials/wiki2/definingmodels.rst +++ b/docs/tutorials/wiki2/definingmodels.rst @@ -34,7 +34,7 @@ sample and we're not going to use it. Then, we added a ``Page`` class. Because this is a SQLAlchemy application, this class inherits from an instance of -:class:`sqlalchemy.ext.declarative.declarative_base`. +:func:`sqlalchemy.ext.declarative.declarative_base`. .. literalinclude:: src/models/tutorial/models.py :pyobject: Page @@ -45,9 +45,10 @@ As you can see, our ``Page`` class has a class level attribute ``__tablename__`` which equals the string ``'pages'``. This means that SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our ``Page`` class will also have class-level attributes named ``id``, ``name`` and -``data`` (all instances of :class:`sqlalchemy.Column`). These will map to -columns in the ``pages`` table. The ``id`` attribute will be the primary key -in the table. The ``name`` attribute will be a text attribute, each value of +``data`` (all instances of :class:`sqlalchemy.schema.Column`). +These will map to columns in the ``pages`` table. +The ``id`` attribute will be the primary key in the table. +The ``name`` attribute will be a text attribute, each value of which needs to be unique within the column. The ``data`` attribute is a text attribute that will hold the body of each page. @@ -77,8 +78,6 @@ following: Installing the Project and re-initializing the Database ------------------------------------------------------- -Redo the steps in :ref:`installing_project_in_dev_mode`. - Because our model has changed, in order to reinitialize the database, we need to rerun the ``initialize_tutorial_db`` command to pick up the changes you've made to both the models.py file and to the initializedb.py file. diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst index a8b8ee877..dd7c76d5f 100644 --- a/docs/tutorials/wiki2/installation.rst +++ b/docs/tutorials/wiki2/installation.rst @@ -70,6 +70,7 @@ Install Pyramid Into the Virtual Python Environment Install SQLite3 and Its Development Packages -------------------------------------------- +<<<<<<< HEAD If you used a package manager to install your Python or if you compiled your Python from source, then you must install SQLite3 and its development packages. If you downloaded your Python as an installer @@ -78,23 +79,40 @@ the next section :ref:`sql_making_a_project`.. If you need to install the SQLite3 packages, then, for example, using the Debian system and apt-get, the command would be the following: +======= +Install SQLite3 and its development packages if you don't already +have them installed. Usually this is via your system's package +manager. On a Debian system, this would be: +>>>>>>> upstream/master .. code-block:: text $ sudo apt-get install libsqlite3-dev +<<<<<<< HEAD Change Directory to Your Virtual Python Environment --------------------------------------------------- Change directory to the ``pyramidtut`` directory. **On UNIX:** +======= +Entering the virtualenv +----------------------- + +Do not forget to switch to the ``pyramidtut`` directory. +In order to do so, run this command if you are on Unix: +>>>>>>> upstream/master .. code-block:: text $ cd pyramidtut +<<<<<<< HEAD **On Windows** +======= +And run this if you are on Windows: +>>>>>>> upstream/master .. code-block:: text diff --git a/pyramid/paster.py b/pyramid/paster.py index ce07d1fe0..967543849 100644 --- a/pyramid/paster.py +++ b/pyramid/paster.py @@ -23,26 +23,34 @@ def get_app(config_uri, name=None, options=None, loadapp=loadapp): path, section = _getpathsec(config_uri, name) config_name = 'config:%s' % path here_dir = os.getcwd() - if options: - kw = {'global_conf': options} - else: - kw = {} - app = loadapp(config_name, name=section, relative_to=here_dir, **kw) + app = loadapp( + config_name, + name=section, + relative_to=here_dir, + global_conf=options) return app -def get_appsettings(config_uri, name=None, appconfig=appconfig): +def get_appsettings(config_uri, name=None, options=None, appconfig=appconfig): """ Return a dictionary representing the key/value pairs in an ``app`` section within the file represented by ``config_uri``. + ``options``, if passed, should be a dictionary used as variable assignments + like ``{'http_port': 8080}``. This is useful if e.g. ``%(http_port)s`` is + used in the config file. + 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) + return appconfig( + config_name, + name=section, + relative_to=here_dir, + global_conf=options) def setup_logging(config_uri, fileConfig=fileConfig, configparser=configparser): diff --git a/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py b/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py index 66feb3008..7dfdece15 100644 --- a/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py +++ b/pyramid/scaffolds/alchemy/+package+/scripts/initializedb.py @@ -9,6 +9,8 @@ from pyramid.paster import ( setup_logging, ) +from pyramid.scripts.common import parse_vars + from ..models import ( DBSession, MyModel, @@ -18,17 +20,18 @@ from ..models import ( def usage(argv): cmd = os.path.basename(argv[0]) - print('usage: %s <config_uri>\n' + print('usage: %s <config_uri> [var=value]\n' '(example: "%s development.ini")' % (cmd, cmd)) sys.exit(1) def main(argv=sys.argv): - if len(argv) != 2: + if len(argv) < 2: usage(argv) config_uri = argv[1] + options = parse_vars(argv[2:]) setup_logging(config_uri) - settings = get_appsettings(config_uri) + settings = get_appsettings(config_uri, options=options) engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) Base.metadata.create_all(engine) diff --git a/pyramid/tests/fixtures/dummy.ini b/pyramid/tests/fixtures/dummy.ini new file mode 100644 index 000000000..bc2281168 --- /dev/null +++ b/pyramid/tests/fixtures/dummy.ini @@ -0,0 +1,4 @@ +[app:myapp] +use = call:pyramid.tests.test_paster:make_dummyapp + +foo = %(bar)s diff --git a/pyramid/tests/test_paster.py b/pyramid/tests/test_paster.py index b72e0e6b6..5e341172c 100644 --- a/pyramid/tests/test_paster.py +++ b/pyramid/tests/test_paster.py @@ -1,12 +1,12 @@ import os import unittest +here = os.path.dirname(__file__) + class Test_get_app(unittest.TestCase): - def _callFUT(self, config_file, section_name, options=None, loadapp=None): + def _callFUT(self, config_file, section_name, **kw): from pyramid.paster import get_app - return get_app( - config_file, section_name, options=options, loadapp=loadapp - ) + return get_app(config_file, section_name, **kw) def test_it(self): app = DummyApp() @@ -55,15 +55,23 @@ class Test_get_app(unittest.TestCase): self.assertEqual(loadapp.kw, {'global_conf':options}) self.assertEqual(result, app) + def test_it_with_dummyapp_requiring_options(self): + options = {'bar': 'baz'} + app = self._callFUT( + os.path.join(here, 'fixtures', 'dummy.ini'), + 'myapp', options=options) + self.assertEqual(app.settings['foo'], 'baz') + class Test_get_appsettings(unittest.TestCase): - def _callFUT(self, config_file, section_name, appconfig): + def _callFUT(self, config_file, section_name, **kw): from pyramid.paster import get_appsettings - return get_appsettings(config_file, section_name, appconfig) + return get_appsettings(config_file, section_name, **kw) def test_it(self): values = {'a':1} appconfig = DummyLoadWSGI(values) - result = self._callFUT('/foo/bar/myapp.ini', 'myapp', appconfig) + 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()) @@ -72,7 +80,8 @@ class Test_get_appsettings(unittest.TestCase): def test_it_with_hash(self): values = {'a':1} appconfig = DummyLoadWSGI(values) - result = self._callFUT('/foo/bar/myapp.ini#myapp', None, appconfig) + 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()) @@ -81,12 +90,20 @@ class Test_get_appsettings(unittest.TestCase): 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) + 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()) self.assertEqual(result, values) + def test_it_with_dummyapp_requiring_options(self): + options = {'bar': 'baz'} + result = self._callFUT( + os.path.join(here, 'fixtures', 'dummy.ini'), + 'myapp', options=options) + self.assertEqual(result['foo'], 'baz') + class Test_setup_logging(unittest.TestCase): def _callFUT(self, config_file): from pyramid.paster import setup_logging @@ -165,6 +182,12 @@ class DummyApp: def __init__(self): self.registry = dummy_registry +def make_dummyapp(global_conf, **settings): + app = DummyApp() + app.settings = settings + app.global_conf = global_conf + return app + class DummyRequest: application_url = 'http://example.com:5432' script_name = '' @@ -181,6 +204,3 @@ class DummyConfigParser(object): class DummyConfigParserModule(object): ConfigParser = DummyConfigParser - - - |
