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
ad0315d4
Commit
ad0315d4
authored
Jan 18, 2016
by
Marius Wachtler
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1057 from undingen/numpy_test2_smallfix
@rudi-c #1027 numpy patch with a small fix
parents
c5b14490
1d9e4b05
Changes
22
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
360 additions
and
191 deletions
+360
-191
src/core/types.h
src/core/types.h
+3
-0
src/runtime/capi.cpp
src/runtime/capi.cpp
+2
-4
src/runtime/code.cpp
src/runtime/code.cpp
+6
-7
src/runtime/descr.cpp
src/runtime/descr.cpp
+5
-6
src/runtime/file.cpp
src/runtime/file.cpp
+2
-1
src/runtime/float.cpp
src/runtime/float.cpp
+5
-2
src/runtime/frame.cpp
src/runtime/frame.cpp
+5
-5
src/runtime/generator.cpp
src/runtime/generator.cpp
+1
-1
src/runtime/int.cpp
src/runtime/int.cpp
+4
-4
src/runtime/long.cpp
src/runtime/long.cpp
+4
-4
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+9
-0
src/runtime/str.cpp
src/runtime/str.cpp
+7
-3
src/runtime/traceback.cpp
src/runtime/traceback.cpp
+1
-1
src/runtime/tuple.cpp
src/runtime/tuple.cpp
+3
-1
src/runtime/types.cpp
src/runtime/types.cpp
+37
-30
src/runtime/types.h
src/runtime/types.h
+5
-2
test/integration/numpy_patch.patch
test/integration/numpy_patch.patch
+165
-96
test/integration/numpy_test.py
test/integration/numpy_test.py
+50
-24
test/tests/descriptors.py
test/tests/descriptors.py
+13
-0
test/tests/future_division.py
test/tests/future_division.py
+3
-0
test/tests/str_functions.py
test/tests/str_functions.py
+25
-0
test/tests/tuples.py
test/tests/tuples.py
+5
-0
No files found.
src/core/types.h
View file @
ad0315d4
...
...
@@ -651,6 +651,9 @@ public:
this
->
setattr
(
attr
,
val
,
NULL
);
}
void
giveAttrDescriptor
(
const
char
*
attr
,
Box
*
(
*
get
)(
Box
*
,
void
*
),
void
(
*
set
)(
Box
*
,
Box
*
,
void
*
));
// getattr() does the equivalent of PyDict_GetItem(obj->dict, attr): it looks up the attribute's value on the
// object's attribute storage. it doesn't look at other objects or do any descriptor logic.
template
<
Rewritable
rewritable
=
REWRITABLE
>
...
...
src/runtime/capi.cpp
View file @
ad0315d4
...
...
@@ -1985,10 +1985,8 @@ void setupCAPI() {
capifunc_cls
->
giveAttr
(
"__call__"
,
capi_call
);
capifunc_cls
->
tpp_call
.
capi_val
=
BoxedCApiFunction
::
tppCall
<
CAPI
>
;
capifunc_cls
->
tpp_call
.
cxx_val
=
BoxedCApiFunction
::
tppCall
<
CXX
>
;
capifunc_cls
->
giveAttr
(
"__name__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCApiFunction
::
getname
,
NULL
,
NULL
));
capifunc_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCApiFunction
::
doc
,
NULL
,
NULL
));
capifunc_cls
->
giveAttrDescriptor
(
"__name__"
,
BoxedCApiFunction
::
getname
,
NULL
);
capifunc_cls
->
giveAttrDescriptor
(
"__doc__"
,
BoxedCApiFunction
::
doc
,
NULL
);
capifunc_cls
->
giveAttr
(
"__module__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedCApiFunction
,
module
)));
...
...
src/runtime/code.cpp
View file @
ad0315d4
...
...
@@ -120,13 +120,12 @@ void setupCode() {
code_cls
->
giveAttr
(
"__new__"
,
None
);
// Hacky way of preventing users from instantiating this
code_cls
->
giveAttr
(
"co_name"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCode
::
name
,
NULL
,
NULL
));
code_cls
->
giveAttr
(
"co_filename"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCode
::
filename
,
NULL
,
NULL
));
code_cls
->
giveAttr
(
"co_firstlineno"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCode
::
firstlineno
,
NULL
,
NULL
));
code_cls
->
giveAttr
(
"co_argcount"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCode
::
argcount
,
NULL
,
NULL
));
code_cls
->
giveAttr
(
"co_varnames"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCode
::
varnames
,
NULL
,
NULL
));
code_cls
->
giveAttr
(
"co_flags"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedCode
::
flags
,
NULL
,
NULL
));
code_cls
->
giveAttrDescriptor
(
"co_name"
,
BoxedCode
::
name
,
NULL
);
code_cls
->
giveAttrDescriptor
(
"co_filename"
,
BoxedCode
::
filename
,
NULL
);
code_cls
->
giveAttrDescriptor
(
"co_firstlineno"
,
BoxedCode
::
firstlineno
,
NULL
);
code_cls
->
giveAttrDescriptor
(
"co_argcount"
,
BoxedCode
::
argcount
,
NULL
);
code_cls
->
giveAttrDescriptor
(
"co_varnames"
,
BoxedCode
::
varnames
,
NULL
);
code_cls
->
giveAttrDescriptor
(
"co_flags"
,
BoxedCode
::
flags
,
NULL
);
code_cls
->
freeze
();
}
...
...
src/runtime/descr.cpp
View file @
ad0315d4
...
...
@@ -688,7 +688,8 @@ extern "C" PyObject* PyDescr_NewMember(PyTypeObject* x, struct PyMemberDef* y) n
extern
"C"
PyObject
*
PyDescr_NewGetSet
(
PyTypeObject
*
x
,
struct
PyGetSetDef
*
y
)
noexcept
{
// TODO do something with __doc__
return
new
(
capi_getset_cls
)
BoxedGetsetDescriptor
(
y
->
get
,
(
void
(
*
)(
Box
*
,
Box
*
,
void
*
))
y
->
set
,
y
->
closure
);
return
new
(
capi_getset_cls
)
BoxedGetsetDescriptor
(
internStringMortal
(
y
->
name
),
y
->
get
,
(
void
(
*
)(
Box
*
,
Box
*
,
void
*
))
y
->
set
,
y
->
closure
);
}
extern
"C"
PyObject
*
PyDescr_NewClassMethod
(
PyTypeObject
*
type
,
PyMethodDef
*
method
)
noexcept
{
...
...
@@ -756,14 +757,13 @@ void setupDescr() {
method_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
method_call_cl
));
method_cls
->
tpp_call
.
capi_val
=
BoxedMethodDescriptor
::
tppCall
<
CAPI
>
;
method_cls
->
tpp_call
.
cxx_val
=
BoxedMethodDescriptor
::
tppCall
<
CXX
>
;
method_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
methodGetDoc
,
NULL
,
NULL
)
);
method_cls
->
giveAttr
Descriptor
(
"__doc__"
,
methodGetDoc
,
NULL
);
method_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
methodRepr
,
UNKNOWN
,
1
)));
method_cls
->
freeze
();
wrapperdescr_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
(
(
void
*
)
BoxedWrapperDescriptor
::
__call__
,
UNKNOWN
,
2
,
true
,
true
)));
wrapperdescr_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
wrapperdescrGetDoc
,
NULL
,
NULL
));
wrapperdescr_cls
->
giveAttrDescriptor
(
"__doc__"
,
wrapperdescrGetDoc
,
NULL
);
wrapperdescr_cls
->
tp_descr_get
=
BoxedWrapperDescriptor
::
descr_get
;
wrapperdescr_cls
->
tpp_call
.
capi_val
=
BoxedWrapperDescriptor
::
tppCall
<
CAPI
>
;
wrapperdescr_cls
->
tpp_call
.
cxx_val
=
BoxedWrapperDescriptor
::
tppCall
<
CXX
>
;
...
...
@@ -777,8 +777,7 @@ void setupDescr() {
(
void
*
)
BoxedWrapperObject
::
__call__
,
UNKNOWN
,
1
,
true
,
true
)));
wrapperobject_cls
->
tpp_call
.
capi_val
=
BoxedWrapperObject
::
tppCall
<
CAPI
>
;
wrapperobject_cls
->
tpp_call
.
cxx_val
=
BoxedWrapperObject
::
tppCall
<
CXX
>
;
wrapperobject_cls
->
giveAttr
(
"__doc__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
wrapperobjectGetDoc
,
NULL
,
NULL
));
wrapperobject_cls
->
giveAttrDescriptor
(
"__doc__"
,
wrapperobjectGetDoc
,
NULL
);
wrapperobject_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
wrapperObjectRepr
,
UNKNOWN
,
1
)));
wrapperobject_cls
->
freeze
();
...
...
src/runtime/file.cpp
View file @
ad0315d4
...
...
@@ -1892,7 +1892,8 @@ void setupFile() {
for
(
auto
&
getset
:
file_getsetlist
)
{
file_cls
->
giveAttr
(
getset
.
name
,
new
(
capi_getset_cls
)
BoxedGetsetDescriptor
(
getset
.
get
,
(
void
(
*
)(
Box
*
,
Box
*
,
void
*
))
getset
.
set
,
getset
.
closure
));
internStringMortal
(
getset
.
name
),
getset
.
get
,
(
void
(
*
)(
Box
*
,
Box
*
,
void
*
))
getset
.
set
,
getset
.
closure
));
}
file_cls
->
freeze
();
...
...
src/runtime/float.cpp
View file @
ad0315d4
...
...
@@ -928,6 +928,9 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C
else
throwCAPIException
();
}
// Make sure that we're not in an error state when we return a non-NULL value.
assert
(
!
PyErr_Occurred
());
return
new
BoxedFloat
(
a_f
);
}
else
if
(
a
->
cls
==
str_cls
||
a
->
cls
==
unicode_cls
)
{
BoxedFloat
*
res
=
(
BoxedFloat
*
)
PyFloat_FromString
(
a
,
NULL
);
...
...
@@ -1755,8 +1758,8 @@ void setupFloat() {
float_cls
->
giveAttr
(
"__long__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
floatLong
,
UNKNOWN
,
1
)));
float_cls
->
giveAttr
(
"__hash__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
floatHash
,
BOXED_INT
,
1
)));
float_cls
->
giveAttr
(
"real"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
floatConjugate
,
NULL
,
NULL
)
);
float_cls
->
giveAttr
(
"imag"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
float0
,
NULL
,
NULL
)
);
float_cls
->
giveAttr
Descriptor
(
"real"
,
floatConjugate
,
NULL
);
float_cls
->
giveAttr
Descriptor
(
"imag"
,
float0
,
NULL
);
float_cls
->
giveAttr
(
"conjugate"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
floatConjugate
,
BOXED_FLOAT
,
1
)));
...
...
src/runtime/frame.cpp
View file @
ad0315d4
...
...
@@ -176,12 +176,12 @@ void setupFrame() {
frame_cls
->
tp_dealloc
=
BoxedFrame
::
simpleDestructor
;
frame_cls
->
has_safe_tp_dealloc
=
true
;
frame_cls
->
giveAttr
(
"f_code"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
code
,
NULL
,
NULL
)
);
frame_cls
->
giveAttr
(
"f_locals"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
locals
,
NULL
,
NULL
)
);
frame_cls
->
giveAttr
(
"f_lineno"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
lineno
,
NULL
,
NULL
)
);
frame_cls
->
giveAttr
Descriptor
(
"f_code"
,
BoxedFrame
::
code
,
NULL
);
frame_cls
->
giveAttr
Descriptor
(
"f_locals"
,
BoxedFrame
::
locals
,
NULL
);
frame_cls
->
giveAttr
Descriptor
(
"f_lineno"
,
BoxedFrame
::
lineno
,
NULL
);
frame_cls
->
giveAttr
(
"f_globals"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
globals
,
NULL
,
NULL
)
);
frame_cls
->
giveAttr
(
"f_back"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
BoxedFrame
::
back
,
NULL
,
NULL
)
);
frame_cls
->
giveAttr
Descriptor
(
"f_globals"
,
BoxedFrame
::
globals
,
NULL
);
frame_cls
->
giveAttr
Descriptor
(
"f_back"
,
BoxedFrame
::
back
,
NULL
);
frame_cls
->
freeze
();
}
...
...
src/runtime/generator.cpp
View file @
ad0315d4
...
...
@@ -502,7 +502,7 @@ void setupGenerator() {
=
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
generatorThrow
,
UNKNOWN
,
4
,
false
,
false
),
{
NULL
,
NULL
});
generator_cls
->
giveAttr
(
"throw"
,
gthrow
);
generator_cls
->
giveAttr
(
"__name__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
generatorName
,
NULL
,
NULL
)
);
generator_cls
->
giveAttr
Descriptor
(
"__name__"
,
generatorName
,
NULL
);
generator_cls
->
freeze
();
generator_cls
->
tp_iter
=
PyObject_SelfIter
;
...
...
src/runtime/int.cpp
View file @
ad0315d4
...
...
@@ -1446,11 +1446,11 @@ void setupInt() {
int_cls
->
giveAttr
(
"bit_length"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
intBitLength
,
BOXED_INT
,
1
)));
int_cls
->
giveAttr
(
"real"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
intIntGetset
,
NULL
,
NULL
)
);
int_cls
->
giveAttr
(
"imag"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
int0
,
NULL
,
NULL
)
);
int_cls
->
giveAttr
Descriptor
(
"real"
,
intIntGetset
,
NULL
);
int_cls
->
giveAttr
Descriptor
(
"imag"
,
int0
,
NULL
);
int_cls
->
giveAttr
(
"conjugate"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
intIntGetset
,
BOXED_INT
,
1
)));
int_cls
->
giveAttr
(
"numerator"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
intIntGetset
,
NULL
,
NULL
)
);
int_cls
->
giveAttr
(
"denominator"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
int1
,
NULL
,
NULL
)
);
int_cls
->
giveAttr
Descriptor
(
"numerator"
,
intIntGetset
,
NULL
);
int_cls
->
giveAttr
Descriptor
(
"denominator"
,
int1
,
NULL
);
add_operators
(
int_cls
);
int_cls
->
freeze
();
...
...
src/runtime/long.cpp
View file @
ad0315d4
...
...
@@ -1705,11 +1705,11 @@ void setupLong() {
long_cls
->
giveAttr
(
"__index__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
longIndex
,
LONG
,
1
)));
long_cls
->
giveAttr
(
"bit_length"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
longBitLength
,
LONG
,
1
)));
long_cls
->
giveAttr
(
"real"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
longDesc
,
NULL
,
NULL
)
);
long_cls
->
giveAttr
(
"imag"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
long0
,
NULL
,
NULL
)
);
long_cls
->
giveAttr
Descriptor
(
"real"
,
longDesc
,
NULL
);
long_cls
->
giveAttr
Descriptor
(
"imag"
,
long0
,
NULL
);
long_cls
->
giveAttr
(
"conjugate"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
longDesc
,
UNKNOWN
,
1
)));
long_cls
->
giveAttr
(
"numerator"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
longDesc
,
NULL
,
NULL
)
);
long_cls
->
giveAttr
(
"denominator"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
long1
,
NULL
,
NULL
)
);
long_cls
->
giveAttr
Descriptor
(
"numerator"
,
longDesc
,
NULL
);
long_cls
->
giveAttr
Descriptor
(
"denominator"
,
long1
,
NULL
);
long_cls
->
giveAttr
(
"__getnewargs__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
long_getnewargs
,
UNKNOWN
,
1
,
ParamNames
::
empty
(),
CAPI
)));
...
...
src/runtime/objmodel.cpp
View file @
ad0315d4
...
...
@@ -4142,6 +4142,10 @@ Box* callCLFunc(FunctionMetadata* md, CallRewriteArgs* rewrite_args, int num_out
}
}
// We check for this assertion later too - by checking it twice, we know
// if the error state was set before calling the chosen CF or after.
ASSERT
(
!
PyErr_Occurred
(),
""
);
Box
*
r
;
// we duplicate the call to callChosenCf here so we can
// distinguish lexically between calls that target jitted python
...
...
@@ -4157,6 +4161,11 @@ Box* callCLFunc(FunctionMetadata* md, CallRewriteArgs* rewrite_args, int num_out
if
(
!
r
)
{
assert
(
S
==
CAPI
);
}
else
{
// If this assertion is triggered because the type isn't what we expected,
// but something that should be allowed (e.g. NotImplementedType), it is
// possible that the program has a bad type annotation. For example, an
// attribute that we added in C++ should have return type UNKNOWN instead
// of BOXED_SOMETHING.
ASSERT
(
chosen_cf
->
spec
->
rtn_type
->
isFitBy
(
r
->
cls
),
"%s (%p) was supposed to return %s, but gave a %s"
,
g
.
func_addr_registry
.
getFuncNameAtAddress
(
chosen_cf
->
code
,
true
,
NULL
).
c_str
(),
chosen_cf
->
code
,
chosen_cf
->
spec
->
rtn_type
->
debugName
().
c_str
(),
r
->
cls
->
tp_name
);
...
...
src/runtime/str.cpp
View file @
ad0315d4
...
...
@@ -1226,9 +1226,13 @@ Box* str_richcompare(Box* lhs, Box* rhs, int op) {
#define JUST_RIGHT 1
#define JUST_CENTER 2
static
Box
*
pad
(
BoxedString
*
self
,
Box
*
width
,
Box
*
fillchar
,
int
justType
)
{
assert
(
width
->
cls
==
int_cls
);
assert
(
PyString_Check
(
fillchar
));
assert
(
static_cast
<
BoxedString
*>
(
fillchar
)
->
size
()
==
1
);
if
(
!
PyInt_Check
(
width
))
{
raiseExcHelper
(
TypeError
,
"an integer is required"
);
}
if
(
!
PyString_Check
(
fillchar
)
||
static_cast
<
BoxedString
*>
(
fillchar
)
->
size
()
!=
1
)
{
raiseExcHelper
(
TypeError
,
"must be char, not %s"
,
fillchar
->
cls
->
tp_name
);
}
int64_t
curWidth
=
self
->
size
();
int64_t
targetWidth
=
static_cast
<
BoxedInt
*>
(
width
)
->
n
;
...
...
src/runtime/traceback.cpp
View file @
ad0315d4
...
...
@@ -144,7 +144,7 @@ void setupTraceback() {
traceback_cls->giveAttr("tb_lineno", new (pyston_getset_cls) BoxedGetsetDescriptor(traceback_tb_lineno, NULL,
NULL));
*/
traceback_cls
->
giveAttr
(
"tb_next"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
traceback_tb_next
,
NULL
,
NULL
)
);
traceback_cls
->
giveAttr
Descriptor
(
"tb_next"
,
traceback_tb_next
,
NULL
);
traceback_cls
->
freeze
();
}
...
...
src/runtime/tuple.cpp
View file @
ad0315d4
...
...
@@ -687,7 +687,9 @@ void setupTuple() {
tuple_cls
->
giveAttr
(
"__len__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
tupleLen
,
BOXED_INT
,
1
)));
tuple_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
tupleRepr
,
STR
,
1
)));
tuple_cls
->
giveAttr
(
"__add__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
tupleAdd
,
BOXED_TUPLE
,
2
)));
// Return type is UNKNOWN as it could be NotImplemented.
tuple_cls
->
giveAttr
(
"__add__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
tupleAdd
,
UNKNOWN
,
2
)));
tuple_cls
->
giveAttr
(
"__mul__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
tupleMul
,
BOXED_TUPLE
,
2
)));
tuple_cls
->
giveAttr
(
"__rmul__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
tupleMul
,
BOXED_TUPLE
,
2
)));
...
...
src/runtime/types.cpp
View file @
ad0315d4
...
...
@@ -1481,6 +1481,12 @@ void BoxedInstanceMethod::gcHandler(GCVisitor* v, Box* b) {
v
->
visit
(
&
im
->
im_class
);
}
void
BoxedGetsetDescriptor
::
gcHandler
(
GCVisitor
*
v
,
Box
*
b
)
{
assert
(
isSubclass
(
b
->
cls
,
pyston_getset_cls
)
||
isSubclass
(
b
->
cls
,
capi_getset_cls
));
BoxedGetsetDescriptor
*
descr
=
static_cast
<
BoxedGetsetDescriptor
*>
(
b
);
v
->
visit
(
&
descr
->
name
);
}
void
BoxedProperty
::
gcHandler
(
GCVisitor
*
v
,
Box
*
b
)
{
Box
::
gcHandler
(
v
,
b
);
...
...
@@ -2736,6 +2742,11 @@ Box* AttrWrapperIter::next_capi(Box* _self) noexcept {
return
r
;
}
void
Box
::
giveAttrDescriptor
(
const
char
*
attr
,
Box
*
(
*
get
)(
Box
*
,
void
*
),
void
(
*
set
)(
Box
*
,
Box
*
,
void
*
))
{
BoxedString
*
bstr
=
internStringMortal
(
attr
);
giveAttr
(
bstr
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
bstr
,
get
,
set
,
NULL
));
}
Box
*
Box
::
getAttrWrapper
()
{
assert
(
cls
->
instancesHaveHCAttrs
());
HCAttrs
*
attrs
=
getHCAttrsPtr
();
...
...
@@ -3576,6 +3587,9 @@ static Box* getsetGet(Box* self, Box* obj, Box* type) {
return
self
;
BoxedGetsetDescriptor
*
getset_descr
=
static_cast
<
BoxedGetsetDescriptor
*>
(
self
);
assert
(
getset_descr
->
get
!=
NULL
);
if
(
isSubclass
(
self
->
cls
,
pyston_getset_cls
))
{
return
getset_descr
->
get
(
obj
,
getset_descr
->
closure
);
}
else
{
...
...
@@ -3591,6 +3605,12 @@ static Box* getsetSet(Box* self, Box* obj, Box* val) {
assert
(
obj
!=
NULL
&&
obj
!=
None
);
BoxedGetsetDescriptor
*
getset_descr
=
static_cast
<
BoxedGetsetDescriptor
*>
(
self
);
if
(
getset_descr
->
set
==
NULL
)
{
raiseExcHelper
(
AttributeError
,
"attribute '%s' of '%s' objects is not writable"
,
getset_descr
->
name
->
data
(),
obj
->
cls
->
tp_name
);
}
if
(
isSubclass
(
self
->
cls
,
pyston_getset_cls
))
{
getset_descr
->
set
(
obj
,
val
,
getset_descr
->
closure
);
return
None
;
...
...
@@ -3603,18 +3623,7 @@ static Box* getsetSet(Box* self, Box* obj, Box* val) {
}
static
Box
*
getsetDelete
(
Box
*
self
,
Box
*
obj
)
{
assert
(
obj
!=
NULL
&&
obj
!=
None
);
BoxedGetsetDescriptor
*
getset_descr
=
static_cast
<
BoxedGetsetDescriptor
*>
(
self
);
if
(
isSubclass
(
self
->
cls
,
pyston_getset_cls
))
{
getset_descr
->
set
(
obj
,
NULL
,
getset_descr
->
closure
);
return
None
;
}
else
{
RELEASE_ASSERT
(
isSubclass
(
self
->
cls
,
capi_getset_cls
),
""
);
getset_descr
->
set
(
obj
,
NULL
,
getset_descr
->
closure
);
checkAndThrowCAPIException
();
return
None
;
}
return
getsetSet
(
self
,
obj
,
NULL
);
}
bool
TRACK_ALLOCATIONS
=
false
;
...
...
@@ -3686,8 +3695,8 @@ void setupRuntime() {
gc
::
registerPermanentRoot
(
EmptyTuple
);
list_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
BoxedList
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedList
),
false
,
"list"
);
list_cls
->
tp_flags
|=
Py_TPFLAGS_LIST_SUBCLASS
;
pyston_getset_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset_descriptor"
);
pyston_getset_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
BoxedGetsetDescriptor
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset_descriptor"
);
attrwrapper_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
AttrWrapper
::
gcHandler
,
0
,
0
,
sizeof
(
AttrWrapper
),
false
,
"attrwrapper"
);
dict_cls
=
new
(
0
)
BoxedClass
(
object_cls
,
&
BoxedDict
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedDict
),
false
,
"dict"
);
...
...
@@ -3816,9 +3825,10 @@ void setupRuntime() {
str_cls
->
tp_flags
|=
Py_TPFLAGS_HAVE_NEWBUFFER
;
dict_descr
=
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeSubDict
,
typeSubSetDict
,
NULL
);
dict_descr
=
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
internStringMortal
(
"__dict__"
),
typeSubDict
,
typeSubSetDict
,
NULL
);
gc
::
registerPermanentRoot
(
dict_descr
);
type_cls
->
giveAttr
(
"__dict__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeDict
,
NULL
,
NULL
)
);
type_cls
->
giveAttr
Descriptor
(
"__dict__"
,
typeDict
,
NULL
);
instancemethod_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedInstanceMethod
::
gcHandler
,
0
,
...
...
@@ -3831,8 +3841,8 @@ void setupRuntime() {
sizeof
(
BoxedSet
),
false
,
"set"
);
frozenset_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedSet
::
gcHandler
,
0
,
offsetof
(
BoxedSet
,
weakreflist
),
sizeof
(
BoxedSet
),
false
,
"frozenset"
);
capi_getset_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
NULL
,
0
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset"
);
capi_getset_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedGetsetDescriptor
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedGetsetDescriptor
),
false
,
"getset"
);
closure_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedClosure
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedClosure
),
false
,
"closure"
);
property_cls
=
BoxedClass
::
create
(
type_cls
,
object_cls
,
&
BoxedProperty
::
gcHandler
,
0
,
0
,
sizeof
(
BoxedProperty
),
...
...
@@ -3875,8 +3885,8 @@ void setupRuntime() {
auto
typeCallObj
=
FunctionMetadata
::
create
((
void
*
)
typeCall
,
UNKNOWN
,
1
,
true
,
true
);
typeCallObj
->
internal_callable
.
cxx_val
=
&
typeCallInternal
;
type_cls
->
giveAttr
(
"__name__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeName
,
typeSetName
,
NULL
)
);
type_cls
->
giveAttr
(
"__bases__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeBases
,
typeSetBases
,
NULL
)
);
type_cls
->
giveAttr
Descriptor
(
"__name__"
,
typeName
,
typeSetName
);
type_cls
->
giveAttr
Descriptor
(
"__bases__"
,
typeBases
,
typeSetBases
);
type_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
typeCallObj
));
type_cls
->
giveAttr
(
...
...
@@ -3884,7 +3894,7 @@ void setupRuntime() {
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
typeNewGeneric
,
UNKNOWN
,
4
,
false
,
false
),
{
NULL
,
NULL
}));
type_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
typeRepr
,
STR
,
1
)));
type_cls
->
tp_hash
=
(
hashfunc
)
_Py_HashPointer
;
type_cls
->
giveAttr
(
"__module__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
typeModule
,
typeSetModule
,
NULL
)
);
type_cls
->
giveAttr
Descriptor
(
"__module__"
,
typeModule
,
typeSetModule
);
type_cls
->
giveAttr
(
"__mro__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedClass
,
tp_mro
)));
type_cls
->
giveAttr
(
"__flags__"
,
...
...
@@ -3921,7 +3931,7 @@ void setupRuntime() {
for
(
auto
&
md
:
object_methods
)
{
object_cls
->
giveAttr
(
md
.
ml_name
,
new
BoxedMethodDescriptor
(
&
md
,
object_cls
));
}
object_cls
->
giveAttr
(
"__class__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
objectClass
,
objectSetClass
,
NULL
)
);
object_cls
->
giveAttr
Descriptor
(
"__class__"
,
objectClass
,
objectSetClass
);
object_cls
->
tp_str
=
object_str
;
add_operators
(
object_cls
);
...
...
@@ -3955,25 +3965,23 @@ void setupRuntime() {
setupFrame
();
function_cls
->
giveAttr
(
"__dict__"
,
dict_descr
);
function_cls
->
giveAttr
(
"__name__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
funcName
,
funcSetName
,
NULL
)
);
function_cls
->
giveAttr
Descriptor
(
"__name__"
,
funcName
,
funcSetName
);
function_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
functionRepr
,
STR
,
1
)));
function_cls
->
giveAttr
(
"__module__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedFunction
,
modname
),
false
));
function_cls
->
giveAttr
(
"__doc__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedFunction
,
doc
),
false
));
function_cls
->
giveAttr
(
"func_doc"
,
function_cls
->
getattr
(
internStringMortal
(
"__doc__"
)));
function_cls
->
giveAttr
(
"__globals__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
functionGlobals
,
NULL
,
NULL
)
);
function_cls
->
giveAttr
Descriptor
(
"__globals__"
,
functionGlobals
,
NULL
);
function_cls
->
giveAttr
(
"__get__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
functionGet
,
UNKNOWN
,
3
)));
function_cls
->
giveAttr
(
"__call__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
functionCall
,
UNKNOWN
,
1
,
true
,
true
)));
function_cls
->
giveAttr
(
"__nonzero__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
functionNonzero
,
BOXED_BOOL
,
1
)));
function_cls
->
giveAttr
(
"func_code"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
functionCode
,
functionSetCode
,
NULL
));
function_cls
->
giveAttrDescriptor
(
"func_code"
,
functionCode
,
functionSetCode
);
function_cls
->
giveAttr
(
"__code__"
,
function_cls
->
getattr
(
internStringMortal
(
"func_code"
)));
function_cls
->
giveAttr
(
"func_name"
,
function_cls
->
getattr
(
internStringMortal
(
"__name__"
)));
function_cls
->
giveAttr
(
"func_defaults"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
functionDefaults
,
functionSetDefaults
,
NULL
));
function_cls
->
giveAttrDescriptor
(
"func_defaults"
,
functionDefaults
,
functionSetDefaults
);
function_cls
->
giveAttr
(
"__defaults__"
,
function_cls
->
getattr
(
internStringMortal
(
"func_defaults"
)));
function_cls
->
giveAttr
(
"func_globals"
,
function_cls
->
getattr
(
internStringMortal
(
"__globals__"
)));
function_cls
->
freeze
();
...
...
@@ -3988,8 +3996,7 @@ void setupRuntime() {
builtin_function_or_method_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
FunctionMetadata
::
create
((
void
*
)
builtinFunctionOrMethodRepr
,
STR
,
1
)));
builtin_function_or_method_cls
->
giveAttr
(
"__name__"
,
new
(
pyston_getset_cls
)
BoxedGetsetDescriptor
(
builtinFunctionOrMethodName
,
NULL
,
NULL
));
builtin_function_or_method_cls
->
giveAttrDescriptor
(
"__name__"
,
builtinFunctionOrMethodName
,
NULL
);
builtin_function_or_method_cls
->
giveAttr
(
"__doc__"
,
new
BoxedMemberDescriptor
(
BoxedMemberDescriptor
::
OBJECT
,
offsetof
(
BoxedBuiltinFunctionOrMethod
,
doc
),
false
));
...
...
src/runtime/types.h
View file @
ad0315d4
...
...
@@ -948,9 +948,12 @@ public:
Box
*
(
*
get
)(
Box
*
,
void
*
);
void
(
*
set
)(
Box
*
,
Box
*
,
void
*
);
void
*
closure
;
BoxedString
*
name
;
BoxedGetsetDescriptor
(
Box
*
(
*
get
)(
Box
*
,
void
*
),
void
(
*
set
)(
Box
*
,
Box
*
,
void
*
),
void
*
closure
)
:
get
(
get
),
set
(
set
),
closure
(
closure
)
{}
BoxedGetsetDescriptor
(
BoxedString
*
name
,
Box
*
(
*
get
)(
Box
*
,
void
*
),
void
(
*
set
)(
Box
*
,
Box
*
,
void
*
),
void
*
closure
)
:
get
(
get
),
set
(
set
),
closure
(
closure
),
name
(
name
)
{}
static
void
gcHandler
(
GCVisitor
*
v
,
Box
*
b
);
// No DEFAULT_CLASS annotation here -- force callers to explicitly specifiy pyston_getset_cls or capi_getset_cls
};
...
...
test/integration/numpy_patch.patch
View file @
ad0315d4
This diff is collapsed.
Click to expand it.
test/integration/numpy_test.py
View file @
ad0315d4
# script expects to find the numpy directory at the same level as the Pyston directory
import
os
import
sys
import
subprocess
import
shutil
"""
Using this test file.
We apply some patches on NumPy for some issues that we can't fix at the moment. The
patches are applied directly to the NumPy subrepository (test/lib/numpy). If you need,
you can make modifications in that folder directly for testing purposes. Just make sure
that everytime you do, run this script again, so that the contents of numpy_test_env_*
are updated (this is where the code and binaries that get tested are located).
Note that sometimes it can be a pain to run this script everytime you make a change,
as it does take a while. You can cd to the numpy_test_env_* directory and run the
binaries inside of that folder, which will be able to "see" the NumPy module. For example:
~/pyston/numpy_test_env_pyston_dbg$ gdb --args ./bin/python -c "import numpy as np; np.test()"
The /bin/python is the pyston executable so if you recompile pyston, you need to run this
script again to update it.
Currently this script is not running the NumPy tests since there are still crashes
happening. If you want to run the test, go to the bottom of the file and uncomment
the subprocess call to the test suite.
Some test cases in test/lib/numpy are commented out by the patch since they caused
a crash where the cause was not immediately obvious and I wanted to make progress. Those
will need to be uncommented at some point.
"""
def
print_progress_header
(
text
):
print
"
\
n
>>>"
print
">>> "
+
text
+
"..."
print
">>>"
ENV_NAME
=
"numpy_test_env_"
+
os
.
path
.
basename
(
sys
.
executable
)
DEPENDENCIES
=
[
"nose==1.3.7"
]
if
not
os
.
path
.
exists
(
ENV_NAME
)
or
os
.
stat
(
sys
.
executable
).
st_mtime
>
os
.
stat
(
ENV_NAME
+
"/bin/python"
).
st_mtime
:
print
"Creating virtualenv to install testing dependencies..."
...
...
@@ -14,6 +46,8 @@ if not os.path.exists(ENV_NAME) or os.stat(sys.executable).st_mtime > os.stat(EN
args
=
[
sys
.
executable
,
VIRTUALENV_SCRIPT
,
"-p"
,
sys
.
executable
,
ENV_NAME
]
print
"Running"
,
args
subprocess
.
check_call
(
args
)
subprocess
.
check_call
([
ENV_NAME
+
"/bin/pip"
,
"install"
]
+
DEPENDENCIES
)
except
:
print
"Error occurred; trying to remove partially-created directory"
ei
=
sys
.
exc_info
()
...
...
@@ -28,10 +62,8 @@ PYTHON_EXE = os.path.abspath(ENV_NAME + "/bin/python")
CYTHON_DIR
=
os
.
path
.
abspath
(
os
.
path
.
join
(
SRC_DIR
,
"Cython-0.22"
))
NUMPY_DIR
=
os
.
path
.
dirname
(
__file__
)
+
"/../lib/numpy"
print
"
\
n
>>>"
print
">>> Setting up Cython..."
print_progress_header
(
"Setting up Cython..."
)
if
not
os
.
path
.
exists
(
CYTHON_DIR
):
print
">>>"
url
=
"http://cython.org/release/Cython-0.22.tar.gz"
subprocess
.
check_call
([
"wget"
,
url
],
cwd
=
SRC_DIR
)
...
...
@@ -39,7 +71,7 @@ if not os.path.exists(CYTHON_DIR):
PATCH_FILE
=
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"Cython_0001-Pyston-change-we-don-t-support-custom-traceback-entr.patch"
))
subprocess
.
check_call
([
"patch"
,
"-p1"
,
"--input="
+
PATCH_FILE
],
cwd
=
CYTHON_DIR
)
print
"Applied Cython patch"
print
"
>>>
Applied Cython patch"
try
:
...
...
@@ -49,11 +81,8 @@ if not os.path.exists(CYTHON_DIR):
subprocess
.
check_call
([
"rm"
,
"-rf"
,
CYTHON_DIR
])
else
:
print
">>> Cython already installed."
print
">>>"
print
"
\
n
>>>"
print
">>> Patching NumPy..."
print
">>>"
print_progress_header
(
"Patching NumPy..."
)
NUMPY_PATCH_FILE
=
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"numpy_patch.patch"
))
try
:
cmd
=
[
"patch"
,
"-p1"
,
"--forward"
,
"-i"
,
NUMPY_PATCH_FILE
,
"-d"
,
NUMPY_DIR
]
...
...
@@ -63,14 +92,10 @@ except subprocess.CalledProcessError as e:
if
"Reversed (or previously applied) patch detected! Skipping patch"
not
in
e
.
output
:
raise
e
print
"
\
n
>>>"
print
">>> Setting up NumPy..."
print
">>>"
print_progress_header
(
"Setting up NumPy..."
)
subprocess
.
check_call
([
PYTHON_EXE
,
"setup.py"
,
"build"
],
cwd
=
NUMPY_DIR
)
print
"
\
n
>>>"
print
">>> Installing NumPy..."
print
">>>"
print_progress_header
(
"Installing NumPy..."
)
subprocess
.
check_call
([
PYTHON_EXE
,
"setup.py"
,
"install"
],
cwd
=
NUMPY_DIR
)
# From Wikipedia
...
...
@@ -110,19 +135,20 @@ m = mandelbrot(complex(400),complex(400))
print m
"""
print
"
\
n
>>>
"
print
">>> Running NumPy linear algebra test..."
print
">>>"
numpy_test
=
"import numpy as np; np.test(verbose=2)
"
print
_progress_header
(
"Running NumPy linear algebra test..."
)
subprocess
.
check_call
([
PYTHON_EXE
,
"-c"
,
script
],
cwd
=
CYTHON_DIR
)
print
"
\
n
>>>"
print
">>> Running NumPy mandelbrot test..."
print
">>>"
print_progress_header
(
"Running NumPy mandelbrot test..."
)
subprocess
.
check_call
([
PYTHON_EXE
,
"-c"
,
mandelbrot
],
cwd
=
CYTHON_DIR
)
print
"
\
n
>>>"
print
">>> Unpatching NumPy..."
print
">>>"
print_progress_header
(
"Running NumPy test suite..."
)
# Currently we crash running the test suite. Uncomment for testing or
# when all the crashes are fixed.
# subprocess.check_call([PYTHON_EXE, "-c", numpy_test], cwd=CYTHON_DIR)
print_progress_header
(
"Unpatching NumPy..."
)
cmd
=
[
"patch"
,
"-p1"
,
"--forward"
,
"-i"
,
NUMPY_PATCH_FILE
,
"-R"
,
"-d"
,
NUMPY_DIR
]
subprocess
.
check_output
(
cmd
,
stderr
=
subprocess
.
STDOUT
)
...
...
test/tests/descriptors.py
View file @
ad0315d4
...
...
@@ -58,3 +58,16 @@ def f2():
type
(
hd
.
x
).
__get__
=
get
print
hd
.
x
f2
()
def
f3
():
print
type
(
max
).
__dict__
[
'__name__'
].
__get__
(
max
,
1
)
try
:
type
(
max
).
__dict__
[
'__name__'
].
__set__
(
max
,
1
)
except
AttributeError
as
e
:
print
e
try
:
type
(
max
).
__dict__
[
'__name__'
].
__delete__
(
max
)
except
AttributeError
as
e
:
print
e
f3
()
test/tests/future_division.py
View file @
ad0315d4
...
...
@@ -19,3 +19,6 @@ test(3.0, 2)
test
(
3.0
,
2.0
)
test
(
3.0
,
-
2.0
)
test
(
-
3.0
,
-
2.0
)
test
(
1.0
+
1.0j
,
2
)
test
(
1.0
+
1.0j
,
2.0
)
test
(
1.0
+
1.0j
,
2.0j
)
test/tests/str_functions.py
View file @
ad0315d4
...
...
@@ -112,6 +112,31 @@ def test_just_funcs(s, w):
t5
=
s
.
rjust
(
w
)
t6
=
s
.
center
(
w
)
try
:
print
s
.
ljust
(
"a string"
)
except
TypeError
as
e
:
print
e
try
:
print
s
.
rjust
(
"a string"
)
except
TypeError
:
print
e
try
:
print
s
.
center
(
"a string"
)
except
TypeError
:
print
e
try
:
print
s
.
ljust
(
10
,
12345
)
except
TypeError
:
print
e
try
:
print
s
.
rjust
(
10
,
12345
)
except
TypeError
:
print
e
try
:
print
s
.
center
(
10
,
12345
)
except
TypeError
:
print
e
print
t1
,
t1
==
s
,
t1
is
s
,
type
(
t1
)
print
t2
,
t2
==
s
,
t2
is
s
,
type
(
t2
)
print
t3
,
t3
==
s
,
t3
is
s
,
type
(
t3
)
...
...
test/tests/tuples.py
View file @
ad0315d4
...
...
@@ -95,6 +95,11 @@ print (1, 2, 3) + ()
print
()
+
(
1
,
2
,
3
)
print
(
1
,
2
)
+
(
2
,
3
)
try
:
(
1
,
2
)
+
"a"
except
TypeError
as
e
:
print
"adding failed"
## __new__
print
tuple
()
print
tuple
((
1
,
3
,
7
,
42
))
...
...
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