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
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ classifiers = [
"Intended Audience :: Developers",
]
name = "type-lens"
version = "0.2.3"
version = "0.2.4"
description = "type-lens is a Python template project designed to simplify the setup of a new project."
readme = "README.md"
license = { text = "MIT" }
Expand Down Expand Up @@ -127,6 +127,7 @@ warn_unused_configs = true
warn_unused_ignores = true

[tool.pyright]
typeCheckingMode = "strict"
disableBytesTypePromotions = true
exclude = [
"tools",
Expand Down
6 changes: 3 additions & 3 deletions tests/test_callable_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ def fn() -> int:

def test_untyped_param() -> None:
def fn(foo): # type: ignore[no-untyped-def]
return foo
return foo # pyright: ignore

function_view = CallableView.from_callable(fn)
function_view = CallableView.from_callable(fn) # pyright: ignore
assert function_view.parameters == (ParameterView("foo", TypeView(Any), has_annotation=False),)


Expand Down Expand Up @@ -127,7 +127,7 @@ def method(self, c: bool) -> bool:
def test_parameters_with_none_default(hint: Any) -> None:
def fn(plain: hint = None, annotated: Annotated[hint, ...] = None) -> None: ... # pyright: ignore

fn_view = CallableView.from_callable(fn, localns=locals(), include_extras=True)
fn_view = CallableView.from_callable(fn, localns=locals(), include_extras=True) # pyright: ignore
plain_param, annotated_param = fn_view.parameters
assert plain_param.type_view.annotation == annotated_param.type_view.annotation

Expand Down
6 changes: 3 additions & 3 deletions tests/test_type_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
T = TypeVar("T")


def _check_parsed_type(type_lens: TypeView, expected: dict[str, Any]) -> None:
def _check_parsed_type(type_lens: TypeView[Any], expected: dict[str, Any]) -> None:
__tracebackhide__ = True
for key, expected_value in expected.items():
lens_value = getattr(type_lens, key)
Expand Down Expand Up @@ -334,8 +334,8 @@ def test_tuple() -> None:
assert TypeView(Tuple[int, ...]).is_tuple is True
assert TypeView(Tuple[int, ...]).is_variadic_tuple is True

assert TypeView(...).is_tuple is False
assert TypeView(...).is_variadic_tuple is False
assert TypeView(...).is_tuple is False # pyright: ignore
assert TypeView(...).is_variadic_tuple is False # pyright: ignore


def test_strip_optional() -> None:
Expand Down
18 changes: 2 additions & 16 deletions type_lens/callable_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


class CallableView:
def __init__(self, fn: Callable, type_hints: dict[str, type]):
def __init__(self, fn: Callable[..., Any], type_hints: dict[str, type]):
self.callable = fn
self.signature = getattr(fn, "__signature__", None) or inspect.signature(fn)

Expand Down Expand Up @@ -45,7 +45,7 @@ def __repr__(self) -> str:
@classmethod
def from_callable(
cls: type[Self],
fn: Callable,
fn: Callable[..., Any],
*,
globalns: dict[str, Any] | None = None,
localns: dict[str, Any] | None = None,
Expand All @@ -61,17 +61,3 @@ def from_callable(

result = get_type_hints(hint_fn, globalns=globalns, localns=localns, include_extras=include_extras)
return cls(fn, result)


def _fix_annotated_optional_type_hints(
hints: dict[str, Any],
) -> dict[str, Any]: # pragma: no cover
"""Normalize `Annotated` interacting with `get_type_hints` in versions <3.11.

https://github.com/python/cpython/issues/90353.
"""
for param_name, hint in hints.items():
type_view = TypeView(hint)
if type_view.is_union and type_view.inner_types[0].is_annotated:
hints[param_name] = type_view.inner_types[0].raw
return hints
2 changes: 1 addition & 1 deletion type_lens/parameter_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ParameterView:
def __init__(
self,
name: str,
type_view: TypeView = _any_type_view,
type_view: TypeView[Any] = _any_type_view,
*,
default: Any | EmptyType = Empty,
has_annotation: bool = True,
Expand Down
30 changes: 20 additions & 10 deletions type_lens/type_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@

from collections import abc
from collections.abc import Collection, Mapping
from typing import Any, AnyStr, Final, ForwardRef, Generic, Literal, TypeVar, Union, _SpecialForm
from typing import (
Any,
AnyStr,
Final,
ForwardRef,
Generic,
Literal,
TypeVar,
Union,
_SpecialForm, # pyright: ignore[reportPrivateUsage]
)

from typing_extensions import Annotated, NotRequired, Required, get_args, get_origin
from typing_extensions import Literal as ExtensionsLiteral
Expand Down Expand Up @@ -44,12 +54,12 @@ def __init__(self, annotation: T) -> None:
unwrapped, metadata, wrappers = unwrap_annotation(annotation)
origin = get_origin(unwrapped)

args: tuple[Any, ...] = () if origin is abc.Callable else get_args(unwrapped)
args: tuple[Any, ...] = () if origin is abc.Callable else get_args(unwrapped) # pyright: ignore

self.raw: Final[T] = annotation
self.annotation: Final = unwrapped
self.origin: Final = origin
self.fallback_origin: Final = origin or unwrapped
self.origin: Final[Any] = origin
self.fallback_origin: Final[Any] = origin or unwrapped
self.args: Final[tuple[Any, ...]] = args
self.metadata: Final = metadata
self._wrappers: Final = wrappers
Expand Down Expand Up @@ -79,23 +89,23 @@ def repr_type(self) -> str:
"""
# Literal/Union both appear to have no name on some versions of python.
if self.is_literal:
name = "Literal"
name: str = "Literal"
elif self.is_union:
name = "Union"
elif isinstance(self.annotation, (type, _SpecialForm)) or self.origin:
try:
name = self.annotation.__name__ # pyright: ignore[reportAttributeAccessIssue]
name = str(self.annotation.__name__) # pyright: ignore
except AttributeError:
# Certain _SpecialForm items have no __name__ python 3.8.
name = self.annotation._name # pyright: ignore[reportAttributeAccessIssue]
name = str(self.annotation._name) # pyright: ignore
else:
name = repr(self.annotation)

if self.origin:
inner_types = ", ".join(t.repr_type for t in self.inner_types)
name = f"{name}[{inner_types}]"

return str(name)
return name

@property
def allows_none(self) -> bool:
Expand Down Expand Up @@ -192,7 +202,7 @@ def is_variadic_tuple(self) -> bool:
Tuples like `tuple[int, ...]` represent a list-like unbounded sequence
of a single type T.
"""
return self.is_tuple and len(self.args) == 2 and self.args[1] == ...
return self.is_tuple and len(self.args) == 2 and self.args[1] == ... # pyright: ignore

@property
def safe_generic_origin(self) -> Any:
Expand Down Expand Up @@ -249,7 +259,7 @@ def is_subclass_of(self, typ: Any | tuple[Any, ...], /) -> bool:
"""
return isinstance(self.fallback_origin, type) and issubclass(self.fallback_origin, typ)

def strip_optional(self) -> TypeView:
def strip_optional(self) -> TypeView[Any]:
if not self.is_optional:
return self

Expand Down
2 changes: 1 addition & 1 deletion type_lens/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def fix_annotated_optional_type_hints(
_get_type_hints = typing.get_type_hints # pyright: ignore

else:
from eval_type_backport import eval_type_backport
from eval_type_backport import eval_type_backport # pyright: ignore

@typing.no_type_check
def _get_type_hints( # noqa: C901
Expand Down
4 changes: 2 additions & 2 deletions type_lens/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def unwrap_annotation(annotation: t.Any) -> tuple[t.Any, tuple[t.Any, ...], set[
A tuple of the unwrapped annotation and any ``Annotated`` metadata, and a set of any wrapper types encountered.
"""
origin = te.get_origin(annotation)
wrappers = set()
metadata = []
wrappers: set[t.Any] = set()
metadata: list[t.Any] = []
while origin in _WRAPPER_TYPES:
wrappers.add(origin)
annotation, *meta = te.get_args(annotation)
Expand Down
Loading