diff options
author | Jan Pokorný <jpokorny@redhat.com> | 2014-05-30 16:24:03 +0200 |
---|---|---|
committer | Jan Pokorný <jpokorny@redhat.com> | 2014-05-30 16:30:43 +0200 |
commit | e7856c2e626fb27e8c27eca4c6a77deba2fca3b7 (patch) | |
tree | c4efcd789dc6279e9b13aaa8e7b29b44b751b53b /format.py | |
parent | 64dccfab85f9d583cbd32a0120f8e750b23c5290 (diff) | |
download | clufter-e7856c2e626fb27e8c27eca4c6a77deba2fca3b7.tar.gz clufter-e7856c2e626fb27e8c27eca4c6a77deba2fca3b7.tar.xz clufter-e7856c2e626fb27e8c27eca4c6a77deba2fca3b7.zip |
format: allow implicit "produce" generic->specific chaining
... which is also applied on XML's get_bytestring, i.e.,:
thanks to "chained" flag in the decorator of the producing method,
the responsibility is first generated upwards, to Format, if the
respective implementation is able to cope with the request on this
general level (like fetching string from file), the product is then
the final product, otherwise (product is None), more specific
implementation is used instead (like getting string from existing
ElementTree object), and this goes on and forth.
Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
Diffstat (limited to 'format.py')
-rw-r--r-- | format.py | 31 |
1 files changed, 21 insertions, 10 deletions
@@ -138,20 +138,34 @@ class Format(object): return self._representations.copy() @staticmethod - def producing(protocol, protect=False): + def producing(protocol, chained=False, protect=False): """Decorator for externalizing method understood by the `Format` magic As a bonus: caching of representations.""" def deco_meth(meth): def deco_args(self, protocol, *args, **kwargs): + # XXX enforce nochain for this interative processing? protect_safe = kwargs.pop('protect_safe', False) try: # stored -> computed norm.: detuple if len == 1 produced = args2unwrapped(*self._representations[protocol]) except KeyError: - produced = meth(self, protocol, *args, **kwargs) - # computed -> stored normalization - self._representations[protocol] = *arg2wrapped(produced) + produced = None + worklist = [type(self)] + this_m = self._protocols[protocol] + while worklist: + t = worklist.pop() + that_m = t._protocols[protocol] + if that_m is this_m and chained: + worklist.extend(b for b in t.__bases__ if formats is + getattr(b, '__metaclass__', None)) + continue + if that_m is not this_m: + produced = that_m(self, protocol, *args, **kwargs) + if produced is None: + produced = meth(self, protocol, *args, **kwargs) + # computed -> stored normalization + self.swallow(protocol, *arg2wrapped(produced)) if protect and not protect_safe and not mutable(produced): log.debug("{0}:{1}:Forced deepcopy of `{2}' instance" @@ -420,13 +434,10 @@ class XML(SimpleFormat): native_protocol = 'etree' - @SimpleFormat.producing('bytestring') - def get_bytestring(self, protocol): - ret = super(XML, self).get_bytestring(self) - if ret is not None: - return ret - # fallback + @SimpleFormat.producing('bytestring', chained=True) + def get_bytestring(self, protocol): + # chained fallback return etree.tostring(self('etree', protect_safe=True), pretty_print=True) |