summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2017-03-03 19:34:05 -0600
committerGitHub <noreply@github.com>2017-03-03 19:34:05 -0600
commit78ac16c1c683b6b4d639e25883fd35f4e9073978 (patch)
tree1baa1d79707ca842f8f150db158f7181201505a1
parent7fb889349d40e361397ed31f3535689182aa5cf0 (diff)
parent870a1d1f957d772cab0eb60bc1d1928da2ebb992 (diff)
downloadpyramid-78ac16c1c683b6b4d639e25883fd35f4e9073978.tar.gz
pyramid-78ac16c1c683b6b4d639e25883fd35f4e9073978.tar.bz2
pyramid-78ac16c1c683b6b4d639e25883fd35f4e9073978.zip
Merge pull request #2967 from Cykooz/fix.memory-leaks
Fixed several reference cycles to prevent memory leaks.
-rw-r--r--CONTRIBUTORS.txt2
-rw-r--r--pyramid/registry.py4
-rw-r--r--pyramid/tests/test_integration.py28
-rw-r--r--pyramid/util.py9
4 files changed, 39 insertions, 4 deletions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index d5c178418..566e91195 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -292,3 +292,5 @@ Contributors
- Mikko Ohtamaa, 2016/12/6
- Martin Frlin, 2016/12/7
+
+- Kirill Kuzminykh, 2017/03/01
diff --git a/pyramid/registry.py b/pyramid/registry.py
index 20b3643e9..7589dfcac 100644
--- a/pyramid/registry.py
+++ b/pyramid/registry.py
@@ -276,7 +276,9 @@ class Deferred(object):
@reify
def value(self):
- return self.func()
+ result = self.func()
+ del self.func
+ return result
def resolve(self):
return self.value
diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py
index 85c4466a4..f23e54609 100644
--- a/pyramid/tests/test_integration.py
+++ b/pyramid/tests/test_integration.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import datetime
+import gc
import locale
import os
import unittest
@@ -8,6 +9,7 @@ import unittest
from pyramid.wsgi import wsgiapp
from pyramid.view import view_config
from pyramid.static import static_view
+from pyramid.testing import skip_on
from pyramid.compat import (
text_,
url_quote,
@@ -741,3 +743,29 @@ def _assertBody(body, filename):
data = data.replace(b'\r', b'')
data = data.replace(b'\n', b'')
assert(body == data)
+
+
+class MemoryLeaksTest(unittest.TestCase):
+
+ def tearDown(self):
+ import pyramid.config
+ pyramid.config.global_registries.empty()
+
+ def get_gc_count(self):
+ last_collected = 0
+ while True:
+ collected = gc.collect()
+ if collected == last_collected:
+ break
+ last_collected = collected
+ return len(gc.get_objects())
+
+ @skip_on('pypy')
+ def test_memory_leaks(self):
+ from pyramid.config import Configurator
+ Configurator().make_wsgi_app() # Initialize all global objects
+
+ initial_count = self.get_gc_count()
+ Configurator().make_wsgi_app()
+ current_count = self.get_gc_count()
+ self.assertEqual(current_count, initial_count)
diff --git a/pyramid/util.py b/pyramid/util.py
index 3337d410d..2827884a3 100644
--- a/pyramid/util.py
+++ b/pyramid/util.py
@@ -231,17 +231,20 @@ class WeakOrderedSet(object):
self._order.remove(oid)
self._order.append(oid)
return
- ref = weakref.ref(item, lambda x: self.remove(item))
+ ref = weakref.ref(item, lambda x: self._remove_by_id(oid))
self._items[oid] = ref
self._order.append(oid)
- def remove(self, item):
+ def _remove_by_id(self, oid):
""" Remove an item from the set."""
- oid = id(item)
if oid in self._items:
del self._items[oid]
self._order.remove(oid)
+ def remove(self, item):
+ """ Remove an item from the set."""
+ self._remove_by_id(id(item))
+
def empty(self):
""" Clear all objects from the set."""
self._items = {}