This document is for a version of USD that is under development. See this page for the current release.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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.