Skip to content

Commit

Permalink
Attempt at automatic typing for basix (#526)
Browse files Browse the repository at this point in the history
* Not tested

* mypy passes on basix module

* Add __version__ to pyi file

* types should no longer be needed in wrapper docs

* remove types from template

* mypy checks

* remove pip install ffcx

* |

* mypy checks

* types

Co-authored-by: Matthew Scroggs <[email protected]>
  • Loading branch information
jhale and mscroggs authored Jun 23, 2022
1 parent 99b2abc commit a1c50aa
Show file tree
Hide file tree
Showing 9 changed files with 492 additions and 157 deletions.
8 changes: 3 additions & 5 deletions .github/workflows/dolfin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,6 @@ jobs:
python3 -m pip install git+https://github.com/FEniCS/ufl.git@${{ github.event.inputs.ufl_branch }}
python3 -m pip install git+https://github.com/FEniCS/ffcx.git@${{ github.event.inputs.ffcx_branch }}
- name: Run cpp demos
run: |
python3 -m pytest demo/cpp/test.py
- name: Get DOLFINx
if: github.event_name != 'workflow_dispatch'
uses: actions/checkout@v3
Expand All @@ -78,14 +74,16 @@ jobs:
path: ./dolfinx
repository: FEniCS/dolfinx
ref: ${{ github.event.inputs.dolfinx_branch }}

- name: Install DOLFINx
run: |
cmake -G Ninja -DCMAKE_BUILD_TYPE=Developer -B build -S dolfinx/cpp/
cmake --build build
cmake --install build
python3 -m pip -v install --global-option build --global-option --debug dolfinx/python/
- name: Run mypy checks
run: python3 -m mypy dolfinx/python/dolfinx

- name: Build DOLFINx C++ unit tests
run: |
cmake -G Ninja -DCMAKE_BUILD_TYPE=Developer -B build/test/ -S build/test/
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ffcx-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ jobs:
repository: FEniCS/ffcx
ref: ${{ github.event.inputs.ffcx_branch }}

- name: Run mypy checks
run: |
python -m pip install mypy types-setuptools
python -m mypy ffcx/ffcx
- name: Install FFCx
run: pip install ./ffcx[ci]
- name: Run FFCx tests
Expand Down
290 changes: 145 additions & 145 deletions cpp/docs.template

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions cpp/generate_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ def get_docstring(matches):
return "\n".join(doclines)

if info_type == "param":
assert typename is not None
params = {}
for i in doc.split("@param")[1:]:
i = i.split("@return")[0]
Expand All @@ -127,16 +126,15 @@ def get_docstring(matches):
p = i
pdoc = "TODO: document this"
params[p] = "\n ".join(pdoc.split("\n"))
return f"{info} ({typename}): {params[info]}"
return f"{info}: {params[info]}"

if info_type == "return":
assert typename is not None
returns = [i.split("@param")[0].strip() for i in doc.split("@return")[1:]]
if len(returns) == 0:
returns.append("TODO: document this")
assert len(returns) == 1
returns = "\n ".join(returns[0].split("\n"))
return f"{typename}: {returns}"
return f"{returns}"


def generate_docs():
Expand Down
331 changes: 331 additions & 0 deletions python/basix/_basixcpp.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
from typing import Any, ClassVar, List, Tuple

from typing import overload
import numpy

import numpy.typing as npt

__version__: str = ...

class CellType:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
hexahedron: ClassVar[CellType] = ...
interval: ClassVar[CellType] = ...
point: ClassVar[CellType] = ...
prism: ClassVar[CellType] = ...
pyramid: ClassVar[CellType] = ...
quadrilateral: ClassVar[CellType] = ...
tetrahedron: ClassVar[CellType] = ...
triangle: ClassVar[CellType] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class DPCVariant:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
diagonal_equispaced: ClassVar[DPCVariant] = ...
diagonal_gll: ClassVar[DPCVariant] = ...
horizontal_equispaced: ClassVar[DPCVariant] = ...
horizontal_gll: ClassVar[DPCVariant] = ...
legendre: ClassVar[DPCVariant] = ...
simplex_equispaced: ClassVar[DPCVariant] = ...
simplex_gll: ClassVar[DPCVariant] = ...
unset: ClassVar[DPCVariant] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class ElementFamily:
__members__: ClassVar[dict] = ... # read-only
BDM: ClassVar[ElementFamily] = ...
CR: ClassVar[ElementFamily] = ...
DPC: ClassVar[ElementFamily] = ...
HHJ: ClassVar[ElementFamily] = ...
Hermite: ClassVar[ElementFamily] = ...
N1E: ClassVar[ElementFamily] = ...
N2E: ClassVar[ElementFamily] = ...
P: ClassVar[ElementFamily] = ...
RT: ClassVar[ElementFamily] = ...
Regge: ClassVar[ElementFamily] = ...
__entries: ClassVar[dict] = ...
bubble: ClassVar[ElementFamily] = ...
custom: ClassVar[ElementFamily] = ...
serendipity: ClassVar[ElementFamily] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class FiniteElement:
def __hash__(self, object, int): ClassVar[None] = ...
def __init__(self, *args, **kwargs) -> None: ...
def apply_dof_transformation(self, arg0: npt.NDArray[numpy.float64], arg1: int, arg2: int) -> npt.NDArray[numpy.float64]: ...
def apply_dof_transformation_to_transpose(self, arg0: npt.NDArray[numpy.float64], arg1: int, arg2: int) -> npt.NDArray[numpy.float64]: ...
def apply_inverse_transpose_dof_transformation(self, arg0: npt.NDArray[numpy.float64], arg1: int, arg2: int) -> npt.NDArray[numpy.float64]: ...
def base_transformations(self) -> npt.NDArray[numpy.float64]: ...
def entity_transformations(self) -> dict: ...
def get_tensor_product_representation(self) -> List[Tuple[List[FiniteElement],List[int]]]: ...
def pull_back(self, arg0: npt.NDArray[numpy.float64], arg1: npt.NDArray[numpy.float64], arg2: npt.NDArray[numpy.float64], arg3: npt.NDArray[numpy.float64]) -> npt.NDArray[numpy.float64]: ...
def push_forward(self, arg0: npt.NDArray[numpy.float64], arg1: npt.NDArray[numpy.float64], arg2: npt.NDArray[numpy.float64], arg3: npt.NDArray[numpy.float64]) -> npt.NDArray[numpy.float64]: ...
def tabulate(self, arg0: int, arg1: npt.NDArray[numpy.float64]) -> npt.NDArray[numpy.float64]: ...
def __eq__(self, arg0: object) -> bool: ...
@property
def M(self) -> List[List[npt.NDArray[numpy.float64]]]: ...
@property
def cell_type(self) -> CellType: ...
@property
def coefficient_matrix(self) -> npt.NDArray[numpy.float64]: ...
@property
def degree(self) -> int: ...
@property
def dim(self) -> int: ...
@property
def discontinuous(self) -> bool: ...
@property
def dof_transformations_are_identity(self) -> bool: ...
@property
def dof_transformations_are_permutations(self) -> bool: ...
@property
def dpc_variant(self) -> Any: ...
@property
def dual_matrix(self) -> npt.NDArray[numpy.float64]: ...
@property
def entity_closure_dofs(self) -> List[List[List[int]]]: ...
@property
def entity_dofs(self) -> List[List[List[int]]]: ...
@property
def family(self) -> ElementFamily: ...
@property
def has_tensor_product_factorisation(self) -> bool: ...
@property
def highest_complete_degree(self) -> int: ...
@property
def highest_degree(self) -> int: ...
@property
def interpolation_is_identity(self) -> bool: ...
@property
def interpolation_matrix(self) -> npt.NDArray[numpy.float64]: ...
@property
def interpolation_nderivs(self) -> int: ...
@property
def lagrange_variant(self) -> Any: ...
@property
def map_type(self) -> MapType: ...
@property
def num_entity_closure_dofs(self) -> List[List[int]]: ...
@property
def num_entity_dofs(self) -> List[List[int]]: ...
@property
def points(self) -> npt.NDArray[numpy.float64]: ...
@property
def value_shape(self) -> List[int]: ...
@property
def value_size(self) -> int: ...
@property
def wcoeffs(self) -> npt.NDArray[numpy.float64]: ...
@property
def x(self) -> List[List[npt.NDArray[numpy.float64]]]: ...

class LagrangeVariant:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
chebyshev_centroid: ClassVar[LagrangeVariant] = ...
chebyshev_isaac: ClassVar[LagrangeVariant] = ...
chebyshev_warped: ClassVar[LagrangeVariant] = ...
equispaced: ClassVar[LagrangeVariant] = ...
gl_centroid: ClassVar[LagrangeVariant] = ...
gl_isaac: ClassVar[LagrangeVariant] = ...
gl_warped: ClassVar[LagrangeVariant] = ...
gll_centroid: ClassVar[LagrangeVariant] = ...
gll_isaac: ClassVar[LagrangeVariant] = ...
gll_warped: ClassVar[LagrangeVariant] = ...
legendre: ClassVar[LagrangeVariant] = ...
unset: ClassVar[LagrangeVariant] = ...
vtk: ClassVar[LagrangeVariant] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class LatticeSimplexMethod:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
centroid: ClassVar[LatticeSimplexMethod] = ...
isaac: ClassVar[LatticeSimplexMethod] = ...
none: ClassVar[LatticeSimplexMethod] = ...
warp: ClassVar[LatticeSimplexMethod] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class LatticeType:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
chebyshev: ClassVar[LatticeType] = ...
equispaced: ClassVar[LatticeType] = ...
gl: ClassVar[LatticeType] = ...
gll: ClassVar[LatticeType] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class MapType:
__members__: ClassVar[dict] = ... # read-only
L2Piola: ClassVar[MapType] = ...
__entries: ClassVar[dict] = ...
contravariantPiola: ClassVar[MapType] = ...
covariantPiola: ClassVar[MapType] = ...
doubleContravariantPiola: ClassVar[MapType] = ...
doubleCovariantPiola: ClassVar[MapType] = ...
identity: ClassVar[MapType] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class PolynomialType:
__members__: ClassVar[dict] = ... # read-only
__entries: ClassVar[dict] = ...
legendre: ClassVar[PolynomialType] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

class QuadratureType:
__members__: ClassVar[dict] = ... # read-only
Default: ClassVar[QuadratureType] = ...
__entries: ClassVar[dict] = ...
gauss_jacobi: ClassVar[QuadratureType] = ...
gll: ClassVar[QuadratureType] = ...
xiao_gimbutas: ClassVar[QuadratureType] = ...
def __init__(self, value: int) -> None: ...
def __eq__(self, other: object) -> bool: ...
def __getstate__(self) -> int: ...
def __hash__(self) -> int: ...
def __index__(self) -> int: ...
def __int__(self) -> int: ...
def __ne__(self, other: object) -> bool: ...
def __setstate__(self, state: int) -> None: ...
@property
def name(self) -> str: ...
@property
def value(self) -> int: ...

def cell_facet_jacobians(arg0: CellType) -> npt.NDArray[numpy.float64]: ...
def cell_facet_normals(arg0: CellType) -> npt.NDArray[numpy.float64]: ...
def cell_facet_orientations(arg0: CellType) -> List[bool]: ...
def cell_facet_outward_normals(arg0: CellType) -> npt.NDArray[numpy.float64]: ...
def cell_facet_reference_volumes(arg0: CellType) -> npt.NDArray[numpy.float64]: ...
def cell_volume(arg0: CellType) -> float: ...
def compute_interpolation_operator(arg0: FiniteElement, arg1: FiniteElement) -> npt.NDArray[numpy.float64]: ...
def create_custom_element(arg0: CellType, arg1: List[int], arg2: npt.NDArray[numpy.float64], arg3: List[List[npt.NDArray[numpy.float64]]], arg4: List[List[npt.NDArray[numpy.float64]]], arg5: int, arg6: MapType, arg7: bool, arg8: int, arg9: int) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: bool) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: LagrangeVariant, arg4: bool) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: DPCVariant, arg4: bool) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: LagrangeVariant, arg4: DPCVariant, arg5: bool) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: LagrangeVariant) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: DPCVariant) -> FiniteElement: ...
@overload
def create_element(arg0: ElementFamily, arg1: CellType, arg2: int, arg3: LagrangeVariant, arg4: DPCVariant) -> FiniteElement: ...
@overload
def create_lattice(arg0, arg1: int, arg2: LatticeType, arg3: bool) -> npt.NDArray[numpy.float64]: ...
@overload
def create_lattice(arg0, arg1: int, arg2: LatticeType, arg3: bool, arg4: LatticeSimplexMethod) -> npt.NDArray[numpy.float64]: ...
def geometry(arg0) -> npt.NDArray[numpy.float64]: ...
@overload
def index(arg0: int) -> int: ...
@overload
def index(arg0: int, arg1: int) -> int: ...
@overload
def index(arg0: int, arg1: int, arg2: int) -> int: ...
@overload
def make_quadrature(arg0: QuadratureType, arg1: CellType, arg2: int) -> Tuple[npt.NDArray[numpy.float64],npt.NDArray[numpy.float64]]: ...
@overload
def make_quadrature(arg0: CellType, arg1: int) -> Tuple[npt.NDArray[numpy.float64],npt.NDArray[numpy.float64]]: ...
def sub_entity_connectivity(arg0) -> List[List[List[List[int]]]]: ...
def sub_entity_geometry(arg0, arg1: int, arg2: int) -> npt.NDArray[numpy.float64]: ...
def tabulate_polynomial_set(arg0: CellType, arg1: int, arg2: int, arg3: npt.NDArray[numpy.float64]) -> npt.NDArray[numpy.float64]: ...
def tabulate_polynomials(arg0: PolynomialType, arg1, arg2: int, arg3: npt.NDArray[numpy.float64]) -> npt.NDArray[numpy.float64]: ...
@overload
def topology(arg0) -> List[List[List[int]]]: ...
@overload
def topology(vertexindices) -> Any: ...
Empty file added python/basix/py.typed
Empty file.
Loading

0 comments on commit a1c50aa

Please sign in to comment.