HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyClassMethod.h
Go to the documentation of this file.
1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the terms set forth in the LICENSE.txt file available at
5 // https://openusd.org/license.
6 //
7 #ifndef PXR_BASE_TF_PY_CLASS_METHOD_H
8 #define PXR_BASE_TF_PY_CLASS_METHOD_H
9 
10 #include "pxr/pxr.h"
11 
12 #include "pxr/external/boost/python/class.hpp"
13 #include "pxr/external/boost/python/dict.hpp"
14 #include "pxr/external/boost/python/object.hpp"
15 #include "pxr/external/boost/python/def_visitor.hpp"
16 
18 
19 namespace Tf_PyClassMethod {
20 
21 using namespace pxr_boost::python;
22 
23 // Visitor for wrapping functions as Python class methods.
24 // See typedef below for docs.
25 // This is very similar to the staticmethod() method on pxr_boost::python::class,
26 // except it uses PyClassMethod_New() instead of PyStaticMethod_New().
27 struct _TfPyClassMethod : def_visitor<_TfPyClassMethod>
28 {
29  friend class def_visitor_access;
30 
31  _TfPyClassMethod(const std::string &methodName) :
32  _methodName(methodName) {}
33  explicit _TfPyClassMethod(const char *methodName) :
34  _methodName(methodName) {}
35 
36  template <typename CLS>
37  void visit(CLS &c) const
38  {
39  PyTypeObject* self = downcast<PyTypeObject>( c.ptr() );
40  dict d((handle<>(borrowed(self->tp_dict))));
41 
42  object method(d[_methodName]);
43 
44  c.attr(_methodName.c_str()) = object(
45  handle<>( PyClassMethod_New((_CallableCheck)(method.ptr()) )));
46  }
47 
48 private:
49 
50  PyObject* _CallableCheck(PyObject* callable) const
51  {
52  if (PyCallable_Check(expect_non_null(callable)))
53  return callable;
54 
55  PyErr_Format( PyExc_TypeError,
56  "classmethod expects callable object; got an object of type %s, "
57  "which is not callable",
58  callable->ob_type->tp_name);
59 
60  throw_error_already_set();
61  return 0;
62  }
63 
64  const std::string _methodName;
65 };
66 
67 }
68 
69 /// A boost.python class visitor which replaces the named method with a
70 /// classmethod()-wrapped one.
71 ///
72 /// \code
73 /// void Foo( pxr_boost::python::object & pyClassObject ) { /* ... */ }
74 ///
75 /// class_<...>(...)
76 /// .def("Foo", &Foo)
77 /// .def(TfPyClassMethod("Foo"))
78 /// ;
79 /// \endcode
80 ///
82 
84 
85 #endif // PXR_BASE_TF_PY_CLASS_METHOD_H
Tf_PyClassMethod::_TfPyClassMethod TfPyClassMethod
Definition: pyClassMethod.h:81
_TfPyClassMethod(const std::string &methodName)
Definition: pyClassMethod.h:31
_TfPyClassMethod(const char *methodName)
Definition: pyClassMethod.h:33
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
Definition: path.h:1425
#define PXR_NAMESPACE_CLOSE_SCOPE
Definition: pxr.h:74