Skip to content

Instantly share code, notes, and snippets.

@thegamecracks
Created May 10, 2024 04:51
Show Gist options
  • Save thegamecracks/e7870f1b922c11c9d3f14b0565f07024 to your computer and use it in GitHub Desktop.
Save thegamecracks/e7870f1b922c11c9d3f14b0565f07024 to your computer and use it in GitHub Desktop.
Basic sphinx objects.inv parser I wrote a year ago
"""
objects.inv v2 Syntax Reference:
https://sphobjinv.readthedocs.io/en/stable/syntax.html
Python Discord Bot Reference:
https://github.com/python-discord/bot/blob/main/bot/exts/info/doc/_inventory_parser.py
"""
import re
import zlib
from dataclasses import dataclass
from typing import Generator
__version__ = "0.1.0"
V2_PATTERN = re.compile(
r"""
(?P<name>.+)
\s+
(?P<domain>[^\s:]+):(?P<role>\S+)
\s+
(?P<priority>-?\d+)
\s+
(?P<uri>\S*)
\s+
(?P<dispname>.+)
\s*
""",
re.VERBOSE,
)
@dataclass
class DocItem:
name: str
domain: str
role: str
priority: int
uri: str
dispname: str
def __post_init__(self):
if self.dispname == "-":
self.dispname = self.name
def yield_zlib_chunks(f) -> Generator[bytes, None, None]:
decomp = zlib.decompressobj()
while chunk := f.read(1024):
yield decomp.decompress(chunk)
def yield_zlib_lines(f) -> Generator[str, None, None]:
buf = b""
for chunk in yield_zlib_chunks(f):
buf += chunk
while (pos := buf.find(b"\n")) != -1:
line, buf = buf[:pos], buf[pos + 1:]
yield line.decode()
if buf:
yield buf.decode()
def yield_inventory_items(f) -> Generator[DocItem, None, None]:
inv_version = f.readline().rstrip()
if inv_version != b"# Sphinx inventory version 2":
raise ValueError(f"Expected version 2 header, got {inv_version!r}")
name = f.readline().rstrip()
if not name.startswith(b"# Project: "):
raise ValueError(f"Unknown project header: {name!r}")
name = name[11:]
version = f.readline().rstrip() # apparently this can be empty
if not version.startswith(b"# Version:"):
raise ValueError(f"Unknown project version: {version!r}")
version = version[11:]
remainder = f.readline()
if b"zlib" not in remainder:
raise ValueError(f"Expected zlib in header, got {remainder!r}")
for line in yield_zlib_lines(f):
m = V2_PATTERN.fullmatch(line)
if m is None:
raise ValueError(f"Failed to match line: {line}")
params = m.groupdict()
params["priority"] = int(params["priority"])
yield DocItem(**params)
def main():
fmt = ":{0.domain}:{0.role}:`{0.name}`"
with open("objects.inv", "rb") as f:
for item in yield_inventory_items(f):
print(fmt.format(item), end="")
if item.priority == -1:
print(" (hidden)", end="")
print()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment