Sophie

Sophie

distrib > Fedora > 17 > i386 > media > updates > by-pkgid > b50d8ee6d7871fcc13c0677a9364ed59 > files > 29

bcfg2-doc-1.3.0-1.fc17.noarch.rpm



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Bcfg2.Server.Plugin.helpers &mdash; Bcfg2 1.3.0 documentation</title>
    
    <link rel="stylesheet" href="../../../../_static/default.css" type="text/css" />
    <link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../../../../',
        VERSION:     '1.3.0',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../../../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../../../_static/sidebar.js"></script>
    <link rel="shortcut icon" href="../../../../_static/favicon.ico"/>
    <link rel="top" title="Bcfg2 1.3.0 documentation" href="../../../../index.html" />
    <link rel="up" title="Bcfg2.Server.Plugin" href="../Plugin.html" />
 
<link rel="stylesheet" href="../../../../_static/bcfg2.css" type=""/>

  </head>
  <body>

<div style="text-align: left; padding: 10px 10px 15px 15px">
<a href="../../../../index.html"><img src="../../../../_static/bcfg2_logo.png" border="0" alt="sampledoc"/></a>
</div>

    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="../../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
	<li><a href="../../../../index.html">home</a> |&nbsp;</li>
	<!--<li><a href="../../../../search.html">search</a> |&nbsp;</li>-->
	<li><a href="../../../../help/index.html">help</a> |&nbsp;</li>
	<li><a href="../../../../contents.html">documentation </a> &raquo;</li>

          <li><a href="../../../index.html" >Module code</a> &raquo;</li>
          <li><a href="../Plugin.html" accesskey="U">Bcfg2.Server.Plugin</a> &raquo;</li> 
      </ul>
    </div>
  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <h1>Source code for Bcfg2.Server.Plugin.helpers</h1><div class="highlight"><pre>
<span class="sd">&quot;&quot;&quot; Helper classes for Bcfg2 server plugins &quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">copy</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">operator</span>
<span class="kn">import</span> <span class="nn">lxml.etree</span>
<span class="kn">import</span> <span class="nn">Bcfg2.Server</span>
<span class="kn">import</span> <span class="nn">Bcfg2.Options</span>
<span class="kn">import</span> <span class="nn">Bcfg2.Statistics</span>
<span class="kn">from</span> <span class="nn">Bcfg2.Compat</span> <span class="kn">import</span> <span class="n">CmpMixin</span><span class="p">,</span> <span class="n">wraps</span>
<span class="kn">from</span> <span class="nn">Bcfg2.Server.Plugin.base</span> <span class="kn">import</span> <span class="n">Debuggable</span><span class="p">,</span> <span class="n">Plugin</span>
<span class="kn">from</span> <span class="nn">Bcfg2.Server.Plugin.interfaces</span> <span class="kn">import</span> <span class="n">Generator</span>
<span class="kn">from</span> <span class="nn">Bcfg2.Server.Plugin.exceptions</span> <span class="kn">import</span> <span class="n">SpecificityError</span><span class="p">,</span> \
    <span class="n">PluginExecutionError</span>

<span class="k">try</span><span class="p">:</span>
    <span class="kn">import</span> <span class="nn">django</span>  <span class="c"># pylint: disable=W0611</span>
    <span class="n">HAS_DJANGO</span> <span class="o">=</span> <span class="bp">True</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
    <span class="n">HAS_DJANGO</span> <span class="o">=</span> <span class="bp">False</span>

<span class="c">#: A dict containing default metadata for Path entries from bcfg2.conf</span>
<span class="n">DEFAULT_FILE_METADATA</span> <span class="o">=</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">OptionParser</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span>
        <span class="n">configfile</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">CFILE</span><span class="p">,</span>
        <span class="n">owner</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_OWNER</span><span class="p">,</span>
        <span class="n">group</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_GROUP</span><span class="p">,</span>
        <span class="n">mode</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_MODE</span><span class="p">,</span>
        <span class="n">secontext</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_SECONTEXT</span><span class="p">,</span>
        <span class="n">important</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_IMPORTANT</span><span class="p">,</span>
        <span class="n">paranoid</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_PARANOID</span><span class="p">,</span>
        <span class="n">sensitive</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">MDATA_SENSITIVE</span><span class="p">))</span>
<span class="n">DEFAULT_FILE_METADATA</span><span class="o">.</span><span class="n">parse</span><span class="p">([</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">CFILE</span><span class="o">.</span><span class="n">cmd</span><span class="p">,</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">CFILE</span><span class="p">])</span>
<span class="k">del</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="p">[</span><span class="s">&#39;args&#39;</span><span class="p">]</span>
<span class="k">del</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="p">[</span><span class="s">&#39;configfile&#39;</span><span class="p">]</span>

<span class="n">LOGGER</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>

<span class="c">#: a compiled regular expression for parsing info and :info files</span>
<span class="n">INFO_REGEX</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;owner:(\s)*(?P&lt;owner&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;group:(\s)*(?P&lt;group&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;mode:(\s)*(?P&lt;mode&gt;\w+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;secontext:(\s)*(?P&lt;secontext&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;paranoid:(\s)*(?P&lt;paranoid&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;sensitive:(\s)*(?P&lt;sensitive&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;encoding:(\s)*(?P&lt;encoding&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;important:(\s)*(?P&lt;important&gt;\S+)|&#39;</span> <span class="o">+</span>
                        <span class="s">&#39;mtime:(\s)*(?P&lt;mtime&gt;\w+)|&#39;</span><span class="p">)</span>


<div class="viewcode-block" id="bind_info"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.bind_info">[docs]</a><span class="k">def</span> <span class="nf">bind_info</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">infoxml</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">DEFAULT_FILE_METADATA</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; Bind the file metadata in the given</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.InfoXML` object to the given</span>
<span class="sd">    entry.</span>

<span class="sd">    :param entry: The abstract entry to bind the info to</span>
<span class="sd">    :type entry: lxml.etree._Element</span>
<span class="sd">    :param metadata: The client metadata to get info for</span>
<span class="sd">    :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">    :param infoxml: The info.xml file to pull file metadata from</span>
<span class="sd">    :type infoxml: Bcfg2.Server.Plugin.helpers.InfoXML</span>
<span class="sd">    :param default: Default metadata to supply when the info.xml file</span>
<span class="sd">                    does not include a particular attribute</span>
<span class="sd">    :type default: dict</span>
<span class="sd">    :returns: None</span>
<span class="sd">    :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">default</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
        <span class="n">entry</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">attr</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">infoxml</span><span class="p">:</span>
        <span class="n">mdata</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
        <span class="n">infoxml</span><span class="o">.</span><span class="n">pnode</span><span class="o">.</span><span class="n">Match</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">mdata</span><span class="p">,</span> <span class="n">entry</span><span class="o">=</span><span class="n">entry</span><span class="p">)</span>
        <span class="k">if</span> <span class="s">&#39;Info&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">mdata</span><span class="p">:</span>
            <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Failed to set metadata for file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
            <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">mdata</span><span class="p">[</span><span class="s">&#39;Info&#39;</span><span class="p">][</span><span class="bp">None</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
            <span class="n">entry</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">attr</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="track_statistics"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.track_statistics">[docs]</a><span class="k">class</span> <span class="nc">track_statistics</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>  <span class="c"># pylint: disable=C0103</span>
    <span class="sd">&quot;&quot;&quot; Decorator that tracks execution time for the given</span>
<span class="sd">    :class:`Plugin` method with :mod:`Bcfg2.Statistics` for reporting</span>
<span class="sd">    via ``bcfg2-admin perf`` &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param name: The name under which statistics for this function</span>
<span class="sd">                     will be tracked.  By default, the name will be</span>
<span class="sd">                     the name of the function concatenated with the</span>
<span class="sd">                     name of the class the function is a member of.</span>
<span class="sd">        :type name: string</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="c"># if this is None, it will be set later during __call_</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>

    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">func</span><span class="o">.</span><span class="n">__name__</span>

        <span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
        <span class="k">def</span> <span class="nf">inner</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
            <span class="sd">&quot;&quot;&quot; The decorated function &quot;&quot;&quot;</span>
            <span class="n">name</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>

            <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
            <span class="k">finally</span><span class="p">:</span>
                <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Statistics</span><span class="o">.</span><span class="n">stats</span><span class="o">.</span><span class="n">add_value</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span>

        <span class="k">return</span> <span class="n">inner</span>

</div>
<div class="viewcode-block" id="DatabaseBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked">[docs]</a><span class="k">class</span> <span class="nc">DatabaseBacked</span><span class="p">(</span><span class="n">Plugin</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; Provides capabilities for a plugin to read and write to a</span>
<span class="sd">    database.</span>

<span class="sd">    .. private-include: _use_db</span>
<span class="sd">    .. private-include: _must_lock</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c">#: The option to look up in :attr:`section` to determine whether or</span>
    <span class="c">#: not to use the database capabilities of this plugin.  The option</span>
    <span class="c">#: is retrieved with</span>
    <span class="c">#: :py:func:`ConfigParser.SafeConfigParser.getboolean`, and so must</span>
    <span class="c">#: conform to the possible values that function can handle.</span>
    <span class="n">option</span> <span class="o">=</span> <span class="s">&quot;use_database&quot;</span>

    <span class="k">def</span> <span class="nf">_section</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; The section to look in for :attr:`DatabaseBacked.option`</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
    <span class="n">section</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="n">_section</span><span class="p">)</span>

    <span class="nd">@property</span>
<div class="viewcode-block" id="DatabaseBacked._use_db"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked._use_db">[docs]</a>    <span class="k">def</span> <span class="nf">_use_db</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Whether or not this plugin is configured to use the</span>
<span class="sd">        database. &quot;&quot;&quot;</span>
        <span class="n">use_db</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">setup</span><span class="o">.</span><span class="n">cfp</span><span class="o">.</span><span class="n">getboolean</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">section</span><span class="p">,</span>
                                                <span class="bp">self</span><span class="o">.</span><span class="n">option</span><span class="p">,</span>
                                                <span class="n">default</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">use_db</span> <span class="ow">and</span> <span class="n">HAS_DJANGO</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">database_available</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">True</span>
        <span class="k">elif</span> <span class="ow">not</span> <span class="n">use_db</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">False</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> is true but django not found&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">option</span><span class="p">)</span>
            <span class="k">return</span> <span class="bp">False</span>
</div>
    <span class="nd">@property</span>
<div class="viewcode-block" id="DatabaseBacked._must_lock"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked._must_lock">[docs]</a>    <span class="k">def</span> <span class="nf">_must_lock</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Whether or not the backend database must acquire a thread</span>
<span class="sd">        lock before writing, because it does not allow multiple</span>
<span class="sd">        threads to write.&quot;&quot;&quot;</span>
        <span class="n">engine</span> <span class="o">=</span> \
            <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">setup</span><span class="o">.</span><span class="n">cfp</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">DB_ENGINE</span><span class="o">.</span><span class="n">cf</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
                                    <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">DB_ENGINE</span><span class="o">.</span><span class="n">cf</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span>
                                    <span class="n">default</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Options</span><span class="o">.</span><span class="n">DB_ENGINE</span><span class="o">.</span><span class="n">default</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">engine</span> <span class="o">==</span> <span class="s">&#39;sqlite3&#39;</span>
</div>
    <span class="nd">@staticmethod</span>
<div class="viewcode-block" id="DatabaseBacked.get_db_lock"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DatabaseBacked.get_db_lock">[docs]</a>    <span class="k">def</span> <span class="nf">get_db_lock</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Decorator to be used by a method of a</span>
<span class="sd">        :class:`DatabaseBacked` plugin that will update database data. &quot;&quot;&quot;</span>

        <span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
        <span class="k">def</span> <span class="nf">_acquire_and_run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
            <span class="sd">&quot;&quot;&quot; The decorated function &quot;&quot;&quot;</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_must_lock</span><span class="p">:</span>  <span class="c"># pylint: disable=W0212</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">db_write_lock</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span>
                    <span class="n">rv</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
                <span class="k">finally</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">db_write_lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">rv</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
            <span class="k">return</span> <span class="n">rv</span>
        <span class="k">return</span> <span class="n">_acquire_and_run</span>

</div></div>
<div class="viewcode-block" id="PluginDatabaseModel"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PluginDatabaseModel">[docs]</a><span class="k">class</span> <span class="nc">PluginDatabaseModel</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; A database model mixin that all database models used by</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.DatabaseBacked` plugins must</span>
<span class="sd">    inherit from.  This is just a mixin; models must also inherit from</span>
<span class="sd">    django.db.models.Model to be valid Django models.&quot;&quot;&quot;</span>

    <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>  <span class="c"># pylint: disable=C0111,W0232</span>
        <span class="n">app_label</span> <span class="o">=</span> <span class="s">&quot;Server&quot;</span>

</div>
<div class="viewcode-block" id="FileBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.FileBacked">[docs]</a><span class="k">class</span> <span class="nc">FileBacked</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; This object caches file data in memory. FileBacked objects are</span>
<span class="sd">    principally meant to be used as a part of</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.DirectoryBacked`. &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param name: The full path to the file to cache and monitor</span>
<span class="sd">        :type name: string</span>
<span class="sd">        :param fam: The FAM object used to receive notifications of</span>
<span class="sd">                    changes</span>
<span class="sd">        :type fam: Bcfg2.Server.FileMonitor.FileMonitor</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="nb">object</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

        <span class="c">#: A string containing the raw data in this file</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>

        <span class="c">#: The full path to the file</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>

        <span class="c">#: The FAM object used to receive notifications of changes</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">fam</span> <span class="o">=</span> <span class="n">fam</span>

<div class="viewcode-block" id="FileBacked.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.FileBacked.HandleEvent">[docs]</a>    <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; HandleEvent is called whenever the FAM registers an event.</span>

<span class="sd">        :param event: The event object</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">event</span> <span class="ow">and</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;exists&#39;</span><span class="p">,</span> <span class="s">&#39;changed&#39;</span><span class="p">,</span> <span class="s">&#39;created&#39;</span><span class="p">]:</span>
            <span class="k">return</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">Index</span><span class="p">()</span>
        <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
            <span class="n">err</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Failed to read file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">err</span><span class="p">))</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="n">err</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Failed to parse file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">err</span><span class="p">))</span>
</div>
<div class="viewcode-block" id="FileBacked.Index"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.FileBacked.Index">[docs]</a>    <span class="k">def</span> <span class="nf">Index</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Index() is called by :func:`HandleEvent` every time the</span>
<span class="sd">        data changes, and parses the data into usable data as</span>
<span class="sd">        required.&quot;&quot;&quot;</span>
        <span class="k">pass</span>
</div>
    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="DirectoryBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked">[docs]</a><span class="k">class</span> <span class="nc">DirectoryBacked</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; DirectoryBacked objects represent a directory that contains</span>
<span class="sd">    files, represented by objects of the type listed in</span>
<span class="sd">    :attr:`__child__`, and other directories recursively.  It monitors</span>
<span class="sd">    for new files and directories to be added, and creates new objects</span>
<span class="sd">    as required to track those.&quot;&quot;&quot;</span>

    <span class="c">#: The type of child objects to create for files contained within</span>
    <span class="c">#: the directory that is tracked.  Default is</span>
    <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.FileBacked`</span>
    <span class="n">__child__</span> <span class="o">=</span> <span class="n">FileBacked</span>

    <span class="c">#: Only track and include files whose names (not paths) match this</span>
    <span class="c">#: compiled regex.</span>
    <span class="n">patterns</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;.*&#39;</span><span class="p">)</span>

    <span class="c">#: Preemptively ignore files whose names (not paths) match this</span>
    <span class="c">#: compiled regex.  ``ignore`` can be set to ``None`` to ignore no</span>
    <span class="c">#: files.  If a file is encountered that does not match</span>
    <span class="c">#: :attr:`patterns` or ``ignore``, then a warning will be produced.</span>
    <span class="n">ignore</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">fam</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param data: The path to the data directory that will be</span>
<span class="sd">                     monitored</span>
<span class="sd">        :type data: string</span>
<span class="sd">        :param fam: The FAM object used to receive notifications of</span>
<span class="sd">                    changes</span>
<span class="sd">        :type fam: Bcfg2.Server.FileMonitor.FileMonitor</span>

<span class="sd">        .. -----</span>
<span class="sd">        .. autoattribute:: __child__</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="nb">object</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">normpath</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">fam</span> <span class="o">=</span> <span class="n">fam</span>

        <span class="c">#: self.entries contains information about the files monitored</span>
        <span class="c">#: by this object. The keys of the dict are the relative</span>
        <span class="c">#: paths to the files. The values are the objects (of type</span>
        <span class="c">#: :attr:`__child__`) that handle their contents.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="c">#: self.handles contains information about the directories</span>
        <span class="c">#: monitored by this object. The keys of the dict are the</span>
        <span class="c">#: values returned by the initial fam.AddMonitor() call (which</span>
        <span class="c">#: appear to be integers). The values are the relative paths of</span>
        <span class="c">#: the directories.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">handles</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="c"># Monitor everything in the plugin&#39;s directory</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">add_directory_monitor</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>

    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">()))</span>

<div class="viewcode-block" id="DirectoryBacked.add_directory_monitor"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked.add_directory_monitor">[docs]</a>    <span class="k">def</span> <span class="nf">add_directory_monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relative</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Add a new directory to the FAM for monitoring.</span>

<span class="sd">        :param relative: Path name to monitor. This must be relative</span>
<span class="sd">                         to the plugin&#39;s directory. An empty string</span>
<span class="sd">                         value (&quot;&quot;) will cause the plugin directory</span>
<span class="sd">                         itself to be monitored.</span>
<span class="sd">        :type relative: string</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">dirpathname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="n">relative</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">relative</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">dirpathname</span><span class="p">):</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> is not a directory&quot;</span> <span class="o">%</span> <span class="n">dirpathname</span><span class="p">)</span>
                <span class="k">return</span>
            <span class="n">reqid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">dirpathname</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">reqid</span><span class="p">]</span> <span class="o">=</span> <span class="n">relative</span>
</div>
<div class="viewcode-block" id="DirectoryBacked.add_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked.add_entry">[docs]</a>    <span class="k">def</span> <span class="nf">add_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relative</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Add a new file to our tracked entries, and to our FAM for</span>
<span class="sd">        monitoring.</span>

<span class="sd">        :param relative: Path name to monitor. This must be relative</span>
<span class="sd">                         to the plugin&#39;s directory.</span>
<span class="sd">        :type relative: string:</span>
<span class="sd">        :param event: FAM event that caused this entry to be added.</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">relative</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__child__</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span>
                                                             <span class="n">relative</span><span class="p">),</span>
                                                <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">relative</span><span class="p">]</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="DirectoryBacked.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.DirectoryBacked.HandleEvent">[docs]</a>    <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>  <span class="c"># pylint: disable=R0912</span>
        <span class="sd">&quot;&quot;&quot; Handle FAM events.</span>

<span class="sd">        This method is invoked by the FAM when it detects a change to</span>
<span class="sd">        a filesystem object we have requsted to be monitored.</span>

<span class="sd">        This method manages the lifecycle of events related to the</span>
<span class="sd">        monitored objects, adding them to our list of entries and</span>
<span class="sd">        creating objects of type :attr:`__child__` that actually do</span>
<span class="sd">        the domain-specific processing. When appropriate, it</span>
<span class="sd">        propogates events those objects by invoking their HandleEvent</span>
<span class="sd">        method in turn.</span>

<span class="sd">        :param event: FAM event that caused this entry to be added.</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">action</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span>

        <span class="c"># Exclude events for actions we don&#39;t care about</span>
        <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;endExist&#39;</span><span class="p">:</span>
            <span class="k">return</span>

        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">requestID</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">:</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Got </span><span class="si">%s</span><span class="s"> event with unknown handle (</span><span class="si">%s</span><span class="s">) for </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                        <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">))</span>
            <span class="k">return</span>

        <span class="c"># Clean up path names</span>
        <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">normpath</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">):</span>
            <span class="c"># the first event we get is on the data directory itself</span>
            <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:]</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;Ignoring event </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
            <span class="k">return</span>

        <span class="c"># Calculate the absolute and relative paths this event refers to</span>
        <span class="n">abspath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">],</span>
                               <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
        <span class="n">relpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">],</span>
                               <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;deleted&#39;</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
                <span class="k">if</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">relpath</span><span class="p">):</span>
                    <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
            <span class="c"># We remove values from self.entries, but not</span>
            <span class="c"># self.handles, because the FileMonitor doesn&#39;t stop</span>
            <span class="c"># watching a directory just because it gets deleted. If it</span>
            <span class="c"># is recreated, we will start getting notifications for it</span>
            <span class="c"># again without having to add a new monitor.</span>
        <span class="k">elif</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">abspath</span><span class="p">):</span>
            <span class="c"># Deal with events for directories</span>
            <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;exists&#39;</span><span class="p">,</span> <span class="s">&#39;created&#39;</span><span class="p">]:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">add_directory_monitor</span><span class="p">(</span><span class="n">relpath</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;changed&#39;</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">relpath</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                    <span class="c"># Ownerships, permissions or timestamps changed on</span>
                    <span class="c"># the directory. None of these should affect the</span>
                    <span class="c"># contents of the files, though it could change</span>
                    <span class="c"># our ability to access them.</span>
                    <span class="c">#</span>
                    <span class="c"># It seems like the right thing to do is to cancel</span>
                    <span class="c"># monitoring the directory and then begin</span>
                    <span class="c"># monitoring it again. But the current FileMonitor</span>
                    <span class="c"># class doesn&#39;t support canceling, so at least let</span>
                    <span class="c"># the user know that a restart might be a good</span>
                    <span class="c"># idea.</span>
                    <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Directory properties for </span><span class="si">%s</span><span class="s"> changed, please &quot;</span>
                                <span class="s">&quot; consider restarting the server&quot;</span> <span class="o">%</span> <span class="n">abspath</span><span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="c"># Got a &quot;changed&quot; event for a directory that we</span>
                    <span class="c"># didn&#39;t know about. Go ahead and treat it like a</span>
                    <span class="c"># &quot;created&quot; event, but log a warning, because this</span>
                    <span class="c"># is unexpected.</span>
                    <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Got </span><span class="si">%s</span><span class="s"> event for unexpected dir </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                                <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">abspath</span><span class="p">))</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">add_directory_monitor</span><span class="p">(</span><span class="n">relpath</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Got unknown dir event </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                            <span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">(),</span> <span class="n">abspath</span><span class="p">))</span>
        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">patterns</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;exists&#39;</span><span class="p">,</span> <span class="s">&#39;created&#39;</span><span class="p">]:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">relpath</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;changed&#39;</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">relpath</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">relpath</span><span class="p">]</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="c"># Got a &quot;changed&quot; event for a file that we didn&#39;t</span>
                    <span class="c"># know about. Go ahead and treat it like a</span>
                    <span class="c"># &quot;created&quot; event, but log a warning, because this</span>
                    <span class="c"># is unexpected.</span>
                    <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Got </span><span class="si">%s</span><span class="s"> event for unexpected file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                                <span class="p">(</span><span class="n">action</span><span class="p">,</span>
                                 <span class="n">abspath</span><span class="p">))</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">relpath</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Got unknown file event </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                            <span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">(),</span> <span class="n">abspath</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Could not process filename </span><span class="si">%s</span><span class="s">; ignoring&quot;</span> <span class="o">%</span>
                        <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>

</div></div>
<div class="viewcode-block" id="XMLFileBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLFileBacked">[docs]</a><span class="k">class</span> <span class="nc">XMLFileBacked</span><span class="p">(</span><span class="n">FileBacked</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; This object parses and caches XML file data in memory.  It can</span>
<span class="sd">    be used as a standalone object or as a part of</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.XMLDirectoryBacked`</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c">#: If ``__identifier__`` is set, then a top-level tag with the</span>
    <span class="c">#: specified name will be required on the file being cached.  Its</span>
    <span class="c">#: value will be available as :attr:`label`.  To disable this</span>
    <span class="c">#: behavior, set ``__identifier__`` to ``None``.</span>
    <span class="n">__identifier__</span> <span class="o">=</span> <span class="s">&#39;name&#39;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">should_monitor</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param filename: The full path to the file to cache and monitor</span>
<span class="sd">        :type filename: string</span>
<span class="sd">        :param fam: The FAM object used to receive notifications of</span>
<span class="sd">                    changes</span>
<span class="sd">        :type fam: Bcfg2.Server.FileMonitor.FileMonitor</span>
<span class="sd">        :param should_monitor: Whether or not to monitor this file for</span>
<span class="sd">                               changes. It may be useful to disable</span>
<span class="sd">                               monitoring when, for instance, the file</span>
<span class="sd">                               is monitored by another object (e.g.,</span>
<span class="sd">                               an</span>
<span class="sd">                               :class:`Bcfg2.Server.Plugin.helpers.XMLDirectoryBacked`</span>
<span class="sd">                               object).</span>
<span class="sd">        :type should_monitor: bool</span>

<span class="sd">        .. -----</span>
<span class="sd">        .. autoattribute:: __identifier__</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">FileBacked</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="n">fam</span><span class="p">)</span>

        <span class="c">#: The raw XML data contained in the file as an</span>
        <span class="c">#: :class:`lxml.etree.ElementTree` object, with XIncludes</span>
        <span class="c">#: processed.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span> <span class="o">=</span> <span class="bp">None</span>

        <span class="c">#: The label of this file.  This is determined from the</span>
        <span class="c">#: top-level tag in the file, which must have an attribute</span>
        <span class="c">#: specified by :attr:`__identifier__`.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">label</span> <span class="o">=</span> <span class="s">&quot;&quot;</span>

        <span class="c">#: All entries in this file.  By default, all immediate</span>
        <span class="c">#: children of the top-level XML tag.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="c">#: &quot;Extra&quot; files included in this file by XInclude.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">extras</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="c">#: Whether or not to monitor this file for changes.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">should_monitor</span> <span class="o">=</span> <span class="n">should_monitor</span>
        <span class="k">if</span> <span class="n">fam</span> <span class="ow">and</span> <span class="n">should_monitor</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_follow_xincludes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fname</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">xdata</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; follow xincludes, adding included files to self.extras &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">xdata</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">fname</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
                <span class="n">xdata</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">getroottree</span><span class="p">()</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">xdata</span> <span class="o">=</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">parse</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span>
        <span class="n">included</span> <span class="o">=</span> <span class="p">[</span><span class="n">el</span> <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">xdata</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s">&#39;//</span><span class="si">%s</span><span class="s">include&#39;</span> <span class="o">%</span>
                                               <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XI_NAMESPACE</span><span class="p">)]</span>
        <span class="k">for</span> <span class="n">el</span> <span class="ow">in</span> <span class="n">included</span><span class="p">:</span>
            <span class="n">name</span> <span class="o">=</span> <span class="n">el</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;href&quot;</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">):</span>
                <span class="n">fpath</span> <span class="o">=</span> <span class="n">name</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">fname</span><span class="p">:</span>
                    <span class="n">rel</span> <span class="o">=</span> <span class="n">fname</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">rel</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span>
                <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">rel</span><span class="p">),</span> <span class="n">name</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">fpath</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">extras</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">fpath</span><span class="p">):</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">_follow_xincludes</span><span class="p">(</span><span class="n">fname</span><span class="o">=</span><span class="n">fpath</span><span class="p">)</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">add_monitor</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s"> does not exist, skipping&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
                    <span class="k">if</span> <span class="n">el</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s">&#39;./</span><span class="si">%s</span><span class="s">fallback&#39;</span> <span class="o">%</span> <span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XI_NAMESPACE</span><span class="p">):</span>
                        <span class="n">LOGGER</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">LOGGER</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>

<div class="viewcode-block" id="XMLFileBacked.Index"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLFileBacked.Index">[docs]</a>    <span class="k">def</span> <span class="nf">Index</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span> <span class="o">=</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XML</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="n">base_url</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
                                    <span class="n">parser</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XMLParser</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_follow_xincludes</span><span class="p">()</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">extras</span><span class="p">:</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">getroottree</span><span class="p">()</span><span class="o">.</span><span class="n">xinclude</span><span class="p">()</span>
            <span class="k">except</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XIncludeError</span><span class="p">:</span>
                <span class="n">err</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;XInclude failed on </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">err</span><span class="p">))</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__identifier__</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">label</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="o">.</span><span class="n">attrib</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">__identifier__</span><span class="p">]</span></div>
    <span class="n">Index</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">FileBacked</span><span class="o">.</span><span class="n">Index</span><span class="o">.</span><span class="n">__doc__</span>

<div class="viewcode-block" id="XMLFileBacked.add_monitor"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLFileBacked.add_monitor">[docs]</a>    <span class="k">def</span> <span class="nf">add_monitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fpath</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Add a FAM monitor to a file that has been XIncluded.  This</span>
<span class="sd">        is only done if the constructor got both a ``fam`` object and</span>
<span class="sd">        ``should_monitor`` set to True.</span>

<span class="sd">        :param fpath: The full path to the file to monitor</span>
<span class="sd">        :type fpath: string</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">extras</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fam</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">should_monitor</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
</div>
    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> at </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="StructFile"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.StructFile">[docs]</a><span class="k">class</span> <span class="nc">StructFile</span><span class="p">(</span><span class="n">XMLFileBacked</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; StructFiles are XML files that contain a set of structure file</span>
<span class="sd">    formatting logic for handling ``&lt;Group&gt;`` and ``&lt;Client&gt;``</span>
<span class="sd">    tags. &quot;&quot;&quot;</span>

    <span class="c">#: If ``__identifier__`` is not None, then it must be the name of</span>
    <span class="c">#: an XML attribute that will be required on the top-level tag of</span>
    <span class="c">#: the file being cached</span>
    <span class="n">__identifier__</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="k">def</span> <span class="nf">_include_element</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; determine if an XML element matches the metadata &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">_Comment</span><span class="p">):</span>  <span class="c"># pylint: disable=W0212</span>
            <span class="k">return</span> <span class="bp">False</span>
        <span class="n">negate</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;negate&#39;</span><span class="p">,</span> <span class="s">&#39;false&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s">&#39;true&#39;</span>
        <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">&#39;Group&#39;</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">negate</span> <span class="o">==</span> <span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">metadata</span><span class="o">.</span><span class="n">groups</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">&#39;Client&#39;</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">negate</span> <span class="o">==</span> <span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span> <span class="o">!=</span> <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">True</span>

    <span class="k">def</span> <span class="nf">_match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; recursive helper for Match() &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_include_element</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">&#39;Group&#39;</span> <span class="ow">or</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">&#39;Client&#39;</span><span class="p">:</span>
                <span class="n">rv</span> <span class="o">=</span> <span class="p">[]</span>
                <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_include_element</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
                    <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span>
                        <span class="n">rv</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">))</span>
                <span class="k">return</span> <span class="n">rv</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">rv</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
                <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">rv</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span>
                    <span class="n">rv</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>
                <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span>
                    <span class="n">rv</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">))</span>
                <span class="k">return</span> <span class="p">[</span><span class="n">rv</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">[]</span>

<div class="viewcode-block" id="StructFile.Match"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.StructFile.Match">[docs]</a>    <span class="k">def</span> <span class="nf">Match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return matching fragments of the data in this file.  A tag</span>
<span class="sd">        is considered to match if all ``&lt;Group&gt;`` and ``&lt;Client&gt;``</span>
<span class="sd">        tags that are its ancestors match the metadata given.  Since</span>
<span class="sd">        tags are included unmodified, it&#39;s possible for a tag to</span>
<span class="sd">        itself match while containing non-matching children.</span>
<span class="sd">        Consequently, only the tags contained in the list returned by</span>
<span class="sd">        Match() (and *not* their descendents) should be considered to</span>
<span class="sd">        match the metadata.</span>

<span class="sd">        :param metadata: Client metadata to match against.</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: list of lxml.etree._Element objects &quot;&quot;&quot;</span>
        <span class="n">rv</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
            <span class="n">rv</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">))</span>
        <span class="k">return</span> <span class="n">rv</span>
</div>
    <span class="k">def</span> <span class="nf">_xml_match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; recursive helper for XMLMatch &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_include_element</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">&#39;Group&#39;</span> <span class="ow">or</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="o">==</span> <span class="s">&#39;Client&#39;</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span>
                    <span class="n">item</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>
                    <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">child</span><span class="p">)</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">_xml_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span>
                <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span><span class="p">:</span>
                    <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
                        <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span>
                    <span class="k">else</span><span class="p">:</span>
                        <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">text</span> <span class="o">+=</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span>
                <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">item</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">_xml_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">item</span><span class="o">.</span><span class="n">getparent</span><span class="p">()</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>

<div class="viewcode-block" id="StructFile.XMLMatch"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.StructFile.XMLMatch">[docs]</a>    <span class="k">def</span> <span class="nf">XMLMatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return a rebuilt XML document that only contains the</span>
<span class="sd">        matching portions of the original file.  A tag is considered</span>
<span class="sd">        to match if all ``&lt;Group&gt;`` and ``&lt;Client&gt;`` tags that are its</span>
<span class="sd">        ancestors match the metadata given.  Unlike :func:`Match`, the</span>
<span class="sd">        document returned by XMLMatch will only contain matching data.</span>
<span class="sd">        All ``&lt;Group&gt;`` and ``&lt;Client&gt;`` tags will have been stripped</span>
<span class="sd">        out.</span>

<span class="sd">        :param metadata: Client metadata to match against.</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: lxml.etree._Element &quot;&quot;&quot;</span>
        <span class="n">rv</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">xdata</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">rv</span><span class="o">.</span><span class="n">iterchildren</span><span class="p">():</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_xml_match</span><span class="p">(</span><span class="n">child</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">rv</span>

</div></div>
<div class="viewcode-block" id="INode"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.INode">[docs]</a><span class="k">class</span> <span class="nc">INode</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; INodes provide lists of things available at a particular group</span>
<span class="sd">    intersection.  INodes are deprecated; new plugins should use</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.StructFile` instead. &quot;&quot;&quot;</span>

    <span class="n">raw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
        <span class="n">Client</span><span class="o">=</span><span class="s">&quot;lambda m, e:&#39;</span><span class="si">%(name)s</span><span class="s">&#39; == m.hostname and predicate(m, e)&quot;</span><span class="p">,</span>
        <span class="n">Group</span><span class="o">=</span><span class="s">&quot;lambda m, e:&#39;</span><span class="si">%(name)s</span><span class="s">&#39; in m.groups and predicate(m, e)&quot;</span><span class="p">)</span>
    <span class="n">nraw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
        <span class="n">Client</span><span class="o">=</span><span class="s">&quot;lambda m, e:&#39;</span><span class="si">%(name)s</span><span class="s">&#39; != m.hostname and predicate(m, e)&quot;</span><span class="p">,</span>
        <span class="n">Group</span><span class="o">=</span><span class="s">&quot;lambda m, e:&#39;</span><span class="si">%(name)s</span><span class="s">&#39; not in m.groups and predicate(m, e)&quot;</span><span class="p">)</span>
    <span class="n">containers</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;Group&#39;</span><span class="p">,</span> <span class="s">&#39;Client&#39;</span><span class="p">]</span>
    <span class="n">ignore</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">idict</span><span class="p">,</span> <span class="n">parent</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="n">data</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">contents</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">if</span> <span class="n">parent</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">predicate</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">m</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span> <span class="bp">True</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">predicate</span> <span class="o">=</span> <span class="n">parent</span><span class="o">.</span><span class="n">predicate</span>
            <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;negate&#39;</span><span class="p">,</span> <span class="s">&#39;false&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s">&#39;true&#39;</span><span class="p">:</span>
                <span class="n">psrc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nraw</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">psrc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">raw</span>
            <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">psrc</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">predicate</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">psrc</span><span class="p">[</span><span class="n">data</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">%</span>
                                      <span class="p">{</span><span class="s">&#39;name&#39;</span><span class="p">:</span> <span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)},</span>
                                      <span class="p">{</span><span class="s">&#39;predicate&#39;</span><span class="p">:</span> <span class="n">predicate</span><span class="p">})</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="s">&quot;Unknown tag: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">data</span><span class="o">.</span><span class="n">tag</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">children</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_load_children</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">idict</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_load_children</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">idict</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; load children &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">getchildren</span><span class="p">():</span>
            <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span><span class="p">:</span>
                <span class="k">continue</span>
            <span class="k">elif</span> <span class="n">item</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">containers</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">children</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">idict</span><span class="p">,</span> <span class="bp">self</span><span class="p">))</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)]</span> <span class="o">=</span> \
                        <span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">attrib</span><span class="p">)</span>
                <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">=</span> \
                        <span class="p">{</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">):</span> <span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">attrib</span><span class="p">)}</span>
                <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">text</span><span class="p">:</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)][</span><span class="s">&#39;__text__&#39;</span><span class="p">]</span> <span class="o">=</span> \
                        <span class="n">item</span><span class="o">.</span><span class="n">text</span>
                <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">getchildren</span><span class="p">():</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)][</span><span class="s">&#39;__children__&#39;</span><span class="p">]</span> \
                        <span class="o">=</span> <span class="n">item</span><span class="o">.</span><span class="n">getchildren</span><span class="p">()</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">idict</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">))</span>
                <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
                    <span class="n">idict</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)]</span>

<div class="viewcode-block" id="INode.Match"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.INode.Match">[docs]</a>    <span class="k">def</span> <span class="nf">Match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">entry</span><span class="o">=</span><span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">Element</span><span class="p">(</span><span class="s">&quot;None&quot;</span><span class="p">)):</span>
        <span class="sd">&quot;&quot;&quot;Return a dictionary of package mappings.&quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">predicate</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">entry</span><span class="p">):</span>
            <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">:</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">key</span><span class="p">])</span>
                <span class="k">except</span><span class="p">:</span>  <span class="c"># pylint: disable=W0702</span>
                    <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
                    <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">contents</span><span class="p">[</span><span class="n">key</span><span class="p">])</span>
            <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">children</span><span class="p">:</span>
                <span class="n">child</span><span class="o">.</span><span class="n">Match</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">entry</span><span class="o">=</span><span class="n">entry</span><span class="p">)</span>

</div></div>
<div class="viewcode-block" id="InfoNode"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.InfoNode">[docs]</a><span class="k">class</span> <span class="nc">InfoNode</span> <span class="p">(</span><span class="n">INode</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; :class:`Bcfg2.Server.Plugin.helpers.INode` implementation that</span>
<span class="sd">    includes ``&lt;Path&gt;`` tags, suitable for use with :file:`info.xml`</span>
<span class="sd">    files.&quot;&quot;&quot;</span>

    <span class="n">raw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
        <span class="n">Client</span><span class="o">=</span><span class="s">&quot;lambda m, e: &#39;</span><span class="si">%(name)s</span><span class="s">&#39; == m.hostname and predicate(m, e)&quot;</span><span class="p">,</span>
        <span class="n">Group</span><span class="o">=</span><span class="s">&quot;lambda m, e: &#39;</span><span class="si">%(name)s</span><span class="s">&#39; in m.groups and predicate(m, e)&quot;</span><span class="p">,</span>
        <span class="n">Path</span><span class="o">=</span><span class="s">&quot;lambda m, e: (&#39;</span><span class="si">%(name)s</span><span class="s">&#39; == e.get(&#39;name&#39;) or &quot;</span> <span class="o">+</span>
                           <span class="s">&quot;&#39;</span><span class="si">%(name)s</span><span class="s">&#39; == e.get(&#39;realname&#39;)) and &quot;</span> <span class="o">+</span>
                          <span class="s">&quot;predicate(m, e)&quot;</span><span class="p">)</span>
    <span class="n">nraw</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span>
        <span class="n">Client</span><span class="o">=</span><span class="s">&quot;lambda m, e: &#39;</span><span class="si">%(name)s</span><span class="s">&#39; != m.hostname and predicate(m, e)&quot;</span><span class="p">,</span>
        <span class="n">Group</span><span class="o">=</span><span class="s">&quot;lambda m, e: &#39;</span><span class="si">%(name)s</span><span class="s">&#39; not in m.groups and predicate(m, e)&quot;</span><span class="p">,</span>
        <span class="n">Path</span><span class="o">=</span><span class="s">&quot;lambda m, e: &#39;</span><span class="si">%(name)s</span><span class="s">&#39; != e.get(&#39;name&#39;) and &quot;</span> <span class="o">+</span>
                          <span class="s">&quot;&#39;</span><span class="si">%(name)s</span><span class="s">&#39; != e.get(&#39;realname&#39;) and &quot;</span> <span class="o">+</span>
                          <span class="s">&quot;predicate(m, e)&quot;</span><span class="p">)</span>
    <span class="n">containers</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;Group&#39;</span><span class="p">,</span> <span class="s">&#39;Client&#39;</span><span class="p">,</span> <span class="s">&#39;Path&#39;</span><span class="p">]</span>

</div>
<div class="viewcode-block" id="XMLSrc"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLSrc">[docs]</a><span class="k">class</span> <span class="nc">XMLSrc</span><span class="p">(</span><span class="n">XMLFileBacked</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; XMLSrc files contain a</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.INode` hierarchy that returns</span>
<span class="sd">    matching entries. XMLSrc objects are deprecated and</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.StructFile` should be</span>
<span class="sd">    preferred where possible.&quot;&quot;&quot;</span>
    <span class="n">__node__</span> <span class="o">=</span> <span class="n">INode</span>
    <span class="n">__cacheobj__</span> <span class="o">=</span> <span class="nb">dict</span>
    <span class="n">__priority_required__</span> <span class="o">=</span> <span class="bp">True</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">should_monitor</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="n">XMLFileBacked</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="n">fam</span><span class="p">,</span> <span class="n">should_monitor</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">priority</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>

<div class="viewcode-block" id="XMLSrc.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLSrc.HandleEvent">[docs]</a>    <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Read file upon update.&quot;&quot;&quot;</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
        <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
            <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Failed to read file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
            <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">xdata</span> <span class="o">=</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XML</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">parser</span><span class="o">=</span><span class="n">Bcfg2</span><span class="o">.</span><span class="n">Server</span><span class="o">.</span><span class="n">XMLParser</span><span class="p">)</span>
        <span class="k">except</span> <span class="n">lxml</span><span class="o">.</span><span class="n">etree</span><span class="o">.</span><span class="n">XMLSyntaxError</span><span class="p">:</span>
            <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Failed to parse file </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
                                                   <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
            <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__node__</span><span class="p">(</span><span class="n">xdata</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">items</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">priority</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">xdata</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;priority&#39;</span><span class="p">))</span>
        <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">TypeError</span><span class="p">):</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">__priority_required__</span><span class="p">:</span>
                <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Got bogus priority </span><span class="si">%s</span><span class="s"> for file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> \
                    <span class="p">(</span><span class="n">xdata</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;priority&#39;</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
                <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>

        <span class="k">del</span> <span class="n">xdata</span><span class="p">,</span> <span class="n">data</span>
</div>
<div class="viewcode-block" id="XMLSrc.Cache"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLSrc.Cache">[docs]</a>    <span class="k">def</span> <span class="nf">Cache</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Build a package dict for a given host.&quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">metadata</span><span class="p">:</span>
            <span class="n">cache</span> <span class="o">=</span> <span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">__cacheobj__</span><span class="p">())</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Cache method called early for </span><span class="si">%s</span><span class="s">; &quot;</span>
                             <span class="s">&quot;forcing data load&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">()</span>
                <span class="k">return</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pnode</span><span class="o">.</span><span class="n">Match</span><span class="p">(</span><span class="n">metadata</span><span class="p">,</span> <span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="n">cache</span>
</div>
    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">items</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="InfoXML"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.InfoXML">[docs]</a><span class="k">class</span> <span class="nc">InfoXML</span><span class="p">(</span><span class="n">XMLSrc</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; InfoXML files contain a</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.InfoNode` hierarchy that</span>
<span class="sd">    returns matching entries, suitable for use with :file:`info.xml`</span>
<span class="sd">    files.&quot;&quot;&quot;</span>
    <span class="n">__node__</span> <span class="o">=</span> <span class="n">InfoNode</span>
    <span class="n">__priority_required__</span> <span class="o">=</span> <span class="bp">False</span>

</div>
<div class="viewcode-block" id="XMLDirectoryBacked"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.XMLDirectoryBacked">[docs]</a><span class="k">class</span> <span class="nc">XMLDirectoryBacked</span><span class="p">(</span><span class="n">DirectoryBacked</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; :class:`Bcfg2.Server.Plugin.helpers.DirectoryBacked` for XML files. &quot;&quot;&quot;</span>

    <span class="c">#: Only track and include files whose names (not paths) match this</span>
    <span class="c">#: compiled regex.</span>
    <span class="n">patterns</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;^.*\.xml$&#39;</span><span class="p">)</span>

    <span class="c">#: The type of child objects to create for files contained within</span>
    <span class="c">#: the directory that is tracked.  Default is</span>
    <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.XMLFileBacked`</span>
    <span class="n">__child__</span> <span class="o">=</span> <span class="n">XMLFileBacked</span>

</div>
<div class="viewcode-block" id="PrioDir"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir">[docs]</a><span class="k">class</span> <span class="nc">PrioDir</span><span class="p">(</span><span class="n">Plugin</span><span class="p">,</span> <span class="n">Generator</span><span class="p">,</span> <span class="n">XMLDirectoryBacked</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; PrioDir handles a directory of XML files where each file has a</span>
<span class="sd">    set priority.</span>

<span class="sd">    .. -----</span>
<span class="sd">    .. autoattribute:: __child__</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c">#: The type of child objects to create for files contained within</span>
    <span class="c">#: the directory that is tracked.  Default is</span>
    <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.XMLSrc`</span>
    <span class="n">__child__</span> <span class="o">=</span> <span class="n">XMLSrc</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">):</span>
        <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">)</span>
        <span class="n">Generator</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="n">XMLDirectoryBacked</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">fam</span><span class="p">)</span>
    <span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span>

<div class="viewcode-block" id="PrioDir.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir.HandleEvent">[docs]</a>    <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="n">XMLDirectoryBacked</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">()):</span>
            <span class="k">for</span> <span class="n">itype</span><span class="p">,</span> <span class="n">children</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">items</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
                <span class="k">for</span> <span class="n">child</span> <span class="ow">in</span> <span class="n">children</span><span class="p">:</span>
                    <span class="k">try</span><span class="p">:</span>
                        <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="n">itype</span><span class="p">][</span><span class="n">child</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">BindEntry</span>
                    <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
                        <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="n">itype</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">child</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">BindEntry</span><span class="p">}</span></div>
    <span class="n">HandleEvent</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">XMLDirectoryBacked</span><span class="o">.</span><span class="n">HandleEvent</span><span class="o">.</span><span class="n">__doc__</span>

    <span class="k">def</span> <span class="nf">_matches</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">rules</span><span class="p">):</span>  <span class="c"># pylint: disable=W0613</span>
        <span class="sd">&quot;&quot;&quot; Whether or not a given entry has a matching entry in this</span>
<span class="sd">        PrioDir.  By default this does strict matching (i.e., the</span>
<span class="sd">        entry name is in ``rules.keys()``), but this can be overridden</span>
<span class="sd">        to provide regex matching, etc.</span>

<span class="sd">        :param entry: The entry to find a match for</span>
<span class="sd">        :type entry: lxml.etree._Element</span>
<span class="sd">        :param metadata: The metadata to get attributes for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :rules: A dict of rules to look in for a matching rule</span>
<span class="sd">        :type rules: dict</span>
<span class="sd">        :returns: bool</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span> <span class="ow">in</span> <span class="n">rules</span>

<div class="viewcode-block" id="PrioDir.BindEntry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir.BindEntry">[docs]</a>    <span class="k">def</span> <span class="nf">BindEntry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Bind the attributes that apply to an entry to it.  The</span>
<span class="sd">        entry is modified in-place.</span>

<span class="sd">        :param entry: The entry to add attributes to.</span>
<span class="sd">        :type entry: lxml.etree._Element</span>
<span class="sd">        :param metadata: The metadata to get attributes for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">attrs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_attrs</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">attrs</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
            <span class="n">entry</span><span class="o">.</span><span class="n">attrib</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">val</span>
</div>
<div class="viewcode-block" id="PrioDir.get_attrs"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.PrioDir.get_attrs">[docs]</a>    <span class="k">def</span> <span class="nf">get_attrs</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Get a list of attributes to add to the entry during the</span>
<span class="sd">        bind.  This is a complex method, in that it both modifies the</span>
<span class="sd">        entry, and returns attributes that need to be added to the</span>
<span class="sd">        entry.  That seems sub-optimal, and should probably be changed</span>
<span class="sd">        at some point.  Namely:</span>

<span class="sd">        * The return value includes all XML attributes that need to be</span>
<span class="sd">          added to the entry, but it does not add them.</span>
<span class="sd">        * If text contents or child tags need to be added to the</span>
<span class="sd">          entry, they are added to the entry in place.</span>

<span class="sd">        :param entry: The entry to add attributes to.</span>
<span class="sd">        :type entry: lxml.etree._Element</span>
<span class="sd">        :param metadata: The metadata to get attributes for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: dict of &lt;attr name&gt;:&lt;attr value&gt;</span>
<span class="sd">        :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
            <span class="n">src</span><span class="o">.</span><span class="n">Cache</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span>

        <span class="n">matching</span> <span class="o">=</span> <span class="p">[</span><span class="n">src</span> <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
                    <span class="k">if</span> <span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">cache</span> <span class="ow">and</span>
                        <span class="n">entry</span><span class="o">.</span><span class="n">tag</span> <span class="ow">in</span> <span class="n">src</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">and</span>
                        <span class="bp">self</span><span class="o">.</span><span class="n">_matches</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span>
                                      <span class="n">src</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">]))]</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">matching</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="s">&quot;No matching source for entry when &quot;</span>
                                       <span class="s">&quot;retrieving attributes for </span><span class="si">%s</span><span class="s">(</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span>
                                       <span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">attrib</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)))</span>
        <span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">matching</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">prio</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">src</span><span class="o">.</span><span class="n">priority</span><span class="p">)</span> <span class="k">for</span> <span class="n">src</span> <span class="ow">in</span> <span class="n">matching</span><span class="p">]</span>
            <span class="k">if</span> <span class="n">prio</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">prio</span><span class="p">))</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Found conflicting sources with same priority for &quot;</span> <span class="o">+</span> \
                    <span class="s">&quot;</span><span class="si">%s</span><span class="s">:</span><span class="si">%s</span><span class="s"> for </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">,</span> <span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;name&quot;</span><span class="p">),</span>
                                      <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">([</span><span class="n">item</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">matching</span><span class="p">])</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Priority was </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="nb">max</span><span class="p">(</span><span class="n">prio</span><span class="p">))</span>
                <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
            <span class="n">index</span> <span class="o">=</span> <span class="n">prio</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">prio</span><span class="p">))</span>

        <span class="k">for</span> <span class="n">rname</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">matching</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">]</span><span class="o">.</span><span class="n">keys</span><span class="p">()):</span>
            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_matches</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="p">[</span><span class="n">rname</span><span class="p">]):</span>
                <span class="n">data</span> <span class="o">=</span> <span class="n">matching</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">rname</span><span class="p">]</span>
                <span class="k">break</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="c"># Fall back on __getitem__. Required if override used</span>
            <span class="n">data</span> <span class="o">=</span> <span class="n">matching</span><span class="p">[</span><span class="n">index</span><span class="p">]</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">tag</span><span class="p">][</span><span class="n">entry</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)]</span>
        <span class="k">if</span> <span class="s">&#39;__text__&#39;</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
            <span class="n">entry</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">&#39;__text__&#39;</span><span class="p">]</span>
        <span class="k">if</span> <span class="s">&#39;__children__&#39;</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">data</span><span class="p">[</span><span class="s">&#39;__children__&#39;</span><span class="p">]:</span>
                <span class="n">entry</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>

        <span class="k">return</span> <span class="nb">dict</span><span class="p">([(</span><span class="n">key</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">])</span>
                     <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
                     <span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;__&#39;</span><span class="p">)])</span>

</div></div>
<div class="viewcode-block" id="Specificity"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.Specificity">[docs]</a><span class="k">class</span> <span class="nc">Specificity</span><span class="p">(</span><span class="n">CmpMixin</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; Represent the specificity of an object; i.e., what client(s)</span>
<span class="sd">    it applies to.  It can be group- or client-specific, or apply to</span>
<span class="sd">    all clients.</span>

<span class="sd">    Specificity objects are sortable; objects that are less specific</span>
<span class="sd">    are considered less than objects that are more specific.  Objects</span>
<span class="sd">    that apply to all clients are the least specific; objects that</span>
<span class="sd">    apply to a single client are the most specific.  Objects that</span>
<span class="sd">    apply to groups are sorted by priority. &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">all</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">group</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>  <span class="c"># pylint: disable=W0622</span>
                 <span class="n">hostname</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">prio</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">delta</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param all: The object applies to all clients.</span>
<span class="sd">        :type all: bool</span>
<span class="sd">        :param group: The object applies only to the given group.</span>
<span class="sd">        :type group: string or False</span>
<span class="sd">        :param hostname: The object applies only to the named client.</span>
<span class="sd">        :type hostname: string or False</span>
<span class="sd">        :param prio: The object has the given priority relative to</span>
<span class="sd">                     other objects that also apply to the same group.</span>
<span class="sd">                     ``&lt;group&gt;`` must be specified with ``&lt;prio&gt;``.</span>
<span class="sd">        :type prio: int</span>
<span class="sd">        :param delta: The object is a delta (i.e., a .cat or .diff</span>
<span class="sd">                      file, not a full file).  Deltas are deprecated.</span>
<span class="sd">        :type delta: bool</span>

<span class="sd">        Exactly one of {all|group|hostname} should be given.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">CmpMixin</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">=</span> <span class="n">hostname</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">all</span> <span class="o">=</span> <span class="nb">all</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">group</span> <span class="o">=</span> <span class="n">group</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">prio</span> <span class="o">=</span> <span class="n">prio</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">delta</span> <span class="o">=</span> <span class="n">delta</span>

<div class="viewcode-block" id="Specificity.matches"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.Specificity.matches">[docs]</a>    <span class="k">def</span> <span class="nf">matches</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return True if the object described by this Specificity</span>
<span class="sd">        object applies to the given client.  That is, if this</span>
<span class="sd">        Specificity applies to all clients, or to a group the client</span>
<span class="sd">        is a member of, or to the client individually.</span>

<span class="sd">        :param metadata: The client metadata</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: bool</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">all</span> <span class="ow">or</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">==</span> <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span> <span class="ow">or</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">group</span> <span class="ow">in</span> <span class="n">metadata</span><span class="o">.</span><span class="n">groups</span><span class="p">)</span>
</div>
    <span class="k">def</span> <span class="nf">__cmp__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>  <span class="c"># pylint: disable=R0911</span>
        <span class="sd">&quot;&quot;&quot;Sort most to least specific.&quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">all</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">all</span><span class="p">:</span>
                <span class="k">return</span> <span class="mi">0</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="k">return</span> <span class="mi">1</span>
        <span class="k">elif</span> <span class="n">other</span><span class="o">.</span><span class="n">all</span><span class="p">:</span>
            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">group</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span>
                <span class="k">return</span> <span class="mi">1</span>
            <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">group</span> <span class="ow">and</span> <span class="n">other</span><span class="o">.</span><span class="n">prio</span> <span class="o">&gt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span><span class="p">:</span>
                <span class="k">return</span> <span class="mi">1</span>
            <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">group</span> <span class="ow">and</span> <span class="n">other</span><span class="o">.</span><span class="n">prio</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span><span class="p">:</span>
                <span class="k">return</span> <span class="mi">0</span>
        <span class="k">elif</span> <span class="n">other</span><span class="o">.</span><span class="n">group</span><span class="p">:</span>
            <span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="ow">and</span> <span class="n">other</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span>
            <span class="k">return</span> <span class="mi">0</span>
        <span class="k">return</span> <span class="o">-</span><span class="mi">1</span>

    <span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">rv</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="s">&#39;: &#39;</span><span class="p">]</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">all</span><span class="p">:</span>
            <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;all&quot;</span><span class="p">)</span>
        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">group</span><span class="p">:</span>
            <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;Group </span><span class="si">%s</span><span class="s">, priority </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">group</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">prio</span><span class="p">))</span>
        <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span><span class="p">:</span>
            <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;Host </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="p">:</span>
            <span class="n">rv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;, delta=</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="p">)</span>
        <span class="k">return</span> <span class="s">&quot;&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span>

</div>
<div class="viewcode-block" id="SpecificData"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.SpecificData">[docs]</a><span class="k">class</span> <span class="nc">SpecificData</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; A file that is specific to certain clients, groups, or all</span>
<span class="sd">    clients. &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">specific</span><span class="p">,</span> <span class="n">encoding</span><span class="p">):</span>  <span class="c"># pylint: disable=W0613</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param name: The full path to the file</span>
<span class="sd">        :type name: string</span>
<span class="sd">        :param specific: A</span>
<span class="sd">                         :class:`Bcfg2.Server.Plugin.helpers.Specificity`</span>
<span class="sd">                         object describing what clients this file</span>
<span class="sd">                         applies to.</span>
<span class="sd">        :type specific: Bcfg2.Server.Plugin.helpers.Specificity</span>
<span class="sd">        :param encoding: The encoding to use for data in this file</span>
<span class="sd">        :type encoding: string</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">specific</span> <span class="o">=</span> <span class="n">specific</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">None</span>

<div class="viewcode-block" id="SpecificData.handle_event"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.SpecificData.handle_event">[docs]</a>    <span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Handle a FAM event.  Note that the SpecificData object</span>
<span class="sd">        itself has no FAM, so this must be produced by a parent object</span>
<span class="sd">        (e.g., :class:`Bcfg2.Server.Plugin.helpers.EntrySet`).</span>

<span class="sd">        :param event: The event that applies to this file</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        :raises: :exc:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span> <span class="o">==</span> <span class="s">&#39;deleted&#39;</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
        <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s">&#39;rb&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
        <span class="k">except</span><span class="p">:</span>  <span class="c"># pylint: disable=W0201</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Failed to read file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>

</div></div>
<div class="viewcode-block" id="EntrySet"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet">[docs]</a><span class="k">class</span> <span class="nc">EntrySet</span><span class="p">(</span><span class="n">Debuggable</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; EntrySets deal with a collection of host- and group-specific</span>
<span class="sd">    files (e.g., :class:`Bcfg2.Server.Plugin.helpers.SpecificData`</span>
<span class="sd">    objects) in a single directory. EntrySets are usually used as part</span>
<span class="sd">    of :class:`Bcfg2.Server.Plugin.helpers.GroupSpool` objects.&quot;&quot;&quot;</span>

    <span class="c">#: Preemptively ignore files whose names (not paths) match this</span>
    <span class="c">#: compiled regex.  ``ignore`` cannot be set to ``None``.  If a</span>
    <span class="c">#: file is encountered that does not match the ``basename``</span>
    <span class="c">#: argument passed to the constructor or ``ignore``, then a</span>
    <span class="c">#: warning will be produced.</span>
    <span class="n">ignore</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&quot;^(\.#.*|.*~|</span><span class="se">\\</span><span class="s">..*</span><span class="se">\\</span><span class="s">.(sw[px])|.*</span><span class="se">\\</span><span class="s">.genshi_include)$&quot;</span><span class="p">)</span>

    <span class="c"># The ``basename`` argument passed to the constructor will be</span>
    <span class="c">#: processed as a string that contains a regular expression (i.e.,</span>
    <span class="c">#: *not* a compiled regex object) if ``basename_is_regex`` is True,</span>
    <span class="c">#: and all files that match the regex will be cincluded in the</span>
    <span class="c">#: EntrySet.  If ``basename_is_regex`` is False, then it will be</span>
    <span class="c">#: considered a plain string and filenames must match exactly.</span>
    <span class="n">basename_is_regex</span> <span class="o">=</span> <span class="bp">False</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">basename</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">entry_type</span><span class="p">,</span> <span class="n">encoding</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">        :param basename: The filename or regular expression that files</span>
<span class="sd">                         in this EntrySet must match.  See</span>
<span class="sd">                         :attr:`basename_is_regex` for more details.</span>
<span class="sd">        :type basename: string</span>
<span class="sd">        :param path: The full path to the directory containing files</span>
<span class="sd">                     for this EntrySet</span>
<span class="sd">        :type path: string</span>
<span class="sd">        :param entry_type: A callable that returns an object that</span>
<span class="sd">                           represents files in this EntrySet.  This</span>
<span class="sd">                           will usually be a class object, but it can</span>
<span class="sd">                           be an object factory or similar callable.</span>
<span class="sd">                           See below for the expected signature.</span>
<span class="sd">        :type entry_type: callable</span>
<span class="sd">        :param encoding: The encoding of all files in this entry set.</span>
<span class="sd">        :type encoding: string</span>

<span class="sd">        The ``entry_type`` callable must have the following signature::</span>

<span class="sd">            entry_type(filepath, specificity, encoding)</span>

<span class="sd">        Where the parameters are:</span>

<span class="sd">        :param filepath: Full path to file</span>
<span class="sd">        :type filepath: string</span>
<span class="sd">        :param specific: A</span>
<span class="sd">                         :class:`Bcfg2.Server.Plugin.helpers.Specificity`</span>
<span class="sd">                         object describing what clients this file</span>
<span class="sd">                         applies to.</span>
<span class="sd">        :type specific: Bcfg2.Server.Plugin.helpers.Specificity</span>
<span class="sd">        :param encoding: The encoding to use for data in this file</span>
<span class="sd">        :type encoding: string</span>

<span class="sd">        Additionally, the object returned by ``entry_type`` must have</span>
<span class="sd">        a ``specific`` attribute that is sortable (e.g., a</span>
<span class="sd">        :class:`Bcfg2.Server.Plugin.helpers.Specificity` object).</span>

<span class="sd">        See :class:`Bcfg2.Server.Plugin.helpers.SpecificData` for an</span>
<span class="sd">        example of a class that can be used as an ``entry_type``.</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">Debuggable</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">basename</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="n">path</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span> <span class="o">=</span> <span class="n">entry_type</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">encoding</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">basename_is_regex</span><span class="p">:</span>
            <span class="n">base_pat</span> <span class="o">=</span> <span class="n">basename</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">base_pat</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">basename</span><span class="p">)</span>
        <span class="n">pattern</span> <span class="o">=</span> <span class="s">&#39;(.*/)?</span><span class="si">%s</span><span class="s">(\.((H_(?P&lt;hostname&gt;\S+))|&#39;</span> <span class="o">%</span> <span class="n">base_pat</span>
        <span class="n">pattern</span> <span class="o">+=</span> <span class="s">&#39;(G(?P&lt;prio&gt;\d+)_(?P&lt;group&gt;\S+))))?$&#39;</span>

        <span class="c">#: ``specific`` is a regular expression that is used to</span>
        <span class="c">#: determine the specificity of a file in this entry set.  It</span>
        <span class="c">#: must have three named groups: ``hostname``, ``prio`` (the</span>
        <span class="c">#: priority of a group-specific file), and ``group``.  The base</span>
        <span class="c">#: regex is constructed from the ``basename`` argument. It can</span>
        <span class="c">#: be overridden on a per-entry basis in :func:`entry_init`.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">specific</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span>

<div class="viewcode-block" id="EntrySet.get_matching"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.get_matching">[docs]</a>    <span class="k">def</span> <span class="nf">get_matching</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Get a list of all entries that apply to the given client.</span>
<span class="sd">        This gets all matching entries; for example, there could be an</span>
<span class="sd">        entry that applies to all clients, multiple group-specific</span>
<span class="sd">        entries, and a client-specific entry, all of which would be</span>
<span class="sd">        returned by get_matching().  You can use :func:`best_matching`</span>
<span class="sd">        to get the single best matching entry.</span>

<span class="sd">        :param metadata: The client metadata to get matching entries for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: list -- all matching ``entry_type`` objects (see the</span>
<span class="sd">                  constructor docs for more details)</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="p">[</span><span class="n">item</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
                <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">specific</span><span class="o">.</span><span class="n">matches</span><span class="p">(</span><span class="n">metadata</span><span class="p">)]</span>
</div>
<div class="viewcode-block" id="EntrySet.best_matching"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.best_matching">[docs]</a>    <span class="k">def</span> <span class="nf">best_matching</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">matching</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return the single most specific matching entry from the</span>
<span class="sd">        set of matching entries.  You can use :func:`get_matching` to</span>
<span class="sd">        get all matching entries.</span>

<span class="sd">        :param metadata: The client metadata to get matching entries for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :param matching: The set of matching entries to pick from.  If</span>
<span class="sd">                         this is not provided, :func:`get_matching`</span>
<span class="sd">                         will be called.</span>
<span class="sd">        :type matching: list of ``entry_type`` objects (see the constructor</span>
<span class="sd">                        docs for more details)</span>
<span class="sd">        :returns: a single object from the list of matching</span>
<span class="sd">                  ``entry_type`` objects</span>
<span class="sd">        :raises: :class:`Bcfg2.Server.Plugin.exceptions.PluginExecutionError`</span>
<span class="sd">                 if no matching entries are found</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">matching</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">matching</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_matching</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">matching</span><span class="p">:</span>
            <span class="n">matching</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="n">operator</span><span class="o">.</span><span class="n">attrgetter</span><span class="p">(</span><span class="s">&quot;specific&quot;</span><span class="p">))</span>
            <span class="k">return</span> <span class="n">matching</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">PluginExecutionError</span><span class="p">(</span><span class="s">&quot;No matching entries available for </span><span class="si">%s</span><span class="s"> &quot;</span>
                                       <span class="s">&quot;for </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span>
                                                   <span class="n">metadata</span><span class="o">.</span><span class="n">hostname</span><span class="p">))</span>
</div>
<div class="viewcode-block" id="EntrySet.handle_event"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.handle_event">[docs]</a>    <span class="k">def</span> <span class="nf">handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Dispatch a FAM event to the appropriate function or child</span>
<span class="sd">        ``entry_type`` object.  This will probably be handled by a</span>
<span class="sd">        call to :func:`update_metadata`, :func:`reset_metadata`,</span>
<span class="sd">        :func:`entry_init`, or to the ``entry_type``</span>
<span class="sd">        ``handle_event()`` function.</span>

<span class="sd">        :param event: An event that applies to a file handled by this</span>
<span class="sd">                      EntrySet</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">action</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span>

        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;info&#39;</span><span class="p">,</span> <span class="s">&#39;info.xml&#39;</span><span class="p">,</span> <span class="s">&#39;:info&#39;</span><span class="p">]:</span>
            <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;exists&#39;</span><span class="p">,</span> <span class="s">&#39;created&#39;</span><span class="p">,</span> <span class="s">&#39;changed&#39;</span><span class="p">]:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">update_metadata</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;deleted&#39;</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">reset_metadata</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
            <span class="k">return</span>

        <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;exists&#39;</span><span class="p">,</span> <span class="s">&#39;created&#39;</span><span class="p">]:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">entry_init</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                <span class="n">LOGGER</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">&quot;Got </span><span class="si">%s</span><span class="s"> event for unknown file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                               <span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">))</span>
                <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;changed&#39;</span><span class="p">:</span>
                    <span class="c"># received a bogus changed event; warn, but treat</span>
                    <span class="c"># it like a created event</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">entry_init</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
                <span class="k">return</span>
            <span class="k">if</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;changed&#39;</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;deleted&#39;</span><span class="p">:</span>
                <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span>
</div>
<div class="viewcode-block" id="EntrySet.entry_init"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.entry_init">[docs]</a>    <span class="k">def</span> <span class="nf">entry_init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">,</span> <span class="n">entry_type</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">specific</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Handle the creation of a file on the filesystem and the</span>
<span class="sd">        creation of an object in this EntrySet to track it.</span>

<span class="sd">        :param event: An event that applies to a file handled by this</span>
<span class="sd">                      EntrySet</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :param entry_type: Override the default ``entry_type`` for</span>
<span class="sd">                           this EntrySet object and create a different</span>
<span class="sd">                           object for this entry.  See the constructor</span>
<span class="sd">                           docs for more information on</span>
<span class="sd">                           ``entry_type``.</span>
<span class="sd">        :type entry_type: callable</span>
<span class="sd">        :param specific: Override the default :attr:`specific` regular</span>
<span class="sd">                         expression used by this object with a custom</span>
<span class="sd">                         regular expression that will be used to</span>
<span class="sd">                         determine the specificity of this entry.</span>
<span class="sd">        :type specific: compiled regular expression object</span>
<span class="sd">        :returns: None</span>
<span class="sd">        :raises: :class:`Bcfg2.Server.Plugin.exceptions.SpecificityError`</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">entry_type</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">entry_type</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span>

        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
            <span class="n">LOGGER</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Got duplicate add for </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">spec</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">specificity_from_filename</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span>
                                                      <span class="n">specific</span><span class="o">=</span><span class="n">specific</span><span class="p">)</span>
            <span class="k">except</span> <span class="n">SpecificityError</span><span class="p">:</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">ignore</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">):</span>
                    <span class="n">LOGGER</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Could not process filename </span><span class="si">%s</span><span class="s">; ignoring&quot;</span> <span class="o">%</span>
                                 <span class="n">fpath</span><span class="p">)</span>
                <span class="k">return</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry_type</span><span class="p">(</span><span class="n">fpath</span><span class="p">,</span> <span class="n">spec</span><span class="p">,</span>
                                                      <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="EntrySet.specificity_from_filename"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.specificity_from_filename">[docs]</a>    <span class="k">def</span> <span class="nf">specificity_from_filename</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fname</span><span class="p">,</span> <span class="n">specific</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Construct a</span>
<span class="sd">        :class:`Bcfg2.Server.Plugin.helpers.Specificity` object from a</span>
<span class="sd">        filename and regex. See :attr:`specific` for details on the</span>
<span class="sd">        regex.</span>

<span class="sd">        :param fname: The filename (not full path) of a file that is</span>
<span class="sd">                      in this EntrySet&#39;s directory.  It is not</span>
<span class="sd">                      necessary to determine first if the filename</span>
<span class="sd">                      matches this EntrySet&#39;s basename; that can be</span>
<span class="sd">                      done by catching</span>
<span class="sd">                      :class:`Bcfg2.Server.Plugin.exceptions.SpecificityError`</span>
<span class="sd">                      from this function.</span>
<span class="sd">        :type fname: string</span>
<span class="sd">        :param specific: Override the default :attr:`specific` regular</span>
<span class="sd">                         expression used by this object with a custom</span>
<span class="sd">                         regular expression that will be used to</span>
<span class="sd">                         determine the specificity of this entry.</span>
<span class="sd">        :type specific: compiled regular expression object</span>
<span class="sd">        :returns: Object representing the specificity of the file</span>
<span class="sd">        :rtype: :class:`Bcfg2.Server.Plugin.helpers.Specificity`</span>
<span class="sd">        :raises: :class:`Bcfg2.Server.Plugin.exceptions.SpecificityError`</span>
<span class="sd">                 if the regex does not match the filename</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">specific</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
            <span class="n">specific</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">specific</span>
        <span class="n">data</span> <span class="o">=</span> <span class="n">specific</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">SpecificityError</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span>
        <span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">&#39;hostname&#39;</span><span class="p">):</span>
            <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;hostname&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">&#39;hostname&#39;</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">&#39;group&#39;</span><span class="p">):</span>
            <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;group&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">&#39;group&#39;</span><span class="p">)</span>
            <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;prio&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">&#39;prio&#39;</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;all&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="k">if</span> <span class="s">&#39;delta&#39;</span> <span class="ow">in</span> <span class="n">data</span><span class="o">.</span><span class="n">groupdict</span><span class="p">():</span>
            <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;delta&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s">&#39;delta&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">Specificity</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="EntrySet.update_metadata"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.update_metadata">[docs]</a>    <span class="k">def</span> <span class="nf">update_metadata</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Process changes to or creation of info, :info, and</span>
<span class="sd">        info.xml files for the EntrySet.</span>

<span class="sd">        :param event: An event that applies to an info handled by this</span>
<span class="sd">                      EntrySet</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">==</span> <span class="s">&#39;info.xml&#39;</span><span class="p">:</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span> <span class="o">=</span> <span class="n">InfoXML</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span><span class="o">.</span><span class="n">HandleEvent</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;:info&#39;</span><span class="p">,</span> <span class="s">&#39;info&#39;</span><span class="p">]:</span>
            <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="n">fpath</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
                <span class="n">match</span> <span class="o">=</span> <span class="n">INFO_REGEX</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span>
                    <span class="n">LOGGER</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">&quot;Failed to match line in </span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">fpath</span><span class="p">,</span>
                                                                       <span class="n">line</span><span class="p">))</span>
                    <span class="k">continue</span>
                <span class="k">else</span><span class="p">:</span>
                    <span class="n">mgd</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groupdict</span><span class="p">()</span>
                    <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">mgd</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
                        <span class="k">if</span> <span class="n">value</span><span class="p">:</span>
                            <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
                    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">&#39;mode&#39;</span><span class="p">])</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
                        <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">&#39;mode&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;0</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">[</span><span class="s">&#39;mode&#39;</span><span class="p">]</span>
</div>
<div class="viewcode-block" id="EntrySet.reset_metadata"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.reset_metadata">[docs]</a>    <span class="k">def</span> <span class="nf">reset_metadata</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Reset metadata to defaults if info. :info, or info.xml are</span>
<span class="sd">        removed.</span>

<span class="sd">        :param event: An event that applies to an info handled by this</span>
<span class="sd">                      EntrySet</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="o">==</span> <span class="s">&#39;info.xml&#39;</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span> <span class="o">=</span> <span class="bp">None</span>
        <span class="k">elif</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;:info&#39;</span><span class="p">,</span> <span class="s">&#39;info&#39;</span><span class="p">]:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">metadata</span> <span class="o">=</span> <span class="n">DEFAULT_FILE_METADATA</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="EntrySet.bind_info_to_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.bind_info_to_entry">[docs]</a>    <span class="k">def</span> <span class="nf">bind_info_to_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Shortcut to call :func:`bind_info` with the base</span>
<span class="sd">        info/info.xml for this EntrySet.</span>

<span class="sd">        :param entry: The abstract entry to bind the info to. This</span>
<span class="sd">                      will be modified in place</span>
<span class="sd">        :type entry: lxml.etree._Element</span>
<span class="sd">        :param metadata: The client metadata to get info for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">bind_info</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">infoxml</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">infoxml</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">metadata</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="EntrySet.bind_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.EntrySet.bind_entry">[docs]</a>    <span class="k">def</span> <span class="nf">bind_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return the single best fully-bound entry from the set of</span>
<span class="sd">        available entries for the specified client.</span>

<span class="sd">        :param entry: The abstract entry to bind the info to</span>
<span class="sd">        :type entry: lxml.etree._Element</span>
<span class="sd">        :param metadata: The client metadata to get info for</span>
<span class="sd">        :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata</span>
<span class="sd">        :returns: lxml.etree._Element - the fully-bound entry</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">bind_info_to_entry</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">best_matching</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span><span class="o">.</span><span class="n">bind_entry</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">metadata</span><span class="p">)</span>

</div></div>
<div class="viewcode-block" id="GroupSpool"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool">[docs]</a><span class="k">class</span> <span class="nc">GroupSpool</span><span class="p">(</span><span class="n">Plugin</span><span class="p">,</span> <span class="n">Generator</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot; A GroupSpool is a collection of</span>
<span class="sd">    :class:`Bcfg2.Server.Plugin.helpers.EntrySet` objects -- i.e., a</span>
<span class="sd">    directory tree, each directory in which may contain files that are</span>
<span class="sd">    specific to groups/clients/etc. &quot;&quot;&quot;</span>

    <span class="c">#: ``filename_pattern`` is used as the ``basename`` argument to the</span>
    <span class="c">#: :attr:`es_cls` callable.  It may or may not be a regex,</span>
    <span class="c">#: depending on the :attr:`EntrySet.basename_is_regex` setting.</span>
    <span class="n">filename_pattern</span> <span class="o">=</span> <span class="s">&quot;&quot;</span>

    <span class="c">#: ``es_child_cls`` is a callable that will be used as the</span>
    <span class="c">#: ``entry_type`` argument to the :attr:`es_cls` callable.  It must</span>
    <span class="c">#: return objects that will represent individual files in the</span>
    <span class="c">#: GroupSpool.  For instance,</span>
    <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.SpecificData`.</span>
    <span class="n">es_child_cls</span> <span class="o">=</span> <span class="nb">object</span>

    <span class="c">#: ``es_cls`` is a callable that must return objects that will be</span>
    <span class="c">#: used to represent directories (i.e., sets of entries) within the</span>
    <span class="c">#: GroupSpool.  E.g.,</span>
    <span class="c">#: :class:`Bcfg2.Server.Plugin.helpers.EntrySet`.  The returned</span>
    <span class="c">#: object must implement a callable called ``bind_entry`` that has</span>
    <span class="c">#: the same signature as :attr:`EntrySet.bind_entry`.</span>
    <span class="n">es_cls</span> <span class="o">=</span> <span class="n">EntrySet</span>

    <span class="c">#: The entry type (i.e., the XML tag) handled by this GroupSpool</span>
    <span class="c">#: object.</span>
    <span class="n">entry_type</span> <span class="o">=</span> <span class="s">&#39;Path&#39;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">):</span>
        <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">core</span><span class="p">,</span> <span class="n">datastore</span><span class="p">)</span>
        <span class="n">Generator</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;/&#39;</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>

        <span class="c">#: See :class:`Bcfg2.Server.Plugins.interfaces.Generator` for</span>
        <span class="c">#: details on the Entries attribute.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="c">#: ``entries`` is a dict whose keys are :func:`event_id` return</span>
        <span class="c">#: values and whose values are :attr:`es_cls` objects. It ties</span>
        <span class="c">#: the directories handled by this GroupSpools to the</span>
        <span class="c">#: :attr:`es_cls` objects that handle each directory.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">handles</span> <span class="o">=</span> <span class="p">{}</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">AddDirectoryMonitor</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">core</span><span class="o">.</span><span class="n">setup</span><span class="p">[</span><span class="s">&#39;encoding&#39;</span><span class="p">]</span>
    <span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">__init__</span><span class="o">.</span><span class="n">__doc__</span>

<div class="viewcode-block" id="GroupSpool.add_entry"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.add_entry">[docs]</a>    <span class="k">def</span> <span class="nf">add_entry</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; This method handles two functions:</span>

<span class="sd">        * Adding a new entry of type :attr:`es_cls` to track a new</span>
<span class="sd">          directory.</span>
<span class="sd">        * Passing off an event on a file to the correct entry object</span>
<span class="sd">          to handle it.</span>

<span class="sd">        :param event: An event that applies to a file or directory</span>
<span class="sd">                      handled by this GroupSpool</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">epath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_path</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="n">ident</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_id</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">AddDirectoryMonitor</span><span class="p">(</span><span class="n">epath</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">):])</span>
        <span class="k">if</span> <span class="n">ident</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span>
            <span class="n">dirpath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">+</span> <span class="n">ident</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">es_cls</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">filename_pattern</span><span class="p">,</span>
                                              <span class="n">dirpath</span><span class="p">,</span>
                                              <span class="bp">self</span><span class="o">.</span><span class="n">es_child_cls</span><span class="p">,</span>
                                              <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">][</span><span class="n">ident</span><span class="p">]</span> <span class="o">=</span> \
                <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">bind_entry</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span>
            <span class="c"># do not pass through directory events</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="GroupSpool.event_path"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.event_path">[docs]</a>    <span class="k">def</span> <span class="nf">event_path</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return the full path to the filename affected by an event.</span>
<span class="sd">        :class:`Bcfg2.Server.FileMonitor.Event` objects just contain</span>
<span class="sd">        the filename, not the full path, so this function reconstructs</span>
<span class="sd">        the fill path based on the path to the :attr:`es_cls` object</span>
<span class="sd">        that handles the event.</span>

<span class="sd">        :param event: An event that applies to a file or directory</span>
<span class="sd">                      handled by this GroupSpool</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: string</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">,</span>
                            <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">),</span>
                            <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="GroupSpool.event_id"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.event_id">[docs]</a>    <span class="k">def</span> <span class="nf">event_id</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Return a string that can be used to relate the event</span>
<span class="sd">        unambiguously to a single :attr:`es_cls` object in the</span>
<span class="sd">        :attr:`entries` dict.  In practice, this means:</span>

<span class="sd">        * If the event is on a directory, ``event_id`` returns the</span>
<span class="sd">          full path to the directory.</span>
<span class="sd">        * If the event is on a file, ``event_id`` returns the full</span>
<span class="sd">          path to the directory the file is in.</span>

<span class="sd">        :param event: An event that applies to a file or directory</span>
<span class="sd">                      handled by this GroupSpool</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: string</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">epath</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_path</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">epath</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">),</span>
                                <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="GroupSpool.set_debug"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.set_debug">[docs]</a>    <span class="k">def</span> <span class="nf">set_debug</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
            <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="s">&quot;set_debug&quot;</span><span class="p">):</span>
                <span class="n">entry</span><span class="o">.</span><span class="n">set_debug</span><span class="p">(</span><span class="n">debug</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">set_debug</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">debug</span><span class="p">)</span></div>
    <span class="n">set_debug</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="n">Plugin</span><span class="o">.</span><span class="n">set_debug</span><span class="o">.</span><span class="n">__doc__</span>

<div class="viewcode-block" id="GroupSpool.HandleEvent"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.HandleEvent">[docs]</a>    <span class="k">def</span> <span class="nf">HandleEvent</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; HandleEvent is the event dispatcher for GroupSpool</span>
<span class="sd">        objects.  It receives all events and dispatches them the</span>
<span class="sd">        appropriate handling object (e.g., one of the :attr:`es_cls`</span>
<span class="sd">        objects in :attr:`entries`), function (e.g.,</span>
<span class="sd">        :func:`add_entry`), or behavior (e.g., deleting an entire</span>
<span class="sd">        entry set).</span>

<span class="sd">        :param event: An event that applies to a file or directory</span>
<span class="sd">                      handled by this GroupSpool</span>
<span class="sd">        :type event: Bcfg2.Server.FileMonitor.Event</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="n">action</span> <span class="o">=</span> <span class="n">event</span><span class="o">.</span><span class="n">code2str</span><span class="p">()</span>
        <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;/&#39;</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="n">ident</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">event_id</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">action</span> <span class="ow">in</span> <span class="p">[</span><span class="s">&#39;exists&#39;</span><span class="p">,</span> <span class="s">&#39;created&#39;</span><span class="p">]:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;changed&#39;</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">ident</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c"># got a changed event for a file we didn&#39;t know</span>
                <span class="c"># about. go ahead and process this as a &#39;created&#39;, but</span>
                <span class="c"># warn</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">&quot;Got changed event for unknown file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                                    <span class="n">ident</span><span class="p">)</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">add_entry</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
        <span class="k">elif</span> <span class="n">action</span> <span class="o">==</span> <span class="s">&#39;deleted&#39;</span><span class="p">:</span>
            <span class="n">fbase</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">event</span><span class="o">.</span><span class="n">requestID</span><span class="p">]</span> <span class="o">+</span> <span class="n">event</span><span class="o">.</span><span class="n">filename</span>
            <span class="k">if</span> <span class="n">fbase</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                <span class="c"># a directory was deleted</span>
                <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">fbase</span><span class="p">]</span>
                <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">Entries</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">entry_type</span><span class="p">][</span><span class="n">fbase</span><span class="p">]</span>
            <span class="k">elif</span> <span class="n">ident</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">[</span><span class="n">ident</span><span class="p">]</span><span class="o">.</span><span class="n">handle_event</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">ident</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">entries</span><span class="p">:</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s">&quot;Got deleted event for unknown file </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span>
                                    <span class="n">ident</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="GroupSpool.AddDirectoryMonitor"><a class="viewcode-back" href="../../../../development/plugins.html#Bcfg2.Server.Plugin.helpers.GroupSpool.AddDirectoryMonitor">[docs]</a>    <span class="k">def</span> <span class="nf">AddDirectoryMonitor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relative</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot; Add a FAM monitor to a new directory and set the</span>
<span class="sd">        appropriate event handler.</span>

<span class="sd">        :param relative: The path to the directory relative to the</span>
<span class="sd">                         base data directory of the GroupSpool object.</span>
<span class="sd">        :type relative: string</span>
<span class="sd">        :returns: None</span>
<span class="sd">        &quot;&quot;&quot;</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">relative</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">):</span>
            <span class="n">relative</span> <span class="o">+=</span> <span class="s">&#39;/&#39;</span>
        <span class="n">name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">+</span> <span class="n">relative</span>
        <span class="k">if</span> <span class="n">relative</span> <span class="ow">not</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="o">.</span><span class="n">values</span><span class="p">()):</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s">&quot;Failed to open directory </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span>
                <span class="k">return</span>
            <span class="n">reqid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">fam</span><span class="o">.</span><span class="n">AddMonitor</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">handles</span><span class="p">[</span><span class="n">reqid</span><span class="p">]</span> <span class="o">=</span> <span class="n">relative</span></div></div>
</pre></div>

          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="../../../../search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../../../../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="../../../../py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
	<li><a href="../../../../index.html">home</a> |&nbsp;</li>
	<!--<li><a href="../../../../search.html">search</a> |&nbsp;</li>-->
	<li><a href="../../../../help/index.html">help</a> |&nbsp;</li>
	<li><a href="../../../../contents.html">documentation </a> &raquo;</li>

          <li><a href="../../../index.html" >Module code</a> &raquo;</li>
          <li><a href="../Plugin.html" >Bcfg2.Server.Plugin</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
        &copy; Copyright 2009-2013, Narayan Desai.
      Last updated on Mar 20, 2013.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
    </div>
  </body>
</html>