From a1e9ca7097f80b546ccf2e788841fcd33794605d Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 23 Feb 2016 01:17:31 +0200 Subject: Add tests for protocol-relative URLs generation. Close #29 --- tests/test_functional/test_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_functional/test_utils.py b/tests/test_functional/test_utils.py index 3f4dd47..e2a6a04 100644 --- a/tests/test_functional/test_utils.py +++ b/tests/test_functional/test_utils.py @@ -62,6 +62,8 @@ class TestUtils(unittest.TestCase): eq_('/content', urlobj()) eq_('https://www.test.com/viewpost', urlobj(controller='post', action='view', protocol='https')) eq_('http://www.test.org/content', urlobj(host='www.test.org')) + eq_('//www.test.com/viewpost', urlobj(controller='post', action='view', protocol='')) + eq_('//www.test.org/content', urlobj(host='www.test.org', protocol='')) def test_url_raises(self): con = self.con -- cgit v1.2.1 From d3021164cdbf996267dd049c25b2144cedb60d7a Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 23 Feb 2016 01:18:03 +0200 Subject: Add support for protocol-relative URLs generation. Close #29 --- routes/util.py | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/routes/util.py b/routes/util.py index baeeac7..24eb3e1 100644 --- a/routes/util.py +++ b/routes/util.py @@ -180,15 +180,19 @@ def url_for(*args, **kargs): """ anchor = kargs.get('anchor') host = kargs.get('host') - protocol = kargs.get('protocol') + protocol = kargs.pop('protocol', None) qualified = kargs.pop('qualified', None) # Remove special words from kargs, convert placeholders - for key in ['anchor', 'host', 'protocol']: + for key in ['anchor', 'host']: if kargs.get(key): del kargs[key] if key+'_' in kargs: kargs[key] = kargs.pop(key+'_') + + if 'protocol_' in kargs: + kargs['protocol_'] = protocol + config = request_config() route = None static = False @@ -250,21 +254,23 @@ def url_for(*args, **kargs): newargs = _screenargs(kargs, config.mapper, environ) anchor = newargs.pop('_anchor', None) or anchor host = newargs.pop('_host', None) or host - protocol = newargs.pop('_protocol', None) or protocol + protocol = newargs.pop('_protocol', protocol) url = config.mapper.generate(*route_args, **newargs) if anchor is not None: url += '#' + _url_quote(anchor, encoding) - if host or protocol or qualified: + if host or protocol is not None or qualified: if not host and not qualified: # Ensure we don't use a specific port, as changing the protocol # means that we most likely need a new port host = config.host.split(':')[0] elif not host: host = config.host - if not protocol: + if protocol is None: protocol = config.protocol + if protocol != '': + protocol += ':' if url is not None: - url = protocol + '://' + host + url + url = protocol + '//' + host + url if not ascii_characters(url) and url is not None: raise GenerationException("url_for can only return a string, got " @@ -324,16 +330,19 @@ class URLGenerator(object): """ anchor = kargs.get('anchor') host = kargs.get('host') - protocol = kargs.get('protocol') + protocol = kargs.pop('protocol', None) qualified = kargs.pop('qualified', None) # Remove special words from kargs, convert placeholders - for key in ['anchor', 'host', 'protocol']: + for key in ['anchor', 'host']: if kargs.get(key): del kargs[key] if key+'_' in kargs: kargs[key] = kargs.pop(key+'_') + if 'protocol_' in kargs: + kargs['protocol_'] = protocol + route = None use_current = '_use_current' in kargs and kargs.pop('_use_current') @@ -396,12 +405,13 @@ class URLGenerator(object): anchor = anchor or newargs.pop('_anchor', None) host = host or newargs.pop('_host', None) - protocol = protocol or newargs.pop('_protocol', None) + if protocol is None: + protocol = newargs.pop('_protocol', None) newargs['_environ'] = self.environ url = self.mapper.generate(*route_args, **newargs) if anchor is not None: url += '#' + _url_quote(anchor, encoding) - if host or protocol or qualified: + if host or protocol is not None or qualified: if 'routes.cached_hostinfo' not in self.environ: cache_hostinfo(self.environ) hostinfo = self.environ['routes.cached_hostinfo'] @@ -412,12 +422,14 @@ class URLGenerator(object): host = hostinfo['host'].split(':')[0] elif not host: host = hostinfo['host'] - if not protocol: + if protocol is None: protocol = hostinfo['protocol'] + if protocol != '': + protocol += ':' if url is not None: if host[-1] != '/': host += '/' - url = protocol + '://' + host + url.lstrip('/') + url = protocol + '//' + host + url.lstrip('/') if not ascii_characters(url) and url is not None: raise GenerationException("Can only return a string, got " -- cgit v1.2.1 From 4557f52729e4e7f5b03c876bcb476de3b8cdc706 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 23 Feb 2016 01:21:20 +0200 Subject: Document support for protocol-relative URLs generation. Close #29 --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2a8a322..3b08d25 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,8 @@ Routes Changelog Release 2.3 (**dev**) ===================== +* Add support for protocol-relative URLs generation (i.e. starting with double + slash ``//``). PR #60. Patch by Sviatoslav Sydorenko. * Add support for the ``middleware`` extra requirement, making possible to depend on ``webob`` optionally. PR #59. Patch by Sviatoslav Sydorenko. * Fix matching of an empty string route, which led to exception in earlier -- cgit v1.2.1 From f4b2cb0297f4f07d27f142e9112bd5fbf6a0a2c6 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sun, 28 Feb 2016 10:56:30 +0200 Subject: Wrap conditions with parentheses --- routes/util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/routes/util.py b/routes/util.py index 24eb3e1..f3d2dc4 100644 --- a/routes/util.py +++ b/routes/util.py @@ -258,7 +258,7 @@ def url_for(*args, **kargs): url = config.mapper.generate(*route_args, **newargs) if anchor is not None: url += '#' + _url_quote(anchor, encoding) - if host or protocol is not None or qualified: + if host or (protocol is not None) or qualified: if not host and not qualified: # Ensure we don't use a specific port, as changing the protocol # means that we most likely need a new port @@ -411,7 +411,7 @@ class URLGenerator(object): url = self.mapper.generate(*route_args, **newargs) if anchor is not None: url += '#' + _url_quote(anchor, encoding) - if host or protocol is not None or qualified: + if host or (protocol is not None) or qualified: if 'routes.cached_hostinfo' not in self.environ: cache_hostinfo(self.environ) hostinfo = self.environ['routes.cached_hostinfo'] -- cgit v1.2.1 From 1dd523357a100d97bbe4abc8f0e0316150895adb Mon Sep 17 00:00:00 2001 From: Nikita Uvarov Date: Thu, 24 Mar 2016 16:44:56 +0200 Subject: Fix subdomain equivalence check. Use regex instead of startswith Problem occurred when new subdomain was left substring of current one. In this case subdomain was not replaced. --- routes/util.py | 8 +++++--- tests/test_functional/test_explicit_use.py | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/routes/util.py b/routes/util.py index f3d2dc4..c48445f 100644 --- a/routes/util.py +++ b/routes/util.py @@ -93,10 +93,12 @@ def _subdomain_check(kargs, mapper, environ): port = '' if len(hostmatch) > 1: port += ':' + hostmatch[1] - sub_match = re.compile('^.+?\.(%s)$' % mapper.domain_match) - domain = re.sub(sub_match, r'\1', host) + + match = re.match('^(.+?)\.(%s)$' % mapper.domain_match, host) + host_subdomain, domain = match.groups() if match else (None, host) + subdomain = as_unicode(subdomain, mapper.encoding) - if subdomain and not host.startswith(subdomain) and \ + if subdomain and host_subdomain != subdomain and \ subdomain not in mapper.sub_domains_ignore: kargs['_host'] = subdomain + '.' + domain + port elif (subdomain in mapper.sub_domains_ignore or \ diff --git a/tests/test_functional/test_explicit_use.py b/tests/test_functional/test_explicit_use.py index 32579d8..ccd3b7a 100644 --- a/tests/test_functional/test_explicit_use.py +++ b/tests/test_functional/test_explicit_use.py @@ -52,6 +52,14 @@ class TestUtils(unittest.TestCase): url = URLGenerator(m, environ.copy()) assert_raises(GenerationException, lambda: url.current(qualified=True)) + environ = {'HTTP_HOST': 'subdomain.localhost.com'} + url = URLGenerator(m, environ.copy()) + eq_('http://sub.localhost.com/hi/smith', url(fred='smith', sub_domain='sub', qualified=True)) + + environ = {'HTTP_HOST': 'sub.sub.localhost.com'} + url = URLGenerator(m, environ.copy()) + eq_('http://new.localhost.com/hi/smith', url(fred='smith', sub_domain='new', qualified=True)) + url = URLGenerator(m, {}) eq_('/hi/smith', url(fred='smith', sub_domain=u'home')) -- cgit v1.2.1 From 81705e48824582f0b58a14477bd0732f9e364e73 Mon Sep 17 00:00:00 2001 From: Nikita Uvarov Date: Thu, 24 Mar 2016 16:53:18 +0200 Subject: Add changelog entry for sub_domain fix --- CHANGELOG.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3b08d25..556ec8a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,6 +3,7 @@ Routes Changelog Release 2.3 (**dev**) ===================== +* Fix sub_domain equivalence check. Patch by Nikita Uvarov * Add support for protocol-relative URLs generation (i.e. starting with double slash ``//``). PR #60. Patch by Sviatoslav Sydorenko. * Add support for the ``middleware`` extra requirement, making possible to -- cgit v1.2.1 From 28e061821b556d7df8e89e941638257703a83818 Mon Sep 17 00:00:00 2001 From: Pavlo Kapyshin Date: Sat, 26 Mar 2016 18:38:22 +0200 Subject: Fix typo --- CHANGELOG.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 556ec8a..d5734d8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -434,7 +434,7 @@ Release 1.0 (Nov. 21st, 2005) Or:: - from routes import request_confg, Mapper + from routes import request_config, Mapper The following names are available for importing from routes:: -- cgit v1.2.1 From 3d87edf1744d0ce6da1feba3a7eddcb31a9b4de4 Mon Sep 17 00:00:00 2001 From: Ben Bangert Date: Mon, 28 Mar 2016 08:46:03 -0700 Subject: chore: tag 2.3 release --- CHANGELOG.rst | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d5734d8..4a21f57 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,8 @@ Routes Changelog %%%%%%%%%%%%%%%% -Release 2.3 (**dev**) -===================== +Release 2.3 (March 28, 2016) +============================ * Fix sub_domain equivalence check. Patch by Nikita Uvarov * Add support for protocol-relative URLs generation (i.e. starting with double slash ``//``). PR #60. Patch by Sviatoslav Sydorenko. diff --git a/setup.py b/setup.py index c3be076..f330a60 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -__version__ = '2.2' +__version__ = '2.3' import io import os -- cgit v1.2.1 From 21bc2ea57c5d418f37c528258ebbcf2335e009b6 Mon Sep 17 00:00:00 2001 From: Davanum Srinivas Date: Tue, 29 Mar 2016 11:36:00 -0400 Subject: Tolerate older usage with mandatory routename and optional path With the following review: https://github.com/bbangert/routes/commit/0a417004be7e2d950bdcd629ccf24cf9f56ef817 Routes 2.3 has changed the function signature to mandate path in addition to routename for the connect method. In this patch, we try to get back to path being optional by checking the length of the args list. No other change in logic. This hopefully fixes the problem reported here: https://github.com/bbangert/routes/issues/64 Add an entry in Changelog as well. --- CHANGELOG.rst | 5 +++++ routes/mapper.py | 20 ++++++++++---------- tests/test_functional/test_submapper.py | 6 ++++++ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 4a21f57..9fe0abc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,11 @@ Routes Changelog %%%%%%%%%%%%%%%% +Release 2.3.1 (**dev**) +======================= +* Backwards compatability fix - connect should work with mandatory + routename and optional path. Patch by Davanum Srinivas (PR #65). + Release 2.3 (March 28, 2016) ============================ * Fix sub_domain equivalence check. Patch by Nikita Uvarov diff --git a/routes/mapper.py b/routes/mapper.py index 06f09f2..48bba45 100644 --- a/routes/mapper.py +++ b/routes/mapper.py @@ -162,25 +162,25 @@ class SubMapper(SubMapperParent): self.formatted = True self.add_actions(actions or [], **kwargs) - def connect(self, *args, **kwargs): + def connect(self, routename, path=None, **kwargs): newkargs = {} - # newargs = args - routename, path = args + _routename = routename + _path = path for key, value in six.iteritems(self.kwargs): if key == 'path_prefix': - if len(args) > 1: + if path is not None: # if there's a name_prefix, add it to the route name # and if there's a path_prefix - path = ''.join((self.kwargs[key], args[1])) + _path = ''.join((self.kwargs[key], path)) else: - path = ''.join((self.kwargs[key], args[0])) + _path = ''.join((self.kwargs[key], routename)) elif key == 'name_prefix': - if len(args) > 1: + if path is not None: # if there's a name_prefix, add it to the route name # and if there's a path_prefix - routename = ''.join((self.kwargs[key], args[0])) + _routename = ''.join((self.kwargs[key], routename)) else: - routename = None + _routename = None elif key in kwargs: if isinstance(value, dict): newkargs[key] = dict(value, **kwargs[key]) # merge dicts @@ -197,7 +197,7 @@ class SubMapper(SubMapperParent): if key not in self.kwargs: newkargs[key] = kwargs[key] - newargs = (routename, path) + newargs = (_routename, _path) return self.obj.connect(*newargs, **newkargs) def link(self, rel=None, name=None, action=None, method='GET', diff --git a/tests/test_functional/test_submapper.py b/tests/test_functional/test_submapper.py index 1516a58..8821de9 100644 --- a/tests/test_functional/test_submapper.py +++ b/tests/test_functional/test_submapper.py @@ -13,6 +13,12 @@ class TestSubmapper(unittest.TestCase): eq_('/entries/1', url_for('entry', id=1)) assert_raises(Exception, url_for, 'entry', id='foo') + def test_submapper_with_no_path(self): + m = Mapper() + c = m.submapper(path_prefix='/') + c.connect('entry') + eq_('/entry?id=1', url_for('entry', id=1)) + def test_submapper_nesting(self): m = Mapper() c = m.submapper(path_prefix='/entries', controller='entry', -- cgit v1.2.1 From 16d1688075fb74d494b2febe56431e7a6194d720 Mon Sep 17 00:00:00 2001 From: Ben Bangert Date: Wed, 30 Mar 2016 07:59:09 -0700 Subject: chore: update version to 2.3.1 and year refs to 2016 --- CHANGELOG.rst | 4 ++-- LICENSE.txt | 2 +- docs/conf.py | 6 +++--- setup.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9fe0abc..bde71f9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,8 @@ Routes Changelog %%%%%%%%%%%%%%%% -Release 2.3.1 (**dev**) -======================= +Release 2.3.1 (March 30, 2016) +============================== * Backwards compatability fix - connect should work with mandatory routename and optional path. Patch by Davanum Srinivas (PR #65). diff --git a/LICENSE.txt b/LICENSE.txt index 493ea52..5a11de7 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2005-2015 Ben Bangert +Copyright (c) 2005-2016 Ben Bangert Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/docs/conf.py b/docs/conf.py index 6673a37..467a6be 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,15 +36,15 @@ master_doc = 'index' # General substitutions. project = 'Routes' -copyright = '2005-2015, Ben Bangert, Mike Orr' +copyright = '2005-2016, Ben Bangert, Mike Orr, and numerous contributers' # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. # # The short X.Y version. -version = '1.13' +version = '2.3' # The full version, including alpha/beta/rc tags. -release = '1.13' +release = '2.3.1' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff --git a/setup.py b/setup.py index f330a60..c20dd4d 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -__version__ = '2.3' +__version__ = '2.3.1' import io import os -- cgit v1.2.1 From 3ca54e83c109f95d8cac3eaf02e8d795ee7a5275 Mon Sep 17 00:00:00 2001 From: Ben Bangert Date: Wed, 30 Mar 2016 08:00:49 -0700 Subject: chore: add codecov --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 65a02f6..484b853 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,3 +13,5 @@ matrix: - python: "nightly" install: pip install tox-travis script: tox +after_success: + - codecov -- cgit v1.2.1 From cefc10b1562ddb4cba7e1670803fd1bcb19835a4 Mon Sep 17 00:00:00 2001 From: Adam Chainz Date: Sun, 5 Jun 2016 20:29:27 +0100 Subject: Convert readthedocs links for their .org -> .io migration for hosted projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per [their blog post of the 27th April](https://blog.readthedocs.com/securing-subdomains/) ‘Securing subdomains’: > Starting today, Read the Docs will start hosting projects from subdomains on the domain readthedocs.io, instead of on readthedocs.org. This change addresses some security concerns around site cookies while hosting user generated data on the same domain as our dashboard. Test Plan: Manually visited all the links I’ve modified. --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index c20dd4d..989c01d 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ setup(name="Routes", keywords='routes webob dispatch', author="Ben Bangert", author_email="ben@groovie.org", - url='http://routes.readthedocs.org/', + url='https://routes.readthedocs.io/', license="MIT", test_suite="nose.collector", include_package_data=True, -- cgit v1.2.1 From d1030ec7ace3c8f2f8e3d71bcc03eb9fb641a2e0 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Mon, 20 Jun 2016 09:50:12 -0400 Subject: Fix missing quotes in documentation When reading the docs I discovered a missing set of single quotes in this code example which makes the example invalid python code. Fixed. --- routes/mapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/mapper.py b/routes/mapper.py index 48bba45..eb4060a 100644 --- a/routes/mapper.py +++ b/routes/mapper.py @@ -1230,7 +1230,7 @@ class Mapper(SubMapperParent): Example:: map = Mapper() - map.redirect('/legacyapp/archives/{url:.*}, '/archives/{url}) + map.redirect('/legacyapp/archives/{url:.*}', '/archives/{url}') map.redirect('/home/index', '/', _redirect_code='301 Moved Permanently') -- cgit v1.2.1