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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
cython
Commits
105cf92d
Commit
105cf92d
authored
Jan 30, 2020
by
Stefan Behnel
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '0.29.x'
parents
016762d1
888bc4a4
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
62 additions
and
51 deletions
+62
-51
CHANGES.rst
CHANGES.rst
+3
-0
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+29
-40
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+11
-11
tests/run/pyclass_dynamic_bases.pyx
tests/run/pyclass_dynamic_bases.pyx
+19
-0
No files found.
CHANGES.rst
View file @
105cf92d
...
@@ -178,6 +178,9 @@ Other changes
...
@@ -178,6 +178,9 @@ Other changes
*
Double
reference
free
in
``
__class__
``
cell
handling
for
``
super
()``
calls
.
*
Double
reference
free
in
``
__class__
``
cell
handling
for
``
super
()``
calls
.
(
Github
issue
#
3246
)
(
Github
issue
#
3246
)
*
Compile
error
when
using
``*
args
``
as
Python
class
bases
.
(
Github
issue
#
3338
)
*
Import
failure
in
IPython
7.11
.
*
Import
failure
in
IPython
7.11
.
(
Github
issue
#
3297
)
(
Github
issue
#
3297
)
...
...
Cython/Compiler/ExprNodes.py
View file @
105cf92d
...
@@ -8914,12 +8914,11 @@ class ClassNode(ExprNode, ModuleNameMixin):
...
@@ -8914,12 +8914,11 @@ class ClassNode(ExprNode, ModuleNameMixin):
# a name, tuple of bases and class dictionary.
# a name, tuple of bases and class dictionary.
#
#
# name EncodedString Name of the class
# name EncodedString Name of the class
# bases ExprNode Base class tuple
# class_def_node PyClassDefNode PyClassDefNode defining this class
# dict ExprNode Class dict (not owned by this node)
# doc ExprNode or None Doc string
# doc ExprNode or None Doc string
# module_name EncodedString Name of defining module
# module_name EncodedString Name of defining module
subexprs
=
[
'
bases'
,
'
doc'
]
subexprs
=
[
'doc'
]
type
=
py_object_type
type
=
py_object_type
is_temp
=
True
is_temp
=
True
...
@@ -8928,7 +8927,6 @@ class ClassNode(ExprNode, ModuleNameMixin):
...
@@ -8928,7 +8927,6 @@ class ClassNode(ExprNode, ModuleNameMixin):
return
py_object_type
return
py_object_type
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
):
self
.
bases
=
self
.
bases
.
analyse_types
(
env
)
if
self
.
doc
:
if
self
.
doc
:
self
.
doc
=
self
.
doc
.
analyse_types
(
env
)
self
.
doc
=
self
.
doc
.
analyse_types
(
env
)
self
.
doc
=
self
.
doc
.
coerce_to_pyobject
(
env
)
self
.
doc
=
self
.
doc
.
coerce_to_pyobject
(
env
)
...
@@ -8941,12 +8939,13 @@ class ClassNode(ExprNode, ModuleNameMixin):
...
@@ -8941,12 +8939,13 @@ class ClassNode(ExprNode, ModuleNameMixin):
gil_message
=
"Constructing Python class"
gil_message
=
"Constructing Python class"
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
class_def_node
=
self
.
class_def_node
cname
=
code
.
intern_identifier
(
self
.
name
)
cname
=
code
.
intern_identifier
(
self
.
name
)
if
self
.
doc
:
if
self
.
doc
:
code
.
put_error_if_neg
(
self
.
pos
,
code
.
put_error_if_neg
(
self
.
pos
,
'PyDict_SetItem(%s, %s, %s)'
%
(
'PyDict_SetItem(%s, %s, %s)'
%
(
self
.
dict
.
py_result
(),
class_def_node
.
dict
.
py_result
(),
code
.
intern_identifier
(
code
.
intern_identifier
(
StringEncoding
.
EncodedString
(
"__doc__"
)),
StringEncoding
.
EncodedString
(
"__doc__"
)),
self
.
doc
.
py_result
()))
self
.
doc
.
py_result
()))
...
@@ -8955,8 +8954,8 @@ class ClassNode(ExprNode, ModuleNameMixin):
...
@@ -8955,8 +8954,8 @@ class ClassNode(ExprNode, ModuleNameMixin):
code
.
putln
(
code
.
putln
(
'%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s'
%
(
'%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s'
%
(
self
.
result
(),
self
.
result
(),
self
.
bases
.
py_result
(),
class_def_node
.
bases
.
py_result
(),
self
.
dict
.
py_result
(),
class_def_node
.
dict
.
py_result
(),
cname
,
cname
,
qualname
,
qualname
,
py_mod_name
,
py_mod_name
,
...
@@ -8970,8 +8969,8 @@ class Py3ClassNode(ExprNode):
...
@@ -8970,8 +8969,8 @@ class Py3ClassNode(ExprNode):
# a name, tuple of bases and class dictionary.
# a name, tuple of bases and class dictionary.
#
#
# name EncodedString Name of the class
# name EncodedString Name of the class
# dict ExprNode Class dict (not owned by this node)
# module_name EncodedString Name of defining module
# module_name EncodedString Name of defining module
# class_def_node PyClassDefNode PyClassDefNode defining this class
# calculate_metaclass bool should call CalculateMetaclass()
# calculate_metaclass bool should call CalculateMetaclass()
# allow_py2_metaclass bool should look for Py2 metaclass
# allow_py2_metaclass bool should look for Py2 metaclass
...
@@ -8994,12 +8993,10 @@ class Py3ClassNode(ExprNode):
...
@@ -8994,12 +8993,10 @@ class Py3ClassNode(ExprNode):
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"Py3ClassCreate"
,
"ObjectHandling.c"
))
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"Py3ClassCreate"
,
"ObjectHandling.c"
))
cname
=
code
.
intern_identifier
(
self
.
name
)
cname
=
code
.
intern_identifier
(
self
.
name
)
if
self
.
mkw
:
class_def_node
=
self
.
class_def_node
mkw
=
self
.
mkw
.
py_result
()
mkw
=
class_def_node
.
mkw
.
py_result
()
if
class_def_node
.
mkw
else
'NULL'
else
:
if
class_def_node
.
metaclass
:
mkw
=
'NULL'
metaclass
=
class_def_node
.
metaclass
.
py_result
()
if
self
.
metaclass
:
metaclass
=
self
.
metaclass
.
py_result
()
else
:
else
:
metaclass
=
"((PyObject*)&__Pyx_DefaultClassType)"
metaclass
=
"((PyObject*)&__Pyx_DefaultClassType)"
code
.
putln
(
code
.
putln
(
...
@@ -9007,8 +9004,8 @@ class Py3ClassNode(ExprNode):
...
@@ -9007,8 +9004,8 @@ class Py3ClassNode(ExprNode):
self
.
result
(),
self
.
result
(),
metaclass
,
metaclass
,
cname
,
cname
,
self
.
bases
.
py_result
(),
class_def_node
.
bases
.
py_result
(),
self
.
dict
.
py_result
(),
class_def_node
.
dict
.
py_result
(),
mkw
,
mkw
,
self
.
calculate_metaclass
,
self
.
calculate_metaclass
,
self
.
allow_py2_metaclass
,
self
.
allow_py2_metaclass
,
...
@@ -9019,8 +9016,7 @@ class Py3ClassNode(ExprNode):
...
@@ -9019,8 +9016,7 @@ class Py3ClassNode(ExprNode):
class
PyClassMetaclassNode
(
ExprNode
):
class
PyClassMetaclassNode
(
ExprNode
):
# Helper class holds Python3 metaclass object
# Helper class holds Python3 metaclass object
#
#
# bases ExprNode Base class tuple (not owned by this node)
# class_def_node PyClassDefNode PyClassDefNode defining this class
# mkw ExprNode Class keyword arguments (not owned by this node)
subexprs
=
[]
subexprs
=
[]
...
@@ -9033,38 +9029,38 @@ class PyClassMetaclassNode(ExprNode):
...
@@ -9033,38 +9029,38 @@ class PyClassMetaclassNode(ExprNode):
return
True
return
True
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
if
self
.
mkw
:
bases
=
self
.
class_def_node
.
bases
mkw
=
self
.
class_def_node
.
mkw
if
mkw
:
code
.
globalstate
.
use_utility_code
(
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"Py3MetaclassGet"
,
"ObjectHandling.c"
))
UtilityCode
.
load_cached
(
"Py3MetaclassGet"
,
"ObjectHandling.c"
))
call
=
"__Pyx_Py3MetaclassGet(%s, %s)"
%
(
call
=
"__Pyx_Py3MetaclassGet(%s, %s)"
%
(
self
.
bases
.
result
(),
bases
.
result
(),
self
.
mkw
.
result
())
mkw
.
result
())
else
:
else
:
code
.
globalstate
.
use_utility_code
(
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CalculateMetaclass"
,
"ObjectHandling.c"
))
UtilityCode
.
load_cached
(
"CalculateMetaclass"
,
"ObjectHandling.c"
))
call
=
"__Pyx_CalculateMetaclass(NULL, %s)"
%
(
call
=
"__Pyx_CalculateMetaclass(NULL, %s)"
%
(
self
.
bases
.
result
())
bases
.
result
())
code
.
putln
(
code
.
putln
(
"%s = %s; %s"
%
(
"%s = %s; %s"
%
(
self
.
result
(),
call
,
self
.
result
(),
call
,
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
class
PyClassNamespaceNode
(
ExprNode
,
ModuleNameMixin
):
class
PyClassNamespaceNode
(
ExprNode
,
ModuleNameMixin
):
# Helper class holds Python3 namespace object
# Helper class holds Python3 namespace object
#
#
# All this are not owned by this node
# All this are not owned by this node
# metaclass ExprNode Metaclass object
# class_def_node PyClassDefNode PyClassDefNode defining this class
# bases ExprNode Base class tuple
# mkw ExprNode Class keyword arguments
# doc ExprNode or None Doc string (owned)
# doc ExprNode or None Doc string (owned)
subexprs
=
[
'doc'
]
subexprs
=
[
'doc'
]
def
analyse_types
(
self
,
env
):
def
analyse_types
(
self
,
env
):
if
self
.
doc
:
if
self
.
doc
:
self
.
doc
=
self
.
doc
.
analyse_types
(
env
)
self
.
doc
=
self
.
doc
.
analyse_types
(
env
).
coerce_to_pyobject
(
env
)
self
.
doc
=
self
.
doc
.
coerce_to_pyobject
(
env
)
self
.
type
=
py_object_type
self
.
type
=
py_object_type
self
.
is_temp
=
1
self
.
is_temp
=
1
return
self
return
self
...
@@ -9076,23 +9072,16 @@ class PyClassNamespaceNode(ExprNode, ModuleNameMixin):
...
@@ -9076,23 +9072,16 @@ class PyClassNamespaceNode(ExprNode, ModuleNameMixin):
cname
=
code
.
intern_identifier
(
self
.
name
)
cname
=
code
.
intern_identifier
(
self
.
name
)
py_mod_name
=
self
.
get_py_mod_name
(
code
)
py_mod_name
=
self
.
get_py_mod_name
(
code
)
qualname
=
self
.
get_py_qualified_name
(
code
)
qualname
=
self
.
get_py_qualified_name
(
code
)
if
self
.
doc
:
class_def_node
=
self
.
class_def_node
doc_code
=
self
.
doc
.
result
()
null
=
"(PyObject *) NULL"
else
:
doc_code
=
self
.
doc
.
result
()
if
self
.
doc
else
null
doc_code
=
'(PyObject *) NULL'
mkw
=
class_def_node
.
mkw
.
py_result
()
if
class_def_node
.
mkw
else
null
if
self
.
mkw
:
metaclass
=
class_def_node
.
metaclass
.
py_result
()
if
class_def_node
.
metaclass
else
null
mkw
=
self
.
mkw
.
py_result
()
else
:
mkw
=
'(PyObject *) NULL'
if
self
.
metaclass
:
metaclass
=
self
.
metaclass
.
py_result
()
else
:
metaclass
=
"(PyObject *) NULL"
code
.
putln
(
code
.
putln
(
"%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s"
%
(
"%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s"
%
(
self
.
result
(),
self
.
result
(),
metaclass
,
metaclass
,
self
.
bases
.
result
(),
class_def_node
.
bases
.
result
(),
cname
,
cname
,
qualname
,
qualname
,
mkw
,
mkw
,
...
...
Cython/Compiler/Nodes.py
View file @
105cf92d
...
@@ -4675,26 +4675,22 @@ class PyClassDefNode(ClassDefNode):
...
@@ -4675,26 +4675,22 @@ class PyClassDefNode(ClassDefNode):
pass
# no base classes => no inherited metaclass
pass
# no base classes => no inherited metaclass
else
:
else
:
self
.
metaclass
=
ExprNodes
.
PyClassMetaclassNode
(
self
.
metaclass
=
ExprNodes
.
PyClassMetaclassNode
(
pos
,
mkw
=
mkdict
,
bases
=
self
.
bases
)
pos
,
class_def_node
=
self
)
needs_metaclass_calculation
=
False
needs_metaclass_calculation
=
False
else
:
else
:
needs_metaclass_calculation
=
True
needs_metaclass_calculation
=
True
self
.
dict
=
ExprNodes
.
PyClassNamespaceNode
(
self
.
dict
=
ExprNodes
.
PyClassNamespaceNode
(
pos
,
name
=
name
,
doc
=
doc_node
,
pos
,
name
=
name
,
doc
=
doc_node
,
class_def_node
=
self
)
metaclass
=
self
.
metaclass
,
bases
=
self
.
bases
,
mkw
=
self
.
mkw
)
self
.
classobj
=
ExprNodes
.
Py3ClassNode
(
self
.
classobj
=
ExprNodes
.
Py3ClassNode
(
pos
,
name
=
name
,
pos
,
name
=
name
,
class_def_node
=
self
,
doc
=
doc_node
,
bases
=
self
.
bases
,
dict
=
self
.
dict
,
doc
=
doc_node
,
metaclass
=
self
.
metaclass
,
mkw
=
self
.
mkw
,
calculate_metaclass
=
needs_metaclass_calculation
,
calculate_metaclass
=
needs_metaclass_calculation
,
allow_py2_metaclass
=
allow_py2_metaclass
)
allow_py2_metaclass
=
allow_py2_metaclass
)
else
:
else
:
# no bases, no metaclass => old style class creation
# no bases, no metaclass => old style class creation
self
.
dict
=
ExprNodes
.
DictNode
(
pos
,
key_value_pairs
=
[])
self
.
dict
=
ExprNodes
.
DictNode
(
pos
,
key_value_pairs
=
[])
self
.
classobj
=
ExprNodes
.
ClassNode
(
self
.
classobj
=
ExprNodes
.
ClassNode
(
pos
,
name
=
name
,
pos
,
name
=
name
,
class_def_node
=
self
,
doc
=
doc_node
)
bases
=
bases
,
dict
=
self
.
dict
,
doc
=
doc_node
)
self
.
target
=
ExprNodes
.
NameNode
(
pos
,
name
=
name
)
self
.
target
=
ExprNodes
.
NameNode
(
pos
,
name
=
name
)
self
.
class_cell
=
ExprNodes
.
ClassCellInjectorNode
(
self
.
pos
)
self
.
class_cell
=
ExprNodes
.
ClassCellInjectorNode
(
self
.
pos
)
...
@@ -4712,7 +4708,7 @@ class PyClassDefNode(ClassDefNode):
...
@@ -4712,7 +4708,7 @@ class PyClassDefNode(ClassDefNode):
visibility
=
'private'
,
visibility
=
'private'
,
module_name
=
None
,
module_name
=
None
,
class_name
=
self
.
name
,
class_name
=
self
.
name
,
bases
=
self
.
classobj
.
bases
or
ExprNodes
.
TupleNode
(
self
.
pos
,
args
=
[]),
bases
=
self
.
bases
or
ExprNodes
.
TupleNode
(
self
.
pos
,
args
=
[]),
decorators
=
self
.
decorators
,
decorators
=
self
.
decorators
,
body
=
self
.
body
,
body
=
self
.
body
,
in_pxd
=
False
,
in_pxd
=
False
,
...
@@ -4736,6 +4732,10 @@ class PyClassDefNode(ClassDefNode):
...
@@ -4736,6 +4732,10 @@ class PyClassDefNode(ClassDefNode):
args
=
[
class_result
])
args
=
[
class_result
])
self
.
decorators
=
None
self
.
decorators
=
None
self
.
class_result
=
class_result
self
.
class_result
=
class_result
if
self
.
bases
:
self
.
bases
.
analyse_declarations
(
env
)
if
self
.
mkw
:
self
.
mkw
.
analyse_declarations
(
env
)
self
.
class_result
.
analyse_declarations
(
env
)
self
.
class_result
.
analyse_declarations
(
env
)
self
.
target
.
analyse_target_declaration
(
env
)
self
.
target
.
analyse_target_declaration
(
env
)
cenv
=
self
.
create_scope
(
env
)
cenv
=
self
.
create_scope
(
env
)
...
@@ -4748,10 +4748,10 @@ class PyClassDefNode(ClassDefNode):
...
@@ -4748,10 +4748,10 @@ class PyClassDefNode(ClassDefNode):
def
analyse_expressions
(
self
,
env
):
def
analyse_expressions
(
self
,
env
):
if
self
.
bases
:
if
self
.
bases
:
self
.
bases
=
self
.
bases
.
analyse_expressions
(
env
)
self
.
bases
=
self
.
bases
.
analyse_expressions
(
env
)
if
self
.
metaclass
:
self
.
metaclass
=
self
.
metaclass
.
analyse_expressions
(
env
)
if
self
.
mkw
:
if
self
.
mkw
:
self
.
mkw
=
self
.
mkw
.
analyse_expressions
(
env
)
self
.
mkw
=
self
.
mkw
.
analyse_expressions
(
env
)
if
self
.
metaclass
:
self
.
metaclass
=
self
.
metaclass
.
analyse_expressions
(
env
)
self
.
dict
=
self
.
dict
.
analyse_expressions
(
env
)
self
.
dict
=
self
.
dict
.
analyse_expressions
(
env
)
self
.
class_result
=
self
.
class_result
.
analyse_expressions
(
env
)
self
.
class_result
=
self
.
class_result
.
analyse_expressions
(
env
)
cenv
=
self
.
scope
cenv
=
self
.
scope
...
...
tests/run/pyclass_dynamic_bases.pyx
View file @
105cf92d
...
@@ -24,3 +24,22 @@ def cond_if_bases(x):
...
@@ -24,3 +24,22 @@ def cond_if_bases(x):
class
PyClass
(
A
if
x
else
B
):
class
PyClass
(
A
if
x
else
B
):
p
=
5
p
=
5
return
PyClass
return
PyClass
def
make_subclass
(
*
bases
):
"""
>>> cls = make_subclass(list)
>>> issubclass(cls, list) or cls.__mro__
True
>>> class Cls(object): pass
>>> cls = make_subclass(Cls, list)
>>> issubclass(cls, list) or cls.__mro__
True
>>> issubclass(cls, Cls) or cls.__mro__
True
"""
# GH-3338
class
MadeClass
(
*
bases
):
pass
return
MadeClass
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