All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pyMapEditProxy.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_PYMAPEDITPROXY_H
25 #define SDF_PYMAPEDITPROXY_H
26 
28 
29 #include "pxr/pxr.h"
30 #include "pxr/usd/sdf/changeBlock.h"
31 #include "pxr/base/arch/demangle.h"
32 #include "pxr/base/tf/iterator.h"
33 #include "pxr/base/tf/pyUtils.h"
34 #include "pxr/base/tf/stringUtils.h"
35 #include <boost/python.hpp>
36 
37 PXR_NAMESPACE_OPEN_SCOPE
38 
39 template <class T>
40 class SdfPyWrapMapEditProxy {
41 public:
42  typedef T Type;
43  typedef typename Type::key_type key_type;
44  typedef typename Type::mapped_type mapped_type;
45  typedef typename Type::value_type value_type;
46  typedef typename Type::iterator iterator;
47  typedef typename Type::const_iterator const_iterator;
48  typedef SdfPyWrapMapEditProxy<Type> This;
49 
50  SdfPyWrapMapEditProxy()
51  {
52  TfPyWrapOnce<Type>(&This::_Wrap);
53  }
54 
55 private:
56  typedef std::pair<key_type, mapped_type> pair_type;
57 
58  struct _ExtractItem {
59  static boost::python::object Get(const const_iterator& i)
60  {
61  return boost::python::make_tuple(i->first, i->second);
62  }
63  };
64 
65  struct _ExtractKey {
66  static boost::python::object Get(const const_iterator& i)
67  {
68  return boost::python::object(i->first);
69  }
70  };
71 
72  struct _ExtractValue {
73  static boost::python::object Get(const const_iterator& i)
74  {
75  return boost::python::object(i->second);
76  }
77  };
78 
79  template <class E>
80  class _Iterator {
81  public:
82  _Iterator(const boost::python::object& object) :
83  _object(object),
84  _owner(boost::python::extract<const Type&>(object)),
85  _cur(_owner.begin()),
86  _end(_owner.end())
87  {
88  // Do nothing
89  }
90 
91  _Iterator<E> GetCopy() const
92  {
93  return *this;
94  }
95 
96  boost::python::object GetNext()
97  {
98  if (_cur == _end) {
99  TfPyThrowStopIteration("End of MapEditProxy iteration");
100  }
101  boost::python::object result = E::Get(_cur);
102  ++_cur;
103  return result;
104  }
105 
106  private:
107  boost::python::object _object;
108  const Type& _owner;
109  const_iterator _cur;
110  const_iterator _end;
111  };
112 
113  static void _Wrap()
114  {
115  using namespace boost::python;
116 
117  std::string name = _GetName();
118 
119  scope thisScope =
120  class_<Type>(name.c_str())
121  .def("__repr__", &This::_GetRepr)
122  .def("__str__", &This::_GetStr)
123  .def("__len__", &Type::size)
124  .def("__getitem__", &This::_GetItem)
125  .def("__setitem__", &This::_SetItem)
126  .def("__delitem__", &This::_DelItem)
127  .def("__contains__", &This::_HasKey)
128  .def("__iter__", &This::_GetKeyIterator)
129  .def("itervalues", &This::_GetValueIterator)
130  .def("iterkeys", &This::_GetKeyIterator)
131  .def("iteritems", &This::_GetItemIterator)
132  .def("clear", &Type::clear)
133  .def("get", &This::_PyGet)
134  .def("get", &This::_PyGetDefault)
135  .def("has_key", &This::_HasKey)
136  .def("items", &This::_GetItems)
137  .def("keys", &This::_GetKeys)
138  .def("values", &This::_GetValues)
139  .def("pop", &This::_Pop)
140  .def("popitem", &This::_PopItem)
141  .def("setdefault", &This::_SetDefault)
142  .def("update", &This::_UpdateDict)
143  .def("update", &This::_UpdateList)
144  .def("copy", &This::_Copy)
145  .add_property("expired", &Type::IsExpired)
146  .def("__nonzero__", &This::_NonZero)
147  .def(self == self)
148  .def(self != self)
149  ;
150 
151  class_<_Iterator<_ExtractItem> >
152  ((name + "_Iterator").c_str(), no_init)
153  .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
154  .def("next", &This::template _Iterator<_ExtractItem>::GetNext)
155  ;
156 
157  class_<_Iterator<_ExtractKey> >
158  ((name + "_KeyIterator").c_str(), no_init)
159  .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
160  .def("next", &This::template _Iterator<_ExtractKey>::GetNext)
161  ;
162 
163  class_<_Iterator<_ExtractValue> >
164  ((name + "_ValueIterator").c_str(), no_init)
165  .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
166  .def("next", &This::template _Iterator<_ExtractValue>::GetNext)
167  ;
168  }
169 
170  static std::string _GetName()
171  {
172  std::string name = "MapEditProxy_" +
173  ArchGetDemangled<typename Type::Type>();
174  name = TfStringReplace(name, " ", "_");
175  name = TfStringReplace(name, ",", "_");
176  name = TfStringReplace(name, "::", "_");
177  name = TfStringReplace(name, "<", "_");
178  name = TfStringReplace(name, ">", "_");
179  return name;
180  }
181 
182  static std::string _GetRepr(const Type& x)
183  {
184  std::string arg;
185  if (x) {
186  arg = TfStringPrintf("<%s>", x._Location().c_str());
187  }
188  else {
189  arg = "<invalid>";
190  }
191  return TF_PY_REPR_PREFIX + _GetName() + "(" + arg + ")";
192  }
193 
194  static std::string _GetStr(const Type& x)
195  {
196  std::string result("{");
197  if (x && ! x.empty()) {
198  const_iterator i = x.begin(), n = x.end();
199  result += TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
200  while (++i != n) {
201  result +=", " + TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
202  }
203  }
204  result += "}";
205  return result;
206  }
207 
208  static mapped_type _GetItem(const Type& x, const key_type& key)
209  {
210  const_iterator i = x.find(key);
211  if (i == x.end()) {
213  return mapped_type();
214  }
215  else {
216  return i->second;
217  }
218  }
219 
220  static void _SetItem(Type& x, const key_type& key, const mapped_type& value)
221  {
222  std::pair<typename Type::iterator, bool> i =
223  x.insert(value_type(key, value));
224  if (! i.second && i.first != typename Type::iterator()) {
225  i.first->second = value;
226  }
227  }
228 
229  static void _DelItem(Type& x, const key_type& key)
230  {
231  x.erase(key);
232  }
233 
234  static bool _HasKey(const Type& x, const key_type& key)
235  {
236  return x.count(key) != 0;
237  }
238 
239  static _Iterator<_ExtractItem>
240  _GetItemIterator(const boost::python::object& x)
241  {
242  return _Iterator<_ExtractItem>(x);
243  }
244 
245  static _Iterator<_ExtractKey>
246  _GetKeyIterator(const boost::python::object& x)
247  {
248  return _Iterator<_ExtractKey>(x);
249  }
250 
251  static _Iterator<_ExtractValue>
252  _GetValueIterator(const boost::python::object& x)
253  {
254  return _Iterator<_ExtractValue>(x);
255  }
256 
257  static boost::python::object _PyGet(const Type& x, const key_type& key)
258  {
259  const_iterator i = x.find(key);
260  return i == x.end() ? boost::python::object() :
261  boost::python::object(i->second);
262  }
263 
264  static mapped_type _PyGetDefault(const Type& x, const key_type& key,
265  const mapped_type& def)
266  {
267  const_iterator i = x.find(key);
268  return i == x.end() ? def : i->second;
269  }
270 
271  template <class E>
272  static boost::python::list _Get(const Type& x)
273  {
274  boost::python::list result;
275  for (const_iterator i = x.begin(), n = x.end(); i != n; ++i) {
276  result.append(E::Get(i));
277  }
278  return result;
279  }
280 
281  static boost::python::list _GetItems(const Type& x)
282  {
283  return _Get<_ExtractItem>(x);
284  }
285 
286  static boost::python::list _GetKeys(const Type& x)
287  {
288  return _Get<_ExtractKey>(x);
289  }
290 
291  static boost::python::list _GetValues(const Type& x)
292  {
293  return _Get<_ExtractValue>(x);
294  }
295 
296  static mapped_type _Pop(Type& x, const key_type& key)
297  {
298  iterator i = x.find(key);
299  if (i == x.end()) {
301  return mapped_type();
302  }
303  else {
304  mapped_type result = i->second;
305  x.erase(i);
306  return result;
307  }
308  }
309 
310  static boost::python::tuple _PopItem(Type& x)
311  {
312  if (x.empty()) {
313  TfPyThrowKeyError("MapEditProxy is empty");
314  return boost::python::tuple();
315  }
316  else {
317  iterator i = x.begin();
318  value_type result = *i;
319  x.erase(i);
320  return boost::python::make_tuple(result.first, result.second);
321  }
322  }
323 
324  static mapped_type _SetDefault(Type& x, const key_type& key,
325  const mapped_type& def)
326  {
327  const_iterator i = x.find(key);
328  if (i != x.end()) {
329  return i->second;
330  }
331  else {
332  return x[key] = def;
333  }
334  }
335 
336  static void _Update(Type& x, const std::vector<pair_type>& values)
337  {
338  SdfChangeBlock block;
339  TF_FOR_ALL(i, values) {
340  x[i->first] = i->second;
341  }
342  }
343 
344  static void _UpdateDict(Type& x, const boost::python::dict& d)
345  {
346  _UpdateList(x, d.items());
347  }
348 
349  static void _UpdateList(Type& x, const boost::python::list& pairs)
350  {
351  using namespace boost::python;
352 
353  std::vector<pair_type> values;
354  for (int i = 0, n = len(pairs); i != n; ++i) {
355  values.push_back(pair_type(
356  extract<key_type>(pairs[i][0])(),
357  extract<mapped_type>(pairs[i][1])()));
358  }
359  _Update(x, values);
360  }
361 
362  static void _Copy(Type& x, const typename Type::Type& other)
363  {
364  x = other;
365  }
366 
367  static bool _NonZero(const Type& x)
368  {
369  return static_cast<bool>(x);
370  }
371 };
372 
373 PXR_NAMESPACE_CLOSE_SCOPE
374 
375 #endif // SDF_PYMAPEDITPROXY_H
TF_API std::string TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
DANGER DANGER DANGER
Definition: changeBlock.h:72
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:390
TF_API void TfPyThrowKeyError(std::string const &msg)
Raises a python KeyError and throws a C++ exception.
TF_API void TfPyThrowStopIteration(std::string const &msg)
Raises a python StopIteration exception and throws a C++ exception.
#define TF_PY_REPR_PREFIX
A macro which expands to the proper repr prefix for a library.
Definition: pyUtils.h:57
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