One small change in Python 2.5 is the __hash__ method behavior. In earlier versions the __hash__ method was supposed to return a normal integer always, but now due to changes in the id() builtin function the __hash__ method behavior was changed and it can return a long or an int.
This was easy to change in PyPy, the hash() builtin function implementation is part of the ObjectSpace as almost all the builtin functions and types.
It’s in pypy/objspace/descroperation.py:
def hash(space, w_obj):
w_hash = space.lookup(w_obj, '__hash__')
if w_hash is None:
if space.lookup(w_obj, '__eq__') is not None or \
space.lookup(w_obj, '__cmp__') is not None:
raise OperationError(space.w_TypeError,
space.wrap("unhashable type"))
return default_identity_hash(space, w_obj)
w_result = space.get_and_call_function(w_hash, w_obj)
if space.is_true(space.isinstance(w_result, space.w_int)):
return w_result
else:
raise OperationError(space.w_TypeError,
space.wrap("__hash__() should return an int or long"))
One don’t even need to know PyPy well to understand that the lines
if space.is_true(space.isinstance(w_result, space.w_int)):
return w_result
else:
raise OperationError(space.w_TypeError,
space.wrap("__hash__() should return an int or long"))
are responsible for raising a TypeError when the returning value from __hash__ is not an integer.
So just changing the condition
space.is_true(space.isinstance(w_result, space.w_int)):
to
(space.is_true(space.isinstance(w_result, space.w_int)) or space.is_true(space.isinstance(w_result, space.w_long))):
will solve this, I hope!
But that’s not all the code needed, I promised Carl to write tests for everything, but as I like to use TDD (test-driven development) it was already done.
Oh, and should I mention that I love PyPy’s documentation? Thanks guys!
(space.is_true(space.isinstance(w_result, space.w_int)) or
space.is_true(space.isinstance(w_result, space.w_long))):
cara o space.isinstance não suporta uma lista de parametros q nem a do python? E não seria legal q suportasse?
ai teu codigo seria só:
space.is_true(space.isinstance(w_result, [space.w_int, space.w_long]))
Leonardo:
not really sure what you are saying, but the space.isinstance method takes only a type as the second argument. Remember that you are dealing with RPython here, so the arguments of isinstance need to be compatible. A list and a type aren’t compatible.
Bruno:
Thanks for the compliments. Usually people find our documentation not so great (at least not well organized). If you find anything that needs improvement, please tell me.