Loading...
Searching...
No Matches
pyChildrenProxy.h
Go to the documentation of this file.
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifndef PXR_USD_SDF_PY_CHILDREN_PROXY_H
25#define PXR_USD_SDF_PY_CHILDREN_PROXY_H
26
28
29#include "pxr/pxr.h"
32#include "pxr/base/tf/pyError.h"
33#include "pxr/base/tf/pyUtils.h"
35#include <boost/python.hpp>
36#include <boost/python/slice.hpp>
37
38PXR_NAMESPACE_OPEN_SCOPE
39
40template <class _View>
41class SdfPyChildrenProxy {
42public:
43 typedef _View View;
44 typedef SdfChildrenProxy<View> Proxy;
45 typedef typename Proxy::key_type key_type;
46 typedef typename Proxy::mapped_type mapped_type;
47 typedef typename Proxy::mapped_vector_type mapped_vector_type;
48 typedef typename Proxy::size_type size_type;
49 typedef SdfPyChildrenProxy<View> This;
50
51 SdfPyChildrenProxy(const Proxy& proxy) : _proxy(proxy)
52 {
53 _Init();
54 }
55
56 SdfPyChildrenProxy(const View& view, const std::string& type,
57 int permission = Proxy::CanSet |
58 Proxy::CanInsert |
59 Proxy::CanErase) :
60 _proxy(view, type, permission)
61 {
62 _Init();
63 }
64
65 bool operator==(const This& other) const
66 {
67 return _proxy == other._proxy;
68 }
69
70 bool operator!=(const This& other) const
71 {
72 return _proxy != other._proxy;
73 }
74
75private:
76 typedef typename Proxy::const_iterator _const_iterator;
77 typedef typename View::const_iterator _view_const_iterator;
78
79 struct _ExtractItem {
80 static boost::python::object Get(const _const_iterator& i)
81 {
82 return boost::python::make_tuple(i->first, i->second);
83 }
84 };
85
86 struct _ExtractKey {
87 static boost::python::object Get(const _const_iterator& i)
88 {
89 return boost::python::object(i->first);
90 }
91 };
92
93 struct _ExtractValue {
94 static boost::python::object Get(const _const_iterator& i)
95 {
96 return boost::python::object(i->second);
97 }
98 };
99
100 template <class E>
101 class _Iterator {
102 public:
103 _Iterator(const boost::python::object& object) :
104 _object(object),
105 _owner(boost::python::extract<const This&>(object)()._proxy)
106 {
107 _cur = _owner.begin();
108 }
109
110 _Iterator<E> GetCopy() const
111 {
112 return *this;
113 }
114
115 boost::python::object GetNext()
116 {
117 if (_cur == _owner.end()) {
118 TfPyThrowStopIteration("End of ChildrenProxy iteration");
119 }
120 boost::python::object result = E::Get(_cur);
121 ++_cur;
122 return result;
123 }
124
125 private:
126 boost::python::object _object;
127 const Proxy& _owner;
128 _const_iterator _cur;
129 };
130
131 void _Init()
132 {
133 TfPyWrapOnce<This>(&This::_Wrap);
134 }
135
136 static void _Wrap()
137 {
138 using namespace boost::python;
139
140 std::string name = _GetName();
141
142 scope thisScope =
143 class_<This>(name.c_str(), no_init)
144 .def("__repr__", &This::_GetRepr, TfPyRaiseOnError<>())
145 .def("__len__", &This::_GetSize, TfPyRaiseOnError<>())
146 .def("__getitem__", &This::_GetItemByKey, TfPyRaiseOnError<>())
147 .def("__getitem__", &This::_GetItemByIndex, TfPyRaiseOnError<>())
148 .def("__setitem__", &This::_SetItemByKey, TfPyRaiseOnError<>())
149 .def("__setitem__", &This::_SetItemBySlice, TfPyRaiseOnError<>())
150 .def("__delitem__", &This::_DelItemByKey, TfPyRaiseOnError<>())
151 .def("__delitem__", &This::_DelItemByIndex, TfPyRaiseOnError<>())
152 .def("__contains__", &This::_HasKey, TfPyRaiseOnError<>())
153 .def("__contains__", &This::_HasValue, TfPyRaiseOnError<>())
154 .def("__iter__", &This::_GetValueIterator, TfPyRaiseOnError<>())
155 .def("clear", &This::_Clear, TfPyRaiseOnError<>())
156 .def("append", &This::_AppendItem, TfPyRaiseOnError<>())
157 .def("insert", &This::_InsertItemByIndex, TfPyRaiseOnError<>())
158 .def("get", &This::_PyGet, TfPyRaiseOnError<>())
159 .def("get", &This::_PyGetDefault, TfPyRaiseOnError<>())
160 .def("items", &This::_GetItemIterator, TfPyRaiseOnError<>())
161 .def("keys", &This::_GetKeyIterator, TfPyRaiseOnError<>())
162 .def("values", &This::_GetValueIterator, TfPyRaiseOnError<>())
163 .def("index", &This::_FindIndexByKey, TfPyRaiseOnError<>())
164 .def("index", &This::_FindIndexByValue, TfPyRaiseOnError<>())
165 .def("__eq__", &This::operator==, TfPyRaiseOnError<>())
166 .def("__ne__", &This::operator!=, TfPyRaiseOnError<>())
167 ;
168
169 class_<_Iterator<_ExtractItem> >
170 ((name + "_Iterator").c_str(), no_init)
171 .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
172 .def("__next__", &This::template _Iterator<_ExtractItem>::GetNext)
173 ;
174
175 class_<_Iterator<_ExtractKey> >
176 ((name + "_KeyIterator").c_str(), no_init)
177 .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
178 .def("__next__", &This::template _Iterator<_ExtractKey>::GetNext)
179 ;
180
181 class_<_Iterator<_ExtractValue> >
182 ((name + "_ValueIterator").c_str(), no_init)
183 .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
184 .def("__next__", &This::template _Iterator<_ExtractValue>::GetNext)
185 ;
186 }
187
188 static std::string _GetName()
189 {
190 std::string name = "ChildrenProxy_" +
191 ArchGetDemangled<View>();
192 name = TfStringReplace(name, " ", "_");
193 name = TfStringReplace(name, ",", "_");
194 name = TfStringReplace(name, "::", "_");
195 name = TfStringReplace(name, "<", "_");
196 name = TfStringReplace(name, ">", "_");
197 return name;
198 }
199
200 const View& _GetView() const
201 {
202 return _proxy._view;
203 }
204
205 View& _GetView()
206 {
207 return _proxy._view;
208 }
209
210 std::string _GetRepr() const
211 {
212 std::string result("{");
213 if (! _proxy.empty()) {
214 _const_iterator i = _proxy.begin(), n = _proxy.end();
215 result += TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
216 while (++i != n) {
217 result += ", " + TfPyRepr(i->first) +
218 ": " + TfPyRepr(i->second);
219 }
220 }
221 result += "}";
222 return result;
223 }
224
225 size_type _GetSize() const
226 {
227 return _proxy.size();
228 }
229
230 mapped_type _GetItemByKey(const key_type& key) const
231 {
232 _view_const_iterator i = _GetView().find(key);
233 if (i == _GetView().end()) {
235 return mapped_type();
236 }
237 else {
238 return *i;
239 }
240 }
241
242 mapped_type _GetItemByIndex(int index) const
243 {
244 index = TfPyNormalizeIndex(index, _proxy.size(), true /*throwError*/);
245 return _GetView()[index];
246 }
247
248 void _SetItemByKey(const key_type& key, const mapped_type& value)
249 {
250 TF_CODING_ERROR("can't directly reparent a %s",
251 _proxy._GetType().c_str());
252 }
253
254 void _SetItemBySlice(const boost::python::slice& slice,
255 const mapped_vector_type& values)
256 {
257 if (! TfPyIsNone(slice.start()) ||
258 ! TfPyIsNone(slice.stop()) ||
259 ! TfPyIsNone(slice.step())) {
260 TfPyThrowIndexError("can only assign to full slice [:]");
261 }
262 else {
263 _proxy._Copy(values);
264 }
265 }
266
267 void _DelItemByKey(const key_type& key)
268 {
269 if (_GetView().find(key) == _GetView().end()) {
271 }
272 _proxy._Erase(key);
273 }
274
275 void _DelItemByIndex(int index)
276 {
277 _proxy._Erase(_GetView().key(_GetItemByIndex(index)));
278 }
279
280 void _Clear()
281 {
282 _proxy._Copy(mapped_vector_type());
283 }
284
285 void _AppendItem(const mapped_type& value)
286 {
287 _proxy._Insert(value, _proxy.size());
288 }
289
290 void _InsertItemByIndex(int index, const mapped_type& value)
291 {
292 // Note that -1 below means to insert at end for the _proxy._Insert API.
293 index = index < (int)_proxy.size()
294 ? TfPyNormalizeIndex(index, _proxy.size(), false /*throwError*/)
295 : -1;
296
297 _proxy._Insert(value, index);
298 }
299
300 boost::python::object _PyGet(const key_type& key) const
301 {
302 _view_const_iterator i = _GetView().find(key);
303 return i == _GetView().end() ? boost::python::object() :
304 boost::python::object(*i);
305 }
306
307 boost::python::object _PyGetDefault(const key_type& key,
308 const mapped_type& def) const
309 {
310 _view_const_iterator i = _GetView().find(key);
311 return i == _GetView().end() ? boost::python::object(def) :
312 boost::python::object(*i);
313 }
314
315 bool _HasKey(const key_type& key) const
316 {
317 return _GetView().find(key) != _GetView().end();
318 }
319
320 bool _HasValue(const mapped_type& value) const
321 {
322 return _GetView().find(value) != _GetView().end();
323 }
324
325 static
326 _Iterator<_ExtractItem> _GetItemIterator(const boost::python::object &x)
327 {
328 return _Iterator<_ExtractItem>(x);
329 }
330
331 static
332 _Iterator<_ExtractKey> _GetKeyIterator(const boost::python::object &x)
333 {
334 return _Iterator<_ExtractKey>(x);
335 }
336
337 static
338 _Iterator<_ExtractValue> _GetValueIterator(const boost::python::object &x)
339 {
340 return _Iterator<_ExtractValue>(x);
341 }
342
343 template <class E>
344 boost::python::list _Get() const
345 {
346 boost::python::list result;
347 for (_const_iterator i = _proxy.begin(), n = _proxy.end(); i != n; ++i){
348 result.append(E::Get(i));
349 }
350 return result;
351 }
352
353 int _FindIndexByKey(const key_type& key) const
354 {
355 size_t i = std::distance(_GetView().begin(), _GetView().find(key));
356 return i == _GetView().size() ? -1 : i;
357 }
358
359 int _FindIndexByValue(const mapped_type& value) const
360 {
361 size_t i = std::distance(_GetView().begin(), _GetView().find(value));
362 return i == _GetView().size() ? -1 : i;
363 }
364
365private:
366 Proxy _proxy;
367
368 template <class E> friend class _Iterator;
369};
370
371PXR_NAMESPACE_CLOSE_SCOPE
372
373#endif // PXR_USD_SDF_PY_CHILDREN_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 boost::python::error_already_set exc...
TF_API void TfPyThrowStopIteration(const char *msg)
Raises a Python StopIteration with the given error msg and throws a boost::python::error_already_set ...
TF_API bool TfPyIsNone(boost::python::object const &obj)
Return true iff obj is None.
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:180
Demangle C++ typenames generated by the typeid() facility.
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:85
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.
Definitions of basic string utilities in tf.
A boost.python call policy class which, when applied to a wrapped function, will create an error mark...
Definition: pyError.h:64