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 PXR_USD_SDF_PY_CHILDREN_PROXY_H
25 #define PXR_USD_SDF_PY_CHILDREN_PROXY_H
26 
28 
29 #include "pxr/pxr.h"
31 #include "pxr/base/arch/demangle.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 
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("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 #if PY_MAJOR_VERSION < 3
161  .def("has_key", &This::_HasKey, TfPyRaiseOnError<>())
162  .def("itervalues", &This::_GetValueIterator, TfPyRaiseOnError<>())
163  .def("iterkeys", &This::_GetKeyIterator, TfPyRaiseOnError<>())
164  .def("iteritems", &This::_GetItemIterator, TfPyRaiseOnError<>())
165  .def("items", &This::_GetItems, TfPyRaiseOnError<>())
166  .def("keys", &This::_GetKeys, TfPyRaiseOnError<>())
167  .def("values", &This::_GetValues, TfPyRaiseOnError<>())
168 #else
169  .def("items", &This::_GetItemIterator, TfPyRaiseOnError<>())
170  .def("keys", &This::_GetKeyIterator, TfPyRaiseOnError<>())
171  .def("values", &This::_GetValueIterator, TfPyRaiseOnError<>())
172 #endif
173  .def("index", &This::_FindIndexByKey, TfPyRaiseOnError<>())
174  .def("index", &This::_FindIndexByValue, TfPyRaiseOnError<>())
175  .def("__eq__", &This::operator==, TfPyRaiseOnError<>())
176  .def("__ne__", &This::operator!=, TfPyRaiseOnError<>())
177  ;
178 
179  class_<_Iterator<_ExtractItem> >
180  ((name + "_Iterator").c_str(), no_init)
181  .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
182  .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractItem>::GetNext)
183  ;
184 
185  class_<_Iterator<_ExtractKey> >
186  ((name + "_KeyIterator").c_str(), no_init)
187  .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
188  .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractKey>::GetNext)
189  ;
190 
191  class_<_Iterator<_ExtractValue> >
192  ((name + "_ValueIterator").c_str(), no_init)
193  .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
194  .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractValue>::GetNext)
195  ;
196  }
197 
198  static std::string _GetName()
199  {
200  std::string name = "ChildrenProxy_" +
201  ArchGetDemangled<View>();
202  name = TfStringReplace(name, " ", "_");
203  name = TfStringReplace(name, ",", "_");
204  name = TfStringReplace(name, "::", "_");
205  name = TfStringReplace(name, "<", "_");
206  name = TfStringReplace(name, ">", "_");
207  return name;
208  }
209 
210  const View& _GetView() const
211  {
212  return _proxy._view;
213  }
214 
215  View& _GetView()
216  {
217  return _proxy._view;
218  }
219 
220  std::string _GetRepr() const
221  {
222  std::string result("{");
223  if (! _proxy.empty()) {
224  _const_iterator i = _proxy.begin(), n = _proxy.end();
225  result += TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
226  while (++i != n) {
227  result += ", " + TfPyRepr(i->first) +
228  ": " + TfPyRepr(i->second);
229  }
230  }
231  result += "}";
232  return result;
233  }
234 
235  size_type _GetSize() const
236  {
237  return _proxy.size();
238  }
239 
240  mapped_type _GetItemByKey(const key_type& key) const
241  {
242  _view_const_iterator i = _GetView().find(key);
243  if (i == _GetView().end()) {
245  return mapped_type();
246  }
247  else {
248  return *i;
249  }
250  }
251 
252  mapped_type _GetItemByIndex(int index) const
253  {
254  index = TfPyNormalizeIndex(index, _proxy.size(), true /*throwError*/);
255  return _GetView()[index];
256  }
257 
258  void _SetItemByKey(const key_type& key, const mapped_type& value)
259  {
260  TF_CODING_ERROR("can't directly reparent a %s",
261  _proxy._GetType().c_str());
262  }
263 
264  void _SetItemBySlice(const boost::python::slice& slice,
265  const mapped_vector_type& values)
266  {
267  if (! TfPyIsNone(slice.start()) ||
268  ! TfPyIsNone(slice.stop()) ||
269  ! TfPyIsNone(slice.step())) {
270  TfPyThrowIndexError("can only assign to full slice [:]");
271  }
272  else {
273  _proxy._Copy(values);
274  }
275  }
276 
277  void _DelItemByKey(const key_type& key)
278  {
279  if (_GetView().find(key) == _GetView().end()) {
281  }
282  _proxy._Erase(key);
283  }
284 
285  void _DelItemByIndex(int index)
286  {
287  _proxy._Erase(_GetView().key(_GetItemByIndex(index)));
288  }
289 
290  void _Clear()
291  {
292  _proxy._Copy(mapped_vector_type());
293  }
294 
295  void _AppendItem(const mapped_type& value)
296  {
297  _proxy._Insert(value, _proxy.size());
298  }
299 
300  void _InsertItemByIndex(int index, const mapped_type& value)
301  {
302  // Note that -1 below means to insert at end for the _proxy._Insert API.
303  index = index < (int)_proxy.size()
304  ? TfPyNormalizeIndex(index, _proxy.size(), false /*throwError*/)
305  : -1;
306 
307  _proxy._Insert(value, index);
308  }
309 
310  boost::python::object _PyGet(const key_type& key) const
311  {
312  _view_const_iterator i = _GetView().find(key);
313  return i == _GetView().end() ? boost::python::object() :
314  boost::python::object(*i);
315  }
316 
317  boost::python::object _PyGetDefault(const key_type& key,
318  const mapped_type& def) const
319  {
320  _view_const_iterator i = _GetView().find(key);
321  return i == _GetView().end() ? boost::python::object(def) :
322  boost::python::object(*i);
323  }
324 
325  bool _HasKey(const key_type& key) const
326  {
327  return _GetView().find(key) != _GetView().end();
328  }
329 
330  bool _HasValue(const mapped_type& value) const
331  {
332  return _GetView().find(value) != _GetView().end();
333  }
334 
335  static
336  _Iterator<_ExtractItem> _GetItemIterator(const boost::python::object &x)
337  {
338  return _Iterator<_ExtractItem>(x);
339  }
340 
341  static
342  _Iterator<_ExtractKey> _GetKeyIterator(const boost::python::object &x)
343  {
344  return _Iterator<_ExtractKey>(x);
345  }
346 
347  static
348  _Iterator<_ExtractValue> _GetValueIterator(const boost::python::object &x)
349  {
350  return _Iterator<_ExtractValue>(x);
351  }
352 
353  template <class E>
354  boost::python::list _Get() const
355  {
356  boost::python::list result;
357  for (_const_iterator i = _proxy.begin(), n = _proxy.end(); i != n; ++i){
358  result.append(E::Get(i));
359  }
360  return result;
361  }
362 
363 #if PY_MAJOR_VERSION < 3
364  boost::python::list _GetItems() const
365  {
366  return _Get<_ExtractItem>();
367  }
368 
369  boost::python::list _GetKeys() const
370  {
371  return _Get<_ExtractKey>();
372  }
373 
374  boost::python::list _GetValues() const
375  {
376  return _Get<_ExtractValue>();
377  }
378 #endif
379 
380  int _FindIndexByKey(const key_type& key) const
381  {
382  size_t i = std::distance(_GetView().begin(), _GetView().find(key));
383  return i == _GetView().size() ? -1 : i;
384  }
385 
386  int _FindIndexByValue(const mapped_type& value) const
387  {
388  size_t i = std::distance(_GetView().begin(), _GetView().find(value));
389  return i == _GetView().size() ? -1 : i;
390  }
391 
392 private:
393  Proxy _proxy;
394 
395  template <class E> friend class _Iterator;
396 };
397 
398 PXR_NAMESPACE_CLOSE_SCOPE
399 
400 #endif // PXR_USD_SDF_PY_CHILDREN_PROXY_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:85
Definitions of basic string utilities in tf.
Miscellaneous Utilities for dealing with script.
TF_API void TfPyThrowIndexError(std::string const &msg)
Raises a python IndexError and throws a C++ exception.
Demangle C++ typenames generated by the typeid() facility.
std::string TfPyRepr(T const &t)
Return repr(t).
Definition: pyUtils.h:138
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.
TF_API int64_t TfPyNormalizeIndex(int64_t index, uint64_t size, bool throwError=false)
Return a positive index in the range [0,size).
VT_API bool operator==(VtDictionary const &, VtDictionary const &)
Equality comparison.
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.