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
a53ab1a8
Commit
a53ab1a8
authored
Apr 24, 2015
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #465 from kmod/virtualenv
bcrypt support
parents
7b71c6f8
578f9b6a
Changes
25
Show whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
966 additions
and
138 deletions
+966
-138
CMakeLists.txt
CMakeLists.txt
+1
-1
Makefile
Makefile
+4
-3
from_cpython/CMakeLists.txt
from_cpython/CMakeLists.txt
+1
-0
from_cpython/Include/Python.h
from_cpython/Include/Python.h
+1
-0
from_cpython/Include/cobject.h
from_cpython/Include/cobject.h
+91
-0
from_cpython/Include/object.h
from_cpython/Include/object.h
+1
-1
from_cpython/Include/objimpl.h
from_cpython/Include/objimpl.h
+1
-1
from_cpython/Include/pydebug.h
from_cpython/Include/pydebug.h
+8
-5
from_cpython/Lib/distutils/ccompiler.py
from_cpython/Lib/distutils/ccompiler.py
+1
-0
from_cpython/Objects/cobject.c
from_cpython/Objects/cobject.c
+173
-0
src/capi/abstract.cpp
src/capi/abstract.cpp
+47
-14
src/capi/object.cpp
src/capi/object.cpp
+438
-30
src/capi/typeobject.cpp
src/capi/typeobject.cpp
+73
-4
src/core/cfg.cpp
src/core/cfg.cpp
+2
-0
src/runtime/builtin_modules/builtins.cpp
src/runtime/builtin_modules/builtins.cpp
+5
-3
src/runtime/builtin_modules/thread.cpp
src/runtime/builtin_modules/thread.cpp
+1
-1
src/runtime/capi.cpp
src/runtime/capi.cpp
+38
-38
src/runtime/code.cpp
src/runtime/code.cpp
+16
-0
src/runtime/import.cpp
src/runtime/import.cpp
+32
-2
src/runtime/objmodel.cpp
src/runtime/objmodel.cpp
+1
-0
src/runtime/types.cpp
src/runtime/types.cpp
+1
-0
test/integration/virtualenv_bcrypt_test.py
test/integration/virtualenv_bcrypt_test.py
+0
-33
test/integration/virtualenv_test.py
test/integration/virtualenv_test.py
+5
-2
test/tests/cmp_test.py
test/tests/cmp_test.py
+23
-0
test/tests/code_test.py
test/tests/code_test.py
+2
-0
No files found.
CMakeLists.txt
View file @
a53ab1a8
...
...
@@ -207,7 +207,7 @@ add_test(NAME analysis_unittest COMMAND analysis_unittest)
add_test
(
NAME pyston_defaults COMMAND
${
PYTHON_EXE
}
${
CMAKE_SOURCE_DIR
}
/tools/tester.py -R ./pyston -j
${
TEST_THREADS
}
-a=-S -k
${
CMAKE_SOURCE_DIR
}
/test/tests
)
# we pass -I to cpython tests and skip failing ones b/c they are slooow otherwise
add_test
(
NAME pyston_defaults_cpython_tests COMMAND
${
PYTHON_EXE
}
${
CMAKE_SOURCE_DIR
}
/tools/tester.py -R ./pyston -j
${
TEST_THREADS
}
-a=-S -k --exit-code-only --skip-failing -t30
${
CMAKE_SOURCE_DIR
}
/test/cpython
)
add_test
(
NAME pyston_defaults_integration_tests COMMAND
${
PYTHON_EXE
}
${
CMAKE_SOURCE_DIR
}
/tools/tester.py -R ./pyston -j
${
TEST_THREADS
}
-a=-S -k --exit-code-only --skip-failing -t1
2
0
${
CMAKE_SOURCE_DIR
}
/test/integration
)
add_test
(
NAME pyston_defaults_integration_tests COMMAND
${
PYTHON_EXE
}
${
CMAKE_SOURCE_DIR
}
/tools/tester.py -R ./pyston -j
${
TEST_THREADS
}
-a=-S -k --exit-code-only --skip-failing -t1
8
0
${
CMAKE_SOURCE_DIR
}
/test/integration
)
add_test
(
NAME pyston_max_compilation_tier COMMAND
${
PYTHON_EXE
}
${
CMAKE_SOURCE_DIR
}
/tools/tester.py -R ./pyston -j
${
TEST_THREADS
}
-a=-O -a=-S -k
${
CMAKE_SOURCE_DIR
}
/test/tests
)
add_test
(
NAME pyston_old_parser COMMAND
${
PYTHON_EXE
}
${
CMAKE_SOURCE_DIR
}
/tools/tester.py -a=-x -R ./pyston -j1 -a=-n -a=-S -k
${
CMAKE_SOURCE_DIR
}
/test/tests
)
...
...
Makefile
View file @
a53ab1a8
...
...
@@ -366,6 +366,7 @@ STDOBJECT_SRCS := \
memoryobject.c
\
iterobject.c
\
bufferobject.c
\
cobject.c
\
$(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS
:=
\
...
...
@@ -494,7 +495,7 @@ check:
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_dbg
-j$(TEST_THREADS)
-k
-a
=
-S
$(TESTS_DIR)
$(ARGS)
@
# we pass -I to cpython tests & skip failing ones because they are sloooow otherwise
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_dbg
-j$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t30
$(TEST_DIR)
/cpython
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_dbg
-j$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t1
2
0
$(TEST_DIR)
/integration
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_dbg
-j$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t1
8
0
$(TEST_DIR)
/integration
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_dbg
-j$(TEST_THREADS)
-k
-a
=
-n
-a
=
-x
-a
=
-S
$(TESTS_DIR)
$(ARGS)
@
# skip -O for dbg
...
...
@@ -511,7 +512,7 @@ check:
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_release
-j$(TEST_THREADS)
-k
-a
=
-S
$(TESTS_DIR)
$(ARGS)
@
# we pass -I to cpython tests and skip failing ones because they are sloooow otherwise
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_release
-j$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
$(TEST_DIR)
/cpython
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_release
-j$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t
6
0
$(TEST_DIR)
/integration
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_release
-j$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t
12
0
$(TEST_DIR)
/integration
$(ARGS)
@
# skip -n for dbg
$(PYTHON)
$(TOOLS_DIR)/tester.py
-R
pyston_release
-j$(TEST_THREADS)
-k
-a
=
-O
-a
=
-x
-a
=
-S
$(TESTS_DIR)
$(ARGS)
...
...
@@ -956,7 +957,7 @@ check$1 test$1: $(PYTHON_EXE_DEPS) pyston$1 ext_pyston
$(PYTHON)
$(TOOLS_DIR)
/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-a
=
-S
-k
$(TESTS_DIR)
$(ARGS)
@
# we pass -I to cpython tests and skip failing ones because they are sloooow otherwise
$(PYTHON)
$(TOOLS_DIR)
/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-a
=
-S
-k
--exit-code-only
--skip-failing
-t30
$(TEST_DIR)
/cpython
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)
/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t1
2
0
$(TEST_DIR)
/integration
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)
/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-k
-a
=
-S
--exit-code-only
--skip-failing
-t1
8
0
$(TEST_DIR)
/integration
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)
/tester.py
-a
=
-x
-R
pyston
$1
-j
$(TEST_THREADS)
-a
=
-n
-a
=
-S
-k
$(TESTS_DIR)
$(ARGS)
$(PYTHON)
$(TOOLS_DIR)
/tester.py
-R
pyston
$1
-j
$(TEST_THREADS)
-a
=
-O
-a
=
-S
-k
$(TESTS_DIR)
$(ARGS)
...
...
from_cpython/CMakeLists.txt
View file @
a53ab1a8
...
...
@@ -76,6 +76,7 @@ file(GLOB_RECURSE STDOBJECT_SRCS Objects
bytearrayobject.c
bytes_methods.c
capsule.c
cobject.c
exceptions.c
iterobject.c
memoryobject.c
...
...
from_cpython/Include/Python.h
View file @
a53ab1a8
...
...
@@ -75,6 +75,7 @@
#include "methodobject.h"
#include "moduleobject.h"
#include "classobject.h"
#include "cobject.h"
#include "fileobject.h"
#include "pycapsule.h"
#include "traceback.h"
...
...
from_cpython/Include/cobject.h
0 → 100644
View file @
a53ab1a8
// This file is originally from CPython 2.7, with modifications for Pyston
/*
CObjects are marked Pending Deprecation as of Python 2.7.
The full schedule for 2.x is as follows:
- CObjects are marked Pending Deprecation in Python 2.7.
- CObjects will be marked Deprecated in Python 2.8
(if there is one).
- CObjects will be removed in Python 2.9 (if there is one).
Additionally, for the Python 3.x series:
- CObjects were marked Deprecated in Python 3.1.
- CObjects will be removed in Python 3.2.
You should switch all use of CObjects to capsules. Capsules
have a safer and more consistent API. For more information,
see Include/pycapsule.h, or read the "Capsules" topic in
the "Python/C API Reference Manual".
Python 2.7 no longer uses CObjects itself; all objects which
were formerly CObjects are now capsules. Note that this change
does not by itself break binary compatibility with extensions
built for previous versions of Python--PyCObject_AsVoidPtr()
has been changed to also understand capsules.
*/
/* original file header comment follows: */
/* C objects to be exported from one extension module to another.
C objects are used for communication between extension modules.
They provide a way for an extension module to export a C interface
to other extension modules, so that extension modules can use the
Python import mechanism to link to one another.
*/
#ifndef Py_COBJECT_H
#define Py_COBJECT_H
#ifdef __cplusplus
extern
"C"
{
#endif
PyAPI_DATA
(
PyTypeObject
)
PyCObject_Type
;
#define PyCObject_Check(op) (Py_TYPE(op) == &PyCObject_Type)
/* Create a PyCObject from a pointer to a C object and an optional
destructor function. If the second argument is non-null, then it
will be called with the first argument if and when the PyCObject is
destroyed.
*/
PyAPI_FUNC
(
PyObject
*
)
PyCObject_FromVoidPtr
(
void
*
cobj
,
void
(
*
destruct
)(
void
*
))
PYSTON_NOEXCEPT
;
/* Create a PyCObject from a pointer to a C object, a description object,
and an optional destructor function. If the third argument is non-null,
then it will be called with the first and second arguments if and when
the PyCObject is destroyed.
*/
PyAPI_FUNC
(
PyObject
*
)
PyCObject_FromVoidPtrAndDesc
(
void
*
cobj
,
void
*
desc
,
void
(
*
destruct
)(
void
*
,
void
*
))
PYSTON_NOEXCEPT
;
/* Retrieve a pointer to a C object from a PyCObject. */
PyAPI_FUNC
(
void
*
)
PyCObject_AsVoidPtr
(
PyObject
*
)
PYSTON_NOEXCEPT
;
/* Retrieve a pointer to a description object from a PyCObject. */
PyAPI_FUNC
(
void
*
)
PyCObject_GetDesc
(
PyObject
*
)
PYSTON_NOEXCEPT
;
/* Import a pointer to a C object from a module using a PyCObject. */
PyAPI_FUNC
(
void
*
)
PyCObject_Import
(
char
*
module_name
,
char
*
cobject_name
)
PYSTON_NOEXCEPT
;
/* Modify a C object. Fails (==0) if object has a destructor. */
PyAPI_FUNC
(
int
)
PyCObject_SetVoidPtr
(
PyObject
*
self
,
void
*
cobj
)
PYSTON_NOEXCEPT
;
typedef
struct
{
PyObject_HEAD
void
*
cobject
;
void
*
desc
;
void
(
*
destructor
)(
void
*
);
}
PyCObject
;
#ifdef __cplusplus
}
#endif
#endif
/* !Py_COBJECT_H */
from_cpython/Include/object.h
View file @
a53ab1a8
...
...
@@ -553,7 +553,7 @@ PyAPI_FUNC(int) PyNumber_CoerceEx(PyObject **, PyObject **) PYSTON_NOEXCEPT;
PyAPI_FUNC
(
void
)
PyObject_ClearWeakRefs
(
PyObject
*
)
PYSTON_NOEXCEPT
;
/* A slot function whose address we need to compare */
extern
int
_PyObject_SlotCompare
(
PyObject
*
,
PyObject
*
);
extern
int
_PyObject_SlotCompare
(
PyObject
*
,
PyObject
*
)
PYSTON_NOEXCEPT
;
/* Same as PyObject_Generic{Get,Set}Attr, but passing the attributes
dict as the last parameter. */
PyAPI_FUNC
(
PyObject
*
)
...
...
from_cpython/Include/objimpl.h
View file @
a53ab1a8
...
...
@@ -312,13 +312,13 @@ extern PyGC_Head *_PyGC_generation0;
(PyObject_IS_GC(obj) && \
(!PyTuple_CheckExact(obj) || _PyObject_GC_IS_TRACKED(obj)))
#endif
PyAPI_FUNC
(
PyObject
*
)
_PyObject_GC_Malloc
(
size_t
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyObject
*
)
_PyObject_GC_New
(
PyTypeObject
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
PyVarObject
*
)
_PyObject_GC_NewVar
(
PyTypeObject
*
,
Py_ssize_t
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
void
)
PyObject_GC_Track
(
void
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
void
)
PyObject_GC_UnTrack
(
void
*
)
PYSTON_NOEXCEPT
;
PyAPI_FUNC
(
void
)
PyObject_GC_Del
(
void
*
)
PYSTON_NOEXCEPT
;
#endif
#define PyType_IS_GC(t) ((t),1)
#define _PyObject_GC_TRACK(o) ((void)(o))
#define _PyObject_GC_UNTRACK(o) ((void)(o))
...
...
from_cpython/Include/pydebug.h
View file @
a53ab1a8
...
...
@@ -36,13 +36,16 @@ PyAPI_DATA(int) Py_HashRandomizationFlag;
// Pyston change: make Py_FatalError a macro so that it can access linenumber info, similar to assert:
//PyAPI_FUNC(void) Py_FatalError(const char *message) __attribute__((__noreturn__)) PYSTON_NOEXCEPT;
PyAPI_FUNC
(
void
)
_Py_FatalError
(
const
char
*
fmt
,
const
char
*
function
,
const
char
*
message
)
__attribute__
((
__noreturn__
));
#define _PYSTON_STRINGIFY(N) #N
#define PYSTON_STRINGIFY(N) _PYSTON_STRINGIFY(N)
// Defer the real work of Py_FatalError to a function, since some users expect it to be a real function,
// ie can be used as an expression (a do-while(0) loop would fail that).
#define Py_FatalError(message) \
do { \
fprintf(stderr, __FILE__ ":" PYSTON_STRINGIFY(__LINE__) ": %s: Fatal Python error: %s\n", __PRETTY_FUNCTION__, message); \
abort(); \
} while (0)
_Py_FatalError(__FILE__ \
":" PYSTON_STRINGIFY(__LINE__) ": %s: Fatal Python error: %s\n", \
__PRETTY_FUNCTION__, message)
#ifdef __cplusplus
}
...
...
from_cpython/Lib/distutils/ccompiler.py
View file @
a53ab1a8
...
...
@@ -371,6 +371,7 @@ class CCompiler:
cc_args
[:
0
]
=
[
'-g'
]
if
before
:
cc_args
[:
0
]
=
before
cc_args
=
cc_args
+
[
"-Werror=implicit-function-declaration"
]
return
cc_args
def
_fix_compile_args
(
self
,
output_dir
,
macros
,
include_dirs
):
...
...
from_cpython/Objects/cobject.c
0 → 100644
View file @
a53ab1a8
// This file is originally from CPython 2.7, with modifications for Pyston
/* Wrap void* pointers to be passed between C modules */
#include "Python.h"
/* Declarations for objects of type PyCObject */
typedef
void
(
*
destructor1
)(
void
*
);
typedef
void
(
*
destructor2
)(
void
*
,
void
*
);
static
int
cobject_deprecation_warning
(
void
)
{
return
PyErr_WarnPy3k
(
"CObject type is not supported in 3.x. "
"Please use capsule objects instead."
,
1
);
}
PyObject
*
PyCObject_FromVoidPtr
(
void
*
cobj
,
void
(
*
destr
)(
void
*
))
{
PyCObject
*
self
;
if
(
cobject_deprecation_warning
())
{
return
NULL
;
}
self
=
PyObject_NEW
(
PyCObject
,
&
PyCObject_Type
);
if
(
self
==
NULL
)
return
NULL
;
self
->
cobject
=
cobj
;
self
->
destructor
=
destr
;
self
->
desc
=
NULL
;
return
(
PyObject
*
)
self
;
}
PyObject
*
PyCObject_FromVoidPtrAndDesc
(
void
*
cobj
,
void
*
desc
,
void
(
*
destr
)(
void
*
,
void
*
))
{
PyCObject
*
self
;
if
(
cobject_deprecation_warning
())
{
return
NULL
;
}
if
(
!
desc
)
{
PyErr_SetString
(
PyExc_TypeError
,
"PyCObject_FromVoidPtrAndDesc called with null"
" description"
);
return
NULL
;
}
self
=
PyObject_NEW
(
PyCObject
,
&
PyCObject_Type
);
if
(
self
==
NULL
)
return
NULL
;
self
->
cobject
=
cobj
;
self
->
destructor
=
(
destructor1
)
destr
;
self
->
desc
=
desc
;
return
(
PyObject
*
)
self
;
}
void
*
PyCObject_AsVoidPtr
(
PyObject
*
self
)
{
if
(
self
)
{
if
(
PyCapsule_CheckExact
(
self
))
{
const
char
*
name
=
PyCapsule_GetName
(
self
);
return
(
void
*
)
PyCapsule_GetPointer
(
self
,
name
);
}
if
(
self
->
ob_type
==
&
PyCObject_Type
)
return
((
PyCObject
*
)
self
)
->
cobject
;
PyErr_SetString
(
PyExc_TypeError
,
"PyCObject_AsVoidPtr with non-C-object"
);
}
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_TypeError
,
"PyCObject_AsVoidPtr called with null pointer"
);
return
NULL
;
}
void
*
PyCObject_GetDesc
(
PyObject
*
self
)
{
if
(
self
)
{
if
(
self
->
ob_type
==
&
PyCObject_Type
)
return
((
PyCObject
*
)
self
)
->
desc
;
PyErr_SetString
(
PyExc_TypeError
,
"PyCObject_GetDesc with non-C-object"
);
}
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_TypeError
,
"PyCObject_GetDesc called with null pointer"
);
return
NULL
;
}
void
*
PyCObject_Import
(
char
*
module_name
,
char
*
name
)
{
PyObject
*
m
,
*
c
;
void
*
r
=
NULL
;
if
((
m
=
PyImport_ImportModule
(
module_name
)))
{
if
((
c
=
PyObject_GetAttrString
(
m
,
name
)))
{
r
=
PyCObject_AsVoidPtr
(
c
);
Py_DECREF
(
c
);
}
Py_DECREF
(
m
);
}
return
r
;
}
int
PyCObject_SetVoidPtr
(
PyObject
*
self
,
void
*
cobj
)
{
PyCObject
*
cself
=
(
PyCObject
*
)
self
;
if
(
cself
==
NULL
||
!
PyCObject_Check
(
cself
)
||
cself
->
destructor
!=
NULL
)
{
PyErr_SetString
(
PyExc_TypeError
,
"Invalid call to PyCObject_SetVoidPtr"
);
return
0
;
}
cself
->
cobject
=
cobj
;
return
1
;
}
static
void
PyCObject_dealloc
(
PyCObject
*
self
)
{
if
(
self
->
destructor
)
{
if
(
self
->
desc
)
((
destructor2
)(
self
->
destructor
))(
self
->
cobject
,
self
->
desc
);
else
(
self
->
destructor
)(
self
->
cobject
);
}
PyObject_DEL
(
self
);
}
PyDoc_STRVAR
(
PyCObject_Type__doc__
,
"C objects to be exported from one extension module to another
\n
\
\n
\
C objects are used for communication between extension modules. They
\n
\
provide a way for an extension module to export a C interface to other
\n
\
extension modules, so that extension modules can use the Python import
\n
\
mechanism to link to one another."
);
PyTypeObject
PyCObject_Type
=
{
PyVarObject_HEAD_INIT
(
/* Pyston change: &PyType_Type */
NULL
,
0
)
"PyCObject"
,
/*tp_name*/
sizeof
(
PyCObject
),
/*tp_basicsize*/
0
,
/*tp_itemsize*/
/* methods */
(
destructor
)
PyCObject_dealloc
,
/*tp_dealloc*/
0
,
/*tp_print*/
0
,
/*tp_getattr*/
0
,
/*tp_setattr*/
0
,
/*tp_compare*/
0
,
/*tp_repr*/
0
,
/*tp_as_number*/
0
,
/*tp_as_sequence*/
0
,
/*tp_as_mapping*/
0
,
/*tp_hash*/
0
,
/*tp_call*/
0
,
/*tp_str*/
0
,
/*tp_getattro*/
0
,
/*tp_setattro*/
0
,
/*tp_as_buffer*/
0
,
/*tp_flags*/
PyCObject_Type__doc__
/*tp_doc*/
};
src/capi/abstract.cpp
View file @
a53ab1a8
...
...
@@ -27,6 +27,31 @@
namespace
pyston
{
static
PyObject
*
type_error
(
const
char
*
msg
,
PyObject
*
obj
)
noexcept
{
PyErr_Format
(
PyExc_TypeError
,
msg
,
Py_TYPE
(
obj
)
->
tp_name
);
return
NULL
;
}
static
PyObject
*
null_error
(
void
)
noexcept
{
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_SystemError
,
"null argument to internal routine"
);
return
NULL
;
}
extern
"C"
int
PyObject_Cmp
(
PyObject
*
o1
,
PyObject
*
o2
,
int
*
result
)
noexcept
{
int
r
;
if
(
o1
==
NULL
||
o2
==
NULL
)
{
null_error
();
return
-
1
;
}
r
=
PyObject_Compare
(
o1
,
o2
);
if
(
PyErr_Occurred
())
return
-
1
;
*
result
=
r
;
return
0
;
}
extern
"C"
Py_ssize_t
_PyObject_LengthHint
(
PyObject
*
o
,
Py_ssize_t
defaultvalue
)
noexcept
{
static
PyObject
*
hintstrobj
=
NULL
;
PyObject
*
ro
,
*
hintmeth
;
...
...
@@ -227,17 +252,6 @@ extern "C" void PyBuffer_Release(Py_buffer* view) noexcept {
view
->
obj
=
NULL
;
}
static
PyObject
*
type_error
(
const
char
*
msg
,
PyObject
*
obj
)
noexcept
{
PyErr_Format
(
PyExc_TypeError
,
msg
,
Py_TYPE
(
obj
)
->
tp_name
);
return
NULL
;
}
static
PyObject
*
null_error
(
void
)
noexcept
{
if
(
!
PyErr_Occurred
())
PyErr_SetString
(
PyExc_SystemError
,
"null argument to internal routine"
);
return
NULL
;
}
static
PyObject
*
objargs_mktuple
(
va_list
va
)
noexcept
{
int
i
,
n
=
0
;
va_list
countva
;
...
...
@@ -1516,9 +1530,28 @@ extern "C" int PyNumber_Coerce(PyObject**, PyObject**) noexcept {
return
-
1
;
}
extern
"C"
int
PyNumber_CoerceEx
(
PyObject
**
,
PyObject
**
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
-
1
;
extern
"C"
int
PyNumber_CoerceEx
(
PyObject
**
pv
,
PyObject
**
pw
)
noexcept
{
PyObject
*
v
=
*
pv
;
PyObject
*
w
=
*
pw
;
int
res
;
/* Shortcut only for old-style types */
if
(
v
->
cls
==
w
->
cls
&&
!
PyType_HasFeature
(
v
->
cls
,
Py_TPFLAGS_CHECKTYPES
))
{
Py_INCREF
(
v
);
Py_INCREF
(
w
);
return
0
;
}
if
(
v
->
cls
->
tp_as_number
&&
v
->
cls
->
tp_as_number
->
nb_coerce
)
{
res
=
(
*
v
->
cls
->
tp_as_number
->
nb_coerce
)(
pv
,
pw
);
if
(
res
<=
0
)
return
res
;
}
if
(
w
->
cls
->
tp_as_number
&&
w
->
cls
->
tp_as_number
->
nb_coerce
)
{
res
=
(
*
w
->
cls
->
tp_as_number
->
nb_coerce
)(
pw
,
pv
);
if
(
res
<=
0
)
return
res
;
}
return
1
;
}
extern
"C"
PyObject
*
_PyNumber_ConvertIntegralToInt
(
PyObject
*
integral
,
const
char
*
error_format
)
noexcept
{
...
...
src/capi/object.cpp
View file @
a53ab1a8
...
...
@@ -472,31 +472,6 @@ extern "C" int PyObject_AsWriteBuffer(PyObject* obj, void** buffer, Py_ssize_t*
Py_FatalError
(
"unimplemented"
);
}
/* Return -1 if error; 1 if v op w; 0 if not (v op w). */
extern
"C"
int
PyObject_RichCompareBool
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
{
PyObject
*
res
;
int
ok
;
/* Quick result when objects are the same.
Guarantees that identity implies equality. */
if
(
v
==
w
)
{
if
(
op
==
Py_EQ
)
return
1
;
else
if
(
op
==
Py_NE
)
return
0
;
}
res
=
PyObject_RichCompare
(
v
,
w
,
op
);
if
(
res
==
NULL
)
return
-
1
;
if
(
PyBool_Check
(
res
))
ok
=
(
res
==
Py_True
);
else
ok
=
PyObject_IsTrue
(
res
);
Py_DECREF
(
res
);
return
ok
;
}
// I'm not sure how we can support this one:
extern
"C"
PyObject
**
_PyObject_GetDictPtr
(
PyObject
*
obj
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
...
...
@@ -564,10 +539,443 @@ extern "C" void Py_ReprLeave(PyObject* obj) noexcept {
}
}
extern
"C"
int
PyObject_Compare
(
PyObject
*
o1
,
PyObject
*
o2
)
noexcept
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
// 'On error, the value returned is undefined; use PyErr_Occurred() to detect an error.'
// - https://docs.python.org/2/c-api/object.html
return
0xdeadbeef
;
/* Helper to warn about deprecated tp_compare return values. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w.
(This function cannot return 2.)
*/
static
int
adjust_tp_compare
(
int
c
)
{
if
(
PyErr_Occurred
())
{
if
(
c
!=
-
1
&&
c
!=
-
2
)
{
PyObject
*
t
,
*
v
,
*
tb
;
PyErr_Fetch
(
&
t
,
&
v
,
&
tb
);
if
(
PyErr_Warn
(
PyExc_RuntimeWarning
,
"tp_compare didn't return -1 or -2 "
"for exception"
)
<
0
)
{
Py_XDECREF
(
t
);
Py_XDECREF
(
v
);
Py_XDECREF
(
tb
);
}
else
PyErr_Restore
(
t
,
v
,
tb
);
}
return
-
2
;
}
else
if
(
c
<
-
1
||
c
>
1
)
{
if
(
PyErr_Warn
(
PyExc_RuntimeWarning
,
"tp_compare didn't return -1, 0 or 1"
)
<
0
)
return
-
2
;
else
return
c
<
-
1
?
-
1
:
1
;
}
else
{
assert
(
c
>=
-
1
&&
c
<=
1
);
return
c
;
}
}
/* Macro to get the tp_richcompare field of a type if defined */
#define RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) ? (t)->tp_richcompare : NULL)
/* Map rich comparison operators to their swapped version, e.g. LT --> GT */
extern
"C"
{
int
_Py_SwappedOp
[]
=
{
Py_GT
,
Py_GE
,
Py_EQ
,
Py_NE
,
Py_LT
,
Py_LE
};
}
/* Try a genuine rich comparison, returning an object. Return:
NULL for exception;
NotImplemented if this particular rich comparison is not implemented or
undefined;
some object not equal to NotImplemented if it is implemented
(this latter object may not be a Boolean).
*/
static
PyObject
*
try_rich_compare
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
{
richcmpfunc
f
;
PyObject
*
res
;
if
(
v
->
cls
!=
w
->
cls
&&
PyType_IsSubtype
(
w
->
cls
,
v
->
cls
)
&&
(
f
=
RICHCOMPARE
(
w
->
cls
))
!=
NULL
)
{
res
=
(
*
f
)(
w
,
v
,
_Py_SwappedOp
[
op
]);
if
(
res
!=
Py_NotImplemented
)
return
res
;
Py_DECREF
(
res
);
}
if
((
f
=
RICHCOMPARE
(
v
->
cls
))
!=
NULL
)
{
res
=
(
*
f
)(
v
,
w
,
op
);
if
(
res
!=
Py_NotImplemented
)
return
res
;
Py_DECREF
(
res
);
}
if
((
f
=
RICHCOMPARE
(
w
->
cls
))
!=
NULL
)
{
return
(
*
f
)(
w
,
v
,
_Py_SwappedOp
[
op
]);
}
res
=
Py_NotImplemented
;
Py_INCREF
(
res
);
return
res
;
}
/* Try a genuine rich comparison, returning an int. Return:
-1 for exception (including the case where try_rich_compare() returns an
object that's not a Boolean);
0 if the outcome is false;
1 if the outcome is true;
2 if this particular rich comparison is not implemented or undefined.
*/
static
int
try_rich_compare_bool
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
{
PyObject
*
res
;
int
ok
;
if
(
RICHCOMPARE
(
v
->
cls
)
==
NULL
&&
RICHCOMPARE
(
w
->
cls
)
==
NULL
)
return
2
;
/* Shortcut, avoid INCREF+DECREF */
res
=
try_rich_compare
(
v
,
w
,
op
);
if
(
res
==
NULL
)
return
-
1
;
if
(
res
==
Py_NotImplemented
)
{
Py_DECREF
(
res
);
return
2
;
}
ok
=
PyObject_IsTrue
(
res
);
Py_DECREF
(
res
);
return
ok
;
}
/* Try rich comparisons to determine a 3-way comparison. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular rich comparison is not implemented or undefined.
*/
static
int
try_rich_to_3way_compare
(
PyObject
*
v
,
PyObject
*
w
)
{
static
struct
{
int
op
;
int
outcome
;
}
tries
[
3
]
=
{
/* Try this operator, and if it is true, use this outcome: */
{
Py_EQ
,
0
},
{
Py_LT
,
-
1
},
{
Py_GT
,
1
},
};
int
i
;
if
(
RICHCOMPARE
(
v
->
cls
)
==
NULL
&&
RICHCOMPARE
(
w
->
cls
)
==
NULL
)
return
2
;
/* Shortcut */
for
(
i
=
0
;
i
<
3
;
i
++
)
{
switch
(
try_rich_compare_bool
(
v
,
w
,
tries
[
i
].
op
))
{
case
-
1
:
return
-
2
;
case
1
:
return
tries
[
i
].
outcome
;
}
}
return
2
;
}
/* Try a 3-way comparison, returning an int. Return:
-2 for an exception;
-1 if v < w;
0 if v == w;
1 if v > w;
2 if this particular 3-way comparison is not implemented or undefined.
*/
static
int
try_3way_compare
(
PyObject
*
v
,
PyObject
*
w
)
{
int
c
;
cmpfunc
f
;
/* Comparisons involving instances are given to instance_compare,
which has the same return conventions as this function. */
f
=
v
->
cls
->
tp_compare
;
if
(
PyInstance_Check
(
v
))
return
(
*
f
)(
v
,
w
);
if
(
PyInstance_Check
(
w
))
return
(
*
w
->
cls
->
tp_compare
)(
v
,
w
);
/* If both have the same (non-NULL) tp_compare, use it. */
if
(
f
!=
NULL
&&
f
==
w
->
cls
->
tp_compare
)
{
c
=
(
*
f
)(
v
,
w
);
return
adjust_tp_compare
(
c
);
}
/* If either tp_compare is _PyObject_SlotCompare, that's safe. */
if
(
f
==
_PyObject_SlotCompare
||
w
->
cls
->
tp_compare
==
_PyObject_SlotCompare
)
return
_PyObject_SlotCompare
(
v
,
w
);
/* If we're here, v and w,
a) are not instances;
b) have different types or a type without tp_compare; and
c) don't have a user-defined tp_compare.
tp_compare implementations in C assume that both arguments
have their type, so we give up if the coercion fails or if
it yields types which are still incompatible (which can
happen with a user-defined nb_coerce).
*/
c
=
PyNumber_CoerceEx
(
&
v
,
&
w
);
if
(
c
<
0
)
return
-
2
;
if
(
c
>
0
)
return
2
;
f
=
v
->
cls
->
tp_compare
;
if
(
f
!=
NULL
&&
f
==
w
->
cls
->
tp_compare
)
{
c
=
(
*
f
)(
v
,
w
);
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
adjust_tp_compare
(
c
);
}
/* No comparison defined */
Py_DECREF
(
v
);
Py_DECREF
(
w
);
return
2
;
}
/* Final fallback 3-way comparison, returning an int. Return:
-2 if an error occurred;
-1 if v < w;
0 if v == w;
1 if v > w.
*/
static
int
default_3way_compare
(
PyObject
*
v
,
PyObject
*
w
)
{
int
c
;
const
char
*
vname
,
*
wname
;
if
(
v
->
cls
==
w
->
cls
)
{
/* When comparing these pointers, they must be cast to
* integer types (i.e. Py_uintptr_t, our spelling of C9X's
* uintptr_t). ANSI specifies that pointer compares other
* than == and != to non-related structures are undefined.
*/
Py_uintptr_t
vv
=
(
Py_uintptr_t
)
v
;
Py_uintptr_t
ww
=
(
Py_uintptr_t
)
w
;
return
(
vv
<
ww
)
?
-
1
:
(
vv
>
ww
)
?
1
:
0
;
}
/* None is smaller than anything */
if
(
v
==
Py_None
)
return
-
1
;
if
(
w
==
Py_None
)
return
1
;
/* different type: compare type names; numbers are smaller */
if
(
PyNumber_Check
(
v
))
vname
=
""
;
else
vname
=
v
->
cls
->
tp_name
;
if
(
PyNumber_Check
(
w
))
wname
=
""
;
else
wname
=
w
->
cls
->
tp_name
;
c
=
strcmp
(
vname
,
wname
);
if
(
c
<
0
)
return
-
1
;
if
(
c
>
0
)
return
1
;
/* Same type name, or (more likely) incomparable numeric types */
return
((
Py_uintptr_t
)(
v
->
cls
)
<
(
Py_uintptr_t
)(
w
->
cls
))
?
-
1
:
1
;
}
/* Do a 3-way comparison, by hook or by crook. Return:
-2 for an exception (but see below);
-1 if v < w;
0 if v == w;
1 if v > w;
BUT: if the object implements a tp_compare function, it returns
whatever this function returns (whether with an exception or not).
*/
static
int
do_cmp
(
PyObject
*
v
,
PyObject
*
w
)
{
int
c
;
cmpfunc
f
;
if
(
v
->
cls
==
w
->
cls
&&
(
f
=
v
->
cls
->
tp_compare
)
!=
NULL
)
{
c
=
(
*
f
)(
v
,
w
);
if
(
PyInstance_Check
(
v
))
{
/* Instance tp_compare has a different signature.
But if it returns undefined we fall through. */
if
(
c
!=
2
)
return
c
;
/* Else fall through to try_rich_to_3way_compare() */
}
else
return
adjust_tp_compare
(
c
);
}
/* We only get here if one of the following is true:
a) v and w have different types
b) v and w have the same type, which doesn't have tp_compare
c) v and w are instances, and either __cmp__ is not defined or
__cmp__ returns NotImplemented
*/
c
=
try_rich_to_3way_compare
(
v
,
w
);
if
(
c
<
2
)
return
c
;
c
=
try_3way_compare
(
v
,
w
);
if
(
c
<
2
)
return
c
;
return
default_3way_compare
(
v
,
w
);
}
/* Compare v to w. Return
-1 if v < w or exception (PyErr_Occurred() true in latter case).
0 if v == w.
1 if v > w.
XXX The docs (C API manual) say the return value is undefined in case
XXX of error.
*/
extern
"C"
int
PyObject_Compare
(
PyObject
*
v
,
PyObject
*
w
)
noexcept
{
int
result
;
if
(
v
==
NULL
||
w
==
NULL
)
{
PyErr_BadInternalCall
();
return
-
1
;
}
if
(
v
==
w
)
return
0
;
if
(
Py_EnterRecursiveCall
(
" in cmp"
))
return
-
1
;
result
=
do_cmp
(
v
,
w
);
Py_LeaveRecursiveCall
();
return
result
<
0
?
-
1
:
result
;
}
/* Return (new reference to) Py_True or Py_False. */
static
PyObject
*
convert_3way_to_object
(
int
op
,
int
c
)
noexcept
{
PyObject
*
result
;
switch
(
op
)
{
case
Py_LT
:
c
=
c
<
0
;
break
;
case
Py_LE
:
c
=
c
<=
0
;
break
;
case
Py_EQ
:
c
=
c
==
0
;
break
;
case
Py_NE
:
c
=
c
!=
0
;
break
;
case
Py_GT
:
c
=
c
>
0
;
break
;
case
Py_GE
:
c
=
c
>=
0
;
break
;
}
result
=
c
?
Py_True
:
Py_False
;
Py_INCREF
(
result
);
return
result
;
}
/* We want a rich comparison but don't have one. Try a 3-way cmp instead.
Return
NULL if error
Py_True if v op w
Py_False if not (v op w)
*/
static
PyObject
*
try_3way_to_rich_compare
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
{
int
c
;
c
=
try_3way_compare
(
v
,
w
);
if
(
c
>=
2
)
{
/* Py3K warning if types are not equal and comparison isn't == or != */
if
(
Py_Py3kWarningFlag
&&
v
->
cls
!=
w
->
cls
&&
op
!=
Py_EQ
&&
op
!=
Py_NE
&&
PyErr_WarnEx
(
PyExc_DeprecationWarning
,
"comparing unequal types not supported "
"in 3.x"
,
1
)
<
0
)
{
return
NULL
;
}
c
=
default_3way_compare
(
v
,
w
);
}
if
(
c
<=
-
2
)
return
NULL
;
return
convert_3way_to_object
(
op
,
c
);
}
/* Do rich comparison on v and w. Return
NULL if error
Else a new reference to an object other than Py_NotImplemented, usually(?):
Py_True if v op w
Py_False if not (v op w)
*/
static
PyObject
*
do_richcmp
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
{
PyObject
*
res
;
res
=
try_rich_compare
(
v
,
w
,
op
);
if
(
res
!=
Py_NotImplemented
)
return
res
;
Py_DECREF
(
res
);
return
try_3way_to_rich_compare
(
v
,
w
,
op
);
}
/* Return:
NULL for exception;
some object not equal to NotImplemented if it is implemented
(this latter object may not be a Boolean).
*/
extern
"C"
PyObject
*
PyObject_RichCompare
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
{
PyObject
*
res
;
assert
(
Py_LT
<=
op
&&
op
<=
Py_GE
);
if
(
Py_EnterRecursiveCall
(
" in cmp"
))
return
NULL
;
/* If the types are equal, and not old-style instances, try to
get out cheap (don't bother with coercions etc.). */
if
(
v
->
cls
==
w
->
cls
&&
!
PyInstance_Check
(
v
))
{
cmpfunc
fcmp
;
richcmpfunc
frich
=
RICHCOMPARE
(
v
->
cls
);
/* If the type has richcmp, try it first. try_rich_compare
tries it two-sided, which is not needed since we've a
single type only. */
if
(
frich
!=
NULL
)
{
res
=
(
*
frich
)(
v
,
w
,
op
);
if
(
res
!=
Py_NotImplemented
)
goto
Done
;
Py_DECREF
(
res
);
}
/* No richcmp, or this particular richmp not implemented.
Try 3-way cmp. */
fcmp
=
v
->
cls
->
tp_compare
;
if
(
fcmp
!=
NULL
)
{
int
c
=
(
*
fcmp
)(
v
,
w
);
c
=
adjust_tp_compare
(
c
);
if
(
c
==
-
2
)
{
res
=
NULL
;
goto
Done
;
}
res
=
convert_3way_to_object
(
op
,
c
);
goto
Done
;
}
}
/* Fast path not taken, or couldn't deliver a useful result. */
res
=
do_richcmp
(
v
,
w
,
op
);
Done:
Py_LeaveRecursiveCall
();
return
res
;
}
/* Return -1 if error; 1 if v op w; 0 if not (v op w). */
extern
"C"
int
PyObject_RichCompareBool
(
PyObject
*
v
,
PyObject
*
w
,
int
op
)
noexcept
{
PyObject
*
res
;
int
ok
;
/* Quick result when objects are the same.
Guarantees that identity implies equality. */
if
(
v
==
w
)
{
if
(
op
==
Py_EQ
)
return
1
;
else
if
(
op
==
Py_NE
)
return
0
;
}
res
=
PyObject_RichCompare
(
v
,
w
,
op
);
if
(
res
==
NULL
)
return
-
1
;
if
(
PyBool_Check
(
res
))
ok
=
(
res
==
Py_True
);
else
ok
=
PyObject_IsTrue
(
res
);
Py_DECREF
(
res
);
return
ok
;
}
}
src/capi/typeobject.cpp
View file @
a53ab1a8
...
...
@@ -461,6 +461,26 @@ static PyObject* wrap_delitem(PyObject* self, PyObject* args, void* wrapped) noe
return
Py_None
;
}
static
PyObject
*
wrap_cmpfunc
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
)
noexcept
{
cmpfunc
func
=
(
cmpfunc
)
wrapped
;
int
res
;
PyObject
*
other
;
if
(
!
check_num_args
(
args
,
1
))
return
NULL
;
other
=
PyTuple_GET_ITEM
(
args
,
0
);
if
(
Py_TYPE
(
other
)
->
tp_compare
!=
func
&&
!
PyType_IsSubtype
(
Py_TYPE
(
other
),
Py_TYPE
(
self
)))
{
PyErr_Format
(
PyExc_TypeError
,
"%s.__cmp__(x,y) requires y to be a '%s', not a '%s'"
,
Py_TYPE
(
self
)
->
tp_name
,
Py_TYPE
(
self
)
->
tp_name
,
Py_TYPE
(
other
)
->
tp_name
);
return
NULL
;
}
res
=
(
*
func
)(
self
,
other
);
if
(
PyErr_Occurred
())
return
NULL
;
return
PyInt_FromLong
((
long
)
res
);
}
static
PyObject
*
wrap_init
(
PyObject
*
self
,
PyObject
*
args
,
void
*
wrapped
,
PyObject
*
kwds
)
noexcept
{
initproc
func
=
(
initproc
)
wrapped
;
...
...
@@ -565,7 +585,57 @@ static PyObject* call_maybe(PyObject* o, const char* name, PyObject** nameobj, c
return
retval
;
}
PyObject
*
slot_tp_repr
(
PyObject
*
self
)
noexcept
{
static
int
half_compare
(
PyObject
*
self
,
PyObject
*
other
)
noexcept
{
PyObject
*
func
,
*
args
,
*
res
;
static
PyObject
*
cmp_str
;
Py_ssize_t
c
;
func
=
lookup_method
(
self
,
"__cmp__"
,
&
cmp_str
);
if
(
func
==
NULL
)
{
PyErr_Clear
();
}
else
{
args
=
PyTuple_Pack
(
1
,
other
);
if
(
args
==
NULL
)
res
=
NULL
;
else
{
res
=
PyObject_Call
(
func
,
args
,
NULL
);
Py_DECREF
(
args
);
}
Py_DECREF
(
func
);
if
(
res
!=
Py_NotImplemented
)
{
if
(
res
==
NULL
)
return
-
2
;
c
=
PyInt_AsLong
(
res
);
Py_DECREF
(
res
);
if
(
c
==
-
1
&&
PyErr_Occurred
())
return
-
2
;
return
(
c
<
0
)
?
-
1
:
(
c
>
0
)
?
1
:
0
;
}
Py_DECREF
(
res
);
}
return
2
;
}
/* This slot is published for the benefit of try_3way_compare in object.c */
extern
"C"
int
_PyObject_SlotCompare
(
PyObject
*
self
,
PyObject
*
other
)
noexcept
{
int
c
;
if
(
Py_TYPE
(
self
)
->
tp_compare
==
_PyObject_SlotCompare
)
{
c
=
half_compare
(
self
,
other
);
if
(
c
<=
1
)
return
c
;
}
if
(
Py_TYPE
(
other
)
->
tp_compare
==
_PyObject_SlotCompare
)
{
c
=
half_compare
(
other
,
self
);
if
(
c
<
-
1
)
return
-
2
;
if
(
c
<=
1
)
return
-
c
;
}
return
(
void
*
)
self
<
(
void
*
)
other
?
-
1
:
(
void
*
)
self
>
(
void
*
)
other
?
1
:
0
;
}
static
PyObject
*
slot_tp_repr
(
PyObject
*
self
)
noexcept
{
try
{
return
repr
(
self
);
}
catch
(
ExcInfo
e
)
{
...
...
@@ -574,7 +644,7 @@ PyObject* slot_tp_repr(PyObject* self) noexcept {
}
}
PyObject
*
slot_tp_str
(
PyObject
*
self
)
noexcept
{
static
PyObject
*
slot_tp_str
(
PyObject
*
self
)
noexcept
{
try
{
return
str
(
self
);
}
catch
(
ExcInfo
e
)
{
...
...
@@ -1264,6 +1334,7 @@ static slotdef slotdefs[]
TPSLOT
(
"__getattr__"
,
tp_getattr
,
NULL
,
NULL
,
""
),
TPSLOT
(
"__setattr__"
,
tp_setattr
,
NULL
,
NULL
,
""
),
TPSLOT
(
"__delattr__"
,
tp_setattr
,
NULL
,
NULL
,
""
),
TPSLOT
(
"__cmp__"
,
tp_compare
,
_PyObject_SlotCompare
,
wrap_cmpfunc
,
"x.__cmp__(y) <==> cmp(x,y)"
),
TPSLOT
(
"__repr__"
,
tp_repr
,
slot_tp_repr
,
wrap_unaryfunc
,
"x.__repr__() <==> repr(x)"
),
TPSLOT
(
"__hash__"
,
tp_hash
,
slot_tp_hash
,
wrap_hashfunc
,
"x.__hash__() <==> hash(x)"
),
...
...
@@ -2596,8 +2667,6 @@ extern "C" int PyType_Ready(PyTypeObject* cls) noexcept {
// unhandled fields:
RELEASE_ASSERT
(
cls
->
tp_compare
==
NULL
,
""
);
RELEASE_ASSERT
(
cls
->
tp_getattro
==
NULL
||
cls
->
tp_getattro
==
PyObject_GenericGetAttr
,
""
);
int
ALLOWABLE_FLAGS
=
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
|
Py_TPFLAGS_HAVE_GC
|
Py_TPFLAGS_CHECKTYPES
|
Py_TPFLAGS_HAVE_NEWBUFFER
;
ALLOWABLE_FLAGS
|=
Py_TPFLAGS_INT_SUBCLASS
|
Py_TPFLAGS_LONG_SUBCLASS
|
Py_TPFLAGS_LIST_SUBCLASS
...
...
src/core/cfg.cpp
View file @
a53ab1a8
...
...
@@ -1427,6 +1427,8 @@ public:
bool
visit_functiondef
(
AST_FunctionDef
*
node
)
override
{
auto
def
=
new
AST_FunctionDef
();
def
->
lineno
=
node
->
lineno
;
def
->
col_offset
=
node
->
col_offset
;
def
->
name
=
node
->
name
;
def
->
body
=
node
->
body
;
// expensive vector copy
// Decorators are evaluated before the defaults, so this *must* go before remapArguments().
...
...
src/runtime/builtin_modules/builtins.cpp
View file @
a53ab1a8
...
...
@@ -969,9 +969,11 @@ Box* builtinRound(Box* _number, Box* _ndigits) {
throwCAPIException
();
}
Box
*
builtinCmp
(
Box
*
lhs
,
Box
*
rhs
)
{
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
Box
*
builtinCmp
(
Box
*
a
,
Box
*
b
)
{
int
c
;
if
(
PyObject_Cmp
(
a
,
b
,
&
c
)
<
0
)
throwCAPIException
();
return
PyInt_FromLong
((
long
)
c
);
}
Box
*
builtinApply
(
Box
*
func
,
Box
*
args
,
Box
*
keywords
)
{
...
...
src/runtime/builtin_modules/thread.cpp
View file @
a53ab1a8
...
...
@@ -105,7 +105,7 @@ public:
RELEASE_ASSERT
(
_self
->
cls
==
thread_lock_cls
,
""
);
BoxedThreadLock
*
self
=
static_cast
<
BoxedThreadLock
*>
(
_self
);
RELEASE_ASSERT
(
_waitflag
->
cls
==
int_cls
,
""
);
RELEASE_ASSERT
(
isSubclass
(
_waitflag
->
cls
,
int_cls
)
,
""
);
int
waitflag
=
static_cast
<
BoxedInt
*>
(
_waitflag
)
->
n
;
// Copied + adapted from CPython:
...
...
src/runtime/capi.cpp
View file @
a53ab1a8
...
...
@@ -306,44 +306,6 @@ extern "C" int PyObject_DelItem(PyObject* o, PyObject* key) noexcept {
return
-
1
;
}
extern
"C"
PyObject
*
PyObject_RichCompare
(
PyObject
*
o1
,
PyObject
*
o2
,
int
opid
)
noexcept
{
int
translated_op
;
switch
(
opid
)
{
case
Py_LT
:
translated_op
=
AST_TYPE
::
Lt
;
break
;
case
Py_LE
:
translated_op
=
AST_TYPE
::
LtE
;
break
;
case
Py_EQ
:
translated_op
=
AST_TYPE
::
Eq
;
break
;
case
Py_NE
:
translated_op
=
AST_TYPE
::
NotEq
;
break
;
case
Py_GT
:
translated_op
=
AST_TYPE
::
Gt
;
break
;
case
Py_GE
:
translated_op
=
AST_TYPE
::
GtE
;
break
;
default:
fatalOrError
(
PyExc_NotImplementedError
,
"unimplemented"
);
return
nullptr
;
};
try
{
return
compare
(
o1
,
o2
,
translated_op
);
}
catch
(
ExcInfo
e
)
{
setCAPIException
(
e
);
return
NULL
;
}
}
extern
"C"
{
int
_Py_SwappedOp
[]
=
{
Py_GT
,
Py_GE
,
Py_EQ
,
Py_NE
,
Py_LT
,
Py_LE
};
}
extern
"C"
long
PyObject_Hash
(
PyObject
*
o
)
noexcept
{
try
{
return
hash
(
o
)
->
n
;
...
...
@@ -1374,6 +1336,44 @@ static Box* methodGetDoc(Box* b, void*) {
return
None
;
}
/* extension modules might be compiled with GC support so these
functions must always be available */
#undef PyObject_GC_Track
#undef PyObject_GC_UnTrack
#undef PyObject_GC_Del
#undef _PyObject_GC_Malloc
extern
"C"
PyObject
*
_PyObject_GC_Malloc
(
size_t
basicsize
)
noexcept
{
Box
*
r
=
((
PyObject
*
)
PyObject_MALLOC
(
basicsize
));
RELEASE_ASSERT
(
gc
::
isValidGCObject
(
r
),
""
);
return
r
;
}
#undef _PyObject_GC_New
extern
"C"
PyObject
*
_PyObject_GC_New
(
PyTypeObject
*
tp
)
noexcept
{
PyObject
*
op
=
_PyObject_GC_Malloc
(
_PyObject_SIZE
(
tp
));
if
(
op
!=
NULL
)
op
=
PyObject_INIT
(
op
,
tp
);
RELEASE_ASSERT
(
gc
::
isValidGCObject
(
op
),
""
);
return
op
;
}
extern
"C"
PyVarObject
*
_PyObject_GC_NewVar
(
PyTypeObject
*
tp
,
Py_ssize_t
nitems
)
noexcept
{
const
size_t
size
=
_PyObject_VAR_SIZE
(
tp
,
nitems
);
PyVarObject
*
op
=
(
PyVarObject
*
)
_PyObject_GC_Malloc
(
size
);
if
(
op
!=
NULL
)
op
=
PyObject_INIT_VAR
(
op
,
tp
,
nitems
);
RELEASE_ASSERT
(
gc
::
isValidGCObject
(
op
),
""
);
return
op
;
}
extern
"C"
void
_Py_FatalError
(
const
char
*
fmt
,
const
char
*
function
,
const
char
*
message
)
{
fprintf
(
stderr
,
fmt
,
function
,
message
);
fflush
(
stderr
);
/* it helps in Windows debug build */
abort
();
}
void
setupCAPI
()
{
capifunc_cls
->
giveAttr
(
"__repr__"
,
new
BoxedFunction
(
boxRTFunction
((
void
*
)
BoxedCApiFunction
::
__repr__
,
UNKNOWN
,
1
)));
...
...
src/runtime/code.cpp
View file @
a53ab1a8
...
...
@@ -51,6 +51,20 @@ public:
return
boxString
(
static_cast
<
BoxedCode
*>
(
b
)
->
f
->
source
->
fn
);
}
static
Box
*
firstlineno
(
Box
*
b
,
void
*
)
{
RELEASE_ASSERT
(
b
->
cls
==
code_cls
,
""
);
BoxedCode
*
code
=
static_cast
<
BoxedCode
*>
(
b
);
CLFunction
*
cl
=
code
->
f
;
if
(
!
cl
->
source
)
{
// I don't think it really matters what we return here;
// in CPython, builtin functions don't have code objects.
return
boxInt
(
-
1
);
}
return
boxInt
(
cl
->
source
->
ast
->
lineno
);
}
static
Box
*
argcount
(
Box
*
b
,
void
*
)
{
RELEASE_ASSERT
(
b
->
cls
==
code_cls
,
""
);
...
...
@@ -114,6 +128,8 @@ void setupCode() {
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
));
...
...
src/runtime/import.cpp
View file @
a53ab1a8
...
...
@@ -690,7 +690,14 @@ Box* impFindModule(Box* _name, BoxedList* path) {
return
BoxedTuple
::
create
({
None
,
path
,
BoxedTuple
::
create
({
mode
,
mode
,
boxInt
(
sr
.
type
)
})
});
}
Py_FatalError
(
"unimplemented"
);
if
(
sr
.
type
==
SearchResult
::
C_EXTENSION
)
{
Box
*
path
=
boxString
(
sr
.
path
);
Box
*
mode
=
boxStrConstant
(
"rb"
);
Box
*
f
=
runtimeCall
(
file_cls
,
ArgPassSpec
(
2
),
path
,
mode
,
NULL
,
NULL
,
NULL
);
return
BoxedTuple
::
create
({
f
,
path
,
BoxedTuple
::
create
({
boxStrConstant
(
".so"
),
mode
,
boxInt
(
sr
.
type
)
})
});
}
RELEASE_ASSERT
(
0
,
"unknown type: %d"
,
sr
.
type
);
}
Box
*
impLoadModule
(
Box
*
_name
,
Box
*
_file
,
Box
*
_pathname
,
Box
**
args
)
{
...
...
@@ -724,6 +731,26 @@ Box* impLoadModule(Box* _name, Box* _file, Box* _pathname, Box** args) {
Py_FatalError
(
"unimplemented"
);
}
Box
*
impLoadDynamic
(
Box
*
_name
,
Box
*
_pathname
,
Box
*
_file
)
{
RELEASE_ASSERT
(
_name
->
cls
==
str_cls
,
""
);
RELEASE_ASSERT
(
_pathname
->
cls
==
str_cls
,
""
);
RELEASE_ASSERT
(
_file
==
None
,
""
);
BoxedString
*
name
=
(
BoxedString
*
)
_name
;
BoxedString
*
pathname
=
(
BoxedString
*
)
_pathname
;
const
char
*
lastdot
=
strrchr
(
name
->
s
.
data
(),
'.'
);
const
char
*
shortname
;
if
(
lastdot
==
NULL
)
{
shortname
=
name
->
s
.
data
();
}
else
{
shortname
=
lastdot
+
1
;
}
return
importCExtension
(
name
->
s
,
shortname
,
pathname
->
s
);
}
Box
*
impGetSuffixes
()
{
BoxedList
*
list
=
new
BoxedList
;
// For now only add *.py
...
...
@@ -772,9 +799,12 @@ void setupImport() {
CLFunction
*
load_module_func
=
boxRTFunction
((
void
*
)
impLoadModule
,
UNKNOWN
,
4
,
ParamNames
({
"name"
,
"file"
,
"pathname"
,
"description"
},
""
,
""
));
imp_module
->
giveAttr
(
"load_module"
,
new
BoxedBuiltinFunctionOrMethod
(
load_module_func
,
"load_module"
));
CLFunction
*
load_dynamic_func
=
boxRTFunction
((
void
*
)
impLoadDynamic
,
UNKNOWN
,
3
,
1
,
false
,
false
,
ParamNames
({
"name"
,
"pathname"
,
"file"
},
""
,
""
));
imp_module
->
giveAttr
(
"load_dynamic"
,
new
BoxedBuiltinFunctionOrMethod
(
load_dynamic_func
,
"load_dynamic"
,
{
None
}));
imp_module
->
giveAttr
(
"get_suffixes"
,
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
impGetSuffixes
,
UNKNOWN
,
0
),
"get_suffixes"
));
imp_module
->
giveAttr
(
"acquire_lock"
,
new
BoxedBuiltinFunctionOrMethod
(
boxRTFunction
((
void
*
)
impAcquireLock
,
NONE
,
0
),
...
...
src/runtime/objmodel.cpp
View file @
a53ab1a8
...
...
@@ -325,6 +325,7 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
tp_flags
|=
Py_TPFLAGS_HAVE_CLASS
;
tp_flags
|=
Py_TPFLAGS_HAVE_GC
;
tp_flags
|=
Py_TPFLAGS_HAVE_WEAKREFS
;
tp_flags
|=
Py_TPFLAGS_HAVE_RICHCOMPARE
;
if
(
base
&&
(
base
->
tp_flags
&
Py_TPFLAGS_HAVE_NEWBUFFER
))
tp_flags
|=
Py_TPFLAGS_HAVE_NEWBUFFER
;
...
...
src/runtime/types.cpp
View file @
a53ab1a8
...
...
@@ -2273,6 +2273,7 @@ void setupRuntime() {
PyType_Ready
(
&
PyByteArrayIter_Type
);
PyType_Ready
(
&
PyCapsule_Type
);
PyType_Ready
(
&
PyCallIter_Type
);
PyType_Ready
(
&
PyCObject_Type
);
initerrno
();
init_sha
();
...
...
test/integration/virtualenv_bcrypt_test.py
deleted
100644 → 0
View file @
7b71c6f8
# expected: fail
# - misc issues
import
os
import
sys
import
subprocess
import
shutil
VIRTUALENV_SCRIPT
=
os
.
path
.
dirname
(
__file__
)
+
"/virtualenv/virtualenv.py"
if
os
.
path
.
exists
(
"test_env"
):
print
"Removing the existing 'test_env/' directory"
subprocess
.
check_call
([
"rm"
,
"-rf"
,
"test_env"
])
# shutil follows symlinks to directories, and deletes whatever those contain.
# shutil.rmtree("test_env")
args
=
[
sys
.
executable
,
VIRTUALENV_SCRIPT
,
"-p"
,
sys
.
executable
,
"test_env"
]
print
"Running"
,
args
subprocess
.
check_call
(
args
)
sh_script
=
"""
set -e
. test_env/bin/activate
set -ux
python -c 'import __future__'
python -c 'import sys; print sys.executable'
pip install bcrypt==1.1.0
python -c 'import bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"'
"""
.
strip
()
# print sh_script
subprocess
.
check_call
([
"sh"
,
"-c"
,
sh_script
])
test/integration/virtualenv_test.py
View file @
a53ab1a8
...
...
@@ -21,9 +21,12 @@ set -e
set -ux
python -c 'import __future__'
python -c 'import sys; print sys.executable'
pip install
six==1.9.0 cffi==0.9.2
python -c 'import
six; print six.__version__
'
pip install
bcrypt==1.1.0
python -c 'import
bcrypt; assert bcrypt.__version__ == "1.1.0"; assert bcrypt.hashpw("password1", "$2a$12$0123456789012345678901").endswith("I1hdtg4K"); print "bcrypt seems to work"
'
"""
.
strip
()
# print sh_script
subprocess
.
check_call
([
"sh"
,
"-c"
,
sh_script
])
print
print
"PASSED"
test/tests/cmp_test.py
0 → 100644
View file @
a53ab1a8
class
C
(
object
):
def
__eq__
(
self
,
rhs
):
print
"eq"
,
type
(
self
),
type
(
rhs
)
return
False
def
__lt__
(
self
,
rhs
):
print
"lt"
,
type
(
self
),
type
(
rhs
)
return
False
def
__gt__
(
self
,
rhs
):
print
"gt"
,
type
(
self
),
type
(
rhs
)
return
True
class
D
(
C
):
def
__cmp__
(
self
,
rhs
):
print
"cmp"
,
type
(
self
),
type
(
rhs
)
return
0
l
=
[
C
(),
D
()]
for
lhs
in
l
:
for
rhs
in
l
:
r
=
cmp
(
lhs
,
rhs
)
print
type
(
lhs
),
type
(
rhs
),
r
test/tests/code_test.py
View file @
a53ab1a8
...
...
@@ -4,6 +4,7 @@ def f(a, b=2, *args, **kw):
c
=
f
.
func_code
print
c
.
co_argcount
print
c
.
co_varnames
print
c
.
co_firstlineno
print
hex
(
c
.
co_flags
&
0x0c
)
def
f
(
l
=
[]):
...
...
@@ -15,3 +16,4 @@ f()
def
f
():
pass
print
f
.
func_defaults
print
f
.
func_code
.
co_firstlineno
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