Ticket #14 (closed defect: fixed)
Inf and NaN handling needs re-vamp
| Reported by: | Scott David Daniels <Scott.Daniels@…> | Owned by: | xi |
|---|---|---|---|
| Priority: | normal | Component: | pyyaml |
| Severity: | normal | Keywords: | |
| Cc: |
Description (last modified by xi) (diff)
Trying to import YAML fails in Python 2.5. Even simple patches fail, because the root cause is that NaNs and INFs cannot be marshalled/unmarshalled. Marshalling is used to save and restore compiled python modules, so a tested module can work initially, but later fail to load (when not from source).
When handling INFs and NaNs, you need to be careful. 1e300000 is not a safe way to represent infinity, and fails to pickle/unpickle safely from manifest constants. Different C runtimes represent the text for INFs and NaNs differently. Since Python 2.5 folds constants, a simple expression won't solve the problem.
The following changes should allow yaml to work on python 2.5a2 on Win2000 (and I think for 64-bit machines as well):
=============== constructor.py: ===============
*** 231,239 ****
else:
return sign*int(value)
- inf_value = 1e300000
- nan_value = inf_value/inf_value
-
def construct_yaml_float(self, node):
value = str(self.construct_scalar(node))
value = value.replace('_', '')
--- 231,236 ----
***************
***************
*** 242,251 ****
sign = -1
if value[0] in '+-':
value = value[1:]
! if value.lower() == '.inf':
! return sign*self.inf_value
! elif value.lower() == '.nan':
! return self.nan_value
elif ':' in value:
digits = [float(part) for part in value.split(':')]
digits.reverse()
--- 239,253 ----
sign = -1
if value[0] in '+-':
value = value[1:]
! if value.lower() in ('.inf', '.nan'):
! big = 1e300
! bigger = big * big
! while bigger > big and bigger == bigger:
! big = bigger
! bigger = big * big
! if value.lower() == '.nan':
! return bigger / bigger
! return sign * bigger
elif ':' in value:
digits = [float(part) for part in value.split(':')]
digits.reverse()
=============== representer.py: ===============
*** 192,200 ****
def represent_long(self, data):
return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
! repr_pos_inf = repr(1e300000)
! repr_neg_inf = repr(-1e300000)
! repr_nan = repr(1e300000/1e300000)
def represent_float(self, data):
repr_data = repr(data)
--- 192,206 ----
def represent_long(self, data):
return self.represent_scalar(u'tag:yaml.org,2002:int', unicode(data))
! big = 1e300
! bigger = big * big
! while bigger > big and bigger == bigger:
! big = bigger
! bigger = big * big
! repr_pos_inf = repr(bigger)
! repr_neg_inf = repr(-bigger)
! repr_nan = repr(bigger / bigger)
! del big, bigger
def represent_float(self, data):
repr_data = repr(data)
