<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=The_Principia_Machina%2FTPC-PY_tools%2Fverify_tpc_py.py</id>
	<title>The Principia Machina/TPC-PY tools/verify tpc py.py - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://invarians.org/index.php?action=history&amp;feed=atom&amp;title=The_Principia_Machina%2FTPC-PY_tools%2Fverify_tpc_py.py"/>
	<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY_tools/verify_tpc_py.py&amp;action=history"/>
	<updated>2026-10-21T06:41:10Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY_tools/verify_tpc_py.py&amp;diff=4935&amp;oldid=prev</id>
		<title>BFP Rauch: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY_tools/verify_tpc_py.py&amp;diff=4935&amp;oldid=prev"/>
		<updated>2026-09-30T02:11:06Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:11, 30 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key pma_cutover_20261020t051351z-soft_:diff:1.41:old-4934:rev-4935 --&gt;
&lt;/table&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
	<entry>
		<id>https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY_tools/verify_tpc_py.py&amp;diff=4934&amp;oldid=prev</id>
		<title>BFP Rauch: verify_tpc_py.py 0.3.0, SHA-256 06d6f21b8d73e04ef8d6dfd9edc0bc2fe70b9cfde983d7e4bbd7d4eb8c3987b5, published outside the TPC-PY tree</title>
		<link rel="alternate" type="text/html" href="https://invarians.org/index.php?title=The_Principia_Machina/TPC-PY_tools/verify_tpc_py.py&amp;diff=4934&amp;oldid=prev"/>
		<updated>2026-09-30T02:10:58Z</updated>

		<summary type="html">&lt;p&gt;verify_tpc_py.py 0.3.0, SHA-256 06d6f21b8d73e04ef8d6dfd9edc0bc2fe70b9cfde983d7e4bbd7d4eb8c3987b5, published outside the TPC-PY tree&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;# -*- coding: utf-8 -*-&lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;verify_tpc_py 0.3.0: check a TPC-PY download against its digests (CO-8;&lt;br /&gt;
TPS 5.11.9; PMP-TPM TPC: &amp;quot;An agent verifies the digest before running it&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
0.3.0 (agent TR, 2026-09-28; TPC-PY 0.2.0&amp;#039;s release): with --fetch or&lt;br /&gt;
--index, --expect-tps V and --expect-version L also check the index&lt;br /&gt;
page&amp;#039;s entry (TPS 5.11.9: version and conformed TPS version): its lines&lt;br /&gt;
&amp;quot;* Conformed TPS version: V&amp;quot; and &amp;quot;* TPC-PY version: L (...)&amp;quot; (the latter&lt;br /&gt;
written by build_tpc_py_pages 0.3.0 with --version-label; an index&lt;br /&gt;
without it fails --expect-version). The index&amp;#039;s status line is printed.&lt;br /&gt;
Everything else is 0.2.0&amp;#039;s.&lt;br /&gt;
&lt;br /&gt;
Three ways to run it:&lt;br /&gt;
  python3 verify_tpc_py.py DIR [--manifest tpc_py_manifest.json |&lt;br /&gt;
                               --index INDEX_WIKITEXT] [--expect-tree HEX]&lt;br /&gt;
      checks the files already in DIR (a folder laid out as tpc/); with&lt;br /&gt;
      neither --manifest nor --index, every file found in DIR is listed and&lt;br /&gt;
      only the tree digest checks them (so give --expect-tree).&lt;br /&gt;
      [--expect-tps V] [--expect-version L] with --index or --fetch.&lt;br /&gt;
  python3 verify_tpc_py.py --sums SHA256SUMS DIR&lt;br /&gt;
      checks every file a sha256sum-form list names, relative to DIR (for&lt;br /&gt;
      a whole kit, tpc_php/ included); no tree digest.&lt;br /&gt;
  python3 verify_tpc_py.py --fetch INDEX_PHP_URL DIR [--expect-tree HEX]&lt;br /&gt;
      reads the index page &amp;quot;The Principia Machina/TPC-PY&amp;quot; and every source&lt;br /&gt;
      page it lists as raw text (INDEX_PHP_URL?title=...&amp;amp;action=raw), saves&lt;br /&gt;
      each under its path in DIR (which must be empty or absent), then&lt;br /&gt;
      checks them. INDEX_PHP_URL is the wiki&amp;#039;s index.php, for example&lt;br /&gt;
      https://invarians.org/w/index.php (VERIFY the path on the host). A&lt;br /&gt;
      file the index lists under &amp;quot;Files kept in pages&amp;quot; is fetched from its&lt;br /&gt;
      numbered pages &amp;lt;title&amp;gt;/1, /2, ... and joined in order.&lt;br /&gt;
&lt;br /&gt;
The expected SHA-256 of each file comes from the manifest JSON the build&lt;br /&gt;
wrote, or from the index page&amp;#039;s manifest block (&amp;lt;pre&amp;gt;, sha256sum form).&lt;br /&gt;
The tree digest is computed over the files the manifest lists, under the&lt;br /&gt;
convention the index page states: SHA-256 over the netstring encoding&lt;br /&gt;
(TPS 2.5.10) of [&amp;quot;TPC-PY-TREE&amp;quot;, &amp;quot;1&amp;quot;, path_1, sha256_1, ...], paths&lt;br /&gt;
relative to tpc/ with &amp;quot;/&amp;quot; separators, in code-point order. A manifest read&lt;br /&gt;
from the same wiki proves only that the pages agree with each other; the&lt;br /&gt;
anchor is the tree digest H-DECL declares for the version (TPS 5.11.9):&lt;br /&gt;
pass it as --expect-tree, or compare the printed value with the&lt;br /&gt;
declaration by eye.&lt;br /&gt;
&lt;br /&gt;
Exit 0 only when every listed file is present with its SHA-256, no file in&lt;br /&gt;
DIR is unlisted (__pycache__ and *.pyc ignored), and, when --expect-tree is&lt;br /&gt;
given, the tree digest equals it. Standard library only; Python 3.8+;&lt;br /&gt;
Windows and Linux (files are read and written as bytes, so no line-end&lt;br /&gt;
translation touches them).&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
import hashlib&lt;br /&gt;
import json&lt;br /&gt;
import os&lt;br /&gt;
import re&lt;br /&gt;
import sys&lt;br /&gt;
import urllib.parse&lt;br /&gt;
import urllib.request&lt;br /&gt;
&lt;br /&gt;
VERSION = &amp;quot;0.3.0&amp;quot;&lt;br /&gt;
BASE = &amp;quot;The Principia Machina/TPC-PY&amp;quot;&lt;br /&gt;
TAG, FORM = &amp;quot;TPC-PY-TREE&amp;quot;, &amp;quot;1&amp;quot;&lt;br /&gt;
LINE = re.compile(r&amp;quot;^([0-9a-f]{64})  (\S+)$&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def netstring_digest(fields):&lt;br /&gt;
    h = hashlib.sha256()&lt;br /&gt;
    for f in fields:&lt;br /&gt;
        b = f.encode(&amp;quot;utf-8&amp;quot;)&lt;br /&gt;
        h.update(str(len(b)).encode(&amp;quot;ascii&amp;quot;) + b&amp;quot;:&amp;quot; + b)&lt;br /&gt;
    return h.hexdigest()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def tree_digest(entries):&lt;br /&gt;
    fields = [TAG, FORM]&lt;br /&gt;
    for path, sha in sorted(entries):&lt;br /&gt;
        fields += [path, sha]&lt;br /&gt;
    return netstring_digest(fields)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def manifest_from_index(text):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;The &amp;lt;pre&amp;gt; block under &amp;quot;== Manifest ==&amp;quot;: one &amp;quot;sha256  path&amp;quot; per line.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    m = re.search(r&amp;quot;== Manifest ==\s*&amp;lt;pre&amp;gt;\n(.*?)\n&amp;lt;/pre&amp;gt;&amp;quot;, text, re.S)&lt;br /&gt;
    if not m:&lt;br /&gt;
        raise ValueError(&amp;quot;the index text holds no manifest block&amp;quot;)&lt;br /&gt;
    out = []&lt;br /&gt;
    for ln in m.group(1).split(&amp;quot;\n&amp;quot;):&lt;br /&gt;
        mm = LINE.match(ln)&lt;br /&gt;
        if not mm:&lt;br /&gt;
            raise ValueError(&amp;quot;not a manifest line: %r&amp;quot; % ln[:80])&lt;br /&gt;
        out.append((mm.group(2), mm.group(1)))&lt;br /&gt;
    return out&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def pages_from_index(text):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;The &amp;lt;pre&amp;gt; block under &amp;quot;== Files kept in pages ==&amp;quot;, if any: one&lt;br /&gt;
    &amp;quot;n  path&amp;quot; per line (the file is the n numbered pages joined).&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    m = re.search(r&amp;quot;== Files kept in pages ==.*?&amp;lt;pre&amp;gt;\n(.*?)\n&amp;lt;/pre&amp;gt;&amp;quot;, text, re.S)&lt;br /&gt;
    out = {}&lt;br /&gt;
    if m:&lt;br /&gt;
        for ln in m.group(1).split(&amp;quot;\n&amp;quot;):&lt;br /&gt;
            mm = re.match(r&amp;quot;^([1-9][0-9]{0,3})  (\S+)$&amp;quot;, ln)&lt;br /&gt;
            if not mm:&lt;br /&gt;
                raise ValueError(&amp;quot;not a pages line: %r&amp;quot; % ln[:80])&lt;br /&gt;
            out[mm.group(2)] = int(mm.group(1))&lt;br /&gt;
    return out&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def index_entry(text):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;The index&amp;#039;s status line, conformed TPS version and TPC-PY version.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    st = re.search(r&amp;quot;^&amp;#039;{3}Status: (.*?)&amp;#039;{3}&amp;quot;, text, re.M)&lt;br /&gt;
    tps = re.search(r&amp;quot;^\* Conformed TPS version: (\S+)$&amp;quot;, text, re.M)&lt;br /&gt;
    ver = re.search(r&amp;quot;^\* TPC-PY version: (\S+) \((proposed|declared)\)$&amp;quot;, text, re.M)&lt;br /&gt;
    return (st.group(1) if st else None, tps.group(1) if tps else None,&lt;br /&gt;
            (ver.group(1), ver.group(2)) if ver else None)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def entry_check(text, opt):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;--expect-tps and --expect-version against the index; True if every&lt;br /&gt;
    expectation given holds.&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    st, tps, ver = index_entry(text)&lt;br /&gt;
    print(&amp;quot;index: status %s; conformed TPS %s; TPC-PY version %s&amp;quot; % (&lt;br /&gt;
        st or &amp;quot;-&amp;quot;, tps or &amp;quot;-&amp;quot;, (&amp;quot;%s (%s)&amp;quot; % ver) if ver else &amp;quot;-&amp;quot;))&lt;br /&gt;
    ok = True&lt;br /&gt;
    if opt.get(&amp;quot;--expect-tps&amp;quot;) is not None:&lt;br /&gt;
        if tps == opt[&amp;quot;--expect-tps&amp;quot;]:&lt;br /&gt;
            print(&amp;quot;conformed TPS version equals the expected value&amp;quot;)&lt;br /&gt;
        else:&lt;br /&gt;
            print(&amp;quot;CONFORMED TPS VERSION DIFFERS from the expected %s&amp;quot; % opt[&amp;quot;--expect-tps&amp;quot;])&lt;br /&gt;
            ok = False&lt;br /&gt;
    if opt.get(&amp;quot;--expect-version&amp;quot;) is not None:&lt;br /&gt;
        if ver and ver[0] == opt[&amp;quot;--expect-version&amp;quot;]:&lt;br /&gt;
            print(&amp;quot;TPC-PY version equals the expected value&amp;quot;)&lt;br /&gt;
        else:&lt;br /&gt;
            print(&amp;quot;TPC-PY VERSION DIFFERS from the expected %s&amp;quot; % opt[&amp;quot;--expect-version&amp;quot;])&lt;br /&gt;
            ok = False&lt;br /&gt;
    return ok&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def sums_list(path):&lt;br /&gt;
    out = []&lt;br /&gt;
    for ln in open(path, encoding=&amp;quot;utf-8&amp;quot;).read().splitlines():&lt;br /&gt;
        if not ln.strip():&lt;br /&gt;
            continue&lt;br /&gt;
        mm = re.match(r&amp;quot;^([0-9a-f]{64}) [ *](\S+)$&amp;quot;, ln)&lt;br /&gt;
        if not mm:&lt;br /&gt;
            raise ValueError(&amp;quot;not a sha256sum line: %r&amp;quot; % ln[:80])&lt;br /&gt;
        out.append((mm.group(2), mm.group(1)))&lt;br /&gt;
    return out&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def safe_path(root, rel):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;rel must be a relative path of plain segments: no &amp;quot;..&amp;quot;, no absolute&lt;br /&gt;
    path, no backslash (the listing is untrusted input).&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    if (not rel or rel.startswith(&amp;quot;/&amp;quot;) or &amp;quot;\\&amp;quot; in rel or &amp;quot;:&amp;quot; in rel&lt;br /&gt;
            or any(seg in (&amp;quot;&amp;quot;, &amp;quot;.&amp;quot;, &amp;quot;..&amp;quot;) for seg in rel.split(&amp;quot;/&amp;quot;))):&lt;br /&gt;
        raise ValueError(&amp;quot;refused path %r&amp;quot; % rel)&lt;br /&gt;
    return os.path.join(root, *rel.split(&amp;quot;/&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def fetch(url, title):&lt;br /&gt;
    q = urllib.parse.urlencode({&amp;quot;title&amp;quot;: title, &amp;quot;action&amp;quot;: &amp;quot;raw&amp;quot;})&lt;br /&gt;
    req = urllib.request.Request(url + (&amp;quot;&amp;amp;&amp;quot; if &amp;quot;?&amp;quot; in url else &amp;quot;?&amp;quot;) + q,&lt;br /&gt;
                                 headers={&amp;quot;User-Agent&amp;quot;: &amp;quot;verify_tpc_py/%s (TPM; TPC-PY check)&amp;quot; % VERSION})&lt;br /&gt;
    with urllib.request.urlopen(req, timeout=60) as r:&lt;br /&gt;
        return r.read()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def check(root, listed, expect_tree, tree=True, ignore=()):&lt;br /&gt;
    ok = True&lt;br /&gt;
    names = set()&lt;br /&gt;
    found = []&lt;br /&gt;
    for path, sha in listed:&lt;br /&gt;
        p = safe_path(root, path)&lt;br /&gt;
        names.add(path)&lt;br /&gt;
        if not os.path.isfile(p):&lt;br /&gt;
            print(&amp;quot;MISSING   %s&amp;quot; % path)&lt;br /&gt;
            ok = False&lt;br /&gt;
            continue&lt;br /&gt;
        got = hashlib.sha256(open(p, &amp;quot;rb&amp;quot;).read()).hexdigest()&lt;br /&gt;
        found.append((path, got))&lt;br /&gt;
        if got != sha:&lt;br /&gt;
            print(&amp;quot;DIFFERS   %s  expected %s  got %s&amp;quot; % (path, sha, got))&lt;br /&gt;
            ok = False&lt;br /&gt;
    for r, dirs, files in os.walk(root):&lt;br /&gt;
        dirs[:] = [d for d in dirs if d != &amp;quot;__pycache__&amp;quot;]&lt;br /&gt;
        for n in files:&lt;br /&gt;
            if n.endswith(&amp;quot;.pyc&amp;quot;):&lt;br /&gt;
                continue&lt;br /&gt;
            rel = os.path.relpath(os.path.join(r, n), root).replace(os.sep, &amp;quot;/&amp;quot;)&lt;br /&gt;
            if rel not in names and rel not in ignore:&lt;br /&gt;
                print(&amp;quot;UNLISTED  %s&amp;quot; % rel)&lt;br /&gt;
                ok = False&lt;br /&gt;
    if len(found) &amp;lt; len(listed):&lt;br /&gt;
        print(&amp;quot;files listed: %d, found: %d; tree digest not computed&amp;quot; % (len(listed), len(found)))&lt;br /&gt;
        print(&amp;quot;RESULT: FAILURES&amp;quot;)&lt;br /&gt;
        return 1&lt;br /&gt;
    if not tree:&lt;br /&gt;
        print(&amp;quot;files listed: %d; every one found&amp;quot; % len(listed))&lt;br /&gt;
        print(&amp;quot;RESULT:&amp;quot;, &amp;quot;ALL MATCH&amp;quot; if ok else &amp;quot;FAILURES&amp;quot;)&lt;br /&gt;
        return 0 if ok else 1&lt;br /&gt;
    td = tree_digest(found)       # over the files as found, not as listed&lt;br /&gt;
    print(&amp;quot;files listed: %d; tree digest of the files found: %s&amp;quot; % (len(listed), td))&lt;br /&gt;
    if expect_tree:&lt;br /&gt;
        if td == expect_tree.lower():&lt;br /&gt;
            print(&amp;quot;tree digest equals the expected value&amp;quot;)&lt;br /&gt;
        else:&lt;br /&gt;
            print(&amp;quot;TREE DIGEST DIFFERS from the expected %s&amp;quot; % expect_tree)&lt;br /&gt;
            ok = False&lt;br /&gt;
    print(&amp;quot;RESULT:&amp;quot;, &amp;quot;ALL MATCH&amp;quot; if ok else &amp;quot;FAILURES&amp;quot;)&lt;br /&gt;
    return 0 if ok else 1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def main(argv):&lt;br /&gt;
    a = argv[1:]&lt;br /&gt;
    opt = {}&lt;br /&gt;
    pos = []&lt;br /&gt;
    i = 0&lt;br /&gt;
    while i &amp;lt; len(a):&lt;br /&gt;
        if a[i] in (&amp;quot;--manifest&amp;quot;, &amp;quot;--index&amp;quot;, &amp;quot;--expect-tree&amp;quot;, &amp;quot;--fetch&amp;quot;, &amp;quot;--sums&amp;quot;,&lt;br /&gt;
                    &amp;quot;--expect-tps&amp;quot;, &amp;quot;--expect-version&amp;quot;):&lt;br /&gt;
            if i + 1 &amp;gt;= len(a):&lt;br /&gt;
                sys.exit(&amp;quot;missing value for %s&amp;quot; % a[i])&lt;br /&gt;
            opt[a[i]] = a[i + 1]&lt;br /&gt;
            i += 2&lt;br /&gt;
        else:&lt;br /&gt;
            pos.append(a[i])&lt;br /&gt;
            i += 1&lt;br /&gt;
    if len(pos) != 1:&lt;br /&gt;
        sys.exit(__doc__.split(&amp;quot;Three ways to run it:&amp;quot;)[1].split(&amp;quot;The expected&amp;quot;)[0])&lt;br /&gt;
    root = pos[0]&lt;br /&gt;
    entry_ok = True&lt;br /&gt;
    if (&amp;quot;--expect-tps&amp;quot; in opt or &amp;quot;--expect-version&amp;quot; in opt) and not (&lt;br /&gt;
            &amp;quot;--fetch&amp;quot; in opt or &amp;quot;--index&amp;quot; in opt):&lt;br /&gt;
        sys.exit(&amp;quot;--expect-tps and --expect-version need --fetch or --index&amp;quot;)&lt;br /&gt;
    if &amp;quot;--sums&amp;quot; in opt:&lt;br /&gt;
        rel = os.path.relpath(os.path.abspath(opt[&amp;quot;--sums&amp;quot;]), os.path.abspath(root))&lt;br /&gt;
        return check(root, sums_list(opt[&amp;quot;--sums&amp;quot;]), None, tree=False,&lt;br /&gt;
                     ignore=(rel.replace(os.sep, &amp;quot;/&amp;quot;),))&lt;br /&gt;
    if &amp;quot;--fetch&amp;quot; in opt:&lt;br /&gt;
        url = opt[&amp;quot;--fetch&amp;quot;]&lt;br /&gt;
        if os.path.exists(root) and os.listdir(root):&lt;br /&gt;
            sys.exit(&amp;quot;refused: %s is not empty&amp;quot; % root)&lt;br /&gt;
        index = fetch(url, BASE).decode(&amp;quot;utf-8&amp;quot;)&lt;br /&gt;
        entry_ok = entry_check(index, opt)&lt;br /&gt;
        listed = manifest_from_index(index)&lt;br /&gt;
        split = pages_from_index(index)&lt;br /&gt;
        n = 0&lt;br /&gt;
        for path, _ in listed:&lt;br /&gt;
            p = safe_path(root, path)&lt;br /&gt;
            os.makedirs(os.path.dirname(p) or &amp;quot;.&amp;quot;, exist_ok=True)&lt;br /&gt;
            if path in split:&lt;br /&gt;
                data = b&amp;quot;&amp;quot;.join(fetch(url, &amp;quot;%s/%s/%d&amp;quot; % (BASE, path, k))&lt;br /&gt;
                                for k in range(1, split[path] + 1))&lt;br /&gt;
                n += split[path]&lt;br /&gt;
            else:&lt;br /&gt;
                data = fetch(url, BASE + &amp;quot;/&amp;quot; + path)&lt;br /&gt;
                n += 1&lt;br /&gt;
            with open(p, &amp;quot;wb&amp;quot;) as f:&lt;br /&gt;
                f.write(data)&lt;br /&gt;
        print(&amp;quot;fetched the index and %d pages (%d files) into %s&amp;quot; % (n, len(listed), root))&lt;br /&gt;
    elif &amp;quot;--manifest&amp;quot; in opt:&lt;br /&gt;
        m = json.load(open(opt[&amp;quot;--manifest&amp;quot;], encoding=&amp;quot;utf-8&amp;quot;))&lt;br /&gt;
        listed = [(f[&amp;quot;path&amp;quot;], f[&amp;quot;sha256&amp;quot;]) for f in m[&amp;quot;files&amp;quot;]]&lt;br /&gt;
        if m.get(&amp;quot;tree_digest&amp;quot;) and not opt.get(&amp;quot;--expect-tree&amp;quot;):&lt;br /&gt;
            print(&amp;quot;manifest&amp;#039;s tree digest: %s (not the declared value unless it matches&amp;quot;&lt;br /&gt;
                  &amp;quot; the declaration)&amp;quot; % m[&amp;quot;tree_digest&amp;quot;])&lt;br /&gt;
    elif &amp;quot;--index&amp;quot; in opt:&lt;br /&gt;
        index = open(opt[&amp;quot;--index&amp;quot;], encoding=&amp;quot;utf-8&amp;quot;).read()&lt;br /&gt;
        entry_ok = entry_check(index, opt)&lt;br /&gt;
        listed = manifest_from_index(index)&lt;br /&gt;
    else:&lt;br /&gt;
        listed = []&lt;br /&gt;
        for r, dirs, files in os.walk(root):&lt;br /&gt;
            dirs[:] = [d for d in dirs if d != &amp;quot;__pycache__&amp;quot;]&lt;br /&gt;
            for n in files:&lt;br /&gt;
                if not n.endswith(&amp;quot;.pyc&amp;quot;):&lt;br /&gt;
                    p = os.path.join(r, n)&lt;br /&gt;
                    listed.append((os.path.relpath(p, root).replace(os.sep, &amp;quot;/&amp;quot;),&lt;br /&gt;
                                   hashlib.sha256(open(p, &amp;quot;rb&amp;quot;).read()).hexdigest()))&lt;br /&gt;
        print(&amp;quot;no manifest given: every file of %s listed as found&amp;quot; % root)&lt;br /&gt;
    rc = check(root, listed, opt.get(&amp;quot;--expect-tree&amp;quot;))&lt;br /&gt;
    if not entry_ok:&lt;br /&gt;
        print(&amp;quot;RESULT: FAILURES (the index&amp;#039;s entry)&amp;quot;)&lt;br /&gt;
        return 1&lt;br /&gt;
    return rc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
    sys.exit(main(sys.argv))&lt;br /&gt;
&lt;br /&gt;
# END OF ARTIFACT --- verify_tpc_py 0.3.0&lt;br /&gt;
# If this line is absent, the payload arrived truncated.&lt;br /&gt;
&lt;/div&gt;</summary>
		<author><name>BFP Rauch</name></author>
	</entry>
</feed>