summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Anderson <sontek@gmail.com>2015-02-07 12:33:03 -0800
committerJohn Anderson <sontek@gmail.com>2015-02-07 12:33:03 -0800
commit1e0d648503fd992323737c7c702be204337e1e36 (patch)
treef5b3b621d948cff88a8ad9c127420538a94d3fb5
parent50921e94c539318cb9e1789a2f9363352a820542 (diff)
downloadpyramid-1e0d648503fd992323737c7c702be204337e1e36.tar.gz
pyramid-1e0d648503fd992323737c7c702be204337e1e36.tar.bz2
pyramid-1e0d648503fd992323737c7c702be204337e1e36.zip
Raise error at configuration time
-rw-r--r--pyramid/config/factories.py15
-rw-r--r--pyramid/tests/test_config/test_factories.py21
-rw-r--r--pyramid/tests/test_util.py38
-rw-r--r--pyramid/util.py27
4 files changed, 77 insertions, 24 deletions
diff --git a/pyramid/config/factories.py b/pyramid/config/factories.py
index 15cfb796f..4b2517ff1 100644
--- a/pyramid/config/factories.py
+++ b/pyramid/config/factories.py
@@ -15,8 +15,12 @@ from pyramid.traversal import DefaultRootFactory
from pyramid.util import (
action_method,
InstancePropertyMixin,
+ get_callable_name,
)
+from pyramid.compat import native_
+
+
class FactoriesConfiguratorMixin(object):
@action_method
def set_root_factory(self, factory):
@@ -33,9 +37,10 @@ class FactoriesConfiguratorMixin(object):
factory = self.maybe_dotted(factory)
if factory is None:
factory = DefaultRootFactory
+
def register():
self.registry.registerUtility(factory, IRootFactory)
- self.registry.registerUtility(factory, IDefaultRootFactory) # b/c
+ self.registry.registerUtility(factory, IDefaultRootFactory) # b/c
intr = self.introspectable('root factories',
None,
@@ -44,7 +49,7 @@ class FactoriesConfiguratorMixin(object):
intr['factory'] = factory
self.action(IRootFactory, register, introspectables=(intr,))
- _set_root_factory = set_root_factory # bw compat
+ _set_root_factory = set_root_factory # bw compat
@action_method
def set_session_factory(self, factory):
@@ -60,6 +65,7 @@ class FactoriesConfiguratorMixin(object):
achieve the same purpose.
"""
factory = self.maybe_dotted(factory)
+
def register():
self.registry.registerUtility(factory, ISessionFactory)
intr = self.introspectable('session factory', None,
@@ -89,6 +95,7 @@ class FactoriesConfiguratorMixin(object):
can be used to achieve the same purpose.
"""
factory = self.maybe_dotted(factory)
+
def register():
self.registry.registerUtility(factory, IRequestFactory)
intr = self.introspectable('request factory', None,
@@ -173,6 +180,8 @@ class FactoriesConfiguratorMixin(object):
callable, name=name, reify=reify)
elif name is None:
name = callable.__name__
+ else:
+ name = get_callable_name(name)
def register():
exts = self.registry.queryUtility(IRequestExtensions)
@@ -224,9 +233,9 @@ class FactoriesConfiguratorMixin(object):
'set_request_propery() is deprecated as of Pyramid 1.5; use '
'add_request_method() with the property=True argument instead')
+
@implementer(IRequestExtensions)
class _RequestExtensions(object):
def __init__(self):
self.descriptors = {}
self.methods = {}
-
diff --git a/pyramid/tests/test_config/test_factories.py b/pyramid/tests/test_config/test_factories.py
index 35677a91b..42bb5accc 100644
--- a/pyramid/tests/test_config/test_factories.py
+++ b/pyramid/tests/test_config/test_factories.py
@@ -128,24 +128,21 @@ class TestFactoriesMixin(unittest.TestCase):
def test_add_request_method_with_text_type_name(self):
from pyramid.interfaces import IRequestExtensions
- from pyramid.compat import text_
- from pyramid.util import InstancePropertyMixin
+ from pyramid.compat import text_, PY3
+ from pyramid.exceptions import ConfigurationError
config = self._makeOne(autocommit=True)
def boomshaka(r): pass
- name = text_(b'La Pe\xc3\xb1a', 'utf-8')
- config.add_request_method(boomshaka, name=name)
- name2 = b'La Pe\xc3\xb1a'
- config.add_request_method(boomshaka, name=name2)
+ def get_bad_name():
+ if PY3: # pragma: nocover
+ name = b'La Pe\xc3\xb1a'
+ else: # pragma: nocover
+ name = text_(b'La Pe\xc3\xb1a', 'utf-8')
- exts = config.registry.getUtility(IRequestExtensions)
- inst = InstancePropertyMixin()
-
- def set_extensions():
- inst._set_extensions(exts)
+ config.add_request_method(boomshaka, name=name)
- self.assertRaises(ValueError, set_extensions)
+ self.assertRaises(ConfigurationError, get_bad_name)
class TestDeprecatedFactoriesMixinMethods(unittest.TestCase):
def setUp(self):
diff --git a/pyramid/tests/test_util.py b/pyramid/tests/test_util.py
index ac5ea0683..405fe927a 100644
--- a/pyramid/tests/test_util.py
+++ b/pyramid/tests/test_util.py
@@ -124,6 +124,21 @@ class Test_InstancePropertyMixin(unittest.TestCase):
self.assertEqual(1, foo.x)
self.assertEqual(2, foo.y)
+ def test__make_property_unicode(self):
+ from pyramid.compat import text_
+ from pyramid.exceptions import ConfigurationError
+
+ cls = self._getTargetClass()
+ if PY3: # pragma: nocover
+ name = b'La Pe\xc3\xb1a'
+ else: # pragma: nocover
+ name = text_(b'La Pe\xc3\xb1a', 'utf-8')
+
+ def make_bad_name():
+ cls._make_property(lambda x: 1, name=name, reify=True)
+
+ self.assertRaises(ConfigurationError, make_bad_name)
+
def test__set_properties_with_dict(self):
foo = self._makeOne()
x_name, x_fn = foo._make_property(lambda _: 1, name='x', reify=True)
@@ -619,7 +634,30 @@ class TestActionInfo(unittest.TestCase):
"Line 0 of file filename:\n linerepr ")
+class TestCallableName(unittest.TestCase):
+ def test_valid_ascii(self):
+ from pyramid.util import get_callable_name
+ name = u'hello world'
+ self.assertEquals(get_callable_name(name), name)
+
+ def test_invalid_ascii(self):
+ from pyramid.util import get_callable_name
+ from pyramid.compat import text_, PY3
+ from pyramid.exceptions import ConfigurationError
+
+ def get_bad_name():
+ if PY3: # pragma: nocover
+ name = b'La Pe\xc3\xb1a'
+ else: # pragma: nocover
+ name = text_(b'La Pe\xc3\xb1a', 'utf-8')
+
+ get_callable_name(name)
+
+ self.assertRaises(ConfigurationError, get_bad_name)
+
+
def dummyfunc(): pass
+
class Dummy(object):
pass
diff --git a/pyramid/util.py b/pyramid/util.py
index c036c1c2e..7e8535aaf 100644
--- a/pyramid/util.py
+++ b/pyramid/util.py
@@ -22,6 +22,7 @@ from pyramid.compat import (
string_types,
text_,
PY3,
+ native_
)
from pyramid.interfaces import IActionInfo
@@ -55,7 +56,7 @@ class InstancePropertyMixin(object):
raise ValueError('cannot reify a property')
elif name is not None:
fn = lambda this: callable(this)
- fn.__name__ = name
+ fn.__name__ = get_callable_name(name)
fn.__doc__ = callable.__doc__
else:
name = callable.__name__
@@ -111,14 +112,7 @@ class InstancePropertyMixin(object):
def _set_extensions(self, extensions):
for name, fn in iteritems_(extensions.methods):
method = fn.__get__(self, self.__class__)
- try:
- setattr(self, name, method)
- except (UnicodeEncodeError, TypeError):
- msg = (
- '`name="%s"` is invalid. `name` must be ascii because it is '
- 'used on __name__ of the method'
- )
- raise ValueError(msg % name)
+ setattr(self, name, method)
self._set_properties(extensions.descriptors)
@@ -558,3 +552,18 @@ def action_method(wrapped):
functools.update_wrapper(wrapper, wrapped)
wrapper.__docobj__ = wrapped
return wrapper
+
+
+def get_callable_name(name):
+ """
+ Verifies that the ``name`` is ascii and will raise a ``ConfigurationError``
+ if it is not.
+ """
+ try:
+ return native_(name, 'ascii')
+ except (UnicodeEncodeError, UnicodeDecodeError):
+ msg = (
+ '`name="%s"` is invalid. `name` must be ascii because it is '
+ 'used on __name__ of the method'
+ )
+ raise ConfigurationError(msg % name)