Skip to content

Commit

Permalink
Merge pull request #59 from jorenham/stubtest/scipy.io
Browse files Browse the repository at this point in the history
completed `scipy.io`
  • Loading branch information
jorenham authored Oct 9, 2024
2 parents 8a35128 + 1b34bd7 commit 0a7f316
Show file tree
Hide file tree
Showing 34 changed files with 962 additions and 645 deletions.
38 changes: 25 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,37 @@ jobs:
- name: install
run: poetry install

- name: lint (ruff)
- name: lint
run: poe lint --output-format=github

- name: typetest
run: poe typetest

- name: verifytypes (basedpyright)
- name: verifytypes
run: poe verifytypes

- name: typecheck (partial)
run: |
targets=(
"__init__.pyi"
"constants"
"datasets"
"integrate"
"io"
"linalg"
"misc"
"special"
"stats/distributions.pyi"
"version.pyi"
)
for target in "${targets[@]}"; do
poe mypy $target
poe pyright $target
done
stubtest:
needs: lint-and-typecheck
timeout-minutes: 10
timeout-minutes: 5
runs-on: ubuntu-latest
strategy:
fail-fast: false
Expand All @@ -63,8 +82,7 @@ jobs:
"scipy.fftpack",
"scipy.integrate",
# "scipy.interpolate",
# "scipy.io",
"scipy.io.arff scipy.io.matlab",
"scipy.io",
"scipy.linalg",
"scipy.misc",
# "scipy.ndimage",
Expand All @@ -81,10 +99,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- run: |
pipx install poetry poethepoet
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
- run: pipx install poetry poethepoet

- uses: actions/setup-python@v5
with:
Expand All @@ -103,10 +118,7 @@ jobs:
steps:
- uses: actions/checkout@v4

- run: |
pipx install poetry poethepoet
poetry config virtualenvs.create true --local
poetry config virtualenvs.in-project true --local
- run: pipx install poetry poethepoet

- uses: actions/setup-python@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ The exact version requirements are specified in the [`pyproject.toml`](pyproject
| `scipy.fftpack` | 3: ready |
| `scipy.integrate` | **4: done** |
| `scipy.interpolate` | 2: partial |
| `scipy.io` | 2: partial |
| `scipy.io` | **4: done** |
| `scipy.io.arff` | 3: ready |
| `scipy.io.matlab` | 3: ready |
| `scipy.linalg` | **4: done** |
Expand Down
10 changes: 4 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ args = [{name = "path", positional = true, multiple = true, default = ""}]

[tool.poe.tasks.mypy]
cmd = "mypy --config-file=pyproject.toml scipy-stubs/$path"
args = [{name = "path", positional = true, multiple = true, default = ""}]
args = [{name = "path", positional = true, multiple = false, default = ""}]

[tool.poe.tasks.verifytypes]
cmd = "basedpyright --ignoreexternal --verifytypes scipy-stubs/$path"
args = [{name = "path", positional = true, multiple = true, default = ""}]
args = [{name = "path", positional = true, multiple = false, default = ""}]

[tool.poe.tasks.stubtest]
cmd = """
Expand All @@ -95,8 +95,6 @@ warn_unused_ignores = true

[tool.pyright]
include = ["scipy-stubs", "typetests"]
exclude = [".cache"]
ignore = [".venv"]
venv = ".venv"
venvPath = "."
stubPath = "."
Expand All @@ -106,16 +104,16 @@ typeCheckingMode = "strict"

deprecateTypingAliases = true
enableTypeIgnoreComments = false
reportDeprecated = false
reportIgnoreCommentWithoutRule = true
reportImplicitRelativeImport = true
reportInvalidCast = true
reportPrivateUsage = false
reportUnnecessaryTypeIgnoreComment = true
reportUnsafeMultipleInheritance = true

[tool.ruff]
builtins = ["reveal_locals", "reveal_type"]
exclude = ["scipy-pyright", ".venv"]
exclude = [".venv"]
force-exclude = true
target-version = "py310"
# https://typing.readthedocs.io/en/latest/guides/writing_stubs.html#maximum-line-length
Expand Down
16 changes: 15 additions & 1 deletion scipy-stubs/_typing.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Helper types for internal use (type-check only).
from os import PathLike
from collections.abc import Callable, Sequence
from typing import Any, Literal, Protocol, TypeAlias, type_check_only
from typing import IO, Any, Literal, Protocol, TypeAlias, type_check_only
from typing_extensions import LiteralString, TypeVar

import numpy as np
Expand All @@ -17,8 +18,13 @@ __all__ = [
"AnyScalar",
"AnyShape",
"Array0D",
"ByteOrder",
"Casting",
"CorrelateMode",
"FileLike",
"FileModeRW",
"FileModeRWA",
"FileName",
"NanPolicy",
"Seed",
"Untyped",
Expand All @@ -38,6 +44,13 @@ UntypedDict: TypeAlias = dict[Untyped, Untyped]
UntypedCallable: TypeAlias = Callable[..., Untyped]
UntypedArray: TypeAlias = onpt.Array[tuple[int, ...], np.generic]

# I/O
_ByteSOrStr = TypeVar("_ByteSOrStr", bytes, str)
FileName: TypeAlias = str | PathLike[str]
FileLike: TypeAlias = IO[_ByteSOrStr] | FileName
FileModeRW: TypeAlias = Literal["r", "w"]
FileModeRWA: TypeAlias = Literal[FileModeRW, "a"]

_SCT = TypeVar("_SCT", bound=np.generic, default=np.generic)
Array0D: TypeAlias = np.ndarray[tuple[()], np.dtype[_SCT]]

Expand All @@ -55,6 +68,7 @@ AnyShape: TypeAlias = op.CanIndex | Sequence[op.CanIndex]
# numpy literals
RNG: TypeAlias = np.random.Generator | np.random.RandomState
Seed: TypeAlias = int | RNG
ByteOrder: TypeAlias = Literal["S", "<", "little", ">", "big", "=", "native", "|", "I"]
Casting: TypeAlias = Literal["no", "equiv", "safe", "same_kind", "unsafe"]
CorrelateMode: TypeAlias = Literal["valid", "same", "full"]

Expand Down
42 changes: 31 additions & 11 deletions scipy-stubs/io/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
from . import arff as arff, harwell_boeing as harwell_boeing, idl as idl, mmio as mmio, netcdf as netcdf, wavfile as wavfile
from ._fast_matrix_market import mminfo as mminfo, mmread as mmread, mmwrite as mmwrite
from ._fortran import (
FortranEOFError as FortranEOFError,
FortranFile as FortranFile,
FortranFormattingError as FortranFormattingError,
)
from ._harwell_boeing import hb_read as hb_read, hb_write as hb_write
from ._idl import readsav as readsav
from ._netcdf import netcdf_file as netcdf_file, netcdf_variable as netcdf_variable
from .matlab import loadmat as loadmat, savemat as savemat, whosmat as whosmat
from . import arff, harwell_boeing, idl, matlab, mmio, netcdf, wavfile
from ._fast_matrix_market import mminfo, mmread, mmwrite
from ._fortran import FortranEOFError, FortranFile, FortranFormattingError
from ._harwell_boeing import hb_read, hb_write
from ._idl import readsav
from ._netcdf import netcdf_file, netcdf_variable
from .matlab import loadmat, savemat, whosmat

__all__ = [
"FortranEOFError",
"FortranFile",
"FortranFormattingError",
"arff",
"harwell_boeing",
"hb_read",
"hb_write",
"idl",
"loadmat",
"matlab",
"mminfo",
"mmio",
"mmread",
"mmwrite",
"netcdf",
"netcdf_file",
"netcdf_variable",
"readsav",
"savemat",
"wavfile",
"whosmat",
]
60 changes: 43 additions & 17 deletions scipy-stubs/io/_fast_matrix_market/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,27 +1,53 @@
import io
from typing_extensions import override
from typing import Final, Literal, TypeAlias, type_check_only
from typing_extensions import TypedDict, Unpack, override

from scipy._typing import Untyped
import numpy as np
import numpy.typing as npt
import optype.numpy as onpt
from scipy._typing import FileName
from scipy.sparse import coo_matrix, sparray, spmatrix

__all__ = ["mminfo", "mmread", "mmwrite"]

PARALLELISM: int
ALWAYS_FIND_SYMMETRY: bool
_Format: TypeAlias = Literal["coordinate", "array"]
_Field: TypeAlias = Literal["real", "complex", "pattern", "integer"]
_Symmetry: TypeAlias = Literal["general", "symmetric", "skew-symmetric", "hermitian"]

PARALLELISM: Final = 0
ALWAYS_FIND_SYMMETRY: Final = False

@type_check_only
class _TextToBytesWrapperKwargs(TypedDict, total=False):
buffer_size: int

class _TextToBytesWrapper(io.BufferedReader):
encoding: Untyped
errors: Untyped
def __init__(self, text_io_buffer, encoding: Untyped | None = None, errors: Untyped | None = None, **kwargs): ...
encoding: Final[str]
errors: Final[str]
def __init__(
self,
/,
text_io_buffer: io.TextIOBase,
encoding: str | None = None,
errors: str | None = None,
**kwargs: Unpack[_TextToBytesWrapperKwargs],
) -> None: ...
@override
def read(self, /, size: int | None = -1) -> bytes: ...
@override
def read1(self, /, size: int = -1) -> bytes: ...
@override
def peek(self, /, size: int = -1) -> bytes: ...
@override
def seek(self, offset: int, whence: int = 0, /) -> None: ... # type: ignore[override]
def seek(self, /, offset: int, whence: int = 0) -> None: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]

def mmread(source) -> Untyped: ...
def mmread(source: FileName) -> npt.NDArray[np.generic] | coo_matrix: ...
def mmwrite(
target,
a,
comment: Untyped | None = None,
field: Untyped | None = None,
precision: Untyped | None = None,
symmetry: str = "AUTO",
): ...
def mminfo(source) -> Untyped: ...
target: FileName,
a: onpt.CanArray | list[object] | tuple[object, ...] | sparray | spmatrix,
comment: str | None = None,
field: _Field | None = None,
precision: int | None = None,
symmetry: _Symmetry | Literal["AUTO"] = "AUTO",
) -> None: ...
def mminfo(source: FileName) -> tuple[int, int, int, _Format, _Field, _Symmetry]: ...
43 changes: 34 additions & 9 deletions scipy-stubs/io/_fortran.pyi
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
from types import TracebackType
from typing import Any, TypedDict, final, overload, type_check_only
from typing_extensions import Self, Unpack

from scipy._typing import Untyped
import numpy as np
import numpy.typing as npt
import optype.numpy as onpt
from scipy._typing import FileLike, FileModeRW

__all__ = ["FortranEOFError", "FortranFile", "FortranFormattingError"]

@type_check_only
@final
class _DTypeKwargs(TypedDict):
dtype: npt.DTypeLike

class FortranEOFError(TypeError, OSError): ...
class FortranFormattingError(TypeError, OSError): ...

class FortranFile:
def __init__(self, filename, mode: str = "r", header_dtype=...): ...
def write_record(self, *items): ...
def read_record(self, *dtypes, **kwargs) -> Untyped: ...
def read_ints(self, dtype: str = "i4") -> Untyped: ...
def read_reals(self, dtype: str = "f8") -> Untyped: ...
def close(self): ...
def __enter__(self) -> Untyped: ...
def __exit__(self, type: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None): ...
def __init__(self, /, filename: FileLike[bytes], mode: FileModeRW = "r", header_dtype: npt.DTypeLike = ...) -> None: ...
def __enter__(self, /) -> Self: ...
def __exit__(self, /, type: type[BaseException] | None, value: BaseException | None, tb: TracebackType | None) -> None: ...
def close(self, /) -> None: ...
def write_record(self, /, *items: npt.ArrayLike) -> None: ...
@overload
def read_record(self, /, *dtypes: npt.DTypeLike) -> onpt.Array[tuple[int], np.void]: ...
@overload
def read_record(self, /, *dtypes: npt.DTypeLike, **kwargs: Unpack[_DTypeKwargs]) -> onpt.Array[tuple[int], np.void]: ...
@overload
def read_ints(self, /) -> onpt.Array[tuple[int], np.int32]: ...
@overload
def read_ints(self, /, dtype: onpt.AnyIntegerDType) -> onpt.Array[tuple[int], np.integer[Any]]: ...
@overload
def read_ints(self, /, dtype: npt.DTypeLike) -> onpt.Array[tuple[int]]: ...
@overload
def read_reals(self, /) -> onpt.Array[tuple[int], np.float64]: ...
@overload
def read_reals(self, /, dtype: onpt.AnyFloatingDType) -> onpt.Array[tuple[int], np.floating[Any]]: ...
@overload
def read_reals(self, /, dtype: npt.DTypeLike) -> onpt.Array[tuple[int]]: ...
Loading

0 comments on commit 0a7f316

Please sign in to comment.