Skip to content

Commit

Permalink
Change Properties to use IRenderable for rendering properties.
Browse files Browse the repository at this point in the history
This removes the hard-coded instance checks and allows the easy
addition of additional renderers.

Signed-off-by: Tom Prince <tom.prince@ualberta.net>
  • Loading branch information
tomprince committed May 14, 2011
1 parent d719420 commit 7381723
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 14 deletions.
10 changes: 10 additions & 0 deletions master/buildbot/interfaces.py
Expand Up @@ -1114,3 +1114,13 @@ def buildFinished(sb):
@param sb: a L{LatentSlaveBuilder}. The sb is the one for whom the
build finished.
"""

class IRenderable(Interface):
"""An object that can be interpolated with properties from a build.
"""

def render(properties):
"""Return the interpolation with the given properties
@param pmap: a L{Properties} instance containing the properties to interpolate.
"""
88 changes: 74 additions & 14 deletions master/buildbot/process/properties.py
Expand Up @@ -16,6 +16,9 @@
import re
import weakref
from buildbot import util
from buildbot.interfaces import IRenderable
from twisted.python.components import registerAdapter
from zope.interface import implements

class Properties(util.ComparableMixin):
"""
Expand Down Expand Up @@ -122,20 +125,7 @@ def render(self, value):
Return a variant of value that has any WithProperties objects
substituted. This recurses into Python's compound data types.
"""
# we use isinstance to detect Python's standard data types, and call
# this function recursively for the values in those types
if isinstance(value, (str, unicode)):
return value
elif isinstance(value, WithProperties):
return value.render(self)
elif isinstance(value, list):
return [ self.render(e) for e in value ]
elif isinstance(value, tuple):
return tuple([ self.render(e) for e in value ])
elif isinstance(value, dict):
return dict([ (self.render(k), self.render(v)) for k,v in value.iteritems() ])
else:
return value
return IRenderable(value).render(self)

class PropertyMap:
"""
Expand Down Expand Up @@ -219,6 +209,7 @@ class WithProperties(util.ComparableMixin):
want to interpolate build properties.
"""

implements(IRenderable)
compare_attrs = ('fmtstring', 'args')

def __init__(self, fmtstring, *args, **lambda_subs):
Expand All @@ -245,3 +236,72 @@ def render(self, properties):
s = self.fmtstring % pmap
pmap.clear_temporary_values()
return s


class _DefaultRenderer:
"""
Default IRenderable adaptor. Calls .render if availble, otherwise
returns argument unchanged.
"""

implements(IRenderable)

def __init__(self, value):
try:
self.renderer = value.render
except AttributeError:
self.renderer = lambda _: value

def render(self, properties):
return self.renderer(properties)

registerAdapter(_DefaultRenderer, object, IRenderable)


class _ListRenderer:
"""
List IRenderable adaptor. Maps Properties.render over the list.
"""

implements(IRenderable)

def __init__(self, value):
self.value = value

def render(self, properties):
return [ properties.render(e) for e in self.value ]

registerAdapter(_ListRenderer, list, IRenderable)


class _TupleRenderer:
"""
Tuple IRenderable adaptor. Maps Properties.render over the tuple.
"""

implements(IRenderable)

def __init__(self, value):
self.value = value

def render(self, properties):
return tuple([ properties.render(e) for e in self.value ])

registerAdapter(_TupleRenderer, tuple, IRenderable)


class _DictRenderer:
"""
Dict IRenderable adaptor. Maps Properties.render over the keya and values in the dict.
"""

implements(IRenderable)

def __init__(self, value):
self.value = value

def render(self, properties):
return dict([ (properties.render(k), properties.render(v)) for k,v in self.value.iteritems() ])


registerAdapter(_DictRenderer, dict, IRenderable)

0 comments on commit 7381723

Please sign in to comment.