diff --git a/dev_tools/autogenerate-bloqs-notebooks-v2.py b/dev_tools/autogenerate-bloqs-notebooks-v2.py index aba1b9c0e4..66d89998f6 100644 --- a/dev_tools/autogenerate-bloqs-notebooks-v2.py +++ b/dev_tools/autogenerate-bloqs-notebooks-v2.py @@ -43,7 +43,7 @@ python dev_tools/autogenerate-bloqs-notebooks-v2.py """ -from typing import Iterable, List +from collections.abc import Iterable from qualtran_dev_tools.bloq_finder import get_bloqdocspecs from qualtran_dev_tools.jupyter_autogen import NotebookSpecV2, render_notebook @@ -85,7 +85,7 @@ def render_notebooks(): render_notebook(nbspec) -def _get_toc_section_lines(caption: str, entries: List[str], maxdepth: int = 2) -> List[str]: +def _get_toc_section_lines(caption: str, entries: list[str], maxdepth: int = 2) -> list[str]: """Helper function to get the lines for a section of the table-of-contents.""" return ( ['.. toctree::', f' :maxdepth: {maxdepth}', f' :caption: {caption}:', ''] diff --git a/dev_tools/bloq-method-overrides-report.py b/dev_tools/bloq-method-overrides-report.py index 6f106bfc2f..77f512317b 100644 --- a/dev_tools/bloq-method-overrides-report.py +++ b/dev_tools/bloq-method-overrides-report.py @@ -11,14 +11,17 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import ForwardRef, Set, Type +from typing import TYPE_CHECKING from qualtran_dev_tools.bloq_finder import get_bloq_classes from qualtran import Bloq +if TYPE_CHECKING: + from qualtran.resource_counting import BloqCountT -def _call_graph(bc: Type[Bloq]): + +def _call_graph(bc: type[Bloq]): """Check that a bloq class overrides the right call graph methods. - Override `build_call_graph` with canonical type annotations. @@ -42,7 +45,7 @@ def _call_graph(bc: Type[Bloq]): ) if annot['ssa'] != 'SympySymbolAllocator': print(f"{bc}.build_call_graph `ssa: 'SympySymbolAllocator'`") - if annot['return'] != Set[ForwardRef('BloqCountT')]: # type: ignore[misc] + if annot['return'] != set['BloqCountT']: # type: ignore[misc] print(f"{bc}.build_call_graph -> 'BloqCountT'") diff --git a/dev_tools/bloq-quickstarter.html b/dev_tools/bloq-quickstarter.html index fed8cda3ee..7ae2240a78 100644 --- a/dev_tools/bloq-quickstarter.html +++ b/dev_tools/bloq-quickstarter.html @@ -215,7 +215,7 @@

Code

signature += "\n ])" const template = `from functools import cached_property -from typing import Dict, Optional, Set, Union +from typing import Optional, Union from attrs import frozen @@ -238,10 +238,10 @@

Code

def signature(self) -> 'Signature': ${signature} - def build_composite_bloq(self, bb: 'BloqBuilder'${build_sig}) -> Dict[str, 'SoquetT']: + def build_composite_bloq(self, bb: 'BloqBuilder'${build_sig}) -> dict[str, 'SoquetT']: raise NotImplementedError("Implement or delete.") - def bloq_counts(self, ssa: Optional['SympySymbolAllocator'] = None) -> Set['BloqCountT']: + def bloq_counts(self, ssa: Optional['SympySymbolAllocator'] = None) -> set['BloqCountT']: raise NotImplementedError("Implement or delete.") def short_name(self) -> str: diff --git a/dev_tools/dump-bloq-manifest.py b/dev_tools/dump-bloq-manifest.py index a7006a610c..eb83ea0450 100644 --- a/dev_tools/dump-bloq-manifest.py +++ b/dev_tools/dump-bloq-manifest.py @@ -23,7 +23,6 @@ """ from functools import cached_property -from typing import List, Tuple from attrs import frozen from qualtran_dev_tools.bloq_finder import get_bloq_classes, get_bloq_examples @@ -70,7 +69,7 @@ def objectstring(self) -> str: """Returns the canonical string representation of the CObjectNode.""" return self.cobject_node.canonical_str() - def maybe_commented_out(self, be_column_width: int = 30) -> Tuple[str, str, str]: + def maybe_commented_out(self, be_column_width: int = 30) -> tuple[str, str, str]: """Generates a string representation for the manifest, potentially commented out. This method checks if the object string is too long, unparsable, unloadable, or @@ -121,7 +120,7 @@ def main(): names = sorted(bc._class_name_in_pkg_() for bc in bcs) bes = get_bloq_examples() - items: List[BloqExampleListItem] = [] + items: list[BloqExampleListItem] = [] for be in bes: bloq = be.make() try: diff --git a/dev_tools/qualtran_dev_tools/all_call_graph.py b/dev_tools/qualtran_dev_tools/all_call_graph.py index 3c42912442..24fa00cb40 100644 --- a/dev_tools/qualtran_dev_tools/all_call_graph.py +++ b/dev_tools/qualtran_dev_tools/all_call_graph.py @@ -16,7 +16,7 @@ import logging import warnings -from typing import Iterable +from collections.abc import Iterable import networkx as nx diff --git a/dev_tools/qualtran_dev_tools/bloq_finder.py b/dev_tools/qualtran_dev_tools/bloq_finder.py index 63de6f3eeb..ea3e58c374 100644 --- a/dev_tools/qualtran_dev_tools/bloq_finder.py +++ b/dev_tools/qualtran_dev_tools/bloq_finder.py @@ -14,15 +14,16 @@ import importlib import inspect import subprocess +from collections.abc import Callable, Iterable from pathlib import Path -from typing import Callable, Iterable, List, Optional, Tuple, Type +from typing import Optional from qualtran import Bloq, BloqDocSpec, BloqExample from .git_tools import get_git_root -def _get_git_paths(bloqs_root: Path, filter_func: Callable[[Path], bool]) -> List[Path]: +def _get_git_paths(bloqs_root: Path, filter_func: Callable[[Path], bool]) -> list[Path]: """Get only git-tracked *.py files based on `filter_func`.""" cp = subprocess.run( ['git', 'ls-files', '*.py'], @@ -40,7 +41,7 @@ def _get_git_paths(bloqs_root: Path, filter_func: Callable[[Path], bool]) -> Lis def _get_paths( bloqs_root: Path, filter_func: Callable[[Path], bool], committed_only: bool = True -) -> List[Path]: +) -> list[Path]: """Get *.py files based on `filter_func`.""" if committed_only: return _get_git_paths(bloqs_root, filter_func) @@ -50,7 +51,7 @@ def _get_paths( ] -def get_bloq_module_paths(bloqs_root: Path, committed_only: bool = True) -> List[Path]: +def get_bloq_module_paths(bloqs_root: Path, committed_only: bool = True) -> list[Path]: """Get *.py files for non-test, non-init modules under `bloqs_root`.""" def is_module_path(path: Path) -> bool: @@ -65,7 +66,7 @@ def is_module_path(path: Path) -> bool: return _get_paths(bloqs_root, is_module_path, committed_only=committed_only) -def get_bloq_test_module_paths(bloqs_root: Path, committed_only: bool = True) -> List[Path]: +def get_bloq_test_module_paths(bloqs_root: Path, committed_only: bool = True) -> list[Path]: """Get *_test.py files under `bloqs_root`.""" def is_test_module_path(path: Path) -> bool: @@ -82,7 +83,7 @@ def _bloq_modpath_to_modname(path: Path) -> str: return 'qualtran.bloqs.' + str(path)[: -len('.py')].replace('/', '.') -def modpath_to_bloqs(path: Path) -> Iterable[Type[Bloq]]: +def modpath_to_bloqs(path: Path) -> Iterable[type[Bloq]]: """Given a module path, return all the `Bloq` classes defined within.""" modname = _bloq_modpath_to_modname(path) mod = importlib.import_module(modname) @@ -100,7 +101,7 @@ def modpath_to_bloqs(path: Path) -> Iterable[Type[Bloq]]: yield cls -def modpath_to_bloq_exs(path: Path) -> Iterable[Tuple[str, str, BloqExample]]: +def modpath_to_bloq_exs(path: Path) -> Iterable[tuple[str, str, BloqExample]]: """Given a module path, return all the `BloqExample`s defined within.""" modname = _bloq_modpath_to_modname(path) mod = importlib.import_module(modname) @@ -109,7 +110,7 @@ def modpath_to_bloq_exs(path: Path) -> Iterable[Tuple[str, str, BloqExample]]: yield modname, name, obj -def modpath_to_bloqdocspecs(path: Path) -> Iterable[Tuple[str, str, BloqDocSpec]]: +def modpath_to_bloqdocspecs(path: Path) -> Iterable[tuple[str, str, BloqDocSpec]]: """Given a module path, return all the `BloqDocSpec`s defined within.""" modname = _bloq_modpath_to_modname(path) mod = importlib.import_module(modname) @@ -118,20 +119,20 @@ def modpath_to_bloqdocspecs(path: Path) -> Iterable[Tuple[str, str, BloqDocSpec] yield modname, name, obj -def get_bloq_classes(bloqs_root: Optional[Path] = None) -> List[Type[Bloq]]: +def get_bloq_classes(bloqs_root: Optional[Path] = None) -> list[type[Bloq]]: committed_only = bloqs_root is None if bloqs_root is None: reporoot = get_git_root() bloqs_root = reporoot / 'qualtran/bloqs' paths = get_bloq_module_paths(bloqs_root, committed_only=committed_only) - bloq_clss: List[Type[Bloq]] = [] + bloq_clss: list[type[Bloq]] = [] for path in paths: bloq_clss.extend(modpath_to_bloqs(path)) return bloq_clss -def get_bloq_examples(bloqs_root: Optional[Path] = None) -> List[BloqExample]: +def get_bloq_examples(bloqs_root: Optional[Path] = None) -> list[BloqExample]: committed_only = bloqs_root is None if bloqs_root is None: reporoot = get_git_root() @@ -139,7 +140,7 @@ def get_bloq_examples(bloqs_root: Optional[Path] = None) -> List[BloqExample]: paths = get_bloq_module_paths(bloqs_root, committed_only=committed_only) - bexamples: List[BloqExample] = [] + bexamples: list[BloqExample] = [] for path in paths: for modname, name, be in modpath_to_bloq_exs(path): bexamples.append(be) @@ -147,7 +148,7 @@ def get_bloq_examples(bloqs_root: Optional[Path] = None) -> List[BloqExample]: return bexamples -def get_bloqdocspecs(bloqs_root: Optional[Path] = None) -> List[BloqDocSpec]: +def get_bloqdocspecs(bloqs_root: Optional[Path] = None) -> list[BloqDocSpec]: committed_only = bloqs_root is None if bloqs_root is None: reporoot = get_git_root() @@ -155,7 +156,7 @@ def get_bloqdocspecs(bloqs_root: Optional[Path] = None) -> List[BloqDocSpec]: paths = get_bloq_module_paths(bloqs_root, committed_only=committed_only) - bdspecs: List[BloqDocSpec] = [] + bdspecs: list[BloqDocSpec] = [] for path in paths: for modname, name, bds in modpath_to_bloqdocspecs(path): bdspecs.append(bds) diff --git a/dev_tools/qualtran_dev_tools/bloq_report_card.py b/dev_tools/qualtran_dev_tools/bloq_report_card.py index 4d26c7ffbc..cfbb4876d3 100644 --- a/dev_tools/qualtran_dev_tools/bloq_report_card.py +++ b/dev_tools/qualtran_dev_tools/bloq_report_card.py @@ -13,7 +13,8 @@ # limitations under the License. import time import warnings -from typing import Any, Dict, Iterable, List, Optional, Set, Type +from collections.abc import Iterable +from typing import Any, Optional import pandas as pd import pandas.io.formats.style @@ -31,12 +32,12 @@ from .bloq_finder import get_bloq_classes, get_bloq_examples -def _get_package(bloq_cls: Type[Bloq]) -> str: +def _get_package(bloq_cls: type[Bloq]) -> str: """The package name for a bloq class""" return '.'.join(bloq_cls.__module__.split('.')[:-1]) -def color_status(v: BloqCheckResult): +def color_status(v: BloqCheckResult) -> str: """Used to style the dataframe.""" if v is BloqCheckResult.PASS: return 'background-color:lightgreen' @@ -50,14 +51,14 @@ def color_status(v: BloqCheckResult): return 'background-color:red' -def format_status(v: BloqCheckResult): +def format_status(v: BloqCheckResult) -> str: """Used to format the dataframe.""" return v.name.lower() def bloq_classes_with_no_examples( - bclasses: Iterable[Type[Bloq]], bexamples: Iterable[BloqExample] -) -> Set[Type[Bloq]]: + bclasses: Iterable[type[Bloq]], bexamples: Iterable[BloqExample] +) -> set[type[Bloq]]: ks = set(bclasses) for be in bexamples: try: @@ -72,13 +73,13 @@ def bloq_classes_with_no_examples( CHECKCOLS = ['make', 'decomp', 'counts', 'serialize', 'qtyping'] -def record_for_class_with_no_examples(k: Type[Bloq]) -> Dict[str, Any]: +def record_for_class_with_no_examples(k: type[Bloq]) -> dict[str, Any]: return {'bloq_cls': k.__name__, 'package': _get_package(k), 'name': '-'} | { check_name: BloqCheckResult.MISSING for check_name in CHECKCOLS } -def record_for_bloq_example(be: BloqExample) -> Dict[str, Any]: +def record_for_bloq_example(be: BloqExample) -> dict[str, Any]: start = time.perf_counter() record = { 'bloq_cls': be.bloq_cls.__name__, @@ -101,7 +102,7 @@ def show_bloq_report_card(df: pd.DataFrame) -> pandas.io.formats.style.Styler: def get_bloq_report_card( - bclasses: Optional[Iterable[Type[Bloq]]] = None, + bclasses: Optional[Iterable[type[Bloq]]] = None, bexamples: Optional[Iterable[BloqExample]] = None, package_prefix: str = 'qualtran.bloqs.', ) -> pd.DataFrame: @@ -115,7 +116,7 @@ def get_bloq_report_card( skips = ['qubitization_qpe_hubbard_model_small', 'qubitization_qpe_hubbard_model_large'] bexamples = [bex for bex in bexamples if bex.name not in skips] - records: List[Dict[str, Any]] = [] + records: list[dict[str, Any]] = [] missing_bclasses = bloq_classes_with_no_examples(bclasses, bexamples) records.extend(record_for_class_with_no_examples(k) for k in missing_bclasses) records.extend(record_for_bloq_example(be) for be in bexamples) diff --git a/dev_tools/qualtran_dev_tools/clean_notebooks.py b/dev_tools/qualtran_dev_tools/clean_notebooks.py index a5d31baf1c..83871ade6d 100644 --- a/dev_tools/qualtran_dev_tools/clean_notebooks.py +++ b/dev_tools/qualtran_dev_tools/clean_notebooks.py @@ -15,13 +15,13 @@ import subprocess from pathlib import Path from tempfile import NamedTemporaryFile -from typing import Any, List +from typing import Any import nbformat from nbconvert.preprocessors import ClearMetadataPreprocessor, ClearOutputPreprocessor -def get_nb_rel_paths(rootdir) -> List[Path]: +def get_nb_rel_paths(rootdir) -> list[Path]: """List all checked-in *.ipynb files within `rootdir`.""" cp = subprocess.run( ['git', 'ls-files', '*.ipynb'], diff --git a/dev_tools/qualtran_dev_tools/incremental_coverage.py b/dev_tools/qualtran_dev_tools/incremental_coverage.py index e13357eec6..8f7b060b00 100644 --- a/dev_tools/qualtran_dev_tools/incremental_coverage.py +++ b/dev_tools/qualtran_dev_tools/incremental_coverage.py @@ -14,7 +14,7 @@ import os.path import re -from typing import cast, Dict, List, Optional, Set, Tuple +from typing import cast, Optional from . import shell_tools from .prepared_env import PreparedEnv @@ -57,7 +57,7 @@ EXPLICIT_OPT_OUT_COMMENT = "#coverage:ignore" -def diff_to_new_interesting_lines(unified_diff_lines: List[str]) -> Dict[int, str]: +def diff_to_new_interesting_lines(unified_diff_lines: list[str]) -> dict[int, str]: """Extracts a set of 'interesting' lines out of a GNU unified diff format. Format: @@ -124,7 +124,7 @@ def fix_line_from_coverage_file(line): def get_incremental_uncovered_lines( abs_path: str, base_commit: str, actual_commit: Optional[str] -) -> List[Tuple[int, str, str]]: +) -> list[tuple[int, str, str]]: """Find touched but uncovered lines in the given file. Uses git diff and the annotation files created by `pytest --cov-report annotate` to find @@ -190,9 +190,9 @@ def line_content_counts_as_uncovered_manual(content: str) -> bool: return True -def determine_ignored_lines(content: str) -> Set[int]: +def determine_ignored_lines(content: str) -> set[int]: lines = content.split("\n") - result: List[int] = [] + result: list[int] = [] i = 0 while i < len(lines): @@ -222,7 +222,7 @@ def determine_ignored_lines(content: str) -> Set[int]: return {e + 1 for e in result} -def naive_find_end_of_scope(lines: List[str], i: int) -> int: +def naive_find_end_of_scope(lines: list[str], i: int) -> int: # TODO: deal with line continuations, which may be less indented. # Github issue: https://github.com/quantumlib/Cirq/issues/2968 line = lines[i] diff --git a/dev_tools/qualtran_dev_tools/jupyter_autogen.py b/dev_tools/qualtran_dev_tools/jupyter_autogen.py index 5d002d6c5e..0b35c76719 100644 --- a/dev_tools/qualtran_dev_tools/jupyter_autogen.py +++ b/dev_tools/qualtran_dev_tools/jupyter_autogen.py @@ -20,7 +20,7 @@ import textwrap from pathlib import Path from types import ModuleType -from typing import List, Optional, Tuple +from typing import Optional import nbformat from attrs import field, frozen @@ -66,7 +66,7 @@ class NotebookSpecV2: title: str module: ModuleType - bloq_specs: List[BloqDocSpec] + bloq_specs: list[BloqDocSpec] directory: str = field() _path_stem: Optional[str] = None @@ -87,7 +87,7 @@ def path(self) -> Path: return Path(self.directory) / f'{self.path_stem}.ipynb' -def _get_bloq_example_source_lines(bloq_ex: 'BloqExample') -> List[str]: +def _get_bloq_example_source_lines(bloq_ex: 'BloqExample') -> list[str]: """Parse out the source code from a factory function, so we can render it into a cell. Args: @@ -158,7 +158,7 @@ class _PyCell(_Cell): cell_id: str -def get_bloq_doc_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> List[_Cell]: +def get_bloq_doc_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> list[_Cell]: """Cells introducing the `bloq_cls`""" md_doc: str = '\n'.join(get_markdown_docstring_lines(bloqdoc.bloq_cls)) @@ -178,19 +178,19 @@ def _get_one_ex_instance_cell(bloq_ex: BloqExample, cid_prefix): ) -def get_example_instances_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> List[_Cell]: +def get_example_instances_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> list[_Cell]: """Cells constructing example instances of the bloq class.""" examples = bloqdoc.examples if not examples: return [] - cells: List[_Cell] = [ + cells: list[_Cell] = [ _MarkdownCell('### Example Instances', cell_id=f'{cid_prefix}.example_instances.md') ] return cells + [_get_one_ex_instance_cell(ex, cid_prefix) for ex in examples] -def get_graphical_signature_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> List[_Cell]: +def get_graphical_signature_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> list[_Cell]: """Cells showing a 'graphical signature' for the bloq examples.""" if not bloqdoc.examples: return [] @@ -209,7 +209,7 @@ def get_graphical_signature_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> List ] -def get_call_graph_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> List[_Cell]: +def get_call_graph_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> list[_Cell]: """Cells showing a call graph for one of the bloq examples.""" if bloqdoc.call_graph_example is None: return [] @@ -231,8 +231,8 @@ def get_call_graph_cells(bloqdoc: BloqDocSpec, cid_prefix: str) -> List[_Cell]: ] -def get_cells(bloqdoc: BloqDocSpec) -> List[_Cell]: - cells: List[_Cell] = [] +def get_cells(bloqdoc: BloqDocSpec) -> list[_Cell]: + cells: list[_Cell] = [] cid_prefix = f'{bloqdoc.bloq_cls.__name__}' cells += get_bloq_doc_cells(bloqdoc, cid_prefix) cells += get_example_instances_cells(bloqdoc, cid_prefix) @@ -261,7 +261,7 @@ def _cell_to_nbnode(cell: _Cell) -> nbformat.NotebookNode: raise ValueError() -def _get_title_lines(title: str, mod: ModuleType) -> List[str]: +def _get_title_lines(title: str, mod: ModuleType) -> list[str]: """Return markdown lines for the title cell. This consists of the specified title as well as the associated module's docstring. @@ -278,7 +278,7 @@ def _get_title_lines(title: str, mod: ModuleType) -> List[str]: def _init_notebook( path_stem: str, overwrite=False, directory: str = '.' -) -> Tuple[nbformat.NotebookNode, Path]: +) -> tuple[nbformat.NotebookNode, Path]: """Initialize a jupyter notebook. If one already exists: load it in. Otherwise, create a new one. @@ -326,7 +326,7 @@ def render_notebook(nbspec: NotebookSpecV2) -> None: # 3. Merge rendered cells into the existing notebook. # -> we use the cells metadata field to match up cells. - cqids_to_render: List[str] = list(cells.keys()) + cqids_to_render: list[str] = list(cells.keys()) for i in range(len(nb.cells)): nb_node = nb.cells[i] if _K_CQ_AUTOGEN in nb_node.metadata: diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_components/aliases.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_components/aliases.py index 2170b9aaa1..576c7dcad7 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_components/aliases.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_components/aliases.py @@ -11,10 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Dict -def get_aliases_str(pref_dotpath: str, *, aliases_d: Dict[str, str]) -> str: +def get_aliases_str(pref_dotpath: str, *, aliases_d: dict[str, str]) -> str: """From a complete dictionary of aliases, return a formatted string with our aliases. This will return just `pref_dotpath` if there are none, diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_docstring.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_docstring.py index a763321f87..f058617ae9 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_docstring.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_docstring.py @@ -13,7 +13,10 @@ # limitations under the License. import re import warnings -from typing import List, Literal, Tuple, TYPE_CHECKING +from typing import Literal, TYPE_CHECKING + +if TYPE_CHECKING: + from .._linking_writer import Writable from griffe import ( DocstringSection, @@ -37,7 +40,7 @@ PARSER: Literal['google'] = 'google' -def split_docstring(obj: 'griffe.Object') -> Tuple[str, List[DocstringSection]]: +def split_docstring(obj: 'griffe.Object') -> tuple[str, list[DocstringSection]]: """Extract the first, summary line of a docstring from an object. Returns: @@ -47,7 +50,7 @@ def split_docstring(obj: 'griffe.Object') -> Tuple[str, List[DocstringSection]]: if obj.docstring is None: first_line = "" - rest: List[DocstringSection] = [] + rest: list[DocstringSection] = [] return first_line, rest dp0, *dparts = obj.docstring.parse(PARSER) @@ -64,12 +67,12 @@ def split_docstring(obj: 'griffe.Object') -> Tuple[str, List[DocstringSection]]: return first_line, rest -def _write_text(f, part: DocstringSectionText, level: int): +def _write_text(f: 'Writable', part: DocstringSectionText, level: int) -> None: f.write(part.value.strip()) f.write('\n\n') -def _write_parameters(f, part: DocstringSectionParameters, level: int): +def _write_parameters(f: 'Writable', part: DocstringSectionParameters, level: int) -> None: lvl = '#' * level f.write(f'###{lvl} Args\n') for param in part.value: @@ -81,7 +84,7 @@ def _write_parameters(f, part: DocstringSectionParameters, level: int): f.write('\n\n') -def _write_attributes(f, part: DocstringSectionAttributes, level: int): +def _write_attributes(f: 'Writable', part: DocstringSectionAttributes, level: int) -> None: lvl = '#' * level f.write(f'###{lvl} Attributes\n') for attr in part.value: @@ -93,7 +96,7 @@ def _write_attributes(f, part: DocstringSectionAttributes, level: int): f.write('\n\n') -def _write_returns(f, part: DocstringSectionReturns, level: int): +def _write_returns(f: 'Writable', part: DocstringSectionReturns, level: int) -> None: lvl = '#' * level f.write(f'###{lvl} Returns\n') @@ -112,7 +115,7 @@ def _write_returns(f, part: DocstringSectionReturns, level: int): f.write('\n\n') -def _write_admonition(f, part: DocstringSectionAdmonition, level: int): +def _write_admonition(f: 'Writable', part: DocstringSectionAdmonition, level: int) -> None: lvl = '#' * level part = part.value if part.kind == 'see-also': @@ -131,7 +134,7 @@ def _write_admonition(f, part: DocstringSectionAdmonition, level: int): warnings.warn(f"Unknown admonition type {part.kind}") -def _write_examples(f, part: DocstringSectionExamples, level: int): +def _write_examples(f: 'Writable', part: DocstringSectionExamples, level: int) -> None: part = part.value for subkind, subtext in part: if subkind is DocstringSectionKind.examples: @@ -146,7 +149,7 @@ def _write_examples(f, part: DocstringSectionExamples, level: int): f.write('\n\n') -def _write_raises(f, part: DocstringSectionRaises, level: int): +def _write_raises(f: 'Writable', part: DocstringSectionRaises, level: int) -> None: lvl = '#' * level f.write(f'###{lvl} Raises\n') for subpart in part.value: @@ -157,7 +160,7 @@ def _write_raises(f, part: DocstringSectionRaises, level: int): f.write('\n\n') -def _write_yields(f, part: DocstringSectionYields, level: int): +def _write_yields(f: 'Writable', part: DocstringSectionYields, level: int) -> None: lvl = '#' * level f.write(f'###{lvl} Yields\n') @@ -175,7 +178,7 @@ def _write_yields(f, part: DocstringSectionYields, level: int): f.write('\n\n') -def _write_unknown(f, part: DocstringSection, level: int): +def _write_unknown(f: 'Writable', part: DocstringSection, level: int) -> None: f.write(str(part)) f.write('\n') warnings.warn(f"Unknown docstring {part}") @@ -193,7 +196,7 @@ def _write_unknown(f, part: DocstringSection, level: int): } -def write_docstring_parts(f, parts: List[DocstringSection], level: int): +def write_docstring_parts(f: 'Writable', parts: list[DocstringSection], level: int) -> None: for part in parts: _write = _DISPATCH.get(part.kind, _write_unknown) _write(f, part, level) # type: ignore diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_signature.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_signature.py index e9bb777147..f60ade496c 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_signature.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_components/render_signature.py @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. import re -from typing import Optional +from typing import Optional, TYPE_CHECKING from griffe import Function, Object, Parameter, ParameterKind +if TYPE_CHECKING: + from .._linking_writer import Writable + BESPOKE_OBJECT_NAMES_FOR_CLASSES = {'BloqBuilder': 'bb', 'CompositeBloq': 'cbloq'} @@ -43,14 +46,14 @@ def format_parameter(p: Parameter) -> str: raise ValueError(p.kind) -def camel_to_snake(name): +def camel_to_snake(name) -> str: # Turn an UpperCamelCaseName into lower_snake_case # .. we want to make it look like we're calling methods on instances of the class. s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) return s1.lower() -def get_obj_instance_name(obj): +def get_obj_instance_name(obj) -> str: # Get prototypical object instance names for a given class. # First, check if we have a bespoke name @@ -62,7 +65,7 @@ def get_obj_instance_name(obj): return camel_to_snake(obj.name) -def write_property_method_signature(f, obj, obj2: Function): +def write_property_method_signature(f, obj, obj2: Function) -> None: assert obj2.returns, obj2 obj_instance_name = get_obj_instance_name(obj) method_signature = f'{obj_instance_name}.{obj2.name} -> {obj2.returns}' @@ -101,7 +104,7 @@ def write_generic_method_signature( f.write(f'```python\n{method_signature}\n```\n\n') -def write_function_signature(f, obj2: Function): +def write_function_signature(f: 'Writable', obj2: Function) -> None: # Strip `self` or `cls` argument. parameters = list(obj2.parameters) @@ -120,7 +123,7 @@ def write_function_signature(f, obj2: Function): f.write(f'```python\n{method_signature}\n```\n\n') -def write_method_signature(f, obj: Object, obj2: Function) -> None: +def write_method_signature(f: 'Writable', obj: Object, obj2: Function) -> None: if obj2.overloads: # Assume the full documentation is in the defined function, not the overrides. return diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_linking_writer.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_linking_writer.py index 5476406c35..e556b902c8 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_linking_writer.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_linking_writer.py @@ -13,14 +13,15 @@ # limitations under the License. import re from collections import defaultdict +from collections.abc import MutableMapping from pathlib import Path -from typing import Dict, MutableMapping, Optional, Protocol, Set, Tuple +from typing import Optional, Protocol from mdit_py_plugins.anchors.index import slugify from ._page import Page -_CACHE: MutableMapping[str, Dict[str, Optional[str]]] = defaultdict(dict) +_CACHE: MutableMapping[str, dict[str, Optional[str]]] = defaultdict(dict) class Writable(Protocol): @@ -43,12 +44,12 @@ def __init__( self, f: Writable, *, - link_aliases: Dict[str, str], - link_d: Dict[str, Tuple[Page, Optional[str]]], + link_aliases: dict[str, str], + link_d: dict[str, tuple[Page, Optional[str]]], refdoc_relpath: Path, ): self._f: Writable = f - self._linked: Set[str] = set() + self._linked: set[str] = set() self._link_aliases = link_aliases self._link_d = link_d self._reference_relpath = refdoc_relpath @@ -87,13 +88,13 @@ def repl(self, ma: re.Match) -> str: def linkify(self, s: str) -> str: return re.sub(r'`([\w\.]+)`', self.repl, s) - def write(self, s: str): + def write(self, s: str) -> None: self._f.write(self.linkify(s)) - def write_nl(self, s: str): + def write_nl(self, s: str) -> None: self._f.write(s) - def write_link_targets(self): + def write_link_targets(self) -> None: self._f.write('\n') for dotpath in self._linked: self._f.write(f'[`{dotpath}`]: {self.resolve_dotpath(dotpath)}\n') diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_make.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_make.py index 9addcfd04b..8588eccc35 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_make.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_make.py @@ -16,8 +16,9 @@ import ast import warnings from collections import defaultdict +from collections.abc import Sequence from pathlib import Path -from typing import Any, cast, Dict, List, Optional, Sequence, Set, Tuple, Union +from typing import Any, cast, Optional, Union import attrs import griffe @@ -86,7 +87,7 @@ ] -def _get_all_aliases(obj: Union[griffe.Object, griffe.Alias]) -> Set[str]: +def _get_all_aliases(obj: Union[griffe.Object, griffe.Alias]) -> set[str]: """Get all the valid aliases for `obj`.""" # First, try to use the aliases griffe has found @@ -125,7 +126,7 @@ def is_valid_alias(alias: str) -> bool: return valid_aliases -def _get_preferred_dotpath(all_aliases: Set[str]): +def _get_preferred_dotpath(all_aliases: set[str]): """From a list of candidates, select the best "dotpath". A "dotpath" is a string path of the form "foo.bar.X", i.e. with dots. It is in contrast @@ -146,18 +147,18 @@ class _PackageWalker: The public entry point is via the function `get_pages`. """ - seen: Set[str] = attrs.field(factory=set, kw_only=True) + seen: set[str] = attrs.field(factory=set, kw_only=True) """A set of seen canonical dotpaths. Griffe uses canonical dotpaths to uniquely identify things, so we do too for `seen`. Afterwards, the doc system will use only our preferred path.""" - pages_d: Dict[str, Page] = attrs.field(factory=lambda: defaultdict(ModulePage), kw_only=True) + pages_d: dict[str, Page] = attrs.field(factory=lambda: defaultdict(ModulePage), kw_only=True) """Mapping of preferred dotpath to `Page`.""" - aliases_d: Dict[str, str] = attrs.field(factory=dict, kw_only=True) + aliases_d: dict[str, str] = attrs.field(factory=dict, kw_only=True) """Mapping from each alias to the preferred dotpath (many-to-one).""" - link_d: Dict[str, Tuple[Page, Optional[str]]] = attrs.field(factory=dict, kw_only=True) + link_d: dict[str, tuple[Page, Optional[str]]] = attrs.field(factory=dict, kw_only=True) """Mapping from preferred dotpath to a doc location.""" def _walk_table_of_contents(self, obj: Union[griffe.Alias, griffe.Object]): @@ -251,7 +252,7 @@ def _walk_table_of_contents(self, obj: Union[griffe.Alias, griffe.Object]): def get_pages( root_mod: griffe.Module, -) -> Tuple[List[Page], Dict[str, str], Dict[str, Tuple[Page, Optional[str]]]]: +) -> tuple[list[Page], dict[str, str], dict[str, tuple[Page, Optional[str]]]]: """Walk down from `root_mod`.""" assert root_mod.is_module assert root_mod.is_init_module @@ -276,8 +277,8 @@ def walk_and_configure( refdoc_relpath: Path, top_sections: Sequence[str], fake_sections: Sequence[str], - addtl_linkable: Dict[str, str], -) -> Tuple[List[Page], RenderContext]: + addtl_linkable: dict[str, str], +) -> tuple[list[Page], RenderContext]: """Organize things or whatever.""" # Incantation to get `griffe` set up. @@ -342,7 +343,7 @@ def make_reference_docs( repo_root_path: Path, refdoc_relpath: Path = Path("reference"), rootmod_dotpath: str = "qualtran", -): +) -> None: """Make the reference documentation. The steps are diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_major_class.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_major_class.py index b085698ecc..ae7fa34711 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_major_class.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_major_class.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from pathlib import Path -from typing import cast, Dict, TYPE_CHECKING +from typing import cast, TYPE_CHECKING import griffe from griffe import Kind @@ -29,7 +29,7 @@ from .._linking_writer import Writable -def write_major_class_member(f: 'Writable', obj: griffe.Class, obj2: griffe.Object): +def write_major_class_member(f: 'Writable', obj: griffe.Class, obj2: griffe.Object) -> None: if obj2.is_private: return if obj2.name == '__init__': @@ -56,8 +56,8 @@ def write_major_class_member(f: 'Writable', obj: griffe.Class, obj2: griffe.Obje def write_major_class( - f: LinkingWriter, obj: griffe.Class, pref_dotpath: str, aliases_d: Dict[str, str] -): + f: LinkingWriter, obj: griffe.Class, pref_dotpath: str, aliases_d: dict[str, str] +) -> None: # Title f.write(f"# {obj.name}\n\n") @@ -80,7 +80,7 @@ def write_major_class( write_major_class_member(f, obj, cast(griffe.Object, obj2)) -def render_major_class(base_dir: Path, page: MajorClassPage, render_context: RenderContext): +def render_major_class(base_dir: Path, page: MajorClassPage, render_context: RenderContext) -> None: assert page.pref_path is not None, f'Uninitialized {page}' segments = page.pref_path.split('.') out_path = base_dir / '/'.join(segments[:-1]) / f'{segments[-1]}.md' diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_module.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_module.py index 5f4f048aa6..875fab9de8 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_module.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_module.py @@ -13,8 +13,9 @@ # limitations under the License. +from collections.abc import Sequence from pathlib import Path -from typing import cast, Dict, Sequence +from typing import cast import griffe from griffe import Kind @@ -28,7 +29,7 @@ from .._render_context import RenderContext -def write_module_other_member(f: LinkingWriter, obj, pref_path, aliases_d): +def write_module_other_member(f: LinkingWriter, obj, pref_path, aliases_d) -> None: first_line, rest = split_docstring(obj) f.write_nl(f'### `{obj.name}`\n') f.write_nl(get_aliases_str(pref_path, aliases_d=aliases_d)) @@ -69,8 +70,8 @@ def write_module( obj: griffe.Module, pref_path: str, members: Sequence[ModulePageMember], - aliases_d: Dict[str, str], -): + aliases_d: dict[str, str], +) -> None: # Title title_dotpath = '.'.join(pref_path.split('.')[-2:]) f.write_nl(f'# `{title_dotpath}`\n\n') @@ -118,7 +119,7 @@ def write_module( f.write('\n') -def render_module(out_dir: Path, page: ModulePage, render_context: RenderContext): +def render_module(out_dir: Path, page: ModulePage, render_context: RenderContext) -> None: out_path = page.out_path(out_dir=out_dir) print(f"Writing {page.pref_path} to {out_path}") out_path.parent.mkdir(parents=True, exist_ok=True) diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_toc.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_toc.py index e7367e3d5b..02ba2dc6a4 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_toc.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_pages/render_toc.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Callable, List, Sequence +from collections.abc import Callable, Sequence from .._page import ModulePage, Page from .._render_context import RenderContext @@ -28,7 +28,7 @@ def write_toc(toc_f, pages, _page_in_section, _pages_sort_key, render_context: R toc_f.write(f' :caption: {section}\n') toc_f.write(' :maxdepth: 2\n\n') - spages: List[Page] = sorted( + spages: list[Page] = sorted( (p for p in pages if _page_in_section(p, section)), key=_pages_sort_key ) diff --git a/dev_tools/qualtran_dev_tools/make_reference_docs/_render_context.py b/dev_tools/qualtran_dev_tools/make_reference_docs/_render_context.py index 62a268d1b1..d299844f5d 100644 --- a/dev_tools/qualtran_dev_tools/make_reference_docs/_render_context.py +++ b/dev_tools/qualtran_dev_tools/make_reference_docs/_render_context.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. from pathlib import Path -from typing import Dict, List, Optional, Tuple +from typing import Optional import attrs @@ -52,16 +52,16 @@ class RenderContext: refdoc_relpath: Path """Relative subdirectory of where the reference docs go (opposed to the other docs)""" - sections: List[str] + sections: list[str] """Ordered list of section names (to organize pages)""" - aliases_d: Dict[str, str] + aliases_d: dict[str, str] """Returned by `get_pages`, see `_PackageWalker.aliases_d`""" - link_d: Dict[str, Tuple[Page, Optional[str]]] + link_d: dict[str, tuple[Page, Optional[str]]] """Returned by `get_pages`, see `_PackageWalker.link_d`""" - linkable_to_prefpath: Dict[str, str] + linkable_to_prefpath: dict[str, str] """Similar to aliases_d, but can have arbitrary keys that map to preferred dotpaths.""" def get_linking_writer(self, f: Writable) -> LinkingWriter: diff --git a/dev_tools/qualtran_dev_tools/notebook_execution.py b/dev_tools/qualtran_dev_tools/notebook_execution.py index 58146f27ad..e346c93ea0 100644 --- a/dev_tools/qualtran_dev_tools/notebook_execution.py +++ b/dev_tools/qualtran_dev_tools/notebook_execution.py @@ -18,7 +18,7 @@ import sys import time from pathlib import Path -from typing import List, Optional, Tuple +from typing import Optional import attrs import filelock @@ -31,7 +31,7 @@ from .git_tools import get_git_root -def get_nb_rel_paths(sourceroot: Path) -> List[Tuple[Path, Path]]: +def get_nb_rel_paths(sourceroot: Path) -> list[tuple[Path, Path]]: """List all checked-in *.ipynb files within `sourceroot`. Returns a tuple of the relative path and the path it's relative to (aka sourceroot) @@ -101,7 +101,7 @@ def needs_reexport(self): return self.md_needs_reexport() or self.nb_needs_reexport() -def _make_link_replacements() -> List[Tuple[str, str]]: +def _make_link_replacements() -> list[tuple[str, str]]: """Helper function to make a list of link replacements.""" top_level = [ 'Bloq', diff --git a/dev_tools/qualtran_dev_tools/notebook_specs.py b/dev_tools/qualtran_dev_tools/notebook_specs.py index c65508a9e1..82abb930e8 100644 --- a/dev_tools/qualtran_dev_tools/notebook_specs.py +++ b/dev_tools/qualtran_dev_tools/notebook_specs.py @@ -27,8 +27,6 @@ 3. Update the `NotebookSpec` `bloq_specs` field to include the `BloqDocSpec` for your new bloq. """ -from typing import List - from qualtran_dev_tools.git_tools import get_git_root import qualtran.bloqs.arithmetic.addition @@ -146,7 +144,7 @@ # -------------------------------------------------------------------------- # ----- Basic Gates ---------------------------------------------------- # -------------------------------------------------------------------------- -BASIC_GATES: List[NotebookSpecV2] = [ +BASIC_GATES: list[NotebookSpecV2] = [ NotebookSpecV2( title='T Gate', module=qualtran.bloqs.basic_gates.t_gate, @@ -267,7 +265,7 @@ # -------------------------------------------------------------------------- # ----- Chemistry ------------------------------------------------------ # -------------------------------------------------------------------------- -CHEMISTRY: List[NotebookSpecV2] = [ +CHEMISTRY: list[NotebookSpecV2] = [ NotebookSpecV2( title='Sparse', module=qualtran.bloqs.chemistry.sparse, @@ -785,7 +783,7 @@ # -------------------------------------------------------------------------- # ----- Block Encoding ---------------------------------------------------------- # -------------------------------------------------------------------------- -BLOCK_ENCODING: List[NotebookSpecV2] = [ +BLOCK_ENCODING: list[NotebookSpecV2] = [ NotebookSpecV2( title='Block Encoding Interface', module=qualtran.bloqs.block_encoding, @@ -853,7 +851,7 @@ # -------------------------------------------------------------------------- # ----- Optimization --------------------------------------------------- # -------------------------------------------------------------------------- -OPTIMIZATION: List[NotebookSpecV2] = [ +OPTIMIZATION: list[NotebookSpecV2] = [ # ----- Algorithm ------------------------------------------ NotebookSpecV2( title='kXOR: Instance load Oracles', @@ -898,7 +896,7 @@ ), ] -BOOKKEEPING: List[NotebookSpecV2] = [ +BOOKKEEPING: list[NotebookSpecV2] = [ NotebookSpecV2( title='Split / Join', module=qualtran.bloqs.bookkeeping.split, @@ -947,7 +945,7 @@ # -------------------------------------------------------------------------- # ----- Other ---------------------------------------------------------- # -------------------------------------------------------------------------- -OTHER: List[NotebookSpecV2] = [ +OTHER: list[NotebookSpecV2] = [ NotebookSpecV2( title='Prepare Uniform Superposition', module=qualtran.bloqs.state_preparation.prepare_uniform_superposition, diff --git a/dev_tools/qualtran_dev_tools/parse_docstrings.py b/dev_tools/qualtran_dev_tools/parse_docstrings.py index 9958c96d92..b5662154e6 100644 --- a/dev_tools/qualtran_dev_tools/parse_docstrings.py +++ b/dev_tools/qualtran_dev_tools/parse_docstrings.py @@ -14,7 +14,7 @@ import inspect import re -from typing import List, Type, Union +from typing import Union from attrs import frozen from sphinx.ext.napoleon import Config, GoogleDocstring @@ -59,7 +59,7 @@ def parse_reference(ref_text: str) -> ReferenceT: return UnparsedReference(ref_text) -def parse_references(full_reference_text: str) -> List[ReferenceT]: +def parse_references(full_reference_text: str) -> list[ReferenceT]: reference_texts = re.split(r'\n\n', full_reference_text) my_refs = [] for ref_text in reference_texts: @@ -72,14 +72,14 @@ class _GoogleDocstringToMarkdown(GoogleDocstring): """Subclass of sphinx's parser to emit Markdown from Google-style docstrings.""" def __init__(self, *args, **kwargs): - self.references: List[ReferenceT] = [] + self.references: list[ReferenceT] = [] super().__init__(*args, **kwargs) def _load_custom_sections(self) -> None: super()._load_custom_sections() self._sections['registers'] = self._parse_registers_section - def _parse_parameters_section(self, section: str) -> List[str]: + def _parse_parameters_section(self, section: str) -> list[str]: """Sphinx method to emit a 'Parameters' section.""" def _template(name, desc_lines): @@ -92,7 +92,7 @@ def _template(name, desc_lines): '', ] - def _parse_references_section(self, section: str) -> List[str]: + def _parse_references_section(self, section: str) -> list[str]: """Sphinx method to emit a 'References' section.""" lines = self._dedent(self._consume_to_next_section()) @@ -101,7 +101,7 @@ def _parse_references_section(self, section: str) -> List[str]: self.references.extend(my_refs) return ['#### References', '\n'.join(f' - {ref.text}' for ref in my_refs), ''] - def _parse_registers_section(self, section: str) -> List[str]: + def _parse_registers_section(self, section: str) -> list[str]: def _template(name, desc_lines): desc = ' '.join(desc_lines) return f' - `{name}`: {desc}' @@ -113,7 +113,7 @@ def _template(name, desc_lines): ] -def get_markdown_docstring(cls: Type) -> List[str]: +def get_markdown_docstring(cls: type) -> list[str]: """From a class `cls`, return its docstring as Markdown lines.""" # 1. Sphinx incantation @@ -127,7 +127,7 @@ def get_markdown_docstring(cls: Type) -> List[str]: return lines -def get_markdown_docstring_lines(cls: Type) -> List[str]: +def get_markdown_docstring_lines(cls: type) -> list[str]: """From a class `cls`, return its docstring as Markdown lines with a header.""" # 1. Get documentation lines @@ -139,7 +139,7 @@ def get_markdown_docstring_lines(cls: Type) -> List[str]: return lines -def get_references(cls: Type) -> List[ReferenceT]: +def get_references(cls: type) -> list[ReferenceT]: """Get reference information for a class from the References section of its docstring.""" config = Config() docstring = cls.__doc__ if cls.__doc__ else "" diff --git a/dev_tools/qualtran_dev_tools/prepared_env.py b/dev_tools/qualtran_dev_tools/prepared_env.py index 8dfa56b257..3dff97fc5f 100644 --- a/dev_tools/qualtran_dev_tools/prepared_env.py +++ b/dev_tools/qualtran_dev_tools/prepared_env.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import List, Optional +from typing import Optional from . import shell_tools @@ -47,11 +47,11 @@ def __init__( self.destination_directory = destination_directory - def get_changed_files(self) -> List[str]: + def get_changed_files(self) -> list[str]: """Get the files changed on one git branch vs another. Returns: - List[str]: File paths of changed files, relative to the git repo + list[str]: File paths of changed files, relative to the git repo root. """ optional_actual_commit_id = [] if self.actual_commit_id is None else [self.actual_commit_id] diff --git a/dev_tools/qualtran_dev_tools/reference_docs.py b/dev_tools/qualtran_dev_tools/reference_docs.py index eeffc569f6..91ab2bad9e 100644 --- a/dev_tools/qualtran_dev_tools/reference_docs.py +++ b/dev_tools/qualtran_dev_tools/reference_docs.py @@ -14,8 +14,8 @@ import re from collections import defaultdict +from collections.abc import Iterable from pathlib import Path -from typing import Dict, Iterable, List, Type import jinja2 import tensorflow_docs.api_generator.parser @@ -65,7 +65,7 @@ def filter_type_aliases_in_the_wrong_place(path, parent, children): return ret -def _filter_and_sort_members(py_object: object, members: Iterable[MemberInfo]) -> List[MemberInfo]: +def _filter_and_sort_members(py_object: object, members: Iterable[MemberInfo]) -> list[MemberInfo]: """Sort `members` according to their order in the source definition. For example: you can order class methods according to their order of definition @@ -79,7 +79,7 @@ def _filter_and_sort_members(py_object: object, members: Iterable[MemberInfo]) - return sorted(fmembs, key=lambda m: ordering[m.short_name]) -def mixin_custom_template(template_name: str) -> Type: +def mixin_custom_template(template_name: str) -> type: """Return a mixin for using a custom jinja template in TemplatePageBuilder classes.""" class _CustomTemplateMixin: @@ -383,7 +383,7 @@ def generate_ref_toc(reporoot: Path): page_paths = output_dir.glob('qualtran/**/*.md') # Group according to module - grouped_paths: Dict[Path, List] = defaultdict(list) + grouped_paths: dict[Path, list[Path]] = defaultdict(list) for path in page_paths: grouped_paths[path.parent].append(path) diff --git a/dev_tools/qualtran_dev_tools/shell_tools.py b/dev_tools/qualtran_dev_tools/shell_tools.py index 701ddfa269..f2218d5efc 100644 --- a/dev_tools/qualtran_dev_tools/shell_tools.py +++ b/dev_tools/qualtran_dev_tools/shell_tools.py @@ -14,7 +14,7 @@ import subprocess import sys -from typing import List, Tuple, Union +from typing import Union BOLD = 1 DIM = 2 @@ -37,7 +37,7 @@ def highlight(text: str, color_code: int, bold: bool = False) -> str: return "{}\033[{}m{}\033[0m".format("\033[1m" if bold else "", color_code, text) -def abbreviate_command_arguments_after_switches(cmd: Tuple[str, ...]) -> Tuple[str, ...]: +def abbreviate_command_arguments_after_switches(cmd: tuple[str, ...]) -> tuple[str, ...]: result = [cmd[0]] for i in range(1, len(cmd)): if not cmd[i].startswith("-"): @@ -48,7 +48,7 @@ def abbreviate_command_arguments_after_switches(cmd: Tuple[str, ...]) -> Tuple[s def run( - args: Union[str, List[str]], + args: Union[str, list[str]], *, log_run_to_stderr: bool = True, abbreviate_non_option_arguments: bool = False, @@ -87,7 +87,7 @@ def run( # setup our default for subprocess.run flag arguments subprocess_run_kwargs.update(check=check, text=text) if log_run_to_stderr: - cmd_desc: Tuple[str, ...] = (args,) if isinstance(args, str) else tuple(args) + cmd_desc: tuple[str, ...] = (args,) if isinstance(args, str) else tuple(args) if abbreviate_non_option_arguments: cmd_desc = abbreviate_command_arguments_after_switches(cmd_desc) print("run:", cmd_desc, file=sys.stderr) @@ -96,7 +96,7 @@ def run( ) -def output_of(args: Union[str, List[str]], **kwargs) -> str: +def output_of(args: Union[str, list[str]], **kwargs) -> str: """Invokes a subprocess and returns its output as a string. Args: diff --git a/dev_tools/qualtran_dev_tools/tensor_report_card.py b/dev_tools/qualtran_dev_tools/tensor_report_card.py index c2e3fa2df3..cd3284185d 100644 --- a/dev_tools/qualtran_dev_tools/tensor_report_card.py +++ b/dev_tools/qualtran_dev_tools/tensor_report_card.py @@ -13,7 +13,8 @@ # limitations under the License. import multiprocessing.connection import time -from typing import Any, Callable, Dict, List, Optional, Tuple +from collections.abc import Callable +from typing import Any, Optional from attrs import define @@ -28,7 +29,7 @@ class _Pending: p: multiprocessing.Process recv: multiprocessing.connection.Connection start_time: float - kwargs: Dict[str, Any] + kwargs: dict[str, Any] class ExecuteWithTimeout: @@ -42,15 +43,15 @@ def __init__(self, timeout: float, max_workers: int): self.timeout = timeout self.max_workers = max_workers - self.queued: List[Tuple[Callable, Dict[str, Any]]] = [] - self.pending: List[_Pending] = [] + self.queued: list[tuple[Callable, dict[str, Any]]] = [] + self.pending: list[_Pending] = [] @property def work_to_be_done(self) -> int: """The number of tasks currently executing or queued.""" return len(self.queued) + len(self.pending) - def submit(self, func: Callable, kwargs: Dict[str, Any]) -> None: + def submit(self, func: Callable, kwargs: dict[str, Any]) -> None: """Add a task to the queue. `func` must be a callable that can accept `kwargs` in addition to @@ -92,7 +93,7 @@ def _scan_pendings(self) -> Optional[_Pending]: return None - def next_result(self) -> Tuple[Dict[str, Any], Optional[Any]]: + def next_result(self) -> tuple[dict[str, Any], Optional[Any]]: """Get the next available result. This call is blocking, but should never take longer than `self.timeout`. This should @@ -131,7 +132,7 @@ def report_on_tensors(name: str, cls_name: str, bloq: Bloq, cxn) -> None: This should be used with `ExecuteWithTimeout`. The resultant record dictionary is sent over `cxn`. """ - record: Dict[str, Any] = {'name': name, 'cls': cls_name} + record: dict[str, Any] = {'name': name, 'cls': cls_name} try: start = time.perf_counter() diff --git a/qualtran/protos/bloq_pb2.pyi b/qualtran/protos/bloq_pb2.pyi index b3481a7aab..6b06b48a9e 100644 --- a/qualtran/protos/bloq_pb2.pyi +++ b/qualtran/protos/bloq_pb2.pyi @@ -18,6 +18,7 @@ limitations under the License. """ import builtins import collections.abc +import typing import google.protobuf.descriptor import google.protobuf.internal.containers import google.protobuf.message @@ -28,16 +29,10 @@ import qualtran.protos.data_types_pb2 import qualtran.protos.ec_point_pb2 import qualtran.protos.registers_pb2 import qualtran.protos.sympy_pb2 -import sys - -if sys.version_info >= (3, 8): - import typing as typing_extensions -else: - import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor -@typing_extensions.final +@typing.final class BloqArg(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -104,13 +99,13 @@ class BloqArg(google.protobuf.message.Message): complex_val: qualtran.protos.args_pb2.Complex | None = ..., ec_point: qualtran.protos.ec_point_pb2.ECPoint | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["cirq_json_gzip", b"cirq_json_gzip", "complex_val", b"complex_val", "ctrl_spec", b"ctrl_spec", "ec_point", b"ec_point", "float_val", b"float_val", "int_val", b"int_val", "ndarray", b"ndarray", "qdata_type", b"qdata_type", "register", b"register", "registers", b"registers", "string_val", b"string_val", "subbloq", b"subbloq", "sympy_expr", b"sympy_expr", "val", b"val"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["cirq_json_gzip", b"cirq_json_gzip", "complex_val", b"complex_val", "ctrl_spec", b"ctrl_spec", "ec_point", b"ec_point", "float_val", b"float_val", "int_val", b"int_val", "name", b"name", "ndarray", b"ndarray", "qdata_type", b"qdata_type", "register", b"register", "registers", b"registers", "string_val", b"string_val", "subbloq", b"subbloq", "sympy_expr", b"sympy_expr", "val", b"val"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["val", b"val"]) -> typing_extensions.Literal["int_val", "float_val", "string_val", "sympy_expr", "ndarray", "subbloq", "cirq_json_gzip", "qdata_type", "register", "registers", "ctrl_spec", "complex_val", "ec_point"] | None: ... + def HasField(self, field_name: typing.Literal["cirq_json_gzip", b"cirq_json_gzip", "complex_val", b"complex_val", "ctrl_spec", b"ctrl_spec", "ec_point", b"ec_point", "float_val", b"float_val", "int_val", b"int_val", "ndarray", b"ndarray", "qdata_type", b"qdata_type", "register", b"register", "registers", b"registers", "string_val", b"string_val", "subbloq", b"subbloq", "sympy_expr", b"sympy_expr", "val", b"val"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["cirq_json_gzip", b"cirq_json_gzip", "complex_val", b"complex_val", "ctrl_spec", b"ctrl_spec", "ec_point", b"ec_point", "float_val", b"float_val", "int_val", b"int_val", "name", b"name", "ndarray", b"ndarray", "qdata_type", b"qdata_type", "register", b"register", "registers", b"registers", "string_val", b"string_val", "subbloq", b"subbloq", "sympy_expr", b"sympy_expr", "val", b"val"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["val", b"val"]) -> typing.Literal["int_val", "float_val", "string_val", "sympy_expr", "ndarray", "subbloq", "cirq_json_gzip", "qdata_type", "register", "registers", "ctrl_spec", "complex_val", "ec_point"] | None: ... global___BloqArg = BloqArg -@typing_extensions.final +@typing.final class BloqLibrary(google.protobuf.message.Message): """A library of Bloqs. BloqLibrary should be used to represent both primitive Bloqs and composite Bloqs; i.e. Bloqs consisting of other subbloqs, like `CompositeBloq`, @@ -119,13 +114,13 @@ class BloqLibrary(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor - @typing_extensions.final + @typing.final class BloqWithDecomposition(google.protobuf.message.Message): """Decompositions are specified using integer IDs referencing other Bloqs within this library.""" DESCRIPTOR: google.protobuf.descriptor.Descriptor - @typing_extensions.final + @typing.final class BloqCountsEntry(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -140,8 +135,8 @@ class BloqLibrary(google.protobuf.message.Message): key: builtins.int = ..., value: qualtran.protos.args_pb2.IntOrSympy | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["value", b"value"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["key", b"key", "value", b"value"]) -> None: ... + def HasField(self, field_name: typing.Literal["value", b"value"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["key", b"key", "value", b"value"]) -> None: ... BLOQ_ID_FIELD_NUMBER: builtins.int DECOMPOSITION_FIELD_NUMBER: builtins.int @@ -166,8 +161,8 @@ class BloqLibrary(google.protobuf.message.Message): bloq_counts: collections.abc.Mapping[builtins.int, qualtran.protos.args_pb2.IntOrSympy] | None = ..., bloq: global___Bloq | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["bloq", b"bloq"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["bloq", b"bloq", "bloq_counts", b"bloq_counts", "bloq_id", b"bloq_id", "decomposition", b"decomposition"]) -> None: ... + def HasField(self, field_name: typing.Literal["bloq", b"bloq"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["bloq", b"bloq", "bloq_counts", b"bloq_counts", "bloq_id", b"bloq_id", "decomposition", b"decomposition"]) -> None: ... NAME_FIELD_NUMBER: builtins.int TABLE_FIELD_NUMBER: builtins.int @@ -181,11 +176,11 @@ class BloqLibrary(google.protobuf.message.Message): name: builtins.str = ..., table: collections.abc.Iterable[global___BloqLibrary.BloqWithDecomposition] | None = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["name", b"name", "table", b"table"]) -> None: ... + def ClearField(self, field_name: typing.Literal["name", b"name", "table", b"table"]) -> None: ... global___BloqLibrary = BloqLibrary -@typing_extensions.final +@typing.final class Bloq(google.protobuf.message.Message): """Messages to enable efficient description of a BloqLibrary, including Bloq decompositions in terms of other simpler bloqs. @@ -218,12 +213,12 @@ class Bloq(google.protobuf.message.Message): registers: qualtran.protos.registers_pb2.Registers | None = ..., t_complexity: qualtran.protos.annotations_pb2.TComplexity | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["registers", b"registers", "t_complexity", b"t_complexity"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["args", b"args", "name", b"name", "registers", b"registers", "t_complexity", b"t_complexity"]) -> None: ... + def HasField(self, field_name: typing.Literal["registers", b"registers", "t_complexity", b"t_complexity"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["args", b"args", "name", b"name", "registers", b"registers", "t_complexity", b"t_complexity"]) -> None: ... global___Bloq = Bloq -@typing_extensions.final +@typing.final class BloqInstance(google.protobuf.message.Message): """Specific instance of a Bloq.""" @@ -239,11 +234,11 @@ class BloqInstance(google.protobuf.message.Message): instance_id: builtins.int = ..., bloq_id: builtins.int = ..., ) -> None: ... - def ClearField(self, field_name: typing_extensions.Literal["bloq_id", b"bloq_id", "instance_id", b"instance_id"]) -> None: ... + def ClearField(self, field_name: typing.Literal["bloq_id", b"bloq_id", "instance_id", b"instance_id"]) -> None: ... global___BloqInstance = BloqInstance -@typing_extensions.final +@typing.final class Soquet(google.protobuf.message.Message): """One half of a connection.""" @@ -268,13 +263,13 @@ class Soquet(google.protobuf.message.Message): register: qualtran.protos.registers_pb2.Register | None = ..., index: collections.abc.Iterable[builtins.int] | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["binst", b"binst", "bloq_instance", b"bloq_instance", "dangling_t", b"dangling_t", "register", b"register"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["binst", b"binst", "bloq_instance", b"bloq_instance", "dangling_t", b"dangling_t", "index", b"index", "register", b"register"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["binst", b"binst"]) -> typing_extensions.Literal["bloq_instance", "dangling_t"] | None: ... + def HasField(self, field_name: typing.Literal["binst", b"binst", "bloq_instance", b"bloq_instance", "dangling_t", b"dangling_t", "register", b"register"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["binst", b"binst", "bloq_instance", b"bloq_instance", "dangling_t", b"dangling_t", "index", b"index", "register", b"register"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["binst", b"binst"]) -> typing.Literal["bloq_instance", "dangling_t"] | None: ... global___Soquet = Soquet -@typing_extensions.final +@typing.final class Connection(google.protobuf.message.Message): """A connection between two Soquets. Quantum compute graph can be represented as a list of connections. @@ -294,7 +289,7 @@ class Connection(google.protobuf.message.Message): left: global___Soquet | None = ..., right: global___Soquet | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["left", b"left", "right", b"right"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["left", b"left", "right", b"right"]) -> None: ... + def HasField(self, field_name: typing.Literal["left", b"left", "right", b"right"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["left", b"left", "right", b"right"]) -> None: ... global___Connection = Connection diff --git a/qualtran/protos/ec_point_pb2.pyi b/qualtran/protos/ec_point_pb2.pyi index ac82158cd6..bfe37949c1 100644 --- a/qualtran/protos/ec_point_pb2.pyi +++ b/qualtran/protos/ec_point_pb2.pyi @@ -14,19 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. """ import builtins +import typing import google.protobuf.descriptor import google.protobuf.message import qualtran.protos.args_pb2 -import sys - -if sys.version_info >= (3, 8): - import typing as typing_extensions -else: - import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor -@typing_extensions.final +@typing.final class ECPoint(google.protobuf.message.Message): DESCRIPTOR: google.protobuf.descriptor.Descriptor @@ -50,8 +45,8 @@ class ECPoint(google.protobuf.message.Message): mod: qualtran.protos.args_pb2.IntOrSympy | None = ..., curve_a: qualtran.protos.args_pb2.IntOrSympy | None = ..., ) -> None: ... - def HasField(self, field_name: typing_extensions.Literal["_curve_a", b"_curve_a", "curve_a", b"curve_a", "mod", b"mod", "x", b"x", "y", b"y"]) -> builtins.bool: ... - def ClearField(self, field_name: typing_extensions.Literal["_curve_a", b"_curve_a", "curve_a", b"curve_a", "mod", b"mod", "x", b"x", "y", b"y"]) -> None: ... - def WhichOneof(self, oneof_group: typing_extensions.Literal["_curve_a", b"_curve_a"]) -> typing_extensions.Literal["curve_a"] | None: ... + def HasField(self, field_name: typing.Literal["_curve_a", b"_curve_a", "curve_a", b"curve_a", "mod", b"mod", "x", b"x", "y", b"y"]) -> builtins.bool: ... + def ClearField(self, field_name: typing.Literal["_curve_a", b"_curve_a", "curve_a", b"curve_a", "mod", b"mod", "x", b"x", "y", b"y"]) -> None: ... + def WhichOneof(self, oneof_group: typing.Literal["_curve_a", b"_curve_a"]) -> typing.Literal["curve_a"] | None: ... global___ECPoint = ECPoint diff --git a/qualtran/protos/registers_pb2.pyi b/qualtran/protos/registers_pb2.pyi index e51a9bf096..b3e3f1823b 100644 --- a/qualtran/protos/registers_pb2.pyi +++ b/qualtran/protos/registers_pb2.pyi @@ -19,19 +19,13 @@ limitations under the License. import builtins import collections.abc +import typing import google.protobuf.descriptor import google.protobuf.internal.containers import google.protobuf.internal.enum_type_wrapper import google.protobuf.message import qualtran.protos.args_pb2 import qualtran.protos.data_types_pb2 -import sys -import typing - -if sys.version_info >= (3, 10): - import typing as typing_extensions -else: - import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor @@ -41,7 +35,7 @@ class Register(google.protobuf.message.Message): class _Side: ValueType = typing.NewType("ValueType", builtins.int) - V: typing_extensions.TypeAlias = ValueType + V: typing.TypeAlias = ValueType class _SideEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[Register._Side.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor diff --git a/qualtran/protos/sympy_pb2.pyi b/qualtran/protos/sympy_pb2.pyi index 868aae3c3f..48931283ec 100644 --- a/qualtran/protos/sympy_pb2.pyi +++ b/qualtran/protos/sympy_pb2.pyi @@ -19,23 +19,17 @@ limitations under the License. import builtins import collections.abc +import typing import google.protobuf.descriptor import google.protobuf.internal.containers import google.protobuf.internal.enum_type_wrapper import google.protobuf.message -import sys -import typing - -if sys.version_info >= (3, 10): - import typing as typing_extensions -else: - import typing_extensions DESCRIPTOR: google.protobuf.descriptor.FileDescriptor class _Function: ValueType = typing.NewType("ValueType", builtins.int) - V: typing_extensions.TypeAlias = ValueType + V: typing.TypeAlias = ValueType class _FunctionEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_Function.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor @@ -81,7 +75,7 @@ global___Function = Function class _ConstSymbol: ValueType = typing.NewType("ValueType", builtins.int) - V: typing_extensions.TypeAlias = ValueType + V: typing.TypeAlias = ValueType class _ConstSymbolEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_ConstSymbol.ValueType], builtins.type): DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor