Source code for symforce.test_util.stubs_util

# ----------------------------------------------------------------------------
# SymForce - Copyright 2022, Skydio, Inc.
# This source code is under the Apache 2.0 license found in the LICENSE file.
# ----------------------------------------------------------------------------

from __future__ import annotations

import typing as T

import pybind11_stubgen
import pybind11_stubgen.parser.mixins.fix as fix_mixins
import pybind11_stubgen.parser.mixins.parse as parse_mixins
from pybind11_stubgen import ExtractSignaturesFromPybind11Docstrings
from pybind11_stubgen import FixMissingImports as PybindFixMissingImports
from pybind11_stubgen import (
    FixMissingNoneHashFieldAnnotation as PybindFixMissingNoneHashFieldAnnotation,
)
from pybind11_stubgen import IParser
from pybind11_stubgen.structs import Class
from pybind11_stubgen.structs import Docstring
from pybind11_stubgen.structs import Field
from pybind11_stubgen.structs import Identifier
from pybind11_stubgen.structs import Import
from pybind11_stubgen.structs import InvalidExpression
from pybind11_stubgen.structs import QualifiedName
from pybind11_stubgen.structs import ResolvedType
from pybind11_stubgen.structs import Value


[docs] class FixMissingImports(PybindFixMissingImports): def _add_import(self, name: QualifiedName) -> None: if len(name) == 0: return if name[0] == Identifier("lcmtypes"): self.__extra_imports.add(Import(name=None, origin=name.parent)) return super()._add_import(name)
[docs] def patch_lcmtype_imports() -> None: fix_mixins.FixMissingImports = FixMissingImports # type: ignore[misc] pybind11_stubgen.FixMissingImports = FixMissingImports # type: ignore[misc]
[docs] def patch_handle_docstring() -> None: """ Patch BaseParser.handle_docstring to always strip empty lines from the start or end of docstrings """ def handle_docstring(self: IParser, path: QualifiedName, value: T.Any) -> T.Optional[Docstring]: if isinstance(value, str): assert isinstance(self, ExtractSignaturesFromPybind11Docstrings) return self._strip_empty_lines(value.splitlines()) return None parse_mixins.BaseParser.handle_docstring = handle_docstring # type: ignore[method-assign]
[docs] def patch_fix_missing_none_hash_field_annotation() -> None: """ See https://github.com/sizmailov/pybind11-stubgen/pull/236 """ def handle_field( self: PybindFixMissingNoneHashFieldAnnotation, path: QualifiedName, field: T.Any, ) -> T.Optional[Field]: result = super(PybindFixMissingNoneHashFieldAnnotation, self).handle_field(path, field) # type: ignore[safe-super] if result is None: return None if field is None and path[-1] == "__hash__": result.attribute.annotation = self.parse_annotation_str("typing.ClassVar[typing.Any]") return result fix_mixins.FixMissingNoneHashFieldAnnotation.handle_field = handle_field # type: ignore[method-assign]
[docs] class FixNumpyArrayRemoveParameters(IParser): __ndarray_name = QualifiedName.from_str("numpy.typing.ArrayLike")
[docs] def handle_class(self, path: QualifiedName, class_: type) -> T.Optional[Class]: maybe_class = super().handle_class(path, class_) # type: ignore[safe-super] if maybe_class is None: return maybe_class methods = [] for method in maybe_class.methods: if method not in methods: methods.append(method) maybe_class.methods = methods return maybe_class
[docs] def parse_annotation_str(self, annotation_str: str) -> ResolvedType | InvalidExpression | Value: result = super().parse_annotation_str(annotation_str) # type: ignore[safe-super] if isinstance(result, ResolvedType) and result.name == QualifiedName.from_str( "typing.Annotated" ): assert ( result.parameters is not None and len(result.parameters) >= 1 and isinstance(result.parameters[0], ResolvedType) ) if result.parameters[0].name == self.__ndarray_name: return result.parameters[0] return result
[docs] def patch_remove_parameters() -> None: """ Fix NumpyArrayRemoveParameters to work with pybind 3.x and deduplicate overloads """ fix_mixins.FixNumpyArrayRemoveParameters = FixNumpyArrayRemoveParameters # type: ignore[misc,assignment] pybind11_stubgen.FixNumpyArrayRemoveParameters = FixNumpyArrayRemoveParameters # type: ignore[misc,assignment]