From c52e649c6773a99d6077f28ebe0f505d32e72ba6 Mon Sep 17 00:00:00 2001 From: Arndt Droullier Date: Fri, 30 Mar 2012 15:23:55 +0300 Subject: Use predicate.__text__ in predicate mismatch exceptions. See Issue #502 --- pyramid/config/views.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pyramid/config/views.py b/pyramid/config/views.py index ad4df28d8..ac41f7363 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -276,11 +276,13 @@ class ViewDeriver(object): if not predicates: return view def predicate_wrapper(context, request): - if all((predicate(context, request) for predicate in predicates)): - return view(context, request) - view_name = getattr(view, '__name__', view) - raise PredicateMismatch( - 'predicate mismatch for view %s' % view_name) + for predicate in predicates: + if not predicate(context, request): + view_name = getattr(view, '__name__', view) + raise PredicateMismatch( + 'predicate mismatch for view %s (%s)' % ( + view_name, predicate.__text__)) + return view(context, request) def checker(context, request): return all((predicate(context, request) for predicate in predicates)) -- cgit v1.2.3 From 6ef753257617acf8aaf3daaca22de3783970cffe Mon Sep 17 00:00:00 2001 From: Jeff Cook Date: Wed, 4 Jul 2012 18:52:54 -0600 Subject: Include instructions for recursive submodule checkout of Sphinx themes. --- HACKING.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/HACKING.txt b/HACKING.txt index dd735bf22..38c263ed7 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -127,13 +127,19 @@ using to develop Pyramid): 1. Run ``$yourvenv/bin/python setup.py dev docs``. This will cause Sphinx and all development requirements to be installed in your virtualenv. -2. cd to the ``docs`` directory within your Pyramid checkout and execute +2. Update all git submodules from the top-level of your Pyramid checkout, like + so: + git submodule update --init --recursive + This will checkout theme subrepositories and prevent error conditions when + HTML docs are generated. + +3. cd to the ``docs`` directory within your Pyramid checkout and execute ``make clean html SPHINXBUILD=$yourvenv/bin/sphinx-build``. The ``SPHINXBUILD=...`` hair is there in order to tell it to use the virtualenv Python, which will have both Sphinx and Pyramid (for API documentation generation) installed. -3. Open the ``docs/_build/html/index.html`` file to see the resulting HTML +4. Open the ``docs/_build/html/index.html`` file to see the resulting HTML rendering. Change Log -- cgit v1.2.3 From 88bbd46c9a5fab52548f26fe4655a89c00332ad5 Mon Sep 17 00:00:00 2001 From: Maxim Avanov Date: Tue, 10 Jul 2012 21:26:34 +0400 Subject: Replacement markers of url dispatcher can contain regex with colons. --- pyramid/tests/test_urldispatch.py | 8 ++++++++ pyramid/urldispatch.py | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pyramid/tests/test_urldispatch.py b/pyramid/tests/test_urldispatch.py index e15242f75..b2164717e 100644 --- a/pyramid/tests/test_urldispatch.py +++ b/pyramid/tests/test_urldispatch.py @@ -311,6 +311,14 @@ class TestCompileRoute(unittest.TestCase): self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}), '/foo/1/biz/2.html') + + def test_custom_regex_with_colons(self): + matcher, generator = self._callFUT('foo/{baz}/biz/{buz:(?:[^/\.]+)}.{bar}') + self.assertEqual(matcher('/foo/baz/biz/buz.bar'), + {'baz':'baz', 'buz':'buz', 'bar':'bar'}) + self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) + self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}), + '/foo/1/biz/2.html') def test_mixed_newstyle_oldstyle_pattern_defaults_to_newstyle(self): # pattern: '\\/foo\\/(?Pabc)\\/biz\\/(?P[^/]+)\\/bar$' diff --git a/pyramid/urldispatch.py b/pyramid/urldispatch.py index cccff14ba..4182ea665 100644 --- a/pyramid/urldispatch.py +++ b/pyramid/urldispatch.py @@ -148,7 +148,9 @@ def _compile_route(route): name = pat.pop() # unicode name = name[1:-1] if ':' in name: - name, reg = name.split(':') + # reg may contain colons as well, + # so we must strictly split name into two parts + name, reg = name.split(':', 1) else: reg = '[^/]+' gen.append('%%(%s)s' % native_(name)) # native -- cgit v1.2.3 From 3074e78a5b3818bf6c6cb43b832e4ab1df845e16 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 10 Jul 2012 15:56:38 -0400 Subject: garden --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 3cb2f2848..c06b8106d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,9 @@ Bug Fixes return the empty list. This was incorrect, it should have unconditionally returned ``[Everyone]``, and now does. +- Explicit url dispatch regexes can now contain colons. + https://github.com/Pylons/pyramid/issues/629 + Features -------- -- cgit v1.2.3 From e652518e00cde05b55b065196a460efd9bc86e32 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 13 Jul 2012 12:08:18 -0400 Subject: - On at least one 64-bit Ubuntu system under Python 3.2, using the ``view_config`` decorator caused a ``RuntimeError: dictionary changed size during iteration`` exception. It no longer does. See https://github.com/Pylons/pyramid/issues/635 for more information. - Fixes issue #635. --- CHANGES.txt | 5 +++++ pyramid/view.py | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index c06b8106d..c6afaf0c7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -12,6 +12,11 @@ Bug Fixes - Explicit url dispatch regexes can now contain colons. https://github.com/Pylons/pyramid/issues/629 +- On at least one 64-bit Ubuntu system under Python 3.2, using the + ``view_config`` decorator caused a ``RuntimeError: dictionary changed size + during iteration`` exception. It no longer does. See + https://github.com/Pylons/pyramid/issues/635 for more information. + Features -------- diff --git a/pyramid/view.py b/pyramid/view.py index bb531c326..1df0849c0 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -199,7 +199,7 @@ class view_config(object): custom_predicates=default, context=default, decorator=default, mapper=default, http_cache=default, match_param=default): - L = locals() + L = dict(locals()) # See issue #635 for dict() rationale if (context is not default) or (for_ is not default): L['context'] = context or for_ for k, v in L.items(): @@ -367,7 +367,7 @@ class notfound_view_config(object): path_info=default, custom_predicates=default, decorator=default, mapper=default, match_param=default, append_slash=False): - L = locals() + L = dict(locals()) # See issue #635 for dict() rationale for k, v in L.items(): if k not in ('self', 'L') and v is not default: self.__dict__[k] = v @@ -432,7 +432,7 @@ class forbidden_view_config(object): xhr=default, accept=default, header=default, path_info=default, custom_predicates=default, decorator=default, mapper=default, match_param=default): - L = locals() + L = dict(locals()) # See issue #635 for dict() rationale for k, v in L.items(): if k not in ('self', 'L') and v is not default: self.__dict__[k] = v -- cgit v1.2.3 From 70ba5b97f53ac178dac8f81109596fb47bbadde5 Mon Sep 17 00:00:00 2001 From: Siddhartha Kasivajhula Date: Sat, 21 Jul 2012 14:29:00 -0700 Subject: corrected table name tables->pages --- docs/tutorials/wiki2/design.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst index 2e6fc0e77..deaf32ef6 100644 --- a/docs/tutorials/wiki2/design.rst +++ b/docs/tutorials/wiki2/design.rst @@ -20,7 +20,7 @@ Models We'll be using a SQLite database to hold our wiki data, and we'll be using :term:`SQLAlchemy` to access the data in this database. -Within the database, we define a single table named `tables`, whose elements +Within the database, we define a single table named `pages`, whose elements will store the wiki pages. There are two columns: `name` and `data`. URLs like ``/PageName`` will try to find an element in -- cgit v1.2.3 From 14f9fe44ec75c055d89374a7852e1ca2af0ff31c Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Wed, 25 Jul 2012 14:02:10 -0500 Subject: add logging call to wsgi setup --- docs/tutorials/modwsgi/index.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst index e070f8eda..d11167344 100644 --- a/docs/tutorials/modwsgi/index.rst +++ b/docs/tutorials/modwsgi/index.rst @@ -73,9 +73,10 @@ commands and files. .. code-block:: python - from pyramid.paster import get_app - application = get_app( - '/Users/chrism/modwsgi/env/myapp/production.ini', 'main') + from pyramid.paster import get_app, setup_logging + ini_path = '/Users/chrism/modwsgi/env/myapp/production.ini' + setup_logging(ini_path) + application = get_app(ini_path, 'main') The first argument to ``get_app`` is the project configuration file name. It's best to use the ``production.ini`` file provided by your @@ -85,6 +86,10 @@ commands and files. ``application`` is important: mod_wsgi requires finding such an assignment when it opens the file. + The call to ``setup_logging`` initializes the standard library's + `logging` module to allow logging within your application. + See :ref:`logging_config`. + #. Make the ``pyramid.wsgi`` script executable. .. code-block:: text -- cgit v1.2.3 From 440e2e7d94648973a3f9b5aa6136792d02ae1e9e Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 29 Jul 2012 13:18:44 -0400 Subject: give traverse_predicate a __text__ and add a developer note about __text__ --- pyramid/config/util.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyramid/config/util.py b/pyramid/config/util.py index b8d0f2319..4e4c93be3 100644 --- a/pyramid/config/util.py +++ b/pyramid/config/util.py @@ -113,6 +113,12 @@ def make_predicates(xhr=None, request_method=None, path_info=None, # any predicates get an order of MAX_ORDER, meaning that they will # be tried very last. + # NB: each predicate callable constructed by this function (or examined + # by this function, in the case of custom predicates) must leave this + # function with a ``__text__`` attribute. The subsystem which reports + # errors when no predicates match depends upon the existence of this + # attribute on each predicate callable. + predicates = [] weights = [] h = md5() @@ -273,6 +279,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None, tvalue = tgenerate(m) # tvalue will be urlquoted string m['traverse'] = traversal_path(tvalue) # will be seq of unicode return True + traverse_predicate.__text__ = 'traverse matchdict pseudo-predicate' # This isn't actually a predicate, it's just a infodict # modifier that injects ``traverse`` into the matchdict. As a # result, the ``traverse_predicate`` function above always -- cgit v1.2.3 From 61a57eaaa82c3e001ee3b0102e7a1b6cdb42532d Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Sun, 29 Jul 2012 14:54:34 -0400 Subject: - When there is a predicate mismatch exception (seen when no view matches for a given request due to predicates not working), the exception now contains a textual description of the predicate which didn't match. - Fixes issue #502 and issue #519. --- CHANGES.txt | 4 ++++ pyramid/tests/test_config/test_views.py | 31 +++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index c6afaf0c7..ecb2bf659 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -54,3 +54,7 @@ Features result for the view being called. The uri format using an asset spec is package:path/to/template#defname.mako. The old way of returning a tuple from the view is supported for backward compatibility, ('defname', {}). + +- When there is a predicate mismatch exception (seen when no view matches for + a given request due to predicates not working), the exception now contains + a textual description of the predicate which didn't match. diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index 9b46f83c9..ebf1dfb39 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -2905,6 +2905,7 @@ class TestViewDeriver(unittest.TestCase): view = lambda *arg: response def predicate1(context, request): return False + predicate1.__text__ = 'text' deriver = self._makeOne(predicates=[predicate1]) result = deriver(view) request = self._makeRequest() @@ -2912,7 +2913,8 @@ class TestViewDeriver(unittest.TestCase): try: result(None, None) except PredicateMismatch as e: - self.assertEqual(e.detail, 'predicate mismatch for view ') + self.assertEqual(e.detail, + 'predicate mismatch for view (text)') else: # pragma: no cover raise AssertionError @@ -2921,6 +2923,7 @@ class TestViewDeriver(unittest.TestCase): def myview(request): pass def predicate1(context, request): return False + predicate1.__text__ = 'text' deriver = self._makeOne(predicates=[predicate1]) result = deriver(myview) request = self._makeRequest() @@ -2928,7 +2931,29 @@ class TestViewDeriver(unittest.TestCase): try: result(None, None) except PredicateMismatch as e: - self.assertEqual(e.detail, 'predicate mismatch for view myview') + self.assertEqual(e.detail, + 'predicate mismatch for view myview (text)') + else: # pragma: no cover + raise AssertionError + + def test_predicate_mismatch_exception_has_text_in_detail(self): + from pyramid.exceptions import PredicateMismatch + def myview(request): pass + def predicate1(context, request): + return True + predicate1.__text__ = 'pred1' + def predicate2(context, request): + return False + predicate2.__text__ = 'pred2' + deriver = self._makeOne(predicates=[predicate1, predicate2]) + result = deriver(myview) + request = self._makeRequest() + request.method = 'POST' + try: + result(None, None) + except PredicateMismatch as e: + self.assertEqual(e.detail, + 'predicate mismatch for view myview (pred2)') else: # pragma: no cover raise AssertionError @@ -2974,9 +2999,11 @@ class TestViewDeriver(unittest.TestCase): def predicate1(context, request): predicates.append(True) return True + predicate1.__text__ = 'text' def predicate2(context, request): predicates.append(True) return False + predicate2.__text__ = 'text' deriver = self._makeOne(predicates=[predicate1, predicate2]) result = deriver(view) request = self._makeRequest() -- cgit v1.2.3 From b4f193258837f94d6e4d069f37538dc6f55af709 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Thu, 2 Aug 2012 00:37:26 -0400 Subject: closes #643 --- docs/tutorials/wiki2/authorization.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst index 2ef55d15b..d7bd24a53 100644 --- a/docs/tutorials/wiki2/authorization.rst +++ b/docs/tutorials/wiki2/authorization.rst @@ -353,7 +353,7 @@ when we're done: .. literalinclude:: src/authorization/tutorial/views.py :linenos: - :emphasize-lines: 11,14-18,31,37,58,61,73,76,88,91-117,119-123 + :emphasize-lines: 11,14-18,25,31,37,58,61,73,76,88,91-117,119-123 :language: python (Only the highlighted lines need to be added.) -- cgit v1.2.3