primarysource 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- primarysource/__init__.py +5 -0
- primarysource/bbf/__init__.py +56 -0
- primarysource/bbf/_xml.py +63 -0
- primarysource/bbf/catalogue.json +777 -0
- primarysource/bbf/catalogue.py +137 -0
- primarysource/bbf/cli.py +79 -0
- primarysource/bbf/datamodel.py +281 -0
- primarysource/bbf/importer.py +151 -0
- primarysource/bbf/library.py +380 -0
- primarysource/bbf/server.py +72 -0
- primarysource/budget.py +63 -0
- primarysource/c2sp/__init__.py +53 -0
- primarysource/c2sp/_fetch.py +5 -0
- primarysource/c2sp/catalogue.json +231 -0
- primarysource/c2sp/catalogue.py +95 -0
- primarysource/c2sp/cli.py +62 -0
- primarysource/c2sp/importer.py +90 -0
- primarysource/c2sp/library.py +309 -0
- primarysource/c2sp/markdown.py +31 -0
- primarysource/c2sp/server.py +68 -0
- primarysource/cavp/__init__.py +42 -0
- primarysource/cavp/cli.py +84 -0
- primarysource/cavp/data/vectors.toml +47 -0
- primarysource/cavp/importer.py +156 -0
- primarysource/cavp/model.py +279 -0
- primarysource/cavp/parse.py +269 -0
- primarysource/cavp/paths.py +17 -0
- primarysource/cavp/server.py +67 -0
- primarysource/cavp/tools.py +169 -0
- primarysource/cli.py +107 -0
- primarysource/cursor.py +82 -0
- primarysource/cve/__init__.py +5 -0
- primarysource/cve/__main__.py +6 -0
- primarysource/cve/cli.py +144 -0
- primarysource/cve/collection.py +20 -0
- primarysource/cve/config.py +58 -0
- primarysource/cve/errors.py +16 -0
- primarysource/cve/kernel.py +232 -0
- primarysource/cve/mcp.py +139 -0
- primarysource/cve/parse.py +318 -0
- primarysource/cve/py.typed +0 -0
- primarysource/cve/service.py +760 -0
- primarysource/cve/store.py +214 -0
- primarysource/cve/sync.py +438 -0
- primarysource/cve/views.py +304 -0
- primarysource/debpolicy/__init__.py +16 -0
- primarysource/debpolicy/catalogue.py +263 -0
- primarysource/debpolicy/cli.py +12 -0
- primarysource/debpolicy/server.py +11 -0
- primarysource/draft/__init__.py +11 -0
- primarysource/draft/catalogue.py +117 -0
- primarysource/draft/cli.py +149 -0
- primarysource/draft/collection.py +21 -0
- primarysource/draft/datatracker.py +158 -0
- primarysource/draft/importer.py +163 -0
- primarysource/draft/licence.py +89 -0
- primarysource/draft/names.py +64 -0
- primarysource/draft/net.py +133 -0
- primarysource/draft/segment.py +192 -0
- primarysource/draft/server.py +91 -0
- primarysource/draft/status.py +146 -0
- primarysource/draft/store.py +199 -0
- primarysource/draft/tracked.json +104 -0
- primarysource/draft/views.py +430 -0
- primarysource/draft/xmlmeta.py +74 -0
- primarysource/ecma/__init__.py +52 -0
- primarysource/ecma/_pdf.py +143 -0
- primarysource/ecma/catalogue.json +22 -0
- primarysource/ecma/catalogue.py +100 -0
- primarysource/ecma/cli.py +67 -0
- primarysource/ecma/identify.py +25 -0
- primarysource/ecma/importer.py +108 -0
- primarysource/ecma/library.py +240 -0
- primarysource/ecma/server.py +67 -0
- primarysource/errors.py +29 -0
- primarysource/fetch.py +360 -0
- primarysource/fsutil.py +150 -0
- primarysource/gitdocs/__init__.py +15 -0
- primarysource/gitdocs/catalogue.py +116 -0
- primarysource/gitdocs/cli.py +12 -0
- primarysource/gitdocs/server.py +8 -0
- primarysource/home.py +65 -0
- primarysource/iana/__init__.py +32 -0
- primarysource/iana/catalogue.json +244 -0
- primarysource/iana/catalogue.py +69 -0
- primarysource/iana/cli.py +69 -0
- primarysource/iana/importer.py +157 -0
- primarysource/iana/model.py +325 -0
- primarysource/iana/reader.py +315 -0
- primarysource/iana/server.py +67 -0
- primarysource/iana/store.py +83 -0
- primarysource/iana/xmlsafe.py +47 -0
- primarysource/identify.py +186 -0
- primarysource/ieee/__init__.py +58 -0
- primarysource/ieee/_html.py +49 -0
- primarysource/ieee/catalogue.json +74 -0
- primarysource/ieee/catalogue.py +123 -0
- primarysource/ieee/cli.py +79 -0
- primarysource/ieee/identify.py +24 -0
- primarysource/ieee/ieee802.py +47 -0
- primarysource/ieee/importer.py +305 -0
- primarysource/ieee/posix.py +233 -0
- primarysource/ieee/server.py +79 -0
- primarysource/index.py +446 -0
- primarysource/iso/__init__.py +51 -0
- primarysource/iso/cli.py +98 -0
- primarysource/iso/designation.py +95 -0
- primarysource/iso/identify.py +100 -0
- primarysource/iso/importer.py +224 -0
- primarysource/iso/library.py +249 -0
- primarysource/iso/server.py +69 -0
- primarysource/itu/__init__.py +41 -0
- primarysource/itu/__main__.py +8 -0
- primarysource/itu/asn1mod.py +478 -0
- primarysource/itu/catalog.py +472 -0
- primarysource/itu/cli.py +445 -0
- primarysource/itu/collection.py +20 -0
- primarysource/itu/corpus.py +118 -0
- primarysource/itu/errata.py +16 -0
- primarysource/itu/formal.py +565 -0
- primarysource/itu/identify.py +26 -0
- primarysource/itu/index.py +490 -0
- primarysource/itu/mcp.py +474 -0
- primarysource/itu/py.typed +0 -0
- primarysource/itu/sources.py +600 -0
- primarysource/itu/text.py +609 -0
- primarysource/kconfig/__init__.py +16 -0
- primarysource/kconfig/catalogue.py +98 -0
- primarysource/kconfig/cli.py +12 -0
- primarysource/kconfig/server.py +8 -0
- primarysource/model.py +63 -0
- primarysource/nist/__init__.py +5 -0
- primarysource/nist/collection.py +46 -0
- primarysource/nist/data/acquired-nist.json +1657 -0
- primarysource/nist/data/nist-catalog.json +12090 -0
- primarysource/nist/data/sources.toml +1996 -0
- primarysource/nist/identify.py +41 -0
- primarysource/nist/ingest/__init__.py +1 -0
- primarysource/nist/ingest/acquire_nist.py +128 -0
- primarysource/nist/ingest/controls.py +82 -0
- primarysource/nist/ingest/discover_nist.py +218 -0
- primarysource/nist/ingest/extract.py +48 -0
- primarysource/nist/ingest/fetch.py +211 -0
- primarysource/nist/ingest/index.py +14 -0
- primarysource/nist/ingest/oscal.py +480 -0
- primarysource/nist/ingest/prose_layouts.py +236 -0
- primarysource/nist/ingest/sources.py +94 -0
- primarysource/nist/ingest/status.py +255 -0
- primarysource/nist/models.py +7 -0
- primarysource/nist/paths.py +33 -0
- primarysource/nist/server/__init__.py +3 -0
- primarysource/nist/server/corpus.py +38 -0
- primarysource/nist/server/mcp.py +19 -0
- primarysource/nist/server/tools.py +35 -0
- primarysource/nist/spec.py +38 -0
- primarysource/pdfcorpus/__init__.py +16 -0
- primarysource/pdfcorpus/corpus.py +159 -0
- primarysource/pdfcorpus/fts.py +175 -0
- primarysource/pdfcorpus/index.py +70 -0
- primarysource/pdfcorpus/models.py +30 -0
- primarysource/pdfcorpus/server.py +96 -0
- primarysource/pdfcorpus/spec.py +37 -0
- primarysource/pdfcorpus/split.py +391 -0
- primarysource/pdfcorpus/tools.py +244 -0
- primarysource/pep/__init__.py +15 -0
- primarysource/pep/catalogue.py +191 -0
- primarysource/pep/cli.py +12 -0
- primarysource/pep/server.py +8 -0
- primarysource/pkgdocs/__init__.py +19 -0
- primarysource/pkgdocs/fetch.py +356 -0
- primarysource/pkgdocs/index.py +89 -0
- primarysource/pkgdocs/model.py +76 -0
- primarysource/pkgdocs/readers/__init__.py +1 -0
- primarysource/pkgdocs/readers/_common.py +134 -0
- primarysource/pkgdocs/readers/asciidoc.py +160 -0
- primarysource/pkgdocs/readers/latex.py +315 -0
- primarysource/pkgdocs/readers/markdown.py +173 -0
- primarysource/pkgdocs/readers/pod.py +132 -0
- primarysource/pkgdocs/readers/rst.py +239 -0
- primarysource/pkgdocs/readers/scdoc.py +108 -0
- primarysource/pkgdocs/runtime.py +552 -0
- primarysource/pkgdocs/serving.py +158 -0
- primarysource/pkgdocs/store.py +167 -0
- primarysource/pms/__init__.py +16 -0
- primarysource/pms/catalogue.py +88 -0
- primarysource/pms/cli.py +12 -0
- primarysource/pms/server.py +8 -0
- primarysource/py.typed +0 -0
- primarysource/readers/__init__.py +10 -0
- primarysource/readers/bookmarks.py +192 -0
- primarysource/readers/html.py +1312 -0
- primarysource/readers/markdown.py +189 -0
- primarysource/readers/pdf.py +187 -0
- primarysource/readers/xml.py +230 -0
- primarysource/refs.py +87 -0
- primarysource/registry.py +161 -0
- primarysource/render.py +49 -0
- primarysource/rfc/__init__.py +3 -0
- primarysource/rfc/__main__.py +6 -0
- primarysource/rfc/cite.py +204 -0
- primarysource/rfc/cli.py +903 -0
- primarysource/rfc/collection.py +19 -0
- primarysource/rfc/config.py +138 -0
- primarysource/rfc/errata.py +203 -0
- primarysource/rfc/fsutil.py +82 -0
- primarysource/rfc/graph.py +213 -0
- primarysource/rfc/index/__init__.py +1 -0
- primarysource/rfc/index/chunker.py +281 -0
- primarysource/rfc/index/embed.py +166 -0
- primarysource/rfc/index/hybrid.py +305 -0
- primarysource/rfc/index/lexical.py +223 -0
- primarysource/rfc/index/rfcxml.py +673 -0
- primarysource/rfc/index/search.py +508 -0
- primarysource/rfc/index/txtseg.py +585 -0
- primarysource/rfc/library.py +294 -0
- primarysource/rfc/mcp/__init__.py +1 -0
- primarysource/rfc/mcp/server.py +381 -0
- primarysource/rfc/packs/__init__.py +1 -0
- primarysource/rfc/packs/builder.py +228 -0
- primarysource/rfc/packs/collections/all-current-txt.json +10 -0
- primarysource/rfc/packs/collections/essentials.json +19 -0
- primarysource/rfc/packs/collections/fyi-current.json +10 -0
- primarysource/rfc/packs/collections/standards-current.json +10 -0
- primarysource/rfc/packs/collections/year-2025.json +10 -0
- primarysource/rfc/packs/collections/year-2026.json +10 -0
- primarysource/rfc/packs/collections.py +163 -0
- primarysource/rfc/packs/docsetexport.py +163 -0
- primarysource/rfc/packs/epub.py +159 -0
- primarysource/rfc/packs/export.py +306 -0
- primarysource/rfc/packs/htmlexport.py +82 -0
- primarysource/rfc/packs/serve.py +143 -0
- primarysource/rfc/packs/zimexport.py +171 -0
- primarysource/rfc/query.py +466 -0
- primarysource/rfc/subjects.py +457 -0
- primarysource/rfc/sync/__init__.py +1 -0
- primarysource/rfc/sync/downloader.py +132 -0
- primarysource/rfc/sync/manifest.py +162 -0
- primarysource/rfc/sync/scanner.py +49 -0
- primarysource/rfc/sync/state.py +464 -0
- primarysource/rfc/views.py +1067 -0
- primarysource/rpmdocs/__init__.py +15 -0
- primarysource/rpmdocs/catalogue.py +117 -0
- primarysource/rpmdocs/cli.py +12 -0
- primarysource/rpmdocs/server.py +8 -0
- primarysource/scaffold.py +223 -0
- primarysource/serve.py +75 -0
- primarysource/settings.py +152 -0
- primarysource/usb/__init__.py +5 -0
- primarysource/usb/collection.py +37 -0
- primarysource/usb/data/acquired.json +2025 -0
- primarysource/usb/data/sources-usb.toml +852 -0
- primarysource/usb/data/sources.toml +10 -0
- primarysource/usb/data/usb-catalog.json +1663 -0
- primarysource/usb/data/usb-classification.json +1986 -0
- primarysource/usb/data/usb-corpus-build.json +608 -0
- primarysource/usb/data/usb-pdf-choice.json +839 -0
- primarysource/usb/data/usb-split-measure.json +1803 -0
- primarysource/usb/ingest/__init__.py +1 -0
- primarysource/usb/ingest/acquire.py +130 -0
- primarysource/usb/ingest/discover_usb.py +88 -0
- primarysource/usb/ingest/extract.py +48 -0
- primarysource/usb/ingest/fetch.py +197 -0
- primarysource/usb/ingest/index.py +14 -0
- primarysource/usb/ingest/sources.py +85 -0
- primarysource/usb/models.py +7 -0
- primarysource/usb/paths.py +33 -0
- primarysource/usb/server/__init__.py +3 -0
- primarysource/usb/server/corpus.py +38 -0
- primarysource/usb/server/mcp.py +19 -0
- primarysource/usb/server/tools.py +35 -0
- primarysource/usb/spec.py +20 -0
- primarysource/usbids/__init__.py +56 -0
- primarysource/usbids/cli.py +65 -0
- primarysource/usbids/importer.py +272 -0
- primarysource/usbids/parse.py +283 -0
- primarysource/usbids/server.py +55 -0
- primarysource/usbids/store.py +80 -0
- primarysource/usbids/tools.py +174 -0
- primarysource/zim/__init__.py +5 -0
- primarysource/zim/__main__.py +8 -0
- primarysource/zim/_libzim.py +37 -0
- primarysource/zim/catalog.py +594 -0
- primarysource/zim/cli.py +555 -0
- primarysource/zim/collection.py +41 -0
- primarysource/zim/errors.py +100 -0
- primarysource/zim/groups.py +30 -0
- primarysource/zim/library.py +668 -0
- primarysource/zim/manage.py +636 -0
- primarysource/zim/markdown.py +1247 -0
- primarysource/zim/mcp.py +201 -0
- primarysource/zim/purl.py +130 -0
- primarysource/zim/py.typed +0 -0
- primarysource/zim/refs.py +90 -0
- primarysource/zim/service.py +1182 -0
- primarysource/zim/snapshot.py +197 -0
- primarysource/zim/sync.py +269 -0
- primarysource/zim/views.py +230 -0
- primarysource-0.1.0.dist-info/METADATA +118 -0
- primarysource-0.1.0.dist-info/RECORD +303 -0
- primarysource-0.1.0.dist-info/WHEEL +4 -0
- primarysource-0.1.0.dist-info/entry_points.txt +2 -0
- primarysource-0.1.0.dist-info/licenses/LICENSE +203 -0
- primarysource-0.1.0.dist-info/licenses/NOTICE +51 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""The `kconfig` collection: the kernel's Kconfig and Kbuild documents, read as reStructuredText.
|
|
2
|
+
|
|
3
|
+
Source, placement and pin (read from the repositories on 2026-11-13, see `docs/kconfig.md`):
|
|
4
|
+
|
|
5
|
+
- the tree is `Documentation/kbuild/` of torvalds/linux at the commit of the tag `v7.3`, fetched as a gitiles
|
|
6
|
+
subtree archive from kernel.googlesource.com (57 KB; the whole-repository tarball is two orders larger). The
|
|
7
|
+
documents are the twelve `.rst` files there: `kconfig-language` (the language), `kconfig-macro-language`,
|
|
8
|
+
`kconfig` (the configuration targets), `kbuild`, `makefiles`, `modules`, and the rest;
|
|
9
|
+
- the licence is GPL-2.0-only: the kernel's `COPYING` at the root says "GPL-2.0 WITH Linux-syscall-note" and
|
|
10
|
+
names the syscall note's scope as the user-space API headers, and `Documentation/process/license-rules.rst`
|
|
11
|
+
gives the kernel as "GPL version 2 only". Three of the twelve files carry an `SPDX-License-Identifier` line;
|
|
12
|
+
the build records it as the document's `licence` and records the rest as `GPL-2.0-only (COPYING, no file tag)`;
|
|
13
|
+
- placement is **layer**.
|
|
14
|
+
|
|
15
|
+
pkgtrust R165 and kconfigpy read `kconfig-language` for the grammar of a Kconfig file; refs into it are
|
|
16
|
+
`kconfig:kconfig-language§Menu entries` and, once pinned, `kconfig:kconfig-language@c03c1a14§Menu entries`.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from collections import Counter
|
|
23
|
+
from collections.abc import Mapping
|
|
24
|
+
|
|
25
|
+
from primarysource.errors import LibError
|
|
26
|
+
from primarysource.pkgdocs.fetch import Source
|
|
27
|
+
from primarysource.pkgdocs.model import Doc
|
|
28
|
+
from primarysource.pkgdocs.readers._common import decode
|
|
29
|
+
from primarysource.pkgdocs.readers.rst import read_rst
|
|
30
|
+
from primarysource.pkgdocs.runtime import Build, Licence, Pin, Spec, TreeSpec, matching
|
|
31
|
+
|
|
32
|
+
COMMIT = "c03c1a14507dfaf8b856c2608f9ac216021fc222"
|
|
33
|
+
|
|
34
|
+
PIN = Pin(
|
|
35
|
+
commit=COMMIT,
|
|
36
|
+
label="v7.3",
|
|
37
|
+
date="2026-10-18",
|
|
38
|
+
files_sha256="36d3fe2bf74fee4efef91f7a16a56297966652812e314f8122eb4e5d0cd13ecd",
|
|
39
|
+
sources=(
|
|
40
|
+
Source(
|
|
41
|
+
f"https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux/+archive/{COMMIT}/Documentation/kbuild.tar.gz",
|
|
42
|
+
strip=0,
|
|
43
|
+
),
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
LICENCE = Licence(
|
|
48
|
+
spdx="GPL-2.0-only",
|
|
49
|
+
redistribute="layer",
|
|
50
|
+
attribution="Linux kernel developers; GPL-2.0-only",
|
|
51
|
+
evidence="COPYING and Documentation/process/license-rules.rst at torvalds/linux " + COMMIT[:12],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
_SPDX = re.compile(r"SPDX-License-Identifier:\s*([^\n]+)")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def build(files: Mapping[str, bytes], pin: Pin) -> Build:
|
|
58
|
+
docs: list[Doc] = []
|
|
59
|
+
skipped: Counter[str] = Counter()
|
|
60
|
+
for path in sorted(files):
|
|
61
|
+
stem = path[: -len(".rst")]
|
|
62
|
+
try:
|
|
63
|
+
doc = read_rst(files[path], stem)
|
|
64
|
+
tag = _SPDX.search(decode(files[path], path))
|
|
65
|
+
except LibError:
|
|
66
|
+
skipped["not UTF-8 text"] += 1
|
|
67
|
+
continue
|
|
68
|
+
licence = tag.group(1).strip() if tag else "GPL-2.0-only (COPYING, no file tag)"
|
|
69
|
+
docs.append(doc.with_meta(path=f"Documentation/kbuild/{path}", licence=licence))
|
|
70
|
+
return Build(tuple(docs), {}, skipped)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
SPEC = Spec(
|
|
74
|
+
name="kconfig",
|
|
75
|
+
title="Linux Kconfig and Kbuild documentation",
|
|
76
|
+
licence=LICENCE,
|
|
77
|
+
trees=(
|
|
78
|
+
TreeSpec(
|
|
79
|
+
name="kbuild",
|
|
80
|
+
title="Documentation/kbuild/ of torvalds/linux (reStructuredText)",
|
|
81
|
+
pins=(PIN,),
|
|
82
|
+
include=matching(r"[a-z][a-z0-9_.-]*\.rst"),
|
|
83
|
+
build=build,
|
|
84
|
+
),
|
|
85
|
+
),
|
|
86
|
+
instructions=(
|
|
87
|
+
"The kernel's Kconfig language reference (kconfig-language), the macro language (kconfig-macro-language), "
|
|
88
|
+
"the configuration targets (kconfig) and the Kbuild documents (kbuild, makefiles, modules, ...) from the "
|
|
89
|
+
"user's imported copy at a pinned release. Loop: kconfig_search('<words>') -> "
|
|
90
|
+
"kconfig_outline('kconfig-language') -> kconfig_read('<ref>'). A document id is its file name without "
|
|
91
|
+
".rst. A section is an id (2.1), an anchor (menu-entries), a heading or a unique part of one."
|
|
92
|
+
),
|
|
93
|
+
example_refs=(
|
|
94
|
+
"kconfig:kconfig-language§Menu entries",
|
|
95
|
+
"kconfig:kconfig-language§Menu attributes¶3",
|
|
96
|
+
"kconfig:kconfig-macro-language§Built-in functions",
|
|
97
|
+
),
|
|
98
|
+
)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""`primarysource kconfig import|status|docs|outline|read|search|cite`."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from primarysource.kconfig.catalogue import SPEC
|
|
8
|
+
from primarysource.pkgdocs.serving import run
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main(argv: Sequence[str]) -> int:
|
|
12
|
+
return run(SPEC, argv)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""The MCP server for `kconfig` (`primarysource mcp --collection kconfig`). Imports `mcp` when this module loads."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from primarysource.kconfig.catalogue import SPEC
|
|
6
|
+
from primarysource.pkgdocs.serving import build_server
|
|
7
|
+
|
|
8
|
+
server = build_server(SPEC)
|
primarysource/model.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""The sectioned-document model the libraries share.
|
|
2
|
+
|
|
3
|
+
A document is an ordered list of sections; a section is an ordered list of units. What a unit IS differs by
|
|
4
|
+
corpus and cannot be unified honestly: an RFC has real paragraphs (RFCXML `pn` ids), an extracted PDF clause
|
|
5
|
+
only has sentences, a converted HTML article has blocks. So the unit kind is declared, and every result that
|
|
6
|
+
hands out a `¶n` ref says which kind `n` counts.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from enum import StrEnum
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Unit(StrEnum):
|
|
17
|
+
"""What `¶n` counts within a section."""
|
|
18
|
+
|
|
19
|
+
PARAGRAPH = "paragraph"
|
|
20
|
+
SENTENCE = "sentence"
|
|
21
|
+
BLOCK = "block"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True, slots=True)
|
|
25
|
+
class Section:
|
|
26
|
+
"""One addressable part of a document. `units` are in reading order; `¶1` is `units[0]`."""
|
|
27
|
+
|
|
28
|
+
id: str
|
|
29
|
+
title: str
|
|
30
|
+
units: tuple[str, ...] = ()
|
|
31
|
+
depth: int = 1
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True, slots=True)
|
|
35
|
+
class Document:
|
|
36
|
+
"""A document as the core sees it: an id, a title, the unit kind, and its sections in order."""
|
|
37
|
+
|
|
38
|
+
id: str
|
|
39
|
+
title: str
|
|
40
|
+
unit: Unit
|
|
41
|
+
sections: tuple[Section, ...] = field(default=())
|
|
42
|
+
|
|
43
|
+
def section(self, section_id: str) -> Section | None:
|
|
44
|
+
"""The first section with this id, or None. Duplicate ids are the segmenter's to report."""
|
|
45
|
+
for candidate in self.sections:
|
|
46
|
+
if candidate.id == section_id:
|
|
47
|
+
return candidate
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
def duplicate_ids(self) -> tuple[str, ...]:
|
|
51
|
+
"""Section ids that occur more than once, in first-seen order: an ambiguity to warn about."""
|
|
52
|
+
seen: set[str] = set()
|
|
53
|
+
repeated: list[str] = []
|
|
54
|
+
for candidate in self.sections:
|
|
55
|
+
if candidate.id in seen and candidate.id not in repeated:
|
|
56
|
+
repeated.append(candidate.id)
|
|
57
|
+
seen.add(candidate.id)
|
|
58
|
+
return tuple(repeated)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def span_hash(text: str) -> str:
|
|
62
|
+
"""`sha256:<16 hex>` of the exact text cited, so a citation can be checked against a later extraction."""
|
|
63
|
+
return "sha256:" + hashlib.sha256(text.encode("utf-8")).hexdigest()[:16]
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""NIST publications (SP 800, FIPS) as a primarysource collection. Importing this needs nothing beyond the core."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Sequence
|
|
6
|
+
|
|
7
|
+
from primarysource.model import Unit
|
|
8
|
+
from primarysource.pdfcorpus.tools import GRAMMAR
|
|
9
|
+
from primarysource.registry import Collection
|
|
10
|
+
|
|
11
|
+
# The server registers the bare names (search, read, outline, info, cite); `primarysource mcp` serves them as
|
|
12
|
+
# nist_search, ... and `--bare-names` keeps nistlib's names. Refs: `<doc_id>§<section>` and `<doc_id>:<first>-<last>`.
|
|
13
|
+
COLLECTION = Collection(
|
|
14
|
+
name="nist",
|
|
15
|
+
title="NIST publications (SP 800, SP 1800, FIPS), fetched by the user",
|
|
16
|
+
prefix="nist_",
|
|
17
|
+
unit=Unit.BLOCK,
|
|
18
|
+
grammar=GRAMMAR,
|
|
19
|
+
server="primarysource.nist.server.mcp:mcp",
|
|
20
|
+
cli="primarysource.nist.collection:main",
|
|
21
|
+
identify="primarysource.nist.identify:identify",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main(argv: Sequence[str]) -> int:
|
|
26
|
+
"""`primarysource nist fetch ...` (download, extract, index), `primarysource nist oscal ...`,
|
|
27
|
+
`primarysource nist index` (rebuild the search index from the fetched corpus) and `primarysource nist status`
|
|
28
|
+
(write `defaults.json`, so a bare name such as "NIST SP 800-53" resolves to its current final revision)."""
|
|
29
|
+
commands = {
|
|
30
|
+
"fetch": "primarysource.nist.ingest.fetch",
|
|
31
|
+
"oscal": "primarysource.nist.ingest.oscal",
|
|
32
|
+
"status": "primarysource.nist.ingest.status",
|
|
33
|
+
}
|
|
34
|
+
if argv and argv[0] == "index":
|
|
35
|
+
from primarysource.nist.spec import SPEC
|
|
36
|
+
from primarysource.pdfcorpus import fts
|
|
37
|
+
|
|
38
|
+
return fts.main(SPEC, argv[1:])
|
|
39
|
+
if not argv or argv[0] not in commands:
|
|
40
|
+
names = ",".join([*commands, "index"])
|
|
41
|
+
print(f"usage: primarysource nist {{{names}}} [args]", flush=True)
|
|
42
|
+
return 2
|
|
43
|
+
import importlib
|
|
44
|
+
|
|
45
|
+
module = importlib.import_module(commands[argv[0]])
|
|
46
|
+
return int(module.main(list(argv[1:])))
|