Skip to content
Merged
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
7 changes: 3 additions & 4 deletions tests/test_cqa.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def test_cqa_ruff_check(project_root):

def test_cqa_ruff_format_check(project_root):
"""Test that code is properly formatted according to ruff."""
# Ruff format respects pyproject.toml exclusions (_vendor is excluded)
# Ruff format respects pyproject.toml exclusions
result = subprocess.run(
[sys.executable, "-m", "ruff", "format", "--check", "."],
capture_output=True,
Expand All @@ -43,12 +43,11 @@ def test_cqa_ruff_format_check(project_root):
)


@pytest.mark.skip(reason="Mypy is not working yet")
def test_cqa_mypy(project_root):
"""Test that code passes mypy type checking."""
# Mypy uses configuration from pyproject.toml
# Run on the whole project (pi package and tests), excluding _vendor
for subdir in ["pi", "tests/fixtures"]:
# Run on typemap -- tests not ready yet
for subdir in ["typemap"]:
result = subprocess.run(
[
sys.executable,
Expand Down
Empty file added typemap/__init__.py
Empty file.
4 changes: 2 additions & 2 deletions typemap/type_eval/_apply_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def _box(cls: type[Any], args: dict[str, Any]) -> Boxed:

return Boxed(cls, boxed_bases, args)

if isinstance(cls, (typing._GenericAlias, types.GenericAlias)):
if isinstance(cls, (typing._GenericAlias, types.GenericAlias)): # type: ignore[attr-defined]
# XXX this feels out of place, `box()` needs to only accept types.
args = dict(
zip(cls.__origin__.__parameters__, cls.__args__, strict=True)
Expand Down Expand Up @@ -184,7 +184,7 @@ def apply(cls: type[Any]) -> dict[str, Any]:
annos.update(af)

for name, stuff in boxed.cls.__dict__.items():
if name in typing.EXCLUDED_ATTRIBUTES:
if name in typing.EXCLUDED_ATTRIBUTES: # type: ignore[attr-defined]
continue

stuff = inspect.unwrap(stuff)
Expand Down
6 changes: 4 additions & 2 deletions typemap/type_eval/_eval_call.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ def eval_call(func: types.FunctionType, /, *args: Any, **kwargs: Any) -> Any:


def _eval_call(func: types.FunctionType, /, *args: Any, **kwargs: Any) -> Any:
vars = {}
vars: dict[str, Any] = {}

params = func.__type_params__
for p in params:
if p.__bound__ is next.CallSpec:
if hasattr(p, "__bound__") and p.__bound__ is next.CallSpec:
vars[p.__name__] = next._CallSpecWrapper(args, kwargs, func)
else:
vars[p.__name__] = p
Expand All @@ -29,6 +29,8 @@ def _eval_call(func: types.FunctionType, /, *args: Any, **kwargs: Any) -> Any:
af = func.__annotate__
except AttributeError:
raise ValueError("func has no __annotate__ attribute")
if not af:
raise ValueError("func has no __annotate__ attribute")

af_args = tuple(
types.CellType(vars[name]) for name in af.__code__.co_freevars
Expand Down
8 changes: 5 additions & 3 deletions typemap/type_eval/_eval_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def _eval_type_type(obj: type, ctx: EvalContext):
if isinstance(obj, type) and issubclass(obj, typing.Generic):
ret = type(
obj.__name__,
(typing.Protocol,),
(typing.cast(type, typing.Protocol),),
{
"__module__": obj.__module__,
"__name__": obj.__name__,
Expand Down Expand Up @@ -129,6 +129,7 @@ def _eval_type_var(obj: typing.TypeVar, ctx: EvalContext):

@_eval_types_impl.register
def _eval_type_alias(obj: typing.TypeAliasType, ctx: EvalContext):
assert obj.__module__ # FIXME: or can this really happen?
func = obj.evaluate_value
mod = sys.modules[obj.__module__]
ff = types.FunctionType(func.__code__, mod.__dict__, None, None, ())
Expand All @@ -142,7 +143,7 @@ def _eval_generic(obj: types.GenericAlias, ctx: EvalContext):
# This is a GenericAlias over a Python class, e.g. `dict[str, int]`
# Let's reconstruct it by evaluating all arguments
new_args = tuple(_eval_types(arg, ctx) for arg in obj.__args__)
return obj.__origin__[new_args]
return obj.__origin__[new_args] # type: ignore[index]

func = obj.evaluate_value

Expand All @@ -169,5 +170,6 @@ def _eval_generic(obj: types.GenericAlias, ctx: EvalContext):

@_eval_types_impl.register
def _eval_union(obj: typing.Union, ctx: EvalContext): # type: ignore
new_args = tuple(_eval_types(arg, ctx) for arg in obj.__args__)
args: typing.Sequence[typing.Any] = obj.__args__
new_args = tuple(_eval_types(arg, ctx) for arg in args)
return typing.Union[new_args]
9 changes: 5 additions & 4 deletions typemap/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ class CallSpec:
class _CallSpecWrapper:
_args: tuple[typing.Any]
_kwargs: dict[str, typing.Any]
_func: types.FunctionType | types.MethodType
# TODO: Support MethodType!
_func: types.FunctionType # | types.MethodType

@property
def args(self) -> None:
Expand All @@ -32,7 +33,7 @@ class _CallKwarg:
name: str


@typing._SpecialForm
@typing._SpecialForm # type: ignore[call-arg]
def CallSpecKwargs(self, spec: _CallSpecWrapper) -> list[_CallKwarg]:
ff = types.FunctionType(
spec._func.__code__,
Expand Down Expand Up @@ -85,7 +86,7 @@ class DirProperties(metaclass=DirPropertiesMeta):

class NewProtocolMeta(type):
def __getitem__(cls, val: list[Property]):
dct = {}
dct: dict[str, object] = {}
dct["__annotations__"] = {prop.name: prop.type for prop in val}

module_name = __name__
Expand All @@ -99,7 +100,7 @@ def __getitem__(cls, val: list[Property]):

dct["__module__"] = module_name

mcls = type(typing.Protocol)
mcls: type = type(typing.cast(type, typing.Protocol))
cls = mcls(name, (typing.Protocol,), dct)
return cls

Expand Down