-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path__init__.pyi
More file actions
273 lines (221 loc) · 10.3 KB
/
Copy path__init__.pyi
File metadata and controls
273 lines (221 loc) · 10.3 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
"""Type stubs for the rvt Python bindings.
Hand-maintained. Source of truth for the runtime API is
`src/python.rs` — if you add a method there, add it here too.
PEP 561 marker (`py.typed`) accompanies this file so mypy and
pyright pick it up.
"""
from __future__ import annotations
from typing import Any, Final, Optional, Union
__version__: Final[str]
TypedSchemaSummary = dict[str, int]
"""Return shape of `RevitFile.schema_summary()`.
Keys: ``classes``, ``fields``, ``cpp_types`` — all ``int``.
"""
TypedField = dict[str, Union[str, int, list[int]]]
"""Return shape of an entry in `RevitFile.read_adocument()["fields"]`.
All entries have ``name`` (str) and ``kind`` (str). Additional keys
depend on the kind:
- ``kind == "pointer"``: ``slot_a`` (int), ``slot_b`` (int)
- ``kind == "element_id"``: ``tag`` (int), ``id`` (int)
- ``kind == "ref_container"``: ``count`` (int), ``col_a`` (list[int]), ``col_b`` (list[int])
- ``kind == "bytes"``: ``len`` (int)
"""
TypedADocument = dict[str, Union[int, list[TypedField]]]
"""Return shape of `RevitFile.read_adocument()`.
Keys:
- ``entry_offset`` (int): byte offset in decompressed Global/Latest.
- ``version`` (int): Revit release year.
- ``fields`` (list[TypedField]): one entry per schema-declared field.
"""
TypedDecodedElement = dict[str, Any]
"""Return shape of one entry in `RevitFile.decoded_elements()`.
Keys:
- ``id`` (int | None): resolved ElementId when available.
- ``class_name`` (str): schema class name.
- ``byte_range`` (dict[str, int]): ``start`` and ``end`` offsets in
decompressed stream bytes.
- ``fields`` (list[TypedField]): decoded schema fields.
"""
TypedElementCounts = dict[str, Union[int, dict[str, int]]]
"""Return shape of `RevitFile.element_counts()`.
Keys: ``total`` (int) and ``by_class`` (dict[str, int]).
"""
class RevitFile:
"""Opened Revit file. Entry point for all Python bindings.
Construct with a filesystem path to a ``.rvt`` / ``.rfa`` /
``.rte`` / ``.rft`` file. Raises ``IOError`` on missing files,
non-CFB input, or read failures.
"""
def __init__(
self,
path: str,
max_file_bytes: Optional[int] = None,
max_stream_bytes: Optional[int] = None,
max_inflate_bytes: Optional[int] = None,
max_walker_scan_bytes: Optional[int] = None,
max_walker_candidates: Optional[int] = None,
max_walker_trial_offsets: Optional[int] = None,
max_walker_record_decode_bytes: Optional[int] = None,
max_walker_container_records: Optional[int] = None,
) -> None:
"""Open a Revit file from a filesystem path, with optional
resource limits.
:param path: path to ``.rvt`` / ``.rfa`` / ``.rte`` / ``.rft`` file.
:param max_file_bytes: maximum file size to accept (default 2 GiB).
Files exceeding this size are rejected before reading.
:param max_stream_bytes: maximum per-stream size for
``read_stream`` calls (default 256 MiB).
:param max_inflate_bytes: maximum decompressed output per
inflate call (default 256 MiB). Protects against
compressed-bomb DoS.
:param max_walker_scan_bytes: maximum decompressed
``Global/Latest`` bytes scanned by the walker (default
128 MiB).
:param max_walker_candidates: maximum schema-scan candidates
retained by the walker (default 100,000).
:param max_walker_trial_offsets: maximum trial decodes
attempted by schema-directed walker scans (default
16,000,000).
:param max_walker_record_decode_bytes: maximum bytes inspected
while decoding one walker candidate (default 1 MiB).
:param max_walker_container_records: maximum reference
container records accepted by the walker (default 1,000).
Raises ``IOError`` on missing files, non-CFB input, file-size
over ``max_file_bytes``, or other read errors.
"""
def __repr__(self) -> str: ...
@property
def version(self) -> Optional[int]:
"""Revit release year (e.g. ``2024``), or ``None`` if
``BasicFileInfo`` can't be parsed.
"""
@property
def original_path(self) -> Optional[str]:
"""Original file path recorded at save time on the creator's
machine (may be a Windows-style path). Use ``--redact`` in
the CLI equivalent when surfacing to end users.
"""
@property
def build(self) -> Optional[str]:
"""Revit build tag (e.g. ``"20230308_1635(x64)"``), if
recorded in ``BasicFileInfo``.
"""
@property
def guid(self) -> Optional[str]:
"""Document GUID from ``BasicFileInfo``, if present."""
@property
def part_atom_title(self) -> Optional[str]:
"""Document title from the ``PartAtom`` XML stream (family
files carry one; some project files don't).
"""
def stream_names(self) -> list[str]:
"""All OLE stream paths in the file, sorted, `/`-separated
regardless of host OS.
"""
def read_stream(self, name: str) -> bytes:
"""Raw bytes of the named OLE stream. Accepts either
``/Formats/Latest`` or ``Formats/Latest`` (both resolve the
same way). Returns compressed bytes on streams that use
truncated-gzip framing; most Revit streams use this framing
so callers typically want to run the bytes through a
``gzip`` decompressor before parsing.
Raises ``IOError`` when the stream doesn't exist. Use
``stream_names()`` to enumerate available streams.
"""
def missing_required_streams(self) -> list[str]:
"""List of required Revit stream names the file doesn't
contain. Empty list on a valid Revit file. Useful for
pre-validating an input before running heavy extractors.
"""
def basic_file_info_json(self) -> Optional[str]:
"""Full ``BasicFileInfo`` as a JSON string (parseable via
``json.loads``). Single-call equivalent of the four individual
getters (``version``, ``original_path``, ``build``, ``guid``)
plus any future fields added to the Rust ``BasicFileInfo``
struct. Returns ``None`` if the ``BasicFileInfo`` stream
can't be parsed.
"""
def part_atom_json(self) -> Optional[str]:
"""Full ``PartAtom`` as a JSON string (parseable via
``json.loads``). Superset of the ``part_atom_title`` getter —
also includes ``id``, ``updated``, ``taxonomies``,
``categories``, ``omniclass``, and ``raw_xml``. Returns
``None`` if the file has no PartAtom stream (common on
project ``.rvt`` files).
"""
def schema_summary(self) -> TypedSchemaSummary:
"""Decoded schema counts. Cheap. Returns a dict with keys
``classes``, ``fields``, ``cpp_types``.
"""
def schema_json(self) -> str:
"""Full schema as a JSON string (parseable via ``json.loads``).
Return shape: ``{"classes": [...], "cpp_types": [...],
"skipped_records": int}``. Each class has ``name``, ``offset``,
``fields``, ``tag``, ``parent``, ``declared_field_count``,
``was_parent_only``, ``ancestor_tag``. Each field has
``name``, ``cpp_type``, ``field_type`` (a tagged enum).
The string is on the order of 1-2 MB for a typical Revit
family (~395 classes, ~13,570 fields). For just counts, use
``schema_summary()``.
"""
def read_adocument(self) -> Optional[TypedADocument]:
"""Run the Layer-5a walker and return ADocument's instance
as a dict, or ``None`` if the entry-point detector can't
confidently locate ADocument in the file.
See module docs for the field-kind schema.
"""
def decoded_elements(self) -> list[TypedDecodedElement]:
"""Return conservative production decoded elements.
Each entry has ``id``, ``class_name``, ``byte_range``, and
``fields``. The field dictionaries use the same kind-specific
shape as ``read_adocument()["fields"]``.
"""
def element_counts(self) -> TypedElementCounts:
"""Return decoded element counts as ``{"total": int,
"by_class": dict[str, int]}``.
"""
def write_ifc(self, mode: str = "scaffold") -> str:
"""Produce an IFC4 STEP string for this file via the
``RvtDocExporter``.
``mode`` is one of ``"scaffold"``, ``"typed-no-geometry"``,
``"geometry"``, or ``"strict"``. Stronger modes raise
``ValueError`` when the recovered model data is not complete
enough for that quality level.
"""
def export_diagnostics_json(self) -> str:
"""Produce the JSON diagnostics sidecar for the default IFC
export. The schema matches ``rvt-ifc --diagnostics``.
"""
def export_diagnostics(self) -> dict[str, Any]:
"""Produce the default IFC export diagnostics as a Python
dict. Equivalent to ``json.loads(export_diagnostics_json())``.
"""
def elem_table_header(self) -> dict[str, int]:
"""Parse ``Global/ElemTable`` header. Returns a dict with keys
``element_count``, ``record_count``, ``header_flag``,
``decompressed_bytes``.
"""
def elem_table_records(self) -> list[dict[str, int]]:
"""Parse ``Global/ElemTable`` records. Returns a list of dicts
each with ``offset``, ``id_primary``, ``id_secondary``.
Handles the three observed layout variants automatically:
family files (12 B implicit records), Revit 2023 projects
(28 B explicit with 4-byte FF marker), Revit 2024 projects
(40 B explicit with 8-byte FF marker). On a 34 MB project
this returns all 26,425 declared records.
"""
def declared_element_ids(self) -> list[int]:
"""Return the sorted, deduplicated list of ``ElementId``
values declared by ``Global/ElemTable``. Useful for walker
coverage validation — diff against the walker's ``HandleIndex``
to find "declared but not located" elements.
"""
def rvt_to_ifc(path: str, mode: str = "scaffold") -> str:
"""One-shot: open ``path``, run ``RvtDocExporter``, return the
IFC4 STEP text. Equivalent to
``RevitFile(path).write_ifc(mode=mode)``.
"""
def rvt_to_ifc_diagnostics(path: str) -> str:
"""One-shot: open ``path``, run ``RvtDocExporter``, return the
JSON diagnostics sidecar.
"""