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 PXR_USD_SDF_PY_CHILDREN_VIEW_H
25 #define PXR_USD_SDF_PY_CHILDREN_VIEW_H
26 
28 
29 #include "pxr/pxr.h"
31 #include "pxr/base/arch/demangle.h"
32 #include "pxr/base/tf/pyUtils.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("__contains__", &This::_HasKey)
128  .def("__contains__", &This::_HasValue)
129  .def("__iter__", &This::_GetValueIterator)
130  .def("items", &This::_GetItemIterator)
131  .def("keys", &This::_GetKeyIterator)
132  .def("values", &This::_GetValueIterator)
133  .def("index", &This::_FindIndexByKey)
134  .def("index", &This::_FindIndexByValue)
135  .def(self == self)
136  .def(self != self)
137  ;
138 
139  class_<_Iterator<_ExtractItem> >
140  ((name + "_Iterator").c_str(), no_init)
141  .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
142  .def("__next__", &This::template _Iterator<_ExtractItem>::GetNext)
143  ;
144 
145  class_<_Iterator<_ExtractKey> >
146  ((name + "_KeyIterator").c_str(), no_init)
147  .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
148  .def("__next__", &This::template _Iterator<_ExtractKey>::GetNext)
149  ;
150 
151  class_<_Iterator<_ExtractValue> >
152  ((name + "_ValueIterator").c_str(), no_init)
153  .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
154  .def("__next__", &This::template _Iterator<_ExtractValue>::GetNext)
155  ;
156  }
157 
158  static std::string _GetName()
159  {
160  std::string name = "ChildrenView_" +
161  ArchGetDemangled<ChildPolicy>() + "_" +
162  ArchGetDemangled<Predicate>();
163  name = TfStringReplace(name, " ", "_");
164  name = TfStringReplace(name, ",", "_");
165  name = TfStringReplace(name, "::", "_");
166  name = TfStringReplace(name, "<", "_");
167  name = TfStringReplace(name, ">", "_");
168  return name;
169  }
170 
171  static std::string _GetRepr(const View& x)
172  {
173  std::string result("{");
174  if (! x.empty()) {
175  const_iterator i = x.begin(), n = x.end();
176  result += TfPyRepr(x.key(i)) + ": " + TfPyRepr(*i);
177  while (++i != n) {
178  result += ", " + TfPyRepr(x.key(i)) + ": " + TfPyRepr(*i);
179  }
180  }
181  result += "}";
182  return result;
183  }
184 
185  static value_type _GetItemByKey(const View& x, const key_type& key)
186  {
187  const_iterator i = x.find(key);
188  if (i == x.end()) {
190  return value_type();
191  }
192  else {
193  return *i;
194  }
195  }
196 
197  static value_type _GetItemByIndex(const View& x, size_t index)
198  {
199  if (index >= x.size()) {
200  TfPyThrowIndexError("list index out of range");
201  }
202  return x[index];
203  }
204 
205  static boost::python::object _PyGet(const View& x, const key_type& key)
206  {
207  const_iterator i = x.find(key);
208  return i == x.end() ? boost::python::object() :
209  boost::python::object(*i);
210  }
211 
212  static bool _HasKey(const View& x, const key_type& key)
213  {
214  return x.find(key) != x.end();
215  }
216 
217  static bool _HasValue(const View& x, const value_type& value)
218  {
219  return x.find(value) != x.end();
220  }
221 
222  static
223  _Iterator<_ExtractItem> _GetItemIterator(const boost::python::object& x)
224  {
225  return _Iterator<_ExtractItem>(x);
226  }
227 
228  static
229  _Iterator<_ExtractKey> _GetKeyIterator(const boost::python::object& x)
230  {
231  return _Iterator<_ExtractKey>(x);
232  }
233 
234  static
235  _Iterator<_ExtractValue> _GetValueIterator(const boost::python::object& x)
236  {
237  return _Iterator<_ExtractValue>(x);
238  }
239 
240  template <class E>
241  static boost::python::list _Get(const View& x)
242  {
243  boost::python::list result;
244  for (const_iterator i = x.begin(), n = x.end(); i != n; ++i) {
245  result.append(E::Get(x, i));
246  }
247  return result;
248  }
249 
250  static int _FindIndexByKey(const View& x, const key_type& key)
251  {
252  size_t i = std::distance(x.begin(), x.find(key));
253  return i == x.size() ? -1 : i;
254  }
255 
256  static int _FindIndexByValue(const View& x, const value_type& value)
257  {
258  size_t i = std::distance(x.begin(), x.find(value));
259  return i == x.size() ? -1 : i;
260  }
261 };
262 
263 PXR_NAMESPACE_CLOSE_SCOPE
264 
265 #endif // PXR_USD_SDF_PY_CHILDREN_VIEW_H
Definitions of basic string utilities in tf.
TF_API void TfPyThrowStopIteration(const char *msg)
Raises a Python StopIteration with the given error msg and throws a boost::python::error_already_set ...
Miscellaneous Utilities for dealing with script.
Demangle C++ typenames generated by the typeid() facility.
std::string TfPyRepr(T const &t)
Return repr(t).
Definition: pyUtils.h:180
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 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.