[pypy-dev] [pypy-commit] pypy default: issue1059 testing

Alex Gaynor alex.gaynor at gmail.com
Mon Feb 20 18:50:00 CET 2012


Unfortunately this commit has some bad effects.  Going through an iterator
in popitem() will result in O(N**2) behavior for repeated calls.  If you
look at the r_dict implementation of popitem() you can see the fix there.

Alex

On Mon, Feb 20, 2012 at 6:18 AM, cfbolz <noreply at buildbot.pypy.org> wrote:

> Author: Carl Friedrich Bolz <cfbolz at gmx.de>
> Branch:
> Changeset: r52670:4b254e123047
> Date: 2012-02-20 12:17 +0100
> http://bitbucket.org/pypy/pypy/changeset/4b254e123047/
>
> Log:    issue1059 testing
>
>        make the .__dict__.clear method of builtin types raise an error. Fix
>        popitem on dict proxies (builtin types raise an error, normal types
>        work normally).
>
> diff --git a/pypy/objspace/std/dictmultiobject.py
> b/pypy/objspace/std/dictmultiobject.py
> --- a/pypy/objspace/std/dictmultiobject.py
> +++ b/pypy/objspace/std/dictmultiobject.py
> @@ -142,6 +142,13 @@
>             else:
>                 return result
>
> +    def popitem(self, w_dict):
> +        space = self.space
> +        iterator = self.iter(w_dict)
> +        w_key, w_value = iterator.next()
> +        self.delitem(w_dict, w_key)
> +        return (w_key, w_value)
> +
>     def clear(self, w_dict):
>         strategy = self.space.fromcache(EmptyDictStrategy)
>         storage = strategy.get_empty_storage()
> diff --git a/pypy/objspace/std/dictproxyobject.py
> b/pypy/objspace/std/dictproxyobject.py
> --- a/pypy/objspace/std/dictproxyobject.py
> +++ b/pypy/objspace/std/dictproxyobject.py
> @@ -3,7 +3,7 @@
>  from pypy.objspace.std.dictmultiobject import W_DictMultiObject,
> IteratorImplementation
>  from pypy.objspace.std.dictmultiobject import DictStrategy
>  from pypy.objspace.std.typeobject import unwrap_cell
> -from pypy.interpreter.error import OperationError
> +from pypy.interpreter.error import OperationError, operationerrfmt
>
>  from pypy.rlib import rerased
>
> @@ -44,7 +44,8 @@
>                 raise
>             if not w_type.is_cpytype():
>                 raise
> -            # xxx obscure workaround: allow cpyext to write to
> type->tp_dict.
> +            # xxx obscure workaround: allow cpyext to write to
> type->tp_dict
> +            # xxx even in the case of a builtin type.
>             # xxx like CPython, we assume that this is only done early
> after
>             # xxx the type is created, and we don't invalidate any cache.
>             w_type.dict_w[key] = w_value
> @@ -86,8 +87,14 @@
>                     for (key, w_value) in
> self.unerase(w_dict.dstorage).dict_w.iteritems()]
>
>     def clear(self, w_dict):
> -        self.unerase(w_dict.dstorage).dict_w.clear()
> -        self.unerase(w_dict.dstorage).mutated(None)
> +        space = self.space
> +        w_type = self.unerase(w_dict.dstorage)
> +        if (not space.config.objspace.std.mutable_builtintypes
> +                and not w_type.is_heaptype()):
> +            msg = "can't clear dictionary of type '%s'"
> +            raise operationerrfmt(space.w_TypeError, msg, w_type.name)
> +        w_type.dict_w.clear()
> +        w_type.mutated(None)
>
>  class DictProxyIteratorImplementation(IteratorImplementation):
>     def __init__(self, space, strategy, dictimplementation):
> diff --git a/pypy/objspace/std/test/test_dictproxy.py
> b/pypy/objspace/std/test/test_dictproxy.py
> --- a/pypy/objspace/std/test/test_dictproxy.py
> +++ b/pypy/objspace/std/test/test_dictproxy.py
> @@ -22,6 +22,9 @@
>         assert NotEmpty.string == 1
>         raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)')
>
> +        key, value = NotEmpty.__dict__.popitem()
> +        assert (key == 'a' and value == 1) or (key == 'b' and value == 4)
> +
>     def test_dictproxyeq(self):
>         class a(object):
>             pass
> @@ -43,6 +46,11 @@
>         assert s1 == s2
>         assert s1.startswith('{') and s1.endswith('}')
>
> +    def test_immutable_dict_on_builtin_type(self):
> +        raises(TypeError, "int.__dict__['a'] = 1")
> +        raises(TypeError, int.__dict__.popitem)
> +        raises(TypeError, int.__dict__.clear)
> +
>  class AppTestUserObjectMethodCache(AppTestUserObject):
>     def setup_class(cls):
>         cls.space = gettestobjspace(
> diff --git a/pypy/objspace/std/test/test_typeobject.py
> b/pypy/objspace/std/test/test_typeobject.py
> --- a/pypy/objspace/std/test/test_typeobject.py
> +++ b/pypy/objspace/std/test/test_typeobject.py
> @@ -993,7 +993,9 @@
>         raises(TypeError, setattr, list, 'append', 42)
>         raises(TypeError, setattr, list, 'foobar', 42)
>         raises(TypeError, delattr, dict, 'keys')
> -
> +        raises(TypeError, 'int.__dict__["a"] = 1')
> +        raises(TypeError, 'int.__dict__.clear()')
> +
>     def test_nontype_in_mro(self):
>         class OldStyle:
>             pass
> _______________________________________________
> pypy-commit mailing list
> pypy-commit at python.org
> http://mail.python.org/mailman/listinfo/pypy-commit
>



-- 
"I disapprove of what you say, but I will defend to the death your right to
say it." -- Evelyn Beatrice Hall (summarizing Voltaire)
"The people's good is the highest law." -- Cicero
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/pypy-dev/attachments/20120220/a3fa0b4c/attachment.html>


More information about the pypy-dev mailing list