mirror of
https://github.com/Cantera/cantera.git
synced 2026-08-08 20:18:24 -05:00
[Python] Simplify Claude's verbose comments
This commit is contained in:
@@ -162,29 +162,13 @@ private:
|
||||
void* m_pyobj;
|
||||
};
|
||||
|
||||
//! Create a `Func1Py` wrapping a Python callback and return it as a ``shared_ptr``.
|
||||
//!
|
||||
//! This factory exists so that the Cython layer can construct a `Func1Py` without the
|
||||
//! C++ ``new`` operator. ``new`` is not valid Python syntax, and its presence would
|
||||
//! prevent the pure-Python ``.py`` source from being parsed by the Python-based type
|
||||
//! checkers (mypy/stubtest), which is what allows the module to ship its annotations
|
||||
//! inline instead of in a separate ``.pyi`` stub.
|
||||
inline std::shared_ptr<Cantera::Func1> newFunc1Py(callback_wrapper callback, void* pyobj)
|
||||
{
|
||||
return std::make_shared<Func1Py>(callback, pyobj);
|
||||
}
|
||||
|
||||
//! Return the Python ``CanteraError`` class, used by translate_exception() to raise a
|
||||
//! ``CanteraError`` from C++ code.
|
||||
//!
|
||||
//! The class object is fetched on first use from its single canonical definition in the
|
||||
//! ``cantera._utils`` module and cached. Resolving it this way (rather than referencing a
|
||||
//! shared C symbol) keeps each Python extension module self-contained: a shared symbol
|
||||
//! previously required loading the main extension with ``RTLD_GLOBAL`` on POSIX and could
|
||||
//! not be linked across DLL boundaries on Windows (enhancement #241). Because the lookup
|
||||
//! is automatic, any extension that includes this header can raise ``CanteraError``
|
||||
//! without registering anything.
|
||||
inline PyObject* getCanteraError() {
|
||||
//! ``cantera._utils`` module and cached. Resolving it this way keeps each Python
|
||||
// extension module self-contained.
|
||||
inline PyObject* getCanteraErrorClass() {
|
||||
// Cached per extension module; CanteraError is a singleton class object, so the
|
||||
// borrowed reference held here remains valid for the lifetime of the module.
|
||||
static PyObject* cls = nullptr;
|
||||
@@ -262,7 +246,7 @@ inline int translate_exception()
|
||||
} catch (const Cantera::ArraySizeError& exn) {
|
||||
PyErr_SetString(PyExc_ValueError, exn.what());
|
||||
} catch (const Cantera::CanteraError& exn) {
|
||||
PyErr_SetString(getCanteraError(), exn.what());
|
||||
PyErr_SetString(getCanteraErrorClass(), exn.what());
|
||||
} catch (const std::exception& exn) {
|
||||
PyErr_SetString(PyExc_RuntimeError, exn.what());
|
||||
} catch (...) {
|
||||
|
||||
@@ -80,10 +80,10 @@ for pyxfile in multi_glob(localenv, "cantera", "pyx"):
|
||||
f"#build/temp-py/{pyxfile.name.split('.')[0]}", cythonized[0])
|
||||
cython_obj.append(obj)
|
||||
|
||||
# The aggregator module _cantera uses Cython pure-Python (.py) syntax (enhancement #241),
|
||||
# but unlike the standalone pure_py_modules below it is cythonized and compiled INTO the
|
||||
# merged _cantera extension here: it hosts the CythonPackageMetaPathFinder and provides
|
||||
# the PyInit functions for the remaining .pyx modules merged into this extension. Its .py
|
||||
# The aggregator module _cantera uses Cython pure-Python (.py) syntax, but unlike the
|
||||
# standalone pure_py_modules below it is cythonized and compiled INTO the merged
|
||||
# _cantera extension here: it hosts the CythonPackageMetaPathFinder and provides the
|
||||
# PyInit functions for the remaining .pyx modules merged into this extension. Its .py
|
||||
# source ships alongside the extension to serve tracebacks, IDEs, and type checkers.
|
||||
_cantera_cpp = localenv.Command(
|
||||
"cantera/_cantera.cpp", "cantera/_cantera.py",
|
||||
@@ -106,12 +106,14 @@ ext = localenv.LoadableModule(f"cantera/_cantera{module_ext}",
|
||||
cython_obj, LIBPREFIX="", SHLIBSUFFIX=module_ext,
|
||||
SHLIBPREFIX="", LIBSUFFIXES=[module_ext])
|
||||
|
||||
# Cython pure-Python-syntax modules built as their own extensions (PoC, enhancement
|
||||
# #241). Each ships its .py source alongside the compiled extension: the extension wins
|
||||
# CPython import precedence, while the .py serves tracebacks, IDEs, and type checkers.
|
||||
pure_py_modules = ["_utils", "jacobians", "constants", "units", "func1", "reactionpath",
|
||||
"yamlwriter", "speciesthermo", "mixture", "transport", "solutionbase",
|
||||
"kinetics", "reaction", "thermo", "reactor", "_onedim", "delegator"]
|
||||
# Cython pure-Python-syntax modules built as their own extensions. Each ships its .py
|
||||
# source alongside the compiled extension: the extension wins CPython import precedence,
|
||||
# while the .py serves tracebacks, IDEs, and type checkers.
|
||||
pure_py_modules = [
|
||||
"constants", "delegator", "func1", "jacobians", "kinetics", "mixture", "_onedim",
|
||||
"reaction", "reactionpath", "reactor", "solutionbase", "speciesthermo", "thermo",
|
||||
"transport", "units", "_utils", "yamlwriter"
|
||||
]
|
||||
pure_py_ext = []
|
||||
for _name in pure_py_modules:
|
||||
if _name == "_utils":
|
||||
|
||||
@@ -41,15 +41,12 @@ if TYPE_CHECKING:
|
||||
|
||||
# Parametrized generics (tuple[...]) are coerced by Cython's annotation_typing just
|
||||
# like bare builtins, rejecting a list where a tuple was published; route through a
|
||||
# TypeAlias (not coerced) to keep the runtime accepting any sequence, as before
|
||||
# (thermo.py's _TPQSetter precedent).
|
||||
# TypeAlias (not coerced) to keep the runtime accepting any sequence
|
||||
_BoundsPair: _TypeAlias = tuple[float, float]
|
||||
|
||||
# `anymap_to_py` may return an `AnyMap` (a `dict` subclass) rather than a plain
|
||||
# `dict`; an inline `dict[str, str]` return annotation is coerced by Cython 3 and
|
||||
# rejects that subclass instance at runtime (regression caught by
|
||||
# test_onedim.py's save/restore tests). Route through a TypeAlias (not coerced),
|
||||
# matching the `_BoundsPair` precedent above.
|
||||
# rejects that subclass instance at runtime. Route through a TypeAlias (not coerced).
|
||||
_RestoreMetadata: _TypeAlias = dict[str, str]
|
||||
|
||||
_ToleranceSettings = _TypedDict(
|
||||
@@ -242,8 +239,6 @@ class Domain1D:
|
||||
def grid(self) -> _Array:
|
||||
"""The grid for this domain."""
|
||||
grid_span: span[const_double] = self.domain.grid()
|
||||
# Non-owning memoryview over the C++ span data (pure-Python spelling of the
|
||||
# .pyx `<double[:grid_span.size()]> grid_span.data()` sized pointer cast).
|
||||
garr: view.array = view.array(shape=(grid_span.size(),),
|
||||
itemsize=cython.sizeof(cython.double), format="d",
|
||||
allocate_buffer=False)
|
||||
@@ -376,9 +371,6 @@ class Domain1D:
|
||||
"""
|
||||
self.domain.setFlatProfile(stringify(component), value)
|
||||
|
||||
# Parametrized generics (tuple[...]) are coerced by Cython's annotation_typing
|
||||
# just like bare builtins; route through a TypeAlias to avoid rejecting e.g. a
|
||||
# list where a tuple was published (see thermo.py's _TPQSetter precedent).
|
||||
def set_bounds(
|
||||
self,
|
||||
*,
|
||||
|
||||
@@ -114,9 +114,6 @@ cdef comp_map_to_dict(Composition m)
|
||||
cdef Composition comp_map(X) except *
|
||||
|
||||
cdef CxxAnyMap py_to_anymap(data, cbool hyphenize=*) except *
|
||||
# Argument passed by value rather than by reference: pure-Python Cython syntax (used in
|
||||
# the paired _utils.py) cannot spell a C++ reference parameter, and these helpers only
|
||||
# read or locally mutate a copy of the argument, so by-value is behavior-preserving.
|
||||
cdef anymap_to_py(CxxAnyMap m)
|
||||
|
||||
cdef CxxAnyValue python_to_anyvalue(item, name=*) except *
|
||||
|
||||
@@ -254,13 +254,12 @@ class AnyMap(dict):
|
||||
self[key] = _DimensionalValue(value, src, True)
|
||||
|
||||
|
||||
# anyvalue_to_python / anymap_to_py take their argument by value so that the cross-module
|
||||
# cimport signature is expressible in pure-Python syntax (which has no C++ reference
|
||||
# spelling). To avoid deep-copying nested children at every level of the recursion, the
|
||||
# by-value entry points immediately take the address of their (now local) argument and
|
||||
# delegate to the pointer-based workers below, which descend without further copies --
|
||||
# matching the original reference-based .pyx (each vector element is still copied once into
|
||||
# its loop variable, exactly as before).
|
||||
# anyvalue_to_python / anymap_to_py take their argument by value so that the
|
||||
# cross-module cimport signature is expressible in pure-Python syntax (which as of
|
||||
# Cython 3.2.5 has no C++ reference spelling). To avoid deep-copying nested children at
|
||||
# every level of the recursion, the by-value entry points immediately take the address
|
||||
# of their (now local) argument and delegate to the pointer-based workers below, which
|
||||
# descend without further copies.
|
||||
|
||||
@cython.cfunc
|
||||
def anyvalue_to_python(name: string, v: CxxAnyValue):
|
||||
|
||||
@@ -481,8 +481,7 @@ class Quantity:
|
||||
|
||||
# Synonyms for total properties. The literal properties below are type-only
|
||||
# declarations: the assignments that follow the class body overwrite them at
|
||||
# runtime with the *bound* property objects (verified equivalent; see also the
|
||||
# dynamically-added pass-through properties below, which use the same pattern).
|
||||
# runtime with the *bound* property objects.
|
||||
@property
|
||||
def V(self) -> float: # type: ignore[empty-body]
|
||||
...
|
||||
@@ -504,19 +503,7 @@ class Quantity:
|
||||
...
|
||||
|
||||
# Dynamically-added properties/methods acting as pass-throughs to Solution
|
||||
# class (assigned via the ``setattr`` loop following this class). That loop
|
||||
# only assigns an attribute if it is not already present in
|
||||
# ``Quantity.__dict__``, so it is NOT safe to declare these as literal
|
||||
# `@property`/`def` members here (doing so puts the name in ``__dict__`` and
|
||||
# silently disables the loop's installation of the real implementation --
|
||||
# this was tried and reverted; see git history). A *bare* (unassigned) class
|
||||
# variable annotation, however, only populates ``__annotations__`` and not
|
||||
# ``__dict__``, so it is invisible to the loop's guard while still telling
|
||||
# type checkers (and `stubtest`) the published type of each dynamic
|
||||
# attribute. That is the technique used below. Unlike `SolutionArray` (whose
|
||||
# equivalent loop unconditionally overwrites and so can use real
|
||||
# `@property`/`def` declarations instead), `Quantity` requires this
|
||||
# annotation-only form.
|
||||
# class (assigned via the ``setattr`` loop following this class)
|
||||
name: str
|
||||
source: str
|
||||
composite: tuple[_ThermoType | None, _KineticsType | None, _TransportModel | None]
|
||||
@@ -758,8 +745,7 @@ class Quantity:
|
||||
set_electron_energy_distribution_parameters: _Callable[..., None]
|
||||
|
||||
# Synonyms for total properties. These class-level re-assignments overwrite the
|
||||
# type-only `...`-body declarations above with the *bound* property objects
|
||||
# (verified equivalent at runtime; see the comment above those declarations).
|
||||
# type-only `...`-body declarations above with the *bound* property objects.
|
||||
Quantity.V = Quantity.volume # type: ignore[method-assign]
|
||||
Quantity.U = Quantity.int_energy # type: ignore[method-assign]
|
||||
Quantity.H = Quantity.enthalpy # type: ignore[method-assign]
|
||||
@@ -1008,10 +994,7 @@ class SolutionArray(SolutionArrayBase, _Generic[_P]):
|
||||
|
||||
# Dynamically-added properties/methods acting as pass-throughs to the
|
||||
# underlying phase (assigned via the ``setattr`` loops/`_make_functions()`
|
||||
# following this class). Unlike `Quantity`'s equivalent loop (which only
|
||||
# installs an attribute if not already present in `Quantity.__dict__`),
|
||||
# these loops unconditionally overwrite, so real class-level annotations
|
||||
# here are safe and do not shadow the runtime implementations.
|
||||
# following this class).
|
||||
TD: tuple[_Array, _Array]
|
||||
TDX: tuple[_Array, _Array, _Array]
|
||||
TDY: tuple[_Array, _Array, _Array]
|
||||
@@ -1502,11 +1485,7 @@ class SolutionArray(SolutionArrayBase, _Generic[_P]):
|
||||
""" See `ThermoPhase.equilibrate` """
|
||||
for loc in range(self.size):
|
||||
self._set_loc(loc)
|
||||
# `XY` is published as optional for parity with `Quantity.equilibrate`,
|
||||
# but unlike that method there is no substitution of a default here;
|
||||
# passing `None` fails at runtime in `ThermoPhase.equilibrate`, matching
|
||||
# pre-merge (and `.pyi`-published) behavior.
|
||||
self._phase.equilibrate(XY, solver, rtol, max_steps, max_iter, # type: ignore[arg-type]
|
||||
self._phase.equilibrate(XY, solver, rtol, max_steps, max_iter,
|
||||
estimate_equil, log_level)
|
||||
self._update_state(loc)
|
||||
|
||||
@@ -1534,9 +1513,6 @@ class SolutionArray(SolutionArrayBase, _Generic[_P]):
|
||||
"""
|
||||
|
||||
# check arguments
|
||||
# `data`'s static type is already `dict[str, Array]`, but this runtime
|
||||
# check still matters because annotations are not enforced at the
|
||||
# boundary for callers passing in arbitrary objects.
|
||||
if not isinstance(data, dict) or len(data) == 0: # type: ignore[redundant-expr]
|
||||
raise ValueError("'SolutionArray.restore_data' requires a "
|
||||
"non-empty data dictionary")
|
||||
@@ -1567,10 +1543,6 @@ class SolutionArray(SolutionArrayBase, _Generic[_P]):
|
||||
)
|
||||
|
||||
# get full state information (may differ depending on ThermoPhase type).
|
||||
# `states` is treated as a plain `list[str]` from here on, since the rest
|
||||
# of this function manipulates its entries with generic string operations
|
||||
# (slicing, `rstrip`, membership tests) that lose the narrow `Literal`
|
||||
# typing published by `_full_states`/`_partial_states`.
|
||||
states: list[str] = list(self._phase._full_states.values())
|
||||
|
||||
# add partial and/or potentially non-unique state definitions
|
||||
|
||||
@@ -8,10 +8,8 @@ import sys as _sys
|
||||
import numpy as np
|
||||
import warnings
|
||||
|
||||
# External typing names are imported under "private" (underscore-prefixed) aliases so
|
||||
# that they are not re-exported into the top-level ``cantera`` namespace via ``from
|
||||
# .func1 import *`` (checked by test_namespace_cleanliness), matching the convention used
|
||||
# in the other Cython submodules.
|
||||
# External typing names are imported under "private" aliases so that they are not
|
||||
# re-exported into the top-level ``cantera`` namespace via ``from .func1 import *``
|
||||
from collections.abc import Callable as _Callable, Iterable as _Iterable
|
||||
from typing import Any as _Any, Literal as _Literal
|
||||
from typing_extensions import Never as _Never
|
||||
|
||||
@@ -4,10 +4,8 @@
|
||||
# distutils: language = c++
|
||||
# cython: language_level=3
|
||||
|
||||
# External names are imported under "private" (underscore-prefixed) aliases so that they
|
||||
# are not re-exported into the top-level ``cantera`` namespace via ``from .jacobians
|
||||
# import *`` (checked by test_namespace_cleanliness), matching the convention used in the
|
||||
# other Cython submodules.
|
||||
# External names are imported under "private" aliases so that they are not re-exported
|
||||
# into the top-level ``cantera`` namespace via ``from .jacobians import *``
|
||||
from typing import Any as _Any, ClassVar as _ClassVar, Literal as _Literal
|
||||
|
||||
import cython
|
||||
@@ -166,9 +164,6 @@ class AdaptivePreconditioner(EigenSparseJacobian):
|
||||
|
||||
@ilut_fill_factor.setter
|
||||
def ilut_fill_factor(self, val: int) -> None:
|
||||
# NOTE: in pure-Python Cython, argument annotations are real C types, so this
|
||||
# must match the C++ signature ``setIlutFillFactor(int)`` (the old .pyi loosely
|
||||
# typed it ``float``, which is fine as a stub but a compile error as source).
|
||||
cython.cast(
|
||||
cython.pointer(CxxAdaptivePreconditioner), self.jac
|
||||
).setIlutFillFactor(val)
|
||||
|
||||
@@ -147,4 +147,4 @@ cdef class InterfaceKinetics(Kinetics):
|
||||
|
||||
cdef np.ndarray get_species_array(Kinetics kin, kineticsMethod1d method)
|
||||
cdef np.ndarray get_reaction_array(Kinetics kin, kineticsMethod1d method)
|
||||
cdef get_from_sparse(CxxSparseMatrix, int, int) # by-value for pure-Python compat (no T& in annotations)
|
||||
cdef get_from_sparse(CxxSparseMatrix, int, int)
|
||||
|
||||
@@ -13,10 +13,6 @@ import cython
|
||||
from cython.cimports.cantera._utils import stringify, pystr
|
||||
from cython.cimports.cantera.solutionbase import _SolutionBase
|
||||
|
||||
# ThermoPhase is imported as an ordinary Python import (under an underscore alias to keep
|
||||
# it out of ``from .mixture import *``) so that its use in the public annotations is
|
||||
# resolvable by mypy/pyright; the runtime class object also serves the isinstance check
|
||||
# in phase_index (mixture needs no C-level access to ThermoPhase).
|
||||
from .thermo import ThermoPhase as _ThermoPhase
|
||||
from ._types import (
|
||||
Array as _Array,
|
||||
@@ -92,7 +88,7 @@ class Mixture:
|
||||
) -> None:
|
||||
# The C++ object is constructed in __cinit__; this typed __init__ exists so that
|
||||
# mypy/pyright (which do not recognize Cython's __cinit__) publish the constructor
|
||||
# signature. Construction is documented in the class docstring above.
|
||||
# signature.
|
||||
pass
|
||||
|
||||
def report(self, threshold: float = 1e-14) -> str:
|
||||
|
||||
@@ -512,7 +512,7 @@ class FlameBase(Sim1D):
|
||||
# strict rejects every compact read-only spelling for these properties
|
||||
# (`Final[...]` needs an initializer, an empty-body `@property` trips
|
||||
# `[empty-body]`), so the read-write/read-only mismatch is allowlisted in
|
||||
# ``.mypyignore`` instead (mirrors `composite.SolutionArray`).
|
||||
# ``.mypyignore`` instead.
|
||||
density: _Array
|
||||
density_mass: _Array
|
||||
density_mole: _Array
|
||||
|
||||
@@ -416,7 +416,7 @@ class BlowersMaselRate(ArrheniusRateBase):
|
||||
input_data: _ReactionRateInput[_BlowersMaselParameters] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def _from_dict(self, input_data: _ReactionRateInput[_BlowersMaselParameters]) -> None:
|
||||
self._rate = make_shared[CxxBlowersMaselRate](py_to_anymap(input_data))
|
||||
@@ -502,7 +502,7 @@ class TwoTempPlasmaRate(ArrheniusRateBase):
|
||||
input_data: _ReactionRateInput[_TwoTempPlasmaParameters] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def __call__(self, temperature: cython.double, elec_temp: cython.double) -> float:
|
||||
"""
|
||||
@@ -568,7 +568,7 @@ class ElectronCollisionPlasmaRate(ReactionRate):
|
||||
input_data: _ReactionRateInput[_ElectronCollisionPlasmaParameters] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def _from_dict(
|
||||
self, input_data: _ReactionRateInput[_ElectronCollisionPlasmaParameters]
|
||||
@@ -665,7 +665,7 @@ class FalloffRate(ReactionRate):
|
||||
input_data: _ReactionRateInput[_FalloffRateInput] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def __call__(self, temperature: cython.double, concm: cython.double) -> float:
|
||||
"""
|
||||
@@ -882,7 +882,7 @@ class PlogRate(ReactionRate):
|
||||
input_data: _PlogRateInput | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def __call__(self, temperature: cython.double, pressure: cython.double) -> float:
|
||||
"""
|
||||
@@ -990,7 +990,7 @@ class ChebyshevRate(ReactionRate):
|
||||
input_data: _ChebyshevRateInput | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def __call__(self, temperature: cython.double, pressure: cython.double) -> float:
|
||||
"""
|
||||
@@ -1050,10 +1050,7 @@ class ChebyshevRate(ReactionRate):
|
||||
2D array of Chebyshev coefficients where rows and columns correspond to
|
||||
temperature and pressure dimensions over which the Chebyshev fit is computed.
|
||||
"""
|
||||
# Must split declaration and assignment: 'data()' returns CxxArray2D&
|
||||
# and assigning it to a typed local copies the value into a CxxArray2D
|
||||
cxxcoeffs: CxxArray2D
|
||||
cxxcoeffs = self.cxx_object().data()
|
||||
cxxcoeffs: CxxArray2D = self.cxx_object().data()
|
||||
c = np.fromiter(cxxcoeffs.data(), np.double)
|
||||
return c.reshape(cxxcoeffs.nRows(), cxxcoeffs.nColumns(), order="F")
|
||||
|
||||
@@ -1087,7 +1084,7 @@ class CustomRate(ReactionRate):
|
||||
f"Cannot convert input with type '{type(k)}' to rate expression.")
|
||||
|
||||
def __init__(self, k: _Func1Like | None = None, init: bool = True) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
@cython.cfunc
|
||||
def cxx_object(self) -> cython.pointer(CxxCustomFunc1Rate):
|
||||
@@ -1359,7 +1356,7 @@ class InterfaceArrheniusRate(InterfaceRateBase):
|
||||
input_data: _ReactionRateInput[_ArrheniusParameters] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def _from_dict(self, input_data: _ReactionRateInput[_ArrheniusParameters]) -> None:
|
||||
self._rate = make_shared[CxxInterfaceArrheniusRate](py_to_anymap(input_data))
|
||||
@@ -1402,7 +1399,7 @@ class InterfaceBlowersMaselRate(InterfaceRateBase):
|
||||
input_data: _ReactionRateInput[_BlowersMaselParameters] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def _from_dict(
|
||||
self, input_data: _ReactionRateInput[_BlowersMaselParameters]
|
||||
@@ -1577,7 +1574,7 @@ class StickingBlowersMaselRate(StickRateBase):
|
||||
input_data: _ReactionRateInput[_BlowersMaselParameters] | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
def _from_dict(
|
||||
self, input_data: _ReactionRateInput[_BlowersMaselParameters]
|
||||
@@ -1669,7 +1666,7 @@ class ThirdBody:
|
||||
default_efficiency: float | None = None,
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
@cython.cfunc
|
||||
@staticmethod
|
||||
@@ -1827,20 +1824,17 @@ class Reaction:
|
||||
)
|
||||
else:
|
||||
self._reaction = make_shared[CxxReaction](
|
||||
comp_map(reactants), comp_map(products),
|
||||
_rate._rate
|
||||
comp_map(reactants), comp_map(products), _rate._rate
|
||||
)
|
||||
elif equation:
|
||||
# create from reaction equation
|
||||
if third_body:
|
||||
self._reaction = make_shared[CxxReaction](
|
||||
stringify(equation),
|
||||
_rate._rate, _third_body._third_body
|
||||
stringify(equation), _rate._rate, _third_body._third_body
|
||||
)
|
||||
else:
|
||||
self._reaction = make_shared[CxxReaction](
|
||||
stringify(equation),
|
||||
_rate._rate
|
||||
stringify(equation), _rate._rate
|
||||
)
|
||||
else:
|
||||
# create default object
|
||||
@@ -1863,7 +1857,7 @@ class Reaction:
|
||||
init: bool = True,
|
||||
third_body: ThirdBody | _Str | None = None,
|
||||
) -> None:
|
||||
"""Published constructor signature."""
|
||||
pass # Placeholder for constructor type annotations
|
||||
|
||||
@cython.cfunc
|
||||
@staticmethod
|
||||
|
||||
@@ -32,9 +32,6 @@ class ReactionPathDiagram:
|
||||
according to the net reaction rates determined by the `Kinetics` object
|
||||
``phase``.
|
||||
"""
|
||||
# The C++ diagram is constructed in __cinit__; this typed __init__ exists so
|
||||
# that mypy/pyright (which do not recognize Cython's __cinit__) publish the
|
||||
# constructor signature.
|
||||
|
||||
@property
|
||||
def show_details(self) -> bool:
|
||||
|
||||
@@ -39,10 +39,7 @@ if TYPE_CHECKING:
|
||||
|
||||
from .drawnetwork import *
|
||||
|
||||
# `anymap_to_py` may return an `AnyMap` (a `dict` subclass) rather than a plain
|
||||
# `dict`; an inline `dict[str, int]` return annotation is coerced by Cython 3 and
|
||||
# rejects that subclass instance at runtime. Route through a TypeAlias (not coerced),
|
||||
# matching the `_onedim._RestoreMetadata` precedent.
|
||||
# Non-coercing alias for AnyMap used by ReactorNet.solver_stats
|
||||
_SolverStats: _TypeAlias = dict[str, int]
|
||||
|
||||
|
||||
@@ -152,7 +149,7 @@ class ReactorBase:
|
||||
y = np.zeros(self.n_vars)
|
||||
cy: cython.double[::1] = y
|
||||
self.rbase.getState(span[double](cython.address(cy[0]),
|
||||
cython.cast(cython.size_t, y.size)))
|
||||
cython.cast(cython.size_t, y.size)))
|
||||
return y
|
||||
|
||||
def get_state_dae(self) -> tuple[_Array, _Array]:
|
||||
@@ -699,8 +696,6 @@ class ExtensibleReactor(Reactor):
|
||||
self.accessor = dynamic_cast[CxxReactorAccessorPtr](self.rbase)
|
||||
sdot: span[cython.double] = \
|
||||
dynamic_cast[CxxReactorAccessorPtr](self.rbase).surfaceProductionRates()
|
||||
# Non-owning memoryview over the C++ span data (pure-Python spelling of the
|
||||
# .pyx `<double[:sdot.size()]> sdot.data()` sized pointer cast).
|
||||
sarr: view.array = view.array(shape=(sdot.size(),),
|
||||
itemsize=cython.sizeof(cython.double), format="d",
|
||||
allocate_buffer=False)
|
||||
@@ -1095,8 +1090,6 @@ class ExtensibleReactorSurface(ReactorSurface):
|
||||
assign_delegates(self, dynamic_cast[CxxDelegatorPtr](self.rbase))
|
||||
sdot: span[cython.double] = \
|
||||
dynamic_cast[CxxReactorAccessorPtr](self.rbase).surfaceProductionRates()
|
||||
# Non-owning memoryview over the C++ span data (pure-Python spelling of the
|
||||
# .pyx `<double[:sdot.size()]> sdot.data()` sized pointer cast).
|
||||
sarr: view.array = view.array(shape=(sdot.size(),),
|
||||
itemsize=cython.sizeof(cython.double), format="d",
|
||||
allocate_buffer=False)
|
||||
@@ -2253,7 +2246,7 @@ class ReactorNet:
|
||||
y = np.zeros(self.n_vars)
|
||||
cy: cython.double[::1] = y
|
||||
self.net.getState(span[double](cython.address(cy[0]),
|
||||
cython.cast(cython.size_t, y.size)))
|
||||
cython.cast(cython.size_t, y.size)))
|
||||
return y
|
||||
|
||||
def get_state_dae(self) -> tuple[_Array, _Array]:
|
||||
|
||||
@@ -41,11 +41,8 @@ from ._types import (Array as _Array, ArrayLike as _ArrayLike, Basis as _Basis,
|
||||
|
||||
_CxxSurfPhasePtr = cython.typedef(cython.pointer(CxxSurfPhase))
|
||||
|
||||
# A ``str`` alias used for component/``extra`` names: these are published as ``str``
|
||||
# but flow in as ``numpy.str_`` (a ``str`` subclass) from array operations. A bare
|
||||
# ``str`` annotation would make Cython's annotation_typing reject the subclass (Cython
|
||||
# is deliberately stricter than PEP 484); routing through an alias keeps the published
|
||||
# type ``str`` while accepting subclasses, matching the pre-merge runtime behavior.
|
||||
# Alias to prevent Cython from rejecting numpy.str_ for functions that take str
|
||||
# arguments.
|
||||
_Str: _TypeAlias = str
|
||||
|
||||
_SortingType: _TypeAlias = _Literal["alphabetical", "molar-mass"] | None
|
||||
@@ -637,9 +634,7 @@ class SolutionArrayBase:
|
||||
meta: "dict[str, _Any]" = {},
|
||||
init: bool = True,
|
||||
) -> None:
|
||||
"""
|
||||
Construct a `SolutionArrayBase`. The C++ object is created in ``__cinit__``.
|
||||
"""
|
||||
pass
|
||||
|
||||
def _share(self, dest: SolutionArrayBase, selected):
|
||||
""" Share entries with new `SolutionArrayBase` object. """
|
||||
|
||||
@@ -72,10 +72,6 @@ class SpeciesThermo:
|
||||
def __init__(self, T_low: float | None = None, T_high: float | None = None,
|
||||
P_ref: float | None = None, coeffs: _ArrayLike | None = None,
|
||||
*args: _Any, init: bool = True, **kwargs: _Any) -> None:
|
||||
# The C++ object is constructed in __cinit__; this typed __init__ exists so
|
||||
# that mypy/pyright (which do not recognize Cython's __cinit__) publish the
|
||||
# constructor signature. Constructor parameters are documented in the class
|
||||
# docstring above.
|
||||
pass
|
||||
|
||||
@cython.cfunc
|
||||
@@ -119,8 +115,7 @@ class SpeciesThermo:
|
||||
cdata: cython.double[::1] = data
|
||||
view: span[cython.double] = span[cython.double](
|
||||
cython.address(cdata[0]), cython.cast(cython.size_t, self.n_coeffs))
|
||||
self.spthermo.reportParameters(index, thermo_type, T_low,
|
||||
T_high, P_ref, view)
|
||||
self.spthermo.reportParameters(index, thermo_type, T_low, T_high, P_ref, view)
|
||||
return data
|
||||
|
||||
def _check_n_coeffs(self, n: int) -> bool:
|
||||
|
||||
@@ -43,9 +43,8 @@ if TYPE_CHECKING:
|
||||
from .composite import Solution as _Solution
|
||||
from .reaction import Reaction as _Reaction
|
||||
|
||||
# TypeAlias to str is NOT coerced by Cython's annotation_typing (unlike a bare `str`
|
||||
# annotation, which rejects subclasses such as numpy.str_); use this for params that
|
||||
# are forwarded to `stringify()` (which itself accepts any str-like object).
|
||||
# Alias to prevent Cython from rejecting numpy.str_ or other types derived from str
|
||||
# for functions that should allow any string-like type
|
||||
_Str: _TypeAlias = str
|
||||
|
||||
# Avoid fixed options unless we can find a way to support custom extensions:
|
||||
@@ -90,9 +89,7 @@ _PhaseOfMatter: _TypeAlias = str
|
||||
|
||||
_QuadratureMethod: _TypeAlias = _Literal["simpson", "trapezoidal"]
|
||||
|
||||
# Parametrized generics (tuple[...]) are coerced by Cython's annotation_typing just
|
||||
# like bare builtins, rejecting a list where a tuple was published; route through a
|
||||
# TypeAlias (not coerced) to keep the runtime accepting any sequence, as before.
|
||||
# Type alias relaxes Cython's strict checking and allows any type of sequence
|
||||
_TPQSetter: _TypeAlias = tuple[float | None, float | None, float | None]
|
||||
|
||||
_SpeciesInput = _TypedDict(
|
||||
@@ -109,7 +106,6 @@ _SpeciesInput = _TypedDict(
|
||||
total=False,
|
||||
)
|
||||
|
||||
# Module-level C int constants replacing the private `cdef enum ThermoBasisType`
|
||||
mass_basis = cython.declare(cython.int, 0)
|
||||
molar_basis = cython.declare(cython.int, 1)
|
||||
|
||||
|
||||
@@ -50,9 +50,6 @@ class Units:
|
||||
self.units = CxxUnits(stringify(name), True)
|
||||
|
||||
def __init__(self, name: str | None = None) -> None:
|
||||
# The C++ object is constructed in __cinit__; this typed __init__ exists so
|
||||
# that mypy/pyright (which do not recognize Cython's __cinit__) publish the
|
||||
# constructor signature.
|
||||
pass
|
||||
|
||||
def __repr__(self) -> str:
|
||||
@@ -107,12 +104,7 @@ class UnitStack:
|
||||
@cython.cfunc
|
||||
@staticmethod
|
||||
def copy(other: CxxUnitStack) -> UnitStack:
|
||||
"""Copy a C++ UnitStack object to a Python object.
|
||||
|
||||
Note: the ``&`` (C++ reference) was dropped for pure-Python Cython compatibility
|
||||
(pure-Python syntax has no spelling for reference parameters). Rvalue callers
|
||||
get copy elision; ``copy()`` already copies into a new ``CxxUnitStack``.
|
||||
"""
|
||||
"""Copy a C++ UnitStack object to a Python object."""
|
||||
stack: UnitStack = UnitStack()
|
||||
stack.stack = CxxUnitStack(other)
|
||||
return stack
|
||||
@@ -165,9 +157,6 @@ class UnitSystem:
|
||||
self.units = units
|
||||
|
||||
def __init__(self, units: _UnitDict | None = None) -> None:
|
||||
# The C++ object is constructed in __cinit__; this typed __init__ exists so
|
||||
# that mypy/pyright (which do not recognize Cython's __cinit__) publish the
|
||||
# constructor signature.
|
||||
pass
|
||||
|
||||
def __repr__(self) -> str:
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
# distutils: language = c++
|
||||
# cython: language_level=3
|
||||
|
||||
# Sibling cdef classes used in the public annotations are imported as ordinary
|
||||
# Python imports (resolvable by mypy/pyright); the companion yamlwriter.pxd cimports
|
||||
# the same names so Cython still sees them as C-level extension types. Names that do
|
||||
# not already start with an underscore are aliased to an underscore-prefixed name so
|
||||
# they are not re-exported by ``from .yamlwriter import *`` (test_namespace_cleanliness).
|
||||
# typing_extensions is a hard runtime dependency, so ``Never`` is imported directly.
|
||||
from typing_extensions import Never as _Never
|
||||
|
||||
import cython
|
||||
|
||||
@@ -21,10 +21,10 @@ foreach(CY_SOURCE IN LISTS CY_SOURCES)
|
||||
VERBATIM)
|
||||
endforeach()
|
||||
|
||||
# The aggregator module _cantera uses pure-Python (.py) Cython syntax (enhancement #241)
|
||||
# but is always compiled INTO the merged _cantera extension (it hosts the metapath finder
|
||||
# and the PyInit functions for the .pyx modules merged here), so cythonize it alongside the
|
||||
# .pyx sources rather than as a standalone pure-Python module.
|
||||
# The aggregator module _cantera uses pure-Python (.py) Cython syntax but is always
|
||||
# compiled INTO the merged _cantera extension (it hosts the metapath finder and the
|
||||
# PyInit functions for the .pyx modules merged here), so cythonize it alongside the .pyx
|
||||
# sources rather than as a standalone pure-Python module.
|
||||
set(CANTERA_AGG_CPP "${CMAKE_CURRENT_BINARY_DIR}/_cantera.cpp")
|
||||
add_custom_command(
|
||||
OUTPUT ${CANTERA_AGG_CPP}
|
||||
@@ -34,8 +34,7 @@ add_custom_command(
|
||||
VERBATIM)
|
||||
list(APPEND CY_OUTPUTS ${CANTERA_AGG_CPP})
|
||||
|
||||
# Cython pure-Python-syntax modules use the .py extension rather than .pyx
|
||||
# (enhancement #241). Cythonize each to a .cpp here; how it is compiled depends on the
|
||||
# Cythonize each Cython pure-Python-syntax modules. How they are compiled depends on the
|
||||
# platform (see below).
|
||||
set(PURE_CY_MODULES _utils jacobians constants units func1 reactionpath
|
||||
yamlwriter speciesthermo mixture transport solutionbase
|
||||
@@ -54,12 +53,12 @@ foreach(MODULE IN LISTS PURE_CY_MODULES)
|
||||
endforeach()
|
||||
|
||||
if(CANTERA_PYODIDE)
|
||||
# On Pyodide the standalone-extension + shared-libcantera layout isn't usable (see
|
||||
# src/CMakeLists.txt), so compile the pure-Python modules INTO the merged _cantera
|
||||
# extension, just like the .pyx modules. cantera.<module> is then provided by
|
||||
# PyInit_<module> within _cantera and resolved by the CythonPackageMetaPathFinder in
|
||||
# _cantera.pyx; the raw .py is excluded from the Pyodide wheel (see pyproject.toml.in)
|
||||
# so it doesn't shadow the merged module on import.
|
||||
# On Pyodide the standalone-extension + shared-libcantera layout isn't usable,
|
||||
# so compile the pure-Python modules INTO the merged _cantera extension.
|
||||
# cantera.<module> is then provided by PyInit_<module> within _cantera and
|
||||
# resolved by the CythonPackageMetaPathFinder in _cantera.py; the raw .py is excluded
|
||||
# from the Pyodide wheel (see pyproject.toml.in) so it doesn't shadow the merged
|
||||
# module on import.
|
||||
list(APPEND CY_OUTPUTS ${PURE_CY_OUTPUTS})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -82,11 +82,6 @@ HDF5_ROOT = { env = "HDF5_ROOT" }
|
||||
exclude = ["pyproject.toml.in", "cantera/with_units/solution.py.in"]
|
||||
|
||||
[tool.scikit-build.wheel]
|
||||
# jacobians.py and the other pure-Python-syntax modules listed in PURE_CY_MODULES
|
||||
# (cantera/CMakeLists.txt) are each built as their own standalone extension linked
|
||||
# against the shared libcantera. The .py source ships alongside the compiled module so
|
||||
# IDEs, type checkers, and tracebacks can read it; CPython prefers the extension over
|
||||
# the source on import.
|
||||
exclude = ["include", "lib", "share", "**.pyx", "cantera/CMakeLists.txt"]
|
||||
|
||||
[[tool.scikit-build.overrides]]
|
||||
|
||||
@@ -143,16 +143,15 @@ endif()
|
||||
|
||||
configure_file("../include/cantera/base/config.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/../include/cantera/base/config.h")
|
||||
|
||||
# On native platforms (Linux/macOS/Windows) libcantera is SHARED, so the Cython
|
||||
# pure-Python-syntax modules (enhancement #241) can be standalone extensions that link it
|
||||
# and ship their .py source beside the compiled .so. On Pyodide this split layout is not
|
||||
# viable: each extension and libcantera would be an emscripten "side module", and
|
||||
# emscripten cannot resolve C++ vague-linkage *data* symbols (RTTI typeinfo / vtables,
|
||||
# which exception handling depends on) across the side-module boundary -- loading
|
||||
# _cantera fails with e.g. "bad export type for 'typeinfo for Cantera::CanteraError'".
|
||||
# So on Pyodide we fall back to a STATIC libcantera merged into a single _cantera
|
||||
# extension (see cantera/CMakeLists.txt; full writeup in the developer notes). Revisit if
|
||||
# emscripten's dynamic linking of data symbols improves.
|
||||
# On native platforms (Linux/macOS/Windows) libcantera is a SHARED library, so the
|
||||
# Cython pure-Python-syntax modules can be standalone extensions that link it and ship
|
||||
# their .py source beside the compiled .so. On Pyodide this split layout is not viable:
|
||||
# each extension and libcantera would be an emscripten "side module", and emscripten
|
||||
# cannot resolve C++ vague-linkage *data* symbols (RTTI typeinfo / vtables, which
|
||||
# exception handling depends on) across the side-module boundary. So on Pyodide we fall
|
||||
# back to a STATIC libcantera merged into a single _cantera extension (see
|
||||
# cantera/CMakeLists.txt). Revisit if emscripten's dynamic linking of data symbols
|
||||
# improves.
|
||||
if(CANTERA_PYODIDE)
|
||||
add_library(cantera_lib STATIC ${CT_LIB_SOURCES})
|
||||
else()
|
||||
@@ -163,8 +162,7 @@ target_include_directories(cantera_lib SYSTEM PRIVATE "${Python_INCLUDE_DIRS}" "
|
||||
set_target_properties(cantera_lib PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
# Cantera's headers don't annotate the public API with dllexport/dllimport, so
|
||||
# have CMake generate a .def exporting all symbols from the shared library (the
|
||||
# SCons build achieves the same result with a filtered dumpbin-generated .def).
|
||||
# have CMake generate a .def exporting all symbols from the shared library
|
||||
WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
# pythonShim.cpp (embedded interpreter support) calls into the Python C API, so the
|
||||
# shared library must resolve those symbols at link time on Windows. Python::Module
|
||||
|
||||
Reference in New Issue
Block a user