Commit 106a8dca authored by Tres Seaver's avatar Tres Seaver

Merge pull request #8 from NextThought/jython

In WeakSet, use the `valuerefs` method from Python 2.5 instead of accessing the internal `data` implementation detail.
parents bf6e186c b42a65c5
...@@ -4,6 +4,9 @@ Changes ...@@ -4,6 +4,9 @@ Changes
1.4.4 (unreleased) 1.4.4 (unreleased)
------------------ ------------------
- Use the standard ``valuerefs()`` method rather than relying on
implementation details of ``WeakValueDictionary`` in ``WeakSet``.
- Add support for PyPy3. - Add support for PyPy3.
- Require 100% branch coverage (in addition to 100% statement coverage). - Require 100% branch coverage (in addition to 100% statement coverage).
......
[tox] [tox]
envlist = # Jython 2.7rc2+ does work, but unfortunately has an issue running
# Jython support pending 2.7 support, due 2012-07-15 or so. See: # with Tox 1.9.2 (see https://github.com/pypa/virtualenv/pull/746)
# http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html envlist =
# py26,py27,py32,pypy,jython,coverage
py26,py27,pypy,py32,py33,py34,pypy3,coverage,docs py26,py27,pypy,py32,py33,py34,pypy3,coverage,docs
[testenv] [testenv]
commands = commands =
python setup.py test -q python setup.py test -q
deps = transaction deps = transaction
[testenv:jython]
commands =
jython setup.py test -q
[testenv:coverage] [testenv:coverage]
basepython = basepython =
python2.6 python2.6
commands = commands =
nosetests --with-xunit --with-xcoverage nosetests --with-xunit --with-xcoverage
deps = deps =
nose nose
...@@ -27,7 +22,7 @@ deps = ...@@ -27,7 +22,7 @@ deps =
[testenv:docs] [testenv:docs]
basepython = basepython =
python2.6 python2.6
commands = commands =
sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
deps = deps =
......
...@@ -2,6 +2,7 @@ import sys ...@@ -2,6 +2,7 @@ import sys
import types import types
PY3 = sys.version_info[0] == 3 PY3 = sys.version_info[0] == 3
JYTHON = sys.platform.startswith('java')
if PY3: # pragma: no cover if PY3: # pragma: no cover
string_types = str, string_types = str,
...@@ -79,12 +80,11 @@ if PY3: #pragma NO COVER ...@@ -79,12 +80,11 @@ if PY3: #pragma NO COVER
from threading import _get_ident as get_thread_ident from threading import _get_ident as get_thread_ident
else: else:
from thread import get_ident as get_thread_ident from thread import get_ident as get_thread_ident
if PY3: if PY3:
def func_name(func): #pragma NO COVER def func_name(func): #pragma NO COVER
return func.__name__ return func.__name__
else: else:
def func_name(func): #pragma NO COVER def func_name(func): #pragma NO COVER
return func.func_name return func.func_name
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
# #
############################################################################## ##############################################################################
import unittest import unittest
from transaction._compat import JYTHON
class WeakSetTests(unittest.TestCase): class WeakSetTests(unittest.TestCase):
def test_contains(self): def test_contains(self):
...@@ -35,7 +35,9 @@ class WeakSetTests(unittest.TestCase): ...@@ -35,7 +35,9 @@ class WeakSetTests(unittest.TestCase):
self.assertEqual(len(w), 2) self.assertEqual(len(w), 2)
del d1 del d1
gc.collect() gc.collect()
self.assertEqual(len(w), 1) if not JYTHON:
# The Jython GC is non deterministic
self.assertEqual(len(w), 1)
def test_remove(self): def test_remove(self):
from transaction.weakset import WeakSet from transaction.weakset import WeakSet
...@@ -100,17 +102,17 @@ class WeakSetTests(unittest.TestCase): ...@@ -100,17 +102,17 @@ class WeakSetTests(unittest.TestCase):
gc.collect() gc.collect()
return result return result
w.as_weakref_list = _as_weakref_list w.as_weakref_list = _as_weakref_list
def poker(x): def poker(x):
x.poked = 1 x.poked = 1
w.map(poker) w.map(poker)
for thing in dummy, dummy2: for thing in dummy, dummy2:
self.assertEqual(thing.poked, 1) self.assertEqual(thing.poked, 1)
class Dummy: class Dummy:
pass pass
def test_suite(): def test_suite():
return unittest.makeSuite(WeakSetTests) return unittest.makeSuite(WeakSetTests)
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
############################################################################ ############################################################################
import weakref import weakref
from ._compat import PY3
# A simple implementation of weak sets, supplying just enough of Python's # A simple implementation of weak sets, supplying just enough of Python's
# sets.Set interface for our needs. # sets.Set interface for our needs.
...@@ -62,7 +63,6 @@ class WeakSet(object): ...@@ -62,7 +63,6 @@ class WeakSet(object):
# underlying dict may change size during iteration, due to gc or # underlying dict may change size during iteration, due to gc or
# activity from other threads). as_weakef_list() is safe. # activity from other threads). as_weakef_list() is safe.
# #
# Something like this should really be a method of Python's weak dicts.
# If we invoke self.data.values() instead, we get back a list of live # If we invoke self.data.values() instead, we get back a list of live
# objects instead of weakrefs. If gc occurs while this list is alive, # objects instead of weakrefs. If gc occurs while this list is alive,
# all the objects move to an older generation (because they're strongly # all the objects move to an older generation (because they're strongly
...@@ -75,9 +75,12 @@ class WeakSet(object): ...@@ -75,9 +75,12 @@ class WeakSet(object):
# elements are actually trash. By returning a list of weakrefs instead, # elements are actually trash. By returning a list of weakrefs instead,
# we avoid that, although the decision to use weakrefs is now very # we avoid that, although the decision to use weakrefs is now very
# visible to our clients. # visible to our clients.
def as_weakref_list(self): if PY3: #pragma: no cover (coverage tests run under 2.7)
# We're cheating by breaking into the internals of Python's # Python 3: be sure to freeze the iterator, to avoid RuntimeError:
# WeakValueDictionary here (accessing its .data attribute).
# Python 3: be sure to freeze the list, to avoid RuntimeError:
# dictionary changed size during iteration. # dictionary changed size during iteration.
return list(self.data.data.values()) def as_weakref_list(self):
return list(self.data.valuerefs())
else:
# On Python2 we already get a list, no need to copy
def as_weakref_list(self):
return self.data.valuerefs()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment