Edit on GitHub

pytact.data_reader

This module provides read access to dataset files of a Tactican API dataset. Additionally, there is support for communicating with a Coq processes through the same data-format. The next sections give an overview of how this can be accomplished. For an overview of examples, see pytact.

Reading a dataset

The dataset is mapped into memory using mmap, allowing random access to it's structures while keeping memory low. This file contains three entry-points to a dataset in order of preference:

  1. Contextmanager data_reader(path) provides high-level access to the data in directory path. This is the preferred entry-point unless you need something special.
  2. Contextmanager lowlevel_data_reader(path) provides low-level access to the data in directory path, giving direct access to the Cap'n Proto structures of the dataset. Use this when data_reader is too slow or you need access to data not provided by data_reader.
  3. Contextmanager file_dataset_reader provides low-level access to the Cap'n Proto structures of a single file. Using this is usually not advisable.

Additionally, some indexing and traversal helpers are provided:

Communicating with a Coq process

Communication with a Coq process can be done either through a high-level or low-level interface.

Highlevel interface

The function capnp_message_generator converts a socket into a nested generator that yields request messages for predictions and expects to be sent response messages in return. A simple example of how to handle these messages is in pytact.fake_python_server. Some docs can be found with capnp_message_generator.

The capnp_message_generator function can also dump the sequence of messages send and received to a file. One can then use capnp_message_generator_from_file to replay that sequence against a server, either in a unit-test where the call to capnp_message_generator is mocked by capnp_message_generator_from_file, or using a fully fledged socket test as can be found in pytact.fake_coq_client.

Lowlevel interface

The function capnp_message_generator_lowlevel converts a socket into a generator that yields lowlevel Cap'n Proto request messages for predictions and expects to be sent Cap'n proto messages in return. There are four types of messages msg Coq sends.

  1. Synchronize: If msg.is_synchronize is true, Coq is attempting to synchronize its state with the server. A PredictionProtocol.Response.synchronized message is expected in return.
  2. Initialize: If msg.is_initialize is true, Coq is sending a list of available tactics and a global context fragment to be added to an existing stack of global context information. An empty stack can be created through empty_online_definitions_initialize. To add an initialize message to the stack, you can use
    with online_definitions_initialize(existing_stack, msg) as definitions:
        print(type(definitions))
    
    Any subsequent messages will be made in the context of the tactics and predictions sent in this message, until an initialize message is received such that msg.initialize.stack_size is smaller than the current stack size. A PredictionProtocol.Response.initialized message is expected in response of this message.
  3. Predict: If msg.is_predict is true, Coq is asking to predict a list of plausible tactics given a proof state. The proof state can be easily accessed using
    with online_data_predict(definitions, msg.predict) as proof_state:
        print(dir(proof_state))
    
    A PredictionProtocol.Response.prediction or PredictionProtocol.Response.textPrediction message is expected in return.
  4. Check Alignment: If msg.is_check_alignment is true, then Coq is asking the server to check which tactics and definitions are known to it. A PredictionProtocol.Response.alignment message is expected in return.

You can wrap the generator produced by capnp_message_generator_lowlevel into record_lowlevel_generator in order to record the exchanged messages to disk. This trace can later be replayed using capnp_message_generator_from_file_lowlevel (or using the high-level interface).

  1# NOTE: This file is derived from data_reader.pyx. Any changes here should be reflected there as well.
  2
  3"""This module provides read access to dataset files of a Tactican API dataset.
  4Additionally, there is support for communicating with a Coq processes through
  5the same data-format. The next sections give an overview of how this can be
  6accomplished. For an overview of examples, see `pytact`.
  7
  8# Reading a dataset
  9
 10The dataset is mapped into memory using mmap, allowing random access to it's
 11structures while keeping memory low. This file contains three entry-points to a
 12dataset in order of preference:
 13
 141. Contextmanager `pytact.data_reader.data_reader(path)` provides high-level access to the data
 15   in directory `path`. This is the preferred entry-point unless you need
 16   something special.
 172. Contextmanager `pytact.data_reader.lowlevel_data_reader(path)` provides low-level access to
 18   the data in directory `path`, giving direct access to the Cap'n Proto structures
 19   of the dataset. Use this when `data_reader` is too slow or you need access
 20   to data not provided by `data_reader`.
 213. Contextmanager `file_dataset_reader` provides low-level access to
 22   the Cap'n Proto structures of a single file. Using this is usually not
 23   advisable.
 24
 25Additionally, some indexing and traversal helpers are provided:
 26- `GlobalContextSets` calculates and caches the global context of a definition
 27  as a set, also caching intermediate results.
 28- `definition_dependencies` and `node_dependencies` traverse the graph starting
 29  from a node and return all direct, non-transitive definitions that node depends on.
 30
 31# Communicating with a Coq process
 32
 33Communication with a Coq process can be done either through a high-level or
 34low-level interface.
 35
 36## Highlevel interface
 37
 38The function `capnp_message_generator` converts a socket into a nested generator that
 39yields request messages for predictions and expects to be sent response messages
 40in return. A simple example of how to handle these messages is in `pytact.fake_python_server`.
 41Some docs can be found with `capnp_message_generator`.
 42
 43The `capnp_message_generator` function can also dump the sequence of messages send
 44and received to a file. One can then use `capnp_message_generator_from_file` to replay
 45that sequence against a server, either in a unit-test where the call to `capnp_message_generator`
 46is mocked by `capnp_message_generator_from_file`, or using a fully fledged socket test
 47as can be found in `pytact.fake_coq_client`.
 48
 49## Lowlevel interface
 50
 51The function `capnp_message_generator_lowlevel` converts a socket into a generator that
 52yields lowlevel Cap'n Proto request messages for predictions and expects to be sent Cap'n proto
 53messages in return. There are four types of messages `msg` Coq sends.
 541. Synchronize: If `msg.is_synchronize` is true, Coq is attempting to synchronize
 55   its state with the server. A `PredictionProtocol.Response.synchronized` message is expected
 56   in return.
 572. Initialize: If `msg.is_initialize` is true, Coq is sending a list of available
 58   tactics and a global context fragment to be added to an existing stack of global context
 59   information. An empty stack can be created through `empty_online_definitions_initialize`.
 60   To add an initialize message to the stack, you can use
 61   ```
 62   with pytact.data_reader.online_definitions_initialize(existing_stack, msg) as definitions:
 63       print(type(definitions))
 64   ```
 65   Any subsequent messages will be made in the context of the
 66   tactics and predictions sent in this message, until an initialize message is received
 67   such that `msg.initialize.stack_size` is smaller than the current stack size.
 68   A `PredictionProtocol.Response.initialized` message is expected in response of this message.
 694. Predict: If `msg.is_predict` is true, Coq is asking to predict a list of plausible
 70   tactics given a proof state. The proof state can be easily accessed using
 71   ```
 72   with pytact.data_reader.online_data_predict(definitions, msg.predict) as proof_state:
 73       print(dir(proof_state))
 74   ```
 75   A `PredictionProtocol.Response.prediction` or `PredictionProtocol.Response.textPrediction`
 76   message is expected in return.
 775. Check Alignment: If `msg.is_check_alignment` is true, then Coq is asking the server
 78   to check which tactics and definitions are known to it. A
 79   `PredictionProtocol.Response.alignment` message is expected in return.
 80
 81You can wrap the generator produced by `capnp_message_generator_lowlevel` into
 82`record_lowlevel_generator` in order to record the exchanged messages to disk.
 83This trace can later be replayed using
 84`capnp_message_generator_from_file_lowlevel` (or using the high-level interface).
 85
 86"""
 87
 88from __future__ import annotations
 89from contextlib import contextmanager, ExitStack
 90from dataclasses import dataclass
 91from typing import Any, Callable, TypeAlias, TypeVar, Union, cast, BinaryIO
 92from collections.abc import Iterable, Sequence, Generator
 93from pathlib import Path
 94from immutables import Map
 95import signal
 96import pytact.graph_api_capnp_cython as apic # type: ignore
 97import capnp# type: ignore
 98import pytact.graph_api_capnp as graph_api_capnp # type: ignore
 99import socket
100import mmap
101import itertools
102import resource
103import threading
104import subprocess
105import shutil
106import time
107
108@contextmanager
109def file_dataset_reader(fname: Path) -> Generator[apic.Dataset_Reader, None, None]:
110    """Load a single dataset file into memory, and expose its raw Cap'n Proto structures.
111
112    This is a low-level function. Prefer to use `data_reader` or `lowlevel_data_reader`.
113    """
114    ...
115
116class LowlevelDataReader:
117    """A thin wrapper around the raw Cap'n Proto structures contained in a dataset directory.
118
119    Every file in the directory is assigned an integer called a graph-id. This class is a
120    `Sequence` that allows the retrieval of the structures in a file by its graph-id.
121    Additionally, the function `local_to_global` translates a dependency-index relative to
122    a graph-id to a new graph-id. This allows one to find out in which file a node in a
123    graph is located.
124
125    This is a lowlevel interface. For details on using the exposed structures the documentation
126    in the Cap'n Proto API file.
127    """
128
129    graphid_by_filename : dict[Path, int]
130    """Map from filenames in the data directory to their graph-id's."""
131
132    graph_files : list[Path]
133    """Map's a graph-id to a filename. Inverse of `graphid_by_filename`."""
134
135    def local_to_global(self, graph: int, dep_index: int) -> int:
136        """Convert a dependency-index relative to a graph-id to a new graph-id.
137
138        This is used to find the graph-id where a particular node can be found. If `graph` is the
139        graph-id that contains a reference to a node and `dep_index` is the relative location
140        where that node can be found then `local_to_global(graph, dep_index)` finds the graph-id
141        of the file where the node is physically located.
142        """
143        ...
144
145    def __getitem__(self, graph: int):
146        """Retrieve the raw Cap'n Proto structures associated with a graph-id."""
147        ...
148
149    def __len__(self) -> int: ...
150
151@contextmanager
152def lowlevel_data_reader(dataset_path: Path) -> Generator[LowlevelDataReader, None, None]:
153    """Map a directory of dataset files into memory, and expose their raw Cap'n Proto structures.
154
155    Arguments:
156    `dataset_path`: Can either be a dataset directory, or a SquashFS image file. In case of an image
157                    file `dataset.squ`, the image will be mounted using `squashfuse` on directory
158                    `dataset/`, after which the contents of that directory will be read.
159
160    This is a low-level function. Prefer to use `data_reader`. See `LowlevelDataReader` for
161    further documentation.
162    """
163    ...
164
165ProofStateId = int
166TacticId = int
167GraphId = int
168NodeId = int
169NodeHash = int
170
171class Node:
172    """A node in the calculus of inductive construction graph.
173
174    A node has a `label`, a unique `identity` and `children`. Some nodes are also
175    a `Definition`.
176    """
177
178    graph : GraphId
179    """The id of the graph in which this node occurs. For lowlevel use only."""
180
181    nodeid : NodeId
182    """The local id of the node in the dataset. For lowlevel use only."""
183
184    def __repr__(self):
185        ...
186
187    def __eq__(self, other: object) -> bool:
188        """Physical equality of two nodes. Note that two nodes with a different physical equality
189        may have the same `identity`. See `identity` for details.
190        """
191        ...
192
193    def __hash__(self):
194        """A hash that is corresponds to physical equality, not to be confused by `identity`."""
195        ...
196
197    @property
198    def label(self) -> apic.Graph_Node_Label_Reader:
199        """The label of the node, indicating it's function in the CIC graph."""
200        ...
201
202    @property
203    def identity(self) -> NodeHash:
204        """The identity of a node uniquely determines it. That is, one can consider any to nodes with the same
205        identity to be equal. The notion of equal we use is as follows:
206        1. Graph perspective: Two nodes have the same identity if and only if they are bisimilar.
207           In this notion, bisimilarity does take into consideration the label of the nodes, modulo some
208           equivalence class that is not fully specified here. One aspect of the equivalence class is that
209           for definition nodes their associated global context (accessed through `Definition.previous`) is
210           not taken into account.
211        2. Lambda calculus perspective: Two nodes have the same identity if their corresponding lambda terms
212           are alpha-equivalent. Note that two definitions with the same body are not considered
213           alpha-equivalent.
214
215        The identity of a node is used to perform partial graph-sharing. That is, two nodes with the same
216        identity are merged when the graph is generated. There are two reasons why two nodes with the same
217        semantic identity might have a different physical identity:
218        1. Nodes are only merged when the first node exists in the same graph as the second node, or exists
219           in a dependent graph. Hence, nodes originating from developments that do not depend on each other
220           are never merged. Full graph-sharing would require global analysis on a dataset, which any consumer
221           can optionally do as a post-processing step.
222        2. Two definition nodes with the same name and body have the same identity. But if they occur in
223           different global contexts, these nodes are physically different to ensure the integrity of their
224           global contexts.
225
226        Beware that the identity is currently a 64 bit field. For datasets that have graphs of size in the
227        order of billions of nodes there is a non-trivial chance of a collision. (We consider this acceptable
228        for machine learning purposes.)
229        """
230        ...
231
232    @property
233    def children(self) -> Sequence[tuple[int, Node]]:
234        """The children of a node, together with the labels of the edges towards the children.
235        Note that for efficiency purposes, the label is represented as an integer. The corresponding
236        enum of this integer is `graph_api_capnp.EdgeClassification`."""
237        ...
238
239    @property
240    def definition(self) -> Definition | None:
241        """Some nodes in the CIC graph represent definitions. Such nodes contain extra information about the
242        definition.
243        """
244        ...
245
246class ProofState:
247    """A proof state represents a particular point in the tactical proof of a constant."""
248
249    @property
250    def lowlevel(self):
251        ...
252    def __repr__(self):
253        ...
254
255    @property
256    def root(self) -> Node:
257        """The entry-point of the proof state, all nodes that are 'part of' the proof state are
258        reachable from here."""
259        ...
260
261    @property
262    def context(self) -> Sequence[Node]:
263        """The local context of the proof state, given as a tuple of their original name as they appeared in the
264        proof and the corresponding node.
265
266        The nodes always have either label `contextAssum` or `contextDef`.
267        Note that these nodes are also reachable from the root of the proof state.
268
269        The names of the context elements should be used for debugging and viewing purposes only, because
270        hypothesis-generating tactics have been modified to use auto-generated names. Hence, tactics should
271        not be concerned about the names of the context.
272        """
273        ...
274
275    @property
276    def context_names(self) -> Sequence[str]:
277        """The names of the local context nodes of the proof state, as they originally appeared in the proof.
278
279        These names should be used for debugging and viewing purposes only, because hypothesis-generating tactics have
280        been modified to use auto-generated names. Hence, tactics should not be concerned about the names of
281        the context.
282        """
283        ...
284
285    @property
286    def context_text(self) -> Sequence[str]:
287        """A textual representation of the type/definition of context nodes
288        """
289        ...
290
291    @property
292    def conclusion_text(self) -> str:
293        """A textual representation of the conclusion of the proof state.
294        """
295        ...
296
297    @property
298    def text(self) -> str:
299        """A textual representation of the proof state."""
300        ...
301
302    def __str__(self) -> str:
303        ...
304
305    @property
306    def id(self) -> ProofStateId:
307        """
308        A unique identifier of the proof state. Any two proof states in a tactical proof that have an equal id
309        can morally be regarded to be 'the same' proof state.
310        IMPORTANT: Two proof states with the same id may still have different contents. This is because proof states
311                   can contain existential variables (represented by the `evar` node) that can be filled as a
312                   side-effect by a tactic running on another proof state.
313        """
314        ...
315
316Unresolvable : TypeAlias = None
317Unknown : TypeAlias = None
318class Outcome:
319    """An outcome is the result of running a tactic on a proof state. A tactic may run on multiple proof states."""
320
321    tactic : apic.Tactic_Reader | Unknown
322    """The tactic that generated the outcome. For it's arguments, see `tactic_arguments`
323
324    Sometimes a tactic cannot or should not be recorded. In those cases, it is marked as 'unknown'.
325    This currently happens with tactics that are run as a result of the `Proof with tac` construct and it
326    happens for tactics that are known to be unsafe like `change_no_check`, `fix`, `cofix` and more.
327    """
328
329    @property
330    def lowlevel(self):
331        ...
332    def __repr__(self):
333        ...
334
335    @property
336    def before(self) -> ProofState:
337        """The proof state before the tactic execution."""
338        ...
339
340    @property
341    def after(self) -> Sequence[ProofState]:
342        """The new proof states that were generated by the tactic."""
343        ...
344
345    @property
346    def term(self) -> Node:
347        """The proof term that witnesses the transition from the before state to the after states. It contains a
348        hole (an `evar` node) for each of the after states. It may also refer to elements of the local context of
349        the before state.
350        """
351        ...
352
353    @property
354    def term_text(self) -> str:
355        """A textual representation of the proof term."""
356        ...
357
358    @property
359    def tactic_arguments(self) -> Sequence[Node | Unresolvable]:
360        """The arguments of the tactic that produced this outcome.
361
362        The node is the root of a graph representing an argument that is a term in the calculus of constructions.
363        Sometimes, an argument is not resolvable to a term, in which case it is marked as `Unresolvable`.
364        """
365        ...
366
367class ProofStep:
368    """A proof step is the execution of a single tactic on one or more proof states, producing a list of outcomes.
369    """
370
371    @property
372    def lowlevel(self):
373        ...
374    def __repr__(self):
375        ...
376
377    @property
378    def tactic(self) -> apic.Tactic_Reader | Unknown:
379        """The tactic that generated the proof step. Note that the arguments of the tactic can be found in the
380        individual outcomes, because they may be different for each outcome.
381
382        Sometimes a tactic cannot or should not be recorded. In those cases, it is marked as 'unknown'.
383        This currently happens with tactics that are run as a result of the `Proof with tac` construct and it
384        happens for tactics that are known to be unsafe like `change_no_check`, `fix`, `cofix` and more.
385        """
386        ...
387
388    @property
389    def outcomes(self) -> Sequence[Outcome]:
390        """A list of transformations of proof states to other proof states, as executed by the tactic of the proof
391        step
392        """
393        ...
394
395@dataclass
396class Original:
397    """Token that signals that a definition is original, as inputted by the
398    user."""
399    pass
400
401@dataclass
402class Discharged:
403    """Token that signals that a definition is derived from an original after
404    section closing."""
405
406    original: Definition
407
408@dataclass
409class Substituted:
410    """Token that signals that a definition is derived from an original after
411    module functor instantiation."""
412
413    original: Definition
414
415@dataclass
416class Inductive:
417    """Token that signals that a definition is inductive."""
418
419    representative: Definition
420    """The representative of the mutually recursive cluster. For lowlevel use only"""
421
422@dataclass
423class Constructor:
424    """Token that signals that a definition is a constructor."""
425
426    representative: Definition
427    """The representative of the mutually recursive cluster. For lowlevel use only"""
428
429@dataclass
430class Projection:
431    """Token that signals that a definition is a projection."""
432
433    representative: Definition
434    """The representative of the mutually recursive cluster. For lowlevel use only"""
435
436@dataclass
437class ManualConstant:
438    """Token that signals that a definition was inputted by the user by
439    manually inputting a term."""
440    pass
441
442@dataclass
443class TacticalConstant:
444    """Token that signals that a lemma was proved by the user using
445    a tactic proof."""
446
447    proof: Sequence[ProofStep]
448    """The proof of the lemma."""
449
450@dataclass
451class ManualSectionConstant:
452    """Token that signals that a constant is a section variable or let-construct."""
453    pass
454
455@dataclass
456class TacticalSectionConstant:
457    """Token that signals that a constant is a section let-construct with a tactic proof."""
458
459    proof: Sequence[ProofStep]
460    """The proof of the lemma."""
461
462class Definition:
463    """A definition of the CIC, which is either a constant, inductive, constructor, projection or section
464    variable. Constants and section variables can have tactical proofs associated to them.
465    """
466
467    node : Node
468    """The node that is associated with this definition. It holds that
469    `definition.node.definition == definition`.
470    """
471
472    @property
473    def lowlevel(self):
474        ...
475    def __repr__(self):
476        ...
477
478    def __eq__(self, other: object) -> bool:
479        """Physical equality of two nodes. Note that two nodes with a different physical equality
480        may have the same `identity`. See `identity` for details.
481        """
482        ...
483
484    def __hash__(self):
485        """A hash that is corresponds to physical equality, not to be confused by `identity`."""
486        ...
487
488    @property
489    def name(self) -> str:
490        """The fully-qualified name of the definition. The name should be unique in a particular global context,
491        but is not unique among different branches of the global in a dataset.
492        """
493        ...
494
495    @property
496    def previous(self) -> Definition | None:
497        """The previous definition within the global context of the current file.
498
499        Note that this is a lowlevel property. Prefer to use `global_context` or `clustered_global_context`.
500
501        The contract on this field is that any definition nodes reachable from the forward closure of the definition
502        must also be reachable through the chain of previous fields. An exception to this rule are mutually
503        recursive definitions. Those nodes are placed into the global context in an arbitrary ordering.
504        """
505        ...
506
507    @property
508    def external_previous(self) -> Sequence[Definition]:
509        """A list of definitions that are the representatives of files other than the current file that are
510        part of the global context. This list becomes populated when a `Require` statement occurred right before
511        the definition.
512
513        Note that this is a lowlevel property. Prefer to use `global_context` or `clustered_global_context`.
514        """
515        ...
516
517    def global_context(self, across_files : bool = True, inclusive = False) -> Iterable[Definition]:
518        """All of the definitions in the global context when this definition was created.
519
520        Note that this does not include this definition itself, except when the definition is a inductive,
521        constructor or projection. Because those are mutually recursive objects, they reference themselves
522        and are therefore part of their own global context.
523
524        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
525        definition reachable from the forward closure of the definition also exists in the remainder of the
526        stream. An exception to this rule are mutually recursive definitions, because no topological sort
527        is possible there (see also `clustered_global_context`).
528
529        Arguments:
530        * `across_files`: if `False`, outputs only the definitions from the local file, default `True`.
531        * `inclusive`: if `True`, outputs also itself, default `False`.
532        Note: if it is a self-recursive definition, the `inclusive` argument is ignored, and considered as `True`
533        """
534        ...
535
536    def clustered_global_context(self, across_files : bool = True, inclusive : bool = False) -> Iterable[list[Definition]]:
537        """All of the definitions in the global context when this definition was created, clustered into
538        mutually recursive cliques.
539
540        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
541        definition reachable from the forward closure of the definition also exists in the remainder of the
542        stream.
543
544        Arguments:
545        * `across_files`: if `False`, outputs only the definitions from the local file, default `True`.
546        * `inclusive`: if `True`, outputs also the cluster of itself, default `False`.
547        Note: if it is a self-recursive definition, the `inclusive` argument is ignored, and considered as `True`.
548        """
549        ...
550
551    @property
552    def status(self) -> Original | Discharged | Substituted:
553        """
554        A definition is either
555        (1) an object as originally inputted by the user.
556        (2) a definition that was originally defined in a section and has now had the section
557            variables discharged into it.
558        (3) a definition that was obtained by performing some sort of module functor substitution.
559        When a definition is not original, we cross-reference to the definition that it was derived from.
560        """
561        ...
562
563    @property
564    def kind(self) -> Union[Inductive, Constructor, Projection,
565                            ManualConstant, TacticalConstant,
566                            ManualSectionConstant, TacticalSectionConstant]:
567        """The kind of the definition.
568
569        It can be an constant, section constant, inductive, constructor or projection. In case of a constant
570        of a constant or section constant, an optional tactical proof can be associated. In case of an inductive,
571        constructor or projection, another definition that acts as the representative of the mutually recursive
572        cluster of definitions is associated.
573
574        The associated information is low-level. Prefer to use the properties `proof` and `cluster` to access them.
575        """
576        ...
577
578    @property
579    def proof(self) -> Sequence[ProofStep] | None:
580        """An optional tactical proof that was used to create this definition."""
581        ...
582
583    @property
584    def cluster_representative(self) -> Definition:
585        """A unique representative of the mutually recursive cluster of definitions this definition is part of.
586        If the definition is not mutually recursive, the representative is itself.
587
588        This is a low-level property. Prefer to use the `cluster` property.
589        """
590        ...
591
592    @property
593    def cluster(self) -> Iterable[Definition]:
594        """The cluster of mutually recursive definitions that this definition is part of.
595        If the definition is not mutually recursive, the cluster is a singleton."""
596        ...
597
598    @property
599    def type_text(self) -> str:
600        """A textual representation of the type of this definition."""
601        ...
602
603    @property
604    def term_text(self) -> str | None:
605        """A textual representation of the body of this definition.
606        For inductives, constructors, projections, section variables and axioms this is `None`.
607        """
608        ...
609
610    @property
611    def is_file_representative(self) -> bool:
612        """Returns true if this definition is the representative of the super-global context of it's file.
613        Se also `Dataset.representative`."""
614        ...
615
616class Dataset:
617    """The data corresponding to a single Coq source file. The data contains a representation of all definitions
618    that have existed at any point throughout the compilation of the source file.
619    """
620
621    graph : GraphId
622    filename : Path
623    """The physical file in which the data contained in this class can be found."""
624
625    @property
626    def lowlevel(self):
627        ...
628    def __repr__(self):
629        ...
630
631    @property
632    def dependencies(self) -> Sequence[Path]:
633        """A list of physical paths of data files that are direct dependencies of this file.
634
635        It is guaranteed that no cycles exist in the dependency relation between files induced by this field.
636        """
637        ...
638
639    @property
640    def representative(self) -> Definition | None:
641        """The entry point of the global context of definitions that are available when this file is 'Required' by
642        another file. The full global context can be obtained by following the `previous` node of definitions.
643        If the compilation unit does not contain any 'super'-global definitions this may be `None`.
644
645        This is a low-level property.
646        Prefer to use `definitions(spine_only = True)` and `clustered_definitions(spine_only=True)`.
647        """
648        ...
649
650    def definitions(self, across_files = False, spine_only = False) -> Iterable[Definition]:
651        """All of the definitions present in the file.
652        Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside
653        of sections or module functors.
654
655        Arguments:
656        * `across_files`: if `True`, outputs also definitions from dependent files, default `False`.
657        * `spine_only`: if True, outputs only the definitions on the main spine, default `False`.
658        Note: `across_files = True` is incompatible with `spine_only = False`.
659
660        When `spine_only = True`, the resulting iterable is topologically sorted. That is, for
661        any definition in the stream, any definition reachable from the forward closure of the definition
662        also exists in the remainder of the stream. An exception to this rule are mutually recursive definitions,
663        because no topological sort is possible there (see also `clustered_definitions`).
664        """
665        ...
666
667    def clustered_definitions(self, across_files = False, spine_only = False) -> Iterable[list[Definition]]:
668        """All of the definitions present in the file, clustered by mutually recursive definitions.
669        Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside
670        of sections or module functors.
671
672        Arguments:
673        * `across_files`: if `True`, outputs also definitions from dependent files, default `False`.
674        * `spine_only`: if `True`, outputs only the definitions on the main spine, default `False`.
675        Note: `across_files = True` is incompatible with `spine_only = False`.
676
677        When `spine_only = True`, the resulting iterable is topologically sorted. That is, for
678        any definition in the stream, any definition reachable from the forward closure of the definition
679        also exists in the remainder of the stream.
680        """
681        ...
682
683    @property
684    def module_name(self) -> str:
685        ...
686
687    def node_by_id(self, nodeid: NodeId) -> Node:
688        """Lookup a node inside of this file by it's local node-id. This is a low-level function."""
689        ...
690
691def lowlevel_to_highlevel(lreader : LowlevelDataReader) -> dict[Path, Dataset]:
692    """Convert a dataset initialized as a `LowLevelDataReader` into a high level interface."""
693    ...
694
695@contextmanager
696def data_reader(dataset_path: Path) -> Generator[dict[Path, Dataset], None, None]:
697    """Load a directory of dataset files into memory, and expose the data they contain.
698    The result is a dictionary that maps physical paths to `Dataset` instances that allow access to the data.
699
700    Arguments:
701    `dataset_path`: Can either be a dataset directory, or a SquashFS image file. In case of an image
702                    file `dataset.squ`, the image will be mounted using `squashfuse` on directory
703                    `dataset/`, after which the contents of that directory will be read.
704
705    """
706    ...
707
708class OnlineDefinitionsReader:
709    """This class represents a global context to Python by Coq, containing all
710    known definitions and available tactics."""
711
712    def local_to_global(self, graph: int, dep_index: int) -> int:
713        """Convert a dependency-index relative to a graph-id to a new graph-id.
714
715        This is used to find the graph-id where a particular node can be found. If `graph` is the
716        graph-id that contains a reference to a node and `dep_index` is the relative location
717        where that node can be found then `local_to_global(graph, dep_index)` finds the index in
718        the global context stack where the node is physically located.
719
720        Lowlevel function.
721        """
722        ...
723
724    @property
725    def representative(self) -> Definition | None:
726        """The last definition in the global context. All other definitions can be accessed by following
727        the `Definition.previous` chain starting from this definitions.
728
729        This is a low-level property.
730        Prefer to use `definitions` and `clustered_definitions`.
731        """
732        ...
733
734    def definitions(self, full : bool = True) -> Iterable[Definition]:
735        """The list of definitions that are currently in the global context.
736
737        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
738        definition reachable from the forward closure of the definition also exists in the remainder of
739        the stream. An exception to this rule are mutually recursive definitions,
740        because no topological sort is possible there (see also `clustered_definitions`).
741        """
742        ...
743
744    def clustered_definitions(self, full : bool = True) -> Iterable[list[Definition]]:
745        """All of the definitions present in the global context, clustered by mutually recursive definitions.
746
747        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
748        definition reachable from the forward closure of the definition also exists in the remainder of
749        the stream.
750        """
751        ...
752
753@contextmanager
754def online_definitions_initialize(stack: OnlineDefinitionsReader,
755                                  init: apic.PredictionProtocol_Request_Initialize_Reader) -> Generator[OnlineDefinitionsReader, None, None]:
756    """Given a new initialization message sent by Coq, construct a
757    `OnlineDefinitiosnReader` object. This can be used to inspect the
758    definitions currently available. Additionally, using `online_data_predict`
759    it can be combined with a subsequent prediction request received from Coq
760    to build a `ProofState`.
761    """
762    ...
763
764def empty_online_definitions_initialize() -> OnlineDefinitionsReader:
765    ...
766
767@contextmanager
768def online_data_predict(base: OnlineDefinitionsReader,
769                        predict: apic.PredictionProtocol_Request_Predict_Reader) -> Generator[ProofState, None, None]:
770    """Given a `OnlineDefinitionsReader` instance constructed through
771    `online_data_initialize`, and a prediction message sent by Coq, construct a
772    `ProofState` object that represents the current proof state in Coq.
773    """
774    ...
775
776@dataclass
777class TacticPredictionGraph:
778    ident : int
779    arguments : list[Node]
780    confidence : float
781
782@dataclass
783class TacticPredictionsGraph:
784    predictions : list[TacticPredictionsGraph]
785
786@dataclass
787class TacticPredictionText:
788    tactic_text : str
789    confidence : float
790
791@dataclass
792class TacticPredictionsText:
793    predictions : list[TacticPredictionsText]
794
795@dataclass
796class CheckAlignmentMessage:
797    pass
798
799@dataclass
800class CheckAlignmentResponse:
801    unknown_definitions : list[Definition]
802    unknown_tactics : list[int]
803
804@dataclass
805class GlobalContextMessage:
806    """A message containing a new global context sent to Python from Coq,
807    including all known definitions and available tactics."""
808
809    definitions : OnlineDefinitionsReader
810    tactics : Sequence[apic.AbstractTactic_Reader]
811
812    log_annotation : str
813    """An annotation representing the current position of Coq in a source
814    document. For logging and debugging purposes."""
815
816    prediction_requests : Generator[GlobalContextMessage | ProofState | CheckAlignmentMessage,
817                                    None | TacticPredictionsGraph | TacticPredictionsText | CheckAlignmentResponse,
818                                    None]
819    """A sub-generator that produces new requests from Coq that are based on or
820    extend the global context of the current message. Once the sub-generator
821    runs out, the parent generator continues."""
822
823def capnp_message_generator_lowlevel(socket: socket.socket) -> (
824        Generator[apic.PredictionProtocol_Request_Reader,
825                  capnp.lib.capnp._DynamicStructBuilder, None]):
826    """A generator that facilitates communication between a prediction server and a Coq process.
827
828    Given a `socket`, this function creates a generator that yields messages of type
829    `pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader` after which a
830    `capnp.lib.capnp._DynamicStructBuilder` message needs to be `send` back.
831    """
832    ...
833
834def capnp_message_generator_from_file_lowlevel(
835        message_file: BinaryIO,
836        check : Callable[[Any, Any, Any], None] | None = None) -> (
837        Generator[apic.PredictionProtocol_Request_Reader,
838                  capnp.lib.capnp._DynamicStructBuilder, None]):
839    """Replay and verify a pre-recorded communication sequence between Coq and a prediction server.
840
841    Lowlevel variant of `capnp_message_generator_from_file`.
842
843    Accepts a `message_file` containing a stream of Capt'n Proto messages as recorded using
844    `capnp_message_generator(s, record=message_file)`. The resulting generator acts just like the generator
845    created by `capnp_message_generator` except that it is not connected to the socket but just replays the
846    pre-recorded messages.
847
848    Arguments:
849    - `check` is an optional callable that can be used to compare the response of the server to the recorded
850      response. It accepts three arguments: The recorded message that was sent by Coq, the response of the server
851      and the recorded response.
852    """
853    ...
854
855def record_lowlevel_generator(
856        record_file: BinaryIO,
857        gen: Generator[apic.PredictionProtocol_Request_Reader,
858                       capnp.lib.capnp._DynamicStructBuilder, None]) -> (
859                           Generator[apic.PredictionProtocol_Request_Reader,
860                                     capnp.lib.capnp._DynamicStructBuilder, None]):
861    """Record a trace of the full interaction of a lowlevel generator to a file
862
863    Wrap a lowlevel generator (such as from `capnp_message_generator_lowlevel`) and dump all exchanged messages
864    to the given file. The file can later be replayed with `capnp_message_generator_from_file_lowlevel`.
865    """
866    ...
867
868def prediction_generator(
869        lgenerator: Generator[apic.PredictionProtocol_Request_Reader,
870                              capnp.lib.capnp._DynamicStructBuilder, None],
871        defs: OnlineDefinitionsReader):
872    """Given the current global context stack `defs`, convert a low-level
873    generator to a high-level `GlobalContextMessage`"""
874    ...
875
876def capnp_message_generator(socket: socket.socket, record: BinaryIO | None = None) -> GlobalContextMessage:
877    """A generator that facilitates communication between a prediction server and a Coq process.
878
879    Given a `socket`, this function creates a `GlobalContextMessage` `context`. This message contains an
880    initially empty list of available tactics and definitions in the global context. Through
881    `context.prediction_requests` one can access a generator that yields prediction requests and expects
882    predictions to be sent in response. The possible messages are as follows:
883    - `GlobalContextMessage`: An additional, nested, global context message that amends the current context
884       with additional tactics and definitions. The prediction requests of this nested context need to be
885       exhausted before continuing with messages from the current context.
886    - `CheckAlignmentMessage`: A request to check which of Coq's current tactics and definitions the
887      prediction server currently "knows about". The generator expects a `CheckAlignmentResponse` to be
888      sent in response.
889    - `ProofState`: A request to make tactic predictions for a given proof state. Either a
890      `TacticPredictionsGraph` or a `TacticPredictionsText` message is expected in return.
891
892    When `record` is passed a file descriptor, all received and sent messages will be dumped into that file
893    descriptor. These messages can then be replayed later using `capnp_message_generator_from_file`.
894    """
895    ...
896
897def capnp_message_generator_from_file(message_file: BinaryIO,
898                                      check : Callable[[Any, Any, Any], None] | None = None,
899                                      record: BinaryIO | None = None) -> GlobalContextMessage:
900    """Replay and verify a pre-recorded communication sequence between Coq and a prediction server.
901
902    Highlevel variant of `capnp_message_generator_from_file_lowlevel`.
903
904    Accepts a `message_file` containing a stream of Capt'n Proto messages as recorded using
905    `capnp_message_generator(s, record=message_file)`. The resulting generator acts just like the generator
906    created by `capnp_message_generator` except that it is not connected to the socket but just replays the
907    pre-recorded messages.
908
909    Arguments:
910    - `check` is an optional callable that can be used to compare the response of the server to the recorded
911      response. It accepts three arguments: The recorded message that was sent by Coq, the response of the server
912      and the recorded response.
913    - `record` is an optional file that re-records the interaction with the current server
914    """
915    ...
916
917class GlobalContextSets:
918    """Lazily retrieve a the global context of a definition as a set, with memoization.
919
920    Because this class can allocate (large) amounts of memory, use it as a context-manager. To create a new
921    instance, and retrieve the context of a definition, use:
922    ```
923    with GlobalContextSets.new_context() as gcs:
924        gcs.global_context_set(my_definition)
925    ```
926    This context will be cached, as well as intermediate results (global contexts of other definitions) as
927    long as the context-set is in scope. Caching can be nested by using `sub_context`:
928    ```
929    with GlobalContextSets.new_context() as gcs:
930        gcs.global_context_set(my_definition)
931        with gcs.sub_context(lambda d:is_file_representative) as gcs_sub:
932            # gcs_sub remembers anything in the case of gcs
933            # caching is propagated to the parent cache only if the provided lambda evaluates to true
934            gcs_sub.global_context_set(my_definition2)
935    ```
936    """
937    def __init__(self, cache, parent: GlobalContextSets | None,
938                 should_propagate: Callable[[Definition], bool]):
939        """Do not call directly. Use `GlobalContextSets.new_context` and `GlobalContextSets.sub_context`."""
940        ...
941
942    def global_context_set(self, d: Definition) -> Map:
943        """Retrieve the global context of a definition, caching the result, and intermediate results."""
944        ...
945
946    @contextmanager
947    def sub_context(self, propagate: Callable[[Definition], bool]) -> Generator[GlobalContextSets, None, None]:
948        """Create a sub-context with a separate cache from it's parent, but sharing any info that was
949        already present in the parent's cache.
950
951        For any intermediate results for a definition `d` for which `propagate(d)` evaluates to true,
952        the result is propagated to the parent's cache."""
953        ...
954
955    @staticmethod
956    def new_context() -> Generator[GlobalContextSets, None, None]:
957        """Crate a new caching context where global-context-set's can be retrieved and cached."""
958        ...
959
960def node_dependencies(n: Node, deps: set[Definition] | None = None) -> set[Definition]:
961    """Given a `Node` `n`, calculate the set of `Definition`'s that are directly reachable
962    from `n`. Transitively reachable definitions are not included.
963    """
964    ...
965
966def definition_dependencies(d: Definition) -> set[Definition]:
967    """Given a `Definition` `d`, calculate the set of `Definition`'s that are directly reachable for `d`.
968    Transitively reachable definitions are not included nor is `d` itself.
969    """
970    ...
@contextmanager
def file_dataset_reader( fname: pathlib.Path) -> collections.abc.Generator[pytact.graph_api_capnp_cython.Dataset_Reader, None, None]:
109@contextmanager
110def file_dataset_reader(fname: Path) -> Generator[apic.Dataset_Reader, None, None]:
111    """Load a single dataset file into memory, and expose its raw Cap'n Proto structures.
112
113    This is a low-level function. Prefer to use `data_reader` or `lowlevel_data_reader`.
114    """
115    ...

Load a single dataset file into memory, and expose its raw Cap'n Proto structures.

This is a low-level function. Prefer to use data_reader or lowlevel_data_reader.

class LowlevelDataReader:
117class LowlevelDataReader:
118    """A thin wrapper around the raw Cap'n Proto structures contained in a dataset directory.
119
120    Every file in the directory is assigned an integer called a graph-id. This class is a
121    `Sequence` that allows the retrieval of the structures in a file by its graph-id.
122    Additionally, the function `local_to_global` translates a dependency-index relative to
123    a graph-id to a new graph-id. This allows one to find out in which file a node in a
124    graph is located.
125
126    This is a lowlevel interface. For details on using the exposed structures the documentation
127    in the Cap'n Proto API file.
128    """
129
130    graphid_by_filename : dict[Path, int]
131    """Map from filenames in the data directory to their graph-id's."""
132
133    graph_files : list[Path]
134    """Map's a graph-id to a filename. Inverse of `graphid_by_filename`."""
135
136    def local_to_global(self, graph: int, dep_index: int) -> int:
137        """Convert a dependency-index relative to a graph-id to a new graph-id.
138
139        This is used to find the graph-id where a particular node can be found. If `graph` is the
140        graph-id that contains a reference to a node and `dep_index` is the relative location
141        where that node can be found then `local_to_global(graph, dep_index)` finds the graph-id
142        of the file where the node is physically located.
143        """
144        ...
145
146    def __getitem__(self, graph: int):
147        """Retrieve the raw Cap'n Proto structures associated with a graph-id."""
148        ...
149
150    def __len__(self) -> int: ...

A thin wrapper around the raw Cap'n Proto structures contained in a dataset directory.

Every file in the directory is assigned an integer called a graph-id. This class is a Sequence that allows the retrieval of the structures in a file by its graph-id. Additionally, the function local_to_global translates a dependency-index relative to a graph-id to a new graph-id. This allows one to find out in which file a node in a graph is located.

This is a lowlevel interface. For details on using the exposed structures the documentation in the Cap'n Proto API file.

graphid_by_filename: dict[pathlib.Path, int]

Map from filenames in the data directory to their graph-id's.

graph_files: list[pathlib.Path]

Map's a graph-id to a filename. Inverse of graphid_by_filename.

def local_to_global(self, graph: int, dep_index: int) -> int:
136    def local_to_global(self, graph: int, dep_index: int) -> int:
137        """Convert a dependency-index relative to a graph-id to a new graph-id.
138
139        This is used to find the graph-id where a particular node can be found. If `graph` is the
140        graph-id that contains a reference to a node and `dep_index` is the relative location
141        where that node can be found then `local_to_global(graph, dep_index)` finds the graph-id
142        of the file where the node is physically located.
143        """
144        ...

Convert a dependency-index relative to a graph-id to a new graph-id.

This is used to find the graph-id where a particular node can be found. If graph is the graph-id that contains a reference to a node and dep_index is the relative location where that node can be found then local_to_global(graph, dep_index) finds the graph-id of the file where the node is physically located.

@contextmanager
def lowlevel_data_reader( dataset_path: pathlib.Path) -> collections.abc.Generator[LowlevelDataReader, None, None]:
152@contextmanager
153def lowlevel_data_reader(dataset_path: Path) -> Generator[LowlevelDataReader, None, None]:
154    """Map a directory of dataset files into memory, and expose their raw Cap'n Proto structures.
155
156    Arguments:
157    `dataset_path`: Can either be a dataset directory, or a SquashFS image file. In case of an image
158                    file `dataset.squ`, the image will be mounted using `squashfuse` on directory
159                    `dataset/`, after which the contents of that directory will be read.
160
161    This is a low-level function. Prefer to use `data_reader`. See `LowlevelDataReader` for
162    further documentation.
163    """
164    ...

Map a directory of dataset files into memory, and expose their raw Cap'n Proto structures.

Arguments: dataset_path: Can either be a dataset directory, or a SquashFS image file. In case of an image file dataset.squ, the image will be mounted using squashfuse on directory dataset/, after which the contents of that directory will be read.

This is a low-level function. Prefer to use data_reader. See LowlevelDataReader for further documentation.

ProofStateId = <class 'int'>
TacticId = <class 'int'>
GraphId = <class 'int'>
NodeId = <class 'int'>
NodeHash = <class 'int'>
class Node:
172class Node:
173    """A node in the calculus of inductive construction graph.
174
175    A node has a `label`, a unique `identity` and `children`. Some nodes are also
176    a `Definition`.
177    """
178
179    graph : GraphId
180    """The id of the graph in which this node occurs. For lowlevel use only."""
181
182    nodeid : NodeId
183    """The local id of the node in the dataset. For lowlevel use only."""
184
185    def __repr__(self):
186        ...
187
188    def __eq__(self, other: object) -> bool:
189        """Physical equality of two nodes. Note that two nodes with a different physical equality
190        may have the same `identity`. See `identity` for details.
191        """
192        ...
193
194    def __hash__(self):
195        """A hash that is corresponds to physical equality, not to be confused by `identity`."""
196        ...
197
198    @property
199    def label(self) -> apic.Graph_Node_Label_Reader:
200        """The label of the node, indicating it's function in the CIC graph."""
201        ...
202
203    @property
204    def identity(self) -> NodeHash:
205        """The identity of a node uniquely determines it. That is, one can consider any to nodes with the same
206        identity to be equal. The notion of equal we use is as follows:
207        1. Graph perspective: Two nodes have the same identity if and only if they are bisimilar.
208           In this notion, bisimilarity does take into consideration the label of the nodes, modulo some
209           equivalence class that is not fully specified here. One aspect of the equivalence class is that
210           for definition nodes their associated global context (accessed through `Definition.previous`) is
211           not taken into account.
212        2. Lambda calculus perspective: Two nodes have the same identity if their corresponding lambda terms
213           are alpha-equivalent. Note that two definitions with the same body are not considered
214           alpha-equivalent.
215
216        The identity of a node is used to perform partial graph-sharing. That is, two nodes with the same
217        identity are merged when the graph is generated. There are two reasons why two nodes with the same
218        semantic identity might have a different physical identity:
219        1. Nodes are only merged when the first node exists in the same graph as the second node, or exists
220           in a dependent graph. Hence, nodes originating from developments that do not depend on each other
221           are never merged. Full graph-sharing would require global analysis on a dataset, which any consumer
222           can optionally do as a post-processing step.
223        2. Two definition nodes with the same name and body have the same identity. But if they occur in
224           different global contexts, these nodes are physically different to ensure the integrity of their
225           global contexts.
226
227        Beware that the identity is currently a 64 bit field. For datasets that have graphs of size in the
228        order of billions of nodes there is a non-trivial chance of a collision. (We consider this acceptable
229        for machine learning purposes.)
230        """
231        ...
232
233    @property
234    def children(self) -> Sequence[tuple[int, Node]]:
235        """The children of a node, together with the labels of the edges towards the children.
236        Note that for efficiency purposes, the label is represented as an integer. The corresponding
237        enum of this integer is `graph_api_capnp.EdgeClassification`."""
238        ...
239
240    @property
241    def definition(self) -> Definition | None:
242        """Some nodes in the CIC graph represent definitions. Such nodes contain extra information about the
243        definition.
244        """
245        ...

A node in the calculus of inductive construction graph.

A node has a label, a unique identity and children. Some nodes are also a Definition.

graph: int

The id of the graph in which this node occurs. For lowlevel use only.

nodeid: int

The local id of the node in the dataset. For lowlevel use only.

The label of the node, indicating it's function in the CIC graph.

identity: int

The identity of a node uniquely determines it. That is, one can consider any to nodes with the same identity to be equal. The notion of equal we use is as follows:

  1. Graph perspective: Two nodes have the same identity if and only if they are bisimilar. In this notion, bisimilarity does take into consideration the label of the nodes, modulo some equivalence class that is not fully specified here. One aspect of the equivalence class is that for definition nodes their associated global context (accessed through Definition.previous) is not taken into account.
  2. Lambda calculus perspective: Two nodes have the same identity if their corresponding lambda terms are alpha-equivalent. Note that two definitions with the same body are not considered alpha-equivalent.

The identity of a node is used to perform partial graph-sharing. That is, two nodes with the same identity are merged when the graph is generated. There are two reasons why two nodes with the same semantic identity might have a different physical identity:

  1. Nodes are only merged when the first node exists in the same graph as the second node, or exists in a dependent graph. Hence, nodes originating from developments that do not depend on each other are never merged. Full graph-sharing would require global analysis on a dataset, which any consumer can optionally do as a post-processing step.
  2. Two definition nodes with the same name and body have the same identity. But if they occur in different global contexts, these nodes are physically different to ensure the integrity of their global contexts.

Beware that the identity is currently a 64 bit field. For datasets that have graphs of size in the order of billions of nodes there is a non-trivial chance of a collision. (We consider this acceptable for machine learning purposes.)

children: collections.abc.Sequence[tuple[int, Node]]

The children of a node, together with the labels of the edges towards the children. Note that for efficiency purposes, the label is represented as an integer. The corresponding enum of this integer is graph_api_capnp.EdgeClassification.

definition: Definition | None

Some nodes in the CIC graph represent definitions. Such nodes contain extra information about the definition.

class ProofState:
247class ProofState:
248    """A proof state represents a particular point in the tactical proof of a constant."""
249
250    @property
251    def lowlevel(self):
252        ...
253    def __repr__(self):
254        ...
255
256    @property
257    def root(self) -> Node:
258        """The entry-point of the proof state, all nodes that are 'part of' the proof state are
259        reachable from here."""
260        ...
261
262    @property
263    def context(self) -> Sequence[Node]:
264        """The local context of the proof state, given as a tuple of their original name as they appeared in the
265        proof and the corresponding node.
266
267        The nodes always have either label `contextAssum` or `contextDef`.
268        Note that these nodes are also reachable from the root of the proof state.
269
270        The names of the context elements should be used for debugging and viewing purposes only, because
271        hypothesis-generating tactics have been modified to use auto-generated names. Hence, tactics should
272        not be concerned about the names of the context.
273        """
274        ...
275
276    @property
277    def context_names(self) -> Sequence[str]:
278        """The names of the local context nodes of the proof state, as they originally appeared in the proof.
279
280        These names should be used for debugging and viewing purposes only, because hypothesis-generating tactics have
281        been modified to use auto-generated names. Hence, tactics should not be concerned about the names of
282        the context.
283        """
284        ...
285
286    @property
287    def context_text(self) -> Sequence[str]:
288        """A textual representation of the type/definition of context nodes
289        """
290        ...
291
292    @property
293    def conclusion_text(self) -> str:
294        """A textual representation of the conclusion of the proof state.
295        """
296        ...
297
298    @property
299    def text(self) -> str:
300        """A textual representation of the proof state."""
301        ...
302
303    def __str__(self) -> str:
304        ...
305
306    @property
307    def id(self) -> ProofStateId:
308        """
309        A unique identifier of the proof state. Any two proof states in a tactical proof that have an equal id
310        can morally be regarded to be 'the same' proof state.
311        IMPORTANT: Two proof states with the same id may still have different contents. This is because proof states
312                   can contain existential variables (represented by the `evar` node) that can be filled as a
313                   side-effect by a tactic running on another proof state.
314        """
315        ...

A proof state represents a particular point in the tactical proof of a constant.

lowlevel
root: Node

The entry-point of the proof state, all nodes that are 'part of' the proof state are reachable from here.

context: collections.abc.Sequence[Node]

The local context of the proof state, given as a tuple of their original name as they appeared in the proof and the corresponding node.

The nodes always have either label contextAssum or contextDef. Note that these nodes are also reachable from the root of the proof state.

The names of the context elements should be used for debugging and viewing purposes only, because hypothesis-generating tactics have been modified to use auto-generated names. Hence, tactics should not be concerned about the names of the context.

context_names: collections.abc.Sequence[str]

The names of the local context nodes of the proof state, as they originally appeared in the proof.

These names should be used for debugging and viewing purposes only, because hypothesis-generating tactics have been modified to use auto-generated names. Hence, tactics should not be concerned about the names of the context.

context_text: collections.abc.Sequence[str]

A textual representation of the type/definition of context nodes

conclusion_text: str

A textual representation of the conclusion of the proof state.

text: str

A textual representation of the proof state.

id: int

A unique identifier of the proof state. Any two proof states in a tactical proof that have an equal id can morally be regarded to be 'the same' proof state. IMPORTANT: Two proof states with the same id may still have different contents. This is because proof states can contain existential variables (represented by the evar node) that can be filled as a side-effect by a tactic running on another proof state.

Unresolvable: TypeAlias = None
Unknown: TypeAlias = None
class Outcome:
319class Outcome:
320    """An outcome is the result of running a tactic on a proof state. A tactic may run on multiple proof states."""
321
322    tactic : apic.Tactic_Reader | Unknown
323    """The tactic that generated the outcome. For it's arguments, see `tactic_arguments`
324
325    Sometimes a tactic cannot or should not be recorded. In those cases, it is marked as 'unknown'.
326    This currently happens with tactics that are run as a result of the `Proof with tac` construct and it
327    happens for tactics that are known to be unsafe like `change_no_check`, `fix`, `cofix` and more.
328    """
329
330    @property
331    def lowlevel(self):
332        ...
333    def __repr__(self):
334        ...
335
336    @property
337    def before(self) -> ProofState:
338        """The proof state before the tactic execution."""
339        ...
340
341    @property
342    def after(self) -> Sequence[ProofState]:
343        """The new proof states that were generated by the tactic."""
344        ...
345
346    @property
347    def term(self) -> Node:
348        """The proof term that witnesses the transition from the before state to the after states. It contains a
349        hole (an `evar` node) for each of the after states. It may also refer to elements of the local context of
350        the before state.
351        """
352        ...
353
354    @property
355    def term_text(self) -> str:
356        """A textual representation of the proof term."""
357        ...
358
359    @property
360    def tactic_arguments(self) -> Sequence[Node | Unresolvable]:
361        """The arguments of the tactic that produced this outcome.
362
363        The node is the root of a graph representing an argument that is a term in the calculus of constructions.
364        Sometimes, an argument is not resolvable to a term, in which case it is marked as `Unresolvable`.
365        """
366        ...

An outcome is the result of running a tactic on a proof state. A tactic may run on multiple proof states.

The tactic that generated the outcome. For it's arguments, see tactic_arguments

Sometimes a tactic cannot or should not be recorded. In those cases, it is marked as 'unknown'. This currently happens with tactics that are run as a result of the Proof with tac construct and it happens for tactics that are known to be unsafe like change_no_check, fix, cofix and more.

lowlevel
before: ProofState

The proof state before the tactic execution.

after: collections.abc.Sequence[ProofState]

The new proof states that were generated by the tactic.

term: Node

The proof term that witnesses the transition from the before state to the after states. It contains a hole (an evar node) for each of the after states. It may also refer to elements of the local context of the before state.

term_text: str

A textual representation of the proof term.

tactic_arguments: collections.abc.Sequence[Node | None]

The arguments of the tactic that produced this outcome.

The node is the root of a graph representing an argument that is a term in the calculus of constructions. Sometimes, an argument is not resolvable to a term, in which case it is marked as Unresolvable.

class ProofStep:
368class ProofStep:
369    """A proof step is the execution of a single tactic on one or more proof states, producing a list of outcomes.
370    """
371
372    @property
373    def lowlevel(self):
374        ...
375    def __repr__(self):
376        ...
377
378    @property
379    def tactic(self) -> apic.Tactic_Reader | Unknown:
380        """The tactic that generated the proof step. Note that the arguments of the tactic can be found in the
381        individual outcomes, because they may be different for each outcome.
382
383        Sometimes a tactic cannot or should not be recorded. In those cases, it is marked as 'unknown'.
384        This currently happens with tactics that are run as a result of the `Proof with tac` construct and it
385        happens for tactics that are known to be unsafe like `change_no_check`, `fix`, `cofix` and more.
386        """
387        ...
388
389    @property
390    def outcomes(self) -> Sequence[Outcome]:
391        """A list of transformations of proof states to other proof states, as executed by the tactic of the proof
392        step
393        """
394        ...

A proof step is the execution of a single tactic on one or more proof states, producing a list of outcomes.

lowlevel

The tactic that generated the proof step. Note that the arguments of the tactic can be found in the individual outcomes, because they may be different for each outcome.

Sometimes a tactic cannot or should not be recorded. In those cases, it is marked as 'unknown'. This currently happens with tactics that are run as a result of the Proof with tac construct and it happens for tactics that are known to be unsafe like change_no_check, fix, cofix and more.

outcomes: collections.abc.Sequence[Outcome]

A list of transformations of proof states to other proof states, as executed by the tactic of the proof step

@dataclass
class Original:
396@dataclass
397class Original:
398    """Token that signals that a definition is original, as inputted by the
399    user."""
400    pass

Token that signals that a definition is original, as inputted by the user.

@dataclass
class Discharged:
402@dataclass
403class Discharged:
404    """Token that signals that a definition is derived from an original after
405    section closing."""
406
407    original: Definition

Token that signals that a definition is derived from an original after section closing.

Discharged(original: Definition)
original: Definition
@dataclass
class Substituted:
409@dataclass
410class Substituted:
411    """Token that signals that a definition is derived from an original after
412    module functor instantiation."""
413
414    original: Definition

Token that signals that a definition is derived from an original after module functor instantiation.

Substituted(original: Definition)
original: Definition
@dataclass
class Inductive:
416@dataclass
417class Inductive:
418    """Token that signals that a definition is inductive."""
419
420    representative: Definition
421    """The representative of the mutually recursive cluster. For lowlevel use only"""

Token that signals that a definition is inductive.

Inductive(representative: Definition)
representative: Definition

The representative of the mutually recursive cluster. For lowlevel use only

@dataclass
class Constructor:
423@dataclass
424class Constructor:
425    """Token that signals that a definition is a constructor."""
426
427    representative: Definition
428    """The representative of the mutually recursive cluster. For lowlevel use only"""

Token that signals that a definition is a constructor.

Constructor(representative: Definition)
representative: Definition

The representative of the mutually recursive cluster. For lowlevel use only

@dataclass
class Projection:
430@dataclass
431class Projection:
432    """Token that signals that a definition is a projection."""
433
434    representative: Definition
435    """The representative of the mutually recursive cluster. For lowlevel use only"""

Token that signals that a definition is a projection.

Projection(representative: Definition)
representative: Definition

The representative of the mutually recursive cluster. For lowlevel use only

@dataclass
class ManualConstant:
437@dataclass
438class ManualConstant:
439    """Token that signals that a definition was inputted by the user by
440    manually inputting a term."""
441    pass

Token that signals that a definition was inputted by the user by manually inputting a term.

@dataclass
class TacticalConstant:
443@dataclass
444class TacticalConstant:
445    """Token that signals that a lemma was proved by the user using
446    a tactic proof."""
447
448    proof: Sequence[ProofStep]
449    """The proof of the lemma."""

Token that signals that a lemma was proved by the user using a tactic proof.

TacticalConstant(proof: collections.abc.Sequence[ProofStep])
proof: collections.abc.Sequence[ProofStep]

The proof of the lemma.

@dataclass
class ManualSectionConstant:
451@dataclass
452class ManualSectionConstant:
453    """Token that signals that a constant is a section variable or let-construct."""
454    pass

Token that signals that a constant is a section variable or let-construct.

@dataclass
class TacticalSectionConstant:
456@dataclass
457class TacticalSectionConstant:
458    """Token that signals that a constant is a section let-construct with a tactic proof."""
459
460    proof: Sequence[ProofStep]
461    """The proof of the lemma."""

Token that signals that a constant is a section let-construct with a tactic proof.

TacticalSectionConstant(proof: collections.abc.Sequence[ProofStep])
proof: collections.abc.Sequence[ProofStep]

The proof of the lemma.

class Definition:
463class Definition:
464    """A definition of the CIC, which is either a constant, inductive, constructor, projection or section
465    variable. Constants and section variables can have tactical proofs associated to them.
466    """
467
468    node : Node
469    """The node that is associated with this definition. It holds that
470    `definition.node.definition == definition`.
471    """
472
473    @property
474    def lowlevel(self):
475        ...
476    def __repr__(self):
477        ...
478
479    def __eq__(self, other: object) -> bool:
480        """Physical equality of two nodes. Note that two nodes with a different physical equality
481        may have the same `identity`. See `identity` for details.
482        """
483        ...
484
485    def __hash__(self):
486        """A hash that is corresponds to physical equality, not to be confused by `identity`."""
487        ...
488
489    @property
490    def name(self) -> str:
491        """The fully-qualified name of the definition. The name should be unique in a particular global context,
492        but is not unique among different branches of the global in a dataset.
493        """
494        ...
495
496    @property
497    def previous(self) -> Definition | None:
498        """The previous definition within the global context of the current file.
499
500        Note that this is a lowlevel property. Prefer to use `global_context` or `clustered_global_context`.
501
502        The contract on this field is that any definition nodes reachable from the forward closure of the definition
503        must also be reachable through the chain of previous fields. An exception to this rule are mutually
504        recursive definitions. Those nodes are placed into the global context in an arbitrary ordering.
505        """
506        ...
507
508    @property
509    def external_previous(self) -> Sequence[Definition]:
510        """A list of definitions that are the representatives of files other than the current file that are
511        part of the global context. This list becomes populated when a `Require` statement occurred right before
512        the definition.
513
514        Note that this is a lowlevel property. Prefer to use `global_context` or `clustered_global_context`.
515        """
516        ...
517
518    def global_context(self, across_files : bool = True, inclusive = False) -> Iterable[Definition]:
519        """All of the definitions in the global context when this definition was created.
520
521        Note that this does not include this definition itself, except when the definition is a inductive,
522        constructor or projection. Because those are mutually recursive objects, they reference themselves
523        and are therefore part of their own global context.
524
525        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
526        definition reachable from the forward closure of the definition also exists in the remainder of the
527        stream. An exception to this rule are mutually recursive definitions, because no topological sort
528        is possible there (see also `clustered_global_context`).
529
530        Arguments:
531        * `across_files`: if `False`, outputs only the definitions from the local file, default `True`.
532        * `inclusive`: if `True`, outputs also itself, default `False`.
533        Note: if it is a self-recursive definition, the `inclusive` argument is ignored, and considered as `True`
534        """
535        ...
536
537    def clustered_global_context(self, across_files : bool = True, inclusive : bool = False) -> Iterable[list[Definition]]:
538        """All of the definitions in the global context when this definition was created, clustered into
539        mutually recursive cliques.
540
541        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
542        definition reachable from the forward closure of the definition also exists in the remainder of the
543        stream.
544
545        Arguments:
546        * `across_files`: if `False`, outputs only the definitions from the local file, default `True`.
547        * `inclusive`: if `True`, outputs also the cluster of itself, default `False`.
548        Note: if it is a self-recursive definition, the `inclusive` argument is ignored, and considered as `True`.
549        """
550        ...
551
552    @property
553    def status(self) -> Original | Discharged | Substituted:
554        """
555        A definition is either
556        (1) an object as originally inputted by the user.
557        (2) a definition that was originally defined in a section and has now had the section
558            variables discharged into it.
559        (3) a definition that was obtained by performing some sort of module functor substitution.
560        When a definition is not original, we cross-reference to the definition that it was derived from.
561        """
562        ...
563
564    @property
565    def kind(self) -> Union[Inductive, Constructor, Projection,
566                            ManualConstant, TacticalConstant,
567                            ManualSectionConstant, TacticalSectionConstant]:
568        """The kind of the definition.
569
570        It can be an constant, section constant, inductive, constructor or projection. In case of a constant
571        of a constant or section constant, an optional tactical proof can be associated. In case of an inductive,
572        constructor or projection, another definition that acts as the representative of the mutually recursive
573        cluster of definitions is associated.
574
575        The associated information is low-level. Prefer to use the properties `proof` and `cluster` to access them.
576        """
577        ...
578
579    @property
580    def proof(self) -> Sequence[ProofStep] | None:
581        """An optional tactical proof that was used to create this definition."""
582        ...
583
584    @property
585    def cluster_representative(self) -> Definition:
586        """A unique representative of the mutually recursive cluster of definitions this definition is part of.
587        If the definition is not mutually recursive, the representative is itself.
588
589        This is a low-level property. Prefer to use the `cluster` property.
590        """
591        ...
592
593    @property
594    def cluster(self) -> Iterable[Definition]:
595        """The cluster of mutually recursive definitions that this definition is part of.
596        If the definition is not mutually recursive, the cluster is a singleton."""
597        ...
598
599    @property
600    def type_text(self) -> str:
601        """A textual representation of the type of this definition."""
602        ...
603
604    @property
605    def term_text(self) -> str | None:
606        """A textual representation of the body of this definition.
607        For inductives, constructors, projections, section variables and axioms this is `None`.
608        """
609        ...
610
611    @property
612    def is_file_representative(self) -> bool:
613        """Returns true if this definition is the representative of the super-global context of it's file.
614        Se also `Dataset.representative`."""
615        ...

A definition of the CIC, which is either a constant, inductive, constructor, projection or section variable. Constants and section variables can have tactical proofs associated to them.

node: Node

The node that is associated with this definition. It holds that definition.node.definition == definition.

lowlevel
name: str

The fully-qualified name of the definition. The name should be unique in a particular global context, but is not unique among different branches of the global in a dataset.

previous: Definition | None

The previous definition within the global context of the current file.

Note that this is a lowlevel property. Prefer to use global_context or clustered_global_context.

The contract on this field is that any definition nodes reachable from the forward closure of the definition must also be reachable through the chain of previous fields. An exception to this rule are mutually recursive definitions. Those nodes are placed into the global context in an arbitrary ordering.

external_previous: collections.abc.Sequence[Definition]

A list of definitions that are the representatives of files other than the current file that are part of the global context. This list becomes populated when a Require statement occurred right before the definition.

Note that this is a lowlevel property. Prefer to use global_context or clustered_global_context.

def global_context( self, across_files: bool = True, inclusive=False) -> collections.abc.Iterable[Definition]:
518    def global_context(self, across_files : bool = True, inclusive = False) -> Iterable[Definition]:
519        """All of the definitions in the global context when this definition was created.
520
521        Note that this does not include this definition itself, except when the definition is a inductive,
522        constructor or projection. Because those are mutually recursive objects, they reference themselves
523        and are therefore part of their own global context.
524
525        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
526        definition reachable from the forward closure of the definition also exists in the remainder of the
527        stream. An exception to this rule are mutually recursive definitions, because no topological sort
528        is possible there (see also `clustered_global_context`).
529
530        Arguments:
531        * `across_files`: if `False`, outputs only the definitions from the local file, default `True`.
532        * `inclusive`: if `True`, outputs also itself, default `False`.
533        Note: if it is a self-recursive definition, the `inclusive` argument is ignored, and considered as `True`
534        """
535        ...

All of the definitions in the global context when this definition was created.

Note that this does not include this definition itself, except when the definition is a inductive, constructor or projection. Because those are mutually recursive objects, they reference themselves and are therefore part of their own global context.

The resulting iterable is topologically sorted. That is, for any definition in the stream, any definition reachable from the forward closure of the definition also exists in the remainder of the stream. An exception to this rule are mutually recursive definitions, because no topological sort is possible there (see also clustered_global_context).

Arguments:

  • across_files: if False, outputs only the definitions from the local file, default True.
  • inclusive: if True, outputs also itself, default False. Note: if it is a self-recursive definition, the inclusive argument is ignored, and considered as True
def clustered_global_context( self, across_files: bool = True, inclusive: bool = False) -> collections.abc.Iterable[list[Definition]]:
537    def clustered_global_context(self, across_files : bool = True, inclusive : bool = False) -> Iterable[list[Definition]]:
538        """All of the definitions in the global context when this definition was created, clustered into
539        mutually recursive cliques.
540
541        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
542        definition reachable from the forward closure of the definition also exists in the remainder of the
543        stream.
544
545        Arguments:
546        * `across_files`: if `False`, outputs only the definitions from the local file, default `True`.
547        * `inclusive`: if `True`, outputs also the cluster of itself, default `False`.
548        Note: if it is a self-recursive definition, the `inclusive` argument is ignored, and considered as `True`.
549        """
550        ...

All of the definitions in the global context when this definition was created, clustered into mutually recursive cliques.

The resulting iterable is topologically sorted. That is, for any definition in the stream, any definition reachable from the forward closure of the definition also exists in the remainder of the stream.

Arguments:

  • across_files: if False, outputs only the definitions from the local file, default True.
  • inclusive: if True, outputs also the cluster of itself, default False. Note: if it is a self-recursive definition, the inclusive argument is ignored, and considered as True.

A definition is either (1) an object as originally inputted by the user. (2) a definition that was originally defined in a section and has now had the section variables discharged into it. (3) a definition that was obtained by performing some sort of module functor substitution. When a definition is not original, we cross-reference to the definition that it was derived from.

The kind of the definition.

It can be an constant, section constant, inductive, constructor or projection. In case of a constant of a constant or section constant, an optional tactical proof can be associated. In case of an inductive, constructor or projection, another definition that acts as the representative of the mutually recursive cluster of definitions is associated.

The associated information is low-level. Prefer to use the properties proof and cluster to access them.

proof: collections.abc.Sequence[ProofStep] | None

An optional tactical proof that was used to create this definition.

cluster_representative: Definition

A unique representative of the mutually recursive cluster of definitions this definition is part of. If the definition is not mutually recursive, the representative is itself.

This is a low-level property. Prefer to use the cluster property.

cluster: collections.abc.Iterable[Definition]

The cluster of mutually recursive definitions that this definition is part of. If the definition is not mutually recursive, the cluster is a singleton.

type_text: str

A textual representation of the type of this definition.

term_text: str | None

A textual representation of the body of this definition. For inductives, constructors, projections, section variables and axioms this is None.

is_file_representative: bool

Returns true if this definition is the representative of the super-global context of it's file. Se also Dataset.representative.

class Dataset:
617class Dataset:
618    """The data corresponding to a single Coq source file. The data contains a representation of all definitions
619    that have existed at any point throughout the compilation of the source file.
620    """
621
622    graph : GraphId
623    filename : Path
624    """The physical file in which the data contained in this class can be found."""
625
626    @property
627    def lowlevel(self):
628        ...
629    def __repr__(self):
630        ...
631
632    @property
633    def dependencies(self) -> Sequence[Path]:
634        """A list of physical paths of data files that are direct dependencies of this file.
635
636        It is guaranteed that no cycles exist in the dependency relation between files induced by this field.
637        """
638        ...
639
640    @property
641    def representative(self) -> Definition | None:
642        """The entry point of the global context of definitions that are available when this file is 'Required' by
643        another file. The full global context can be obtained by following the `previous` node of definitions.
644        If the compilation unit does not contain any 'super'-global definitions this may be `None`.
645
646        This is a low-level property.
647        Prefer to use `definitions(spine_only = True)` and `clustered_definitions(spine_only=True)`.
648        """
649        ...
650
651    def definitions(self, across_files = False, spine_only = False) -> Iterable[Definition]:
652        """All of the definitions present in the file.
653        Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside
654        of sections or module functors.
655
656        Arguments:
657        * `across_files`: if `True`, outputs also definitions from dependent files, default `False`.
658        * `spine_only`: if True, outputs only the definitions on the main spine, default `False`.
659        Note: `across_files = True` is incompatible with `spine_only = False`.
660
661        When `spine_only = True`, the resulting iterable is topologically sorted. That is, for
662        any definition in the stream, any definition reachable from the forward closure of the definition
663        also exists in the remainder of the stream. An exception to this rule are mutually recursive definitions,
664        because no topological sort is possible there (see also `clustered_definitions`).
665        """
666        ...
667
668    def clustered_definitions(self, across_files = False, spine_only = False) -> Iterable[list[Definition]]:
669        """All of the definitions present in the file, clustered by mutually recursive definitions.
670        Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside
671        of sections or module functors.
672
673        Arguments:
674        * `across_files`: if `True`, outputs also definitions from dependent files, default `False`.
675        * `spine_only`: if `True`, outputs only the definitions on the main spine, default `False`.
676        Note: `across_files = True` is incompatible with `spine_only = False`.
677
678        When `spine_only = True`, the resulting iterable is topologically sorted. That is, for
679        any definition in the stream, any definition reachable from the forward closure of the definition
680        also exists in the remainder of the stream.
681        """
682        ...
683
684    @property
685    def module_name(self) -> str:
686        ...
687
688    def node_by_id(self, nodeid: NodeId) -> Node:
689        """Lookup a node inside of this file by it's local node-id. This is a low-level function."""
690        ...

The data corresponding to a single Coq source file. The data contains a representation of all definitions that have existed at any point throughout the compilation of the source file.

graph: int
filename: pathlib.Path

The physical file in which the data contained in this class can be found.

lowlevel
dependencies: collections.abc.Sequence[pathlib.Path]

A list of physical paths of data files that are direct dependencies of this file.

It is guaranteed that no cycles exist in the dependency relation between files induced by this field.

representative: Definition | None

The entry point of the global context of definitions that are available when this file is 'Required' by another file. The full global context can be obtained by following the previous node of definitions. If the compilation unit does not contain any 'super'-global definitions this may be None.

This is a low-level property. Prefer to use definitions(spine_only = True) and clustered_definitions(spine_only=True).

def definitions( self, across_files=False, spine_only=False) -> collections.abc.Iterable[Definition]:
651    def definitions(self, across_files = False, spine_only = False) -> Iterable[Definition]:
652        """All of the definitions present in the file.
653        Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside
654        of sections or module functors.
655
656        Arguments:
657        * `across_files`: if `True`, outputs also definitions from dependent files, default `False`.
658        * `spine_only`: if True, outputs only the definitions on the main spine, default `False`.
659        Note: `across_files = True` is incompatible with `spine_only = False`.
660
661        When `spine_only = True`, the resulting iterable is topologically sorted. That is, for
662        any definition in the stream, any definition reachable from the forward closure of the definition
663        also exists in the remainder of the stream. An exception to this rule are mutually recursive definitions,
664        because no topological sort is possible there (see also `clustered_definitions`).
665        """
666        ...

All of the definitions present in the file. Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside of sections or module functors.

Arguments:

  • across_files: if True, outputs also definitions from dependent files, default False.
  • spine_only: if True, outputs only the definitions on the main spine, default False. Note: across_files = True is incompatible with spine_only = False.

When spine_only = True, the resulting iterable is topologically sorted. That is, for any definition in the stream, any definition reachable from the forward closure of the definition also exists in the remainder of the stream. An exception to this rule are mutually recursive definitions, because no topological sort is possible there (see also clustered_definitions).

def clustered_definitions( self, across_files=False, spine_only=False) -> collections.abc.Iterable[list[Definition]]:
668    def clustered_definitions(self, across_files = False, spine_only = False) -> Iterable[list[Definition]]:
669        """All of the definitions present in the file, clustered by mutually recursive definitions.
670        Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside
671        of sections or module functors.
672
673        Arguments:
674        * `across_files`: if `True`, outputs also definitions from dependent files, default `False`.
675        * `spine_only`: if `True`, outputs only the definitions on the main spine, default `False`.
676        Note: `across_files = True` is incompatible with `spine_only = False`.
677
678        When `spine_only = True`, the resulting iterable is topologically sorted. That is, for
679        any definition in the stream, any definition reachable from the forward closure of the definition
680        also exists in the remainder of the stream.
681        """
682        ...

All of the definitions present in the file, clustered by mutually recursive definitions. Note that some of these nodes may not be part of the 'super-global' context. Those are definitions inside of sections or module functors.

Arguments:

  • across_files: if True, outputs also definitions from dependent files, default False.
  • spine_only: if True, outputs only the definitions on the main spine, default False. Note: across_files = True is incompatible with spine_only = False.

When spine_only = True, the resulting iterable is topologically sorted. That is, for any definition in the stream, any definition reachable from the forward closure of the definition also exists in the remainder of the stream.

module_name: str
def node_by_id(self, nodeid: int) -> Node:
688    def node_by_id(self, nodeid: NodeId) -> Node:
689        """Lookup a node inside of this file by it's local node-id. This is a low-level function."""
690        ...

Lookup a node inside of this file by it's local node-id. This is a low-level function.

def lowlevel_to_highlevel( lreader: LowlevelDataReader) -> dict[pathlib.Path, Dataset]:
692def lowlevel_to_highlevel(lreader : LowlevelDataReader) -> dict[Path, Dataset]:
693    """Convert a dataset initialized as a `LowLevelDataReader` into a high level interface."""
694    ...

Convert a dataset initialized as a LowLevelDataReader into a high level interface.

@contextmanager
def data_reader( dataset_path: pathlib.Path) -> collections.abc.Generator[dict[pathlib.Path, Dataset], None, None]:
696@contextmanager
697def data_reader(dataset_path: Path) -> Generator[dict[Path, Dataset], None, None]:
698    """Load a directory of dataset files into memory, and expose the data they contain.
699    The result is a dictionary that maps physical paths to `Dataset` instances that allow access to the data.
700
701    Arguments:
702    `dataset_path`: Can either be a dataset directory, or a SquashFS image file. In case of an image
703                    file `dataset.squ`, the image will be mounted using `squashfuse` on directory
704                    `dataset/`, after which the contents of that directory will be read.
705
706    """
707    ...

Load a directory of dataset files into memory, and expose the data they contain. The result is a dictionary that maps physical paths to Dataset instances that allow access to the data.

Arguments: dataset_path: Can either be a dataset directory, or a SquashFS image file. In case of an image file dataset.squ, the image will be mounted using squashfuse on directory dataset/, after which the contents of that directory will be read.

class OnlineDefinitionsReader:
709class OnlineDefinitionsReader:
710    """This class represents a global context to Python by Coq, containing all
711    known definitions and available tactics."""
712
713    def local_to_global(self, graph: int, dep_index: int) -> int:
714        """Convert a dependency-index relative to a graph-id to a new graph-id.
715
716        This is used to find the graph-id where a particular node can be found. If `graph` is the
717        graph-id that contains a reference to a node and `dep_index` is the relative location
718        where that node can be found then `local_to_global(graph, dep_index)` finds the index in
719        the global context stack where the node is physically located.
720
721        Lowlevel function.
722        """
723        ...
724
725    @property
726    def representative(self) -> Definition | None:
727        """The last definition in the global context. All other definitions can be accessed by following
728        the `Definition.previous` chain starting from this definitions.
729
730        This is a low-level property.
731        Prefer to use `definitions` and `clustered_definitions`.
732        """
733        ...
734
735    def definitions(self, full : bool = True) -> Iterable[Definition]:
736        """The list of definitions that are currently in the global context.
737
738        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
739        definition reachable from the forward closure of the definition also exists in the remainder of
740        the stream. An exception to this rule are mutually recursive definitions,
741        because no topological sort is possible there (see also `clustered_definitions`).
742        """
743        ...
744
745    def clustered_definitions(self, full : bool = True) -> Iterable[list[Definition]]:
746        """All of the definitions present in the global context, clustered by mutually recursive definitions.
747
748        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
749        definition reachable from the forward closure of the definition also exists in the remainder of
750        the stream.
751        """
752        ...

This class represents a global context to Python by Coq, containing all known definitions and available tactics.

def local_to_global(self, graph: int, dep_index: int) -> int:
713    def local_to_global(self, graph: int, dep_index: int) -> int:
714        """Convert a dependency-index relative to a graph-id to a new graph-id.
715
716        This is used to find the graph-id where a particular node can be found. If `graph` is the
717        graph-id that contains a reference to a node and `dep_index` is the relative location
718        where that node can be found then `local_to_global(graph, dep_index)` finds the index in
719        the global context stack where the node is physically located.
720
721        Lowlevel function.
722        """
723        ...

Convert a dependency-index relative to a graph-id to a new graph-id.

This is used to find the graph-id where a particular node can be found. If graph is the graph-id that contains a reference to a node and dep_index is the relative location where that node can be found then local_to_global(graph, dep_index) finds the index in the global context stack where the node is physically located.

Lowlevel function.

representative: Definition | None

The last definition in the global context. All other definitions can be accessed by following the Definition.previous chain starting from this definitions.

This is a low-level property. Prefer to use definitions and clustered_definitions.

def definitions( self, full: bool = True) -> collections.abc.Iterable[Definition]:
735    def definitions(self, full : bool = True) -> Iterable[Definition]:
736        """The list of definitions that are currently in the global context.
737
738        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
739        definition reachable from the forward closure of the definition also exists in the remainder of
740        the stream. An exception to this rule are mutually recursive definitions,
741        because no topological sort is possible there (see also `clustered_definitions`).
742        """
743        ...

The list of definitions that are currently in the global context.

The resulting iterable is topologically sorted. That is, for any definition in the stream, any definition reachable from the forward closure of the definition also exists in the remainder of the stream. An exception to this rule are mutually recursive definitions, because no topological sort is possible there (see also clustered_definitions).

def clustered_definitions( self, full: bool = True) -> collections.abc.Iterable[list[Definition]]:
745    def clustered_definitions(self, full : bool = True) -> Iterable[list[Definition]]:
746        """All of the definitions present in the global context, clustered by mutually recursive definitions.
747
748        The resulting iterable is topologically sorted. That is, for any definition in the stream, any
749        definition reachable from the forward closure of the definition also exists in the remainder of
750        the stream.
751        """
752        ...

All of the definitions present in the global context, clustered by mutually recursive definitions.

The resulting iterable is topologically sorted. That is, for any definition in the stream, any definition reachable from the forward closure of the definition also exists in the remainder of the stream.

@contextmanager
def online_definitions_initialize( stack: OnlineDefinitionsReader, init: pytact.graph_api_capnp_cython.PredictionProtocol_Request_Initialize_Reader) -> collections.abc.Generator[OnlineDefinitionsReader, None, None]:
754@contextmanager
755def online_definitions_initialize(stack: OnlineDefinitionsReader,
756                                  init: apic.PredictionProtocol_Request_Initialize_Reader) -> Generator[OnlineDefinitionsReader, None, None]:
757    """Given a new initialization message sent by Coq, construct a
758    `OnlineDefinitiosnReader` object. This can be used to inspect the
759    definitions currently available. Additionally, using `online_data_predict`
760    it can be combined with a subsequent prediction request received from Coq
761    to build a `ProofState`.
762    """
763    ...

Given a new initialization message sent by Coq, construct a OnlineDefinitiosnReader object. This can be used to inspect the definitions currently available. Additionally, using online_data_predict it can be combined with a subsequent prediction request received from Coq to build a ProofState.

def empty_online_definitions_initialize() -> OnlineDefinitionsReader:
765def empty_online_definitions_initialize() -> OnlineDefinitionsReader:
766    ...
@contextmanager
def online_data_predict( base: OnlineDefinitionsReader, predict: pytact.graph_api_capnp_cython.PredictionProtocol_Request_Predict_Reader) -> collections.abc.Generator[ProofState, None, None]:
768@contextmanager
769def online_data_predict(base: OnlineDefinitionsReader,
770                        predict: apic.PredictionProtocol_Request_Predict_Reader) -> Generator[ProofState, None, None]:
771    """Given a `OnlineDefinitionsReader` instance constructed through
772    `online_data_initialize`, and a prediction message sent by Coq, construct a
773    `ProofState` object that represents the current proof state in Coq.
774    """
775    ...

Given a OnlineDefinitionsReader instance constructed through online_data_initialize, and a prediction message sent by Coq, construct a ProofState object that represents the current proof state in Coq.

@dataclass
class TacticPredictionGraph:
777@dataclass
778class TacticPredictionGraph:
779    ident : int
780    arguments : list[Node]
781    confidence : float
TacticPredictionGraph( ident: int, arguments: list[Node], confidence: float)
ident: int
arguments: list[Node]
confidence: float
@dataclass
class TacticPredictionsGraph:
783@dataclass
784class TacticPredictionsGraph:
785    predictions : list[TacticPredictionsGraph]
TacticPredictionsGraph(predictions: list[TacticPredictionsGraph])
predictions: list[TacticPredictionsGraph]
@dataclass
class TacticPredictionText:
787@dataclass
788class TacticPredictionText:
789    tactic_text : str
790    confidence : float
TacticPredictionText(tactic_text: str, confidence: float)
tactic_text: str
confidence: float
@dataclass
class TacticPredictionsText:
792@dataclass
793class TacticPredictionsText:
794    predictions : list[TacticPredictionsText]
TacticPredictionsText(predictions: list[TacticPredictionsText])
predictions: list[TacticPredictionsText]
@dataclass
class CheckAlignmentMessage:
796@dataclass
797class CheckAlignmentMessage:
798    pass
@dataclass
class CheckAlignmentResponse:
800@dataclass
801class CheckAlignmentResponse:
802    unknown_definitions : list[Definition]
803    unknown_tactics : list[int]
CheckAlignmentResponse( unknown_definitions: list[Definition], unknown_tactics: list[int])
unknown_definitions: list[Definition]
unknown_tactics: list[int]
@dataclass
class GlobalContextMessage:
805@dataclass
806class GlobalContextMessage:
807    """A message containing a new global context sent to Python from Coq,
808    including all known definitions and available tactics."""
809
810    definitions : OnlineDefinitionsReader
811    tactics : Sequence[apic.AbstractTactic_Reader]
812
813    log_annotation : str
814    """An annotation representing the current position of Coq in a source
815    document. For logging and debugging purposes."""
816
817    prediction_requests : Generator[GlobalContextMessage | ProofState | CheckAlignmentMessage,
818                                    None | TacticPredictionsGraph | TacticPredictionsText | CheckAlignmentResponse,
819                                    None]
820    """A sub-generator that produces new requests from Coq that are based on or
821    extend the global context of the current message. Once the sub-generator
822    runs out, the parent generator continues."""

A message containing a new global context sent to Python from Coq, including all known definitions and available tactics.

GlobalContextMessage( definitions: OnlineDefinitionsReader, tactics: collections.abc.Sequence[pytact.graph_api_capnp_cython.AbstractTactic_Reader], log_annotation: str, prediction_requests: collections.abc.Generator[GlobalContextMessage | ProofState | CheckAlignmentMessage, None | TacticPredictionsGraph | TacticPredictionsText | CheckAlignmentResponse, None])
tactics: collections.abc.Sequence[pytact.graph_api_capnp_cython.AbstractTactic_Reader]
log_annotation: str

An annotation representing the current position of Coq in a source document. For logging and debugging purposes.

A sub-generator that produces new requests from Coq that are based on or extend the global context of the current message. Once the sub-generator runs out, the parent generator continues.

def capnp_message_generator_lowlevel( socket: socket.socket) -> collections.abc.Generator[pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader, capnp.lib.capnp._DynamicStructBuilder, None]:
824def capnp_message_generator_lowlevel(socket: socket.socket) -> (
825        Generator[apic.PredictionProtocol_Request_Reader,
826                  capnp.lib.capnp._DynamicStructBuilder, None]):
827    """A generator that facilitates communication between a prediction server and a Coq process.
828
829    Given a `socket`, this function creates a generator that yields messages of type
830    `pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader` after which a
831    `capnp.lib.capnp._DynamicStructBuilder` message needs to be `send` back.
832    """
833    ...

A generator that facilitates communication between a prediction server and a Coq process.

Given a socket, this function creates a generator that yields messages of type pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader after which a capnp.lib.capnp._DynamicStructBuilder message needs to be send back.

def capnp_message_generator_from_file_lowlevel( message_file: <class 'BinaryIO'>, check: Optional[Callable[[Any, Any, Any], NoneType]] = None) -> collections.abc.Generator[pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader, capnp.lib.capnp._DynamicStructBuilder, None]:
835def capnp_message_generator_from_file_lowlevel(
836        message_file: BinaryIO,
837        check : Callable[[Any, Any, Any], None] | None = None) -> (
838        Generator[apic.PredictionProtocol_Request_Reader,
839                  capnp.lib.capnp._DynamicStructBuilder, None]):
840    """Replay and verify a pre-recorded communication sequence between Coq and a prediction server.
841
842    Lowlevel variant of `capnp_message_generator_from_file`.
843
844    Accepts a `message_file` containing a stream of Capt'n Proto messages as recorded using
845    `capnp_message_generator(s, record=message_file)`. The resulting generator acts just like the generator
846    created by `capnp_message_generator` except that it is not connected to the socket but just replays the
847    pre-recorded messages.
848
849    Arguments:
850    - `check` is an optional callable that can be used to compare the response of the server to the recorded
851      response. It accepts three arguments: The recorded message that was sent by Coq, the response of the server
852      and the recorded response.
853    """
854    ...

Replay and verify a pre-recorded communication sequence between Coq and a prediction server.

Lowlevel variant of capnp_message_generator_from_file.

Accepts a message_file containing a stream of Capt'n Proto messages as recorded using capnp_message_generator(s, record=message_file). The resulting generator acts just like the generator created by capnp_message_generator except that it is not connected to the socket but just replays the pre-recorded messages.

Arguments:

  • check is an optional callable that can be used to compare the response of the server to the recorded response. It accepts three arguments: The recorded message that was sent by Coq, the response of the server and the recorded response.
def record_lowlevel_generator( record_file: <class 'BinaryIO'>, gen: collections.abc.Generator[pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader, capnp.lib.capnp._DynamicStructBuilder, None]) -> collections.abc.Generator[pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader, capnp.lib.capnp._DynamicStructBuilder, None]:
856def record_lowlevel_generator(
857        record_file: BinaryIO,
858        gen: Generator[apic.PredictionProtocol_Request_Reader,
859                       capnp.lib.capnp._DynamicStructBuilder, None]) -> (
860                           Generator[apic.PredictionProtocol_Request_Reader,
861                                     capnp.lib.capnp._DynamicStructBuilder, None]):
862    """Record a trace of the full interaction of a lowlevel generator to a file
863
864    Wrap a lowlevel generator (such as from `capnp_message_generator_lowlevel`) and dump all exchanged messages
865    to the given file. The file can later be replayed with `capnp_message_generator_from_file_lowlevel`.
866    """
867    ...

Record a trace of the full interaction of a lowlevel generator to a file

Wrap a lowlevel generator (such as from capnp_message_generator_lowlevel) and dump all exchanged messages to the given file. The file can later be replayed with capnp_message_generator_from_file_lowlevel.

def prediction_generator( lgenerator: collections.abc.Generator[pytact.graph_api_capnp_cython.PredictionProtocol_Request_Reader, capnp.lib.capnp._DynamicStructBuilder, None], defs: OnlineDefinitionsReader):
869def prediction_generator(
870        lgenerator: Generator[apic.PredictionProtocol_Request_Reader,
871                              capnp.lib.capnp._DynamicStructBuilder, None],
872        defs: OnlineDefinitionsReader):
873    """Given the current global context stack `defs`, convert a low-level
874    generator to a high-level `GlobalContextMessage`"""
875    ...

Given the current global context stack defs, convert a low-level generator to a high-level GlobalContextMessage

def capnp_message_generator( socket: socket.socket, record: typing.BinaryIO | None = None) -> GlobalContextMessage:
877def capnp_message_generator(socket: socket.socket, record: BinaryIO | None = None) -> GlobalContextMessage:
878    """A generator that facilitates communication between a prediction server and a Coq process.
879
880    Given a `socket`, this function creates a `GlobalContextMessage` `context`. This message contains an
881    initially empty list of available tactics and definitions in the global context. Through
882    `context.prediction_requests` one can access a generator that yields prediction requests and expects
883    predictions to be sent in response. The possible messages are as follows:
884    - `GlobalContextMessage`: An additional, nested, global context message that amends the current context
885       with additional tactics and definitions. The prediction requests of this nested context need to be
886       exhausted before continuing with messages from the current context.
887    - `CheckAlignmentMessage`: A request to check which of Coq's current tactics and definitions the
888      prediction server currently "knows about". The generator expects a `CheckAlignmentResponse` to be
889      sent in response.
890    - `ProofState`: A request to make tactic predictions for a given proof state. Either a
891      `TacticPredictionsGraph` or a `TacticPredictionsText` message is expected in return.
892
893    When `record` is passed a file descriptor, all received and sent messages will be dumped into that file
894    descriptor. These messages can then be replayed later using `capnp_message_generator_from_file`.
895    """
896    ...

A generator that facilitates communication between a prediction server and a Coq process.

Given a socket, this function creates a GlobalContextMessage context. This message contains an initially empty list of available tactics and definitions in the global context. Through context.prediction_requests one can access a generator that yields prediction requests and expects predictions to be sent in response. The possible messages are as follows:

  • GlobalContextMessage: An additional, nested, global context message that amends the current context with additional tactics and definitions. The prediction requests of this nested context need to be exhausted before continuing with messages from the current context.
  • CheckAlignmentMessage: A request to check which of Coq's current tactics and definitions the prediction server currently "knows about". The generator expects a CheckAlignmentResponse to be sent in response.
  • ProofState: A request to make tactic predictions for a given proof state. Either a TacticPredictionsGraph or a TacticPredictionsText message is expected in return.

When record is passed a file descriptor, all received and sent messages will be dumped into that file descriptor. These messages can then be replayed later using capnp_message_generator_from_file.

def capnp_message_generator_from_file( message_file: <class 'BinaryIO'>, check: Optional[Callable[[Any, Any, Any], NoneType]] = None, record: typing.BinaryIO | None = None) -> GlobalContextMessage:
898def capnp_message_generator_from_file(message_file: BinaryIO,
899                                      check : Callable[[Any, Any, Any], None] | None = None,
900                                      record: BinaryIO | None = None) -> GlobalContextMessage:
901    """Replay and verify a pre-recorded communication sequence between Coq and a prediction server.
902
903    Highlevel variant of `capnp_message_generator_from_file_lowlevel`.
904
905    Accepts a `message_file` containing a stream of Capt'n Proto messages as recorded using
906    `capnp_message_generator(s, record=message_file)`. The resulting generator acts just like the generator
907    created by `capnp_message_generator` except that it is not connected to the socket but just replays the
908    pre-recorded messages.
909
910    Arguments:
911    - `check` is an optional callable that can be used to compare the response of the server to the recorded
912      response. It accepts three arguments: The recorded message that was sent by Coq, the response of the server
913      and the recorded response.
914    - `record` is an optional file that re-records the interaction with the current server
915    """
916    ...

Replay and verify a pre-recorded communication sequence between Coq and a prediction server.

Highlevel variant of capnp_message_generator_from_file_lowlevel.

Accepts a message_file containing a stream of Capt'n Proto messages as recorded using capnp_message_generator(s, record=message_file). The resulting generator acts just like the generator created by capnp_message_generator except that it is not connected to the socket but just replays the pre-recorded messages.

Arguments:

  • check is an optional callable that can be used to compare the response of the server to the recorded response. It accepts three arguments: The recorded message that was sent by Coq, the response of the server and the recorded response.
  • record is an optional file that re-records the interaction with the current server
class GlobalContextSets:
918class GlobalContextSets:
919    """Lazily retrieve a the global context of a definition as a set, with memoization.
920
921    Because this class can allocate (large) amounts of memory, use it as a context-manager. To create a new
922    instance, and retrieve the context of a definition, use:
923    ```
924    with GlobalContextSets.new_context() as gcs:
925        gcs.global_context_set(my_definition)
926    ```
927    This context will be cached, as well as intermediate results (global contexts of other definitions) as
928    long as the context-set is in scope. Caching can be nested by using `sub_context`:
929    ```
930    with GlobalContextSets.new_context() as gcs:
931        gcs.global_context_set(my_definition)
932        with gcs.sub_context(lambda d:is_file_representative) as gcs_sub:
933            # gcs_sub remembers anything in the case of gcs
934            # caching is propagated to the parent cache only if the provided lambda evaluates to true
935            gcs_sub.global_context_set(my_definition2)
936    ```
937    """
938    def __init__(self, cache, parent: GlobalContextSets | None,
939                 should_propagate: Callable[[Definition], bool]):
940        """Do not call directly. Use `GlobalContextSets.new_context` and `GlobalContextSets.sub_context`."""
941        ...
942
943    def global_context_set(self, d: Definition) -> Map:
944        """Retrieve the global context of a definition, caching the result, and intermediate results."""
945        ...
946
947    @contextmanager
948    def sub_context(self, propagate: Callable[[Definition], bool]) -> Generator[GlobalContextSets, None, None]:
949        """Create a sub-context with a separate cache from it's parent, but sharing any info that was
950        already present in the parent's cache.
951
952        For any intermediate results for a definition `d` for which `propagate(d)` evaluates to true,
953        the result is propagated to the parent's cache."""
954        ...
955
956    @staticmethod
957    def new_context() -> Generator[GlobalContextSets, None, None]:
958        """Crate a new caching context where global-context-set's can be retrieved and cached."""
959        ...

Lazily retrieve a the global context of a definition as a set, with memoization.

Because this class can allocate (large) amounts of memory, use it as a context-manager. To create a new instance, and retrieve the context of a definition, use:

with GlobalContextSets.new_context() as gcs:
    gcs.global_context_set(my_definition)

This context will be cached, as well as intermediate results (global contexts of other definitions) as long as the context-set is in scope. Caching can be nested by using sub_context:

with GlobalContextSets.new_context() as gcs:
    gcs.global_context_set(my_definition)
    with gcs.sub_context(lambda d:is_file_representative) as gcs_sub:
        # gcs_sub remembers anything in the case of gcs
        # caching is propagated to the parent cache only if the provided lambda evaluates to true
        gcs_sub.global_context_set(my_definition2)
GlobalContextSets( cache, parent: GlobalContextSets | None, should_propagate: Callable[[Definition], bool])
938    def __init__(self, cache, parent: GlobalContextSets | None,
939                 should_propagate: Callable[[Definition], bool]):
940        """Do not call directly. Use `GlobalContextSets.new_context` and `GlobalContextSets.sub_context`."""
941        ...
def global_context_set(self, d: Definition) -> immutables.map.Map:
943    def global_context_set(self, d: Definition) -> Map:
944        """Retrieve the global context of a definition, caching the result, and intermediate results."""
945        ...

Retrieve the global context of a definition, caching the result, and intermediate results.

@contextmanager
def sub_context( self, propagate: Callable[[Definition], bool]) -> collections.abc.Generator[GlobalContextSets, None, None]:
947    @contextmanager
948    def sub_context(self, propagate: Callable[[Definition], bool]) -> Generator[GlobalContextSets, None, None]:
949        """Create a sub-context with a separate cache from it's parent, but sharing any info that was
950        already present in the parent's cache.
951
952        For any intermediate results for a definition `d` for which `propagate(d)` evaluates to true,
953        the result is propagated to the parent's cache."""
954        ...

Create a sub-context with a separate cache from it's parent, but sharing any info that was already present in the parent's cache.

For any intermediate results for a definition d for which propagate(d) evaluates to true, the result is propagated to the parent's cache.

@staticmethod
def new_context() -> collections.abc.Generator[GlobalContextSets, None, None]:
956    @staticmethod
957    def new_context() -> Generator[GlobalContextSets, None, None]:
958        """Crate a new caching context where global-context-set's can be retrieved and cached."""
959        ...

Crate a new caching context where global-context-set's can be retrieved and cached.

def node_dependencies( n: Node, deps: set[Definition] | None = None) -> set[Definition]:
961def node_dependencies(n: Node, deps: set[Definition] | None = None) -> set[Definition]:
962    """Given a `Node` `n`, calculate the set of `Definition`'s that are directly reachable
963    from `n`. Transitively reachable definitions are not included.
964    """
965    ...

Given a Node n, calculate the set of Definition's that are directly reachable from n. Transitively reachable definitions are not included.

def definition_dependencies(d: Definition) -> set[Definition]:
967def definition_dependencies(d: Definition) -> set[Definition]:
968    """Given a `Definition` `d`, calculate the set of `Definition`'s that are directly reachable for `d`.
969    Transitively reachable definitions are not included nor is `d` itself.
970    """
971    ...

Given a Definition d, calculate the set of Definition's that are directly reachable for d. Transitively reachable definitions are not included nor is d itself.