refactor: module -> module_ with typedef (#2544)

* WIP: module -> module_ without typedef

* refactor: allow py::module to work again
This commit is contained in:
Henry Schreiner 2020-10-03 13:38:03 -04:00 committed by GitHub
parent 560ed3e34f
commit 6bcd220c8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 132 additions and 127 deletions

View File

@ -108,11 +108,11 @@ The two approaches can also be combined:
Importing modules
=================
Python modules can be imported using `module::import()`:
Python modules can be imported using `module_::import()`:
.. code-block:: cpp
py::module sys = py::module::import("sys");
py::module_ sys = py::module_::import("sys");
py::print(sys.attr("path"));
For convenience, the current working directory is included in ``sys.path`` when
@ -128,12 +128,12 @@ embedding the interpreter. This makes it easy to import local Python files:
.. code-block:: cpp
py::module calc = py::module::import("calc");
py::module_ calc = py::module_::import("calc");
py::object result = calc.attr("add")(1, 2);
int n = result.cast<int>();
assert(n == 3);
Modules can be reloaded using `module::reload()` if the source is modified e.g.
Modules can be reloaded using `module_::reload()` if the source is modified e.g.
by an external process. This can be useful in scenarios where the application
imports a user defined data processing script which needs to be updated after
changes by the user. Note that this function does not reload modules recursively.
@ -153,7 +153,7 @@ like any other module.
namespace py = pybind11;
PYBIND11_EMBEDDED_MODULE(fast_calc, m) {
// `m` is a `py::module` which is used to bind functions and classes
// `m` is a `py::module_` which is used to bind functions and classes
m.def("add", [](int i, int j) {
return i + j;
});
@ -162,7 +162,7 @@ like any other module.
int main() {
py::scoped_interpreter guard{};
auto fast_calc = py::module::import("fast_calc");
auto fast_calc = py::module_::import("fast_calc");
auto result = fast_calc.attr("add")(1, 2).cast<int>();
assert(result == 3);
}
@ -196,7 +196,7 @@ naturally:
int main() {
py::scoped_interpreter guard{};
auto py_module = py::module::import("py_module");
auto py_module = py::module_::import("py_module");
auto locals = py::dict("fmt"_a="{} + {} = {}", **py_module.attr("__dict__"));
assert(locals["a"].cast<int>() == 1);

View File

@ -182,7 +182,7 @@ For example:
try {
// open("missing.txt", "r")
auto file = py::module::import("io").attr("open")("missing.txt", "r");
auto file = py::module_::import("io").attr("open")("missing.txt", "r");
auto text = file.attr("read")();
file.attr("close")();
} catch (py::error_already_set &e) {

View File

@ -17,7 +17,7 @@ bindings for functions that return a non-trivial type. Just by looking at the
type information, it is not clear whether Python should take charge of the
returned value and eventually free its resources, or if this is handled on the
C++ side. For this reason, pybind11 provides a several *return value policy*
annotations that can be passed to the :func:`module::def` and
annotations that can be passed to the :func:`module_::def` and
:func:`class_::def` functions. The default policy is
:enum:`return_value_policy::automatic`.

View File

@ -132,7 +132,7 @@ However, it can be acquired as follows:
.. code-block:: cpp
py::object pet = (py::object) py::module::import("basic").attr("Pet");
py::object pet = (py::object) py::module_::import("basic").attr("Pet");
py::class_<Dog>(m, "Dog", pet)
.def(py::init<const std::string &>())
@ -146,7 +146,7 @@ has been executed:
.. code-block:: cpp
py::module::import("basic");
py::module_::import("basic");
py::class_<Dog, Pet>(m, "Dog")
.def(py::init<const std::string &>())
@ -243,7 +243,7 @@ avoids this issue involves weak reference with a cleanup callback:
.. code-block:: cpp
auto atexit = py::module::import("atexit");
auto atexit = py::module_::import("atexit");
atexit.attr("register")(py::cpp_function([]() {
// perform cleanup here -- this function is called with the GIL held
}));
@ -284,7 +284,7 @@ work, it is important that all lines are indented consistently, i.e.:
)mydelimiter");
By default, pybind11 automatically generates and prepends a signature to the docstring of a function
registered with ``module::def()`` and ``class_::def()``. Sometimes this
registered with ``module_::def()`` and ``class_::def()``. Sometimes this
behavior is not desirable, because you want to provide your own signature or remove
the docstring completely to exclude the function from the Sphinx documentation.
The class ``options`` allows you to selectively suppress auto-generated signatures:

View File

@ -56,12 +56,12 @@ This example obtains a reference to the Python ``Decimal`` class.
.. code-block:: cpp
// Equivalent to "from decimal import Decimal"
py::object Decimal = py::module::import("decimal").attr("Decimal");
py::object Decimal = py::module_::import("decimal").attr("Decimal");
.. code-block:: cpp
// Try to import scipy
py::object scipy = py::module::import("scipy");
py::object scipy = py::module_::import("scipy");
return scipy.attr("__version__");
@ -81,7 +81,7 @@ via ``operator()``.
.. code-block:: cpp
// Use Python to make our directories
py::object os = py::module::import("os");
py::object os = py::module_::import("os");
py::object makedirs = os.attr("makedirs");
makedirs("/tmp/path/to/somewhere");
@ -196,9 +196,9 @@ C++ functions that require a specific subtype rather than a generic :class:`obje
#include <pybind11/numpy.h>
using namespace pybind11::literals;
py::module os = py::module::import("os");
py::module path = py::module::import("os.path"); // like 'import os.path as path'
py::module np = py::module::import("numpy"); // like 'import numpy as np'
py::module_ os = py::module_::import("os");
py::module_ path = py::module_::import("os.path"); // like 'import os.path as path'
py::module_ np = py::module_::import("numpy"); // like 'import numpy as np'
py::str curdir_abs = path.attr("abspath")(path.attr("curdir"));
py::print(py::str("Current directory: ") + curdir_abs);

View File

@ -42,7 +42,7 @@ redirects output to the corresponding Python streams:
m.def("noisy_func", []() {
py::scoped_ostream_redirect stream(
std::cout, // std::ostream&
py::module::import("sys").attr("stdout") // Python output
py::module_::import("sys").attr("stdout") // Python output
);
call_noisy_func();
});
@ -104,7 +104,7 @@ can be used.
...
// Evaluate in scope of main module
py::object scope = py::module::import("__main__").attr("__dict__");
py::object scope = py::module_::import("__main__").attr("__dict__");
// Evaluate an isolated expression
int result = py::eval("my_variable + 10", scope).cast<int>();

View File

@ -118,8 +118,8 @@ a file named :file:`example.cpp` with the following contents:
The :func:`PYBIND11_MODULE` macro creates a function that will be called when an
``import`` statement is issued from within Python. The module name (``example``)
is given as the first macro argument (it should not be in quotes). The second
argument (``m``) defines a variable of type :class:`py::module <module>` which
is the main interface for creating bindings. The method :func:`module::def`
argument (``m``) defines a variable of type :class:`py::module_ <module>` which
is the main interface for creating bindings. The method :func:`module_::def`
generates binding code that exposes the ``add()`` function to Python.
.. note::
@ -181,7 +181,7 @@ names of the arguments ("i" and "j" in this case).
py::arg("i"), py::arg("j"));
:class:`arg` is one of several special tag classes which can be used to pass
metadata into :func:`module::def`. With this modified binding code, we can now
metadata into :func:`module_::def`. With this modified binding code, we can now
call the function using keyword arguments, which is a more readable alternative
particularly for functions taking many parameters:

View File

@ -11,9 +11,9 @@ v2.6.0 (IN PROGRESS)
See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
* Provide an additional spelling of ``py::module`` - ``py::module_`` (with a
trailing underscore), for C++20 compatibility. Only relevant when used
unqualified.
* ``py::module`` was renamed ``py::module_`` to avoid issues with C++20 when
used unqualified, but an alias ``py::module`` is provided for backward
compatibility.
`#2489 <https://github.com/pybind/pybind11/pull/2489>`_
* ``pybind11_add_module()`` now accepts an optional ``OPT_SIZE`` flag that
@ -529,7 +529,7 @@ v2.2.2 (February 7, 2018)
v2.2.1 (September 14, 2017)
-----------------------------------------------------
* Added ``py::module::reload()`` member function for reloading a module.
* Added ``py::module_::reload()`` member function for reloading a module.
`#1040 <https://github.com/pybind/pybind11/pull/1040>`_.
* Fixed a reference leak in the number converter.

View File

@ -100,8 +100,8 @@ following example:
.. code-block:: cpp
void init_ex1(py::module &);
void init_ex2(py::module &);
void init_ex1(py::module_ &);
void init_ex2(py::module_ &);
/* ... */
PYBIND11_MODULE(example, m) {
@ -114,7 +114,7 @@ following example:
.. code-block:: cpp
void init_ex1(py::module &m) {
void init_ex1(py::module_ &m) {
m.def("add", [](int a, int b) { return a + b; });
}
@ -122,7 +122,7 @@ following example:
.. code-block:: cpp
void init_ex2(py::module &m) {
void init_ex2(py::module_ &m) {
m.def("sub", [](int a, int b) { return a - b; });
}

View File

@ -569,17 +569,17 @@ inline PyObject* make_new_python_type(const type_record &rec) {
#endif
}
object module;
object module_;
if (rec.scope) {
if (hasattr(rec.scope, "__module__"))
module = rec.scope.attr("__module__");
module_ = rec.scope.attr("__module__");
else if (hasattr(rec.scope, "__name__"))
module = rec.scope.attr("__name__");
module_ = rec.scope.attr("__name__");
}
auto full_name = c_str(
#if !defined(PYPY_VERSION)
module ? str(module).cast<std::string>() + "." + rec.name :
module_ ? str(module_).cast<std::string>() + "." + rec.name :
#endif
rec.name);
@ -658,8 +658,8 @@ inline PyObject* make_new_python_type(const type_record &rec) {
else
Py_INCREF(type); // Keep it alive forever (reference leak)
if (module) // Needed by pydoc
setattr((PyObject *) type, "__module__", module);
if (module_) // Needed by pydoc
setattr((PyObject *) type, "__module__", module_);
PYBIND11_SET_OLDPY_QUALNAME(type, qualname);

View File

@ -263,13 +263,13 @@ extern "C" {
***Deprecated in favor of PYBIND11_MODULE***
This macro creates the entry point that will be invoked when the Python interpreter
imports a plugin library. Please create a `module` in the function body and return
imports a plugin library. Please create a `module_` in the function body and return
the pointer to its underlying Python object at the end.
.. code-block:: cpp
PYBIND11_PLUGIN(example) {
pybind11::module m("example", "pybind11 example plugin");
pybind11::module_ m("example", "pybind11 example plugin");
/// Set up bindings here
return m.ptr();
}
@ -290,7 +290,7 @@ extern "C" {
This macro creates the entry point that will be invoked when the Python interpreter
imports an extension module. The module name is given as the fist argument and it
should not be in quotes. The second macro argument defines a variable of type
`py::module` which can be used to initialize the module.
`py::module_` which can be used to initialize the module.
The entry point is marked as "maybe unused" to aid dead-code detection analysis:
since the entry point is typically only looked up at runtime and not referenced
@ -317,12 +317,12 @@ extern "C" {
#else
#define PYBIND11_DETAIL_MODULE_STATIC_DEF(name)
#define PYBIND11_DETAIL_MODULE_CREATE(name) \
auto m = pybind11::module(PYBIND11_TOSTRING(name));
auto m = pybind11::module_(PYBIND11_TOSTRING(name));
#endif
#define PYBIND11_MODULE(name, variable) \
PYBIND11_DETAIL_MODULE_STATIC_DEF(name) \
PYBIND11_MAYBE_UNUSED \
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module_ &); \
PYBIND11_PLUGIN_IMPL(name) { \
PYBIND11_CHECK_PYTHON_VERSION \
PYBIND11_ENSURE_INTERNALS_READY \
@ -332,7 +332,7 @@ extern "C" {
return m.ptr(); \
} PYBIND11_CATCH_INIT_EXCEPTIONS \
} \
void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable)
void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module_ &variable)
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

View File

@ -549,7 +549,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
return false;
auto obj = reinterpret_borrow<object>(src);
object sparse_module = module::import("scipy.sparse");
object sparse_module = module_::import("scipy.sparse");
object matrix_type = sparse_module.attr(
rowMajor ? "csr_matrix" : "csc_matrix");
@ -580,7 +580,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
const_cast<Type&>(src).makeCompressed();
object matrix_type = module::import("scipy.sparse").attr(
object matrix_type = module_::import("scipy.sparse").attr(
rowMajor ? "csr_matrix" : "csc_matrix");
array data(src.nonZeros(), src.valuePtr());

View File

@ -46,9 +46,9 @@
}
\endrst */
#define PYBIND11_EMBEDDED_MODULE(name, variable) \
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &); \
static void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module_ &); \
static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \
auto m = pybind11::module(PYBIND11_TOSTRING(name)); \
auto m = pybind11::module_(PYBIND11_TOSTRING(name)); \
try { \
PYBIND11_CONCAT(pybind11_init_, name)(m); \
return m.ptr(); \
@ -64,7 +64,7 @@
pybind11::detail::embedded_module PYBIND11_CONCAT(pybind11_module_, name) \
(PYBIND11_TOSTRING(name), \
PYBIND11_CONCAT(pybind11_init_impl_, name)); \
void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module &variable)
void PYBIND11_CONCAT(pybind11_init_, name)(pybind11::module_ &variable)
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
@ -109,7 +109,7 @@ inline void initialize_interpreter(bool init_signal_handlers = true) {
Py_InitializeEx(init_signal_handlers ? 1 : 0);
// Make .py files in the working directory available by default
module::import("sys").attr("path").cast<list>().append(".");
module_::import("sys").attr("path").cast<list>().append(".");
}
/** \rst

View File

@ -52,7 +52,7 @@ object eval(str expr, object global = globals(), object local = object()) {
template <eval_mode mode = eval_expr, size_t N>
object eval(const char (&s)[N], object global = globals(), object local = object()) {
/* Support raw string literals by removing common leading whitespace */
auto expr = (s[0] == '\n') ? str(module::import("textwrap").attr("dedent")(s))
auto expr = (s[0] == '\n') ? str(module_::import("textwrap").attr("dedent")(s))
: str(s);
return eval<mode>(expr, global, local);
}

View File

@ -102,7 +102,7 @@ PYBIND11_NAMESPACE_END(detail)
.. code-block:: cpp
{
py::scoped_ostream_redirect output{std::cerr, py::module::import("sys").attr("stderr")};
py::scoped_ostream_redirect output{std::cerr, py::module_::import("sys").attr("stderr")};
std::cerr << "Hello, World!";
}
\endrst */
@ -115,7 +115,7 @@ protected:
public:
scoped_ostream_redirect(
std::ostream &costream = std::cout,
object pyostream = module::import("sys").attr("stdout"))
object pyostream = module_::import("sys").attr("stdout"))
: costream(costream), buffer(pyostream) {
old = costream.rdbuf(&buffer);
}
@ -146,7 +146,7 @@ class scoped_estream_redirect : public scoped_ostream_redirect {
public:
scoped_estream_redirect(
std::ostream &costream = std::cerr,
object pyostream = module::import("sys").attr("stderr"))
object pyostream = module_::import("sys").attr("stderr"))
: scoped_ostream_redirect(costream,pyostream) {}
};
@ -206,7 +206,7 @@ PYBIND11_NAMESPACE_END(detail)
m.noisy_function_with_error_printing()
\endrst */
inline class_<detail::OstreamRedirect> add_ostream_redirect(module m, std::string name = "ostream_redirect") {
inline class_<detail::OstreamRedirect> add_ostream_redirect(module_ m, std::string name = "ostream_redirect") {
return class_<detail::OstreamRedirect>(m, name.c_str(), module_local())
.def(init<bool,bool>(), arg("stdout")=true, arg("stderr")=true)
.def("__enter__", &detail::OstreamRedirect::enter)

View File

@ -222,7 +222,7 @@ private:
};
static npy_api lookup() {
module_ m = module::import("numpy.core.multiarray");
module_ m = module_::import("numpy.core.multiarray");
auto c = m.attr("_ARRAY_API");
#if PY_MAJOR_VERSION >= 3
void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL);
@ -505,7 +505,7 @@ public:
private:
static object _dtype_from_pep3118() {
static PyObject *obj = module::import("numpy.core._internal")
static PyObject *obj = module_::import("numpy.core._internal")
.attr("_dtype_from_pep3118").cast<object>().release().ptr();
return reinterpret_borrow<object>(obj);
}

View File

@ -904,9 +904,9 @@ public:
.. code-block:: cpp
py::module m("example", "pybind11 example plugin");
py::module m2 = m.def_submodule("sub", "A submodule of 'example'");
py::module m3 = m2.def_submodule("subsub", "A submodule of 'example.sub'");
py::module_ m("example", "pybind11 example plugin");
py::module_ m2 = m.def_submodule("sub", "A submodule of 'example'");
py::module_ m3 = m2.def_submodule("subsub", "A submodule of 'example.sub'");
\endrst */
module_ def_submodule(const char *name, const char *doc = nullptr) {
std::string full_name = std::string(PyModule_GetName(m_ptr))
@ -965,12 +965,15 @@ private:
};
m_ptr = PyModule_Create(def);
if (m_ptr == nullptr)
pybind11_fail("Internal error in module::module()");
pybind11_fail("Internal error in module_::module_()");
inc_ref();
}
#endif
};
// When inside a namespace (or anywhere as long as it's not the first item on a line),
// C++20 allows "module" to be used. This is provided for backward compatibility, and for
// simplicity, if someone wants to use py::module for example, that is perfectly safe.
using module = module_;
#if PY_MAJOR_VERSION >= 3
@ -986,7 +989,7 @@ PYBIND11_NAMESPACE_END(detail)
/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded).
inline dict globals() {
PyObject *p = PyEval_GetGlobals();
return reinterpret_borrow<dict>(p ? p : module::import("__main__").attr("__dict__").ptr());
return reinterpret_borrow<dict>(p ? p : module_::import("__main__").attr("__dict__").ptr());
}
PYBIND11_NAMESPACE_BEGIN(detail)
@ -1973,7 +1976,7 @@ PYBIND11_NOINLINE inline void print(tuple args, dict kwargs) {
file = kwargs["file"].cast<object>();
} else {
try {
file = module::import("sys").attr("stdout");
file = module_::import("sys").attr("stdout");
} catch (const error_already_set &) {
/* If print() is called from code that is executed as
part of garbage collection during interpreter shutdown,

View File

@ -120,7 +120,7 @@ public:
throw py::error_already_set();
Py_DECREF(result);
#else
py::module::import("gc").attr("collect")();
py::module_::import("gc").attr("collect")();
#endif
}

View File

@ -26,8 +26,8 @@ productively.
Instead, see the "How can I reduce the build time?" question in the "Frequently asked questions"
section of the documentation for good practice on splitting binding code over multiple files.
*/
std::list<std::function<void(py::module &)>> &initializers() {
static std::list<std::function<void(py::module &)>> inits;
std::list<std::function<void(py::module_ &)>> &initializers() {
static std::list<std::function<void(py::module_ &)>> inits;
return inits;
}
@ -36,13 +36,13 @@ test_initializer::test_initializer(Initializer init) {
}
test_initializer::test_initializer(const char *submodule_name, Initializer init) {
initializers().emplace_back([=](py::module &parent) {
initializers().emplace_back([=](py::module_ &parent) {
auto m = parent.def_submodule(submodule_name);
init(m);
});
}
void bind_ConstructorStats(py::module &m) {
void bind_ConstructorStats(py::module_ &m) {
py::class_<ConstructorStats>(m, "ConstructorStats")
.def("alive", &ConstructorStats::alive)
.def("values", &ConstructorStats::values)

View File

@ -10,7 +10,7 @@ namespace py = pybind11;
using namespace pybind11::literals;
class test_initializer {
using Initializer = void (*)(py::module &);
using Initializer = void (*)(py::module_ &);
public:
test_initializer(Initializer init);
@ -18,9 +18,9 @@ public:
};
#define TEST_SUBMODULE(name, variable) \
void test_submodule_##name(py::module &); \
void test_submodule_##name(py::module_ &); \
test_initializer name(#name, test_submodule_##name); \
void test_submodule_##name(py::module &variable)
void test_submodule_##name(py::module_ &variable)
/// Dummy type which is not exported anywhere -- something to trigger a conversion error

View File

@ -18,7 +18,7 @@ TEST_SUBMODULE(async_module, m) {
.def(py::init<>())
.def("__await__", [](const SupportsAsync& self) -> py::object {
static_cast<void>(self);
py::object loop = py::module::import("asyncio.events").attr("get_event_loop")();
py::object loop = py::module_::import("asyncio.events").attr("get_event_loop")();
py::object f = loop.attr("create_future")();
f.attr("set_result")(5);
return f.attr("__await__")();

View File

@ -172,12 +172,12 @@ TEST_SUBMODULE(class_, m) {
struct MismatchDerived2 : MismatchBase2 { };
m.def("mismatched_holder_1", []() {
auto mod = py::module::import("__main__");
auto mod = py::module_::import("__main__");
py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(mod, "MismatchBase1");
py::class_<MismatchDerived1, MismatchBase1>(mod, "MismatchDerived1");
});
m.def("mismatched_holder_2", []() {
auto mod = py::module::import("__main__");
auto mod = py::module_::import("__main__");
py::class_<MismatchBase2>(mod, "MismatchBase2");
py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>,
MismatchBase2>(mod, "MismatchDerived2");

View File

@ -12,10 +12,10 @@ int main(int argc, char *argv[]) {
py::scoped_interpreter guard{};
auto m = py::module::import("test_cmake_build");
auto m = py::module_::import("test_cmake_build");
if (m.attr("add")(1, 2).cast<int>() != 3)
throw std::runtime_error("embed.cpp failed");
py::module::import("sys").attr("argv") = py::make_tuple("test.py", "embed.cpp");
py::module_::import("sys").attr("argv") = py::make_tuple("test.py", "embed.cpp");
py::eval_file(test_py_file, py::globals());
}

View File

@ -317,11 +317,11 @@ TEST_SUBMODULE(eigen, m) {
// a new array (np.ones(10)) increases the chances that the temp array will be garbage
// collected and/or that its memory will be overridden with different values.
m.def("get_elem_direct", [](Eigen::Ref<const Eigen::VectorXd> v) {
py::module::import("numpy").attr("ones")(10);
py::module_::import("numpy").attr("ones")(10);
return v(5);
});
m.def("get_elem_indirect", [](std::vector<Eigen::Ref<const Eigen::VectorXd>> v) {
py::module::import("numpy").attr("ones")(10);
py::module_::import("numpy").attr("ones")(10);
return v[0](5);
});
}

View File

@ -51,17 +51,17 @@ PYBIND11_EMBEDDED_MODULE(throw_error_already_set, ) {
}
TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
auto module = py::module::import("test_interpreter");
REQUIRE(py::hasattr(module, "DerivedWidget"));
auto module_ = py::module_::import("test_interpreter");
REQUIRE(py::hasattr(module_, "DerivedWidget"));
auto locals = py::dict("hello"_a="Hello, World!", "x"_a=5, **module.attr("__dict__"));
auto locals = py::dict("hello"_a="Hello, World!", "x"_a=5, **module_.attr("__dict__"));
py::exec(R"(
widget = DerivedWidget("{} - {}".format(hello, x))
message = widget.the_message
)", py::globals(), locals);
REQUIRE(locals["message"].cast<std::string>() == "Hello, World! - 5");
auto py_widget = module.attr("DerivedWidget")("The question");
auto py_widget = module_.attr("DerivedWidget")("The question");
auto message = py_widget.attr("the_message");
REQUIRE(message.cast<std::string>() == "The question");
@ -70,10 +70,10 @@ TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
}
TEST_CASE("Import error handling") {
REQUIRE_NOTHROW(py::module::import("widget_module"));
REQUIRE_THROWS_WITH(py::module::import("throw_exception"),
REQUIRE_NOTHROW(py::module_::import("widget_module"));
REQUIRE_THROWS_WITH(py::module_::import("throw_exception"),
"ImportError: C++ Error");
REQUIRE_THROWS_WITH(py::module::import("throw_error_already_set"),
REQUIRE_THROWS_WITH(py::module_::import("throw_error_already_set"),
Catch::Contains("ImportError: KeyError"));
}
@ -107,14 +107,14 @@ bool has_pybind11_internals_static() {
TEST_CASE("Restart the interpreter") {
// Verify pre-restart state.
REQUIRE(py::module::import("widget_module").attr("add")(1, 2).cast<int>() == 3);
REQUIRE(py::module_::import("widget_module").attr("add")(1, 2).cast<int>() == 3);
REQUIRE(has_pybind11_internals_builtin());
REQUIRE(has_pybind11_internals_static());
REQUIRE(py::module::import("external_module").attr("A")(123).attr("value").cast<int>() == 123);
REQUIRE(py::module_::import("external_module").attr("A")(123).attr("value").cast<int>() == 123);
// local and foreign module internals should point to the same internals:
REQUIRE(reinterpret_cast<uintptr_t>(*py::detail::get_internals_pp()) ==
py::module::import("external_module").attr("internals_at")().cast<uintptr_t>());
py::module_::import("external_module").attr("internals_at")().cast<uintptr_t>());
// Restart the interpreter.
py::finalize_interpreter();
@ -130,14 +130,14 @@ TEST_CASE("Restart the interpreter") {
REQUIRE(has_pybind11_internals_builtin());
REQUIRE(has_pybind11_internals_static());
REQUIRE(reinterpret_cast<uintptr_t>(*py::detail::get_internals_pp()) ==
py::module::import("external_module").attr("internals_at")().cast<uintptr_t>());
py::module_::import("external_module").attr("internals_at")().cast<uintptr_t>());
// Make sure that an interpreter with no get_internals() created until finalize still gets the
// internals destroyed
py::finalize_interpreter();
py::initialize_interpreter();
bool ran = false;
py::module::import("__main__").attr("internals_destroy_test") =
py::module_::import("__main__").attr("internals_destroy_test") =
py::capsule(&ran, [](void *ran) { py::detail::get_internals(); *static_cast<bool *>(ran) = true; });
REQUIRE_FALSE(has_pybind11_internals_builtin());
REQUIRE_FALSE(has_pybind11_internals_static());
@ -149,20 +149,20 @@ TEST_CASE("Restart the interpreter") {
REQUIRE_FALSE(has_pybind11_internals_static());
// C++ modules can be reloaded.
auto cpp_module = py::module::import("widget_module");
auto cpp_module = py::module_::import("widget_module");
REQUIRE(cpp_module.attr("add")(1, 2).cast<int>() == 3);
// C++ type information is reloaded and can be used in python modules.
auto py_module = py::module::import("test_interpreter");
auto py_module = py::module_::import("test_interpreter");
auto py_widget = py_module.attr("DerivedWidget")("Hello after restart");
REQUIRE(py_widget.attr("the_message").cast<std::string>() == "Hello after restart");
}
TEST_CASE("Subinterpreter") {
// Add tags to the modules in the main interpreter and test the basics.
py::module::import("__main__").attr("main_tag") = "main interpreter";
py::module_::import("__main__").attr("main_tag") = "main interpreter";
{
auto m = py::module::import("widget_module");
auto m = py::module_::import("widget_module");
m.attr("extension_module_tag") = "added to module in main interpreter";
REQUIRE(m.attr("add")(1, 2).cast<int>() == 3);
@ -181,9 +181,9 @@ TEST_CASE("Subinterpreter") {
REQUIRE(has_pybind11_internals_static());
// Modules tags should be gone.
REQUIRE_FALSE(py::hasattr(py::module::import("__main__"), "tag"));
REQUIRE_FALSE(py::hasattr(py::module_::import("__main__"), "tag"));
{
auto m = py::module::import("widget_module");
auto m = py::module_::import("widget_module");
REQUIRE_FALSE(py::hasattr(m, "extension_module_tag"));
// Function bindings should still work.
@ -194,8 +194,8 @@ TEST_CASE("Subinterpreter") {
Py_EndInterpreter(sub_tstate);
PyThreadState_Swap(main_tstate);
REQUIRE(py::hasattr(py::module::import("__main__"), "main_tag"));
REQUIRE(py::hasattr(py::module::import("widget_module"), "extension_module_tag"));
REQUIRE(py::hasattr(py::module_::import("__main__"), "main_tag"));
REQUIRE(py::hasattr(py::module_::import("widget_module"), "extension_module_tag"));
}
TEST_CASE("Execution frame") {
@ -245,7 +245,7 @@ TEST_CASE("Reload module from file") {
// Disable generation of cached bytecode (.pyc files) for this test, otherwise
// Python might pick up an old version from the cache instead of the new versions
// of the .py files generated below
auto sys = py::module::import("sys");
auto sys = py::module_::import("sys");
bool dont_write_bytecode = sys.attr("dont_write_bytecode").cast<bool>();
sys.attr("dont_write_bytecode") = true;
// Reset the value at scope exit
@ -267,8 +267,8 @@ TEST_CASE("Reload module from file") {
});
// Import the module from file
auto module = py::module::import(module_name.c_str());
int result = module.attr("test")().cast<int>();
auto module_ = py::module_::import(module_name.c_str());
int result = module_.attr("test")().cast<int>();
REQUIRE(result == 1);
// Update the module .py file with a small change
@ -278,7 +278,7 @@ TEST_CASE("Reload module from file") {
test_module.close();
// Reload the module
module.reload();
result = module.attr("test")().cast<int>();
module_.reload();
result = module_.attr("test")().cast<int>();
REQUIRE(result == 2);
}

View File

@ -14,7 +14,7 @@
TEST_SUBMODULE(eval_, m) {
// test_evals
auto global = py::dict(py::module::import("__main__").attr("__dict__"));
auto global = py::dict(py::module_::import("__main__").attr("__dict__"));
m.def("test_eval_statements", [global]() {
auto local = py::dict();

View File

@ -163,7 +163,7 @@ TEST_SUBMODULE(exceptions, m) {
m.def("modulenotfound_exception_matches_base", []() {
try {
// On Python >= 3.6, this raises a ModuleNotFoundError, a subclass of ImportError
py::module::import("nonexistent");
py::module_::import("nonexistent");
}
catch (py::error_already_set &ex) {
if (!ex.matches(PyExc_ImportError)) throw;

View File

@ -142,7 +142,7 @@ public:
TEST_SUBMODULE(factory_constructors, m) {
// Define various trivial types to allow simpler overload resolution:
py::module m_tag = m.def_submodule("tag");
py::module_ m_tag = m.def_submodule("tag");
#define MAKE_TAG_TYPE(Name) \
struct Name##_tag {}; \
py::class_<Name##_tag>(m_tag, #Name "_tag").def(py::init<>()); \

View File

@ -45,7 +45,7 @@ TEST_SUBMODULE(gil_scoped, m) {
[](VirtClass &virt) { virt.pure_virtual_func(); });
m.def("test_cross_module_gil",
[]() {
auto cm = py::module::import("cross_module_gil_utils");
auto cm = py::module_::import("cross_module_gil_utils");
auto gil_acquire = reinterpret_cast<void (*)()>(
PyLong_AsVoidPtr(cm.attr("gil_acquire_funcaddr").ptr()));
py::gil_scoped_release gil_release;

View File

@ -37,7 +37,7 @@ TEST_SUBMODULE(iostream, m) {
});
m.def("captured_output", [](std::string msg) {
py::scoped_ostream_redirect redir(std::cout, py::module::import("sys").attr("stdout"));
py::scoped_ostream_redirect redir(std::cout, py::module_::import("sys").attr("stdout"));
std::cout << msg << std::flush;
});
@ -46,7 +46,7 @@ TEST_SUBMODULE(iostream, m) {
py::arg("msg"), py::arg("flush")=true);
m.def("captured_err", [](std::string msg) {
py::scoped_ostream_redirect redir(std::cerr, py::module::import("sys").attr("stderr"));
py::scoped_ostream_redirect redir(std::cerr, py::module_::import("sys").attr("stderr"));
std::cerr << msg << std::flush;
});
@ -65,8 +65,8 @@ TEST_SUBMODULE(iostream, m) {
});
m.def("captured_dual", [](std::string msg, std::string emsg) {
py::scoped_ostream_redirect redirout(std::cout, py::module::import("sys").attr("stdout"));
py::scoped_ostream_redirect redirerr(std::cerr, py::module::import("sys").attr("stderr"));
py::scoped_ostream_redirect redirout(std::cout, py::module_::import("sys").attr("stdout"));
py::scoped_ostream_redirect redirerr(std::cerr, py::module_::import("sys").attr("stderr"));
std::cout << msg << std::flush;
std::cerr << emsg << std::flush;
});

View File

@ -107,7 +107,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
return py::make_tuple(i, j, k, kwargs); },
py::arg() /* positional */, py::arg("j") = -1 /* both */, py::kw_only(), py::arg("k") /* kw-only */);
m.def("register_invalid_kw_only", [](py::module m) {
m.def("register_invalid_kw_only", [](py::module_ m) {
m.def("bad_kw_only", [](int i, int j) { return py::make_tuple(i, j); },
py::kw_only(), py::arg() /* invalid unnamed argument */, "j"_a);
});
@ -138,5 +138,5 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
// Make sure a class (not an instance) can be used as a default argument.
// The return value doesn't matter, only that the module is importable.
m.def("class_default_argument", [](py::object a) { return py::repr(a); },
"a"_a = py::module::import("decimal").attr("Decimal"));
"a"_a = py::module_::import("decimal").attr("Decimal"));
}

View File

@ -41,7 +41,7 @@ TEST_SUBMODULE(local_bindings, m) {
// should raise a runtime error from the duplicate definition attempt. If test_class isn't
// available it *also* throws a runtime error (with "test_class not enabled" as value).
m.def("register_local_external", [m]() {
auto main = py::module::import("pybind11_tests");
auto main = py::module_::import("pybind11_tests");
if (py::hasattr(main, "class_")) {
bind_local<LocalExternal, 7>(m, "LocalExternal", py::module_local());
}

View File

@ -207,12 +207,12 @@ TEST_SUBMODULE(methods_and_attributes, m) {
// test_no_mixed_overloads
// Raise error if trying to mix static/non-static overloads on the same name:
.def_static("add_mixed_overloads1", []() {
auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module_::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
emna.def ("overload_mixed1", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded))
.def_static("overload_mixed1", static_cast<py::str ( *)(float )>(&ExampleMandA::overloaded));
})
.def_static("add_mixed_overloads2", []() {
auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module_::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
emna.def_static("overload_mixed2", static_cast<py::str ( *)(float )>(&ExampleMandA::overloaded))
.def ("overload_mixed2", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded));
})
@ -308,11 +308,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
m.attr("debug_enabled") = false;
#endif
m.def("bad_arg_def_named", []{
auto m = py::module::import("pybind11_tests");
auto m = py::module_::import("pybind11_tests");
m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg("a") = UnregisteredType());
});
m.def("bad_arg_def_unnamed", []{
auto m = py::module::import("pybind11_tests");
auto m = py::module_::import("pybind11_tests");
m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg() = UnregisteredType());
});

View File

@ -13,6 +13,7 @@
TEST_SUBMODULE(modules, m) {
// test_nested_modules
// This is intentionally "py::module" to verify it still can be used in place of "py::module_"
py::module m_sub = m.def_submodule("subsubmodule");
m_sub.def("submodule_func", []() { return "submodule_func()"; });
@ -50,6 +51,7 @@ TEST_SUBMODULE(modules, m) {
.def_readwrite("a1", &B::a1) // def_readonly uses an internal reference return policy by default
.def_readwrite("a2", &B::a2);
// This is intentionally "py::module" to verify it still can be used in place of "py::module_"
m.attr("OD") = py::module::import("collections").attr("OrderedDict");
// test_duplicate_registration
@ -60,7 +62,7 @@ TEST_SUBMODULE(modules, m) {
class Dupe3 { };
class DupeException { };
auto dm = py::module("dummy");
auto dm = py::module_("dummy");
auto failures = py::list();
py::class_<Dupe1>(dm, "Dupe1");

View File

@ -22,7 +22,7 @@ struct DtypeCheck {
template <typename T>
DtypeCheck get_dtype_check(const char* name) {
py::module np = py::module::import("numpy");
py::module_ np = py::module_::import("numpy");
DtypeCheck check{};
check.numpy = np.attr("dtype")(np.attr(name));
check.pybind11 = py::dtype::of<T>();
@ -133,7 +133,7 @@ template <typename T, typename T2> py::handle auxiliaries(T &&r, T2 &&r2) {
static int data_i = 42;
TEST_SUBMODULE(numpy_array, sm) {
try { py::module::import("numpy"); }
try { py::module_::import("numpy"); }
catch (...) { return; }
// test_dtypes

View File

@ -255,7 +255,7 @@ struct A {};
struct B {};
TEST_SUBMODULE(numpy_dtypes, m) {
try { py::module::import("numpy"); }
try { py::module_::import("numpy"); }
catch (...) { return; }
// typeinfo may be registered before the dtype descriptor for scalar casts to work...

View File

@ -17,7 +17,7 @@ double my_func(int x, float y, double z) {
}
TEST_SUBMODULE(numpy_vectorize, m) {
try { py::module::import("numpy"); }
try { py::module_::import("numpy"); }
catch (...) { return; }
// test_vectorize, test_docs, test_array_collapse

View File

@ -289,7 +289,7 @@ TEST_SUBMODULE(pytypes, m) {
py::print("no new line here", "end"_a=" -- ");
py::print("next print");
auto py_stderr = py::module::import("sys").attr("stderr");
auto py_stderr = py::module_::import("sys").attr("stderr");
py::print("this goes to stderr", "file"_a=py_stderr);
py::print("flush", "flush"_a=true);

View File

@ -117,7 +117,7 @@ TEST_SUBMODULE(stl_binders, m) {
});
// The rest depends on numpy:
try { py::module::import("numpy"); }
try { py::module_::import("numpy"); }
catch (...) { return; }
// test_vector_buffer_numpy

View File

@ -187,7 +187,7 @@ static void test_gil_from_thread() {
// Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
// rather long).
void initialize_inherited_virtuals(py::module &m);
void initialize_inherited_virtuals(py::module_ &m);
TEST_SUBMODULE(virtual_functions, m) {
// test_override
@ -459,7 +459,7 @@ public:
};
*/
void initialize_inherited_virtuals(py::module &m) {
void initialize_inherited_virtuals(py::module_ &m) {
// test_inherited_virtuals
// Method 1: repeat