Loading...
Searching...
No Matches
pyListProxy.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7#ifndef PXR_USD_SDF_PY_LIST_PROXY_H
8#define PXR_USD_SDF_PY_LIST_PROXY_H
9
11
12#include "pxr/pxr.h"
13#include "pxr/usd/sdf/changeBlock.h"
16#include "pxr/base/tf/pyLock.h"
17#include "pxr/base/tf/pyUtils.h"
18#include "pxr/base/tf/pyResultConversions.h"
20#include <stdexcept>
21#include "pxr/external/boost/python.hpp"
22#include "pxr/external/boost/python/slice.hpp"
23
24PXR_NAMESPACE_OPEN_SCOPE
25
26template <class T>
27class SdfPyWrapListProxy {
28public:
29 typedef T Type;
30 typedef typename Type::TypePolicy TypePolicy;
31 typedef typename Type::value_type value_type;
32 typedef typename Type::value_vector_type value_vector_type;
33 typedef SdfPyWrapListProxy<Type> This;
34
35 SdfPyWrapListProxy()
36 {
37 TfPyWrapOnce<Type>(&This::_Wrap);
38 }
39
40private:
41 static void _Wrap()
42 {
43 using namespace pxr_boost::python;
44
45 class_<Type>(_GetName().c_str(), no_init)
46 .def("__str__", &This::_GetStr)
47 .def("__len__", &Type::size)
48 .def("__getitem__", &This::_GetItemIndex)
49 .def("__getitem__", &This::_GetItemSlice)
50 .def("__setitem__", &This::_SetItemIndex)
51 .def("__setitem__", &This::_SetItemSlice)
52 .def("__delitem__", &This::_DelItemIndex)
53 .def("__delitem__", &This::_DelItemSlice)
54 .def("__delitem__", &Type::Remove)
55 .def("count", &Type::Count)
56 .def("copy", &Type::operator value_vector_type,
57 return_value_policy<TfPySequenceToList>())
58 .def("index", &This::_FindIndex)
59 .def("clear", &Type::clear)
60 .def("insert", &This::_Insert)
61 .def("append", &Type::push_back)
62 .def("remove", &Type::Remove)
63 .def("replace", &Type::Replace)
64 .def("ApplyList", &Type::ApplyList)
65 .def("ApplyEditsToList", &This::_ApplyEditsToList)
66 .add_property("expired", &This::_IsExpired)
67 .add_static_property("invalidIndex", &This::_GetInvalidIndex)
68 .def(self == self)
69 .def(self != self)
70 .def(self < self)
71 .def(self <= self)
72 .def(self > self)
73 .def(self >= self)
74 .def(self == other<value_vector_type>())
75 .def(self != other<value_vector_type>())
76 .def(self < other<value_vector_type>())
77 .def(self <= other<value_vector_type>())
78 .def(self > other<value_vector_type>())
79 .def(self >= other<value_vector_type>())
80 ;
81 }
82
83 static std::string _GetName()
84 {
85 std::string name = "ListProxy_" +
86 ArchGetDemangled<TypePolicy>();
87 name = TfStringReplace(name, " ", "_");
88 name = TfStringReplace(name, ",", "_");
89 name = TfStringReplace(name, "::", "_");
90 name = TfStringReplace(name, "<", "_");
91 name = TfStringReplace(name, ">", "_");
92 return name;
93 }
94
95 static std::string _GetStr(const Type& x)
96 {
97 return TfPyRepr(static_cast<value_vector_type>(x));
98 }
99
100 static value_type _GetItemIndex(const Type& x, int index)
101 {
102 return x[TfPyNormalizeIndex(index, x._GetSize(), true)];
103 }
104
105 static pxr_boost::python::list _GetItemSlice(const Type& x,
106 const pxr_boost::python::slice& index)
107 {
108 using namespace pxr_boost::python;
109
110 list result;
111
112 if (x._Validate()) {
113 try {
114 slice::range<typename Type::const_iterator> range =
115 index.get_indicies(x.begin(), x.end());
116 for (; range.start != range.stop; range.start += range.step) {
117 result.append(*range.start);
118 }
119 result.append(*range.start);
120 }
121 catch (const std::invalid_argument&) {
122 // Ignore.
123 }
124 }
125
126 return result;
127 }
128
129 static void _SetItemIndex(Type& x, int index, const value_type& value)
130 {
131 x[TfPyNormalizeIndex(index, x._GetSize(), true)] = value;
132 }
133
134 static void _SetItemSlice(Type& x, const pxr_boost::python::slice& index,
135 const value_vector_type& values)
136 {
137 using namespace pxr_boost::python;
138
139 if (! x._Validate()) {
140 return;
141 }
142
143 // Get the range and the number of items in the slice.
144 size_t start, step, count;
145 try {
146 slice::range<typename Type::iterator> range =
147 index.get_indicies(x.begin(), x.end());
148 start = range.start - x.begin();
149 step = range.step;
150 count = 1 + (range.stop - range.start) / range.step;
151 }
152 catch (const std::invalid_argument&) {
153 // Empty range.
154 extract<int> e(index.start());
155 start = e.check() ? TfPyNormalizeIndex(e(), x._GetSize(), true) : 0;
156 step = 0;
157 count = 0;
158 }
159
160 if (TfPyIsNone(index.step())) {
161 // Replace contiguous sequence with values.
162 x._Edit(start, count, values);
163 }
164 else {
165 // Replace exactly the selected items.
166 if (count != values.size()) {
168 TfStringPrintf("attempt to assign sequence of size %zd "
169 "to extended slice of size %zd",
170 values.size(), count).c_str());
171 }
172 else if (step == 1) {
173 x._Edit(start, count, values);
174 }
175 else {
176 SdfChangeBlock block;
177 for (size_t i = 0, j = start; i != count; j += step, ++i) {
178 x._Edit(j, 1, value_vector_type(1, values[i]));
179 }
180 }
181 }
182 }
183
184 static void _DelItemIndex(Type& x, int i)
185 {
186 x._Edit(TfPyNormalizeIndex(i, x._GetSize(), true),
187 1, value_vector_type());
188 }
189
190 static void _DelItemSlice(Type& x, const pxr_boost::python::slice& index)
191 {
192 using namespace pxr_boost::python;
193
194 if (x._Validate()) {
195 try {
196 // Get the range and the number of items in the slice.
197 slice::range<typename Type::iterator> range =
198 index.get_indicies(x.begin(), x.end());
199 size_t start = range.start - x.begin();
200 size_t step = range.step;
201 size_t count = 1 + (range.stop - range.start) / range.step;
202
203 // Erase items.
204 if (step == 1) {
205 x._Edit(start, count, value_vector_type());
206 }
207 else {
208 SdfChangeBlock block;
209 value_vector_type empty;
210 for (size_t j = start; count > 0; j += step - 1, --count) {
211 x._Edit(j, 1, empty);
212 }
213 }
214 }
215 catch (const std::invalid_argument&) {
216 // Empty slice -- do nothing.
217 }
218 }
219 }
220
221 static int _GetInvalidIndex()
222 {
223 // Note that SdfListProxy::Find returns an unsigned value, however the
224 // wrapped class returns -1 in the event that a value could not be found
225 // in the list of operations.
226 return -1;
227 }
228
229 static int _FindIndex(const Type& x, const value_type& value)
230 {
231 if (x._Validate()) {
232 const size_t index = x.Find(value);
233 return index == Type::invalidIndex
234 ? _GetInvalidIndex()
235 : static_cast<int>(index);
236 }
237 else {
238 return _GetInvalidIndex();
239 }
240 }
241
242 static void _Insert(Type& x, int index, const value_type& value)
243 {
244 if (index < 0) {
245 index += x._GetSize();
246 }
247 if (index < 0 || index > static_cast<int>(x._GetSize())) {
248 TfPyThrowIndexError("list index out of range");
249 }
250 x._Edit(index, 0, value_vector_type(1, value));
251 }
252
253 static bool _IsExpired(const Type& x)
254 {
255 return x.IsExpired();
256 }
257
258 static value_vector_type _ApplyEditsToList(Type& x,
259 const value_vector_type& values)
260 {
261 value_vector_type newValues = values;
262 x.ApplyEditsToList(&newValues);
263 return newValues;
264 }
265};
266
267PXR_NAMESPACE_CLOSE_SCOPE
268
269#endif // PXR_USD_SDF_PY_LIST_PROXY_H
Miscellaneous Utilities for dealing with script.
TF_API void TfPyThrowIndexError(const char *msg)
Raises a Python IndexError with the given error msg and throws a pxr_boost::python::error_already_set...
TF_API bool TfPyIsNone(pxr_boost::python::object const &obj)
Return true iff obj is None.
TF_API void TfPyThrowValueError(const char *msg)
Raises a Python ValueError with the given error msg and throws a pxr_boost::python::error_already_set...
TF_API int64_t TfPyNormalizeIndex(int64_t index, uint64_t size, bool throwError=false)
Return a positive index in the range [0,size).
std::string TfPyRepr(T const &t)
Return repr(t).
Definition: pyUtils.h:163
DANGER DANGER DANGER
Definition: changeBlock.h:56
Demangle C++ typenames generated by the typeid() facility.
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 TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
Definitions of basic string utilities in tf.