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
26587156
Commit
26587156
authored
Jan 25, 2016
by
Marius Wachtler
1
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1061 from corona10/subclass
Add list of not subclassable class
parents
189c7ac1
fc5bd373
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
91 additions
and
31 deletions
+91
-31
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+1
-1
src/runtime/classobj.cpp
src/runtime/classobj.cpp
+6
-4
src/runtime/code.cpp
src/runtime/code.cpp
+2
-1
src/runtime/frame.cpp
src/runtime/frame.cpp
+2
-2
src/runtime/generator.cpp
src/runtime/generator.cpp
+1
-1
src/runtime/inline/xrange.cpp
src/runtime/inline/xrange.cpp
+2
-2
src/runtime/iterobject.cpp
src/runtime/iterobject.cpp
+1
-1
src/runtime/list.cpp
src/runtime/list.cpp
+1
-1
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+7
-5
src/runtime/str.cpp
src/runtime/str.cpp
+1
-1
src/runtime/types.cpp
src/runtime/types.cpp
+6
-7
src/runtime/types.h
src/runtime/types.h
+3
-2
test/tests/builtin_type_not_subclassable.py
test/tests/builtin_type_not_subclassable.py
+58
-3
No files found.
src/runtime/builtin_modules/builtins.cpp
View file @
26587156
...
...
@@ -1850,7 +1850,7 @@ void setupBuiltins() {
"Built-in functions, exceptions, and other objects.
\n\n
Noteworthy: None is "
"the `nil' object; Ellipsis represents `...' in slices."
);
ellipsis_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
0
,
sizeof
(
Box
),
false
,
"ellipsis"
);
ellipsis_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
0
,
sizeof
(
Box
),
false
,
"ellipsis"
,
false
);
ellipsis_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
ellipsisRepr
,
STR
,
1
)));
Ellipsis
=
new
(
ellipsis_cls
)
Box
();
assert
(
Ellipsis
->
cls
);
...
...
src/runtime/classobj.cpp
View file @
26587156
...
...
@@ -1642,10 +1642,12 @@ extern "C" PyObject* PyMethod_Class(PyObject* im) noexcept {
}
void
setupClassobj
()
{
classobj_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
offsetof
(
BoxedClassobj
,
weakreflist
),
sizeof
(
BoxedClassobj
),
false
,
"classobj"
);
instance_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
offsetof
(
BoxedInstance
,
weakreflist
),
sizeof
(
BoxedInstance
),
false
,
"instance"
);
classobj_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedClassobj
::
gcHandler
,
offsetof
(
BoxedClassobj
,
attrs
),
offsetof
(
BoxedClassobj
,
weakreflist
),
sizeof
(
BoxedClassobj
),
false
,
"classobj"
,
false
);
instance_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedInstance
::
gcHandler
,
offsetof
(
BoxedInstance
,
attrs
),
offsetof
(
BoxedInstance
,
weakreflist
),
sizeof
(
BoxedInstance
),
false
,
"instance"
,
false
);
classobj_cls
->
giveAttr
(
"__new__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
classobjNew
,
UNKNOWN
,
4
,
false
,
false
)));
...
...
src/runtime/code.cpp
View file @
26587156
...
...
@@ -116,7 +116,8 @@ extern "C" int PyCode_GetArgCount(PyCodeObject* op) noexcept {
}
void
setupCode
()
{
code_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedCode
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedCode
),
false
,
"code"
);
code_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedCode
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedCode
),
false
,
"code"
,
false
);
code_cls
->
giveAttr
(
"__new__"
,
None
);
// Hacky way of preventing users from instantiating this
...
...
src/runtime/frame.cpp
View file @
26587156
...
...
@@ -171,8 +171,8 @@ extern "C" PyFrameObject* PyFrame_ForStackLevel(int stack_level) noexcept {
}
void
setupFrame
()
{
frame_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedFrame
::
gchandler
,
0
,
0
,
sizeof
(
BoxedFrame
),
false
,
"frame"
);
frame_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedFrame
::
gchandler
,
0
,
0
,
sizeof
(
BoxedFrame
),
false
,
"frame"
,
false
);
frame_cls
->
tp_dealloc
=
BoxedFrame
::
simpleDestructor
;
frame_cls
->
has_safe_tp_dealloc
=
true
;
...
...
src/runtime/generator.cpp
View file @
26587156
...
...
@@ -481,7 +481,7 @@ void generatorDestructor(Box* b) {
void
setupGenerator
()
{
generator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedGenerator
::
gcHandler
,
0
,
offsetof
(
BoxedGenerator
,
weakreflist
),
sizeof
(
BoxedGenerator
),
false
,
"generator"
);
sizeof
(
BoxedGenerator
),
false
,
"generator"
,
false
);
generator_cls
->
tp_dealloc
=
generatorDestructor
;
generator_cls
->
has_safe_tp_dealloc
=
true
;
generator_cls
->
giveAttr
(
...
...
src/runtime/inline/xrange.cpp
View file @
26587156
...
...
@@ -243,9 +243,9 @@ Box* xrangeReduce(Box* self) {
}
void
setupXrange
()
{
xrange_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedXrange
),
false
,
"xrange"
);
xrange_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedXrange
),
false
,
"xrange"
,
false
);
xrange_iterator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedXrangeIterator
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedXrangeIterator
),
false
,
"rangeiterator"
);
sizeof
(
BoxedXrangeIterator
),
false
,
"rangeiterator"
,
false
);
static
PySequenceMethods
xrange_as_sequence
;
xrange_cls
->
tp_as_sequence
=
&
xrange_as_sequence
;
...
...
src/runtime/iterobject.cpp
View file @
26587156
...
...
@@ -210,7 +210,7 @@ llvm_compat_bool calliterHasnextUnboxed(Box* b) {
void
setupIter
()
{
seqiter_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSeqIter
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedSeqIter
),
false
,
"iterator"
);
"iterator"
,
false
);
seqiter_cls
->
giveAttr
(
"next"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
seqiterNext
,
UNKNOWN
,
1
)));
seqiter_cls
->
giveAttr
(
"__hasnext__"
,
...
...
src/runtime/list.cpp
View file @
26587156
...
...
@@ -1295,7 +1295,7 @@ void setupList() {
list_cls
->
tp_as_mapping
=
&
list_as_mapping
;
list_iterator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedListIterator
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedListIterator
),
false
,
"listiterator"
);
sizeof
(
BoxedListIterator
),
false
,
"listiterator"
,
false
);
list_reverse_iterator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedListIterator
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedListIterator
),
false
,
"listreverseiterator"
);
list_iterator_cls
->
instances_are_nonzero
=
list_reverse_iterator_cls
->
instances_are_nonzero
=
true
;
...
...
src/runtime/objmodel.cpp
View file @
26587156
...
...
@@ -399,7 +399,7 @@ void BoxedClass::freeze() {
}
BoxedClass
::
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
)
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
,
bool
is_subclassable
)
:
attrs
(
HiddenClass
::
makeSingleton
()),
gc_visit
(
gc_visit
),
attrs_offset
(
attrs_offset
),
...
...
@@ -418,7 +418,8 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_flags
|=
Py_TPFLAGS_DEFAULT_CORE
;
tp_flags
|=
Py_TPFLAGS_CHECKTYPES
;
tp_flags
|=
Py_TPFLAGS_BASETYPE
;
if
(
is_subclassable
)
tp_flags
|=
Py_TPFLAGS_BASETYPE
;
tp_flags
|=
Py_TPFLAGS_HAVE_GC
;
if
(
base
&&
(
base
->
tp_flags
&
Py_TPFLAGS_HAVE_NEWBUFFER
))
...
...
@@ -496,10 +497,11 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
}
BoxedClass
*
BoxedClass
::
create
(
BoxedClass
*
metaclass
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
)
{
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
,
bool
is_subclassable
)
{
assert
(
!
is_user_defined
);
BoxedClass
*
made
=
new
(
metaclass
,
0
)
BoxedClass
(
base
,
gc_visit
,
attrs_offset
,
weaklist_offset
,
instance_size
,
is_user_defined
,
nam
e
);
BoxedClass
*
made
=
new
(
metaclass
,
0
)
BoxedClass
(
base
,
gc_visit
,
attrs_offset
,
weaklist_offset
,
instance_size
,
is_user_defined
,
name
,
is_subclassabl
e
);
// While it might be ok if these were set, it'd indicate a difference in
// expectations as to who was going to calculate them:
...
...
src/runtime/str.cpp
View file @
26587156
...
...
@@ -2805,7 +2805,7 @@ void setupStr() {
str_cls
->
tp_flags
|=
Py_TPFLAGS_HAVE_NEWBUFFER
;
str_iterator_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedStringIterator
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedStringIterator
),
false
,
"striterator"
);
sizeof
(
BoxedStringIterator
),
false
,
"striterator"
,
false
);
str_iterator_cls
->
giveAttr
(
"__hasnext__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
BoxedStringIterator
::
hasnext
,
BOXED_BOOL
,
1
)));
str_iterator_cls
->
giveAttr
(
...
...
src/runtime/types.cpp
View file @
26587156
...
...
@@ -3705,17 +3705,17 @@ void setupRuntime() {
sizeof
(
BoxedFile
),
false
,
"file"
);
int_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedInt
),
false
,
"int"
);
int_cls
->
tp_flags
|=
Py_TPFLAGS_INT_SUBCLASS
;
bool_cls
=
new
(
0
)
BoxedClass
(
int_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedBool
),
false
,
"bool"
);
bool_cls
=
new
(
0
)
BoxedClass
(
int_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedBool
),
false
,
"bool"
,
false
);
complex_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedComplex
),
false
,
"complex"
);
long_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
BoxedLong
::
gchandler
,
0
,
0
,
sizeof
(
BoxedLong
),
false
,
"long"
);
long_cls
->
tp_flags
|=
Py_TPFLAGS_LONG_SUBCLASS
;
float_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedFloat
),
false
,
"float"
);
function_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
BoxedFunction
::
gcHandler
,
offsetof
(
BoxedFunction
,
attrs
),
offsetof
(
BoxedFunction
,
in_weakreflist
),
sizeof
(
BoxedFunction
),
false
,
"function"
);
offsetof
(
BoxedFunction
,
in_weakreflist
),
sizeof
(
BoxedFunction
),
false
,
"function"
,
false
);
builtin_function_or_method_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
BoxedFunction
::
gcHandler
,
0
,
offsetof
(
BoxedBuiltinFunctionOrMethod
,
in_weakreflist
),
sizeof
(
BoxedBuiltinFunctionOrMethod
),
false
,
"builtin_function_or_method"
);
sizeof
(
BoxedBuiltinFunctionOrMethod
),
false
,
"builtin_function_or_method"
,
false
);
function_cls
->
tp_dealloc
=
builtin_function_or_method_cls
->
tp_dealloc
=
functionDtor
;
function_cls
->
has_safe_tp_dealloc
=
builtin_function_or_method_cls
->
has_safe_tp_dealloc
=
true
;
...
...
@@ -3833,10 +3833,10 @@ void setupRuntime() {
instancemethod_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedInstanceMethod
::
gcHandler
,
0
,
offsetof
(
BoxedInstanceMethod
,
in_weakreflist
),
sizeof
(
BoxedInstanceMethod
),
false
,
"instancemethod"
);
false
,
"instancemethod"
,
false
);
slice_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSlice
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedSlice
),
false
,
"slice"
);
slice_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSlice
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedSlice
),
false
,
"slice"
,
false
);
set_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSet
::
gcHandler
,
0
,
offsetof
(
BoxedSet
,
weakreflist
),
sizeof
(
BoxedSet
),
false
,
"set"
);
frozenset_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSet
::
gcHandler
,
0
,
offsetof
(
BoxedSet
,
weakreflist
),
...
...
@@ -4037,7 +4037,6 @@ void setupRuntime() {
slice_cls
->
giveAttr
(
"step"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedSlice
,
step
)));
slice_cls
->
freeze
();
slice_cls
->
tp_compare
=
(
cmpfunc
)
slice_compare
;
slice_cls
->
tp_flags
&=
~
Py_TPFLAGS_BASETYPE
;
static
PyMappingMethods
attrwrapper_as_mapping
;
attrwrapper_cls
->
tp_as_mapping
=
&
attrwrapper_as_mapping
;
...
...
src/runtime/types.h
View file @
26587156
...
...
@@ -291,10 +291,11 @@ public:
// These should only be used for builtin types:
static
BoxedClass
*
create
(
BoxedClass
*
metatype
,
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
);
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
,
bool
is_subclassable
=
true
);
BoxedClass
(
BoxedClass
*
base
,
gcvisit_func
gc_visit
,
int
attrs_offset
,
int
weaklist_offset
,
int
instance_size
,
bool
is_user_defined
,
const
char
*
name
);
bool
is_user_defined
,
const
char
*
name
,
bool
is_subclassable
=
true
);
DEFAULT_CLASS_VAR
(
type_cls
,
sizeof
(
SlotOffset
));
...
...
test/tests/builtin_type_not_subclassable.py
View file @
26587156
# should_error
class
foo
(
slice
):
pass
import
re
import
inspect
def
gen
():
print
(
"generator test"
)
yield
'a'
yield
'b'
def
is_subclassable
(
base_cls
):
try
:
class
C
(
base_cls
):
pass
except
TypeError
as
e
:
assert
'is not an acceptable base type'
in
repr
(
e
)
return
False
return
True
class
b
:
def
__init__
(
self
):
self
.
c
=
1
def
d
(
self
):
print
self
.
c
#slice
assert
not
is_subclassable
(
slice
)
#xrange
assert
not
is_subclassable
(
type
(
xrange
(
1
)))
#range-iterator
assert
not
is_subclassable
(
type
(
iter
(
range
(
5
))))
#xrange-iterator
assert
not
is_subclassable
(
type
(
iter
(
xrange
(
5
))))
#callable-iterator
assert
not
is_subclassable
(
type
(
re
.
finditer
(
r'\bs\
w+
', "some text with swords")))
#striterator
assert not is_subclassable(type(iter("abc")))
#memoryview
assert not is_subclassable(type(memoryview("abc")))
#buffer
assert not is_subclassable(type(buffer('
abcde
', 2,1)))
#Ellipsis
assert not is_subclassable(type(Ellipsis))
#generator
assert not is_subclassable(type(gen()))
#bool
assert not is_subclassable(type(True))
#classobj
assert not is_subclassable(type(b))
#code
assert not is_subclassable(type(compile('
sum
([
1
,
2
,
3
])
', '', '
single
')))
#instance
ins = b()
assert not is_subclassable(type(ins))
#instance_method
assert not is_subclassable(type(ins.d))
#frame
assert not is_subclassable(type(inspect.currentframe()))
#function
assert not is_subclassable(type(is_subclassable))
Boxiang Sun
@Daetalus
mentioned in commit
89d32425
·
Sep 08, 2016
mentioned in commit
89d32425
mentioned in commit 89d324252648402404a0a37125eca19da76cb2ff
Toggle commit list
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