Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Run runtime type checks in CI #322

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13-dev"]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
Expand Down Expand Up @@ -103,3 +103,19 @@ jobs:
name: codecov-py${{ matrix.python-version }}
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true

test-runtime-typing:
name: Test runtime typing
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install requirements
run: pip install --upgrade '.[all,test]'
- name: Run tests with runtime typing enabled
run: make test-typeguard
20 changes: 14 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,45 @@ SHELL := /usr/bin/env bash
# - phantom._base
# - phantom.ext.phonenumbers
typeguard_packages := \
phantom._hypothesis \
phantom._utils.misc \
phantom._utils.types \
phantom._version \
phantom.boolean \
phantom.bounds \
phantom.datetime \
phantom.errors \
phantom.fn \
phantom.iso3166 \
phantom.negated \
phantom.re \
phantom.schema \
phantom.sized \
phantom.utils \
phantom.predicates._base \
phantom.predicates._utils \
phantom.predicates.boolean \
phantom.predicates.collection \
phantom.predicates.datetime \
phantom.prediactes.generic \
phantom.predicates.interval \
phantom.predicates.numeric \
phantom.predicates.re \
phantom.predicates.utils
phantom.predicates.re
typeguard_arg := \
--typeguard-packages=$(shell echo $(typeguard_packages) | sed 's/ /,/g')

tests_selection := 'external or not no_external'

.PHONY: test
test:
pytest $(test)
pytest $(test) -m $(tests_selection)

.PHONY: test-runtime
test-runtime:
pytest $(test) -k.py
pytest $(test) -k.py -m $(tests_selection)

.PHONY: test-typeguard
test-typeguard:
pytest $(typeguard_arg) $(test)
pytest $(typeguard_arg) $(test) -k.py -m $(tests_selection)

.PHONY: test-typing
test-typing:
Expand Down
14 changes: 9 additions & 5 deletions src/phantom/_hypothesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,25 @@
from typing import TYPE_CHECKING
from typing import Callable
from typing import TypeVar
from typing import Union

from typing_extensions import TypeAlias

if TYPE_CHECKING:
from hypothesis.strategies import SearchStrategy
else:
SearchStrategy = None

try:
from hypothesis.strategies import SearchStrategy
except ImportError:
SearchStrategy = None

__all__ = ("HypothesisStrategy", "register_type_strategy", "SearchStrategy")

T = TypeVar("T")
HypothesisStrategy: TypeAlias = (
"SearchStrategy | Callable[[type[T]], SearchStrategy[T] | None]"
)
HypothesisStrategy: TypeAlias = Union[
SearchStrategy,
Callable[[type[T]], Union[SearchStrategy[T], None]],
]
register_type_strategy: Callable[[type, HypothesisStrategy], None] | None


Expand Down
12 changes: 6 additions & 6 deletions src/phantom/_utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

@runtime_checkable
class _SupportsLt(Protocol[T_contra]):
def __lt__(self, other: T_contra) -> bool: ...
def __lt__(self, other: T_contra, /) -> bool: ...


class SupportsLt(
Expand All @@ -22,7 +22,7 @@ class SupportsLt(

@runtime_checkable
class _SupportsLe(Protocol[T_contra]):
def __le__(self, other: T_contra) -> bool: ...
def __le__(self, other: T_contra, /) -> bool: ...


class SupportsLe(
Expand All @@ -34,7 +34,7 @@ class SupportsLe(

@runtime_checkable
class _SupportsGt(Protocol[T_contra]):
def __gt__(self, other: T_contra) -> bool: ...
def __gt__(self, other: T_contra, /) -> bool: ...


class SupportsGt(
Expand All @@ -46,7 +46,7 @@ class SupportsGt(

@runtime_checkable
class _SupportsGe(Protocol[T_contra]):
def __ge__(self, other: T_contra) -> bool: ...
def __ge__(self, other: T_contra, /) -> bool: ...


class SupportsGe(
Expand All @@ -58,7 +58,7 @@ class SupportsGe(

@runtime_checkable
class _SupportsEq(Protocol):
def __eq__(self, other: object) -> bool: ...
def __eq__(self, other: object, /) -> bool: ...
def __hash__(self) -> int: ...


Expand Down Expand Up @@ -155,7 +155,7 @@ class SupportsLtGt(

@runtime_checkable
class _SupportsMod(Protocol[T_contra, U_co]):
def __mod__(self, other: T_contra) -> U_co: ...
def __mod__(self, other: T_contra, /) -> U_co: ...


class SupportsMod(
Expand Down
Loading