[Python-checkins] python/nondist/sandbox/pickletools pickletools.py,1.2,1.3
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Sat, 25 Jan 2003 15:44:22 -0800
Update of /cvsroot/python/python/nondist/sandbox/pickletools
In directory sc8-pr-cvs1:/tmp/cvs-serv17068
Modified Files:
pickletools.py
Log Message:
Fleshed out the two ways to pickle floats. It's best not to think too
much about all the ways this can screw up <0.6 wink>.
Index: pickletools.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/pickletools/pickletools.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -C2 -d -r1.2 -r1.3
*** pickletools.py 25 Jan 2003 22:32:08 -0000 1.2
--- pickletools.py 25 Jan 2003 23:44:19 -0000 1.3
***************
*** 223,226 ****
--- 223,283 ----
""")
+
+ def read_floatnl(f):
+ """
+ >>> import StringIO
+ >>> read_floatnl(StringIO.StringIO("-1.25\\n6"))
+ -1.25
+ """
+ s = read_stringnl(f, decode=False)
+ return float(s)
+
+ floatnl = ArgumentDescriptor(
+ name='floatnl',
+ n=None,
+ reader=read_floatnl,
+ doc="""A newline-terminated decimal floating literal.
+
+ In general this requires 17 significant digits for roundtrip
+ identity, and pickling then unpickling infinities, NaNs, and
+ minus zero doesn't work across boxes, or on some boxes even
+ on itself (e.g., Windows can't read the strings it produces
+ for infinities or NaNs).
+ """)
+
+ def read_float8(f):
+ """
+ >>> import StringIO, struct
+ >>> raw = struct.pack(">d", -1.25)
+ >>> raw
+ '\\xbf\\xf4\\x00\\x00\\x00\\x00\\x00\\x00'
+ >>> read_float8(StringIO.StringIO(raw + "\\n"))
+ -1.25
+ """
+
+ data = f.read(8)
+ if len(data) == 8:
+ return _unpack(">d", data)[0]
+ raise ValueError("not enough data in stream to read float8")
+
+
+ float8 = ArgumentDescriptor(
+ name='float8',
+ n=8,
+ reader=read_float8,
+ doc="""An 8-byte binary representation of a float, big-endian.
+
+ The format is unique to Python, and shared with the struct
+ module (format string '>d') "in theory" (the struct and cPickle
+ implementations don't share the code -- they should). It's
+ strongly related to the IEEE-754 double format, and, in normal
+ cases, is in fact identical to the big-endian 754 double format.
+ On other boxes the dynamic range is limited to that of a 754
+ double, and "add a half and chop" rounding is used to reduce
+ the precision to 53 bits. However, even on a 754 box,
+ infinities, NaNs, and minus zero may not be handled correctly
+ (may not survive roundtrip pickling intact).
+ """)
+
##############################################################################
# Python object descriptors. The stack used by the pickle machine holds
***************
*** 268,271 ****
--- 325,332 ----
doc="A Python integer object, short or long.")
+ pyfloat = PythonObject(
+ name='float',
+ obtype=float,
+ doc="A Python float object.")
##############################################################################
***************
*** 392,395 ****
--- 453,494 ----
"""),
+ # Two ways to spell floats.
+
+ I(name='FLOAT',
+ code='F',
+ args=[floatnl],
+ stack_before=[],
+ stack_after=[pyfloat],
+ proto=0,
+ doc="""Newline-terminated decimal float literal.
+
+ The argument is repr(a_float), and in general requires 17 significant
+ digits for roundtrip conversion to be an identity (this is so for
+ IEEE-754 double precision values, which is what Python float maps to
+ on most boxes).
+
+ In general, FLOAT cannot be used to transport infinities, NaNs, or
+ minus zero across boxes (or even on a single box, if the platform C
+ library can't read the strings it produces for such things -- Windows
+ is like that), but may do less damage than BINFLOAT on boxes with
+ greater precision or dynamic range than IEEE-754 double.
+ """),
+
+ I(name='BINFLOAT',
+ code='G',
+ args=[float8],
+ stack_before=[],
+ stack_after=[pyfloat],
+ proto=1,
+ doc="""Float stored in binary form, with 8 bytes of data.
+
+ This generally requires less than half the space of FLOAT encoding.
+ In general, BINFLOAT cannot be used to transport infinities, NaNs, or
+ minus zero, raises an exception if the exponent exceeds the range of
+ an IEEE-754 double, and retains no more than 53 bits of precision (if
+ there are more than that, "add a half and chop" rounding is used to
+ cut it back to 53 significant bits).
+ """),
+
# XXX opcodes below this point haven't been done yet.
***************
*** 449,463 ****
"""),
- I(name='FLOAT',
- code='F',
- args=[],
- stack_before=[],
- stack_after=[],
- proto=0,
- doc="""XXX One-line description goes here.
-
- XXX Doc body goes here.
- """),
-
I(name='NONE',
code='N',
--- 548,551 ----
***************
*** 770,784 ****
I(name='SETITEMS',
code='u',
- args=[],
- stack_before=[],
- stack_after=[],
- proto=0,
- doc="""XXX One-line description goes here.
-
- XXX Doc body goes here.
- """),
-
- I(name='BINFLOAT',
- code='G',
args=[],
stack_before=[],
--- 858,861 ----