7#ifndef PXR_BASE_TF_PY_ENUM_H
8#define PXR_BASE_TF_PY_ENUM_H
15#include "pxr/base/tf/api.h"
16#include "pxr/base/tf/pyObjWrapper.h"
18#include "pxr/base/tf/type.h"
23#include "pxr/base/tf/hashmap.h"
28#include "pxr/external/boost/python/class.hpp"
29#include "pxr/external/boost/python/converter/from_python.hpp"
30#include "pxr/external/boost/python/converter/registered.hpp"
31#include "pxr/external/boost/python/converter/rvalue_from_python_data.hpp"
32#include "pxr/external/boost/python/list.hpp"
33#include "pxr/external/boost/python/object.hpp"
34#include "pxr/external/boost/python/operators.hpp"
35#include "pxr/external/boost/python/refcount.hpp"
36#include "pxr/external/boost/python/scope.hpp"
37#include "pxr/external/boost/python/to_python_converter.hpp"
38#include "pxr/external/boost/python/tuple.hpp"
42PXR_NAMESPACE_OPEN_SCOPE
53class Tf_PyEnumRegistry {
56 typedef Tf_PyEnumRegistry This;
60 virtual ~Tf_PyEnumRegistry();
65 TF_API
static This &GetInstance() {
70 void RegisterValue(
TfEnum const &e, pxr_boost::python::object
const &obj);
73 void RegisterEnumConversions() {
75 pxr_boost::python::to_python_converter<T, _EnumToPython<T> >();
82 PyObject *_ConvertEnumToPython(
TfEnum const &e);
85 struct _EnumFromPython {
87 pxr_boost::python::converter::registry::insert
88 (&convertible, &construct, pxr_boost::python::type_id<T>());
90 static void *convertible(PyObject *obj) {
91 TfHashMap<PyObject *, TfEnum, _ObjectHash>
const &o2e =
92 Tf_PyEnumRegistry::GetInstance()._objectsToEnums;
93 TfHashMap<PyObject *, TfEnum, _ObjectHash>::const_iterator
98 if (std::is_same<T, TfEnum>::value ||
99 (std::is_integral<T>::value && !std::is_enum<T>::value))
100 return i != o2e.end() ? obj : 0;
102 return (i != o2e.end() && i->second.IsA<T>()) ? obj : 0;
104 static void construct(PyObject *src, pxr_boost::python::converter::
105 rvalue_from_python_stage1_data *data) {
107 ((pxr_boost::python::converter::
108 rvalue_from_python_storage<T> *)data)->storage.bytes;
109 new (storage) T(_GetEnumValue(src, (T *)0));
110 data->convertible = storage;
115 template <
typename U>
116 static U _GetEnumValue(PyObject *src, U *) {
117 return U(Tf_PyEnumRegistry::GetInstance()._objectsToEnums[src].
121 return Tf_PyEnumRegistry::GetInstance()._objectsToEnums[src];
126 struct _EnumToPython {
127 static PyObject *convert(T t) {
128 return Tf_PyEnumRegistry
129 ::GetInstance()._ConvertEnumToPython(
TfEnum(t));
136 size_t operator()(PyObject *o)
const {
137 return reinterpret_cast<size_t>(o);
141 TfHashMap<TfEnum, PyObject *, TfHash> _enumsToObjects;
142 TfHashMap<PyObject *, TfEnum, _ObjectHash> _objectsToEnums;
150std::string Tf_PyEnumRepr(pxr_boost::python::object
const &self);
154struct Tf_PyEnumWrapper :
public Tf_PyEnum
156 typedef Tf_PyEnumWrapper This;
158 Tf_PyEnumWrapper(std::string
const &n,
TfEnum const &val) :
159 name(n), value(val) {}
160 long GetValue()
const {
161 return value.GetValueAsInt();
163 std::string GetName()
const{
166 std::string GetDisplayName()
const {
169 std::string GetFullName()
const {
172 friend bool operator ==(Tf_PyEnumWrapper
const &self,
174 return self.value.GetValueAsInt() == other;
177 friend bool operator ==(Tf_PyEnumWrapper
const &lhs,
178 Tf_PyEnumWrapper
const &rhs) {
179 return lhs.value == rhs.value;
182 friend bool operator !=(Tf_PyEnumWrapper
const &lhs,
183 Tf_PyEnumWrapper
const &rhs) {
184 return !(lhs == rhs);
187 friend bool operator <(Tf_PyEnumWrapper
const &lhs,
188 Tf_PyEnumWrapper
const &rhs)
194 if (!lhs.value.IsA(rhs.value.GetType()))
198 return lhs.GetValue() < rhs.GetValue();
201 friend bool operator >(Tf_PyEnumWrapper
const& lhs,
202 Tf_PyEnumWrapper
const& rhs)
207 friend bool operator <=(Tf_PyEnumWrapper
const& lhs,
208 Tf_PyEnumWrapper
const& rhs)
213 friend bool operator >=(Tf_PyEnumWrapper
const& lhs,
214 Tf_PyEnumWrapper
const& rhs)
226 friend TfEnum operator |(Tf_PyEnumWrapper
const &lhs,
227 Tf_PyEnumWrapper
const &rhs) {
228 if (lhs.value.IsA(rhs.value.GetType())) {
229 return TfEnum(lhs.value.GetType(),
230 lhs.value.GetValueAsInt() |
231 rhs.value.GetValueAsInt());
236 friend TfEnum operator |(Tf_PyEnumWrapper
const &lhs,
long rhs) {
237 return TfEnum(lhs.value.GetType(), lhs.value.GetValueAsInt() | rhs);
239 friend TfEnum operator |(
long lhs, Tf_PyEnumWrapper
const &rhs) {
240 return TfEnum(rhs.value.GetType(), lhs | rhs.value.GetValueAsInt());
243 friend TfEnum operator &(Tf_PyEnumWrapper
const &lhs,
244 Tf_PyEnumWrapper
const &rhs) {
245 if (lhs.value.IsA(rhs.value.GetType())) {
246 return TfEnum(lhs.value.GetType(),
247 lhs.value.GetValueAsInt() &
248 rhs.value.GetValueAsInt());
253 friend TfEnum operator &(Tf_PyEnumWrapper
const &lhs,
long rhs) {
254 return TfEnum(lhs.value.GetType(), lhs.value.GetValueAsInt() & rhs);
256 friend TfEnum operator &(
long lhs, Tf_PyEnumWrapper
const &rhs) {
257 return TfEnum(rhs.value.GetType(), lhs & rhs.value.GetValueAsInt());
260 friend TfEnum operator ^(Tf_PyEnumWrapper
const &lhs,
261 Tf_PyEnumWrapper
const &rhs) {
262 if (lhs.value.IsA(rhs.value.GetType())) {
263 return TfEnum(lhs.value.GetType(),
264 lhs.value.GetValueAsInt() ^
265 rhs.value.GetValueAsInt());
270 friend TfEnum operator ^(Tf_PyEnumWrapper
const &lhs,
long rhs) {
271 return TfEnum(lhs.value.GetType(), lhs.value.GetValueAsInt() ^ rhs);
273 friend TfEnum operator ^(
long lhs, Tf_PyEnumWrapper
const &rhs) {
274 return TfEnum(rhs.value.GetType(), lhs ^ rhs.value.GetValueAsInt());
277 friend TfEnum operator ~(Tf_PyEnumWrapper
const &rhs) {
278 return TfEnum(rhs.value.GetType(), ~rhs.value.GetValueAsInt());
287struct Tf_TypedPyEnumWrapper : Tf_PyEnumWrapper
289 Tf_TypedPyEnumWrapper(std::string
const &n,
TfEnum const &val) :
290 Tf_PyEnumWrapper(n, val) {}
292 static pxr_boost::python::object GetValueFromName(
const std::string& name) {
294 const TfEnum value = TfEnum::GetValueFromName<T>(name, &found);
296 ? pxr_boost::python::object(value)
297 : pxr_boost::python::object();
308std::string Tf_PyCleanEnumName(std::string name,
309 bool stripPackageName =
false);
314void Tf_PyEnumAddAttribute(pxr_boost::python::scope &s,
315 const std::string &name,
316 const pxr_boost::python::object &value);
362template <typename T, bool IsScopedEnum = !std::is_convertible<T, int>::value>
366 typedef pxr_boost::python::class_<
367 Tf_TypedPyEnumWrapper<T>, pxr_boost::python::bases<Tf_PyEnumWrapper> >
378 using namespace pxr_boost::python;
380 const bool explicitName = !name.empty();
383 std::string enumName = explicitName ? name :
389 if (baseName == enumName)
390 baseName = std::string();
399 if (!baseName.empty()) {
400 baseName = Tf_PyCleanEnumName(
404 enumName = Tf_PyCleanEnumName(
412 if (!baseName.empty()) {
415 baseName += enumName;
419 _EnumPyClassType enumClass(enumName.c_str(), no_init);
420 enumClass.def(
"GetValueFromName", &Tf_TypedPyEnumWrapper<T>::GetValueFromName, arg(
"name"));
421 enumClass.staticmethod(
"GetValueFromName");
422 enumClass.setattr(
"_baseName", baseName);
425 Tf_PyEnumRegistry::GetInstance().RegisterEnumConversions<T>();
433 const bool stripPackageName = baseName.empty();
434 _ExportValues(stripPackageName, enumClass);
439 const TfType &type = TfType::Find<T>();
449 void _ExportValues(
bool stripPackageName, _EnumPyClassType &enumClass) {
450 pxr_boost::python::list valueList;
452 for (
const std::string& name : TfEnum::GetAllNames<T>()) {
453 bool success =
false;
454 TfEnum enumValue = TfEnum::GetValueFromName<T>(name, &success);
459 const std::string cleanedName =
460 Tf_PyCleanEnumName(name, stripPackageName);
463 Tf_TypedPyEnumWrapper<T> wrappedValue(cleanedName, enumValue);
464 pxr_boost::python::object pyValue(wrappedValue);
467 Tf_PyEnumRegistry::GetInstance().RegisterValue(enumValue, pyValue);
470 std::string valueName = wrappedValue.GetName();
473 pxr_boost::python::scope s(enumClass);
474 Tf_PyEnumAddAttribute(s, valueName, pyValue);
477 pxr_boost::python::scope s;
478 Tf_PyEnumAddAttribute(s, valueName, pyValue);
481 valueList.append(pyValue);
485 enumClass.setattr(
"allValues", pxr_boost::python::tuple(valueList));
490PXR_NAMESPACE_CLOSE_SCOPE
A simple iterator adapter for STL containers.
Miscellaneous Utilities for dealing with script.
TF_API void TfPyThrowTypeError(const char *msg)
Raises a Python TypeError with the given error msg and throws a pxr_boost::python::error_already_set ...
An enum class that records both enum type and enum value.
static TF_API std::string GetFullName(TfEnum val)
Returns the fully-qualified name for an enumerated value.
static TF_API std::string GetDisplayName(TfEnum val)
Returns the display name for an enumerated value.
Manage a single instance of an object (see.
static T & GetInstance()
Return a reference to an object of type T, creating it if necessary.
TfType represents a dynamic runtime type.
TF_API void DefinePythonClass(const TfPyObjWrapper &classObj) const
Define the Python class object corresponding to this TfType.
bool IsUnknown() const
Return true if this is the unknown type, representing a type unknown to the TfType system.
Demangle C++ typenames generated by the typeid() facility.
std::string ArchGetDemangled()
Return demangled RTTI generated-type name.
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.
TF_API std::string TfStringGetBeforeSuffix(const std::string &name, char delimiter='.')
Returns everything up to the suffix of a string.
TF_API std::string TfStringGetSuffix(const std::string &name, char delimiter='.')
Returns the suffix of a string.
Manage a single instance of an object.
Definitions of basic string utilities in tf.
Used to wrap enum types for script.
TfPyWrapEnum(std::string const &name=std::string())
Construct an enum wrapper object.