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
*
Double
reference
free
in
``
__class__
``
cell
handling
for
``
super
()``
calls
.
(
Github
issue
#
3246
)
*
Compile
error
when
using
``*
args
``
as
Python
class
bases
.
(
Github
issue
#
3338
)
*
Import
failure
in
IPython
7.11
.
(
Github
issue
#
3297
)
...
...
Cython/Compiler/ExprNodes.py
View file @
105cf92d
...
...
@@ -8914,12 +8914,11 @@ class ClassNode(ExprNode, ModuleNameMixin):
# a name, tuple of bases and class dictionary.
#
# name EncodedString Name of the class
# bases ExprNode Base class tuple
# dict ExprNode Class dict (not owned by this node)
# class_def_node PyClassDefNode PyClassDefNode defining this class
# doc ExprNode or None Doc string
# module_name EncodedString Name of defining module
subexprs
=
[
'
bases'
,
'
doc'
]
subexprs
=
[
'doc'
]
type
=
py_object_type
is_temp
=
True
...
...
@@ -8928,7 +8927,6 @@ class ClassNode(ExprNode, ModuleNameMixin):
return
py_object_type
def
analyse_types
(
self
,
env
):
self
.
bases
=
self
.
bases
.
analyse_types
(
env
)
if
self
.
doc
:
self
.
doc
=
self
.
doc
.
analyse_types
(
env
)
self
.
doc
=
self
.
doc
.
coerce_to_pyobject
(
env
)
...
...
@@ -8941,12 +8939,13 @@ class ClassNode(ExprNode, ModuleNameMixin):
gil_message
=
"Constructing Python class"
def
generate_result_code
(
self
,
code
):
class_def_node
=
self
.
class_def_node
cname
=
code
.
intern_identifier
(
self
.
name
)
if
self
.
doc
:
code
.
put_error_if_neg
(
self
.
pos
,
'PyDict_SetItem(%s, %s, %s)'
%
(
self
.
dict
.
py_result
(),
class_def_node
.
dict
.
py_result
(),
code
.
intern_identifier
(
StringEncoding
.
EncodedString
(
"__doc__"
)),
self
.
doc
.
py_result
()))
...
...
@@ -8955,8 +8954,8 @@ class ClassNode(ExprNode, ModuleNameMixin):
code
.
putln
(
'%s = __Pyx_CreateClass(%s, %s, %s, %s, %s); %s'
%
(
self
.
result
(),
self
.
bases
.
py_result
(),
self
.
dict
.
py_result
(),
class_def_node
.
bases
.
py_result
(),
class_def_node
.
dict
.
py_result
(),
cname
,
qualname
,
py_mod_name
,
...
...
@@ -8970,8 +8969,8 @@ class Py3ClassNode(ExprNode):
# a name, tuple of bases and class dictionary.
#
# name EncodedString Name of the class
# dict ExprNode Class dict (not owned by this node)
# module_name EncodedString Name of defining module
# class_def_node PyClassDefNode PyClassDefNode defining this class
# calculate_metaclass bool should call CalculateMetaclass()
# allow_py2_metaclass bool should look for Py2 metaclass
...
...
@@ -8994,12 +8993,10 @@ class Py3ClassNode(ExprNode):
def
generate_result_code
(
self
,
code
):
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"Py3ClassCreate"
,
"ObjectHandling.c"
))
cname
=
code
.
intern_identifier
(
self
.
name
)
if
self
.
mkw
:
mkw
=
self
.
mkw
.
py_result
()
else
:
mkw
=
'NULL'
if
self
.
metaclass
:
metaclass
=
self
.
metaclass
.
py_result
()
class_def_node
=
self
.
class_def_node
mkw
=
class_def_node
.
mkw
.
py_result
()
if
class_def_node
.
mkw
else
'NULL'
if
class_def_node
.
metaclass
:
metaclass
=
class_def_node
.
metaclass
.
py_result
()
else
:
metaclass
=
"((PyObject*)&__Pyx_DefaultClassType)"
code
.
putln
(
...
...
@@ -9007,8 +9004,8 @@ class Py3ClassNode(ExprNode):
self
.
result
(),
metaclass
,
cname
,
self
.
bases
.
py_result
(),
self
.
dict
.
py_result
(),
class_def_node
.
bases
.
py_result
(),
class_def_node
.
dict
.
py_result
(),
mkw
,
self
.
calculate_metaclass
,
self
.
allow_py2_metaclass
,
...
...
@@ -9019,8 +9016,7 @@ class Py3ClassNode(ExprNode):
class
PyClassMetaclassNode
(
ExprNode
):
# Helper class holds Python3 metaclass object
#
# bases ExprNode Base class tuple (not owned by this node)
# mkw ExprNode Class keyword arguments (not owned by this node)
# class_def_node PyClassDefNode PyClassDefNode defining this class
subexprs
=
[]
...
...
@@ -9033,38 +9029,38 @@ class PyClassMetaclassNode(ExprNode):
return
True
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
(
UtilityCode
.
load_cached
(
"Py3MetaclassGet"
,
"ObjectHandling.c"
))
call
=
"__Pyx_Py3MetaclassGet(%s, %s)"
%
(
self
.
bases
.
result
(),
self
.
mkw
.
result
())
bases
.
result
(),
mkw
.
result
())
else
:
code
.
globalstate
.
use_utility_code
(
UtilityCode
.
load_cached
(
"CalculateMetaclass"
,
"ObjectHandling.c"
))
call
=
"__Pyx_CalculateMetaclass(NULL, %s)"
%
(
self
.
bases
.
result
())
bases
.
result
())
code
.
putln
(
"%s = %s; %s"
%
(
self
.
result
(),
call
,
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
class
PyClassNamespaceNode
(
ExprNode
,
ModuleNameMixin
):
# Helper class holds Python3 namespace object
#
# All this are not owned by this node
# metaclass ExprNode Metaclass object
# bases ExprNode Base class tuple
# mkw ExprNode Class keyword arguments
# class_def_node PyClassDefNode PyClassDefNode defining this class
# doc ExprNode or None Doc string (owned)
subexprs
=
[
'doc'
]
def
analyse_types
(
self
,
env
):
if
self
.
doc
:
self
.
doc
=
self
.
doc
.
analyse_types
(
env
)
self
.
doc
=
self
.
doc
.
coerce_to_pyobject
(
env
)
self
.
doc
=
self
.
doc
.
analyse_types
(
env
).
coerce_to_pyobject
(
env
)
self
.
type
=
py_object_type
self
.
is_temp
=
1
return
self
...
...
@@ -9076,23 +9072,16 @@ class PyClassNamespaceNode(ExprNode, ModuleNameMixin):
cname
=
code
.
intern_identifier
(
self
.
name
)
py_mod_name
=
self
.
get_py_mod_name
(
code
)
qualname
=
self
.
get_py_qualified_name
(
code
)
if
self
.
doc
:
doc_code
=
self
.
doc
.
result
()
else
:
doc_code
=
'(PyObject *) NULL'
if
self
.
mkw
:
mkw
=
self
.
mkw
.
py_result
()
else
:
mkw
=
'(PyObject *) NULL'
if
self
.
metaclass
:
metaclass
=
self
.
metaclass
.
py_result
()
else
:
metaclass
=
"(PyObject *) NULL"
class_def_node
=
self
.
class_def_node
null
=
"(PyObject *) NULL"
doc_code
=
self
.
doc
.
result
()
if
self
.
doc
else
null
mkw
=
class_def_node
.
mkw
.
py_result
()
if
class_def_node
.
mkw
else
null
metaclass
=
class_def_node
.
metaclass
.
py_result
()
if
class_def_node
.
metaclass
else
null
code
.
putln
(
"%s = __Pyx_Py3MetaclassPrepare(%s, %s, %s, %s, %s, %s, %s); %s"
%
(
self
.
result
(),
metaclass
,
self
.
bases
.
result
(),
class_def_node
.
bases
.
result
(),
cname
,
qualname
,
mkw
,
...
...
Cython/Compiler/Nodes.py
View file @
105cf92d
...
...
@@ -4675,26 +4675,22 @@ class PyClassDefNode(ClassDefNode):
pass
# no base classes => no inherited metaclass
else
:
self
.
metaclass
=
ExprNodes
.
PyClassMetaclassNode
(
pos
,
mkw
=
mkdict
,
bases
=
self
.
bases
)
pos
,
class_def_node
=
self
)
needs_metaclass_calculation
=
False
else
:
needs_metaclass_calculation
=
True
self
.
dict
=
ExprNodes
.
PyClassNamespaceNode
(
pos
,
name
=
name
,
doc
=
doc_node
,
metaclass
=
self
.
metaclass
,
bases
=
self
.
bases
,
mkw
=
self
.
mkw
)
pos
,
name
=
name
,
doc
=
doc_node
,
class_def_node
=
self
)
self
.
classobj
=
ExprNodes
.
Py3ClassNode
(
pos
,
name
=
name
,
bases
=
self
.
bases
,
dict
=
self
.
dict
,
doc
=
doc_node
,
metaclass
=
self
.
metaclass
,
mkw
=
self
.
mkw
,
pos
,
name
=
name
,
class_def_node
=
self
,
doc
=
doc_node
,
calculate_metaclass
=
needs_metaclass_calculation
,
allow_py2_metaclass
=
allow_py2_metaclass
)
else
:
# no bases, no metaclass => old style class creation
self
.
dict
=
ExprNodes
.
DictNode
(
pos
,
key_value_pairs
=
[])
self
.
classobj
=
ExprNodes
.
ClassNode
(
pos
,
name
=
name
,
bases
=
bases
,
dict
=
self
.
dict
,
doc
=
doc_node
)
pos
,
name
=
name
,
class_def_node
=
self
,
doc
=
doc_node
)
self
.
target
=
ExprNodes
.
NameNode
(
pos
,
name
=
name
)
self
.
class_cell
=
ExprNodes
.
ClassCellInjectorNode
(
self
.
pos
)
...
...
@@ -4712,7 +4708,7 @@ class PyClassDefNode(ClassDefNode):
visibility
=
'private'
,
module_name
=
None
,
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
,
body
=
self
.
body
,
in_pxd
=
False
,
...
...
@@ -4736,6 +4732,10 @@ class PyClassDefNode(ClassDefNode):
args
=
[
class_result
])
self
.
decorators
=
None
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
.
target
.
analyse_target_declaration
(
env
)
cenv
=
self
.
create_scope
(
env
)
...
...
@@ -4748,10 +4748,10 @@ class PyClassDefNode(ClassDefNode):
def
analyse_expressions
(
self
,
env
):
if
self
.
bases
:
self
.
bases
=
self
.
bases
.
analyse_expressions
(
env
)
if
self
.
metaclass
:
self
.
metaclass
=
self
.
metaclass
.
analyse_expressions
(
env
)
if
self
.
mkw
:
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
.
class_result
=
self
.
class_result
.
analyse_expressions
(
env
)
cenv
=
self
.
scope
...
...
tests/run/pyclass_dynamic_bases.pyx
View file @
105cf92d
...
...
@@ -24,3 +24,22 @@ def cond_if_bases(x):
class
PyClass
(
A
if
x
else
B
):
p
=
5
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