All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyChildrenView.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_PYCHILDRENVIEW_H
25 #define SDF_PYCHILDRENVIEW_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/childrenView.h"
31 #include "pxr/base/arch/demangle.h"
32 #include "pxr/base/tf/pyUtils.h"
33 #include "pxr/base/tf/stringUtils.h"
34 #include <boost/python.hpp>
35 
36 PXR_NAMESPACE_OPEN_SCOPE
37 
38 template <class _View>
39 class SdfPyWrapChildrenView {
40 public:
41  typedef _View View;
42  typedef typename View::ChildPolicy ChildPolicy;
43  typedef typename View::Predicate Predicate;
44  typedef typename View::key_type key_type;
45  typedef typename View::value_type value_type;
46  typedef typename View::const_iterator const_iterator;
47  typedef SdfPyWrapChildrenView<View> This;
48 
49  SdfPyWrapChildrenView()
50  {
51  TfPyWrapOnce<View>(&This::_Wrap);
52  }
53 
54 private:
55  struct _ExtractItem {
56  static boost::python::object Get(const View& x, const const_iterator& i)
57  {
58  return boost::python::make_tuple(x.key(i), *i);
59  }
60  };
61 
62  struct _ExtractKey {
63  static boost::python::object Get(const View& x, const const_iterator& i)
64  {
65  return boost::python::object(x.key(i));
66  }
67  };
68 
69  struct _ExtractValue {
70  static boost::python::object Get(const View& x, const const_iterator& i)
71  {
72  return boost::python::object(*i);
73  }
74  };
75 
76  template <class E>
77  class _Iterator {
78  public:
79  _Iterator(const boost::python::object& object) :
80  _object(object),
81  _owner(boost::python::extract<const View&>(object)),
82  _cur(_owner.begin()),
83  _end(_owner.end())
84  {
85  // Do nothing
86  }
87 
88  _Iterator<E> GetCopy() const
89  {
90  return *this;
91  }
92 
93  boost::python::object GetNext()
94  {
95  if (_cur == _end) {
96  TfPyThrowStopIteration("End of ChildrenProxy iteration");
97  }
98  boost::python::object result = E::Get(_owner, _cur);
99  ++_cur;
100  return result;
101  }
102 
103  private:
104  boost::python::object _object;
105  const View& _owner;
106  const_iterator _cur;
107  const_iterator _end;
108  };
109 
110  static void _Wrap()
111  {
112  using namespace boost::python;
113 
114  std::string name = _GetName();
115 
116  // Note: Using the value iterator for the __iter__ method is not
117  // consistent with Python dicts (which iterate over keys).
118  // However, we're emulating TfPyKeyedVector, which iterates
119  // over values as a vector would.
120  scope thisScope =
121  class_<View>(name.c_str(), no_init)
122  .def("__repr__", &This::_GetRepr)
123  .def("__len__", &View::size)
124  .def("__getitem__", &This::_GetItemByKey)
125  .def("__getitem__", &This::_GetItemByIndex)
126  .def("get", &This::_PyGet)
127  .def("has_key", &This::_HasKey)
128  .def("__contains__", &This::_HasKey)
129  .def("__contains__", &This::_HasValue)
130  .def("__iter__", &This::_GetValueIterator)
131  .def("itervalues", &This::_GetValueIterator)
132  .def("iterkeys", &This::_GetKeyIterator)
133  .def("iteritems", &This::_GetItemIterator)
134  .def("items", &This::_GetItems)
135  .def("keys", &This::_GetKeys)
136  .def("values", &This::_GetValues)
137  .def("index", &This::_FindIndexByKey)
138  .def("index", &This::_FindIndexByValue)
139  .def(self == self)
140  .def(self != self)
141  ;
142 
143  class_<_Iterator<_ExtractItem> >
144  ((name + "_Iterator").c_str(), no_init)
145  .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
146  .def("next", &This::template _Iterator<_ExtractItem>::GetNext)
147  ;
148 
149  class_<_Iterator<_ExtractKey> >
150  ((name + "_KeyIterator").c_str(), no_init)
151  .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
152  .def("next", &This::template _Iterator<_ExtractKey>::GetNext)
153  ;
154 
155  class_<_Iterator<_ExtractValue> >
156  ((name + "_ValueIterator").c_str(), no_init)
157  .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
158  .def("next", &This::template _Iterator<_ExtractValue>::GetNext)
159  ;
160  }
161 
162  static std::string _GetName()
163  {
164  std::string name = "ChildrenView_" +
165  ArchGetDemangled<ChildPolicy>() + "_" +
166  ArchGetDemangled<Predicate>();
167  name = TfStringReplace(name, " ", "_");
168  name = TfStringReplace(name, ",", "_");
169  name = TfStringReplace(name, "::", "_");
170  name = TfStringReplace(name, "<", "_");
171  name = TfStringReplace(name, ">", "_");
172  return name;
173  }
174 
175  static std::string _GetRepr(const View& x)
176  {
177  std::string result("{");
178  if (! x.empty()) {
179  const_iterator i = x.begin(), n = x.end();
180  result += TfPyRepr(x.key(i)) + ": " + TfPyRepr(*i);
181  while (++i != n) {
182  result += ", " + TfPyRepr(x.key(i)) + ": " + TfPyRepr(*i);
183  }
184  }
185  result += "}";
186  return result;
187  }
188 
189  static value_type _GetItemByKey(const View& x, const key_type& key)
190  {
191  const_iterator i = x.find(key);
192  if (i == x.end()) {
194  return value_type();
195  }
196  else {
197  return *i;
198  }
199  }
200 
201  static value_type _GetItemByIndex(const View& x, size_t index)
202  {
203  if (index >= x.size()) {
204  TfPyThrowIndexError("list index out of range");
205  }
206  return x[index];
207  }
208 
209  static boost::python::object _PyGet(const View& x, const key_type& key)
210  {
211  const_iterator i = x.find(key);
212  return i == x.end() ? boost::python::object() :
213  boost::python::object(*i);
214  }
215 
216  static bool _HasKey(const View& x, const key_type& key)
217  {
218  return x.find(key) != x.end();
219  }
220 
221  static bool _HasValue(const View& x, const value_type& value)
222  {
223  return x.find(value) != x.end();
224  }
225 
226  static
227  _Iterator<_ExtractItem> _GetItemIterator(const boost::python::object& x)
228  {
229  return _Iterator<_ExtractItem>(x);
230  }
231 
232  static
233  _Iterator<_ExtractKey> _GetKeyIterator(const boost::python::object& x)
234  {
235  return _Iterator<_ExtractKey>(x);
236  }
237 
238  static
239  _Iterator<_ExtractValue> _GetValueIterator(const boost::python::object& x)
240  {
241  return _Iterator<_ExtractValue>(x);
242  }
243 
244  template <class E>
245  static boost::python::list _Get(const View& x)
246  {
247  boost::python::list result;
248  for (const_iterator i = x.begin(), n = x.end(); i != n; ++i) {
249  result.append(E::Get(x, i));
250  }
251  return result;
252  }
253 
254  static boost::python::list _GetItems(const View& x)
255  {
256  return _Get<_ExtractItem>(x);
257  }
258 
259  static boost::python::list _GetKeys(const View& x)
260  {
261  return _Get<_ExtractKey>(x);
262  }
263 
264  static boost::python::list _GetValues(const View& x)
265  {
266  return _Get<_ExtractValue>(x);
267  }
268 
269  static int _FindIndexByKey(const View& x, const key_type& key)
270  {
271  size_t i = std::distance(x.begin(), x.find(key));
272  return i == x.size() ? -1 : i;
273  }
274 
275  static int _FindIndexByValue(const View& x, const value_type& value)
276  {
277  size_t i = std::distance(x.begin(), x.find(value));
278  return i == x.size() ? -1 : i;
279  }
280 };
281 
282 PXR_NAMESPACE_CLOSE_SCOPE
283 
284 #endif // SDF_PYCHILDRENVIEW_H
TF_API void TfPyThrowStopIteration(std::string const &msg)
Raises a python StopIteration exception and throws a C++ exception.
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