diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/python/example/quickstart | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/python/example/quickstart')
5 files changed, 274 insertions, 0 deletions
diff --git a/src/boost/libs/python/example/quickstart/Jamfile b/src/boost/libs/python/example/quickstart/Jamfile new file mode 100644 index 00000000..6dd35130 --- /dev/null +++ b/src/boost/libs/python/example/quickstart/Jamfile @@ -0,0 +1,35 @@ +# Copyright Stefan Seefeld 2016. +# Distributed under the Boost 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 ; +import testing ; + +project quickstart + : requirements + <location>. + ; + +# Declare a Python extension called hello. +python-extension extending : extending.cpp ; + +# Declare an executable called embedding that embeds Python +exe embedding : embedding.cpp /python//python ; + +# Declare a test of the extension module +testing.make-test run-pyd : extending test_extending.py : : test_ext ; + +# Declare a test of the embedding application +testing.run embedding embedding.cpp + : # any ordinary arguments + : script.py # any arguments that should be treated as relative paths + : # requirements + : test_embed ; # name of test + +# Create a "test" target that runs all the tests +alias test : test_ext test_embed ; + +# make sure the tests don't run by default +explicit test_ext test_embed test ; + diff --git a/src/boost/libs/python/example/quickstart/embedding.cpp b/src/boost/libs/python/example/quickstart/embedding.cpp new file mode 100644 index 00000000..65bcd16a --- /dev/null +++ b/src/boost/libs/python/example/quickstart/embedding.cpp @@ -0,0 +1,154 @@ +// Copyright Stefan Seefeld 2005. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/python.hpp> + +#include <boost/detail/lightweight_test.hpp> +#include <iostream> + +namespace python = boost::python; + +// An abstract base class +class Base : public boost::noncopyable +{ +public: + virtual ~Base() {}; + virtual std::string hello() = 0; +}; + +// C++ derived class +class CppDerived : public Base +{ +public: + virtual ~CppDerived() {} + virtual std::string hello() { return "Hello from C++!";} +}; + +// Familiar Boost.Python wrapper class for Base +struct BaseWrap : Base, python::wrapper<Base> +{ + virtual std::string hello() + { +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) + // workaround for VC++ 6.x or 7.0, see + // http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions + return python::call<std::string>(this->get_override("hello").ptr()); +#else + return this->get_override("hello")(); +#endif + } +}; + +// Pack the Base class wrapper into a module +BOOST_PYTHON_MODULE(embedded_hello) +{ + python::class_<BaseWrap, boost::noncopyable> base("Base"); +} + + +void exec_test() +{ + std::cout << "registering extension module embedded_hello..." << std::endl; + + // Register the module with the interpreter + if (PyImport_AppendInittab("embedded_hello", initembedded_hello) == -1) + throw std::runtime_error("Failed to add embedded_hello to the interpreter's " + "builtin modules"); + + std::cout << "defining Python class derived from Base..." << std::endl; + + // Retrieve the main module + python::object main = python::import("__main__"); + + // Retrieve the main module's namespace + python::object global(main.attr("__dict__")); + + // Define the derived class in Python. + python::object result = python::exec( + "from embedded_hello import * \n" + "class PythonDerived(Base): \n" + " def hello(self): \n" + " return 'Hello from Python!' \n", + global, global); + + python::object PythonDerived = global["PythonDerived"]; + + // Creating and using instances of the C++ class is as easy as always. + CppDerived cpp; + BOOST_TEST(cpp.hello() == "Hello from C++!"); + + std::cout << "testing derived class from C++..." << std::endl; + + // But now creating and using instances of the Python class is almost + // as easy! + python::object py_base = PythonDerived(); + Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND; + + // Make sure the right 'hello' method is called. + BOOST_TEST(py.hello() == "Hello from Python!"); + + std::cout << "success!" << std::endl; +} + +void exec_file_test(std::string const &script) +{ + std::cout << "running file " << script << "..." << std::endl; + + // Run a python script in an empty environment. + python::dict global; + python::object result = python::exec_file(script.c_str(), global, global); + + // Extract an object the script stored in the global dictionary. + BOOST_TEST(python::extract<int>(global["number"]) == 42); + + std::cout << "success!" << std::endl; +} + +void exec_test_error() +{ + std::cout << "intentionally causing a python exception..." << std::endl; + + // Execute a statement that raises a python exception. + python::dict global; + python::object result = python::exec("print unknown \n", global, global); + + std::cout << "Oops! This statement should be skipped due to an exception" << std::endl; +} + +int main(int argc, char **argv) +{ + BOOST_TEST(argc == 2); + std::string script = argv[1]; + // Initialize the interpreter + Py_Initialize(); + + bool error_expected = false; + + if ( + python::handle_exception(exec_test) + || python::handle_exception(boost::bind(exec_file_test, script)) + || ( + (error_expected = true) + && python::handle_exception(exec_test_error) + ) + + ) + { + if (PyErr_Occurred()) + { + if (!error_expected) + BOOST_ERROR("Python Error detected"); + PyErr_Print(); + } + else + { + BOOST_ERROR("A C++ exception was thrown for which " + "there was no exception translator registered."); + } + } + + // Boost.Python doesn't support Py_Finalize yet, so don't call it! + return boost::report_errors(); +} diff --git a/src/boost/libs/python/example/quickstart/extending.cpp b/src/boost/libs/python/example/quickstart/extending.cpp new file mode 100644 index 00000000..a539d3b4 --- /dev/null +++ b/src/boost/libs/python/example/quickstart/extending.cpp @@ -0,0 +1,41 @@ +// Copyright Ralf W. Grosse-Kunstleve 2002-2004. Distributed under the Boost +// Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include <boost/python/class.hpp> +#include <boost/python/module.hpp> +#include <boost/python/def.hpp> +#include <iostream> +#include <string> + +namespace { // Avoid cluttering the global namespace. + + // A friendly class. + class hello + { + public: + hello(const std::string& country) { this->country = country; } + std::string greet() const { return "Hello from " + country; } + private: + std::string country; + }; + + // A function taking a hello object as an argument. + std::string invite(const hello& w) { + return w.greet() + "! Please come soon!"; + } +} + +BOOST_PYTHON_MODULE(extending) +{ + using namespace boost::python; + class_<hello>("hello", init<std::string>()) + // Add a regular member function. + .def("greet", &hello::greet) + // Add invite() as a member of hello! + .def("invite", invite) + ; + + // Also add invite() as a regular function to the module. + def("invite", invite); +} diff --git a/src/boost/libs/python/example/quickstart/script.py b/src/boost/libs/python/example/quickstart/script.py new file mode 100644 index 00000000..c3e034ba --- /dev/null +++ b/src/boost/libs/python/example/quickstart/script.py @@ -0,0 +1,7 @@ +#! /usr/bin/env python +# Copyright Stefan Seefeld 2006. Distributed under the Boost +# Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +print('Hello World !') +number = 42 diff --git a/src/boost/libs/python/example/quickstart/test_extending.py b/src/boost/libs/python/example/quickstart/test_extending.py new file mode 100644 index 00000000..938c7b90 --- /dev/null +++ b/src/boost/libs/python/example/quickstart/test_extending.py @@ -0,0 +1,37 @@ +#! /usr/bin/env python +# Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost +# Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +# Using the doctest module here to ensure that the results are as expected. +r'''>>> from extending import * + >>> hi = hello('California') + >>> hi.greet() + 'Hello from California' + >>> invite(hi) + 'Hello from California! Please come soon!' + >>> hi.invite() + 'Hello from California! Please come soon!' + + >>> class wordy(hello): + ... def greet(self): + ... return hello.greet(self) + ', where the weather is fine' + ... + >>> hi2 = wordy('Florida') + >>> hi2.greet() + 'Hello from Florida, where the weather is fine' + >>> invite(hi2) + 'Hello from Florida! Please come soon!' +''' + +def run(args = None): + if args is not None: + import sys + sys.argv = args + import doctest, test_extending + return doctest.testmod(test_extending, verbose=True) + +if __name__ == '__main__': + import sys + sys.exit(run()[0]) + |