Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
ef32680
Add ParamSpec literals
A5rocks Dec 24, 2021
816f3cd
Improve ParamSpec and Parameters checking
A5rocks Dec 25, 2021
d9b352f
Get basic Concatenate features working
A5rocks Dec 26, 2021
58e6dbe
Fix "cache" bug
A5rocks Dec 26, 2021
51ba4ea
Check Concatenate prefixes
A5rocks Dec 26, 2021
24432ee
Polish work
A5rocks Dec 26, 2021
c507152
Merge branch 'master' into paramspec-literals
A5rocks Dec 26, 2021
d202d1e
Tests for literals
A5rocks Dec 26, 2021
9ed9830
Tests for Concatenate
A5rocks Dec 26, 2021
3ffc343
Appease CI
A5rocks Dec 26, 2021
ae8ac73
Forgot to comment out the directives...
A5rocks Dec 26, 2021
9c849cc
Improve literal TODOs
A5rocks Dec 27, 2021
d9dcc76
Add more tests
A5rocks Dec 28, 2021
0e2b207
Allow TypeVars in Concatenate
A5rocks Dec 28, 2021
bd445e5
Fix a couple of dumb oversights
A5rocks Dec 28, 2021
604c304
Allow Callables along with Parameters
A5rocks Dec 28, 2021
f8004ec
Fix tests
A5rocks Dec 28, 2021
9e75481
Misc changes
A5rocks Dec 29, 2021
7b89f06
Solve with self types
A5rocks Jan 1, 2022
f24cf4f
Add fallback return to meeting paramspec literals
A5rocks Jan 1, 2022
472b20c
Type application of ParamSpec literals
A5rocks Jan 3, 2022
14ecfb9
Ellipsis paramspec literals
A5rocks Jan 3, 2022
5e0ae49
Merge branch 'master' into paramspec-literals
A5rocks Jan 3, 2022
45c8057
Appease flake8
A5rocks Jan 3, 2022
10966ea
Merge branch 'master' into paramspec-literals
hauntsaninja Jan 7, 2022
c46feec
Minor code cleanup
A5rocks Jan 9, 2022
6a9cd71
Error notes and better subtyping for paramspec literals
A5rocks Jan 9, 2022
afc1a57
Appease CI
A5rocks Jan 9, 2022
41e38b2
Merge remote-tracking branch 'upstream/master' into paramspec-literals
A5rocks Jan 19, 2022
86e23c2
Fix something I assumed incorrectly
A5rocks Jan 27, 2022
3f4cf5c
Merge branch 'master' into paramspec-literals
A5rocks Jan 27, 2022
61b00cd
Revert "Minor code cleanup"
A5rocks Jan 29, 2022
9c2cefd
Merge branch 'master' into paramspec-literals
A5rocks Mar 1, 2022
a44937b
Fixed raised bugs
A5rocks Mar 1, 2022
bbabbf1
Fix CI errors
A5rocks Mar 1, 2022
ddfd34a
Squash some more bugs
A5rocks Mar 5, 2022
2d54ac4
Concatenate flag
A5rocks Mar 5, 2022
bba91e5
Prepare for GitHub Actions
A5rocks Mar 5, 2022
e0a7663
Merge branch 'master' into paramspec-literals
A5rocks Mar 7, 2022
0363803
Bug report with nested decorators and Concatenate
A5rocks Mar 7, 2022
278b8c4
Switch over to using Parameters instead of CallableType
A5rocks Mar 7, 2022
c2b7628
Add variance to paramspecs
A5rocks Mar 7, 2022
0b1fdfb
Apply suggestions from code review
A5rocks Mar 10, 2022
0fff609
Update tests
A5rocks Mar 10, 2022
4475515
Some of the PR feedback
A5rocks Mar 25, 2022
0091762
Merge branch 'master' into paramspec-literals
A5rocks Mar 26, 2022
81994f1
Prepare for GitHub actions
A5rocks Mar 26, 2022
1ff96c1
Merge branch 'master' into paramspec-literals
A5rocks Apr 5, 2022
c79918e
Fix tests to latest output
A5rocks Apr 5, 2022
9b1fc75
Copy pyright's representation of Concatenate
A5rocks Apr 5, 2022
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
Prev Previous commit
Next Next commit
Ellipsis paramspec literals
  • Loading branch information
A5rocks committed Jan 3, 2022
commit 14ecfb9753514e4e3448bf8bb5345044b6015af1
6 changes: 3 additions & 3 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -929,9 +929,6 @@ def g(x: int) -> int: ...
if check_args_covariantly:
is_compat = flip_compat_check(is_compat)

if right.is_ellipsis_args:
return True

return are_parameters_compatible(left, right, is_compat=is_compat,
ignore_pos_arg_names=ignore_pos_arg_names,
check_args_covariantly=check_args_covariantly,
Expand All @@ -945,6 +942,9 @@ def are_parameters_compatible(left: Union[Parameters, CallableType],
ignore_pos_arg_names: bool = False,
check_args_covariantly: bool = False,
allow_partial_overlap: bool = False) -> bool:
if right.is_ellipsis_args:
return True

"""Helper function for is_callable_compatible, used for Parameter compatibility"""
Comment thread
A5rocks marked this conversation as resolved.
Outdated
left_star = left.var_arg()
left_star2 = left.kw_arg()
Expand Down
11 changes: 9 additions & 2 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -775,8 +775,15 @@ def visit_partial_type(self, t: PartialType) -> Type:
assert False, "Internal error: Unexpected partial type"

def visit_ellipsis_type(self, t: EllipsisType) -> Type:
self.fail('Unexpected "..."', t)
return AnyType(TypeOfAny.from_error)
if self.allow_param_spec_literals:
any_type = AnyType(TypeOfAny.explicit)
return Parameters([any_type, any_type],
[ARG_STAR, ARG_STAR2],
[None, None],
is_ellipsis_args=True)
else:
self.fail('Unexpected "..."', t)
return AnyType(TypeOfAny.from_error)

def visit_type_type(self, t: TypeType) -> Type:
return TypeType.make_normalized(self.anal_type(t.item), line=t.line)
Expand Down
23 changes: 18 additions & 5 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1092,28 +1092,36 @@ class Parameters(ProperType):
__slots__ = ('arg_types',
'arg_kinds',
'arg_names',
'min_args')
'min_args',
'is_ellipsis_args')

def __init__(self,
arg_types: Sequence[Type],
arg_kinds: List[ArgKind],
arg_names: Sequence[Optional[str]],
*,
is_ellipsis_args: bool = False
) -> None:
self.arg_types = list(arg_types)
self.arg_kinds = arg_kinds
self.arg_names = list(arg_names)
self.min_args = arg_kinds.count(ARG_POS)
assert len(arg_types) == len(arg_kinds) == len(arg_names)
self.min_args = arg_kinds.count(ARG_POS)
self.is_ellipsis_args = is_ellipsis_args

def copy_modified(self,
arg_types: Bogus[Sequence[Type]] = _dummy,
arg_kinds: Bogus[List[ArgKind]] = _dummy,
arg_names: Bogus[Sequence[Optional[str]]] = _dummy
arg_names: Bogus[Sequence[Optional[str]]] = _dummy,
*,
is_ellipsis_args: Bogus[bool] = _dummy
) -> 'Parameters':
return Parameters(
arg_types=arg_types if arg_types is not _dummy else self.arg_types,
arg_kinds=arg_kinds if arg_kinds is not _dummy else self.arg_kinds,
arg_names=arg_names if arg_names is not _dummy else self.arg_names,
is_ellipsis_args=is_ellipsis_args
if is_ellipsis_args is not _dummy else self.is_ellipsis_args
)

# the following are copied from CallableType. Is there a way to decrease code duplication?
Expand Down Expand Up @@ -1527,11 +1535,13 @@ def expand_param_spec(self,
if no_prefix:
return self.copy_modified(arg_types=c.arg_types,
arg_kinds=c.arg_kinds,
arg_names=c.arg_names)
arg_names=c.arg_names,
is_ellipsis_args=c.is_ellipsis_args)
else:
return self.copy_modified(arg_types=self.arg_types[:-2] + c.arg_types,
arg_kinds=self.arg_kinds[:-2] + c.arg_kinds,
arg_names=self.arg_names[:-2] + c.arg_names)
arg_names=self.arg_names[:-2] + c.arg_names,
is_ellipsis_args=c.is_ellipsis_args)

def __hash__(self) -> int:
return hash((self.ret_type, self.is_type_obj(),
Expand Down Expand Up @@ -2414,6 +2424,9 @@ def visit_param_spec(self, t: ParamSpecType) -> str:

def visit_parameters(self, t: Parameters) -> str:
# This is copied from visit_callable -- is there a way to decrease duplication?
if t.is_ellipsis_args:
return '...'

s = ''
bare_asterisk = False
for i in range(len(t.arg_types)):
Expand Down
32 changes: 32 additions & 0 deletions test-data/unit/check-parameter-specification.test
Original file line number Diff line number Diff line change
Expand Up @@ -673,3 +673,35 @@ Z[bytes, str](lambda one: None) # E: Cannot infer type of lambda \
Z[bytes, str](f2) # E: Argument 1 to "Z" has incompatible type "Callable[[bytes, int], None]"; expected "Callable[[bytes, str], None]"

[builtins fixtures/tuple.pyi]

[case testParamSpecLiteralEllipsis]
from typing_extensions import ParamSpec
from typing import Generic, Callable

P = ParamSpec("P")

class Z(Generic[P]):
def __init__(self: 'Z[P]', c: Callable[P, None]) -> None:
...

def f1() -> None: ...
def f2(*args: int) -> None: ...
def f3(a: int, *, b: bytes) -> None: ...

def f4(b: bytes) -> None: ...

argh: Callable[..., None] = f4

# check it works
Z[...](f1)
Z[...](f2)
Z[...](f3)

# check subtyping works
n: Z[...]
n = Z(f1)
n = Z(f2)
n = Z(f3)

[builtins fixtures/tuple.pyi]