Skip to content

Commit

Permalink
ZODB.utils grows a new function positive_id(), which returns the id() of
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Tim Peters committed Apr 6, 2004
1 parent fb213a2 commit f7b96ae
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 10 deletions.
6 changes: 3 additions & 3 deletions src/BTrees/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet

from ZODB.utils import positive_id

TYPE_UNKNOWN, TYPE_BTREE, TYPE_BUCKET = range(3)

_type2kind = {IOBTree: (TYPE_BTREE, True),
Expand Down Expand Up @@ -198,9 +200,7 @@ def crack_bucket(b, is_mapping):
return keys, values

def type_and_adr(obj):
# Force the address to look positive. A negative address will
# show up as signed in Python 2.4, and in 2.3 raises FutureWarning.
return "%s (0x%x)" % (type(obj).__name__, id(obj) & 0xffffffffL)
return "%s (0x%x)" % (type(obj).__name__, positive_id(obj))

# Walker implements a depth-first search of a BTree (or TreeSet or Set or
# Bucket). Subclasses must implement the visit_btree() and visit_bucket()
Expand Down
8 changes: 3 additions & 5 deletions src/ZODB/Connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
##############################################################################
"""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 sys
Expand All @@ -33,7 +33,7 @@
from ZODB.POSException \
import ConflictError, ReadConflictError, InvalidObjectReference
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

global_reset_counter = 0
Expand Down Expand Up @@ -223,9 +223,7 @@ def __repr__(self):
ver = ' (in version %s)' % `self._version`
else:
ver = ''
# Force the address to look positive. A negative address will
# show up as signed in Python 2.4, and in 2.3 raises FutureWarning.
return '<Connection at %08x%s>' % (id(self) & 0xffffffffL, ver)
return '<Connection at %08x%s>' % (positive_id(self), ver)

def get(self, oid):
"""Return the persistent object with oid 'oid'.
Expand Down
7 changes: 5 additions & 2 deletions src/ZODB/tests/testTransaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,12 @@
add in tests for objects which are modified multiple times,
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 transaction
from ZODB.utils import positive_id

class TransactionTests(unittest.TestCase):

Expand Down Expand Up @@ -532,7 +533,9 @@ def __init__(self, errors=(), tracing=0):
self.ccommit_sub = 0

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):
# All these jars use the same sort key, and Python's list.sort()
Expand Down
23 changes: 23 additions & 0 deletions src/ZODB/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,26 @@ def oid_repr(oid):
return repr(oid)

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

0 comments on commit f7b96ae

Please sign in to comment.