Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Enhancement: Route-Prefixing re Issue #406 #414

Closed
wants to merge 10 commits into from

1 participant

@simonyarde

#406

route_prefix doesn't allow the prefix pattern to match without a
trailing slash

Suggested solution:

  • Create a route_pattern class (extending list) to centralise route joining operations, principally providing a __str__ method.

  • Implement @mmerickel's route_prefix configurative behaviour via route_pattern.match_slash_style bool attribute, where left-most item influences the route-pattern slash-style (slash-appended or non-slash-appended).

  • Provide (optional) route_suffix as the logical compliment to route_prefix, but having no configurative behaviour; route_prefix affects the route-pattern after the addition of any suffixes. Route-suffixes are added outward with the outer-most include's route-suffix added last.

simonyarde added some commits
@simonyarde simonyarde Enhancement: Route-Prefixing re Issue #406 (initial commit)
Pylons/pyramid#406

    route_prefix doesn't allow the prefix pattern to match without a
    trailing slash

Enhances route-prefixing by offering greater configuration flexibility to
resolve issue #406 comprehensively.

Enabled by ``pyramid.allow_empty_pattern`` for BW compatibility.

Relevant toward creating more-explicit configuration behavior and supporting
project designs that use the non-slash-appended route-style without ugly
workarounds.

Supports TIMTOWTDI design defense.

Option to ship Pyramid with whatever default is deemed most 'correct' as the web evolves.

Affects project that:
a.) enable ``pyramid.allow_empty_pattern``, AND;
b.) mount an empty pattern under a prefix ('/prefix' + ''), AND;
c.) expect a slash-appended route to be created ('/prefix/').

Docs:
- Provided further route-prefixing design examples re sub-callables and
  nested prefixes where common usage might be to prefix a locale string to
  a module routes (e.g. ``/{_LOCALE_}/users/show``);

- Documented enhanced route-prefix behaviour and added advisory note for
  existing projects that want to enable ``pyramid.allow_empty_pattern``.
a0cb44b
@simonyarde simonyarde Added improved join_route_pattern utility to accept any number of pat…
…terns
7b8c142
@simonyarde simonyarde Made join_route_pattern doc less specific f22e533
@simonyarde simonyarde Reverted: REMOVED allow_empty_pattern global 4ffaf86
@simonyarde simonyarde Modify route-prefix behaviour re @mmerickel's proposal where rroute-p…
…refix has configurative behaviour, and add complementary route-suffix behaviour to give control over the other end of the patterh i.e. control over creation of a slash-appended or non-slash-appended routes
780a59b
@simonyarde simonyarde Change approach to passing prefix/suffix lists instead of strings 8fe2f10
@simonyarde

Demonstrate approach of passing route_prefixes as lists instead of strings, in order to simplify code and do all route-pattern creation in add_route.

Todo: change var names route_prefix to route_prefix_list as appropriate (same for route_suffix).

simonyarde added some commits
@simonyarde simonyarde Initialise route_prefix as route_pattern_list or None, revert route_p…
…refix_list varname to route_prefix, same for route_suffix, prepend suffixes to avoid later copy-and-reverse
5c25de9
@simonyarde simonyarde Remove reverse route_suffix (now contructed correctly by include), re…
…move list initialisation
67be9df
@simonyarde simonyarde Merge branch 'master' into route-prefix-issue-406 7a6df9b
@simonyarde simonyarde Add ``route_pattern.match_slash_style`` attribute to centralise route…
…-pattern

operations in ``route_pattern class``, and  make code that uses
``route_pattern`` class neater. Reformat text-width of doc additions.
a89f872
@simonyarde

Finally bring all thinking into a neat route_pattern object and route_pattern.match_slash_style attribute, in order to centralise operations with route-patterns.

@simonyarde

Closed as I have proposed an alternative solution and code

@simonyarde simonyarde closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 23, 2012
  1. @simonyarde

    Enhancement: Route-Prefixing re Issue #406 (initial commit)

    simonyarde authored
    Pylons/pyramid#406
    
        route_prefix doesn't allow the prefix pattern to match without a
        trailing slash
    
    Enhances route-prefixing by offering greater configuration flexibility to
    resolve issue #406 comprehensively.
    
    Enabled by ``pyramid.allow_empty_pattern`` for BW compatibility.
    
    Relevant toward creating more-explicit configuration behavior and supporting
    project designs that use the non-slash-appended route-style without ugly
    workarounds.
    
    Supports TIMTOWTDI design defense.
    
    Option to ship Pyramid with whatever default is deemed most 'correct' as the web evolves.
    
    Affects project that:
    a.) enable ``pyramid.allow_empty_pattern``, AND;
    b.) mount an empty pattern under a prefix ('/prefix' + ''), AND;
    c.) expect a slash-appended route to be created ('/prefix/').
    
    Docs:
    - Provided further route-prefixing design examples re sub-callables and
      nested prefixes where common usage might be to prefix a locale string to
      a module routes (e.g. ``/{_LOCALE_}/users/show``);
    
    - Documented enhanced route-prefix behaviour and added advisory note for
      existing projects that want to enable ``pyramid.allow_empty_pattern``.
Commits on Jan 25, 2012
  1. @simonyarde
  2. @simonyarde
  3. @simonyarde
  4. @simonyarde

    Modify route-prefix behaviour re @mmerickel's proposal where rroute-p…

    simonyarde authored
    …refix has configurative behaviour, and add complementary route-suffix behaviour to give control over the other end of the patterh i.e. control over creation of a slash-appended or non-slash-appended routes
Commits on Jan 27, 2012
  1. @simonyarde
Commits on Jan 30, 2012
  1. @simonyarde

    Initialise route_prefix as route_pattern_list or None, revert route_p…

    simonyarde authored
    …refix_list varname to route_prefix, same for route_suffix, prepend suffixes to avoid later copy-and-reverse
  2. @simonyarde
  3. @simonyarde
Commits on Feb 2, 2012
  1. @simonyarde

    Add ``route_pattern.match_slash_style`` attribute to centralise route…

    simonyarde authored
    …-pattern
    
    operations in ``route_pattern class``, and  make code that uses
    ``route_pattern`` class neater. Reformat text-width of doc additions.
This page is out of date. Refresh to see the latest.
View
60 pyramid/config/__init__.py
@@ -71,6 +71,7 @@
from pyramid.config.util import (
action_method,
ActionInfo,
+ route_pattern,
)
from pyramid.config.views import ViewsConfiguratorMixin
from pyramid.config.zca import ZCAConfiguratorMixin
@@ -105,7 +106,8 @@ class Configurator(
``authorization_policy``, ``renderers``, ``debug_logger``,
``locale_negotiator``, ``request_factory``, ``renderer_globals_factory``,
``default_permission``, ``session_factory``, ``default_view_mapper``,
- ``autocommit``, ``exceptionresponse_view`` and ``route_prefix``.
+ ``autocommit``, ``exceptionresponse_view``, ``route_prefix``, and
+ ``route_suffix``.
If the ``registry`` argument is passed as a non-``None`` value, it must
be an instance of the :class:`pyramid.registry.Registry` class
@@ -239,6 +241,11 @@ class Configurator(
:meth:`pyramid.config.Configurator.add_route` will have the specified path
prepended to their pattern. This parameter is new in Pyramid 1.2.
+ If ``route_suffix`` is passed, all routes added with
+ :meth:`pyramid.config.Configurator.add_route` will have the specified path
+ appended to their pattern. The ``route_suffix`` parameter is new in
+ Pyramid X.X.
+
If ``introspector`` is passed, it must be an instance implementing the
attributes and methods of :class:`pyramid.interfaces.IIntrospector`. If
``introspector`` is not passed (or is passed as ``None``), the default
@@ -272,6 +279,7 @@ def __init__(self,
autocommit=False,
exceptionresponse_view=default_exceptionresponse_view,
route_prefix=None,
+ route_suffix=None,
introspector=None,
):
if package is None:
@@ -283,6 +291,7 @@ def __init__(self,
self.registry = registry
self.autocommit = autocommit
self.route_prefix = route_prefix
+ self.route_suffix = route_suffix
if registry is None:
registry = Registry(self.package_name)
self.registry = registry
@@ -589,7 +598,7 @@ def commit(self):
self.action_state.execute_actions(introspector=self.introspector)
self.action_state = ActionState() # old actions have been processed
- def include(self, callable, route_prefix=None):
+ def include(self, callable, route_prefix=None, route_suffix=None):
"""Include a configuration callables, to support imperative
application extensibility.
@@ -681,25 +690,39 @@ def main(global_config, **settings):
pattern.
The ``route_prefix`` parameter is new as of Pyramid 1.2.
+
+ When the ``route_prefix`` parameter is provided to the outer-most
+ ``include`` it has a special configurative property. If ``route_prefix``
+ ends with a ``/`` then the route will end with a ``/``. If the
+ ``route_prefix`` does not end with a ``/`` then the route created will
+ also not end with a ``/``. In this way implementers may mount existing
+ callables or third-party modules with a slash-appended-style that
+ matches the rest of their application.
+
+ The above configurative behaviour of ``route_prefix`` is new as of
+ Pyramid 1.X.
+
+ The ``route_suffix`` parameter complements ``route_prefix``, allowing a
+ suffix to be appended to included routes. However ``route_suffix`` does
+ not have the same configurative property as ``route_prefix``, since
+ ``route_prefix`` ultimately decides whether the mounted routes
+ (including the suffix) will be slash-appended or not.
+
+ The ``route_suffix`` parameter is new as of Pyramid 1.X.
+
"""
# """ <-- emacs
action_state = self.action_state
- if route_prefix is None:
- route_prefix = ''
-
- old_route_prefix = self.route_prefix
- if old_route_prefix is None:
- old_route_prefix = ''
-
- route_prefix = '%s/%s' % (
- old_route_prefix.rstrip('/'),
- route_prefix.lstrip('/')
- )
- route_prefix = route_prefix.strip('/')
- if not route_prefix:
- route_prefix = None
+ if not route_prefix is None:
+ route_prefix = route_pattern(
+ (self.route_prefix or []) + [route_prefix]
+ )
+ if not route_suffix is None:
+ route_suffix = route_pattern(
+ [route_suffix] + (self.route_suffix or [])
+ )
c = self.maybe_dotted(callable)
module = inspect.getmodule(c)
@@ -720,6 +743,7 @@ def main(global_config, **settings):
package=package_of(module),
autocommit=self.autocommit,
route_prefix=route_prefix,
+ route_suffix=route_suffix,
)
configurator.basepath = os.path.dirname(sourcefile)
configurator.includepath = self.includepath + (spec,)
@@ -780,7 +804,8 @@ def with_context(cls, context):
registry=context.registry,
package=context.package,
autocommit=context.autocommit,
- route_prefix=context.route_prefix
+ route_prefix=context.route_prefix,
+ route_suffix=context.route_suffix,
)
configurator.basepath = context.basepath
configurator.includepath = context.includepath
@@ -798,6 +823,7 @@ def with_package(self, package):
package=package,
autocommit=self.autocommit,
route_prefix=self.route_prefix,
+ route_suffix=self.route_suffix,
)
configurator.basepath = self.basepath
configurator.includepath = self.includepath
View
8 pyramid/config/routes.py
@@ -15,6 +15,7 @@
action_method,
make_predicates,
as_sorted_tuple,
+ route_pattern,
)
class RoutesConfiguratorMixin(object):
@@ -368,8 +369,13 @@ def add_route(self,
if pattern is None:
raise ConfigurationError('"pattern" argument may not be None')
+ pattern = route_pattern(
+ (self.route_prefix or []) + [pattern] + (self.route_suffix or [])
+ )
if self.route_prefix:
- pattern = self.route_prefix.rstrip('/') + '/' + pattern.lstrip('/')
+ pattern.match_slash_style = True
+
+ pattern = str(pattern)
mapper = self.get_routes_mapper()
View
26 pyramid/config/util.py
@@ -291,3 +291,29 @@ def as_sorted_tuple(val):
val = tuple(sorted(val))
return val
+class route_pattern(list):
+ """ Utility: centralise route-pattern operations.
+
+ If ``match_slash_style`` is ``True`` then the slash-style of the first-item
+ determines the slash-style of the route-pattern; if the first-item is
+ slash-appended then the route-pattern will be slash-appended, otherwise the
+ route-pattern will be non-slash-appended. """
+
+ def __init__(self, *args):
+ super(route_pattern, self).__init__(*args)
+ self.match_slash_style = False
+
+ def __str__(self):
+ l = None
+ for r in self:
+ if l is not None and self.match_slash_style:
+ r = r.rstrip('/')
+ if l.endswith('/'):
+ r = '%s/' % r
+ if l is None:
+ l = ''
+ if l and r:
+ l = '%s/%s' % (l.rstrip('/'), r.lstrip('/'))
+ else:
+ l = l + r
+ return l
Something went wrong with that request. Please try again.