Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
b32cc41f
Commit
b32cc41f
authored
Nov 09, 2016
by
Guido van Rossum
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #28556: More typing.py updates from upstream.
parent
47c1c874
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
119 additions
and
150 deletions
+119
-150
Lib/test/test_typing.py
Lib/test/test_typing.py
+47
-16
Lib/typing.py
Lib/typing.py
+72
-134
No files found.
Lib/test/test_typing.py
View file @
b32cc41f
...
...
@@ -378,6 +378,16 @@ class CallableTests(BaseTestCase):
with
self
.
assertRaises
(
TypeError
):
type
(
c
)()
def
test_callable_wrong_forms
(
self
):
with
self
.
assertRaises
(
TypeError
):
Callable
[[...],
int
]
with
self
.
assertRaises
(
TypeError
):
Callable
[(),
int
]
with
self
.
assertRaises
(
TypeError
):
Callable
[[()],
int
]
with
self
.
assertRaises
(
TypeError
):
Callable
[[
int
,
1
],
2
]
def
test_callable_instance_works
(
self
):
def
f
():
pass
...
...
@@ -1296,9 +1306,10 @@ PY36 = sys.version_info[:2] >= (3, 6)
PY36_TESTS
=
"""
from test import ann_module, ann_module2, ann_module3
from collections import ChainMap
class B:
class A:
y: float
class B(A):
x: ClassVar[Optional['B']] = None
y: int
class CSub(B):
...
...
@@ -1317,6 +1328,15 @@ if PY36:
gth
=
get_type_hints
class
GetTypeHintTests
(
BaseTestCase
):
def
test_get_type_hints_from_various_objects
(
self
):
# For invalid objects should fail with TypeError (not AttributeError etc).
with
self
.
assertRaises
(
TypeError
):
gth
(
123
)
with
self
.
assertRaises
(
TypeError
):
gth
(
'abc'
)
with
self
.
assertRaises
(
TypeError
):
gth
(
None
)
@
skipUnless
(
PY36
,
'Python 3.6 required'
)
def
test_get_type_hints_modules
(
self
):
self
.
assertEqual
(
gth
(
ann_module
),
{
1
:
2
,
'f'
:
Tuple
[
int
,
int
],
'x'
:
int
,
'y'
:
str
})
...
...
@@ -1326,18 +1346,15 @@ class GetTypeHintTests(BaseTestCase):
@
skipUnless
(
PY36
,
'Python 3.6 required'
)
def
test_get_type_hints_classes
(
self
):
self
.
assertEqual
(
gth
(
ann_module
.
C
,
ann_module
.
__dict__
),
ChainMap
({
'y'
:
Optional
[
ann_module
.
C
]},
{}))
self
.
assertEqual
(
repr
(
gth
(
ann_module
.
j_class
)),
'ChainMap({}, {})'
)
self
.
assertEqual
(
gth
(
ann_module
.
M
),
ChainMap
({
'123'
:
123
,
'o'
:
type
},
{},
{}))
{
'y'
:
Optional
[
ann_module
.
C
]})
self
.
assertIsInstance
(
gth
(
ann_module
.
j_class
),
dict
)
self
.
assertEqual
(
gth
(
ann_module
.
M
),
{
'123'
:
123
,
'o'
:
type
})
self
.
assertEqual
(
gth
(
ann_module
.
D
),
ChainMap
({
'j'
:
str
,
'k'
:
str
,
'y'
:
Optional
[
ann_module
.
C
]},
{}))
self
.
assertEqual
(
gth
(
ann_module
.
Y
),
ChainMap
({
'z'
:
int
},
{}))
{
'j'
:
str
,
'k'
:
str
,
'y'
:
Optional
[
ann_module
.
C
]})
self
.
assertEqual
(
gth
(
ann_module
.
Y
),
{
'z'
:
int
})
self
.
assertEqual
(
gth
(
ann_module
.
h_class
),
ChainMap
({},
{
'y'
:
Optional
[
ann_module
.
C
]},
{}))
self
.
assertEqual
(
gth
(
ann_module
.
S
),
ChainMap
({
'x'
:
str
,
'y'
:
str
},
{}))
{
'y'
:
Optional
[
ann_module
.
C
]})
self
.
assertEqual
(
gth
(
ann_module
.
S
),
{
'x'
:
str
,
'y'
:
str
})
self
.
assertEqual
(
gth
(
ann_module
.
foo
),
{
'x'
:
int
})
@
skipUnless
(
PY36
,
'Python 3.6 required'
)
...
...
@@ -1355,20 +1372,34 @@ class GetTypeHintTests(BaseTestCase):
class
Der
(
ABase
):
...
self
.
assertEqual
(
gth
(
ABase
.
meth
),
{
'x'
:
int
})
def
test_get_type_hints_for_builins
(
self
):
# Should not fail for built-in classes and functions.
self
.
assertEqual
(
gth
(
int
),
{})
self
.
assertEqual
(
gth
(
type
),
{})
self
.
assertEqual
(
gth
(
dir
),
{})
self
.
assertEqual
(
gth
(
len
),
{})
def
test_previous_behavior
(
self
):
def
testf
(
x
,
y
):
...
testf
.
__annotations__
[
'x'
]
=
'int'
self
.
assertEqual
(
gth
(
testf
),
{
'x'
:
int
})
def
test_get_type_hints_for_object_with_annotations
(
self
):
class
A
:
...
class
B
:
...
b
=
B
()
b
.
__annotations__
=
{
'x'
:
'A'
}
self
.
assertEqual
(
gth
(
b
,
locals
()),
{
'x'
:
A
})
@
skipUnless
(
PY36
,
'Python 3.6 required'
)
def
test_get_type_hints_ClassVar
(
self
):
self
.
assertEqual
(
gth
(
ann_module2
.
CV
,
ann_module2
.
__dict__
),
{
'var'
:
typing
.
ClassVar
[
ann_module2
.
CV
]})
self
.
assertEqual
(
gth
(
B
,
globals
()),
ChainMap
({
'y'
:
int
,
'x'
:
ClassVar
[
Optional
[
B
]]},
{})
)
{
'y'
:
int
,
'x'
:
ClassVar
[
Optional
[
B
]]}
)
self
.
assertEqual
(
gth
(
CSub
,
globals
()),
ChainMap
({
'z'
:
ClassVar
[
CSub
]},
{
'y'
:
int
,
'x'
:
ClassVar
[
Optional
[
B
]]},
{}))
self
.
assertEqual
(
gth
(
G
),
ChainMap
({
'lst'
:
ClassVar
[
List
[
T
]]},{},{}))
{
'z'
:
ClassVar
[
CSub
],
'y'
:
int
,
'x'
:
ClassVar
[
Optional
[
B
]]})
self
.
assertEqual
(
gth
(
G
),
{
'lst'
:
ClassVar
[
List
[
T
]]})
class
CollectionsAbcTests
(
BaseTestCase
):
...
...
Lib/typing.py
View file @
b32cc41f
...
...
@@ -10,8 +10,6 @@ try:
import
collections.abc
as
collections_abc
except
ImportError
:
import
collections
as
collections_abc
# Fallback for PY3.2.
if
sys
.
version_info
[:
2
]
>=
(
3
,
3
):
from
collections
import
ChainMap
# Please keep __all__ alphabetized within each category.
...
...
@@ -1194,14 +1192,12 @@ class CallableMeta(GenericMeta):
# super()._tree_repr() for nice formatting.
arg_list
=
[]
for
arg
in
tree
[
1
:]:
if
arg
==
():
arg_list
.
append
(
'[]'
)
elif
not
isinstance
(
arg
,
tuple
):
if
not
isinstance
(
arg
,
tuple
):
arg_list
.
append
(
_type_repr
(
arg
))
else
:
arg_list
.
append
(
arg
[
0
].
_tree_repr
(
arg
))
if
len
(
arg_list
)
==
2
:
return
repr
(
tree
[
0
])
+
'[
%s]'
%
', '
.
join
(
arg_list
)
if
arg_list
[
0
]
==
'...'
:
return
repr
(
tree
[
0
])
+
'[
..., %s]'
%
arg_list
[
1
]
return
(
repr
(
tree
[
0
])
+
'[[%s], %s]'
%
(
', '
.
join
(
arg_list
[:
-
1
]),
arg_list
[
-
1
]))
...
...
@@ -1216,26 +1212,22 @@ class CallableMeta(GenericMeta):
raise
TypeError
(
"Callable must be used as "
"Callable[[arg, ...], result]."
)
args
,
result
=
parameters
if
args
is
...:
parameters
=
(...,
result
)
elif
args
==
[]:
parameters
=
((),
result
)
if
args
is
Ellipsis
:
parameters
=
(
Ellipsis
,
result
)
else
:
if
not
isinstance
(
args
,
list
):
raise
TypeError
(
"Callable[args, result]: args must be a list."
" Got %.100r."
%
(
args
,))
parameters
=
tuple
(
args
)
+
(
result
,
)
parameters
=
(
tuple
(
args
),
result
)
return
self
.
__getitem_inner__
(
parameters
)
@
_tp_cache
def
__getitem_inner__
(
self
,
parameters
):
*
args
,
result
=
parameters
args
,
result
=
parameters
msg
=
"Callable[args, result]: result must be a type."
result
=
_type_check
(
result
,
msg
)
if
args
==
[...,]
:
if
args
is
Ellipsis
:
return
super
().
__getitem__
((
_TypingEllipsis
,
result
))
if
args
==
[(),]:
return
super
().
__getitem__
((
_TypingEmpty
,
result
))
msg
=
"Callable[[arg, ...], result]: each arg must be a type."
args
=
tuple
(
_type_check
(
arg
,
msg
)
for
arg
in
args
)
parameters
=
args
+
(
result
,)
...
...
@@ -1332,7 +1324,11 @@ def cast(typ, val):
def
_get_defaults
(
func
):
"""Internal helper to extract the default arguments, by name."""
code
=
func
.
__code__
try
:
code
=
func
.
__code__
except
AttributeError
:
# Some built-in functions don't have __code__, __defaults__, etc.
return
{}
pos_count
=
code
.
co_argcount
arg_names
=
code
.
co_varnames
arg_names
=
arg_names
[:
pos_count
]
...
...
@@ -1346,138 +1342,80 @@ def _get_defaults(func):
return
res
if
sys
.
version_info
[:
2
]
>=
(
3
,
3
):
def
get_type_hints
(
obj
,
globalns
=
None
,
localns
=
None
):
"""Return type hints for an object.
def
get_type_hints
(
obj
,
globalns
=
None
,
localns
=
None
):
"""Return type hints for an object.
This is often the same as obj.__annotations__, but it handles
forward references encoded as string literals, and if necessary
adds Optional[t] if a default value equal to None is set.
This is often the same as obj.__annotations__, but it handles
forward references encoded as string literals, and if necessary
adds Optional[t] if a default value equal to None is set.
The argument may be a module, class, method, or function. The annotations
are returned as a dictionary, or in the case of a class, a ChainMap of
dictionarie
s.
The argument may be a module, class, method, or function. The annotations
are returned as a dictionary. For classes, annotations include also
inherited member
s.
TypeError is raised if the argument is not of a type that can contain
annotations, and an empty dictionary is returned if no annotations are
present.
TypeError is raised if the argument is not of a type that can contain
annotations, and an empty dictionary is returned if no annotations are
present.
BEWARE -- the behavior of globalns and localns is counterintuitive
(unless you are familiar with how eval() and exec() work). The
search order is locals first, then globals.
BEWARE -- the behavior of globalns and localns is counterintuitive
(unless you are familiar with how eval() and exec() work). The
search order is locals first, then globals.
- If no dict arguments are passed, an attempt is made to use the
globals from obj, and these are also used as the locals. If the
object does not appear to have globals, an exception is raised.
- If no dict arguments are passed, an attempt is made to use the
globals from obj, and these are also used as the locals. If the
object does not appear to have globals, an exception is raised.
- If one dict argument is passed, it is used for both globals and
locals.
- If one dict argument is passed, it is used for both globals and
locals.
- If two dict arguments are passed, they specify globals and
locals, respectively.
"""
- If two dict arguments are passed, they specify globals and
locals, respectively.
"""
if
getattr
(
obj
,
'__no_type_check__'
,
None
):
return
{}
if
globalns
is
None
:
globalns
=
getattr
(
obj
,
'__globals__'
,
{})
if
localns
is
None
:
localns
=
globalns
elif
localns
is
None
:
if
getattr
(
obj
,
'__no_type_check__'
,
None
):
return
{}
if
globalns
is
None
:
globalns
=
getattr
(
obj
,
'__globals__'
,
{})
if
localns
is
None
:
localns
=
globalns
if
(
isinstance
(
obj
,
types
.
FunctionType
)
or
isinstance
(
obj
,
types
.
BuiltinFunctionType
)
or
isinstance
(
obj
,
types
.
MethodType
)):
defaults
=
_get_defaults
(
obj
)
hints
=
obj
.
__annotations__
for
name
,
value
in
hints
.
items
():
if
value
is
None
:
value
=
type
(
None
)
if
isinstance
(
value
,
str
):
value
=
_ForwardRef
(
value
)
value
=
_eval_type
(
value
,
globalns
,
localns
)
if
name
in
defaults
and
defaults
[
name
]
is
None
:
value
=
Optional
[
value
]
hints
[
name
]
=
value
return
hints
if
isinstance
(
obj
,
types
.
ModuleType
):
try
:
hints
=
obj
.
__annotations__
except
AttributeError
:
return
{}
for
name
,
value
in
hints
.
items
():
elif
localns
is
None
:
localns
=
globalns
# Classes require a special treatment.
if
isinstance
(
obj
,
type
):
hints
=
{}
for
base
in
reversed
(
obj
.
__mro__
):
ann
=
base
.
__dict__
.
get
(
'__annotations__'
,
{})
for
name
,
value
in
ann
.
items
():
if
value
is
None
:
value
=
type
(
None
)
if
isinstance
(
value
,
str
):
value
=
_ForwardRef
(
value
)
value
=
_eval_type
(
value
,
globalns
,
localns
)
hints
[
name
]
=
value
return
hints
if
isinstance
(
object
,
type
):
cmap
=
None
for
base
in
reversed
(
obj
.
__mro__
):
new_map
=
collections
.
ChainMap
if
cmap
is
None
else
cmap
.
new_child
try
:
hints
=
base
.
__dict__
[
'__annotations__'
]
except
KeyError
:
cmap
=
new_map
()
else
:
for
name
,
value
in
hints
.
items
():
if
value
is
None
:
value
=
type
(
None
)
if
isinstance
(
value
,
str
):
value
=
_ForwardRef
(
value
)
value
=
_eval_type
(
value
,
globalns
,
localns
)
hints
[
name
]
=
value
cmap
=
new_map
(
hints
)
return
cmap
raise
TypeError
(
'{!r} is not a module, class, method, '
'or function.'
.
format
(
obj
))
else
:
def
get_type_hints
(
obj
,
globalns
=
None
,
localns
=
None
):
"""Return type hints for a function or method object.
This is often the same as obj.__annotations__, but it handles
forward references encoded as string literals, and if necessary
adds Optional[t] if a default value equal to None is set.
BEWARE -- the behavior of globalns and localns is counterintuitive
(unless you are familiar with how eval() and exec() work). The
search order is locals first, then globals.
- If no dict arguments are passed, an attempt is made to use the
globals from obj, and these are also used as the locals. If the
object does not appear to have globals, an exception is raised.
- If one dict argument is passed, it is used for both globals and
locals.
- If two dict arguments are passed, they specify globals and
locals, respectively.
"""
if
getattr
(
obj
,
'__no_type_check__'
,
None
):
return
{}
if
globalns
is
None
:
globalns
=
getattr
(
obj
,
'__globals__'
,
{})
if
localns
is
None
:
localns
=
globalns
elif
localns
is
None
:
localns
=
globalns
defaults
=
_get_defaults
(
obj
)
hints
=
dict
(
obj
.
__annotations__
)
for
name
,
value
in
hints
.
items
():
if
isinstance
(
value
,
str
):
value
=
_ForwardRef
(
value
)
value
=
_eval_type
(
value
,
globalns
,
localns
)
if
name
in
defaults
and
defaults
[
name
]
is
None
:
value
=
Optional
[
value
]
hints
[
name
]
=
value
return
hints
hints
=
getattr
(
obj
,
'__annotations__'
,
None
)
if
hints
is
None
:
# Return empty annotations for something that _could_ have them.
if
(
isinstance
(
obj
,
types
.
FunctionType
)
or
isinstance
(
obj
,
types
.
BuiltinFunctionType
)
or
isinstance
(
obj
,
types
.
MethodType
)
or
isinstance
(
obj
,
types
.
ModuleType
)):
return
{}
else
:
raise
TypeError
(
'{!r} is not a module, class, method, '
'or function.'
.
format
(
obj
))
defaults
=
_get_defaults
(
obj
)
hints
=
dict
(
hints
)
for
name
,
value
in
hints
.
items
():
if
value
is
None
:
value
=
type
(
None
)
if
isinstance
(
value
,
str
):
value
=
_ForwardRef
(
value
)
value
=
_eval_type
(
value
,
globalns
,
localns
)
if
name
in
defaults
and
defaults
[
name
]
is
None
:
value
=
Optional
[
value
]
hints
[
name
]
=
value
return
hints
def
no_type_check
(
arg
):
...
...
@@ -2160,7 +2098,7 @@ class TextIO(IO[str]):
pass
@
abstractproperty
def
errors
(
self
)
->
str
:
def
errors
(
self
)
->
Optional
[
str
]
:
pass
@
abstractproperty
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment