summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pyramid/tests/test_request.py59
-rw-r--r--pyramid/util.py14
2 files changed, 66 insertions, 7 deletions
diff --git a/pyramid/tests/test_request.py b/pyramid/tests/test_request.py
index 79cf1abb8..257e70435 100644
--- a/pyramid/tests/test_request.py
+++ b/pyramid/tests/test_request.py
@@ -435,6 +435,7 @@ class Test_call_app_with_subpath_as_path_info(unittest.TestCase):
self.assertEqual(request.environ['SCRIPT_NAME'], '/' + encoded)
self.assertEqual(request.environ['PATH_INFO'], '/' + encoded)
+<<<<<<< HEAD
class Test_apply_request_extensions(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()
@@ -478,6 +479,64 @@ class Test_apply_request_extensions(unittest.TestCase):
class Dummy(object):
pass
+class Test_subclassing_Request(unittest.TestCase):
+ def test_subclass(self):
+ from pyramid.interfaces import IRequest
+ from pyramid.request import Request
+ from zope.interface import providedBy, implementedBy
+
+ class RequestSub(Request):
+ pass
+
+ self.assertTrue(hasattr(Request, '__provides__'))
+ self.assertTrue(hasattr(Request, '__implemented__'))
+ self.assertTrue(hasattr(Request, '__providedBy__'))
+ self.assertFalse(hasattr(RequestSub, '__provides__'))
+ self.assertTrue(hasattr(RequestSub, '__providedBy__'))
+ self.assertTrue(hasattr(RequestSub, '__implemented__'))
+
+ self.assertTrue(IRequest.implementedBy(RequestSub))
+ # The call to implementedBy will add __provides__ to the class
+ self.assertTrue(hasattr(RequestSub, '__provides__'))
+
+
+ def test_subclass_with_implementer(self):
+ from pyramid.interfaces import IRequest
+ from pyramid.request import Request
+ from zope.interface import providedBy, implementedBy, implementer
+
+ @implementer(IRequest)
+ class RequestSub(Request):
+ pass
+
+ self.assertTrue(hasattr(Request, '__provides__'))
+ self.assertTrue(hasattr(Request, '__implemented__'))
+ self.assertTrue(hasattr(Request, '__providedBy__'))
+ self.assertTrue(hasattr(RequestSub, '__provides__'))
+ self.assertTrue(hasattr(RequestSub, '__providedBy__'))
+ self.assertTrue(hasattr(RequestSub, '__implemented__'))
+
+ req = RequestSub({})
+ req._set_properties({'b': 'b'})
+
+ self.assertTrue(IRequest.providedBy(req))
+ self.assertTrue(IRequest.implementedBy(RequestSub))
+
+ def test_subclass_mutate_before_providedBy(self):
+ from pyramid.interfaces import IRequest
+ from pyramid.request import Request
+ from zope.interface import providedBy, implementedBy, implementer
+
+ class RequestSub(Request):
+ pass
+
+ req = RequestSub({})
+ req._set_properties({'b': 'b'})
+
+ self.assertTrue(IRequest.providedBy(req))
+ self.assertTrue(IRequest.implementedBy(RequestSub))
+
+
class DummyRequest(object):
def __init__(self, environ=None):
if environ is None:
diff --git a/pyramid/util.py b/pyramid/util.py
index 7a8af4899..4a722b381 100644
--- a/pyramid/util.py
+++ b/pyramid/util.py
@@ -85,19 +85,19 @@ class InstancePropertyHelper(object):
if attrs:
parent = target.__class__
newcls = type(parent.__name__, (parent, object), attrs)
- # We assign __provides__, __implemented__ and __providedBy__ below
- # to prevent a memory leak that results from from the usage of this
- # instance's eventual use in an adapter lookup. Adapter lookup
- # results in ``zope.interface.implementedBy`` being called with the
+ # We assign __provides__ and __implemented__ below to prevent a
+ # memory leak that results from from the usage of this instance's
+ # eventual use in an adapter lookup. Adapter lookup results in
+ # ``zope.interface.implementedBy`` being called with the
# newly-created class as an argument. Because the newly-created
# class has no interface specification data of its own, lookup
# causes new ClassProvides and Implements instances related to our
# just-generated class to be created and set into the newly-created
# class' __dict__. We don't want these instances to be created; we
# want this new class to behave exactly like it is the parent class
- # instead. See https://github.com/Pylons/pyramid/issues/1212 for
- # more information.
- for name in ('__implemented__', '__providedBy__', '__provides__'):
+ # instead. See GitHub issues #1212, #1529 and #1568 for more
+ # information.
+ for name in ('__implemented__', '__provides__'):
# we assign these attributes conditionally to make it possible
# to test this class in isolation without having any interfaces
# attached to it