7#ifndef PXR_USD_SDF_PY_SPEC_H
8#define PXR_USD_SDF_PY_SPEC_H
50#include "pxr/usd/sdf/api.h"
52#include <boost/python/def_visitor.hpp>
53#include <boost/python/dict.hpp>
54#include <boost/python/errors.hpp>
55#include <boost/python/raw_function.hpp>
56#include <boost/python/pointee.hpp>
57#include <boost/python/to_python_converter.hpp>
58#include <boost/python/tuple.hpp>
60#include "pxr/base/tf/pyError.h"
82PXR_NAMESPACE_OPEN_SCOPE
86namespace Sdf_PySpecDetail {
88namespace bp = boost::python;
90SDF_API bp::object _DummyInit(bp::tuple
const & , bp::dict
const & );
92template <
typename CTOR>
93struct NewVisitor : bp::def_visitor<NewVisitor<CTOR> > {
95 NewVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
97 template <
typename CLS>
98 void visit(CLS& c)
const
112 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
113 c.attr(
"__new__") = c.attr(
"__new__");
114 c.def(
"__new__", CTOR::template __new__<CLS>, _doc.c_str());
115 c.staticmethod(
"__new__");
117 c.def(
"__init__", bp::raw_function(_DummyInit));
120 template <
class CLS,
class Options>
121 void visit(CLS& c,
char const* name, Options& options)
const
135 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
136 c.attr(
"__new__") = c.attr(
"__new__");
137 c.def(
"__new__", CTOR::template __new__<CLS>,
143 c.staticmethod(
"__new__");
145 c.def(
"__init__", bp::raw_function(_DummyInit));
149 const std::string _doc;
151 friend class bp::def_visitor_access;
154template <
typename SIG>
160 static void SetFunc(Sig *func)
168 "Duplicate will be ignored.",
175template <
typename SIG> SIG *CtorBase<SIG>::_func = 0;
177template <
typename SIG>
struct NewCtor;
182Sdf_PySpecDetail::NewVisitor<typename Sdf_PySpecDetail::NewCtor<T> >
183SdfMakePySpecConstructor(T *func,
const std::string &doc = std::string())
186 Sdf_PySpecDetail::NewCtor<T> Ctor(func);
187 return Sdf_PySpecDetail::NewVisitor<Sdf_PySpecDetail::NewCtor<T> >(doc);
190namespace Sdf_PySpecDetail {
193SDF_API std::string _SpecRepr(
const bp::object&,
const SdfSpec*);
197typedef PyObject* (*_HolderCreator)(
const SdfSpec&);
198SDF_API
void _RegisterHolderCreator(
const std::type_info&, _HolderCreator);
199SDF_API PyObject* _CreateHolder(
const std::type_info&,
const SdfSpec&);
201template <
class _SpecType>
202struct _ConstHandleToPython {
203 typedef _SpecType SpecType;
206 _ConstHandleToPython() {
207 bp::to_python_converter<ConstHandle, _ConstHandleToPython<SpecType> >();
209 static PyObject *convert(ConstHandle
const &p) {
210 return bp::incref(bp::object(TfConst_cast<Handle>(p)).ptr());
215template <
class _SpecType,
class _Held,
class _Holder>
216struct _HandleToPython {
218 typedef _SpecType SpecType;
219 typedef _Holder Holder;
220 typedef _Held Handle;
221 typedef _HandleToPython<SpecType, Handle, Holder> This;
223 static void Register()
225 _originalConverter = _RegisterConverter<Handle>(&This::_Convert);
226 _RegisterHolderCreator(
typeid(SpecType), &This::_Creator);
229 static PyObject* convert(
const Handle& x)
231 return _CreateHolder(
typeid(SpecType), x.GetSpec());
235 static PyObject* _Creator(
const SdfSpec& spec)
237 Handle x(Sdf_CastAccess::CastSpec<SpecType,SdfSpec>(spec));
238 return bp::objects::make_ptr_instance<SpecType, Holder>::execute(x);
243 bp::converter::to_python_function_t
244 _RegisterConverter(bp::converter::to_python_function_t f)
249 bp::converter::registration* r =
250 const_cast<bp::converter::registration*
>(
251 bp::converter::registry::query(bp::type_id<T>()));
253 bp::converter::to_python_function_t old = r->m_to_python;
266 static PyObject* _Convert(
const void* p)
268 const Handle& x = *
static_cast<const Handle*
>(p);
269 return _CreateHolder(
typeid(SpecType), x.GetSpec());
273 static bp::converter::to_python_function_t _originalConverter;
275template <
class SpecType,
class Held,
class Holder>
276bp::converter::to_python_function_t
277_HandleToPython<SpecType, Held, Holder>::_originalConverter = 0;
279template <
class _SpecType>
280struct _HandleFromPython {
281 typedef _SpecType SpecType;
286 bp::converter::registry::insert(&convertible, &construct,
287 bp::type_id<Handle>());
291 static void *convertible(PyObject *p)
296 bp::converter::get_lvalue_from_python(p,
297 bp::converter::registered<SpecType>::converters);
301 static void construct(PyObject* source,
302 bp::converter::rvalue_from_python_stage1_data* data)
304 void*
const storage =
305 ((bp::converter::rvalue_from_python_storage<Handle>*)
306 data)->storage.bytes;
308 if (data->convertible == source)
309 new (storage) Handle();
311 new (storage) Handle(*
static_cast<SpecType*
>(data->convertible));
313 data->convertible = storage;
318template <
bool Abstract>
319struct SpecVisitor : bp::def_visitor<SpecVisitor<Abstract> > {
321 template<
typename CLS>
323 typedef typename CLS::wrapped_type SpecType;
324 typedef typename CLS::metadata::held_type HeldType;
325 typedef typename CLS::metadata::held_type_arg HeldArgType;
326 typedef typename CLS::metadata::holder HolderType;
329 static std::string Repr(
const bp::object& self)
331 const HeldType& held = bp::extract<const HeldType&>(self);
332 return _SpecRepr(self, get_pointer(held));
335 static bool IsExpired(
const HeldType& self)
340 static bool IsValid(
const HeldType& self)
345 static size_t __hash__(
const HeldType& self)
350 static bool __eq__(
const HeldType& a,
const HeldType& b)
355 static bool __ne__(
const HeldType& a,
const HeldType& b)
360 static bool __lt__(
const HeldType& a,
const HeldType& b)
365 static bool __le__(
const HeldType& a,
const HeldType& b)
370 static bool __gt__(
const HeldType& a,
const HeldType& b)
375 static bool __ge__(
const HeldType& a,
const HeldType& b)
382 SpecVisitor(
bool addRepr =
true) : _addRepr(addRepr) { }
384 template <
typename CLS>
385 void visit(CLS& c)
const
387 typedef typename CLS::wrapped_type SpecType;
388 typedef typename CLS::metadata::held_type HeldType;
389 typedef typename CLS::metadata::held_type_arg HeldArgType;
390 typedef typename CLS::metadata::holder HolderType;
392 static_assert(std::is_same<HeldType, SdfHandle<SpecType> >::value,
393 "HeldType must be SdfHandle<SpecType>.");
396 c.add_property(
"expired", &_Helper<CLS>::IsExpired);
397 c.def(
"__bool__", &_Helper<CLS>::IsValid);
398 c.def(
"__hash__", &_Helper<CLS>::__hash__);
399 c.def(
"__eq__", &_Helper<CLS>::__eq__);
400 c.def(
"__ne__", &_Helper<CLS>::__ne__);
401 c.def(
"__lt__", &_Helper<CLS>::__lt__);
402 c.def(
"__le__", &_Helper<CLS>::__le__);
403 c.def(
"__gt__", &_Helper<CLS>::__gt__);
404 c.def(
"__ge__", &_Helper<CLS>::__ge__);
407 _ConstHandleToPython<SpecType>();
410 _HandleFromPython<SpecType>();
411 _HandleFromPython<const SpecType>();
412 _HandleToPython<SpecType, HeldArgType, HolderType>::Register();
416 c.def(
"__repr__", &_Helper<CLS>::Repr);
427Sdf_PySpecDetail::SpecVisitor<false>
430 return Sdf_PySpecDetail::SpecVisitor<false>();
434Sdf_PySpecDetail::SpecVisitor<true>
437 return Sdf_PySpecDetail::SpecVisitor<true>();
441Sdf_PySpecDetail::SpecVisitor<false>
444 return Sdf_PySpecDetail::SpecVisitor<false>(
false);
448Sdf_PySpecDetail::SpecVisitor<true>
449SdfPyAbstractSpecNoRepr()
451 return Sdf_PySpecDetail::SpecVisitor<true>(
false);
455namespace Sdf_PySpecDetail
460template <
typename R,
typename... Args>
461struct NewCtor<R(Args...)> : CtorBase<R(Args...)> {
462 typedef CtorBase<R(Args...)> Base;
463 typedef typename Base::Sig Sig;
464 NewCtor(Sig *func) { Base::SetFunc(func); }
467 static bp::object __new__(bp::object &cls, Args... args) {
468 typedef typename CLS::metadata::held_type HeldType;
470 HeldType specHandle(Base::_func(args...));
471 if (TfPyConvertTfErrorsToPythonException(m))
472 bp::throw_error_already_set();
478 bp::detail::initialize_wrapper(result.ptr(), get_pointer(specHandle));
480 bp::setattr(result,
"__class__", cls);
488PXR_NAMESPACE_CLOSE_SCOPE
Low-level utilities for informing users of various internal and external diagnostic conditions.
Miscellaneous Utilities for dealing with script.
TF_API void TfPyThrowRuntimeError(const char *msg)
Raises a Python RuntimeError with the given error msg and throws a boost::python::error_already_set e...
TF_API bool TfPyIsNone(boost::python::object const &obj)
Return true iff obj is None.
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.
SdfHandle is a smart ptr that calls IsDormant() on the pointed-to object as an extra expiration check...
Base class for all Sdf spec classes.
Class used to record the end of the error-list.
Demangle C++ typenames generated by the typeid() facility.
std::string ArchGetDemangled()
Return demangled RTTI generated-type name.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definitions of basic string utilities in tf.
A file containing basic constants and definitions.
size_t hash_value(const TfToken &x)
Overload hash_value for TfToken.