set __module__ attribute of functions (fixes #95)

This commit is contained in:
Wenzel Jakob 2016-02-04 23:02:07 +01:00
parent de3ad07899
commit a65017902e
5 changed files with 91 additions and 58 deletions

View File

@ -1,19 +1,19 @@
Help on built-in function kw_func Help on built-in function kw_func in module example
kkww__ffuunncc(...) kkww__ffuunncc(...)
Signature : (x : int, y : int) -> NoneType Signature : (x : int, y : int) -> NoneType
Help on built-in function kw_func2 Help on built-in function kw_func2 in module example
kkww__ffuunncc22(...) kkww__ffuunncc22(...)
Signature : (x : int = 100L, y : int = 200L) -> NoneType Signature : (x : int = 100L, y : int = 200L) -> NoneType
Help on built-in function kw_func3 Help on built-in function kw_func3 in module example
kkww__ffuunncc33(...) kkww__ffuunncc33(...)
Signature : (data : unicode = u'Hello world!') -> NoneType Signature : (data : unicode = u'Hello world!') -> NoneType
Help on built-in function kw_func4 Help on built-in function kw_func4 in module example
kkww__ffuunncc44(...) kkww__ffuunncc44(...)
Signature : (myList : list<int> = [13L, 17L]) -> NoneType Signature : (myList : list<int> = [13L, 17L]) -> NoneType

View File

@ -3,6 +3,7 @@ from __future__ import print_function
import sys, pydoc import sys, pydoc
sys.path.append('.') sys.path.append('.')
import example
from example import Example2 from example import Example2
Example2.value = 15 Example2.value = 15
@ -54,3 +55,9 @@ print(instance.pair_passthrough((True, "test")))
print(instance.tuple_passthrough((True, "test", 5))) print(instance.tuple_passthrough((True, "test", 5)))
print(pydoc.render_doc(Example2, "Help on %s")) print(pydoc.render_doc(Example2, "Help on %s"))
print("__name__(example) = %s" % example.__name__)
print("__name__(example.Example2) = %s" % Example2.__name__)
print("__module__(example.Example2) = %s" % Example2.__module__)
print("__name__(example.Example2.get_set) = %s" % Example2.get_set.__name__)
print("__module__(example.Example2.get_set) = %s" % Example2.get_set.__module__)

View File

@ -1,11 +1,15 @@
key: key, value=value 15
5
example.Example2: No constructor defined!
can't set attribute
key: key2, value=value2 key: key2, value=value2
key: key, value=value key: key, value=value
key: key, value=value
key: key2, value=value2 key: key2, value=value2
key: key3 key: key3
key: key1
key: key2 key: key2
key: key1 key: key1
key: key1
key: key2 key: key2
key: key3 key: key3
Entry at positon 0: value Entry at positon 0: value
@ -13,107 +17,108 @@ list item 0: overwritten
list item 1: value2 list item 1: value2
list item 0: value list item 0: value
list item 1: value2 list item 1: value2
15
5
example.Example2: No constructor defined!
can't set attribute
This exception was intentionally thrown. This exception was intentionally thrown.
('test', True) (u'test', True)
(5, 'test', True) (5L, u'test', True)
Help on class Example2 in module example Help on class Example2 in module example
class EExxaammppllee22(builtins.object) class EExxaammppllee22(__builtin__.object)
| Example 2 documentation | Example 2 documentation
| |
| Methods defined here: | Methods defined here:
| |
| ____iinniitt____(self, /, *args, **kwargs) | ____iinniitt____(...)
| Initialize self. See help(type(self)) for accurate signature. | x.__init__(...) initializes x; see help(type(x)) for signature
| |
| ____nneeww____ = <built-in method __new__ of example.Example2_meta object> | ggeett__ddiicctt(...)
| ggeett__ddiicctt(...) from builtins.PyCapsule
| Signature : (example.Example2) -> dict | Signature : (example.Example2) -> dict
| |
| Return a Python dictionary | Return a Python dictionary
| |
| ggeett__ddiicctt__22(...) from builtins.PyCapsule | ggeett__ddiicctt__22(...)
| Signature : (example.Example2) -> dict<str, str> | Signature : (example.Example2) -> dict<unicode, unicode>
| |
| Return a C++ dictionary | Return a C++ dictionary
| |
| ggeett__lliisstt(...) from builtins.PyCapsule | ggeett__lliisstt(...)
| Signature : (example.Example2) -> list | Signature : (example.Example2) -> list
| |
| Return a Python list | Return a Python list
| |
| ggeett__lliisstt__22(...) from builtins.PyCapsule | ggeett__lliisstt__22(...)
| Signature : (example.Example2) -> list<str> | Signature : (example.Example2) -> list<unicode>
| |
| Return a C++ list | Return a C++ list
| |
| ggeett__sseett(...) from builtins.PyCapsule | ggeett__sseett(...)
| Signature : (example.Example2) -> set | Signature : (example.Example2) -> set
| |
| Return a Python set | Return a Python set
| |
| ggeett__sseett22(...) from builtins.PyCapsule | ggeett__sseett22(...)
| Signature : (example.Example2) -> set | Signature : (example.Example2) -> set
| |
| Return a C++ set | Return a C++ set
| |
| nneeww__iinnssttaannccee(...) from builtins.PyCapsule | ppaaiirr__ppaasssstthhrroouugghh(...)
| Signature : () -> example.Example2 | Signature : (example.Example2, (bool, unicode)) -> (unicode, bool)
|
| Return an instance
|
| ppaaiirr__ppaasssstthhrroouugghh(...) from builtins.PyCapsule
| Signature : (example.Example2, (bool, str)) -> (str, bool)
| |
| Return a pair in reversed order | Return a pair in reversed order
| |
| pprriinntt__ddiicctt(...) from builtins.PyCapsule | pprriinntt__ddiicctt(...)
| Signature : (example.Example2, dict) -> None | Signature : (example.Example2, dict) -> NoneType
| |
| Print entries of a Python dictionary | Print entries of a Python dictionary
| |
| pprriinntt__ddiicctt__22(...) from builtins.PyCapsule | pprriinntt__ddiicctt__22(...)
| Signature : (example.Example2, dict<str, str>) -> None | Signature : (example.Example2, dict<unicode, unicode>) -> NoneType
| |
| Print entries of a C++ dictionary | Print entries of a C++ dictionary
| |
| pprriinntt__lliisstt(...) from builtins.PyCapsule | pprriinntt__lliisstt(...)
| Signature : (example.Example2, list) -> None | Signature : (example.Example2, list) -> NoneType
| |
| Print entries of a Python list | Print entries of a Python list
| |
| pprriinntt__lliisstt__22(...) from builtins.PyCapsule | pprriinntt__lliisstt__22(...)
| Signature : (example.Example2, list<str>) -> None | Signature : (example.Example2, list<unicode>) -> NoneType
| |
| Print entries of a C++ list | Print entries of a C++ list
| |
| pprriinntt__sseett(...) from builtins.PyCapsule | pprriinntt__sseett(...)
| Signature : (example.Example2, set) -> None | Signature : (example.Example2, set) -> NoneType
| |
| Print entries of a Python set | Print entries of a Python set
| |
| pprriinntt__sseett__22(...) from builtins.PyCapsule | pprriinntt__sseett__22(...)
| Signature : (example.Example2, set<str>) -> None | Signature : (example.Example2, set<unicode>) -> NoneType
| |
| Print entries of a C++ set | Print entries of a C++ set
| |
| tthhrrooww__eexxcceeppttiioonn(...) from builtins.PyCapsule | tthhrrooww__eexxcceeppttiioonn(...)
| Signature : (example.Example2) -> None | Signature : (example.Example2) -> NoneType
| |
| Throw an exception | Throw an exception
| |
| ttuuppllee__ppaasssstthhrroouugghh(...) from builtins.PyCapsule | ttuuppllee__ppaasssstthhrroouugghh(...)
| Signature : (example.Example2, (bool, str, int)) -> (int, str, bool) | Signature : (example.Example2, (bool, unicode, int)) -> (int, unicode, bool)
| |
| Return a triple in reversed order | Return a triple in reversed order
| |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------
| Data and other attributes defined here: | Data and other attributes defined here:
| |
| ____ppyybbiinndd1111____ = <capsule object NULL> | ____nneeww____ = <built-in method __new__ of example.Example2__Meta object>
| T.__new__(S, ...) -> a new object with type S, a subtype of T
|
| nneeww__iinnssttaannccee = <built-in method new_instance of PyCapsule object>
| Signature : () -> example.Example2
|
| Return an instance
__name__(example) = example
__name__(example.Example2) = Example2
__module__(example.Example2) = example
__name__(example.Example2.get_set) = get_set
__module__(example.Example2.get_set) = example
Destructing Example2 Destructing Example2

View File

@ -36,6 +36,9 @@ template <typename T> arg_t<T> arg::operator=(const T &value) { return arg_t<T>(
/// Annotation for methods /// Annotation for methods
struct is_method { handle class_; is_method(const handle &c) : class_(c) { } }; struct is_method { handle class_; is_method(const handle &c) : class_(c) { } };
/// Annotation for parent scope
struct scope { handle value; scope(const handle &s) : value(s) { } };
/// Annotation for documentation /// Annotation for documentation
struct doc { const char *value; doc(const char *value) : value(value) { } }; struct doc { const char *value; doc(const char *value) : value(value) { } };
@ -105,6 +108,9 @@ struct function_record {
/// Python handle to the associated class (if this is method) /// Python handle to the associated class (if this is method)
handle class_; handle class_;
/// Python handle to the parent scope (a class or a module)
handle scope;
/// Python handle to the sibling function representing an overload chain /// Python handle to the sibling function representing an overload chain
handle sibling; handle sibling;
@ -190,9 +196,15 @@ template <> struct process_attribute<sibling> : process_attribute_default<siblin
/// Process an attribute which indicates that this function is a method /// Process an attribute which indicates that this function is a method
template <> struct process_attribute<is_method> : process_attribute_default<is_method> { template <> struct process_attribute<is_method> : process_attribute_default<is_method> {
static void init(const is_method &s, function_record *r) { r->class_ = s.class_; } static void init(const is_method &s, function_record *r) { r->class_ = s.class_; r->scope = s.class_; }
}; };
/// Process an attribute which indicates the parent scope of a method
template <> struct process_attribute<scope> : process_attribute_default<scope> {
static void init(const scope &s, function_record *r) { r->scope = s.value; }
};
/// Process a keyword argument attribute (*without* a default value) /// Process a keyword argument attribute (*without* a default value)
template <> struct process_attribute<arg> : process_attribute_default<arg> { template <> struct process_attribute<arg> : process_attribute_default<arg> {
static void init(const arg &a, function_record *r) { static void init(const arg &a, function_record *r) {

View File

@ -263,10 +263,19 @@ protected:
rec->def->ml_name = rec->name; rec->def->ml_name = rec->name;
rec->def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher); rec->def->ml_meth = reinterpret_cast<PyCFunction>(*dispatcher);
rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS; rec->def->ml_flags = METH_VARARGS | METH_KEYWORDS;
capsule rec_capsule(rec, [](PyObject *o) { capsule rec_capsule(rec, [](PyObject *o) {
destruct((detail::function_record *) PyCapsule_GetPointer(o, nullptr)); destruct((detail::function_record *) PyCapsule_GetPointer(o, nullptr));
}); });
m_ptr = PyCFunction_New(rec->def, rec_capsule.ptr());
object scope_module;
if (rec->scope) {
scope_module = (object) rec->scope.attr("__module__");
if (!scope_module)
scope_module = (object) rec->scope.attr("__name__");
}
m_ptr = PyCFunction_NewEx(rec->def, rec_capsule.ptr(), scope_module.ptr());
if (!m_ptr) if (!m_ptr)
pybind11_fail("cpp_function::cpp_function(): Could not allocate function object"); pybind11_fail("cpp_function::cpp_function(): Could not allocate function object");
} else { } else {
@ -467,7 +476,7 @@ public:
template <typename Func, typename... Extra> template <typename Func, typename... Extra>
module &def(const char *name_, Func &&f, const Extra& ... extra) { module &def(const char *name_, Func &&f, const Extra& ... extra) {
cpp_function func(std::forward<Func>(f), name(name_), cpp_function func(std::forward<Func>(f), name(name_),
sibling((handle) attr(name_)), extra...); sibling((handle) attr(name_)), scope(*this), extra...);
/* PyModule_AddObject steals a reference to 'func' */ /* PyModule_AddObject steals a reference to 'func' */
PyModule_AddObject(ptr(), name_, func.inc_ref().ptr()); PyModule_AddObject(ptr(), name_, func.inc_ref().ptr());
return *this; return *this;
@ -742,26 +751,26 @@ public:
template <typename Func, typename... Extra> class_ & template <typename Func, typename... Extra> class_ &
def_static(const char *name_, Func f, const Extra&... extra) { def_static(const char *name_, Func f, const Extra&... extra) {
cpp_function cf(std::forward<Func>(f), name(name_), cpp_function cf(std::forward<Func>(f), name(name_),
sibling(attr(name_)), extra...); sibling(attr(name_)), scope(*this), extra...);
attr(cf.name()) = cf; attr(cf.name()) = cf;
return *this; return *this;
} }
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra> template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra&... extra) { class_ &def(const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
op.template execute<type>(*this, extra...); op.template execute<type>(*this, is_method(*this), extra...);
return *this; return *this;
} }
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra> template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
class_ & def_cast(const detail::op_<id, ot, L, R> &op, const Extra&... extra) { class_ & def_cast(const detail::op_<id, ot, L, R> &op, const Extra&... extra) {
op.template execute_cast<type>(*this, extra...); op.template execute_cast<type>(*this, is_method(*this), extra...);
return *this; return *this;
} }
template <typename... Args, typename... Extra> template <typename... Args, typename... Extra>
class_ &def(const detail::init<Args...> &init, const Extra&... extra) { class_ &def(const detail::init<Args...> &init, const Extra&... extra) {
init.template execute<type>(*this, extra...); init.template execute<type>(*this, is_method(*this), extra...);
return *this; return *this;
} }
@ -800,8 +809,8 @@ public:
template <typename D, typename... Extra> template <typename D, typename... Extra>
class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) { class_ &def_readwrite_static(const char *name, D *pm, const Extra& ...extra) {
cpp_function fget([pm](object) -> const D &{ return *pm; }, cpp_function fget([pm](object) -> const D &{ return *pm; },
return_value_policy::reference_internal, extra...), return_value_policy::reference_internal, scope(*this), extra...),
fset([pm](object, const D &value) { *pm = value; }, extra...); fset([pm](object, const D &value) { *pm = value; }, scope(*this), extra...);
def_property_static(name, fget, fset); def_property_static(name, fget, fset);
return *this; return *this;
} }
@ -809,7 +818,7 @@ public:
template <typename D, typename... Extra> template <typename D, typename... Extra>
class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) { class_ &def_readonly_static(const char *name, const D *pm, const Extra& ...extra) {
cpp_function fget([pm](object) -> const D &{ return *pm; }, cpp_function fget([pm](object) -> const D &{ return *pm; },
return_value_policy::reference_internal, extra...); return_value_policy::reference_internal, scope(*this), extra...);
def_property_readonly_static(name, fget); def_property_readonly_static(name, fget);
return *this; return *this;
} }