[ZODB-Dev] 0 is not really equal to my object

Derrick Hudson dman at dman13.dyndns.org
Tue Feb 15 17:16:21 EST 2005


On Tue, Feb 15, 2005 at 04:02:59PM -0500, Tim Peters wrote:
| [Derrick Hudson]
| >> At least I can use "float('inf')" for my sentinel value to work around
| >> this problem.
| 
| [and Derrick replies]
| > Actually, I can't.
| >
| >         File "lib/python/ZODB/Connection.py", line 416, in commit
| >             dump(state)
| >     SystemError: frexp() result out of range
| >
| > I guess that's to protect people from saving 'inf' on linux then
| > wondering why they can't load their database on windows (or solaris, or
| > [other non-GNU-libc system]).
| 
| Na, it's just an accident.  All Python behavior in the presence of
| infinities, NaNs, and signed zeroes is a platform-dependent accident.
| That's because Python's implementation is written to the C89 standard, and
| the latter says nothing about any of those IEEE-754 special cases; as a
| result, there's no predicting what C will do across platforms in these
| cases, and so also no predicting what Python's C code will do.

Oh, I thought C used IEEE 754 and that 754 specified the bit pattern to
represent infinity, etc.  I thought at the byte-level the platforms
were consistent, just not in their conversion to and from strings.

So why doesn't the ZODB allow storing platform-dependent
representations (of course with some suitable warning to users)?

>>> import pickle
>>> pickle.dumps(float('inf'))
'Finf\n.'
>>> import cPickle
>>> cPickle.dumps(float('inf'))
'Finf\n.'
>>> cPickle.loads(cPickle.dumps(float('inf')))
inf

This is actually what I expected.

| For example, if you tried the code above on Windows, it would have died much
| earlier:
| 
| Python 2.3.5 (#62, Feb  8 2005, 16:23:02) [MSC v.1200 32 bit (Intel)] on
| win32
| >>> float('inf')
| Traceback (most recent call last):
|   File "<stdin>", line 1, in ?
| ValueError: invalid literal for float(): inf
| 
| That's because Microsoft C's strtod() implementation doesn't accept "inf"
| (in fact, MS's strtod() doesn't support any way to spell infinity, although
| its sprintf() produces "1.#INF" when fed an infinity).

I'm not surprised 'inf' isn't understood by msvcrt, but I am surprised
they don't provide their own representation.  How did you get an
infinity in to sprintf()?

| There's little hope of that changing before C99 becomes universal, _and_ C99
| compiler vendors all agree to support C99's optional 754/IEC floating-point
| gimmicks.  Given the current age of the C99 standard, and the weak efforts
| across vendors to supply conforming implementations so far, "never" is my
| best guess.

I'm certainly not attempting suffocation.  (I mean, holding my breath :-))

| Python could solve it itself, but that requires some
| knowledgeable volunteers able to commit to more work than anyone would
| believe at first (unless they've done this kind of work before -- I have, so
| I don't underestimate the pain).

The closest I've come is implementing single-precision addition and
subtraction in M68K assembly for a school lab.  My friend did the
scientific notation to/from ASCII conversion.  (this was not a group
lab, though, and no one actually finished it)

| > I also learned that I can't use the singleton trick:
| >
| >     class Infinite:
| >         ...
| >     Infinite = Infinite()
| >
| > because the ZODB stores the classname of the instance, and then tries to
| > find the class from the name when unpickling it.
| 
| You might find it helpful to study Python's docs for the pickle/cPickle
| modules.  It's really pickle that stores a class by storing a pair of
| strings (the path to the module the class can be found in, and the name of
| the class).  ZODB adds a few tricks of its own, but in general can't work
| with any object that cPickle can't work with on its own.

ZODB could do a better job of reporting the problem.  I realized what
was happening (duh!) when I studied how the ZODB loads the stored
object:

+++ Connection.py       15 Feb 2005 21:57:04 -0000
@@ -196,9 +196,13 @@
                     # Maybe their's more current data in the
                     # object's actual record!
                     return self[oid]
 
-            object=klass.__basicnew__()
+            try :
+                object=klass.__basicnew__()
+            except :
+                print locals()
+                raise
             object._p_oid=oid
             object._p_jar=self

I suppose that 'print' should be replaced with raising a more
appropriate exception.  I guess I only managed to find that issue
because I made that sentinel (with the same name as the class) a
string and string objects don't have a __basicnew__ attribute.

| > I reduced my sentinel value down to a basic string, and procedural-style
| > "if" blocks in the code that must handle it.
| 
| Did you try defining a *non*-Persistent class to model the behavior you want
| (an utterly ordinary Python class, preferably "new style")?

So now you tell me that that is -supposed- to work!  :-)

That was the first thing I tried.  (see the end of
http://mail.zope.org/pipermail/zodb-dev/2005-February/008483.html)

Hmm, now I understand the error I got then.  I was using that
singleton pattern.  Now I'm back full-circle to being able to do what
I wanted in the first place.  At least the result is good, and I
learned quite a bit along the way :-).

As far as value vs. reference .. value is good enough (hmm, I better
make __eq__ test value not identity) although having more than one
instance of this class isn't actually beneficial.

-D

-- 
How to shoot yourself in the foot with Java:
    You find that Microsoft and Sun have released incompatible class libraries
    both implementing Gun objects. You then find that although there are
    plenty of feet objects implemented in the past in many other languages,
    you cannot get access to one. But seeing as Java is so cool, you don't
    care and go around shooting anything else you can find.
                                                     (written by Mark Hammond)
 
www: http://dman13.dyndns.org/~dman/            jabber: dman at dman13.dyndns.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mail.zope.org/pipermail/zodb-dev/attachments/20050215/47b6efe8/attachment.bin


More information about the ZODB-Dev mailing list