<!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>stem.descriptor.networkstatus — Stem 1.1.0 documentation</title> <link rel="stylesheet" href="../../../_static/haiku.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" /> <link rel="stylesheet" href="../../../_static/print.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '../../../', VERSION: '1.1.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/theme_extras.js"></script> <link rel="shortcut icon" href="../../../_static/favicon.png"/> <link rel="top" title="Stem 1.1.0 documentation" href="../../../index.html" /> <link rel="up" title="stem" href="../../stem.html" /> </head> <body> <div class="header"><img class="rightlogo" src="../../../_static/logo.png" alt="Logo"/><h1 class="heading"><a href="../../../index.html"> <span>Stem Docs</span></a></h1> <h2 class="heading"><span>stem.descriptor.networkstatus</span></h2> </div> <div class="topnav"> <p> <ul id="navbar"> <li><a href="../../../index.html">Home</a></li> <li><a href="../../../tutorials.html">Tutorials</a> <ul> <li><a href="../../../tutorials/the_little_relay_that_could.html">Hello World</a></li> <li><a href="../../../tutorials/to_russia_with_love.html">Client Usage</a></li> <li><a href="../../../tutorials/tortoise_and_the_hare.html">Event Listening</a></li> <li><a href="../../../tutorials/mirror_mirror_on_the_wall.html">Tor Descriptors</a></li> <li><a href="../../../tutorials/east_of_the_sun.html">Utilities</a></li> <li><a href="../../../tutorials/double_double_toil_and_trouble.html">Examples</a></li> </ul> </li> <li><a href="../../../api.html">API</a> <ul> <li><a href="../../../api/control.html">stem.control</a></li> <li><a href="../../../api/connection.html">stem.connection</a></li> <li><a href="../../../api/socket.html">stem.socket</a></li> <li><a href="../../../api/process.html">stem.process</a></li> <li><a href="../../../api/response.html">stem.response</a></li> <li><a href="../../../api/exit_policy.html">stem.exit_policy</a></li> <li><a href="../../../api/version.html">stem.version</a></li> <li><a href="../../../api.html#descriptors">Descriptors</a></li> <li><a href="../../../api.html#utilities">Utilities</a></li> </ul> </li> <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem">Development</a> <ul> <li><a href="../../../faq.html">FAQ</a></li> <li><a href="../../../change_log.html">Change Log</a></li> <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem/bugs">Bug Tracker</a></li> <li><a href="../../../download.html">Download</a></li> </ul> </li> </ul> </p> </div> <div class="content"> <h1>Source code for stem.descriptor.networkstatus</h1><div class="highlight"><pre> <span class="c"># Copyright 2012-2013, Damian Johnson and The Tor Project</span> <span class="c"># See LICENSE for licensing information</span> <span class="sd">"""</span> <span class="sd">Parsing for Tor network status documents. This supports both the v2 and v3</span> <span class="sd">dir-spec. Documents can be obtained from a few sources...</span> <span class="sd">* the 'cached-consensus' file in tor's data directory</span> <span class="sd">* tor metrics, at https://metrics.torproject.org/data.html</span> <span class="sd">* directory authorities and mirrors via their DirPort</span> <span class="sd">... and contain the following sections...</span> <span class="sd">* document header</span> <span class="sd">* list of :class:`stem.descriptor.networkstatus.DirectoryAuthority`</span> <span class="sd">* list of :class:`stem.descriptor.router_status_entry.RouterStatusEntry`</span> <span class="sd">* document footer</span> <span class="sd">Of these, the router status entry section can be quite large (on the order of</span> <span class="sd">hundreds of kilobytes). As such we provide a couple of methods for reading</span> <span class="sd">network status documents through :func:`~stem.descriptor.__init__.parse_file`.</span> <span class="sd">For more information see :func:`~stem.descriptor.__init__.DocumentHandler`...</span> <span class="sd">::</span> <span class="sd"> from stem.descriptor import parse_file, DocumentHandler</span> <span class="sd"> with open('.tor/cached-consensus', 'rb') as consensus_file:</span> <span class="sd"> # Processes the routers as we read them in. The routers refer to a document</span> <span class="sd"> # with an unset 'routers' attribute.</span> <span class="sd"> for router in parse_file(consensus_file, 'network-status-consensus-3 1.0', document_handler = DocumentHandler.ENTRIES):</span> <span class="sd"> print router.nickname</span> <span class="sd">**Module Overview:**</span> <span class="sd">::</span> <span class="sd"> NetworkStatusDocument - Network status document</span> <span class="sd"> |- NetworkStatusDocumentV2 - Version 2 network status document</span> <span class="sd"> |- NetworkStatusDocumentV3 - Version 3 network status document</span> <span class="sd"> +- BridgeNetworkStatusDocument - Version 3 network status document for bridges</span> <span class="sd"> KeyCertificate - Certificate used to authenticate an authority</span> <span class="sd"> DocumentSignature - Signature of a document by a directory authority</span> <span class="sd"> DirectoryAuthority - Directory authority as defined in a v3 network status document</span> <span class="sd">"""</span> <span class="kn">import</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="nn">io</span> <span class="kn">import</span> <span class="nn">stem.descriptor.router_status_entry</span> <span class="kn">import</span> <span class="nn">stem.util.str_tools</span> <span class="kn">import</span> <span class="nn">stem.util.tor_tools</span> <span class="kn">import</span> <span class="nn">stem.version</span> <span class="kn">from</span> <span class="nn">stem.descriptor</span> <span class="kn">import</span> <span class="p">(</span> <span class="n">PGP_BLOCK_END</span><span class="p">,</span> <span class="n">Descriptor</span><span class="p">,</span> <span class="n">DocumentHandler</span><span class="p">,</span> <span class="n">_get_descriptor_components</span><span class="p">,</span> <span class="n">_read_until_keywords</span><span class="p">,</span> <span class="p">)</span> <span class="c"># Version 2 network status document fields, tuples of the form...</span> <span class="c"># (keyword, is_mandatory)</span> <span class="n">NETWORK_STATUS_V2_FIELDS</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="s">"network-status-version"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"dir-source"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"fingerprint"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"contact"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"dir-signing-key"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"client-versions"</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"server-versions"</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"published"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"dir-options"</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"directory-signature"</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">)</span> <span class="c"># Network status document are either a 'vote' or 'consensus', with different</span> <span class="c"># mandatory fields for each. Both though require that their fields appear in a</span> <span class="c"># specific order. This is an ordered listing of the following...</span> <span class="c">#</span> <span class="c"># (field, in_votes, in_consensus, is_mandatory)</span> <span class="n">HEADER_STATUS_DOCUMENT_FIELDS</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="s">"network-status-version"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"vote-status"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"consensus-methods"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"consensus-method"</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"published"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"valid-after"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"fresh-until"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"valid-until"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"voting-delay"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"client-versions"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"server-versions"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"known-flags"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">"flag-thresholds"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"params"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">)</span> <span class="n">FOOTER_STATUS_DOCUMENT_FIELDS</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="s">"directory-footer"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"bandwidth-weights"</span><span class="p">,</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">"directory-signature"</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">)</span> <span class="n">HEADER_FIELDS</span> <span class="o">=</span> <span class="p">[</span><span class="n">attr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">HEADER_STATUS_DOCUMENT_FIELDS</span><span class="p">]</span> <span class="n">FOOTER_FIELDS</span> <span class="o">=</span> <span class="p">[</span><span class="n">attr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">FOOTER_STATUS_DOCUMENT_FIELDS</span><span class="p">]</span> <span class="n">AUTH_START</span> <span class="o">=</span> <span class="s">"dir-source"</span> <span class="n">ROUTERS_START</span> <span class="o">=</span> <span class="s">"r"</span> <span class="n">FOOTER_START</span> <span class="o">=</span> <span class="s">"directory-footer"</span> <span class="n">V2_FOOTER_START</span> <span class="o">=</span> <span class="s">"directory-signature"</span> <span class="n">DEFAULT_PARAMS</span> <span class="o">=</span> <span class="p">{</span> <span class="s">"bwweightscale"</span><span class="p">:</span> <span class="mi">10000</span><span class="p">,</span> <span class="s">"cbtdisabled"</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s">"cbtnummodes"</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="s">"cbtrecentcount"</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span> <span class="s">"cbtmaxtimeouts"</span><span class="p">:</span> <span class="mi">18</span><span class="p">,</span> <span class="s">"cbtmincircs"</span><span class="p">:</span> <span class="mi">100</span><span class="p">,</span> <span class="s">"cbtquantile"</span><span class="p">:</span> <span class="mi">80</span><span class="p">,</span> <span class="s">"cbtclosequantile"</span><span class="p">:</span> <span class="mi">95</span><span class="p">,</span> <span class="s">"cbttestfreq"</span><span class="p">:</span> <span class="mi">60</span><span class="p">,</span> <span class="s">"cbtmintimeout"</span><span class="p">:</span> <span class="mi">2000</span><span class="p">,</span> <span class="s">"cbtinitialtimeout"</span><span class="p">:</span> <span class="mi">60000</span><span class="p">,</span> <span class="s">"Support022HiddenServices"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="p">}</span> <span class="c"># KeyCertificate fields, tuple is of the form...</span> <span class="c"># (keyword, is_mandatory)</span> <span class="n">KEY_CERTIFICATE_PARAMS</span> <span class="o">=</span> <span class="p">(</span> <span class="p">(</span><span class="s">'dir-key-certificate-version'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-address'</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">'fingerprint'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-identity-key'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-key-published'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-key-expires'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-signing-key'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-key-crosscert'</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="p">(</span><span class="s">'dir-key-certification'</span><span class="p">,</span> <span class="bp">True</span><span class="p">),</span> <span class="p">)</span> <span class="k">def</span> <span class="nf">_parse_file</span><span class="p">(</span><span class="n">document_file</span><span class="p">,</span> <span class="n">document_type</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="n">is_microdescriptor</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span> <span class="n">document_handler</span> <span class="o">=</span> <span class="n">DocumentHandler</span><span class="o">.</span><span class="n">ENTRIES</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parses a network status and iterates over the RouterStatusEntry in it. The</span> <span class="sd"> document that these instances reference have an empty 'routers' attribute to</span> <span class="sd"> allow for limited memory usage.</span> <span class="sd"> :param file document_file: file with network status document content</span> <span class="sd"> :param class document_type: NetworkStatusDocument subclass</span> <span class="sd"> :param bool validate: checks the validity of the document's contents if</span> <span class="sd"> **True**, skips these checks otherwise</span> <span class="sd"> :param bool is_microdescriptor: **True** if this is for a microdescriptor</span> <span class="sd"> consensus, **False** otherwise</span> <span class="sd"> :param stem.descriptor.__init__.DocumentHandler document_handler: method in</span> <span class="sd"> which to parse :class:`~stem.descriptor.networkstatus.NetworkStatusDocument`</span> <span class="sd"> :param dict kwargs: additional arguments for the descriptor constructor</span> <span class="sd"> :returns: :class:`stem.descriptor.networkstatus.NetworkStatusDocument` object</span> <span class="sd"> :raises:</span> <span class="sd"> * **ValueError** if the document_version is unrecognized or the contents is</span> <span class="sd"> malformed and validate is **True**</span> <span class="sd"> * **IOError** if the file can't be read</span> <span class="sd"> """</span> <span class="c"># we can't properly default this since NetworkStatusDocumentV3 isn't defined yet</span> <span class="k">if</span> <span class="n">document_type</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">document_type</span> <span class="o">=</span> <span class="n">NetworkStatusDocumentV3</span> <span class="k">if</span> <span class="n">document_type</span> <span class="o">==</span> <span class="n">NetworkStatusDocumentV2</span><span class="p">:</span> <span class="n">document_type</span> <span class="o">=</span> <span class="n">NetworkStatusDocumentV2</span> <span class="n">router_type</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV2</span> <span class="k">elif</span> <span class="n">document_type</span> <span class="o">==</span> <span class="n">NetworkStatusDocumentV3</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">is_microdescriptor</span><span class="p">:</span> <span class="n">router_type</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV3</span> <span class="k">else</span><span class="p">:</span> <span class="n">router_type</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryMicroV3</span> <span class="k">elif</span> <span class="n">document_type</span> <span class="o">==</span> <span class="n">BridgeNetworkStatusDocument</span><span class="p">:</span> <span class="n">document_type</span> <span class="o">=</span> <span class="n">BridgeNetworkStatusDocument</span> <span class="n">router_type</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV2</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Document type </span><span class="si">%i</span><span class="s"> isn't recognized (only able to parse v2, v3, and bridge)"</span> <span class="o">%</span> <span class="n">document_type</span><span class="p">)</span> <span class="k">if</span> <span class="n">document_handler</span> <span class="o">==</span> <span class="n">DocumentHandler</span><span class="o">.</span><span class="n">DOCUMENT</span><span class="p">:</span> <span class="k">yield</span> <span class="n">document_type</span><span class="p">(</span><span class="n">document_file</span><span class="o">.</span><span class="n">read</span><span class="p">(),</span> <span class="n">validate</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="c"># getting the document without the routers section</span> <span class="n">header</span> <span class="o">=</span> <span class="n">_read_until_keywords</span><span class="p">((</span><span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">FOOTER_START</span><span class="p">,</span> <span class="n">V2_FOOTER_START</span><span class="p">),</span> <span class="n">document_file</span><span class="p">)</span> <span class="n">routers_start</span> <span class="o">=</span> <span class="n">document_file</span><span class="o">.</span><span class="n">tell</span><span class="p">()</span> <span class="n">_read_until_keywords</span><span class="p">((</span><span class="n">FOOTER_START</span><span class="p">,</span> <span class="n">V2_FOOTER_START</span><span class="p">),</span> <span class="n">document_file</span><span class="p">,</span> <span class="n">skip</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span> <span class="n">routers_end</span> <span class="o">=</span> <span class="n">document_file</span><span class="o">.</span><span class="n">tell</span><span class="p">()</span> <span class="n">footer</span> <span class="o">=</span> <span class="n">document_file</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span> <span class="n">document_content</span> <span class="o">=</span> <span class="nb">bytes</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">b</span><span class="s">""</span><span class="p">,</span> <span class="n">header</span> <span class="o">+</span> <span class="n">footer</span><span class="p">)</span> <span class="k">if</span> <span class="n">document_handler</span> <span class="o">==</span> <span class="n">DocumentHandler</span><span class="o">.</span><span class="n">BARE_DOCUMENT</span><span class="p">:</span> <span class="k">yield</span> <span class="n">document_type</span><span class="p">(</span><span class="n">document_content</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">elif</span> <span class="n">document_handler</span> <span class="o">==</span> <span class="n">DocumentHandler</span><span class="o">.</span><span class="n">ENTRIES</span><span class="p">:</span> <span class="n">desc_iterator</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span> <span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">entry_class</span> <span class="o">=</span> <span class="n">router_type</span><span class="p">,</span> <span class="n">entry_keyword</span> <span class="o">=</span> <span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">start_position</span> <span class="o">=</span> <span class="n">routers_start</span><span class="p">,</span> <span class="n">end_position</span> <span class="o">=</span> <span class="n">routers_end</span><span class="p">,</span> <span class="n">extra_args</span> <span class="o">=</span> <span class="p">(</span><span class="n">document_type</span><span class="p">(</span><span class="n">document_content</span><span class="p">,</span> <span class="n">validate</span><span class="p">),),</span> <span class="o">**</span><span class="n">kwargs</span> <span class="p">)</span> <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">desc_iterator</span><span class="p">:</span> <span class="k">yield</span> <span class="n">desc</span> <span class="k">else</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Unrecognized document_handler: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">document_handler</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_parse_file_key_certs</span><span class="p">(</span><span class="n">certificate_file</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parses a file containing one or more authority key certificates.</span> <span class="sd"> :param file certificate_file: file with key certificates</span> <span class="sd"> :param bool validate: checks the validity of the certificate's contents if</span> <span class="sd"> **True**, skips these checks otherwise</span> <span class="sd"> :returns: iterator for :class:`stem.descriptor.networkstatus.KeyCertificate`</span> <span class="sd"> instance in the file</span> <span class="sd"> :raises:</span> <span class="sd"> * **ValueError** if the key certificate content is invalid and validate is</span> <span class="sd"> **True**</span> <span class="sd"> * **IOError** if the file can't be read</span> <span class="sd"> """</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span> <span class="n">keycert_content</span> <span class="o">=</span> <span class="n">_read_until_keywords</span><span class="p">(</span><span class="s">"dir-key-certification"</span><span class="p">,</span> <span class="n">certificate_file</span><span class="p">)</span> <span class="c"># we've reached the 'router-signature', now include the pgp style block</span> <span class="n">block_end_prefix</span> <span class="o">=</span> <span class="n">PGP_BLOCK_END</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="n">keycert_content</span> <span class="o">+=</span> <span class="n">_read_until_keywords</span><span class="p">(</span><span class="n">block_end_prefix</span><span class="p">,</span> <span class="n">certificate_file</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> <span class="k">if</span> <span class="n">keycert_content</span><span class="p">:</span> <span class="k">yield</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">networkstatus</span><span class="o">.</span><span class="n">KeyCertificate</span><span class="p">(</span><span class="nb">bytes</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">b</span><span class="s">""</span><span class="p">,</span> <span class="n">keycert_content</span><span class="p">),</span> <span class="n">validate</span> <span class="o">=</span> <span class="n">validate</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">break</span> <span class="c"># done parsing file</span> <div class="viewcode-block" id="NetworkStatusDocument"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.NetworkStatusDocument">[docs]</a><span class="k">class</span> <span class="nc">NetworkStatusDocument</span><span class="p">(</span><span class="n">Descriptor</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Common parent for network status documents.</span> <span class="sd"> """</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">raw_content</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">NetworkStatusDocument</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">=</span> <span class="p">[]</span> <div class="viewcode-block" id="NetworkStatusDocument.get_unrecognized_lines"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.NetworkStatusDocument.get_unrecognized_lines">[docs]</a> <span class="k">def</span> <span class="nf">get_unrecognized_lines</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span><span class="p">)</span> </div></div> <div class="viewcode-block" id="NetworkStatusDocumentV2"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.NetworkStatusDocumentV2">[docs]</a><span class="k">class</span> <span class="nc">NetworkStatusDocumentV2</span><span class="p">(</span><span class="n">NetworkStatusDocument</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Version 2 network status document. These have been deprecated and are no</span> <span class="sd"> longer generated by Tor.</span> <span class="sd"> :var dict routers: fingerprints to :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV2`</span> <span class="sd"> contained in the document</span> <span class="sd"> :var int version: **\*** document version</span> <span class="sd"> :var str hostname: **\*** hostname of the authority</span> <span class="sd"> :var str address: **\*** authority's IP address</span> <span class="sd"> :var int dir_port: **\*** authority's DirPort</span> <span class="sd"> :var str fingerprint: **\*** authority's fingerprint</span> <span class="sd"> :var str contact: **\*** authority's contact information</span> <span class="sd"> :var str signing_key: **\*** authority's public signing key</span> <span class="sd"> :var list client_versions: list of recommended client tor version strings</span> <span class="sd"> :var list server_versions: list of recommended server tor version strings</span> <span class="sd"> :var datetime published: **\*** time when the document was published</span> <span class="sd"> :var list options: **\*** list of things that this authority decides</span> <span class="sd"> :var str signing_authority: **\*** name of the authority signing the document</span> <span class="sd"> :var str signature: **\*** authority's signature for the document</span> <span class="sd"> **\*** attribute is either required when we're parsed with validation or has</span> <span class="sd"> a default value, others are left as **None** if undefined</span> <span class="sd"> """</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">raw_content</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">NetworkStatusDocumentV2</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">dir_port</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">contact</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">signing_key</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_versions</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_versions</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">signing_authority</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">signatures</span> <span class="o">=</span> <span class="bp">None</span> <span class="c"># Splitting the document from the routers. Unlike v3 documents we're not</span> <span class="c"># bending over backwards on the validation by checking the field order or</span> <span class="c"># that header/footer attributes aren't in the wrong section. This is a</span> <span class="c"># deprecated descriptor type - patches welcome if you want those checks.</span> <span class="n">document_file</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="n">document_content</span> <span class="o">=</span> <span class="nb">bytes</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">b</span><span class="s">""</span><span class="p">,</span> <span class="n">_read_until_keywords</span><span class="p">((</span><span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">V2_FOOTER_START</span><span class="p">),</span> <span class="n">document_file</span><span class="p">))</span> <span class="n">router_iter</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span> <span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">entry_class</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV2</span><span class="p">,</span> <span class="n">entry_keyword</span> <span class="o">=</span> <span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">section_end_keywords</span> <span class="o">=</span> <span class="p">(</span><span class="n">V2_FOOTER_START</span><span class="p">,),</span> <span class="n">extra_args</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">,),</span> <span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">routers</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">desc</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">,</span> <span class="n">desc</span><span class="p">)</span> <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">router_iter</span><span class="p">)</span> <span class="n">document_content</span> <span class="o">+=</span> <span class="n">b</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span> <span class="o">+</span> <span class="n">document_file</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="n">document_content</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">document_content</span><span class="p">)</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">_get_descriptor_components</span><span class="p">(</span><span class="n">document_content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_check_constraints</span><span class="p">(</span><span class="n">entries</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parse</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entries</span><span class="p">,</span> <span class="n">validate</span><span class="p">):</span> <span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="n">value</span><span class="p">,</span> <span class="n">block_contents</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">line</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="c"># original line</span> <span class="k">if</span> <span class="n">block_contents</span><span class="p">:</span> <span class="n">line</span> <span class="o">+=</span> <span class="s">"</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">block_contents</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"network-status-version"</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">value</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document has a non-numeric version: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Expected a version 2 network status document, got version '</span><span class="si">%s</span><span class="s">' instead"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"dir-source"</span><span class="p">:</span> <span class="n">dir_source_comp</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">()</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">)</span> <span class="o"><</span> <span class="mi">3</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"The 'dir-source' line of a v2 network status document must have three values: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span> <span class="c"># https://trac.torproject.org/7055</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's hostname can't be blank: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's address isn't a valid IPv4 address: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">allow_zero</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's DirPort is invalid: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">continue</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">=</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">dir_source_comp</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">dir_port</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">if</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="s">'0'</span> <span class="k">else</span> <span class="nb">int</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"fingerprint"</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">value</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's fingerprint in a v2 network status document is malformed: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">=</span> <span class="n">value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"contact"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">contact</span> <span class="o">=</span> <span class="n">value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"dir-signing-key"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">signing_key</span> <span class="o">=</span> <span class="n">block_contents</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"client-versions"</span><span class="p">,</span> <span class="s">"server-versions"</span><span class="p">):</span> <span class="c"># v2 documents existed while there were tor versions using the 'old'</span> <span class="c"># style, hence we aren't attempting to parse them</span> <span class="k">for</span> <span class="n">version_str</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">","</span><span class="p">):</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'client-versions'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_versions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">version_str</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'server-versions'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_versions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">version_str</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"published"</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">published</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s">"%Y-%m-</span><span class="si">%d</span><span class="s"> %H:%M:%S"</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Version 2 network status document's 'published' time wasn't parsable: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"dir-options"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">()</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"directory-signature"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">signing_authority</span> <span class="o">=</span> <span class="n">value</span> <span class="bp">self</span><span class="o">.</span><span class="n">signature</span> <span class="o">=</span> <span class="n">block_contents</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="c"># 'client-versions' and 'server-versions' are only required if "Versions"</span> <span class="c"># is among the options</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="s">"Versions"</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="s">'client-versions'</span> <span class="ow">in</span> <span class="n">entries</span> <span class="ow">and</span> <span class="s">'server-versions'</span> <span class="ow">in</span> <span class="n">entries</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Version 2 network status documents must have a 'client-versions' and 'server-versions' when 'Versions' is listed among its dir-options:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span> <span class="k">def</span> <span class="nf">_check_constraints</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entries</span><span class="p">):</span> <span class="n">required_fields</span> <span class="o">=</span> <span class="p">[</span><span class="n">field</span> <span class="k">for</span> <span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">is_mandatory</span><span class="p">)</span> <span class="ow">in</span> <span class="n">NETWORK_STATUS_V2_FIELDS</span> <span class="k">if</span> <span class="n">is_mandatory</span><span class="p">]</span> <span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">required_fields</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">entries</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document (v2) must have a '</span><span class="si">%s</span><span class="s">' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)))</span> <span class="c"># all recognized fields can only appear once</span> <span class="n">single_fields</span> <span class="o">=</span> <span class="p">[</span><span class="n">field</span> <span class="k">for</span> <span class="p">(</span><span class="n">field</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span> <span class="ow">in</span> <span class="n">NETWORK_STATUS_V2_FIELDS</span><span class="p">]</span> <span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">single_fields</span><span class="p">:</span> <span class="k">if</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">entries</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">entries</span><span class="p">[</span><span class="n">keyword</span><span class="p">])</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document (v2) can only have a single '</span><span class="si">%s</span><span class="s">' line, got </span><span class="si">%i</span><span class="s">:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">entries</span><span class="p">[</span><span class="n">keyword</span><span class="p">]),</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)))</span> <span class="k">if</span> <span class="s">'network-status-version'</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="mi">0</span><span class="p">]:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document (v2) are expected to start with a 'network-status-version' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span> </div> <div class="viewcode-block" id="NetworkStatusDocumentV3"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.NetworkStatusDocumentV3">[docs]</a><span class="k">class</span> <span class="nc">NetworkStatusDocumentV3</span><span class="p">(</span><span class="n">NetworkStatusDocument</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Version 3 network status document. This could be either a vote or consensus.</span> <span class="sd"> :var tuple routers: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3`</span> <span class="sd"> contained in the document</span> <span class="sd"> :var int version: **\*** document version</span> <span class="sd"> :var str version_flavor: **\*** flavor associated with the document (such as 'microdesc')</span> <span class="sd"> :var bool is_consensus: **\*** **True** if the document is a consensus</span> <span class="sd"> :var bool is_vote: **\*** **True** if the document is a vote</span> <span class="sd"> :var bool is_microdescriptor: **\*** **True** if this is a microdescriptor</span> <span class="sd"> flavored document, **False** otherwise</span> <span class="sd"> :var datetime valid_after: **\*** time when the consensus became valid</span> <span class="sd"> :var datetime fresh_until: **\*** time when the next consensus should be produced</span> <span class="sd"> :var datetime valid_until: **\*** time when this consensus becomes obsolete</span> <span class="sd"> :var int vote_delay: **\*** number of seconds allowed for collecting votes</span> <span class="sd"> from all authorities</span> <span class="sd"> :var int dist_delay: **\*** number of seconds allowed for collecting</span> <span class="sd"> signatures from all authorities</span> <span class="sd"> :var list client_versions: list of recommended client tor versions</span> <span class="sd"> :var list server_versions: list of recommended server tor versions</span> <span class="sd"> :var list known_flags: **\*** list of :data:`~stem.Flag` for the router's flags</span> <span class="sd"> :var dict params: **\*** dict of parameter(**str**) => value(**int**) mappings</span> <span class="sd"> :var list directory_authorities: **\*** list of :class:`~stem.descriptor.networkstatus.DirectoryAuthority`</span> <span class="sd"> objects that have generated this document</span> <span class="sd"> :var list signatures: **\*** :class:`~stem.descriptor.networkstatus.DocumentSignature`</span> <span class="sd"> of the authorities that have signed the document</span> <span class="sd"> **Consensus Attributes:**</span> <span class="sd"> :var int consensus_method: method version used to generate this consensus</span> <span class="sd"> :var dict bandwidth_weights: dict of weight(str) => value(int) mappings</span> <span class="sd"> **Vote Attributes:**</span> <span class="sd"> :var list consensus_methods: list of ints for the supported method versions</span> <span class="sd"> :var datetime published: time when the document was published</span> <span class="sd"> :var dict flag_thresholds: **\*** mapping of internal performance thresholds used while making the vote, values are **ints** or **floats**</span> <span class="sd"> **\*** attribute is either required when we're parsed with validation or has</span> <span class="sd"> a default value, others are left as None if undefined</span> <span class="sd"> """</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">raw_content</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="n">default_params</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parse a v3 network status document.</span> <span class="sd"> :param str raw_content: raw network status document data</span> <span class="sd"> :param bool validate: **True** if the document is to be validated, **False** otherwise</span> <span class="sd"> :param bool default_params: includes defaults in our params dict, otherwise</span> <span class="sd"> it just contains values from the document</span> <span class="sd"> :raises: **ValueError** if the document is invalid</span> <span class="sd"> """</span> <span class="nb">super</span><span class="p">(</span><span class="n">NetworkStatusDocumentV3</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="n">document_file</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_header</span> <span class="o">=</span> <span class="n">_DocumentHeader</span><span class="p">(</span><span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">default_params</span><span class="p">)</span> <span class="c"># merge header attributes into us</span> <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">vars</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_header</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="k">if</span> <span class="n">attr</span> <span class="o">!=</span> <span class="s">"_unrecognized_lines"</span><span class="p">:</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">+=</span> <span class="n">value</span> <span class="bp">self</span><span class="o">.</span><span class="n">directory_authorities</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span> <span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">entry_class</span> <span class="o">=</span> <span class="n">DirectoryAuthority</span><span class="p">,</span> <span class="n">entry_keyword</span> <span class="o">=</span> <span class="n">AUTH_START</span><span class="p">,</span> <span class="n">section_end_keywords</span> <span class="o">=</span> <span class="p">(</span><span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">FOOTER_START</span><span class="p">,</span> <span class="n">V2_FOOTER_START</span><span class="p">),</span> <span class="n">extra_args</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_header</span><span class="o">.</span><span class="n">is_vote</span><span class="p">,),</span> <span class="p">))</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_header</span><span class="o">.</span><span class="n">is_vote</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">directory_authorities</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Votes should only have an authority entry for the one that issued it, got </span><span class="si">%i</span><span class="s">: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</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">directory_authorities</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">directory_authorities</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">_header</span><span class="o">.</span><span class="n">is_microdescriptor</span><span class="p">:</span> <span class="n">router_type</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV3</span> <span class="k">else</span><span class="p">:</span> <span class="n">router_type</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryMicroV3</span> <span class="n">router_iter</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span> <span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">entry_class</span> <span class="o">=</span> <span class="n">router_type</span><span class="p">,</span> <span class="n">entry_keyword</span> <span class="o">=</span> <span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">section_end_keywords</span> <span class="o">=</span> <span class="p">(</span><span class="n">FOOTER_START</span><span class="p">,</span> <span class="n">V2_FOOTER_START</span><span class="p">),</span> <span class="n">extra_args</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">,),</span> <span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">routers</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">desc</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">,</span> <span class="n">desc</span><span class="p">)</span> <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">router_iter</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_footer</span> <span class="o">=</span> <span class="n">_DocumentFooter</span><span class="p">(</span><span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_header</span><span class="p">)</span> <span class="c"># merge header attributes into us</span> <span class="k">for</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">vars</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_footer</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="k">if</span> <span class="n">attr</span> <span class="o">!=</span> <span class="s">"_unrecognized_lines"</span><span class="p">:</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">+=</span> <span class="n">value</span> <div class="viewcode-block" id="NetworkStatusDocumentV3.meets_consensus_method"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.NetworkStatusDocumentV3.meets_consensus_method">[docs]</a> <span class="k">def</span> <span class="nf">meets_consensus_method</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">method</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Checks if we meet the given consensus-method. This works for both votes and</span> <span class="sd"> consensuses, checking our 'consensus-method' and 'consensus-methods'</span> <span class="sd"> entries.</span> <span class="sd"> :param int method: consensus-method to check for</span> <span class="sd"> :returns: **True** if we meet the given consensus-method, and **False** otherwise</span> <span class="sd"> """</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_header</span><span class="o">.</span><span class="n">meets_consensus_method</span><span class="p">(</span><span class="n">method</span><span class="p">)</span> </div> <span class="k">def</span> <span class="nf">_compare</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="n">method</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">NetworkStatusDocumentV3</span><span class="p">):</span> <span class="k">return</span> <span class="bp">False</span> <span class="k">return</span> <span class="n">method</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="nb">str</span><span class="p">(</span><span class="n">other</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">def</span> <span class="nf">__hash__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">hash</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">def</span> <span class="nf">__eq__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o">==</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__lt__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__le__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><=</span> <span class="n">o</span><span class="p">)</span> </div> <span class="k">class</span> <span class="nc">_DocumentHeader</span><span class="p">(</span><span class="nb">object</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">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">default_params</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">version_flavor</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_consensus</span> <span class="o">=</span> <span class="bp">True</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_vote</span> <span class="o">=</span> <span class="bp">False</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_microdescriptor</span> <span class="o">=</span> <span class="bp">False</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_methods</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_method</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">valid_after</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">fresh_until</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">valid_until</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">vote_delay</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">dist_delay</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_versions</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_versions</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">known_flags</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">flag_thresholds</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">DEFAULT_PARAMS</span><span class="p">)</span> <span class="k">if</span> <span class="n">default_params</span> <span class="k">else</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">content</span> <span class="o">=</span> <span class="nb">bytes</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">b</span><span class="s">""</span><span class="p">,</span> <span class="n">_read_until_keywords</span><span class="p">((</span><span class="n">AUTH_START</span><span class="p">,</span> <span class="n">ROUTERS_START</span><span class="p">,</span> <span class="n">FOOTER_START</span><span class="p">),</span> <span class="n">document_file</span><span class="p">))</span> <span class="n">content</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">_get_descriptor_components</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parse</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="c"># doing this validation afterward so we know our 'is_consensus' and</span> <span class="c"># 'is_vote' attributes</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="n">_check_for_missing_and_disallowed_fields</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entries</span><span class="p">,</span> <span class="n">HEADER_STATUS_DOCUMENT_FIELDS</span><span class="p">)</span> <span class="n">_check_for_misordered_fields</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">HEADER_FIELDS</span><span class="p">)</span> <span class="k">def</span> <span class="nf">meets_consensus_method</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">method</span><span class="p">):</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_method</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_method</span> <span class="o">>=</span> <span class="n">method</span> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_methods</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span> <span class="o">>=</span> <span class="n">method</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_methods</span><span class="p">))</span> <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="bp">False</span> <span class="c"># malformed document</span> <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entries</span><span class="p">,</span> <span class="n">validate</span><span class="p">):</span> <span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="n">value</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">line</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="c"># all known header fields can only appear once except</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">HEADER_FIELDS</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status documents can only have a single '</span><span class="si">%s</span><span class="s">' line, got </span><span class="si">%i</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)))</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'network-status-version'</span><span class="p">:</span> <span class="c"># "network-status-version" version</span> <span class="k">if</span> <span class="s">' '</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span> <span class="n">version</span><span class="p">,</span> <span class="n">flavor</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">version</span><span class="p">,</span> <span class="n">flavor</span> <span class="o">=</span> <span class="n">value</span><span class="p">,</span> <span class="bp">None</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">version</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document has a non-numeric version: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">version</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">version_flavor</span> <span class="o">=</span> <span class="n">flavor</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_microdescriptor</span> <span class="o">=</span> <span class="n">flavor</span> <span class="o">==</span> <span class="s">'microdesc'</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Expected a version 3 network status document, got version '</span><span class="si">%s</span><span class="s">' instead"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'vote-status'</span><span class="p">:</span> <span class="c"># "vote-status" type</span> <span class="c">#</span> <span class="c"># The consensus-method and consensus-methods fields are optional since</span> <span class="c"># they weren't included in version 1. Setting a default now that we</span> <span class="c"># know if we're a vote or not.</span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="s">'consensus'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_consensus</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_vote</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="bp">False</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_method</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">value</span> <span class="o">==</span> <span class="s">'vote'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_consensus</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_vote</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span> <span class="bp">True</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_methods</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">elif</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"A network status document's vote-status line can only be 'consensus' or 'vote', got '</span><span class="si">%s</span><span class="s">' instead"</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'consensus-methods'</span><span class="p">:</span> <span class="c"># "consensus-methods" IntegerList</span> <span class="n">consensus_methods</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">):</span> <span class="k">if</span> <span class="n">entry</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="n">consensus_methods</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">entry</span><span class="p">))</span> <span class="k">elif</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"A network status document's consensus-methods must be a list of integer values, but was '</span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_methods</span> <span class="o">=</span> <span class="n">consensus_methods</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="p">(</span><span class="mi">1</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_methods</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status votes must include consensus-method version 1"</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'consensus-method'</span><span class="p">:</span> <span class="c"># "consensus-method" Integer</span> <span class="k">if</span> <span class="n">value</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">consensus_method</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"A network status document's consensus-method must be an integer, but was '</span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'published'</span><span class="p">,</span> <span class="s">'valid-after'</span><span class="p">,</span> <span class="s">'fresh-until'</span><span class="p">,</span> <span class="s">'valid-until'</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">date_value</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s">"%Y-%m-</span><span class="si">%d</span><span class="s"> %H:%M:%S"</span><span class="p">)</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'published'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="n">date_value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'valid-after'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">valid_after</span> <span class="o">=</span> <span class="n">date_value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'fresh-until'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">fresh_until</span> <span class="o">=</span> <span class="n">date_value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'valid-until'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">valid_until</span> <span class="o">=</span> <span class="n">date_value</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document's '</span><span class="si">%s</span><span class="s">' time wasn't parsable: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"voting-delay"</span><span class="p">:</span> <span class="c"># "voting-delay" VoteSeconds DistSeconds</span> <span class="n">value_comp</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">value_comp</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">value_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">isdigit</span><span class="p">()</span> <span class="ow">and</span> <span class="n">value_comp</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">vote_delay</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">dist_delay</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value_comp</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">elif</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"A network status document's 'voting-delay' line must be a pair of integer values, but was '</span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"client-versions"</span><span class="p">,</span> <span class="s">"server-versions"</span><span class="p">):</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">","</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">version_value</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">_get_version</span><span class="p">(</span><span class="n">entry</span><span class="p">)</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'client-versions'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">client_versions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">version_value</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'server-versions'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">server_versions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">version_value</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document's '</span><span class="si">%s</span><span class="s">' line had '</span><span class="si">%s</span><span class="s">', which isn't a parsable tor version: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">entry</span><span class="p">,</span> <span class="n">line</span><span class="p">))</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"known-flags"</span><span class="p">:</span> <span class="c"># "known-flags" FlagList</span> <span class="c"># simply fetches the entries, excluding empty strings</span> <span class="bp">self</span><span class="o">.</span><span class="n">known_flags</span> <span class="o">=</span> <span class="p">[</span><span class="n">entry</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span> <span class="k">if</span> <span class="n">entry</span><span class="p">]</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"flag-thresholds"</span><span class="p">:</span> <span class="c"># "flag-thresholds" SP THRESHOLDS</span> <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">if</span> <span class="n">value</span><span class="p">:</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="s">'='</span> <span class="ow">in</span> <span class="n">entry</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document's '</span><span class="si">%s</span><span class="s">' line is expected to be space separated key=value mappings, got: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">line</span><span class="p">))</span> <span class="n">entry_key</span><span class="p">,</span> <span class="n">entry_value</span> <span class="o">=</span> <span class="n">entry</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">"="</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="k">if</span> <span class="n">entry_value</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">"%"</span><span class="p">):</span> <span class="c"># opting for string manipulation rather than just</span> <span class="c"># 'float(entry_value) / 100' because floating point arithmetic</span> <span class="c"># will lose precision</span> <span class="bp">self</span><span class="o">.</span><span class="n">flag_thresholds</span><span class="p">[</span><span class="n">entry_key</span><span class="p">]</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="s">"0."</span> <span class="o">+</span> <span class="n">entry_value</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'.'</span><span class="p">,</span> <span class="s">''</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span> <span class="k">elif</span> <span class="s">'.'</span> <span class="ow">in</span> <span class="n">entry_value</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">flag_thresholds</span><span class="p">[</span><span class="n">entry_key</span><span class="p">]</span> <span class="o">=</span> <span class="nb">float</span><span class="p">(</span><span class="n">entry_value</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">flag_thresholds</span><span class="p">[</span><span class="n">entry_key</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">entry_value</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document's '</span><span class="si">%s</span><span class="s">' line is expected to have float values, got: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">line</span><span class="p">))</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"params"</span><span class="p">:</span> <span class="c"># "params" [Parameters]</span> <span class="c"># Parameter ::= Keyword '=' Int32</span> <span class="c"># Int32 ::= A decimal integer between -2147483648 and 2147483647.</span> <span class="c"># Parameters ::= Parameter | Parameters SP Parameter</span> <span class="c"># should only appear in consensus-method 7 or later</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">meets_consensus_method</span><span class="p">(</span><span class="mi">7</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"A network status document's 'params' line should only appear in consensus-method 7 or later"</span><span class="p">)</span> <span class="c"># skip if this is a blank line</span> <span class="k">if</span> <span class="n">value</span> <span class="o">==</span> <span class="s">""</span><span class="p">:</span> <span class="k">continue</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">_parse_int_mappings</span><span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">validate</span><span class="p">))</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_check_params_constraints</span><span class="p">()</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_check_params_constraints</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Checks that the params we know about are within their documented ranges.</span> <span class="sd"> """</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="bp">self</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="c"># all parameters are constrained to int32 range</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2147483648</span><span class="p">,</span> <span class="mi">2147483647</span> <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"circwindow"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">100</span><span class="p">,</span> <span class="mi">1000</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"CircuitPriorityHalflifeMsec"</span><span class="p">:</span> <span class="n">minimum</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"perconnbwrate"</span><span class="p">,</span> <span class="s">"perconnbwburst"</span><span class="p">):</span> <span class="n">minimum</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"refuseunknownexits"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"bwweightscale"</span><span class="p">:</span> <span class="n">minimum</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtdisabled"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtnummodes"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">20</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtrecentcount"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1000</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtmaxtimeouts"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">10000</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtmincircs"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">10000</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtquantile"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">99</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtclosequantile"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"cbtquantile"</span><span class="p">,</span> <span class="n">minimum</span><span class="p">),</span> <span class="mi">99</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbttestfreq"</span><span class="p">:</span> <span class="n">minimum</span> <span class="o">=</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtmintimeout"</span><span class="p">:</span> <span class="n">minimum</span> <span class="o">=</span> <span class="mi">500</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"cbtinitialtimeout"</span><span class="p">:</span> <span class="n">minimum</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"cbtmintimeout"</span><span class="p">,</span> <span class="n">minimum</span><span class="p">)</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"UseOptimisticData"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span> <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">"Support022HiddenServices"</span><span class="p">:</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">value</span> <span class="o"><</span> <span class="n">minimum</span> <span class="ow">or</span> <span class="n">value</span> <span class="o">></span> <span class="n">maximum</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"'</span><span class="si">%s</span><span class="s">' value on the params line must be in the range of </span><span class="si">%i</span><span class="s"> - </span><span class="si">%i</span><span class="s">, was </span><span class="si">%i</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">minimum</span><span class="p">,</span> <span class="n">maximum</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span> <span class="k">class</span> <span class="nc">_DocumentFooter</span><span class="p">(</span><span class="nb">object</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">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">header</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">signatures</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">bandwidth_weights</span> <span class="o">=</span> <span class="p">{}</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">content</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">document_file</span><span class="o">.</span><span class="n">read</span><span class="p">())</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">content</span><span class="p">:</span> <span class="k">return</span> <span class="c"># footer is optional and there's nothing to parse</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">_get_descriptor_components</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parse</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">header</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="c"># Check that the footer has the right initial line. Prior to consensus</span> <span class="c"># method 9 it's a 'directory-signature' and after that footers start with</span> <span class="c"># 'directory-footer'.</span> <span class="k">if</span> <span class="n">header</span><span class="o">.</span><span class="n">meets_consensus_method</span><span class="p">(</span><span class="mi">9</span><span class="p">):</span> <span class="k">if</span> <span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s">'directory-footer'</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document's footer should start with a 'directory-footer' line in consensus-method 9 or later"</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="k">if</span> <span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s">'directory-signature'</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document's footer should start with a 'directory-signature' line prior to consensus-method 9"</span><span class="p">)</span> <span class="n">_check_for_missing_and_disallowed_fields</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">entries</span><span class="p">,</span> <span class="n">FOOTER_STATUS_DOCUMENT_FIELDS</span><span class="p">)</span> <span class="n">_check_for_misordered_fields</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">FOOTER_FIELDS</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">entries</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">header</span><span class="p">):</span> <span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="n">value</span><span class="p">,</span> <span class="n">block_contents</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">line</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="c"># all known footer fields can only appear once except...</span> <span class="c"># * 'directory-signature' in a consensus</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">FOOTER_FIELDS</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">keyword</span> <span class="o">==</span> <span class="s">'directory-signature'</span> <span class="ow">and</span> <span class="n">header</span><span class="o">.</span><span class="n">is_consensus</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status documents can only have a single '</span><span class="si">%s</span><span class="s">' line, got </span><span class="si">%i</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)))</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"directory-footer"</span><span class="p">:</span> <span class="c"># nothing to parse, simply checking that we don't have a value</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="n">value</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"A network status document's 'directory-footer' line shouldn't have any content, got '</span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"bandwidth-weights"</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">bandwidth_weights</span> <span class="o">=</span> <span class="n">_parse_int_mappings</span><span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">"directory-signature"</span><span class="p">:</span> <span class="k">for</span> <span class="n">sig_value</span><span class="p">,</span> <span class="n">block_contents</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">sig_value</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">block_contents</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority signatures in a network status document are expected to be of the form 'directory-signature [METHOD] FINGERPRINT KEY_DIGEST</span><span class="se">\\</span><span class="s">nSIGNATURE', got:</span><span class="se">\n</span><span class="si">%s</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">sig_value</span><span class="p">,</span> <span class="n">block_contents</span><span class="p">))</span> <span class="k">if</span> <span class="n">sig_value</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span> <span class="n">method</span> <span class="o">=</span> <span class="s">'sha1'</span> <span class="c"># default if none was provided</span> <span class="n">fingerprint</span><span class="p">,</span> <span class="n">key_digest</span> <span class="o">=</span> <span class="n">sig_value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">method</span><span class="p">,</span> <span class="n">fingerprint</span><span class="p">,</span> <span class="n">key_digest</span> <span class="o">=</span> <span class="n">sig_value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">signatures</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">DocumentSignature</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="n">fingerprint</span><span class="p">,</span> <span class="n">key_digest</span><span class="p">,</span> <span class="n">block_contents</span><span class="p">,</span> <span class="n">validate</span><span class="p">))</span> <span class="k">def</span> <span class="nf">_check_for_missing_and_disallowed_fields</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">entries</span><span class="p">,</span> <span class="n">fields</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Checks that we have mandatory fields for our type, and that we don't have</span> <span class="sd"> any fields exclusive to the other (ie, no vote-only fields appear in a</span> <span class="sd"> consensus or vice versa).</span> <span class="sd"> :param _DocumentHeader header: document header</span> <span class="sd"> :param dict entries: ordered keyword/value mappings of the header or footer</span> <span class="sd"> :param list fields: expected field attributes (either</span> <span class="sd"> **HEADER_STATUS_DOCUMENT_FIELDS** or **FOOTER_STATUS_DOCUMENT_FIELDS**)</span> <span class="sd"> :raises: **ValueError** if we're missing mandatory fields or have fields we shouldn't</span> <span class="sd"> """</span> <span class="n">missing_fields</span><span class="p">,</span> <span class="n">disallowed_fields</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">field</span><span class="p">,</span> <span class="n">in_votes</span><span class="p">,</span> <span class="n">in_consensus</span><span class="p">,</span> <span class="n">mandatory</span> <span class="ow">in</span> <span class="n">fields</span><span class="p">:</span> <span class="k">if</span> <span class="n">mandatory</span> <span class="ow">and</span> <span class="p">((</span><span class="n">header</span><span class="o">.</span><span class="n">is_consensus</span> <span class="ow">and</span> <span class="n">in_consensus</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">header</span><span class="o">.</span><span class="n">is_vote</span> <span class="ow">and</span> <span class="n">in_votes</span><span class="p">)):</span> <span class="c"># mandatory field, check that we have it</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span> <span class="n">missing_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field</span><span class="p">)</span> <span class="k">elif</span> <span class="p">(</span><span class="n">header</span><span class="o">.</span><span class="n">is_consensus</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">in_consensus</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">header</span><span class="o">.</span><span class="n">is_vote</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">in_votes</span><span class="p">):</span> <span class="c"># field we shouldn't have, check that we don't</span> <span class="k">if</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span> <span class="n">disallowed_fields</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">field</span><span class="p">)</span> <span class="k">if</span> <span class="n">missing_fields</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document is missing mandatory field: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="s">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">missing_fields</span><span class="p">))</span> <span class="k">if</span> <span class="n">disallowed_fields</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Network status document has fields that shouldn't appear in this document type or version: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="s">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">disallowed_fields</span><span class="p">))</span> <span class="k">def</span> <span class="nf">_check_for_misordered_fields</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">expected</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> To be valid a network status document's fiends need to appear in a specific</span> <span class="sd"> order. Checks that known fields appear in that order (unrecognized fields</span> <span class="sd"> are ignored).</span> <span class="sd"> :param dict entries: ordered keyword/value mappings of the header or footer</span> <span class="sd"> :param list expected: ordered list of expected fields (either</span> <span class="sd"> **HEADER_FIELDS** or **FOOTER_FIELDS**)</span> <span class="sd"> :raises: **ValueError** if entries aren't properly ordered</span> <span class="sd"> """</span> <span class="c"># Earlier validation has ensured that our fields either belong to our</span> <span class="c"># document type or are unknown. Remove the unknown fields since they</span> <span class="c"># reflect a spec change and can appear anywhere in the document.</span> <span class="n">actual</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">field</span><span class="p">:</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">expected</span><span class="p">,</span> <span class="n">entries</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span> <span class="c"># Narrow the expected to just what we have. If the lists then match then the</span> <span class="c"># order's valid.</span> <span class="n">expected</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">field</span><span class="p">:</span> <span class="n">field</span> <span class="ow">in</span> <span class="n">actual</span><span class="p">,</span> <span class="n">expected</span><span class="p">)</span> <span class="k">if</span> <span class="n">actual</span> <span class="o">!=</span> <span class="n">expected</span><span class="p">:</span> <span class="n">actual_label</span> <span class="o">=</span> <span class="s">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">actual</span><span class="p">)</span> <span class="n">expected_label</span> <span class="o">=</span> <span class="s">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">expected</span><span class="p">)</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"The fields in a section of the document are misordered. It should be '</span><span class="si">%s</span><span class="s">' but was '</span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="p">(</span><span class="n">actual_label</span><span class="p">,</span> <span class="n">expected_label</span><span class="p">))</span> <span class="k">def</span> <span class="nf">_parse_int_mappings</span><span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">validate</span><span class="p">):</span> <span class="c"># Parse a series of 'key=value' entries, checking the following:</span> <span class="c"># - values are integers</span> <span class="c"># - keys are sorted in lexical order</span> <span class="n">results</span><span class="p">,</span> <span class="n">seen_keys</span> <span class="o">=</span> <span class="p">{},</span> <span class="p">[]</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="s">'='</span> <span class="ow">in</span> <span class="n">entry</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"must only have 'key=value' entries"</span><span class="p">)</span> <span class="n">entry_key</span><span class="p">,</span> <span class="n">entry_value</span> <span class="o">=</span> <span class="n">entry</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">"="</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">try</span><span class="p">:</span> <span class="c"># the int() function accepts things like '+123', but we don't want to</span> <span class="k">if</span> <span class="n">entry_value</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">'+'</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">()</span> <span class="n">entry_value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">entry_value</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"'</span><span class="si">%s</span><span class="s">' is a non-numeric value"</span> <span class="o">%</span> <span class="n">entry_value</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="c"># parameters should be in ascending order by their key</span> <span class="k">for</span> <span class="n">prior_key</span> <span class="ow">in</span> <span class="n">seen_keys</span><span class="p">:</span> <span class="k">if</span> <span class="n">prior_key</span> <span class="o">></span> <span class="n">entry_key</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"parameters must be sorted by their key"</span><span class="p">)</span> <span class="n">results</span><span class="p">[</span><span class="n">entry_key</span><span class="p">]</span> <span class="o">=</span> <span class="n">entry_value</span> <span class="n">seen_keys</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">entry_key</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Unable to parse network status document's '</span><span class="si">%s</span><span class="s">' line (</span><span class="si">%s</span><span class="s">): </span><span class="si">%s</span><span class="s">'"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">exc</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span> <span class="k">return</span> <span class="n">results</span> <div class="viewcode-block" id="DirectoryAuthority"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.DirectoryAuthority">[docs]</a><span class="k">class</span> <span class="nc">DirectoryAuthority</span><span class="p">(</span><span class="n">Descriptor</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Directory authority information obtained from a v3 network status document.</span> <span class="sd"> Authorities can optionally use a legacy format. These are no longer found in</span> <span class="sd"> practice, but have the following differences...</span> <span class="sd"> * The authority's nickname ends with '-legacy'.</span> <span class="sd"> * There's no **contact** or **vote_digest** attribute.</span> <span class="sd"> :var str nickname: **\*** authority's nickname</span> <span class="sd"> :var str fingerprint: **\*** authority's fingerprint</span> <span class="sd"> :var str hostname: **\*** hostname of the authority</span> <span class="sd"> :var str address: **\*** authority's IP address</span> <span class="sd"> :var int dir_port: **\*** authority's DirPort</span> <span class="sd"> :var int or_port: **\*** authority's ORPort</span> <span class="sd"> :var bool is_legacy: **\*** if the authority's using the legacy format</span> <span class="sd"> :var str contact: contact information, this is included if is_legacy is **False**</span> <span class="sd"> **Consensus Attributes:**</span> <span class="sd"> :var str vote_digest: digest of the authority that contributed to the consensus, this is included if is_legacy is **False**</span> <span class="sd"> **Vote Attributes:**</span> <span class="sd"> :var str legacy_dir_key: fingerprint of and obsolete identity key</span> <span class="sd"> :var stem.descriptor.networkstatus.KeyCertificate key_certificate: **\***</span> <span class="sd"> authority's key certificate</span> <span class="sd"> **\*** mandatory attribute</span> <span class="sd"> """</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">raw_content</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="n">is_vote</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parse a directory authority entry in a v3 network status document.</span> <span class="sd"> :param str raw_content: raw directory authority entry information</span> <span class="sd"> :param bool validate: checks the validity of the content if True, skips</span> <span class="sd"> these checks otherwise</span> <span class="sd"> :param bool is_vote: True if this is for a vote, False if it's for a consensus</span> <span class="sd"> :raises: ValueError if the descriptor data is invalid</span> <span class="sd"> """</span> <span class="nb">super</span><span class="p">(</span><span class="n">DirectoryAuthority</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="n">raw_content</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">nickname</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">hostname</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">dir_port</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">or_port</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_legacy</span> <span class="o">=</span> <span class="bp">False</span> <span class="bp">self</span><span class="o">.</span><span class="n">contact</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">vote_digest</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">legacy_dir_key</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_certificate</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parse</span><span class="p">(</span><span class="n">raw_content</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">is_vote</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">is_vote</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parses the given content and applies the attributes.</span> <span class="sd"> :param str content: descriptor content</span> <span class="sd"> :param bool validate: checks validity if True</span> <span class="sd"> :param bool is_vote: **True** if this is for a vote, **False** if it's for</span> <span class="sd"> a consensus</span> <span class="sd"> :raises: **ValueError** if a validity check fails</span> <span class="sd"> """</span> <span class="c"># separate the directory authority entry from its key certificate</span> <span class="n">key_div</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">dir-key-certificate-version'</span><span class="p">)</span> <span class="k">if</span> <span class="n">key_div</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span> <span class="n">key_cert_content</span> <span class="o">=</span> <span class="n">content</span><span class="p">[</span><span class="n">key_div</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:]</span> <span class="n">content</span> <span class="o">=</span> <span class="n">content</span><span class="p">[:</span><span class="n">key_div</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="k">else</span><span class="p">:</span> <span class="n">key_cert_content</span> <span class="o">=</span> <span class="bp">None</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">_get_descriptor_components</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="s">'dir-source'</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="mi">0</span><span class="p">]:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority entries are expected to start with a 'dir-source' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">content</span><span class="p">))</span> <span class="c"># check that we have mandatory fields</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="n">is_legacy</span><span class="p">,</span> <span class="n">dir_source_entry</span> <span class="o">=</span> <span class="bp">False</span><span class="p">,</span> <span class="n">entries</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">"dir-source"</span><span class="p">)</span> <span class="k">if</span> <span class="n">dir_source_entry</span><span class="p">:</span> <span class="n">is_legacy</span> <span class="o">=</span> <span class="n">dir_source_entry</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">"-legacy"</span><span class="p">)</span> <span class="n">required_fields</span><span class="p">,</span> <span class="n">excluded_fields</span> <span class="o">=</span> <span class="p">[</span><span class="s">"dir-source"</span><span class="p">],</span> <span class="p">[]</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">is_legacy</span><span class="p">:</span> <span class="n">required_fields</span> <span class="o">+=</span> <span class="p">[</span><span class="s">"contact"</span><span class="p">]</span> <span class="k">if</span> <span class="n">is_vote</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">key_cert_content</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority votes must have a key certificate:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">content</span><span class="p">)</span> <span class="n">excluded_fields</span> <span class="o">+=</span> <span class="p">[</span><span class="s">"vote-digest"</span><span class="p">]</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">is_vote</span><span class="p">:</span> <span class="k">if</span> <span class="n">key_cert_content</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority consensus entries shouldn't have a key certificate:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">content</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">is_legacy</span><span class="p">:</span> <span class="n">required_fields</span> <span class="o">+=</span> <span class="p">[</span><span class="s">"vote-digest"</span><span class="p">]</span> <span class="n">excluded_fields</span> <span class="o">+=</span> <span class="p">[</span><span class="s">"legacy-dir-key"</span><span class="p">]</span> <span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">required_fields</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">entries</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority entries must have a '</span><span class="si">%s</span><span class="s">' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">content</span><span class="p">))</span> <span class="k">for</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">entries</span><span class="p">:</span> <span class="k">if</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">excluded_fields</span><span class="p">:</span> <span class="n">type_label</span> <span class="o">=</span> <span class="s">"votes"</span> <span class="k">if</span> <span class="n">is_vote</span> <span class="k">else</span> <span class="s">"consensus entries"</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority </span><span class="si">%s</span><span class="s"> shouldn't have a '</span><span class="si">%s</span><span class="s">' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">type_label</span><span class="p">,</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">content</span><span class="p">))</span> <span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="n">value</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">line</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="c"># all known attributes can only appear at most once</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'dir-source'</span><span class="p">,</span> <span class="s">'contact'</span><span class="p">,</span> <span class="s">'legacy-dir-key'</span><span class="p">,</span> <span class="s">'vote-digest'</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority entries can only have a single '</span><span class="si">%s</span><span class="s">' line, got </span><span class="si">%i</span><span class="s">:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">values</span><span class="p">),</span> <span class="n">content</span><span class="p">))</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-source'</span><span class="p">:</span> <span class="c"># "dir-source" nickname identity address IP dirport orport</span> <span class="n">dir_source_comp</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">)</span> <span class="o"><</span> <span class="mi">6</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority entry's 'dir-source' line must have six values: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_nickname</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s">'-legacy'</span><span class="p">)):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's nickname is invalid: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's fingerprint is invalid: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span> <span class="c"># https://trac.torproject.org/7055</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's hostname can't be blank: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">3</span><span class="p">]):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's address isn't a valid IPv4 address: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">allow_zero</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's DirPort is invalid: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">4</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">5</span><span class="p">]):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority's ORPort is invalid: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="k">elif</span> <span class="ow">not</span> <span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span><span class="o">.</span><span class="n">isdigit</span><span class="p">()</span> <span class="ow">and</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span><span class="o">.</span><span class="n">isdigit</span><span class="p">()):</span> <span class="k">continue</span> <span class="bp">self</span><span class="o">.</span><span class="n">nickname</span> <span class="o">=</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">=</span> <span class="n">dir_source_comp</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">hostname</span> <span class="o">=</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="bp">self</span><span class="o">.</span><span class="n">dir_port</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">if</span> <span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="s">'0'</span> <span class="k">else</span> <span class="nb">int</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">4</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">or_port</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">dir_source_comp</span><span class="p">[</span><span class="mi">5</span><span class="p">])</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_legacy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nickname</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">"-legacy"</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'contact'</span><span class="p">:</span> <span class="c"># "contact" string</span> <span class="bp">self</span><span class="o">.</span><span class="n">contact</span> <span class="o">=</span> <span class="n">value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'legacy-dir-key'</span><span class="p">:</span> <span class="c"># "legacy-dir-key" FINGERPRINT</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">value</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority has a malformed legacy directory key: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">legacy_dir_key</span> <span class="o">=</span> <span class="n">value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'vote-digest'</span><span class="p">:</span> <span class="c"># "vote-digest" digest</span> <span class="c"># technically not a fingerprint, but has the same characteristics</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">value</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Authority has a malformed vote digest: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">vote_digest</span> <span class="o">=</span> <span class="n">value</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="k">if</span> <span class="n">key_cert_content</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_certificate</span> <span class="o">=</span> <span class="n">KeyCertificate</span><span class="p">(</span><span class="n">key_cert_content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <div class="viewcode-block" id="DirectoryAuthority.get_unrecognized_lines"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.DirectoryAuthority.get_unrecognized_lines">[docs]</a> <span class="k">def</span> <span class="nf">get_unrecognized_lines</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns any unrecognized lines.</span> <span class="sd"> :returns: a list of unrecognized lines</span> <span class="sd"> """</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> </div> <span class="k">def</span> <span class="nf">_compare</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="n">method</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">DirectoryAuthority</span><span class="p">):</span> <span class="k">return</span> <span class="bp">False</span> <span class="k">return</span> <span class="n">method</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="nb">str</span><span class="p">(</span><span class="n">other</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">def</span> <span class="nf">__eq__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o">==</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__lt__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__le__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><=</span> <span class="n">o</span><span class="p">)</span> </div> <div class="viewcode-block" id="KeyCertificate"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.KeyCertificate">[docs]</a><span class="k">class</span> <span class="nc">KeyCertificate</span><span class="p">(</span><span class="n">Descriptor</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Directory key certificate for a v3 network status document.</span> <span class="sd"> :var int version: **\*** version of the key certificate</span> <span class="sd"> :var str address: authority's IP address</span> <span class="sd"> :var int dir_port: authority's DirPort</span> <span class="sd"> :var str fingerprint: **\*** authority's fingerprint</span> <span class="sd"> :var str identity_key: **\*** long term authority identity key</span> <span class="sd"> :var datetime published: **\*** time when this key was generated</span> <span class="sd"> :var datetime expires: **\*** time after which this key becomes invalid</span> <span class="sd"> :var str signing_key: **\*** directory server's public signing key</span> <span class="sd"> :var str crosscert: signature made using certificate's signing key</span> <span class="sd"> :var str certification: **\*** signature of this key certificate signed with</span> <span class="sd"> the identity key</span> <span class="sd"> **\*** mandatory attribute</span> <span class="sd"> """</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">raw_content</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">KeyCertificate</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="n">raw_content</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">dir_port</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">identity_key</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">expires</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">signing_key</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">crosscert</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">certification</span> <span class="o">=</span> <span class="bp">None</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parse</span><span class="p">(</span><span class="n">raw_content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">,</span> <span class="n">validate</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Parses the given content and applies the attributes.</span> <span class="sd"> :param str content: descriptor content</span> <span class="sd"> :param bool validate: checks validity if **True**</span> <span class="sd"> :raises: **ValueError** if a validity check fails</span> <span class="sd"> """</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">_get_descriptor_components</span><span class="p">(</span><span class="n">content</span><span class="p">,</span> <span class="n">validate</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">if</span> <span class="s">'dir-key-certificate-version'</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="mi">0</span><span class="p">]:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificates must start with a 'dir-key-certificate-version' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">content</span><span class="p">))</span> <span class="k">elif</span> <span class="s">'dir-key-certification'</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="o">-</span><span class="mi">1</span><span class="p">]:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificates must end with a 'dir-key-certification' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">content</span><span class="p">))</span> <span class="c"># check that we have mandatory fields and that our known fields only</span> <span class="c"># appear once</span> <span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">is_mandatory</span> <span class="ow">in</span> <span class="n">KEY_CERTIFICATE_PARAMS</span><span class="p">:</span> <span class="k">if</span> <span class="n">is_mandatory</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="n">entries</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificates must have a '</span><span class="si">%s</span><span class="s">' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">content</span><span class="p">))</span> <span class="n">entry_count</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">entries</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="p">[]))</span> <span class="k">if</span> <span class="n">entry_count</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificates can only have a single '</span><span class="si">%s</span><span class="s">' line, got </span><span class="si">%i</span><span class="s">:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">entry_count</span><span class="p">,</span> <span class="n">content</span><span class="p">))</span> <span class="k">for</span> <span class="n">keyword</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="n">value</span><span class="p">,</span> <span class="n">block_contents</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="n">line</span> <span class="o">=</span> <span class="s">"</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-key-certificate-version'</span><span class="p">:</span> <span class="c"># "dir-key-certificate-version" version</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">value</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate has a non-integer version: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Expected a version 3 key certificate, got version '</span><span class="si">%i</span><span class="s">' instead"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">version</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-address'</span><span class="p">:</span> <span class="c"># "dir-address" IPPort</span> <span class="k">if</span> <span class="ow">not</span> <span class="s">':'</span> <span class="ow">in</span> <span class="n">value</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">validate</span><span class="p">:</span> <span class="k">continue</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate's 'dir-address' is expected to be of the form ADDRESS:PORT: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="n">address</span><span class="p">,</span> <span class="n">dirport</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">':'</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">address</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate's address isn't a valid IPv4 address: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">dirport</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate's dirport is invalid: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="k">elif</span> <span class="ow">not</span> <span class="n">dirport</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span> <span class="k">continue</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="n">address</span> <span class="bp">self</span><span class="o">.</span><span class="n">dir_port</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">dirport</span><span class="p">)</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'fingerprint'</span><span class="p">:</span> <span class="c"># "fingerprint" fingerprint</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">value</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate's fingerprint is malformed: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">line</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">fingerprint</span> <span class="o">=</span> <span class="n">value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'dir-key-published'</span><span class="p">,</span> <span class="s">'dir-key-expires'</span><span class="p">):</span> <span class="c"># "dir-key-published" YYYY-MM-DD HH:MM:SS</span> <span class="c"># "dir-key-expires" YYYY-MM-DD HH:MM:SS</span> <span class="k">try</span><span class="p">:</span> <span class="n">date_value</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s">"%Y-%m-</span><span class="si">%d</span><span class="s"> %H:%M:%S"</span><span class="p">)</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-key-published'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="n">date_value</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-key-expires'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">expires</span> <span class="o">=</span> <span class="n">date_value</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate's '</span><span class="si">%s</span><span class="s">' time wasn't parsable: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'dir-identity-key'</span><span class="p">,</span> <span class="s">'dir-signing-key'</span><span class="p">,</span> <span class="s">'dir-key-crosscert'</span><span class="p">,</span> <span class="s">'dir-key-certification'</span><span class="p">):</span> <span class="c"># "dir-identity-key" NL a public key in PEM format</span> <span class="c"># "dir-signing-key" NL a key in PEM format</span> <span class="c"># "dir-key-crosscert" NL CrossSignature</span> <span class="c"># "dir-key-certification" NL Signature</span> <span class="k">if</span> <span class="n">validate</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">block_contents</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Key certificate's '</span><span class="si">%s</span><span class="s">' line must be followed by a key block: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">keyword</span><span class="p">,</span> <span class="n">line</span><span class="p">))</span> <span class="k">if</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-identity-key'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">identity_key</span> <span class="o">=</span> <span class="n">block_contents</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-signing-key'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">signing_key</span> <span class="o">=</span> <span class="n">block_contents</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-key-crosscert'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">crosscert</span> <span class="o">=</span> <span class="n">block_contents</span> <span class="k">elif</span> <span class="n">keyword</span> <span class="o">==</span> <span class="s">'dir-key-certification'</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">certification</span> <span class="o">=</span> <span class="n">block_contents</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <div class="viewcode-block" id="KeyCertificate.get_unrecognized_lines"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.KeyCertificate.get_unrecognized_lines">[docs]</a> <span class="k">def</span> <span class="nf">get_unrecognized_lines</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Returns any unrecognized lines.</span> <span class="sd"> :returns: **list** of unrecognized lines</span> <span class="sd"> """</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_unrecognized_lines</span> </div> <span class="k">def</span> <span class="nf">_compare</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="n">method</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">KeyCertificate</span><span class="p">):</span> <span class="k">return</span> <span class="bp">False</span> <span class="k">return</span> <span class="n">method</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="nb">str</span><span class="p">(</span><span class="n">other</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">def</span> <span class="nf">__eq__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o">==</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__lt__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__le__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><=</span> <span class="n">o</span><span class="p">)</span> </div> <div class="viewcode-block" id="DocumentSignature"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.DocumentSignature">[docs]</a><span class="k">class</span> <span class="nc">DocumentSignature</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Directory signature of a v3 network status document.</span> <span class="sd"> :var str method: algorithm used to make the signature</span> <span class="sd"> :var str identity: fingerprint of the authority that made the signature</span> <span class="sd"> :var str key_digest: digest of the signing key</span> <span class="sd"> :var str signature: document signature</span> <span class="sd"> :param bool validate: checks validity if **True**</span> <span class="sd"> :raises: **ValueError** if a validity check fails</span> <span class="sd"> """</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">method</span><span class="p">,</span> <span class="n">identity</span><span class="p">,</span> <span class="n">key_digest</span><span class="p">,</span> <span class="n">signature</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="c"># Checking that these attributes are valid. Technically the key</span> <span class="c"># digest isn't a fingerprint, but it has the same characteristics.</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">identity</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Malformed fingerprint (</span><span class="si">%s</span><span class="s">) in the document signature"</span> <span class="o">%</span> <span class="n">identity</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">key_digest</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Malformed key digest (</span><span class="si">%s</span><span class="s">) in the document signature"</span> <span class="o">%</span> <span class="n">key_digest</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">method</span> <span class="bp">self</span><span class="o">.</span><span class="n">identity</span> <span class="o">=</span> <span class="n">identity</span> <span class="bp">self</span><span class="o">.</span><span class="n">key_digest</span> <span class="o">=</span> <span class="n">key_digest</span> <span class="bp">self</span><span class="o">.</span><span class="n">signature</span> <span class="o">=</span> <span class="n">signature</span> <span class="k">def</span> <span class="nf">_compare</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="n">method</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">DocumentSignature</span><span class="p">):</span> <span class="k">return</span> <span class="bp">False</span> <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="p">(</span><span class="s">"method"</span><span class="p">,</span> <span class="s">"identity"</span><span class="p">,</span> <span class="s">"key_digest"</span><span class="p">,</span> <span class="s">"signature"</span><span class="p">):</span> <span class="k">if</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">attr</span><span class="p">):</span> <span class="k">return</span> <span class="n">method</span><span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">),</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">attr</span><span class="p">))</span> <span class="k">return</span> <span class="n">method</span><span class="p">(</span><span class="bp">True</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> <span class="c"># we're equal</span> <span class="k">def</span> <span class="nf">__eq__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o">==</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__lt__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><</span> <span class="n">o</span><span class="p">)</span> <span class="k">def</span> <span class="nf">__le__</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="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_compare</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">,</span> <span class="n">o</span><span class="p">:</span> <span class="n">s</span> <span class="o"><=</span> <span class="n">o</span><span class="p">)</span> </div> <div class="viewcode-block" id="BridgeNetworkStatusDocument"><a class="viewcode-back" href="../../../api/descriptor/networkstatus.html#stem.descriptor.networkstatus.BridgeNetworkStatusDocument">[docs]</a><span class="k">class</span> <span class="nc">BridgeNetworkStatusDocument</span><span class="p">(</span><span class="n">NetworkStatusDocument</span><span class="p">):</span> <span class="sd">"""</span> <span class="sd"> Network status document containing bridges. This is only available through</span> <span class="sd"> the metrics site.</span> <span class="sd"> :var tuple routers: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV2`</span> <span class="sd"> contained in the document</span> <span class="sd"> :var datetime published: time when the document was published</span> <span class="sd"> """</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">raw_content</span><span class="p">,</span> <span class="n">validate</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span> <span class="nb">super</span><span class="p">(</span><span class="n">BridgeNetworkStatusDocument</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">published</span> <span class="o">=</span> <span class="bp">None</span> <span class="n">document_file</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">raw_content</span><span class="p">)</span> <span class="n">published_line</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">document_file</span><span class="o">.</span><span class="n">readline</span><span class="p">())</span> <span class="k">if</span> <span class="n">published_line</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"published "</span><span class="p">):</span> <span class="n">published_line</span> <span class="o">=</span> <span class="n">published_line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">" "</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">strip</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">published</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">published_line</span><span class="p">,</span> <span class="s">"%Y-%m-</span><span class="si">%d</span><span class="s"> %H:%M:%S"</span><span class="p">)</span> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">if</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Bridge network status document's 'published' time wasn't parsable: </span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">published_line</span><span class="p">)</span> <span class="k">elif</span> <span class="n">validate</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">"Bridge network status documents must start with a 'published' line:</span><span class="se">\n</span><span class="si">%s</span><span class="s">"</span> <span class="o">%</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">raw_content</span><span class="p">))</span> <span class="n">router_iter</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span> <span class="n">document_file</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">entry_class</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV2</span><span class="p">,</span> <span class="n">extra_args</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">,),</span> <span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">routers</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">desc</span><span class="o">.</span><span class="n">fingerprint</span><span class="p">,</span> <span class="n">desc</span><span class="p">)</span> <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">router_iter</span><span class="p">)</span></div> </pre></div> </div> <div class="bottomnav"> </div> <div class="footer"> </div> </body> </html>