sync to Atlas repo

This commit is contained in:
Luciano Ramalho
2014-12-06 15:39:48 -02:00
parent b38e6fc5f2
commit dcd59eef31
12 changed files with 490 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
# Code and text by BitBucket user "enigmacurry" posted to
# https://bitbucket.org/pypy/pypy/issue/708/discrepancy-in-dict-subclass-__getitem__
# Adapted by Luciano Ramalho:
# - changed comments to docstring to run with doctest;
# - added test for Test class raising exception
# - and added () to print.
"""
This is a test case to describe a bug I'm seeing in PyPy 1.5. I have
a Cache object that is a dictionary that supports lookup via regular
attribute access. For instance:
>>> c = Cache()
>>> c["asdf"] = "asdf"
>>> c.asdf == c["asdf"]
True
>>> t = Test()
>>> t["asdf"] = "asdf"
>>> t.asdf == t["asdf"]
Traceback (most recent call last):
...
Exception: Trying to getitem: asdf
When looking up keys via attribute, PyPy 1.5 calls __getitem__
whereas CPython 2.7.1 does not.
"""
class Cache(dict):
"A dictionary that supports attribute style key lookup"
def __init__(self, **kw):
dict.__init__(self, kw)
self.__dict__ = self
class Test(Cache):
def __getitem__(self, item):
# I want to process items differently than attributes:
raise Exception("Trying to getitem: %s" % item)
if __name__ == "__main__":
t = Test()
t["asdf"] = "asdf"
#CPython does not call __getitem__ .. PyPy does:
print(t.asdf)
#Doesn't matter if it's a member of __dict__ or not:
print(t.__getattribute__)

View File

@@ -0,0 +1,64 @@
"""
Variation of ``tombola.Tombola`` implementing ``__subclasshook__``.
Tests with simple classes::
>>> Tombola.__subclasshook__(object)
NotImplemented
>>> class Complete:
... def __init__(): pass
... def load(): pass
... def pick(): pass
... def loaded(): pass
...
>>> Tombola.__subclasshook__(Complete)
True
>>> issubclass(Complete, Tombola)
"""
from abc import ABC, abstractmethod
from inspect import getmembers, isfunction
class Tombola(ABC): # <1>
@abstractmethod
def __init__(self, iterable): # <2>
"""New instance is loaded from an iterable."""
@abstractmethod
def load(self, iterable):
"""Add items from an iterable."""
@abstractmethod
def pick(self): # <3>
"""Remove item at random, returning it.
This method should raise `LookupError` when the instance is empty.
"""
def loaded(self): # <4>
try:
item = self.pick()
except LookupError:
return False
else:
self.load([item]) # put it back
return True
@classmethod
def __subclasshook__(cls, other_cls):
if cls is Tombola:
interface_names = function_names(cls)
found_names = set()
for a_cls in other_cls.__mro__:
found_names |= function_names(a_cls)
if found_names >= interface_names:
return True
return NotImplemented
def function_names(obj):
return {name for name, _ in getmembers(obj, isfunction)}