24 #ifndef PXR_USD_SDF_PY_SPEC_H 25 #define PXR_USD_SDF_PY_SPEC_H 67 #include "pxr/usd/sdf/api.h" 69 #include <boost/python/def_visitor.hpp> 70 #include <boost/python/dict.hpp> 71 #include <boost/python/errors.hpp> 72 #include <boost/python/raw_function.hpp> 73 #include <boost/python/pointee.hpp> 74 #include <boost/python/to_python_converter.hpp> 75 #include <boost/python/tuple.hpp> 77 #include "pxr/base/tf/pyError.h" 87 #include <type_traits> 99 PXR_NAMESPACE_OPEN_SCOPE
103 namespace Sdf_PySpecDetail {
105 namespace bp = boost::python;
107 SDF_API bp::object _DummyInit(bp::tuple
const & , bp::dict
const & );
109 template <
typename CTOR>
110 struct NewVisitor : bp::def_visitor<NewVisitor<CTOR> > {
112 NewVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
114 template <
typename CLS>
115 void visit(CLS& c)
const 129 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
130 c.attr(
"__new__") = c.attr(
"__new__");
131 c.def(
"__new__", CTOR::template __new__<CLS>, _doc.c_str());
132 c.staticmethod(
"__new__");
134 c.def(
"__init__", bp::raw_function(_DummyInit));
137 template <
class CLS,
class Options>
138 void visit(CLS& c,
char const* name, Options& options)
const 152 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
153 c.attr(
"__new__") = c.attr(
"__new__");
154 c.def(
"__new__", CTOR::template __new__<CLS>,
160 c.staticmethod(
"__new__");
162 c.def(
"__init__", bp::raw_function(_DummyInit));
166 const std::string _doc;
168 friend class bp::def_visitor_access;
171 template <
typename SIG>
177 static void SetFunc(Sig *func)
185 "Duplicate will be ignored.",
192 template <
typename SIG> SIG *CtorBase<SIG>::_func = 0;
194 template <
typename SIG>
struct NewCtor;
198 template <
typename T>
199 Sdf_PySpecDetail::NewVisitor<typename Sdf_PySpecDetail::NewCtor<T> >
200 SdfMakePySpecConstructor(T *func,
const std::string &doc = std::string())
203 Sdf_PySpecDetail::NewCtor<T> Ctor(func);
204 return Sdf_PySpecDetail::NewVisitor<Sdf_PySpecDetail::NewCtor<T> >(doc);
207 namespace Sdf_PySpecDetail {
210 SDF_API std::string _SpecRepr(
const bp::object&,
const SdfSpec*);
214 typedef PyObject* (*_HolderCreator)(
const SdfSpec&);
215 SDF_API
void _RegisterHolderCreator(
const std::type_info&, _HolderCreator);
216 SDF_API PyObject* _CreateHolder(
const std::type_info&,
const SdfSpec&);
218 template <
class _SpecType>
219 struct _ConstHandleToPython {
220 typedef _SpecType SpecType;
223 _ConstHandleToPython() {
224 bp::to_python_converter<ConstHandle, _ConstHandleToPython<SpecType> >();
226 static PyObject *convert(ConstHandle
const &p) {
227 return bp::incref(bp::object(TfConst_cast<Handle>(p)).ptr());
232 template <
class _SpecType,
class _Held,
class _Holder>
233 struct _HandleToPython {
235 typedef _SpecType SpecType;
236 typedef _Holder Holder;
237 typedef _Held Handle;
238 typedef _HandleToPython<SpecType, Handle, Holder> This;
240 static void Register()
242 _originalConverter = _RegisterConverter<Handle>(&This::_Convert);
243 _RegisterHolderCreator(
typeid(SpecType), &This::_Creator);
246 static PyObject* convert(
const Handle& x)
248 return _CreateHolder(
typeid(SpecType), x.GetSpec());
252 static PyObject* _Creator(
const SdfSpec& spec)
254 Handle x(Sdf_CastAccess::CastSpec<SpecType,SdfSpec>(spec));
255 return bp::objects::make_ptr_instance<SpecType, Holder>::execute(x);
260 bp::converter::to_python_function_t
261 _RegisterConverter(bp::converter::to_python_function_t f)
266 bp::converter::registration* r =
267 const_cast<bp::converter::registration*>(
268 bp::converter::registry::query(bp::type_id<T>()));
270 bp::converter::to_python_function_t old = r->m_to_python;
283 static PyObject* _Convert(
const void* p)
285 const Handle& x = *static_cast<const Handle*>(p);
286 return _CreateHolder(
typeid(SpecType), x.GetSpec());
290 static bp::converter::to_python_function_t _originalConverter;
292 template <
class SpecType,
class Held,
class Holder>
293 bp::converter::to_python_function_t
294 _HandleToPython<SpecType, Held, Holder>::_originalConverter = 0;
296 template <
class _SpecType>
297 struct _HandleFromPython {
298 typedef _SpecType SpecType;
303 bp::converter::registry::insert(&convertible, &construct,
304 bp::type_id<Handle>());
308 static void *convertible(PyObject *p)
313 bp::converter::get_lvalue_from_python(p,
314 bp::converter::registered<SpecType>::converters);
318 static void construct(PyObject* source,
319 bp::converter::rvalue_from_python_stage1_data* data)
321 void*
const storage =
322 ((bp::converter::rvalue_from_python_storage<Handle>*)
323 data)->storage.bytes;
325 if (data->convertible == source)
326 new (storage) Handle();
328 new (storage) Handle(*static_cast<SpecType*>(data->convertible));
330 data->convertible = storage;
335 template <
bool Abstract>
336 struct SpecVisitor : bp::def_visitor<SpecVisitor<Abstract> > {
338 template<
typename CLS>
340 typedef typename CLS::wrapped_type SpecType;
341 typedef typename CLS::metadata::held_type HeldType;
342 typedef typename CLS::metadata::held_type_arg HeldArgType;
343 typedef typename CLS::metadata::holder HolderType;
346 static std::string Repr(
const bp::object&
self)
348 const HeldType& held = bp::extract<const HeldType&>(
self);
349 return _SpecRepr(
self, get_pointer(held));
352 static bool IsExpired(
const HeldType&
self)
357 static bool NonZero(
const HeldType&
self)
362 static size_t __hash__(
const HeldType&
self)
367 static bool __eq__(
const HeldType& a,
const HeldType& b)
372 static bool __ne__(
const HeldType& a,
const HeldType& b)
377 static bool __lt__(
const HeldType& a,
const HeldType& b)
382 static bool __le__(
const HeldType& a,
const HeldType& b)
387 static bool __gt__(
const HeldType& a,
const HeldType& b)
392 static bool __ge__(
const HeldType& a,
const HeldType& b)
399 SpecVisitor(
bool addRepr =
true) : _addRepr(addRepr) { }
401 template <
typename CLS>
402 void visit(CLS& c)
const 404 typedef typename CLS::wrapped_type SpecType;
405 typedef typename CLS::metadata::held_type HeldType;
406 typedef typename CLS::metadata::held_type_arg HeldArgType;
407 typedef typename CLS::metadata::holder HolderType;
410 "HeldType must be SdfHandle<SpecType>.");
413 c.add_property(
"expired", &_Helper<CLS>::IsExpired);
414 c.def(TfPyBoolBuiltinFuncName, &_Helper<CLS>::NonZero);
415 c.def(
"__hash__", &_Helper<CLS>::__hash__);
416 c.def(
"__eq__", &_Helper<CLS>::__eq__);
417 c.def(
"__ne__", &_Helper<CLS>::__ne__);
418 c.def(
"__lt__", &_Helper<CLS>::__lt__);
419 c.def(
"__le__", &_Helper<CLS>::__le__);
420 c.def(
"__gt__", &_Helper<CLS>::__gt__);
421 c.def(
"__ge__", &_Helper<CLS>::__ge__);
424 _ConstHandleToPython<SpecType>();
427 _HandleFromPython<SpecType>();
428 _HandleFromPython<const SpecType>();
429 _HandleToPython<SpecType, HeldArgType, HolderType>::Register();
433 c.def(
"__repr__", &_Helper<CLS>::Repr);
444 Sdf_PySpecDetail::SpecVisitor<false>
447 return Sdf_PySpecDetail::SpecVisitor<false>();
451 Sdf_PySpecDetail::SpecVisitor<true>
454 return Sdf_PySpecDetail::SpecVisitor<true>();
458 Sdf_PySpecDetail::SpecVisitor<false>
461 return Sdf_PySpecDetail::SpecVisitor<false>(
false);
465 Sdf_PySpecDetail::SpecVisitor<true>
466 SdfPyAbstractSpecNoRepr()
468 return Sdf_PySpecDetail::SpecVisitor<true>(
false);
472 namespace Sdf_PySpecDetail
477 template <
typename R,
typename... Args>
478 struct NewCtor<R(Args...)> : CtorBase<R(Args...)> {
479 typedef CtorBase<R(Args...)> Base;
480 typedef typename Base::Sig Sig;
481 NewCtor(Sig *func) { Base::SetFunc(func); }
484 static bp::object __new__(bp::object &cls, Args... args) {
485 typedef typename CLS::metadata::held_type HeldType;
487 HeldType specHandle(Base::_func(args...));
488 if (TfPyConvertTfErrorsToPythonException(m))
489 bp::throw_error_already_set();
495 bp::detail::initialize_wrapper(result.ptr(), get_pointer(specHandle));
497 bp::setattr(result,
"__class__", cls);
505 PXR_NAMESPACE_CLOSE_SCOPE
507 #endif // PXR_USD_SDF_PY_SPEC_H #define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
Return demangled RTTI-generated type name.
Base class for all Sdf spec classes.
Definitions of basic string utilities in tf.
Low-level utilities for informing users of various internal and external diagnostic conditions.
boost::python::object TfPyObject(T const &t, bool complainOnFailure=true)
Return a python object for the given C++ object, loading the appropriate wrapper code if necessary.
Miscellaneous Utilities for dealing with script.
Demangle C++ typenames generated by the typeid() facility.
SdfHandle is a smart ptr that calls IsDormant() on the pointed-to object as an extra expiration check...
Class used to record the end of the error-list.
std::enable_if< std::is_same< Half, half >::value, size_t >::type hash_value(const Half &h)
Overload hash_value for half.
TF_API bool TfPyIsNone(boost::python::object const &obj)
Return true iff obj is None.
TF_API void TfPyThrowRuntimeError(std::string const &msg)
Raises a python RuntimError and throws a C++ exception.
A file containing basic constants and definitions.