From f58977a38ac65dce742dac38fe1179f61bfc3efc Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 22 Jan 2014 03:09:29 -0500 Subject: - Fix a memory leak when the configurator's ``set_request_property`` method was used or when the configurator's ``add_request_method`` method was used with the ``property=True`` attribute. See https://github.com/Pylons/pyramid/issues/1212 . Closes #1212 --- CHANGES.txt | 5 +++++ pyramid/util.py | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 9c38bf814..8a340f320 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -15,6 +15,11 @@ Bug Fixes - Add a trailing semicolon to the JSONP response. This fixes JavaScript syntax errors for old IE versions. See https://github.com/Pylons/pyramid/pull/1205 +- Fix a memory leak when the configurator's ``set_request_property`` method was + used or when the configurator's ``add_request_method`` method was used with + the ``property=True`` attribute. See + https://github.com/Pylons/pyramid/issues/1212 . + 1.5a3 (2013-12-10) ================== diff --git a/pyramid/util.py b/pyramid/util.py index 73f3ebdb0..6b92f17fc 100644 --- a/pyramid/util.py +++ b/pyramid/util.py @@ -26,6 +26,8 @@ class DottedNameResolver(_DottedNameResolver): def __init__(self, package=None): # default to package = None for bw compat return _DottedNameResolver.__init__(self, package) +_marker = object() + class InstancePropertyMixin(object): """ Mixin that will allow an instance to add properties at run-time as if they had been defined via @property or @reify @@ -80,6 +82,25 @@ class InstancePropertyMixin(object): if attrs: parent = self.__class__ cls = 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 + # 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__'): + # we assign these attributes conditionally to make it possible + # to test this class in isolation without having any interfaces + # attached to it + val = getattr(parent, name, _marker) + if val is not _marker: + setattr(cls, name, val) self.__class__ = cls def _set_extensions(self, extensions): -- cgit v1.2.3