Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
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
Boxiang Sun
Pyston
Commits
dce102f3
Commit
dce102f3
authored
Feb 08, 2016
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
super: add descriptor
parent
61c47830
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
213 additions
and
3 deletions
+213
-3
src/runtime/super.cpp
src/runtime/super.cpp
+31
-3
test/tests/super2.py
test/tests/super2.py
+182
-0
No files found.
src/runtime/super.cpp
View file @
dce102f3
...
@@ -157,7 +157,7 @@ Box* superRepr(Box* _s) {
...
@@ -157,7 +157,7 @@ Box* superRepr(Box* _s) {
// Ported from the CPython version:
// Ported from the CPython version:
BoxedClass
*
supercheck
(
BoxedClass
*
type
,
Box
*
obj
)
{
template
<
ExceptionStyle
S
>
BoxedClass
*
superCheck
(
BoxedClass
*
type
,
Box
*
obj
)
noexcept
(
S
==
CAPI
)
{
if
(
PyType_Check
(
obj
)
&&
isSubclass
(
static_cast
<
BoxedClass
*>
(
obj
),
type
))
if
(
PyType_Check
(
obj
)
&&
isSubclass
(
static_cast
<
BoxedClass
*>
(
obj
),
type
))
return
static_cast
<
BoxedClass
*>
(
obj
);
return
static_cast
<
BoxedClass
*>
(
obj
);
...
@@ -172,7 +172,33 @@ BoxedClass* supercheck(BoxedClass* type, Box* obj) {
...
@@ -172,7 +172,33 @@ BoxedClass* supercheck(BoxedClass* type, Box* obj) {
return
static_cast
<
BoxedClass
*>
(
class_attr
);
return
static_cast
<
BoxedClass
*>
(
class_attr
);
}
}
raiseExcHelper
(
TypeError
,
"super(type, obj): obj must be an instance or subtype of type"
);
if
(
S
==
CXX
)
raiseExcHelper
(
TypeError
,
"super(type, obj): obj must be an instance or subtype of type"
);
else
PyErr_SetString
(
TypeError
,
"super(type, obj): obj must be an instance or subtype of type"
);
return
NULL
;
}
template
<
ExceptionStyle
S
>
static
PyObject
*
superGet
(
PyObject
*
_self
,
PyObject
*
obj
,
PyObject
*
type
)
noexcept
(
S
==
CAPI
)
{
BoxedSuper
*
self
=
static_cast
<
BoxedSuper
*>
(
_self
);
if
(
obj
==
NULL
||
obj
==
None
||
self
->
obj
!=
NULL
)
{
/* Not binding to an object, or already bound */
return
self
;
}
if
(
self
->
cls
!=
super_cls
)
{
/* If self is an instance of a (strict) subclass of super,
call its type */
return
runtimeCallInternal
<
S
,
NOT_REWRITABLE
>
(
self
->
cls
,
NULL
,
ArgPassSpec
(
2
),
self
->
type
,
obj
,
NULL
,
NULL
,
NULL
);
}
else
{
/* Inline the common case */
BoxedClass
*
obj_type
=
superCheck
<
S
>
(
self
->
type
,
obj
);
if
(
obj_type
==
NULL
)
return
NULL
;
return
new
BoxedSuper
(
self
->
type
,
obj
,
obj_type
);
}
}
}
Box
*
superInit
(
Box
*
_self
,
Box
*
_type
,
Box
*
obj
)
{
Box
*
superInit
(
Box
*
_self
,
Box
*
_type
,
Box
*
obj
)
{
...
@@ -187,7 +213,7 @@ Box* superInit(Box* _self, Box* _type, Box* obj) {
...
@@ -187,7 +213,7 @@ Box* superInit(Box* _self, Box* _type, Box* obj) {
if
(
obj
==
None
)
if
(
obj
==
None
)
obj
=
NULL
;
obj
=
NULL
;
if
(
obj
!=
NULL
)
if
(
obj
!=
NULL
)
obj_type
=
super
check
(
type
,
obj
);
obj_type
=
super
Check
<
CXX
>
(
type
,
obj
);
self
->
type
=
type
;
self
->
type
=
type
;
self
->
obj
=
obj
;
self
->
obj
=
obj
;
...
@@ -206,6 +232,7 @@ void setupSuper() {
...
@@ -206,6 +232,7 @@ void setupSuper() {
super_cls
->
giveAttr
(
super_cls
->
giveAttr
(
"__init__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
superInit
,
UNKNOWN
,
3
,
false
,
false
),
{
NULL
}));
"__init__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
superInit
,
UNKNOWN
,
3
,
false
,
false
),
{
NULL
}));
super_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
superGet
<
CXX
>
,
UNKNOWN
,
3
)));
super_cls
->
giveAttr
(
"__thisclass__"
,
super_cls
->
giveAttr
(
"__thisclass__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedSuper
,
type
)));
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedSuper
,
type
)));
...
@@ -216,5 +243,6 @@ void setupSuper() {
...
@@ -216,5 +243,6 @@ void setupSuper() {
super_cls
->
freeze
();
super_cls
->
freeze
();
super_cls
->
tp_getattro
=
super_getattro
;
super_cls
->
tp_getattro
=
super_getattro
;
super_cls
->
tp_descr_get
=
superGet
<
CAPI
>
;
}
}
}
}
test/tests/super2.py
0 → 100644
View file @
dce102f3
# this test is a modfied version of a testcase inside test_descr
class
C
:
__metaclass__
=
type
def
__init__
(
self
):
self
.
__state
=
0
def
getstate
(
self
):
return
self
.
__state
def
setstate
(
self
,
state
):
self
.
__state
=
state
a
=
C
()
assert
a
.
getstate
()
==
0
a
.
setstate
(
10
)
assert
a
.
getstate
()
==
10
class
D
:
class
__metaclass__
(
type
):
def
myself
(
cls
):
return
cls
assert
D
.
myself
()
==
D
d
=
D
()
assert
d
.
__class__
==
D
class
M1
(
type
):
def
__new__
(
cls
,
name
,
bases
,
dict
):
dict
[
'__spam__'
]
=
1
return
type
.
__new__
(
cls
,
name
,
bases
,
dict
)
class
C
:
__metaclass__
=
M1
assert
C
.
__spam__
==
1
c
=
C
()
assert
c
.
__spam__
==
1
class
_instance
(
object
):
pass
class
M2
(
object
):
@
staticmethod
def
__new__
(
cls
,
name
,
bases
,
dict
):
self
=
object
.
__new__
(
cls
)
self
.
name
=
name
self
.
bases
=
bases
self
.
dict
=
dict
return
self
def
__call__
(
self
):
it
=
_instance
()
# Early binding of methods
for
key
in
self
.
dict
:
if
key
.
startswith
(
"__"
):
continue
setattr
(
it
,
key
,
self
.
dict
[
key
].
__get__
(
it
,
self
))
return
it
class
C
:
__metaclass__
=
M2
def
spam
(
self
):
return
42
assert
C
.
name
==
'C'
assert
C
.
bases
==
()
assert
'spam'
in
C
.
dict
c
=
C
()
assert
c
.
spam
()
==
42
# More metaclass examples
class
autosuper
(
type
):
# Automatically add __super to the class
# This trick only works for dynamic classes
def
__new__
(
metaclass
,
name
,
bases
,
dict
):
cls
=
super
(
autosuper
,
metaclass
).
__new__
(
metaclass
,
name
,
bases
,
dict
)
# Name mangling for __super removes leading underscores
while
name
[:
1
]
==
"_"
:
name
=
name
[
1
:]
if
name
:
name
=
"_%s__super"
%
name
else
:
name
=
"__super"
setattr
(
cls
,
name
,
super
(
cls
))
return
cls
class
A
:
__metaclass__
=
autosuper
def
meth
(
self
):
return
"A"
class
B
(
A
):
def
meth
(
self
):
return
"B"
+
self
.
__super
.
meth
()
class
C
(
A
):
def
meth
(
self
):
return
"C"
+
self
.
__super
.
meth
()
class
D
(
C
,
B
):
def
meth
(
self
):
return
"D"
+
self
.
__super
.
meth
()
assert
D
().
meth
()
==
"DCBA"
class
E
(
B
,
C
):
def
meth
(
self
):
return
"E"
+
self
.
__super
.
meth
()
assert
E
().
meth
()
==
"EBCA"
class
autoproperty
(
type
):
# Automatically create property attributes when methods
# named _get_x and/or _set_x are found
def
__new__
(
metaclass
,
name
,
bases
,
dict
):
hits
=
{}
for
key
,
val
in
dict
.
iteritems
():
if
key
.
startswith
(
"_get_"
):
key
=
key
[
5
:]
get
,
set
=
hits
.
get
(
key
,
(
None
,
None
))
get
=
val
hits
[
key
]
=
get
,
set
elif
key
.
startswith
(
"_set_"
):
key
=
key
[
5
:]
get
,
set
=
hits
.
get
(
key
,
(
None
,
None
))
set
=
val
hits
[
key
]
=
get
,
set
for
key
,
(
get
,
set
)
in
hits
.
iteritems
():
dict
[
key
]
=
property
(
get
,
set
)
return
super
(
autoproperty
,
metaclass
).
__new__
(
metaclass
,
name
,
bases
,
dict
)
class
A
:
__metaclass__
=
autoproperty
def
_get_x
(
self
):
return
-
self
.
__x
def
_set_x
(
self
,
x
):
self
.
__x
=
-
x
a
=
A
()
assert
not
hasattr
(
a
,
"x"
)
a
.
x
=
12
assert
a
.
x
==
12
assert
a
.
_A__x
==
-
12
class
multimetaclass
(
autoproperty
,
autosuper
):
# Merge of multiple cooperating metaclasses
pass
class
A
:
__metaclass__
=
multimetaclass
def
_get_x
(
self
):
return
"A"
class
B
(
A
):
def
_get_x
(
self
):
return
"B"
+
self
.
__super
.
_get_x
()
class
C
(
A
):
def
_get_x
(
self
):
return
"C"
+
self
.
__super
.
_get_x
()
class
D
(
C
,
B
):
def
_get_x
(
self
):
return
"D"
+
self
.
__super
.
_get_x
()
assert
D
().
x
==
"DCBA"
# Make sure type(x) doesn't call x.__class__.__init__
class
T
(
type
):
counter
=
0
def
__init__
(
self
,
*
args
):
T
.
counter
+=
1
class
C
:
__metaclass__
=
T
assert
T
.
counter
==
1
a
=
C
()
assert
type
(
a
)
==
C
assert
T
.
counter
==
1
class
C
(
object
):
pass
c
=
C
()
try
:
c
()
except
TypeError
:
pass
else
:
self
.
fail
(
"calling object w/o call method should raise "
"TypeError"
)
# Testing code to find most derived baseclass
class
A
(
type
):
def
__new__
(
*
args
,
**
kwargs
):
return
type
.
__new__
(
*
args
,
**
kwargs
)
class
B
(
object
):
pass
class
C
(
object
):
__metaclass__
=
A
# The most derived metaclass of D is A rather than type.
class
D
(
B
,
C
):
pass
print
"finished"
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