Added hooke.util.yaml fixing YAML/NumPy type issues (by dropping data).
authorW. Trevor King <wking@drexel.edu>
Sat, 21 Aug 2010 18:37:20 +0000 (14:37 -0400)
committerW. Trevor King <wking@drexel.edu>
Sat, 21 Aug 2010 18:37:20 +0000 (14:37 -0400)
hooke/__init__.py
hooke/curve.py
hooke/playlist.py
hooke/util/yaml.py [new file with mode: 0644]

index 30abbd1..a220d8b 100644 (file)
@@ -33,6 +33,7 @@ except ImportError, e:
     logging.warn('could not load LICENSE from hooke.license')
     __license__ = 'All rights reserved.' 
 
+from .util import yaml  # extend YAML to parse Hooke-specific items.
 
 __version__ = (1, 0, 0, 'alpha', None, 'Ninken')
 """Version tuple::
index 5a32e6d..12ac5eb 100644 (file)
@@ -87,6 +87,14 @@ class Data (numpy.ndarray):
            [ 20.,  21.]])
     >>> z.info
     {'columns': ['distance (m)', 'force (N)']}
+
+    The data-type is also YAMLable (see :mod:`hooke.util.yaml`).
+
+    >>> import yaml
+    >>> print yaml.dump(d)
+    null
+    ...
+    <BLANKLINE>
     """
     def __new__(subtype, shape, dtype=numpy.float, buffer=None, offset=0,
                 strides=None, order=None, info=None):
@@ -183,7 +191,7 @@ class Curve (object):
     <Curve path>
     >>> z.command_stack[-1].arguments['curve'] == z
     True
-    >>> print yaml.dump(c)
+    >>> print yaml.dump(c)  # doctest: +REPORT_UDIFF
     &id001 !!python/object:hooke.curve.Curve
     command_stack: !!python/object/new:hooke.command_stack.CommandStack
       listitems:
@@ -211,7 +219,7 @@ class Curve (object):
 
     YAML still works, though.
 
-    >>> print yaml.dump(c.command_stack)
+    >>> print yaml.dump(c.command_stack)  # doctest: +REPORT_UDIFF
     &id001 !!python/object/new:hooke.command_stack.CommandStack
     listitems:
     - !!python/object:hooke.engine.CommandMessage
@@ -227,16 +235,7 @@ class Curve (object):
     <BLANKLINE>
     """
     def __init__(self, path, info=None):
-        #the data dictionary contains: {name of data: list of data sets [{[x], [y]}]
-        self.name = None
-        self.set_path(path)
-        self.driver = None
-        self.data = None
-        if info == None:
-            info = {}
-        self.info = info
-        self.command_stack = CommandStack()
-        self._hooke = None  # Hooke instance for Curve.load()
+        self.__setstate__({'path':path, 'info':info})
 
     def __str__(self):
         return str(self.__unicode__())
@@ -258,9 +257,15 @@ class Curve (object):
         return state
 
     def __setstate__(self, state):
-        self.name = self._hooke = None
+        # .data contains: {name of data: list of data sets [{[x], [y]}]
+        # ._hooke contains a Hooke instance for Curve.load()
+        self.name = self.driver = self.data = self._hooke = None
+        self.info = {}
+        self.command_stack = CommandStack()
         for key,value in state.items():
             setattr(self, key, value)
+        if self.info == None:
+            self.info = {}
         self.set_path(state.get('path', None))
 
     def set_hooke(self, hooke=None):
index b996a5f..3380bfc 100644 (file)
@@ -27,24 +27,6 @@ import os
 import os.path
 import types
 
-if False: # YAML dump debugging code
-    """To help isolate data types etc. that give YAML problems.
-
-    This is usually caused by external C modules (e.g. numpy) that
-    define new types (e.g. numpy.dtype) which YAML cannot inspect.
-    """
-    import yaml.representer
-    import sys
-    def ignore_aliases(data):
-        print data, type(data)
-        sys.stdout.flush()
-        if data in [None, ()]:
-            return True
-        if isinstance(data, (str, unicode, bool, int, float)):
-            return True
-    yaml.representer.SafeRepresenter.ignore_aliases = staticmethod(
-        ignore_aliases)
-
 import yaml
 from yaml.representer import RepresenterError
 
diff --git a/hooke/util/yaml.py b/hooke/util/yaml.py
new file mode 100644 (file)
index 0000000..22eeb14
--- /dev/null
@@ -0,0 +1,60 @@
+# Copyright
+
+"""Add representers to YAML to support Hooke.
+
+Without introspection, YAML cannot decide how to save some
+objects.  By refusing to save these objects, we obviously loose
+that information, so make sure the things you drop are either
+stored somewhere else or not important.
+
+>>> import yaml
+>>> a = numpy.array([1,2,3])
+>>> print yaml.dump(a)
+null
+...
+<BLANKLINE>
+
+The default behavior is to crash.
+
+>>> yaml.Dumper.yaml_representers.pop(numpy.ndarray)  # doctest: +ELLIPSIS
+<function ndarray_representer at 0x...>
+>>> print yaml.dump(a)
+Traceback (most recent call last):
+  ...
+    if data in [None, ()]:
+TypeError: data type not understood
+
+Restore the representer for future tests.
+
+>>> yaml.add_representer(numpy.ndarray, ndarray_representer)
+"""
+
+from __future__ import absolute_import
+import sys
+
+import numpy
+import yaml #from yaml.representer import Representer
+
+from ..curve import Data
+
+
+if False: # YAML dump debugging code
+    """To help isolate data types etc. that give YAML problems.
+
+    This is usually caused by external C modules (e.g. numpy) that
+    define new types (e.g. numpy.dtype) which YAML cannot inspect.
+    """
+    def ignore_aliases(data):
+        print data, type(data)
+        sys.stdout.flush()
+        if data in [None, ()]:
+            return True
+        if isinstance(data, (str, unicode, bool, int, float)):
+            return True
+    yaml.representer.SafeRepresenter.ignore_aliases = staticmethod(
+        ignore_aliases)
+
+def ndarray_representer(dumper, data):
+    return dumper.represent_none(None)
+yaml.add_representer(numpy.ndarray, ndarray_representer)
+yaml.add_representer(Data, ndarray_representer)