Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
9bcc8775
Commit
9bcc8775
authored
Aug 10, 2020
by
Yuan
Committed by
GitHub
Aug 10, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support PEP-560 ("__class_getitem__") for extension classes (GH-3765)
parent
0208bf2b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
114 additions
and
3 deletions
+114
-3
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+5
-3
tests/errors/pep487_exttype.pyx
tests/errors/pep487_exttype.pyx
+13
-0
tests/run/test_genericclass_exttype.pyx
tests/run/test_genericclass_exttype.pyx
+96
-0
No files found.
Cython/Compiler/Nodes.py
View file @
9bcc8775
...
...
@@ -2965,10 +2965,12 @@ class DefNode(FuncDefNode):
# staticmethod() was overridden - not much we can do here ...
self
.
is_staticmethod
=
False
if
env
.
is_py_class_scope
:
if
self
.
name
==
'__new__'
:
if
env
.
is_py_class_scope
or
env
.
is_c_class_scope
:
if
self
.
name
==
'__new__'
and
env
.
is_py_class_scope
:
self
.
is_staticmethod
=
True
elif
not
self
.
is_classmethod
and
self
.
name
in
IMPLICIT_CLASSMETHODS
:
elif
self
.
name
==
'__init_subclass__'
and
env
.
is_c_class_scope
:
error
(
self
.
pos
,
"'__init_subclass__' is not supported by extension class"
)
elif
self
.
name
in
IMPLICIT_CLASSMETHODS
and
not
self
.
is_classmethod
:
self
.
is_classmethod
=
True
# TODO: remove the need to generate a real decorator here, is_classmethod=True should suffice.
from
.ExprNodes
import
NameNode
...
...
tests/errors/pep487_exttype.pyx
0 → 100644
View file @
9bcc8775
# mode: error
cdef
class
Imp
:
def
__init_subclass__
(
cls
,
a
=
None
,
**
kwargs
):
super
().
__init_subclass__
(
**
kwargs
)
print
(
a
)
cdef
class
ExImp1
(
Imp
):
pass
class
ExImp2
(
Imp
,
a
=
60
):
pass
_ERRORS
=
u"""
4:4: '__init_subclass__' is not supported by extension class
"""
tests/run/test_genericclass_exttype.pyx
0 → 100644
View file @
9bcc8775
# mode: run
# cython: language_level=3
import
unittest
import
sys
cdef
class
UnSupport
:
pass
cdef
class
Unpack
:
para_list
=
[]
def
__class_getitem__
(
*
args
,
**
kwargs
):
Unpack
.
para_list
.
extend
([
args
,
kwargs
])
cdef
class
Format
:
def
__class_getitem__
(
cls
,
item
):
return
f'
{
cls
.
__name__
}
[
{
item
.
__name__
}
]'
cdef
class
ExFormat
(
Format
):
pass
cdef
class
Override
:
def
__class_getitem__
(
cls
,
item
):
return
'Should not see this'
cdef
class
Covered
(
Override
):
def
__class_getitem__
(
cls
,
item
):
return
f'
{
cls
.
__name__
}
[
{
item
.
__name__
}
]'
cdef
class
Decorated
:
@
classmethod
def
__class_getitem__
(
cls
,
item
):
return
f'
{
cls
.
__name__
}
[
{
item
.
__name__
}
]'
cdef
class
ExDecorated
(
Decorated
):
pass
cdef
class
Invalid1
:
def
__class_getitem__
(
cls
):
pass
cdef
class
Invalid2
:
def
__class_getitem__
(
cls
,
item1
,
item2
):
pass
cdef
class
Invalid3
:
cdef
dict
__dict__
def
__init__
(
self
):
self
.
__class_getitem__
=
lambda
cls
,
items
:
'This will not work'
cdef
class
Invalid4
:
__class_getitem__
=
"Surprise!"
class
TestClassGetitem
(
unittest
.
TestCase
):
# BEGIN - Additional tests from cython
def
test_no_class_getitem
(
self
):
with
self
.
assertRaises
(
TypeError
):
UnSupport
[
int
]
# END - Additional tests from cython
def
test_class_getitem
(
self
):
Unpack
[
int
,
str
]
self
.
assertEqual
(
Unpack
.
para_list
[
0
],
(
Unpack
,
(
int
,
str
)))
self
.
assertEqual
(
Unpack
.
para_list
[
1
],
{})
def
test_class_getitem_format
(
self
):
self
.
assertEqual
(
Format
[
int
],
'Format[int]'
)
self
.
assertEqual
(
Format
[
Format
],
'Format[Format]'
)
def
test_class_getitem_inheritance
(
self
):
self
.
assertEqual
(
ExFormat
[
int
],
'ExFormat[int]'
)
self
.
assertEqual
(
ExFormat
[
ExFormat
],
'ExFormat[ExFormat]'
)
def
test_class_getitem_inheritance_2
(
self
):
self
.
assertEqual
(
Covered
[
int
],
'Covered[int]'
)
self
.
assertEqual
(
Covered
[
Covered
],
'Covered[Covered]'
)
def
test_class_getitem_classmethod
(
self
):
self
.
assertEqual
(
ExDecorated
[
int
],
'ExDecorated[int]'
)
self
.
assertEqual
(
ExDecorated
[
ExDecorated
],
'ExDecorated[ExDecorated]'
)
def
test_class_getitem_errors
(
self
):
with
self
.
assertRaises
(
TypeError
):
Invalid1
[
int
]
with
self
.
assertRaises
(
TypeError
):
Invalid2
[
int
]
def
test_class_getitem_errors_2
(
self
):
with
self
.
assertRaises
(
TypeError
):
Format
()[
int
]
with
self
.
assertRaises
(
TypeError
):
Invalid3
()[
int
]
with
self
.
assertRaises
(
TypeError
):
Invalid4
[
int
]
if
__name__
==
'__main__'
:
unittest
.
main
()
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