Commit b0b7489e authored by Tim Peters's avatar Tim Peters

ZODB.utils grows a new function positive_id(), which returns the id() of

an object as a non-negative integer.  Code trying to pass addresses to
an %x format uses positive_id(), and this avoids a Python FutureWarning
about applying %x to negative ints.  The primary difference between this
and the last stab is that positive_id() should work OK on 64-bit boxes
too.  What we really want here is C's %p format code, but in Python we
can't even reliably know the width of native addresses.
parent 771d5748
...@@ -39,6 +39,8 @@ from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet ...@@ -39,6 +39,8 @@ from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
from ZODB.utils import positive_id
TYPE_UNKNOWN, TYPE_BTREE, TYPE_BUCKET = range(3) TYPE_UNKNOWN, TYPE_BTREE, TYPE_BUCKET = range(3)
_type2kind = {IOBTree: (TYPE_BTREE, True), _type2kind = {IOBTree: (TYPE_BTREE, True),
...@@ -198,9 +200,7 @@ def crack_bucket(b, is_mapping): ...@@ -198,9 +200,7 @@ def crack_bucket(b, is_mapping):
return keys, values return keys, values
def type_and_adr(obj): def type_and_adr(obj):
# Force the address to look positive. A negative address will return "%s (0x%x)" % (type(obj).__name__, positive_id(obj))
# show up as signed in Python 2.4, and in 2.3 raises FutureWarning.
return "%s (0x%x)" % (type(obj).__name__, id(obj) & 0xffffffffL)
# Walker implements a depth-first search of a BTree (or TreeSet or Set or # Walker implements a depth-first search of a BTree (or TreeSet or Set or
# Bucket). Subclasses must implement the visit_btree() and visit_bucket() # Bucket). Subclasses must implement the visit_btree() and visit_bucket()
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
############################################################################## ##############################################################################
"""Database connection support """Database connection support
$Id: Connection.py,v 1.143 2004/04/06 20:21:55 tim_one Exp $""" $Id: Connection.py,v 1.144 2004/04/06 21:47:12 tim_one Exp $"""
import logging import logging
import sys import sys
...@@ -33,7 +33,7 @@ from ZODB.ExportImport import ExportImport ...@@ -33,7 +33,7 @@ from ZODB.ExportImport import ExportImport
from ZODB.POSException \ from ZODB.POSException \
import ConflictError, ReadConflictError, InvalidObjectReference import ConflictError, ReadConflictError, InvalidObjectReference
from ZODB.TmpStore import TmpStore from ZODB.TmpStore import TmpStore
from ZODB.utils import oid_repr, z64 from ZODB.utils import oid_repr, z64, positive_id
from ZODB.serialize import ObjectWriter, ConnectionObjectReader, myhasattr from ZODB.serialize import ObjectWriter, ConnectionObjectReader, myhasattr
global_reset_counter = 0 global_reset_counter = 0
...@@ -223,9 +223,7 @@ class Connection(ExportImport, object): ...@@ -223,9 +223,7 @@ class Connection(ExportImport, object):
ver = ' (in version %s)' % `self._version` ver = ' (in version %s)' % `self._version`
else: else:
ver = '' ver = ''
# Force the address to look positive. A negative address will return '<Connection at %08x%s>' % (positive_id(self), ver)
# show up as signed in Python 2.4, and in 2.3 raises FutureWarning.
return '<Connection at %08x%s>' % (id(self) & 0xffffffffL, ver)
def get(self, oid): def get(self, oid):
"""Return the persistent object with oid 'oid'. """Return the persistent object with oid 'oid'.
......
...@@ -36,11 +36,12 @@ TODO ...@@ -36,11 +36,12 @@ TODO
add in tests for objects which are modified multiple times, add in tests for objects which are modified multiple times,
for example an object that gets modified in multiple sub txns. for example an object that gets modified in multiple sub txns.
$Id: testTransaction.py,v 1.23 2004/04/06 01:06:41 tim_one Exp $ $Id: testTransaction.py,v 1.24 2004/04/06 21:47:12 tim_one Exp $
""" """
import unittest import unittest
import transaction import transaction
from ZODB.utils import positive_id
class TransactionTests(unittest.TestCase): class TransactionTests(unittest.TestCase):
...@@ -532,7 +533,9 @@ class BasicJar: ...@@ -532,7 +533,9 @@ class BasicJar:
self.ccommit_sub = 0 self.ccommit_sub = 0
def __repr__(self): def __repr__(self):
return "<%s %X %s>" % (self.__class__.__name__, id(self), self.errors) return "<%s %X %s>" % (self.__class__.__name__,
positive_id(self),
self.errors)
def sortKey(self): def sortKey(self):
# All these jars use the same sort key, and Python's list.sort() # All these jars use the same sort key, and Python's list.sort()
......
...@@ -69,3 +69,26 @@ def oid_repr(oid): ...@@ -69,3 +69,26 @@ def oid_repr(oid):
return repr(oid) return repr(oid)
serial_repr = oid_repr serial_repr = oid_repr
# Addresses can "look negative" on some boxes, some of the time. If you
# feed a "negative address" to an %x format, Python 2.3 displays it as
# unsigned, but produces a FutureWarning, because Python 2.4 will display
# it as signed. So when you want to prodce an address, use positive_id() to
# obtain it.
def positive_id(obj):
"""Return id(obj) as a non-negative integer."""
result = id(obj)
if result < 0:
# This is a puzzle: there's no way to know the natural width of
# addresses on this box (in particular, there's no necessary
# relation to sys.maxint). Try 32 bits first (and on a 32-bit
# box, adding 2**32 gives a positive number with the same hex
# representation as the original result).
result += 1L << 32
if result < 0:
# Undo that, and try 64 bits.
result -= 1L << 32
result += 1L << 64
assert result >= 0 # else addresses are fatter than 64 bits
return result
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