2
0
mirror of https://github.com/boostorg/python.git synced 2026-02-03 09:22:17 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Eric Niebler
f15bbd7951 Phoenix Reloaded
[SVN r53348]
2009-05-28 17:15:17 +00:00
19 changed files with 78 additions and 284 deletions

View File

@@ -1,9 +1,3 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
if (PYTHON_LIBRARIES)
include_directories(${PYTHON_INCLUDE_PATH})

View File

@@ -186,6 +186,10 @@ And so on... Finally:
Or something similar. If all is well, you should now have built the DLLs and
run the Python program.
[note Starting from Boost 1.35, bjam erases the generated executables
(e.g. pyd file) after the test has concluded to conserve disk space.
To keep bjam from doing that, pass --preserve-test-targets to bjam.]
[:[*There you go... Have fun!]]
[endsect]

View File

@@ -2,15 +2,6 @@
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
if ! [ python.configured ]
{
ECHO "notice: no Python configured in user-config.jam" ;
ECHO "notice: will use default configuration" ;
using python ;
}
# Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost

View File

@@ -55,8 +55,8 @@ inline decorated_type_info::decorated_type_info(type_info base_t, decoration dec
inline bool decorated_type_info::operator<(decorated_type_info const& rhs) const
{
return m_decoration < rhs.m_decoration
|| (m_decoration == rhs.m_decoration
&& m_base_type < rhs.m_base_type);
|| m_decoration == rhs.m_decoration
&& m_base_type < rhs.m_base_type;
}
inline bool decorated_type_info::operator==(decorated_type_info const& rhs) const

View File

@@ -60,9 +60,7 @@ inline
object_operators<U>::operator bool_type() const
{
object_cref2 x = *static_cast<U const*>(this);
int is_true = PyObject_IsTrue(x.ptr());
if (is_true < 0) throw_error_already_set();
return is_true ? &object::ptr : 0;
return PyObject_IsTrue(x.ptr()) ? &object::ptr : 0;
}
template <class U>
@@ -70,9 +68,7 @@ inline bool
object_operators<U>::operator!() const
{
object_cref2 x = *static_cast<U const*>(this);
int is_true = PyObject_IsTrue(x.ptr());
if (is_true < 0) throw_error_already_set();
return !is_true;
return !PyObject_IsTrue(x.ptr());
}
# define BOOST_PYTHON_COMPARE_OP(op, opid) \

View File

@@ -1,9 +1,3 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
if (PYTHON_DEBUG_LIBRARIES AND BUILD_BOOST_PYTHON)
# We have detected that there might be Python debug libraries
# available, but check for ourselves whether this is true by trying

View File

@@ -155,27 +155,10 @@ namespace
{
static T extract(PyObject* intermediate)
{
if (PyLong_Check(intermediate)) {
// PyLong_AsUnsignedLong() checks for negative overflow, so no
// need to check it here.
unsigned long result = PyLong_AsUnsignedLong(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
return numeric_cast<T>(result);
} else {
// None of PyInt_AsUnsigned*() functions check for negative
// overflow, so use PyInt_AS_LONG instead and check if number is
// negative, issuing the exception appropriately.
long result = PyInt_AS_LONG(intermediate);
if (PyErr_Occurred())
throw_error_already_set();
if (result < 0) {
PyErr_SetString(PyExc_OverflowError, "can't convert negative"
" value to unsigned");
throw_error_already_set();
}
return numeric_cast<T>(result);
}
return numeric_cast<T>(
PyLong_Check(intermediate)
? PyLong_AsUnsignedLong(intermediate)
: PyInt_AS_LONG(intermediate));
}
};

View File

@@ -5,7 +5,6 @@
#include <boost/python/exec.hpp>
#include <boost/python/borrowed.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/handle.hpp>
@@ -16,16 +15,6 @@ namespace python
object BOOST_PYTHON_DECL eval(str string, object global, object local)
{
// Set suitable default values for global and local dicts.
object none;
if (global.ptr() == none.ptr())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.ptr() == none.ptr()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_eval_input, global.ptr(), local.ptr());
@@ -35,16 +24,6 @@ object BOOST_PYTHON_DECL eval(str string, object global, object local)
object BOOST_PYTHON_DECL exec(str string, object global, object local)
{
// Set suitable default values for global and local dicts.
object none;
if (global.ptr() == none.ptr())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.ptr() == none.ptr()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_file_input, global.ptr(), local.ptr());
@@ -52,40 +31,11 @@ object BOOST_PYTHON_DECL exec(str string, object global, object local)
return object(detail::new_reference(result));
}
object BOOST_PYTHON_DECL exec_statement(str string, object global, object local)
{
// Set suitable default values for global and local dicts.
object none;
if (global.ptr() == none.ptr())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.ptr() == none.ptr()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *s = python::extract<char *>(string);
PyObject* result = PyRun_String(s, Py_single_input, global.ptr(), local.ptr());
if (!result) throw_error_already_set();
return object(detail::new_reference(result));
}
// Execute python source code from file filename.
// global and local are the global and local scopes respectively,
// used during execution.
object BOOST_PYTHON_DECL exec_file(str filename, object global, object local)
{
// Set suitable default values for global and local dicts.
object none;
if (global.ptr() == none.ptr())
{
if (PyObject *g = PyEval_GetGlobals())
global = object(detail::borrowed_reference(g));
else
global = dict();
}
if (local.ptr() == none.ptr()) local = global;
// should be 'char const *' but older python versions don't use 'const' yet.
char *f = python::extract<char *>(filename);
// Let python open the file to avoid potential binary incompatibilities.

View File

@@ -506,12 +506,13 @@ namespace objects
// Build a tuple of the base Python type objects. If no bases
// were declared, we'll use our class_type() as the single base
// class.
ssize_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
handle<> bases(PyTuple_New(num_bases));
std::size_t const num_bases = (std::max)(num_types - 1, static_cast<std::size_t>(1));
assert(num_bases <= ssize_t_max);
handle<> bases(PyTuple_New(static_cast<ssize_t>(num_bases)));
for (ssize_t i = 1; i <= num_bases; ++i)
for (std::size_t i = 1; i <= num_bases; ++i)
{
type_handle c = (i >= static_cast<ssize_t>(num_types)) ? class_type() : get_class(types[i]);
type_handle c = (i >= num_types) ? class_type() : get_class(types[i]);
// PyTuple_SET_ITEM steals this reference
PyTuple_SET_ITEM(bases.get(), static_cast<ssize_t>(i - 1), upcast<PyObject>(c.release()));
}

View File

@@ -14,7 +14,7 @@
#include <boost/python/object_protocol.hpp>
#include <structmember.h>
namespace boost { namespace python { namespace objects {
namespace boost { namespace python { namespace objects {
struct enum_object
{
@@ -43,7 +43,7 @@ extern "C"
char* name = PyString_AsString(self->name);
if (name == 0)
return 0;
return PyString_FromFormat("%s.%s.%s", mod, self_->ob_type->tp_name, name);
}
}
@@ -139,16 +139,15 @@ namespace
dict d;
d["__slots__"] = tuple();
d["values"] = dict();
d["names"] = dict();
object module_name = module_prefix();
if (module_name)
d["__module__"] = module_name;
if (doc)
d["__doc__"] = doc;
object result = (object(metatype))(name, make_tuple(base), d);
scope().attr(name) = result;
return result;
@@ -168,7 +167,7 @@ enum_base::enum_base(
converter::registration& converters
= const_cast<converter::registration&>(
converter::registry::lookup(id));
converters.m_class_object = downcast<PyTypeObject>(this->ptr());
converter::registry::insert(to_python, id);
converter::registry::insert(convertible, construct, id);
@@ -187,24 +186,23 @@ void enum_base::add_value(char const* name_, long value)
dict d = extract<dict>(this->attr("values"))();
d[value] = x;
// Set the name field in the new enum instanec
enum_object* p = downcast<enum_object>(x.ptr());
Py_XDECREF(p->name);
p->name = incref(name.ptr());
dict names_dict = extract<dict>(this->attr("names"))();
names_dict[x.attr("name")] = x;
}
void enum_base::export_values()
{
dict d = extract<dict>(this->attr("names"))();
list items = d.items();
dict d = extract<dict>(this->attr("values"))();
list values = d.values();
scope current;
for (unsigned i = 0, max = len(items); i < max; ++i)
api::setattr(current, items[i][0], items[i][1]);
for (unsigned i = 0, max = len(values); i < max; ++i)
{
api::setattr(current, object(values[i].attr("name")), values[i]);
}
}
PyObject* enum_base::to_python(PyTypeObject* type_, long x)

View File

@@ -166,7 +166,7 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
else
{
// build a new arg tuple, will adjust its size later
assert(max_arity <= static_cast<std::size_t>(ssize_t_max));
assert(max_arity <= ssize_t_max);
inner_args = handle<>(
PyTuple_New(static_cast<ssize_t>(max_arity)));

View File

@@ -52,9 +52,9 @@ namespace boost { namespace python { namespace objects {
//check if the argument default values are the same
bool f1_has_names = bool(f1->m_arg_names);
bool f2_has_names = bool(f2->m_arg_names);
if ( (f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1])
|| (f1_has_names && !f2_has_names)
|| (!f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object())
if ( f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=f1->m_arg_names[i-1]
|| f1_has_names && !f2_has_names
|| !f1_has_names && f2_has_names && f2->m_arg_names[i-1]!=python::object()
)
return false;
}

View File

@@ -26,7 +26,7 @@ namespace {
ssize_t str_size_as_py_ssize_t(std::size_t n)
{
if (n > static_cast<std::size_t>(ssize_t_max))
if (n > ssize_t_max)
{
throw std::range_error("str size > ssize_t_max");
}

View File

@@ -1,9 +1,3 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
macro(bpl_test TESTNAME)
parse_arguments(BPL_TEST
"ARGS"
@@ -19,43 +13,25 @@ macro(bpl_test TESTNAME)
cdr(BPL_TEST_DEFAULT_ARGS ${BPL_TEST_DEFAULT_ARGS})
get_filename_component(BPL_TEST_PYBASE ${BPL_TEST_PYSOURCE} NAME_WE)
# Process all the .cpp file and extension module names
foreach(SRC ${BPL_TEST_DEFAULT_ARGS})
get_filename_component(BPL_SRC_EXT ${SRC} EXT)
if (BPL_SRC_EXT STREQUAL ".cpp")
# Build a Python extension module from this source file
get_filename_component(BPL_SRC_NAME ${SRC} NAME_WE)
if(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
set(BPL_EXTENSION_MODULE ${BPL_SRC_NAME}_ext)
boost_python_extension(${BPL_SRC_NAME}_ext ${SRC})
else(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
set(BPL_EXTENSION_MODULE ${BPL_SRC_NAME})
boost_python_extension(${BPL_SRC_NAME} ${SRC})
endif(BPL_TEST_PYBASE STREQUAL "${BPL_SRC_NAME}")
boost_python_extension(${BPL_EXTENSION_MODULE} ${SRC})
else (BPL_SRC_EXT STREQUAL ".cpp")
set(BPL_EXTENSION_MODULE ${SRC})
endif (BPL_SRC_EXT STREQUAL ".cpp")
add_dependencies(${PROJECT_NAME}-test ${BPL_EXTENSION_MODULE})
endforeach(SRC ${BPL_TEST_DEFAULT_ARGS})
else (BPL_TEST_DEFAULT_ARGS)
set(BPL_TEST_PYSOURCE "${TESTNAME}.py")
# Build a Python extension module from this source file
boost_python_extension(${TESTNAME}_ext "${TESTNAME}.cpp")
add_dependencies(${PROJECT_NAME}-test ${TESTNAME}_ext)
endif(BPL_TEST_DEFAULT_ARGS)
add_dependencies(${PROJECT_NAME}-test ${BPL_TEST_PYSOURCE})
# We'll need the full patch to run the Python test
set(BPL_TEST_PYSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/${BPL_TEST_PYSOURCE})

View File

@@ -12,7 +12,7 @@
#endif
using namespace boost::python;
enum color { red = 1, green = 2, blue = 4, blood = 1 };
enum color { red = 1, green = 2, blue = 4 };
#if BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
namespace boost // Pro7 has a hard time detecting enums
@@ -34,7 +34,6 @@ BOOST_PYTHON_MODULE(enum_ext)
.value("red", red)
.value("green", green)
.value("blue", blue)
.value("blood", blood)
.export_values()
;

View File

@@ -4,8 +4,8 @@
'''
>>> from enum_ext import *
>>> identity(color.red) # in case of duplicated enums it always take the last enum
enum_ext.color.blood
>>> identity(color.red)
enum_ext.color.red
>>> identity(color.green)
enum_ext.color.green
@@ -13,8 +13,8 @@ enum_ext.color.green
>>> identity(color.blue)
enum_ext.color.blue
>>> identity(color(1)) # in case of duplicated enums it always take the last enum
enum_ext.color.blood
>>> identity(color(1))
enum_ext.color.red
>>> identity(color(2))
enum_ext.color.green
@@ -28,7 +28,7 @@ enum_ext.color.blue
--- check export to scope ---
>>> identity(red)
enum_ext.color.blood
enum_ext.color.red
>>> identity(green)
enum_ext.color.green
@@ -42,18 +42,10 @@ enum_ext.color.blue
>>> c = colorized()
>>> c.x
enum_ext.color.blood
enum_ext.color.red
>>> c.x = green
>>> c.x
enum_ext.color.green
>>> red == blood
True
>>> red == green
False
>>> hash(red) == hash(blood)
True
>>> hash(red) == hash(green)
False
'''
# pickling of enums only works with Python 2.3 or higher

View File

@@ -108,73 +108,46 @@ void exec_test_error()
python::object result = python::exec("print unknown \n", global, global);
}
void exercise_embedding_html()
{
using namespace boost::python;
/* code from: libs/python/doc/tutorial/doc/tutorial.qbk
(generates libs/python/doc/tutorial/doc/html/python/embedding.html)
*/
object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");
object ignored = exec("hello = file('hello.txt', 'w')\n"
"hello.write('Hello world!')\n"
"hello.close()",
main_namespace);
}
void check_pyerr(bool pyerr_expected=false)
{
if (PyErr_Occurred())
{
if (!pyerr_expected) {
BOOST_ERROR("Python Error detected");
PyErr_Print();
}
else {
PyErr_Clear();
}
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception handler registered.");
}
}
int main(int argc, char **argv)
{
BOOST_TEST(argc == 2 || argc == 3);
BOOST_TEST(argc == 2);
std::string script = argv[1];
// Initialize the interpreter
Py_Initialize();
if (python::handle_exception(eval_test)) {
check_pyerr();
}
else if(python::handle_exception(exec_test)) {
check_pyerr();
}
else if (python::handle_exception(boost::bind(exec_file_test, script))) {
check_pyerr();
if (python::handle_exception(eval_test) ||
python::handle_exception(exec_test) ||
python::handle_exception(boost::bind(exec_file_test, script)))
{
if (PyErr_Occurred())
{
BOOST_ERROR("Python Error detected");
PyErr_Print();
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception handler registered.");
}
}
if (python::handle_exception(exec_test_error))
{
check_pyerr(/*pyerr_expected*/ true);
if (PyErr_Occurred())
{
PyErr_Print();
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception handler registered.");
}
}
else
{
BOOST_ERROR("Python exception expected, but not seen.");
BOOST_ERROR("Python exception expected, but not seen.");
}
if (argc > 2) {
// The main purpose is to test compilation. Since this test generates
// a file and I (rwgk) am uncertain about the side-effects, run it only
// if explicitly requested.
exercise_embedding_html();
}
// Boost.Python doesn't support Py_Finalize yet.
// Py_Finalize();
return boost::report_errors();

View File

@@ -17,10 +17,6 @@ struct by_value
{
return x;
}
static int size(void)
{
return sizeof(T);
}
};
template <class T>
@@ -65,17 +61,7 @@ BOOST_PYTHON_MODULE(builtin_converters_ext)
{
def("get_type", get_type);
def("return_null_handle", return_null_handle);
// These methods are used solely for getting some C++ type sizes
def("bool_size", by_value<bool>::size);
def("char_size", by_value<char>::size);
def("int_size", by_value<int>::size);
def("short_size", by_value<short>::size);
def("long_size", by_value<long>::size);
#ifdef HAVE_LONG_LONG
def("long_long_size", by_value<BOOST_PYTHON_LONG_LONG>::size);
#endif
def("rewrap_value_bool", by_value<bool>::rewrap);
def("rewrap_value_char", by_value<char>::rewrap);
def("rewrap_value_signed_char", by_value<signed char>::rewrap);

View File

@@ -4,33 +4,12 @@
r"""
>>> from builtin_converters_ext import *
# Provide values for integer converter tests
>>> def _signed_values(s):
... base = 2 ** (8 * s - 1)
... return [[-base, -1, 1, base - 1], [-base - 1, base]]
>>> def _unsigned_values(s):
... base = 2 ** (8 * s)
... return [[1, base - 1], [-1L, -1, base]]
# Wrappers to simplify tests
>>> def should_pass(method, values):
... result = map(method, values[0])
... if result != values[0]:
... print "Got %s but expected %s" % (result, values[0])
>>> def test_overflow(method, values):
... for v in values[1]:
... try: method(v)
... except OverflowError: pass
... else: print "OverflowError expected"
# Synthesize idendity functions in case long long not supported
>>> if not 'rewrap_value_long_long' in dir():
... def rewrap_value_long_long(x): return long(x)
... def rewrap_value_unsigned_long_long(x): return long(x)
... def rewrap_const_reference_long_long(x): return long(x)
... def rewrap_const_reference_unsigned_long_long(x): return long(x)
>>> if not 'long_long_size' in dir():
... def long_long_size(): return long_size()
>>> try: bool_exists = bool
... except: pass
@@ -83,37 +62,15 @@ False
42L
show that we have range checking.
>>> try: rewrap_value_unsigned_short(-42)
... except OverflowError: pass
... else: print 'expected an OverflowError!'
>>> should_pass(rewrap_value_signed_char, _signed_values(char_size()))
>>> should_pass(rewrap_value_short, _signed_values(short_size()))
>>> should_pass(rewrap_value_int, _signed_values(int_size()))
>>> should_pass(rewrap_value_long, _signed_values(long_size()))
>>> should_pass(rewrap_value_long_long, _signed_values(long_long_size()))
>>> try: rewrap_value_int(sys.maxint * 2)
... except OverflowError: pass
... else: print 'expected an OverflowError!'
>>> should_pass(rewrap_value_unsigned_char, _unsigned_values(char_size()))
>>> should_pass(rewrap_value_unsigned_short, _unsigned_values(short_size()))
>>> should_pass(rewrap_value_unsigned_int, _unsigned_values(int_size()))
>>> should_pass(rewrap_value_unsigned_long, _unsigned_values(long_size()))
>>> should_pass(rewrap_value_unsigned_long_long,
... _unsigned_values(long_long_size()))
>>> test_overflow(rewrap_value_signed_char, _signed_values(char_size()))
>>> test_overflow(rewrap_value_short, _signed_values(short_size()))
>>> test_overflow(rewrap_value_int, _signed_values(int_size()))
>>> test_overflow(rewrap_value_long, _signed_values(long_size()))
>>> test_overflow(rewrap_value_long_long, _signed_values(long_long_size()))
>>> test_overflow(rewrap_value_unsigned_char, _unsigned_values(char_size()))
>>> test_overflow(rewrap_value_unsigned_short, _unsigned_values(short_size()))
>>> test_overflow(rewrap_value_unsigned_int, _unsigned_values(int_size()))
>>> test_overflow(rewrap_value_unsigned_long, _unsigned_values(long_size()))
# Exceptionally for PyLong_AsUnsignedLongLong(), a negative value raises
# TypeError on Python versions prior to 2.7
>>> for v in _unsigned_values(long_long_size())[1]:
... try: rewrap_value_unsigned_long_long(v)
... except (OverflowError, TypeError): pass
... else: print "OverflowError or TypeError expected"
>>> assert abs(rewrap_value_float(4.2) - 4.2) < .000001
>>> rewrap_value_double(4.2) - 4.2