/
inventory.py
132 lines (110 loc) · 4.45 KB
/
inventory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Module responsible for the objects inventory."""
# Credits to Brian Skinn and the sphobjinv project:
# https://github.com/bskinn/sphobjinv
import re
import zlib
from textwrap import dedent
from typing import BinaryIO, Collection, List, Optional
class InventoryItem:
"""Inventory item."""
def __init__(
self, name: str, domain: str, role: str, uri: str, priority: str = "1", dispname: Optional[str] = None
):
"""Initialize the object.
Arguments:
name: The item name.
domain: The item domain, like 'python' or 'crystal'.
role: The item role, like 'class' or 'method'.
uri: The item URI.
priority: The item priority. It can help for inventory suggestions.
dispname: The item display name.
"""
self.name: str = name
self.domain: str = domain
self.role: str = role
self.uri: str = uri
self.priority: str = priority
self.dispname: str = dispname or name
def format_sphinx(self) -> str:
"""Format this item as a Sphinx inventory line.
Returns:
A line formatted for an `objects.inv` file.
"""
dispname = self.dispname
if dispname == self.name:
dispname = "-"
uri = self.uri
if uri.endswith(self.name):
uri = uri[: -len(self.name)] + "$"
return f"{self.name} {self.domain}:{self.role} {self.priority} {uri} {dispname}"
sphinx_item_regex = re.compile(r"^(.+?)\s+(\S+):(\S+)\s+(-?\d+)\s+(\S+)\s*(.*)$")
@classmethod
def parse_sphinx(cls, line: str) -> "InventoryItem":
"""Parse a line from a Sphinx v2 inventory file and return an `InventoryItem` from it."""
match = cls.sphinx_item_regex.search(line)
if not match:
raise ValueError(line)
name, domain, role, priority, uri, dispname = match.groups()
if uri.endswith("$"):
uri = uri[:-1] + name
if dispname == "-":
dispname = name
return cls(name, domain, role, uri, priority, dispname)
class Inventory(dict):
"""Inventory of collected and rendered objects."""
def __init__(self, items: Optional[List[InventoryItem]] = None, project: str = "project", version: str = "0.0.0"):
"""Initialize the object.
Arguments:
items: A list of items.
project: The project name.
version: The project version.
"""
super().__init__()
items = items or []
for item in items:
self[item.name] = item
self.project = project
self.version = version
def register(self, *args: str, **kwargs: str):
"""Create and register an item.
Arguments:
*args: Arguments passed to [InventoryItem][mkdocstrings.inventory.InventoryItem].
**kwargs: Keyword arguments passed to [InventoryItem][mkdocstrings.inventory.InventoryItem].
"""
item = InventoryItem(*args, **kwargs)
self[item.name] = item
def format_sphinx(self) -> bytes:
"""Format this inventory as a Sphinx `objects.inv` file.
Returns:
The inventory as bytes.
"""
header = (
dedent(
f"""
# Sphinx inventory version 2
# Project: {self.project}
# Version: {self.version}
# The remainder of this file is compressed using zlib.
"""
)
.lstrip()
.encode("utf8")
)
lines = [item.format_sphinx().encode("utf8") for item in self.values()]
return header + zlib.compress(b"\n".join(lines) + b"\n", 9)
@classmethod
def parse_sphinx(cls, in_file: BinaryIO, *, domain_filter: Collection[str] = ()) -> "Inventory":
"""Parse a Sphinx v2 inventory file and return an `Inventory` from it.
Arguments:
in_file: The binary file-like object to read from.
domain_filter: A collection of domain values to allow (and filter out all other ones).
Returns:
An `Inventory` containing the collected `InventoryItem`s.
"""
for _ in range(4):
in_file.readline()
lines = zlib.decompress(in_file.read()).splitlines()
items = [InventoryItem.parse_sphinx(line.decode("utf8")) for line in lines]
if domain_filter:
items = [item for item in items if item.domain in domain_filter]
return cls(items)