from bulletml.errors import Error
from bulletml.expr import NumberDef, INumberDef
+
__all_ = ["ParseError", "BulletML"]
class ParseError(Error):
return cls([NumberDef(subelem.text) for subelem in element
if realtag(subelem) == "param"])
- def __getstate__(self):
- if self.params:
- return dict(params=[param.expr for param in self.params])
- else:
- return {}
-
- def __setstate__(self, state):
- self.__init__(NumberDef(param) for param in state.get("params", []))
-
def __call__(self, params, rank):
return [param(params, rank) for param in self.params]
return state
def __setstate__(self, state):
- self.__init__(INumberDef(state["term"]), state.get("horizontal"),
+ self.__init__(INumberDef(state["frames"]), state.get("horizontal"),
state.get("vertical"))
@classmethod
def __getstate__(self):
state = dict(bullet=self.bullet)
if self.params.params:
- state["params"] = self.params.__getstate__()
+ state["params"] = [param.expr for param in self.params.params]
return state
def __setstate__(self, state):
bullet = state["bullet"]
params = [NumberDef(param) for param in state.get("params", [])]
- self.__init__(bullet, params)
+ self.__init__(bullet, ParamList(params))
@classmethod
def FromElement(cls, doc, element):
return dict(actions=self.actions)
def __setstate__(self, state):
- self.__init__(state)
+ self.__init__(state["actions"])
@classmethod
def FromElement(cls, doc, element):
def __getstate__(self):
state = dict(action=self.action)
if self.params.params:
- state["params"] = self.params.__getstate__()
+ state["params"] = [param.expr for param in self.params.params]
return state
def __setstate__(self, state):
action = state["action"]
params = [NumberDef(param) for param in state.get("params", [])]
- self.__init__(action, params)
+ self.__init__(action, ParamList(params))
@classmethod
def FromElement(cls, doc, element):
state["offset"] = self.offset
return state
+ def __setstate__(self, state):
+ self.__init__(**state)
+
@classmethod
def FromElement(cls, doc, element):
"""Construct using an ElementTree-style element."""
def __getstate__(self):
state = dict(fire=self.fire)
if self.params.params:
- state["params"] = self.params.__getstate__()
+ state["params"] = [param.expr for param in self.params.params]
return state
def __setstate__(self, state):
fire = state["fire"]
params = [NumberDef(param) for param in state.get("params", [])]
- self.__init__(fire, params)
+ self.__init__(fire, ParamList(params))
@classmethod
def FromElement(cls, doc, element):
return dict(type=self.type, actions=self.actions)
def __setstate__(self, state):
- self.__init__(state["type"], state.get("actions"))
+ self.__init__(state["type"], actions=state.get("actions"))
@classmethod
- def FromDocument(cls, source):
- """Return a BulletML instance based on a string or file-like."""
+ def FromXML(cls, source):
+ """Return a BulletML instance based on XML."""
if not hasattr(source, 'read'):
source = StringIO(source)
return self
+ @classmethod
+ def FromYAML(cls, source):
+ """Create a BulletML instance based on YAML."""
+
+ # Late import to avoid a circular dependency.
+ try:
+ import bulletml.bulletyaml
+ import yaml
+ except ImportError:
+ raise ParseError("PyYAML is not available")
+ else:
+ try:
+ return yaml.load(source)
+ except Exception, exc:
+ raise ParseError(str(exc))
+
+ @classmethod
+ def FromDocument(cls, source):
+ """Create a BulletML instance based on a seekable file or string.
+
+ This attempts to autodetect if the stream is XML or YAML.
+ """
+ if not hasattr(source, 'read'):
+ source = StringIO(source)
+ start = source.read(1)
+ source.seek(0)
+ if start == "<":
+ return cls.FromXML(source)
+ elif start == "!":
+ return cls.FromYAML(source)
+ else:
+ raise ParseError("unknown initial character %r" % start)
+
@property
def top(self):
"""Get a list of all top-level actions."""