Merge branch 'master' of github.com:Pylons/pyramid
| | |
| | | Features |
| | | -------- |
| | | |
| | | - It is now possible to escape double braces in Pyramid scaffolds (unescaped, |
| | | these represent replacement values). You can use ``\{\{a\}\}`` to |
| | | represent a "bare" ``{{a}}``. See |
| | | https://github.com/Pylons/pyramid/pull/862 |
| | | |
| | | - Add ``localizer`` property (reified) to the request. |
| | | See https://github.com/Pylons/pyramid/issues/508. |
| | | |
| | |
| | | Bug Fixes |
| | | --------- |
| | | |
| | | - Fix an obscure problem when combining a virtual root with a route with a |
| | | ``*traverse`` in its pattern. Now the traversal path generated in |
| | | such a configuration will be correct, instead of an element missing |
| | | a leading slash. |
| | | |
| | | - Fixed a Mako renderer bug returning a tuple with a previous defname value |
| | | in some circumstances. See https://github.com/Pylons/pyramid/issues/1037 |
| | | for more information. |
| | |
| | | previously returned the URL without the query string by default, it now does |
| | | attach the query string unless it is overriden. |
| | | |
| | | - The ``route_url`` and ``route_path`` APIs no longer quote ``/`` |
| | | to ``%2F`` when a replacement value contains a ``/``. This was pointless, |
| | | as WSGI servers always unquote the slash anyway, and Pyramid never sees the |
| | | quoted value. |
| | | |
| | | 1.4 (2012-12-18) |
| | | ================ |
| | | |
| | |
| | | - Andreas Zeidler, 2013/08/15 |
| | | |
| | | - Matthew Wilkes, 2013/08/23 |
| | | |
| | | - Takahiro Fujiwara, 2013/08/28 |
| | |
| | | |
| | | def _pkg_resources_style(self, value, package): |
| | | """ package.module:attr style """ |
| | | if value.startswith('.') or value.startswith(':'): |
| | | if value.startswith(('.', ':')): |
| | | if not package: |
| | | raise ValueError( |
| | | 'relative name %r irresolveable without package' % (value,) |
| | |
| | | """ |
| | | if name.startswith('.'): |
| | | return 'Skipping hidden file %(filename)s' |
| | | if name.endswith('~') or name.endswith('.bak'): |
| | | if name.endswith(('~', '.bak')): |
| | | return 'Skipping backup file %(filename)s' |
| | | if name.endswith('.pyc') or name.endswith('.pyo'): |
| | | if name.endswith(('.pyc', '.pyo')): |
| | | return 'Skipping %s file ' % os.path.splitext(name)[1] + '%(filename)s' |
| | | if name.endswith('$py.class'): |
| | | return 'Skipping $py.class file %(filename)s' |
| | |
| | | content = native_(content, fsenc) |
| | | try: |
| | | return bytes_( |
| | | substitute_double_braces(content, TypeMapper(vars)), fsenc) |
| | | substitute_escaped_double_braces( |
| | | substitute_double_braces(content, TypeMapper(vars))), fsenc) |
| | | except Exception as e: |
| | | _add_except(e, ' in file %s' % filename) |
| | | raise |
| | |
| | | value = match.group('braced').strip() |
| | | return values[value] |
| | | return double_brace_pattern.sub(double_bracerepl, content) |
| | | |
| | | |
| | | escaped_double_brace_pattern = re.compile(r'\\{\\{(?P<escape_braced>[^\\]*?)\\}\\}') |
| | | |
| | | def substitute_escaped_double_braces(content): |
| | | def escaped_double_bracerepl(match): |
| | | value = match.group('escape_braced').strip() |
| | | return "{{%(value)s}}" % locals() |
| | | return escaped_double_brace_pattern.sub(escaped_double_bracerepl, content) |
| | | |
| | | def _add_except(exc, info): # pragma: no cover |
| | | if not hasattr(exc, 'args') or exc.args is None: |
| | | return |
| | |
| | | inst = self._makeOne() |
| | | result = inst.render_template('{{a}} {{b}}', {'a':'1', 'b':'2'}) |
| | | self.assertEqual(result, bytes_('1 2')) |
| | | |
| | | |
| | | def test_render_template_expr_failure(self): |
| | | inst = self._makeOne() |
| | | self.assertRaises(AttributeError, inst.render_template, |
| | |
| | | inst = self._makeOne() |
| | | result = inst.render_template('{{a}}', {'a':None}) |
| | | self.assertEqual(result, b'') |
| | | |
| | | def test_render_template_with_escaped_double_braces(self): |
| | | inst = self._makeOne() |
| | | result = inst.render_template('{{a}} {{b}} \{\{a\}\} \{\{c\}\}', {'a':'1', 'b':'2'}) |
| | | self.assertEqual(result, bytes_('1 2 {{a}} {{c}}')) |
| | | |
| | | def test_render_template_with_breaking_escaped_braces(self): |
| | | inst = self._makeOne() |
| | | result = inst.render_template('{{a}} {{b}} \{\{a\} \{b\}\}', {'a':'1', 'b':'2'}) |
| | | self.assertEqual(result, bytes_('1 2 \{\{a\} \{b\}\}')) |
| | | |
| | | def test_render_template_with_escaped_single_braces(self): |
| | | inst = self._makeOne() |
| | | result = inst.render_template('{{a}} {{b}} \{a\} \{b', {'a':'1', 'b':'2'}) |
| | | self.assertEqual(result, bytes_('1 2 \{a\} \{b')) |
| | | |
| | | def test_module_dir(self): |
| | | import sys |
| | |
| | | 'overwrite':False, |
| | | 'interactive':False, |
| | | }) |
| | | |
| | | |
| | | def test_write_files_path_missing(self): |
| | | L = [] |
| | | inst = self._makeOne() |
| | |
| | | simulate = False |
| | | overwrite = False |
| | | interactive = False |
| | | |
| | | |
| | | class DummyCommand(object): |
| | | options = DummyOptions() |
| | | verbosity = 1 |
| | | |
| | | |
| | | |
| | | |
| | |
| | | self.assertEqual(result['virtual_root'], resource) |
| | | self.assertEqual(result['virtual_root_path'], ()) |
| | | |
| | | def test_withroute_and_traverse_and_vroot(self): |
| | | abc = DummyContext() |
| | | resource = DummyContext(next=abc) |
| | | environ = self._getEnviron(HTTP_X_VHM_ROOT='/abc') |
| | | request = DummyRequest(environ) |
| | | traverser = self._makeOne(resource) |
| | | matchdict = {'traverse':text_('/foo/bar')} |
| | | request.matchdict = matchdict |
| | | result = traverser(request) |
| | | self.assertEqual(result['context'], abc) |
| | | self.assertEqual(result['view_name'], 'foo') |
| | | self.assertEqual(result['subpath'], ('bar',)) |
| | | self.assertEqual(result['traversed'], ('abc', 'foo')) |
| | | self.assertEqual(result['root'], resource) |
| | | self.assertEqual(result['virtual_root'], abc) |
| | | self.assertEqual(result['virtual_root_path'], ('abc',)) |
| | | |
| | | class FindInterfaceTests(unittest.TestCase): |
| | | def _callFUT(self, context, iface): |
| | | from pyramid.traversal import find_interface |
| | |
| | | 'remainder':'/everything/else/here'}) |
| | | self.assertEqual(matcher('foo/baz/biz/buz/bar'), None) |
| | | self.assertEqual(generator( |
| | | {'baz':1, 'buz':2, 'remainder':'/a/b'}), '/foo/1/biz/2/bar%2Fa%2Fb') |
| | | {'baz':1, 'buz':2, 'remainder':'/a/b'}), '/foo/1/biz/2/bar/a/b') |
| | | |
| | | def test_no_beginning_slash(self): |
| | | matcher, generator = self._callFUT('foo/:baz/biz/:buz/bar') |
| | |
| | | self.generates('zzz/{x}*traverse', {'x':'abc', 'traverse':'/def/g'}, |
| | | '/zzz/abc/def/g') |
| | | self.generates('/{x}', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8')}, |
| | | '/%2FLa%20Pe%C3%B1a') |
| | | '//La%20Pe%C3%B1a') |
| | | self.generates('/{x}*y', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8'), |
| | | 'y':'/rest/of/path'}, |
| | | '/%2FLa%20Pe%C3%B1a/rest/of/path') |
| | | '//La%20Pe%C3%B1a/rest/of/path') |
| | | self.generates('*traverse', {'traverse':('a', text_(b'La Pe\xf1a'))}, |
| | | '/a/La%20Pe%C3%B1a') |
| | | self.generates('/foo/{id}.html', {'id':'bar'}, '/foo/bar.html') |
| | |
| | | self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':'/def/g'}, |
| | | '/zzz/abc/def/g') |
| | | self.generates('/:x', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8')}, |
| | | '/%2FLa%20Pe%C3%B1a') |
| | | '//La%20Pe%C3%B1a') |
| | | self.generates('/:x*y', {'x':text_(b'/La Pe\xc3\xb1a', 'utf-8'), |
| | | 'y':'/rest/of/path'}, |
| | | '/%2FLa%20Pe%C3%B1a/rest/of/path') |
| | | '//La%20Pe%C3%B1a/rest/of/path') |
| | | self.generates('*traverse', {'traverse':('a', text_(b'La Pe\xf1a'))}, |
| | | '/a/La%20Pe%C3%B1a') |
| | | self.generates('/foo/:id.html', {'id':'bar'}, '/foo/bar.html') |
| | |
| | | # this is a *traverse stararg (not a {traverse}) |
| | | # routing has already decoded these elements, so we just |
| | | # need to join them |
| | | path = slash.join(path) or slash |
| | | path = '/' + slash.join(path) or slash |
| | | |
| | | subpath = matchdict.get('subpath', ()) |
| | | if not is_nonstr_iter(subpath): |
| | |
| | | if k == remainder: |
| | | # a stararg argument |
| | | if is_nonstr_iter(v): |
| | | v = '/'.join([quote_path_segment(x) for x in v]) # native |
| | | v = '/'.join( |
| | | [quote_path_segment(x, safe='/') for x in v] |
| | | ) # native |
| | | else: |
| | | if v.__class__ not in string_types: |
| | | v = str(v) |
| | |
| | | if v.__class__ not in string_types: |
| | | v = str(v) |
| | | # v may be bytes (py2) or native string (py3) |
| | | v = quote_path_segment(v) |
| | | v = quote_path_segment(v, safe='/') |
| | | |
| | | # at this point, the value will be a native string |
| | | newdict[k] = v |