24 #ifndef PXR_BASE_TF_PY_ENUM_H 25 #define PXR_BASE_TF_PY_ENUM_H 32 #include "pxr/base/tf/api.h" 33 #include "pxr/base/tf/pyObjWrapper.h" 35 #include "pxr/base/tf/type.h" 40 #include "pxr/base/tf/hashmap.h" 45 #include <boost/python/class.hpp> 46 #include <boost/python/converter/from_python.hpp> 47 #include <boost/python/converter/registered.hpp> 48 #include <boost/python/converter/rvalue_from_python_data.hpp> 49 #include <boost/python/list.hpp> 50 #include <boost/python/object.hpp> 51 #include <boost/python/operators.hpp> 52 #include <boost/python/refcount.hpp> 53 #include <boost/python/scope.hpp> 54 #include <boost/python/to_python_converter.hpp> 55 #include <boost/python/tuple.hpp> 59 PXR_NAMESPACE_OPEN_SCOPE
70 class Tf_PyEnumRegistry {
73 typedef Tf_PyEnumRegistry This;
77 virtual ~Tf_PyEnumRegistry();
87 void RegisterValue(
TfEnum const &e, boost::python::object
const &obj);
90 void RegisterEnumConversions() {
92 boost::python::to_python_converter<T, _EnumToPython<T> >();
99 struct _EnumFromPython {
101 boost::python::converter::registry::insert
102 (&convertible, &construct, boost::python::type_id<T>());
104 static void *convertible(PyObject *obj) {
105 TfHashMap<PyObject *, TfEnum, _ObjectHash>
const &o2e =
106 Tf_PyEnumRegistry::GetInstance()._objectsToEnums;
107 TfHashMap<PyObject *, TfEnum, _ObjectHash>::const_iterator
112 if (boost::is_same<T, TfEnum>::value ||
113 (boost::is_integral<T>::value && !boost::is_enum<T>::value))
114 return i != o2e.end() ? obj : 0;
116 return (i != o2e.end() && i->second.IsA<T>()) ? obj : 0;
118 static void construct(PyObject *src, boost::python::converter::
119 rvalue_from_python_stage1_data *data) {
121 ((boost::python::converter::
122 rvalue_from_python_storage<T> *)data)->storage.bytes;
123 new (storage) T(_GetEnumValue(src, (T *)0));
124 data->convertible = storage;
129 template <
typename U>
130 static U _GetEnumValue(PyObject *src, U *) {
131 return U(Tf_PyEnumRegistry::GetInstance()._objectsToEnums[src].
135 return Tf_PyEnumRegistry::GetInstance()._objectsToEnums[src];
139 template <
typename T>
140 struct _EnumToPython {
141 static PyObject *convert(T
const &t);
147 size_t operator()(PyObject *o)
const {
148 return reinterpret_cast<size_t>(o);
152 TfHashMap<TfEnum, PyObject *, TfHash> _enumsToObjects;
153 TfHashMap<PyObject *, TfEnum, _ObjectHash> _objectsToEnums;
161 std::string Tf_PyEnumRepr(boost::python::object
const &
self);
165 struct Tf_PyEnumWrapper
166 :
public Tf_PyEnum, boost::totally_ordered<Tf_PyEnumWrapper>
168 typedef Tf_PyEnumWrapper This;
170 Tf_PyEnumWrapper(std::string
const &n,
TfEnum const &val) :
171 name(n), value(val) {}
172 long GetValue()
const {
173 return value.GetValueAsInt();
175 std::string GetName()
const{
178 std::string GetDisplayName()
const {
181 std::string GetFullName()
const {
184 friend bool operator ==(Tf_PyEnumWrapper
const &
self,
186 return self.value.GetValueAsInt() == other;
189 friend bool operator ==(Tf_PyEnumWrapper
const &lhs,
190 Tf_PyEnumWrapper
const &rhs) {
191 return lhs.value == rhs.value;
194 friend bool operator <(Tf_PyEnumWrapper
const &lhs,
195 Tf_PyEnumWrapper
const &rhs)
201 if (!lhs.value.IsA(rhs.value.GetType()))
205 return lhs.GetValue() < rhs.GetValue();
215 friend TfEnum operator |(Tf_PyEnumWrapper
const &lhs,
216 Tf_PyEnumWrapper
const &rhs) {
217 if (lhs.value.IsA(rhs.value.GetType())) {
218 return TfEnum(lhs.value.GetType(),
219 lhs.value.GetValueAsInt() |
220 rhs.value.GetValueAsInt());
225 friend TfEnum operator |(Tf_PyEnumWrapper
const &lhs,
long rhs) {
226 return TfEnum(lhs.value.GetType(), lhs.value.GetValueAsInt() | rhs);
228 friend TfEnum operator |(
long lhs, Tf_PyEnumWrapper
const &rhs) {
229 return TfEnum(rhs.value.GetType(), lhs | rhs.value.GetValueAsInt());
232 friend TfEnum operator &(Tf_PyEnumWrapper
const &lhs,
233 Tf_PyEnumWrapper
const &rhs) {
234 if (lhs.value.IsA(rhs.value.GetType())) {
235 return TfEnum(lhs.value.GetType(),
236 lhs.value.GetValueAsInt() &
237 rhs.value.GetValueAsInt());
242 friend TfEnum operator &(Tf_PyEnumWrapper
const &lhs,
long rhs) {
243 return TfEnum(lhs.value.GetType(), lhs.value.GetValueAsInt() & rhs);
245 friend TfEnum operator &(
long lhs, Tf_PyEnumWrapper
const &rhs) {
246 return TfEnum(rhs.value.GetType(), lhs & rhs.value.GetValueAsInt());
249 friend TfEnum operator ^(Tf_PyEnumWrapper
const &lhs,
250 Tf_PyEnumWrapper
const &rhs) {
251 if (lhs.value.IsA(rhs.value.GetType())) {
252 return TfEnum(lhs.value.GetType(),
253 lhs.value.GetValueAsInt() ^
254 rhs.value.GetValueAsInt());
259 friend TfEnum operator ^(Tf_PyEnumWrapper
const &lhs,
long rhs) {
260 return TfEnum(lhs.value.GetType(), lhs.value.GetValueAsInt() ^ rhs);
262 friend TfEnum operator ^(
long lhs, Tf_PyEnumWrapper
const &rhs) {
263 return TfEnum(rhs.value.GetType(), lhs ^ rhs.value.GetValueAsInt());
266 friend TfEnum operator ~(Tf_PyEnumWrapper
const &rhs) {
267 return TfEnum(rhs.value.GetType(), ~rhs.value.GetValueAsInt());
273 template <
typename T>
275 Tf_PyEnumRegistry::_EnumToPython<T>::convert(T
const &t)
281 if (!Tf_PyEnumRegistry::GetInstance()._enumsToObjects.count(e)) {
287 name =
"AutoGenerated_" + name +
"_" +
290 boost::python::object wrappedVal =
291 boost::python::object(Tf_PyEnumWrapper(name, e));
293 wrappedVal.attr(
"_baseName") = std::string();
295 Tf_PyEnumRegistry::GetInstance().RegisterValue(e, wrappedVal);
298 return boost::python::
299 incref(Tf_PyEnumRegistry::GetInstance()._enumsToObjects[e]);
304 template <
typename T>
305 struct Tf_TypedPyEnumWrapper : Tf_PyEnumWrapper
307 Tf_TypedPyEnumWrapper(std::string
const &n,
TfEnum const &val) :
308 Tf_PyEnumWrapper(n, val) {}
310 static boost::python::object GetValueFromName(
const std::string& name) {
312 const TfEnum value = TfEnum::GetValueFromName<T>(name, &found);
313 if (found)
return boost::python::object(value);
314 return boost::python::object();
325 std::string Tf_PyCleanEnumName(std::string name,
326 bool stripPackageName =
false);
331 void Tf_PyEnumAddAttribute(boost::python::scope &s,
332 const std::string &name,
333 const boost::python::object &value);
379 template <typename T, bool IsScopedEnum = !std::is_convertible<T, int>::value>
383 typedef boost::python::class_<
384 Tf_TypedPyEnumWrapper<T>, boost::python::bases<Tf_PyEnumWrapper> >
395 using namespace boost::python;
397 const bool explicitName = !name.empty();
400 std::string enumName = explicitName ? name :
406 if (baseName == enumName)
407 baseName = std::string();
416 if (!baseName.empty()) {
417 baseName = Tf_PyCleanEnumName(
421 enumName = Tf_PyCleanEnumName(
429 if (!baseName.empty()) {
432 baseName += enumName;
436 _EnumPyClassType enumClass(enumName.c_str(), no_init);
437 enumClass.def(
"GetValueFromName", &Tf_TypedPyEnumWrapper<T>::GetValueFromName, arg(
"name"));
438 enumClass.staticmethod(
"GetValueFromName");
439 enumClass.setattr(
"_baseName", baseName);
442 Tf_PyEnumRegistry::GetInstance().RegisterEnumConversions<T>();
450 const bool stripPackageName = baseName.empty();
451 _ExportValues(stripPackageName, enumClass);
456 const TfType &type = TfType::Find<T>();
466 void _ExportValues(
bool stripPackageName, _EnumPyClassType &enumClass) {
467 boost::python::list valueList;
469 for (
const std::string& name : TfEnum::GetAllNames<T>()) {
470 bool success =
false;
471 TfEnum enumValue = TfEnum::GetValueFromName<T>(name, &success);
476 const std::string cleanedName =
477 Tf_PyCleanEnumName(name, stripPackageName);
480 Tf_TypedPyEnumWrapper<T> wrappedValue(cleanedName, enumValue);
481 boost::python::object pyValue(wrappedValue);
484 Tf_PyEnumRegistry::GetInstance().RegisterValue(enumValue, pyValue);
487 std::string valueName = wrappedValue.GetName();
490 boost::python::scope s(enumClass);
491 Tf_PyEnumAddAttribute(s, valueName, pyValue);
494 boost::python::scope s;
495 Tf_PyEnumAddAttribute(s, valueName, pyValue);
498 valueList.append(pyValue);
502 enumClass.setattr(
"allValues", boost::python::tuple(valueList));
507 PXR_NAMESPACE_CLOSE_SCOPE
509 #endif // PXR_BASE_TF_PY_ENUM_H Manage a single instance of an object.
Manage a single instance of an object (see.
A simple iterator adapter for STL containers.
TF_API std::string TfStringGetBeforeSuffix(const std::string &name, char delimiter='.')
Returns everything up to the suffix of a string.
TF_API void DefinePythonClass(const TfPyObjWrapper &classObj) const
Define the Python class object corresponding to this TfType.
ARCH_API std::string ArchGetDemangled(const std::string &typeName)
Return demangled RTTI-generated type name.
Definitions of basic string utilities in tf.
An enum class that records both enum type and enum value.
Miscellaneous Utilities for dealing with script.
Demangle C++ typenames generated by the typeid() facility.
static TF_API std::string GetDisplayName(TfEnum val)
Returns the display name for an enumerated value.
static T & GetInstance()
Return a reference to an object of type T, creating it if necessary.
static TF_API std::string GetFullName(TfEnum val)
Returns the fully-qualified name for an enumerated value.
TF_API std::string TfStringGetSuffix(const std::string &name, char delimiter='.')
Returns the suffix of a string.
TF_API void TfPyThrowTypeError(std::string const &msg)
Raises a python TypeError and throws a C++ exception.
TfPyWrapEnum(std::string const &name=std::string())
Construct an enum wrapper object.
TfType represents a dynamic runtime type.
bool IsUnknown() const
Return true if this is the unknown type, representing a type unknown to the TfType system.
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
std::enable_if<!std::is_enum< T >::value, std::string >::type TfStringify(const T &v)
Convert an arbitrary type into a string.
Used to wrap enum types for script.
TF_API std::string TfStringReplace(const std::string &source, const std::string &from, const std::string &to)
Replaces all occurrences of string from with to in source.