summaryrefslogtreecommitdiffstats
path: root/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py')
-rw-r--r--src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py107
1 files changed, 56 insertions, 51 deletions
diff --git a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
index dc128bbe9..21662a984 100644
--- a/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
+++ b/src/lib/Bcfg2/Server/Plugins/Cfg/CfgGenshiGenerator.py
@@ -9,16 +9,17 @@ import traceback
import Bcfg2.Server.Plugin
from Bcfg2.Server.Plugins.Cfg import CfgGenerator
-logger = logging.getLogger(__name__)
+LOGGER = logging.getLogger(__name__)
try:
import genshi.core
from genshi.template import TemplateLoader, NewTextTemplate
from genshi.template.eval import UndefinedError
- have_genshi = True
+ HAS_GENSHI = True
except ImportError:
- TemplateLoader = None
- have_genshi = False
+ TemplateLoader = None # pylint: disable=C0103
+ HAS_GENSHI = False
+
def removecomment(stream):
""" A Genshi filter that removes comments from the stream. This
@@ -42,7 +43,7 @@ class CfgGenshiGenerator(CfgGenerator):
#: Handle .genshi files
__extensions__ = ['genshi']
-
+
#: ``__loader_cls__`` is the class that will be instantiated to
#: load the template files. It must implement one public function,
#: ``load()``, as :class:`genshi.template.TemplateLoader`.
@@ -61,9 +62,9 @@ class CfgGenshiGenerator(CfgGenerator):
def __init__(self, fname, spec, encoding):
CfgGenerator.__init__(self, fname, spec, encoding)
- if not have_genshi:
+ if not HAS_GENSHI:
msg = "Cfg: Genshi is not available: %s" % fname
- logger.error(msg)
+ LOGGER.error(msg)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
self.loader = self.__loader_cls__()
self.template = None
@@ -87,55 +88,59 @@ class CfgGenshiGenerator(CfgGenerator):
stack = traceback.extract_tb(sys.exc_info()[2])
for quad in stack:
if quad[0] == self.name:
- logger.error("Cfg: Error rendering %s at '%s': %s: %s" %
+ LOGGER.error("Cfg: Error rendering %s at '%s': %s: %s" %
(fname, quad[2], err.__class__.__name__, err))
break
raise
except:
- # a failure in a %{ python ... %} block -- the snippet in
- # the traceback is just the beginning of the block.
- err = sys.exc_info()[1]
- stack = traceback.extract_tb(sys.exc_info()[2])
- (filename, lineno, func, text) = stack[-1]
- # this is horrible, and I deeply apologize to whoever gets
- # to maintain this after I go to the Great Beer Garden in
- # the Sky. genshi is incredibly opaque about what's being
- # executed, so the only way I can find to determine which
- # {% python %} block is being executed -- if there are
- # multiples -- is to iterate through them and match the
- # snippet of the first line that's in the traceback with
- # the first non-empty line of the block.
- execs = [contents
- for etype, contents, loc in self.template.stream
- if etype == self.template.EXEC]
- contents = None
- if len(execs) == 1:
- contents = execs[0]
- elif len(execs) > 1:
- match = pyerror_re.match(func)
- if match:
- firstline = match.group(0)
- for pyblock in execs:
- if pyblock.startswith(firstline):
- contents = pyblock
- break
- # else, no EXEC blocks -- WTF?
- if contents:
- # we now have the bogus block, but we need to get the
- # offending line. To get there, we do (line number
- # given in the exception) - (firstlineno from the
- # internal genshi code object of the snippet) + 1 =
- # (line number of the line with an error within the
- # block, with all multiple line breaks elided to a
- # single line break)
- real_lineno = lineno - contents.code.co_firstlineno
- src = re.sub(r'\n\n+', '\n', contents.source).splitlines()
- logger.error("Cfg: Error rendering %s at '%s': %s: %s" %
- (fname, src[real_lineno], err.__class__.__name__,
- err))
- raise
+ self._handle_genshi_exception(fname, sys.exc_info())
get_data.__doc__ = CfgGenerator.get_data.__doc__
+ def _handle_genshi_exception(self, fname, exc):
+ """ this is horrible, and I deeply apologize to whoever gets
+ to maintain this after I go to the Great Beer Garden in the
+ Sky. genshi is incredibly opaque about what's being executed,
+ so the only way I can find to determine which {% python %}
+ block is being executed -- if there are multiples -- is to
+ iterate through them and match the snippet of the first line
+ that's in the traceback with the first non-empty line of the
+ block. """
+
+ # a failure in a %{ python ... %} block -- the snippet in
+ # the traceback is just the beginning of the block.
+ err = [1]
+ stack = traceback.extract_tb(exc[2])
+ lineno, func = stack[-1][1:3]
+ execs = [contents
+ for etype, contents in self.template.stream[:2]
+ if etype == self.template.EXEC]
+ contents = None
+ if len(execs) == 1:
+ contents = execs[0]
+ elif len(execs) > 1:
+ match = self.pyerror_re.match(func)
+ if match:
+ firstline = match.group(0)
+ for pyblock in execs:
+ if pyblock.startswith(firstline):
+ contents = pyblock
+ break
+ # else, no EXEC blocks -- WTF?
+ if contents:
+ # we now have the bogus block, but we need to get the
+ # offending line. To get there, we do (line number
+ # given in the exception) - (firstlineno from the
+ # internal genshi code object of the snippet) + 1 =
+ # (line number of the line with an error within the
+ # block, with all multiple line breaks elided to a
+ # single line break)
+ real_lineno = lineno - contents.code.co_firstlineno
+ src = re.sub(r'\n\n+', '\n', contents.source).splitlines()
+ LOGGER.error("Cfg: Error rendering %s at '%s': %s: %s" %
+ (fname, src[real_lineno], err.__class__.__name__,
+ err))
+ raise
+
def handle_event(self, event):
if event.code2str() == 'deleted':
return
@@ -146,6 +151,6 @@ class CfgGenshiGenerator(CfgGenerator):
except Exception:
msg = "Cfg: Could not load template %s: %s" % (self.name,
sys.exc_info()[1])
- logger.error(msg)
+ LOGGER.error(msg)
raise Bcfg2.Server.Plugin.PluginExecutionError(msg)
handle_event.__doc__ = CfgGenerator.handle_event.__doc__