GUI editor to tame mod_security rules

โŒˆโŒ‹ โŽ‡ branch:  modseccfg


Artifact [2805df632c]

Artifact 2805df632c6fb7f01c1f4619d8729856d9f37ffe26847bc58ede114f56a429f1:

  • File logfmt1/html/logopen.html — part of check-in [582b0b80fb] at 2021-01-01 20:59:39 on branch trunk — Typos fixed in logfmt1 docs (user: mario size: 25801)

<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  
  
  <link rel="shortcut icon" href="img/favicon.ico">
  <title>logopen() - logfmt1</title>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700|Roboto+Slab:400,700|Inconsolata:400,700" />

  <link rel="stylesheet" href="css/theme.css" />
  <link rel="stylesheet" href="css/theme_extra.css" />
  <link href="custom.css" rel="stylesheet" />
  <link href="syntax.css" rel="stylesheet" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "logopen()";
    var mkdocs_page_input_path = "logopen.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="js/jquery-2.1.1.min.js" defer></script>
  <script src="js/modernizr-2.8.3.min.js" defer></script> 
  
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href="." class="icon icon-home"> logfmt1</a>
        
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="index.html">Intro</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="log.fmt.html">.log.fmt</a>
                    </li>
                </ul>
                <ul class="current">
                    <li class="toctree-l1 current"><a class="reference internal current" href="logopen.html">logopen()</a>
    <ul class="current">
    </ul>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="regex.html">regex()</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="fmt.html">global .fmt db</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="update-logfmt.html">update-logfmt</a>
                    </li>
                </ul>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="logex.html">logex</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href=".">logfmt1</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href=".">Docs</a> &raquo;</li>
    
      
    
    <li>logopen()</li>
    <li class="wy-breadcrumbs-aside">
      
    </li>
  </ul>
  
  <hr/>
</div>
          <div role="main">
            <div class="section">
              
                <h3 id="logopen">logopen()</h3>
<div class="doc doc-object doc-class">
<h2 class="hidden-toc" href="#logfmt1.logopen" id="logfmt1.logopen" style="visibility: hidden; position: absolute;">
        </h2>
<div class="doc doc-contents first">
<p>Open log file and its associated .fmt specifier, to iterate over log lines
as dictionary.
File-style wrapper that yields parsed dictionaries instead of string lines.</p>
<div class="codehilite">
<pre><span></span><code><span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">logfmt1</span><span class="o">.</span><span class="n">logopen</span><span class="p">(</span><span class="s2">"/var/log/apache2/access.log"</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="n">True</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">row</span><span class="p">[</span><span class="s2">"remote_host"</span><span class="p">])</span>
</code></pre>
</div>
<p>Though you might want to keep a reference to the iterator to utilize
<code>.names()</code> and <code>.alias{}</code> manually.</p>
<div class="doc doc-children">
<div class="doc doc-object doc-method">
<h2 class="doc doc-heading" id="logfmt1.logopen.__init__">

        <code class="highlight language-python">
__init__<span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">logfn</span><span class="o">=</span><span class="s1">''</span><span class="p">,</span> <span class="n">fmt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">fail</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">duplicate</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>        </code>

  <span class="doc doc-properties">
      <small class="doc doc-property doc-property-special"><code>special</code></small>
  </span>

      </h2>
<div class="doc doc-contents ">
<p>Open log file and its associated .fmt specifier, to iterate over log lines
as dictionary.</p>
<p><strong>Parameters:</strong></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>logfn</code></td>
<td><code>str</code></td>
<td>
<p>Filename of .log file to open.  Which should be
accompanied by a .log.fmt declaration to allow unpacking
lines into dictionary.</p>
</td>
<td><code>''</code></td>
</tr>
<tr>
<td><code>fmt</code></td>
<td><code>dict</code></td>
<td>
<p>Alternatively to existing .log.fmt, a predefined class
might be given with <code>fmt={"class":"syslog"}</code>.  You might
even add a fixated <code>{"record":"%a %t %e %F"}</code> format string
this way.</p>
</td>
<td><code>None</code></td>
</tr>
<tr>
<td><code>debug</code></td>
<td><code>bool</code></td>
<td>
<p>In case of log extraction failures, prints (stdout)
some regex debugging.</p>
</td>
<td><code>False</code></td>
</tr>
<tr>
<td><code>fail</code></td>
<td><code>bool</code></td>
<td>
<p>In case of failure, just error out instead of continuing
the iterator.</p>
</td>
<td><code>False</code></td>
</tr>
<tr>
<td><code>duplicate</code></td>
<td><code>bool</code></td>
<td>
<p>Automatically expand aliases.  This effectively
copies row entries.</p>
</td>
<td><code>True</code></td>
</tr>
</tbody>
</table>
<p><strong>Attributes:</strong></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>f</code></td>
<td><code>file</code></td>
<td>
<p>Read handle onto log file</p>
</td>
</tr>
<tr>
<td><code>debug</code></td>
<td><code>bool</code></td>
<td>
<p>Debug flag</p>
</td>
</tr>
<tr>
<td><code>fail</code></td>
<td><code>bool</code></td>
<td>
<p>Exception flag</p>
</td>
</tr>
<tr>
<td><code>alias</code></td>
<td><code>dict</code></td>
<td>
<p>List of row aliases</p>
</td>
</tr>
<tr>
<td><code>container</code></td>
<td><code>dict</code></td>
<td>
<p>Rules for field expansion</p>
</td>
</tr>
<tr>
<td><code>rx</code></td>
<td><code>re.compile</code></td>
<td>
<p>Compiled regex</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Exceptions:</strong></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>StopIteration</code></td>
<td>
<p>For EOF or if the regex failed and fail=True</p>
</td>
</tr>
<tr>
<td><code>FileNotFound</code></td>
<td>
<p>If logfn doesn't exist etc.</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Returns:</strong></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>iterator</code></td>
<td>
<p>Traverses log file line-wise, but yields dictionaries.</p>
</td>
</tr>
</tbody>
</table>
<details class="quote">
          <summary>Source code in <code>logfmt1/logfmt1.py</code></summary>
          <div class="highlight">
<pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">logfn</span><span class="o">=</span><span class="s2">""</span><span class="p">,</span> <span class="n">fmt</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">fail</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">duplicate</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
    <span class="sd">"""</span>
<span class="sd">        Open log file and its associated .fmt specifier, to iterate over log lines</span>
<span class="sd">        as dictionary.</span>

<span class="sd">        Args:</span>
<span class="sd">            logfn (str):  Filename of .log file to open.  Which should be</span>
<span class="sd">                accompanied by a .log.fmt declaration to allow unpacking</span>
<span class="sd">                lines into dictionary.</span>
<span class="sd">            fmt (dict): Alternatively to existing .log.fmt, a predefined class</span>
<span class="sd">                might be given with `fmt={"class":"syslog"}`.  You might</span>
<span class="sd">                even add a fixated `{"record":"%a %t %e %F"}` format string</span>
<span class="sd">                this way.</span>
<span class="sd">            debug (bool): In case of log extraction failures, prints (stdout)</span>
<span class="sd">                some regex debugging.</span>
<span class="sd">            fail (bool): In case of failure, just error out instead of continuing</span>
<span class="sd">                the iterator.</span>
<span class="sd">            duplicate (bool): Automatically expand aliases.  This effectively</span>
<span class="sd">                copies row entries.</span>

<span class="sd">        Attributes:</span>
<span class="sd">            f (file): Read handle onto log file</span>
<span class="sd">            debug (bool): Debug flag</span>
<span class="sd">            fail (bool): Exception flag</span>
<span class="sd">            alias (dict): List of row aliases</span>
<span class="sd">            container (dict): Rules for field expansion</span>
<span class="sd">            rx (re.compile): Compiled regex</span>

<span class="sd">        Raises:</span>
<span class="sd">            StopIteration: For EOF or if the regex failed and fail=True</span>
<span class="sd">            FileNotFound: If logfn doesn't exist etc.</span>

<span class="sd">        Returns:</span>
<span class="sd">            iterator: Traverses log file line-wise, but yields dictionaries.</span>
<span class="sd">    """</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">debug</span> <span class="o">=</span> <span class="n">debug</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">fail</span> <span class="o">=</span> <span class="n">fail</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">duplicate</span> <span class="o">=</span> <span class="n">duplicate</span>
    <span class="c1"># try + nicer error....</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">logfn</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">"utf-8"</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">fmt</span><span class="p">:</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">fmt</span> <span class="o">=</span> <span class="n">json</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">logfn</span><span class="si">}</span><span class="s2">.fmt"</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">"utf-8"</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">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
            <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
            <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s2">"Use `update-logfmt` or `modseccfg`โ†’Fileโ†’Installโ†’update_logfmt.py to generate a *.log.fmt descriptor.</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
            <span class="n">fmt</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"class"</span><span class="p">:</span><span class="s2">"apache combined"</span><span class="p">}</span>
            <span class="c1">#fmt = rulesdb.find_by_glob(logfn)</span>
    <span class="n">fmt</span> <span class="o">=</span> <span class="n">rulesdb</span><span class="o">.</span><span class="n">merge</span><span class="p">(</span>
        <span class="n">fmt</span><span class="p">,</span>   <span class="c1"># this should be in regex/update</span>
        <span class="n">rulesdb</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">fmt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"class"</span><span class="p">))</span>
    <span class="p">)</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">alias</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"alias"</span><span class="p">,</span> <span class="p">{})</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">container</span> <span class="o">=</span> <span class="n">fmt</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"container"</span><span class="p">,</span> <span class="p">{})</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">rx</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">rx2re</span><span class="p">(</span><span class="n">regex</span><span class="p">(</span><span class="n">fmt</span><span class="p">)))</span>
</code></pre>
</div>
</details>
</div>
</div>
<div class="doc doc-object doc-method">
<h2 class="doc doc-heading" id="logfmt1.logopen.debug_rx">

        <code class="highlight language-python">
debug_rx<span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>        </code>


      </h2>
<div class="doc doc-contents ">
<p>ANSI output for debugging regex/fmt string. Automatically
invoked for failing lines if <code>debug=True</code> was given.</p>
<p><img alt="failed regex + log line" src="https://imgur.com/QBKzDsK.png" /></p>
<p><strong>Parameters:</strong></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>line</code></td>
<td><code>str</code></td>
<td>
<p>Current raw line (string) from log file.</p>
</td>
<td><em>required</em></td>
</tr>
</tbody>
</table>
<p>Output:
  Prints directly to stdout using ANSI escape sequences to
  highlight where regex failed on input line. It's not very
  exact anymore, but reasonably speedy.</p>
<details class="quote">
          <summary>Source code in <code>logfmt1/logfmt1.py</code></summary>
          <div class="highlight">
<pre><span></span><code><span class="k">def</span> <span class="nf">debug_rx</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">line</span><span class="p">:</span><span class="nb">str</span><span class="p">):</span>
    <span class="sd">"""</span>
<span class="sd">        ANSI output for debugging regex/fmt string. Automatically</span>
<span class="sd">        invoked for failing lines if `debug=True` was given.</span>

<span class="sd">        ![failed regex + log line](https://imgur.com/QBKzDsK.png)</span>

<span class="sd">        Args:</span>
<span class="sd">          line: Current raw line (string) from log file.</span>
<span class="sd">        Output:</span>
<span class="sd">          Prints directly to stdout using ANSI escape sequences to</span>
<span class="sd">          highlight where regex failed on input line. It's not very</span>
<span class="sd">          exact anymore, but reasonably speedy.</span>
<span class="sd">    """</span>

    <span class="n">rx</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rx</span><span class="o">.</span><span class="n">pattern</span>
    <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span>
    <span class="c1">#rx_cut = re.compile("[^)]*  \(\?P&lt;\w+&gt;  ( [^()]+ | \([^()]+\) )+  \)  [^()]* \Z", re.X)</span>
    <span class="c1"># iteratively strip (?...) capture groups</span>
    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">rx</span><span class="p">)</span> <span class="ow">and</span> <span class="n">rx</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">"(?P&lt;"</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="c1">#fail = rx_cut.search(rx)</span>
        <span class="c1">#if fail: fail = fail.group(0)</span>
        <span class="c1">#else: fail = "&lt;unknown-last-capture&gt;"; break</span>
        <span class="n">last</span> <span class="o">=</span> <span class="n">rx</span><span class="o">.</span><span class="n">rindex</span><span class="p">(</span><span class="s2">"(?P&lt;"</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">last</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">:</span>
            <span class="n">fail</span> <span class="o">=</span> <span class="s2">"&lt;unknown-last-capture&gt;"</span><span class="p">;</span> <span class="k">break</span>
        <span class="n">fail</span> <span class="o">=</span> <span class="n">rx</span><span class="p">[</span><span class="n">last</span><span class="p">:]</span>
        <span class="c1">#print(f"testfail: `{fail}`")</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">rx</span> <span class="o">=</span> <span class="n">rx</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">last</span><span class="p">]</span>
            <span class="n">rx</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s2">"[^)]*$"</span><span class="p">,</span> <span class="s2">""</span><span class="p">,</span> <span class="n">rx</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">rx</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
                <span class="k">break</span> <span class="c1"># works now, so `fail` was the culprit</span>
        <span class="k">except</span><span class="p">:</span>
            <span class="c1"># likely broke regex nesting, try removing next (?...)</span>
            <span class="k">pass</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">matched</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">rx</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
        <span class="n">matched</span> <span class="o">=</span> <span class="n">matched</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="n">matched</span> <span class="o">=</span> <span class="s2">""</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="se">\033</span><span class="s2">[36m"</span> <span class="o">+</span> <span class="s2">"failed regex section: </span><span class="se">\033</span><span class="s2">[1;33;41m"</span> <span class="o">+</span> <span class="n">fail</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\033</span><span class="s2">[40;0m"</span><span class="p">)</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"</span><span class="se">\033</span><span class="s2">[42m"</span> <span class="o">+</span> <span class="n">matched</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\033</span><span class="s2">[41m"</span> <span class="o">+</span> <span class="n">line</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">matched</span><span class="p">):]</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\033</span><span class="s2">[40;0m"</span><span class="p">)</span>
</code></pre>
</div>
</details>
</div>
</div>
<div class="doc doc-object doc-method">
<h2 class="doc doc-heading" id="logfmt1.logopen.names">

        <code class="highlight language-python">
names<span class="p">(</span><span class="bp">self</span><span class="p">)</span>        </code>


      </h2>
<div class="doc doc-contents ">
<p>Get column names from generated .fmt regex.</p>
<p><strong>Returns:</strong></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>list</code></td>
<td>
<p>dictionary keys of row (without aliases).</p>
</td>
</tr>
</tbody>
</table>
<details class="quote">
          <summary>Source code in <code>logfmt1/logfmt1.py</code></summary>
          <div class="highlight">
<pre><span></span><code><span class="k">def</span> <span class="nf">names</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">"""</span>
<span class="sd">        Get column names from generated .fmt regex.</span>

<span class="sd">        Returns:</span>
<span class="sd">          list: dictionary keys of row (without aliases).</span>
<span class="sd">    """</span>
    <span class="k">return</span> <span class="n">re</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="s2">"\(\?P?&lt;(\w+)&gt;"</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rx</span><span class="o">.</span><span class="n">pattern</span><span class="p">)</span>
</code></pre>
</div>
</details>
</div>
</div>
</div>
</div>
</div>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="regex.html" class="btn btn-neutral float-right" title="regex()">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="log.fmt.html" class="btn btn-neutral" title=".log.fmt"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
      
      
        <span><a href="log.fmt.html" style="color: #fcfcfc;">&laquo; Previous</a></span>
      
      
        <span style="margin-left: 15px"><a href="regex.html" style="color: #fcfcfc">Next &raquo;</a></span>
      
    </span>
</div>
    <script>var base_url = '.';</script>
    <script src="js/theme.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>