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 "pxr/external/boost/python/def_visitor.hpp"
53#include "pxr/external/boost/python/dict.hpp"
54#include "pxr/external/boost/python/errors.hpp"
55#include "pxr/external/boost/python/raw_function.hpp"
56#include "pxr/external/boost/python/pointee.hpp"
57#include "pxr/external/boost/python/to_python_converter.hpp"
58#include "pxr/external/boost/python/tuple.hpp"
60#include "pxr/base/tf/pyError.h"
72namespace PXR_BOOST_NAMESPACE {
83PXR_NAMESPACE_OPEN_SCOPE
87namespace Sdf_PySpecDetail {
89namespace bp = pxr_boost::python;
91SDF_API bp::object _DummyInit(bp::tuple
const & , bp::dict
const & );
93template <
typename CTOR>
94struct NewVisitor : bp::def_visitor<NewVisitor<CTOR> > {
96 NewVisitor(
const std::string &doc = std::string()) : _doc(doc) {}
98 template <
typename CLS>
99 void visit(CLS& c)
const
113 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
114 c.attr(
"__new__") = c.attr(
"__new__");
115 c.def(
"__new__", CTOR::template __new__<CLS>, _doc.c_str());
116 c.staticmethod(
"__new__");
118 c.def(
"__init__", bp::raw_function(_DummyInit));
121 template <
class CLS,
class Options>
122 void visit(CLS& c,
char const* name, Options& options)
const
136 if (PyObject_HasAttrString(c.ptr(),
"__new__"))
137 c.attr(
"__new__") = c.attr(
"__new__");
138 c.def(
"__new__", CTOR::template __new__<CLS>,
144 c.staticmethod(
"__new__");
146 c.def(
"__init__", bp::raw_function(_DummyInit));
150 const std::string _doc;
152 friend class bp::def_visitor_access;
155template <
typename SIG>
161 static void SetFunc(Sig *func)
169 "Duplicate will be ignored.",
176template <
typename SIG> SIG *CtorBase<SIG>::_func = 0;
178template <
typename SIG>
struct NewCtor;
183Sdf_PySpecDetail::NewVisitor<typename Sdf_PySpecDetail::NewCtor<T> >
184SdfMakePySpecConstructor(T *func,
const std::string &doc = std::string())
187 Sdf_PySpecDetail::NewCtor<T> Ctor(func);
188 return Sdf_PySpecDetail::NewVisitor<Sdf_PySpecDetail::NewCtor<T> >(doc);
191namespace Sdf_PySpecDetail {
194SDF_API std::string _SpecRepr(
const bp::object&,
const SdfSpec*);
198typedef PyObject* (*_HolderCreator)(
const SdfSpec&);
199SDF_API
void _RegisterHolderCreator(
const std::type_info&, _HolderCreator);
200SDF_API PyObject* _CreateHolder(
const std::type_info&,
const SdfSpec&);
202template <
class _SpecType>
203struct _ConstHandleToPython {
204 typedef _SpecType SpecType;
207 _ConstHandleToPython() {
208 bp::to_python_converter<ConstHandle, _ConstHandleToPython<SpecType> >();
210 static PyObject *convert(ConstHandle
const &p) {
211 return bp::incref(bp::object(TfConst_cast<Handle>(p)).ptr());
216template <
class _SpecType,
class _Held,
class _Holder>
217struct _HandleToPython {
219 typedef _SpecType SpecType;
220 typedef _Holder Holder;
221 typedef _Held Handle;
222 typedef _HandleToPython<SpecType, Handle, Holder> This;
224 static void Register()
226 _originalConverter = _RegisterConverter<Handle>(&This::_Convert);
227 _RegisterHolderCreator(
typeid(SpecType), &This::_Creator);
230 static PyObject* convert(
const Handle& x)
232 return _CreateHolder(
typeid(SpecType), x.GetSpec());
236 static PyObject* _Creator(
const SdfSpec& spec)
238 Handle x(Sdf_CastAccess::CastSpec<SpecType,SdfSpec>(spec));
239 return bp::objects::make_ptr_instance<SpecType, Holder>::execute(x);
244 bp::converter::to_python_function_t
245 _RegisterConverter(bp::converter::to_python_function_t f)
250 bp::converter::registration* r =
251 const_cast<bp::converter::registration*
>(
252 bp::converter::registry::query(bp::type_id<T>()));
254 bp::converter::to_python_function_t old = r->m_to_python;
267 static PyObject* _Convert(
const void* p)
269 const Handle& x = *
static_cast<const Handle*
>(p);
270 return _CreateHolder(
typeid(SpecType), x.GetSpec());
274 static bp::converter::to_python_function_t _originalConverter;
276template <
class SpecType,
class Held,
class Holder>
277bp::converter::to_python_function_t
278_HandleToPython<SpecType, Held, Holder>::_originalConverter = 0;
280template <
class _SpecType>
281struct _HandleFromPython {
282 typedef _SpecType SpecType;
287 bp::converter::registry::insert(&convertible, &construct,
288 bp::type_id<Handle>());
292 static void *convertible(PyObject *p)
297 bp::converter::get_lvalue_from_python(p,
298 bp::converter::registered<SpecType>::converters);
302 static void construct(PyObject* source,
303 bp::converter::rvalue_from_python_stage1_data* data)
305 void*
const storage =
306 ((bp::converter::rvalue_from_python_storage<Handle>*)
307 data)->storage.bytes;
309 if (data->convertible == source)
310 new (storage) Handle();
312 new (storage) Handle(*
static_cast<SpecType*
>(data->convertible));
314 data->convertible = storage;
319template <
bool Abstract>
320struct SpecVisitor : bp::def_visitor<SpecVisitor<Abstract> > {
322 template<
typename CLS>
324 typedef typename CLS::wrapped_type SpecType;
325 typedef typename CLS::metadata::held_type HeldType;
326 typedef typename CLS::metadata::held_type_arg HeldArgType;
327 typedef typename CLS::metadata::holder HolderType;
330 static std::string Repr(
const bp::object& self)
332 const HeldType& held = bp::extract<const HeldType&>(self);
333 return _SpecRepr(self, get_pointer(held));
336 static bool IsExpired(
const HeldType& self)
341 static bool IsValid(
const HeldType& self)
346 static size_t __hash__(
const HeldType& self)
351 static bool __eq__(
const HeldType& a,
const HeldType& b)
356 static bool __ne__(
const HeldType& a,
const HeldType& b)
361 static bool __lt__(
const HeldType& a,
const HeldType& b)
366 static bool __le__(
const HeldType& a,
const HeldType& b)
371 static bool __gt__(
const HeldType& a,
const HeldType& b)
376 static bool __ge__(
const HeldType& a,
const HeldType& b)
383 SpecVisitor(
bool addRepr =
true) : _addRepr(addRepr) { }
385 template <
typename CLS>
386 void visit(CLS& c)
const
388 typedef typename CLS::wrapped_type SpecType;
389 typedef typename CLS::metadata::held_type HeldType;
390 typedef typename CLS::metadata::held_type_arg HeldArgType;
391 typedef typename CLS::metadata::holder HolderType;
393 static_assert(std::is_same<HeldType, SdfHandle<SpecType> >::value,
394 "HeldType must be SdfHandle<SpecType>.");
397 c.add_property(
"expired", &_Helper<CLS>::IsExpired);
398 c.def(
"__bool__", &_Helper<CLS>::IsValid);
399 c.def(
"__hash__", &_Helper<CLS>::__hash__);
400 c.def(
"__eq__", &_Helper<CLS>::__eq__);
401 c.def(
"__ne__", &_Helper<CLS>::__ne__);
402 c.def(
"__lt__", &_Helper<CLS>::__lt__);
403 c.def(
"__le__", &_Helper<CLS>::__le__);
404 c.def(
"__gt__", &_Helper<CLS>::__gt__);
405 c.def(
"__ge__", &_Helper<CLS>::__ge__);
408 _ConstHandleToPython<SpecType>();
411 _HandleFromPython<SpecType>();
412 _HandleFromPython<const SpecType>();
413 _HandleToPython<SpecType, HeldArgType, HolderType>::Register();
417 c.def(
"__repr__", &_Helper<CLS>::Repr);
428Sdf_PySpecDetail::SpecVisitor<false>
431 return Sdf_PySpecDetail::SpecVisitor<false>();
435Sdf_PySpecDetail::SpecVisitor<true>
438 return Sdf_PySpecDetail::SpecVisitor<true>();
442Sdf_PySpecDetail::SpecVisitor<false>
445 return Sdf_PySpecDetail::SpecVisitor<false>(
false);
449Sdf_PySpecDetail::SpecVisitor<true>
450SdfPyAbstractSpecNoRepr()
452 return Sdf_PySpecDetail::SpecVisitor<true>(
false);
456namespace Sdf_PySpecDetail
461template <
typename R,
typename... Args>
462struct NewCtor<R(Args...)> : CtorBase<R(Args...)> {
463 typedef CtorBase<R(Args...)> Base;
464 typedef typename Base::Sig Sig;
465 NewCtor(Sig *func) { Base::SetFunc(func); }
468 static bp::object __new__(bp::object &cls, Args... args) {
469 typedef typename CLS::metadata::held_type HeldType;
471 HeldType specHandle(Base::_func(args...));
472 if (TfPyConvertTfErrorsToPythonException(m))
473 bp::throw_error_already_set();
479 bp::detail::initialize_wrapper(result.ptr(), get_pointer(specHandle));
481 bp::setattr(result,
"__class__", cls);
489PXR_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 pxr_boost::python::error_already_s...
TF_API bool TfPyIsNone(pxr_boost::python::object const &obj)
Return true iff obj is None.
pxr_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.