-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deprecate public constructors of module_ class #2552
Changes from 3 commits
cddec78
4c41330
7e51331
a65a38b
0d0b596
f0927df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -868,32 +868,30 @@ class cpp_function : public function { | |
} | ||
}; | ||
|
||
|
||
#if PY_MAJOR_VERSION >= 3 | ||
class module_; | ||
|
||
PYBIND11_NAMESPACE_BEGIN(detail) | ||
#if PY_MAJOR_VERSION >= 3 | ||
inline module_ create_top_level_module(const char *name, const char *doc, PyModuleDef *def); | ||
PYBIND11_NAMESPACE_END(detail) | ||
#else | ||
inline module_ create_top_level_module(const char *name, const char *doc); | ||
#endif | ||
PYBIND11_NAMESPACE_END(detail) | ||
|
||
/// Wrapper for Python extension modules | ||
class module_ : public object { | ||
public: | ||
PYBIND11_OBJECT_DEFAULT(module_, object, PyModule_Check) | ||
|
||
/// Create a new top-level Python module with the given name and docstring | ||
explicit module_(const char *name, const char *doc = nullptr) | ||
PYBIND11_DEPRECATED("Use PYBIND11_MODULE, module_::def_submodule, or module_::import instead") | ||
explicit module_(const char *name, const char *doc = nullptr) { | ||
#if PY_MAJOR_VERSION >= 3 | ||
: module_(name, doc, new PyModuleDef()) {} | ||
*this = detail::create_top_level_module(name, doc, new PyModuleDef()); | ||
#else | ||
{ | ||
m_ptr = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr); | ||
if (m_ptr == nullptr) | ||
pybind11_fail("Internal error in module_::module_()"); | ||
inc_ref(); | ||
} | ||
*this = detail::create_top_level_module(name, doc); | ||
#endif | ||
} | ||
|
||
/** \rst | ||
Create Python binding for a new function within the module scope. ``Func`` | ||
|
@@ -946,55 +944,56 @@ class module_ : public object { | |
*this = reinterpret_steal<module_>(obj); | ||
} | ||
|
||
// Adds an object to the module using the given name. Throws if an object with the given name | ||
// already exists. | ||
// | ||
// overwrite should almost always be false: attempting to overwrite objects that pybind11 has | ||
// established will, in most cases, break things. | ||
/** \rst | ||
Adds an object to the module using the given name. Throws if an object with the given name | ||
already exists. | ||
|
||
``overwrite`` should almost always be false: attempting to overwrite objects that pybind11 has | ||
established will, in most cases, break things. | ||
\endrst */ | ||
PYBIND11_NOINLINE void add_object(const char *name, handle obj, bool overwrite = false) { | ||
if (!overwrite && hasattr(*this, name)) | ||
pybind11_fail("Error during initialization: multiple incompatible definitions with name \"" + | ||
std::string(name) + "\""); | ||
|
||
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */); | ||
} | ||
|
||
private: | ||
#if PY_MAJOR_VERSION >= 3 | ||
friend module_ detail::create_top_level_module(const char *, const char *, PyModuleDef *); | ||
|
||
explicit module_(const char *name, const char *doc, PyModuleDef *def) { | ||
def = new (def) PyModuleDef { // Placement new (not an allocation). | ||
/* m_base */ PyModuleDef_HEAD_INIT, | ||
/* m_name */ name, | ||
/* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr, | ||
/* m_size */ -1, | ||
/* m_methods */ nullptr, | ||
/* m_slots */ nullptr, | ||
/* m_traverse */ nullptr, | ||
/* m_clear */ nullptr, | ||
/* m_free */ nullptr | ||
}; | ||
m_ptr = PyModule_Create(def); | ||
if (m_ptr == nullptr) | ||
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 | ||
PYBIND11_NAMESPACE_BEGIN(detail) | ||
#if PY_MAJOR_VERSION >= 3 | ||
inline module_ create_top_level_module(const char *name, const char *doc, PyModuleDef *def) { | ||
return module_(name, doc, def); | ||
def = new (def) PyModuleDef { // Placement new (not an allocation). | ||
/* m_base */ PyModuleDef_HEAD_INIT, | ||
/* m_name */ name, | ||
/* m_doc */ options::show_user_defined_docstrings() ? doc : nullptr, | ||
/* m_size */ -1, | ||
/* m_methods */ nullptr, | ||
/* m_slots */ nullptr, | ||
/* m_traverse */ nullptr, | ||
/* m_clear */ nullptr, | ||
/* m_free */ nullptr | ||
}; | ||
auto m = PyModule_Create(def); | ||
if (m == nullptr) | ||
pybind11_fail("Internal error in detail::create_top_level_module()"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Idea 1: does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Answered in the main thread, but that was maybe not a great idea:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at the 3.7 sources, I see some code paths set an error for sure, but it's difficult to know if that's always the case. The bomb-proof solution would be something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might not need to add name to the error message, if it usually or hopefully always works with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Assuming error_already_set would show the name?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Myeah, or we just trust that this part of the API works in the same way? An I can't both throw There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't know; we don't control that, since that the message is already set by Python. It might be something as cryptic as "didn't manage to create a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, didn't add the name, as the |
||
// TODO: Should be reinterpret_steal, but Python also steals it again when returned from PyInit_... | ||
return reinterpret_borrow<module_>(m); | ||
} | ||
#else | ||
inline module_ create_top_level_module(const char *name, const char *doc) { | ||
auto m = Py_InitModule3(name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr); | ||
if (m == nullptr) | ||
pybind11_fail("Internal error in detail::create_top_level_module()"); | ||
return reinterpret_borrow<module_>(m); | ||
} | ||
PYBIND11_NAMESPACE_END(detail) | ||
#endif | ||
PYBIND11_NAMESPACE_END(detail) | ||
|
||
/// \ingroup python_builtins | ||
/// Return a dictionary representing the global variables in the current execution frame, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use PYBIND11_CATCH_INIT_EXCEPTIONS here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll pour that into another PR, yes.