All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 SDF_PYCHILDRENPROXY_H
25 #define SDF_PYCHILDRENPROXY_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/childrenProxy.h"
31 #include "pxr/base/arch/demangle.h"
32 #include "pxr/base/tf/pyError.h"
33 #include "pxr/base/tf/pyUtils.h"
34 #include "pxr/base/tf/stringUtils.h"
35 #include <boost/python.hpp>
36 #include <boost/python/slice.hpp>
37 
38 PXR_NAMESPACE_OPEN_SCOPE
39 
40 template <class _View>
41 class SdfPyChildrenProxy {
42 public:
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 
75 private:
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("itervalues", &This::_GetValueIterator, TfPyRaiseOnError<>())
156  .def("iterkeys", &This::_GetKeyIterator, TfPyRaiseOnError<>())
157  .def("iteritems", &This::_GetItemIterator, TfPyRaiseOnError<>())
158  .def("clear", &This::_Clear, TfPyRaiseOnError<>())
159  .def("append", &This::_AppendItem, TfPyRaiseOnError<>())
160  .def("insert", &This::_InsertItemByIndex, TfPyRaiseOnError<>())
161  .def("get", &This::_PyGet, TfPyRaiseOnError<>())
162  .def("get", &This::_PyGetDefault, TfPyRaiseOnError<>())
163  .def("has_key", &This::_HasKey, TfPyRaiseOnError<>())
164  .def("items", &This::_GetItems, TfPyRaiseOnError<>())
165  .def("keys", &This::_GetKeys, TfPyRaiseOnError<>())
166  .def("values", &This::_GetValues, TfPyRaiseOnError<>())
167  .def("index", &This::_FindIndexByKey, TfPyRaiseOnError<>())
168  .def("index", &This::_FindIndexByValue, TfPyRaiseOnError<>())
169  .def("__eq__", &This::operator==, TfPyRaiseOnError<>())
170  .def("__ne__", &This::operator!=, TfPyRaiseOnError<>())
171  ;
172 
173  class_<_Iterator<_ExtractItem> >
174  ((name + "_Iterator").c_str(), no_init)
175  .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
176  .def("next", &This::template _Iterator<_ExtractItem>::GetNext)
177  ;
178 
179  class_<_Iterator<_ExtractKey> >
180  ((name + "_KeyIterator").c_str(), no_init)
181  .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
182  .def("next", &This::template _Iterator<_ExtractKey>::GetNext)
183  ;
184 
185  class_<_Iterator<_ExtractValue> >
186  ((name + "_ValueIterator").c_str(), no_init)
187  .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
188  .def("next", &This::template _Iterator<_ExtractValue>::GetNext)
189  ;
190  }
191 
192  static std::string _GetName()
193  {
194  std::string name = "ChildrenProxy_" +
195  ArchGetDemangled<View>();
196  name = TfStringReplace(name, " ", "_");
197  name = TfStringReplace(name, ",", "_");
198  name = TfStringReplace(name, "::", "_");
199  name = TfStringReplace(name, "<", "_");
200  name = TfStringReplace(name, ">", "_");
201  return name;
202  }
203 
204  const View& _GetView() const
205  {
206  return _proxy._view;
207  }
208 
209  View& _GetView()
210  {
211  return _proxy._view;
212  }
213 
214  std::string _GetRepr() const
215  {
216  std::string result("{");
217  if (! _proxy.empty()) {
218  _const_iterator i = _proxy.begin(), n = _proxy.end();
219  result += TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
220  while (++i != n) {
221  result += ", " + TfPyRepr(i->first) +
222  ": " + TfPyRepr(i->second);
223  }
224  }
225  result += "}";
226  return result;
227  }
228 
229  size_type _GetSize() const
230  {
231  return _proxy.size();
232  }
233 
234  mapped_type _GetItemByKey(const key_type& key) const
235  {
236  _view_const_iterator i = _GetView().find(key);
237  if (i == _GetView().end()) {
239  return mapped_type();
240  }
241  else {
242  return *i;
243  }
244  }
245 
246  mapped_type _GetItemByIndex(int index) const
247  {
248  index = TfPyNormalizeIndex(index, _proxy.size(), true /*throwError*/);
249  return _GetView()[index];
250  }
251 
252  void _SetItemByKey(const key_type& key, const mapped_type& value)
253  {
254  TF_CODING_ERROR("can't directly reparent a %s",
255  _proxy._GetType().c_str());
256  }
257 
258  void _SetItemBySlice(const boost::python::slice& slice,
259  const mapped_vector_type& values)
260  {
261  if (! TfPyIsNone(slice.start()) ||
262  ! TfPyIsNone(slice.stop()) ||
263  ! TfPyIsNone(slice.step())) {
264  TfPyThrowIndexError("can only assign to full slice [:]");
265  }
266  else {
267  _proxy._Copy(values);
268  }
269  }
270 
271  void _DelItemByKey(const key_type& key)
272  {
273  if (_GetView().find(key) == _GetView().end()) {
275  }
276  _proxy._Erase(key);
277  }
278 
279  void _DelItemByIndex(int index)
280  {
281  _proxy._Erase(_GetView().key(_GetItemByIndex(index)));
282  }
283 
284  void _Clear()
285  {
286  _proxy._Copy(mapped_vector_type());
287  }
288 
289  void _AppendItem(const mapped_type& value)
290  {
291  _proxy._Insert(value, _proxy.size());
292  }
293 
294  void _InsertItemByIndex(int index, const mapped_type& value)
295  {
296  // Note that -1 below means to insert at end for the _proxy._Insert API.
297  index = index < (int)_proxy.size()
298  ? TfPyNormalizeIndex(index, _proxy.size(), false /*throwError*/)
299  : -1;
300 
301  _proxy._Insert(value, index);
302  }
303 
304  boost::python::object _PyGet(const key_type& key) const
305  {
306  _view_const_iterator i = _GetView().find(key);
307  return i == _GetView().end() ? boost::python::object() :
308  boost::python::object(*i);
309  }
310 
311  boost::python::object _PyGetDefault(const key_type& key,
312  const mapped_type& def) const
313  {
314  _view_const_iterator i = _GetView().find(key);
315  return i == _GetView().end() ? boost::python::object(def) :
316  boost::python::object(*i);
317  }
318 
319  bool _HasKey(const key_type& key) const
320  {
321  return _GetView().find(key) != _GetView().end();
322  }
323 
324  bool _HasValue(const mapped_type& value) const
325  {
326  return _GetView().find(value) != _GetView().end();
327  }
328 
329  static
330  _Iterator<_ExtractItem> _GetItemIterator(const boost::python::object &x)
331  {
332  return _Iterator<_ExtractItem>(x);
333  }
334 
335  static
336  _Iterator<_ExtractKey> _GetKeyIterator(const boost::python::object &x)
337  {
338  return _Iterator<_ExtractKey>(x);
339  }
340 
341  static
342  _Iterator<_ExtractValue> _GetValueIterator(const boost::python::object &x)
343  {
344  return _Iterator<_ExtractValue>(x);
345  }
346 
347  template <class E>
348  boost::python::list _Get() const
349  {
350  boost::python::list result;
351  for (_const_iterator i = _proxy.begin(), n = _proxy.end(); i != n; ++i){
352  result.append(E::Get(i));
353  }
354  return result;
355  }
356 
357  boost::python::list _GetItems() const
358  {
359  return _Get<_ExtractItem>();
360  }
361 
362  boost::python::list _GetKeys() const
363  {
364  return _Get<_ExtractKey>();
365  }
366 
367  boost::python::list _GetValues() const
368  {
369  return _Get<_ExtractValue>();
370  }
371 
372  int _FindIndexByKey(const key_type& key) const
373  {
374  size_t i = std::distance(_GetView().begin(), _GetView().find(key));
375  return i == _GetView().size() ? -1 : i;
376  }
377 
378  int _FindIndexByValue(const mapped_type& value) const
379  {
380  size_t i = std::distance(_GetView().begin(), _GetView().find(value));
381  return i == _GetView().size() ? -1 : i;
382  }
383 
384 private:
385  Proxy _proxy;
386 
387  template <class E> friend class _Iterator;
388 };
389 
390 PXR_NAMESPACE_CLOSE_SCOPE
391 
392 #endif // SDF_PYCHILDRENPROXY_H
A boost.python call policy class which, when applied to a wrapped function, will create an error mark...
Definition: pyError.h:63
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:87
TF_API int64_t TfPyNormalizeIndex(int64_t index, uint64_t size, bool throwError=false)
Return a positive index in the range [0,size).
TF_API void TfPyThrowStopIteration(std::string const &msg)
Raises a python StopIteration exception and throws a C++ exception.
TF_API bool TfPyIsNone(boost::python::object const &obj)
Return true iff obj is None.
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
TF_API void TfPyThrowIndexError(std::string const &msg)
Raises a python IndexError and throws a C++ exception.
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.
std::string TfPyRepr(T const &t)
Return repr(t).
Definition: pyUtils.h:136