# 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)

## Attachments

## Change History

**Note:**See TracTickets for help on using tickets.

Strange, it works for me under Python 2.5a2 on Linux and marshal dumps and loads inf/nan values correctly. Probably it's a win32 issue.

Anyway I've applied a modified version of your patch ([168]). I assume it fixes the problem, so I'm closing the ticket. Could you check in on your PC and reopen it if it still fails?

Thanks for the patch.