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 PXR_USD_SDF_PY_MAP_EDIT_PROXY_H
25 #define PXR_USD_SDF_PY_MAP_EDIT_PROXY_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"
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 #if PY_MAJOR_VERSION < 3
130  .def("itervalues", &This::_GetValueIterator)
131  .def("iterkeys", &This::_GetKeyIterator)
132  .def("iteritems", &This::_GetItemIterator)
133  .def("values", &This::_GetValues)
134  .def("keys", &This::_GetKeys)
135  .def("items", &This::_GetItems)
136  .def("has_key", &This::_HasKey)
137 #else
138  .def("values", &This::_GetValueIterator)
139  .def("keys", &This::_GetKeyIterator)
140  .def("items", &This::_GetItemIterator)
141 #endif
142  .def("clear", &Type::clear)
143  .def("get", &This::_PyGet)
144  .def("get", &This::_PyGetDefault)
145  .def("pop", &This::_Pop)
146  .def("popitem", &This::_PopItem)
147  .def("setdefault", &This::_SetDefault)
148  .def("update", &This::_UpdateDict)
149  .def("update", &This::_UpdateList)
150  .def("copy", &This::_Copy)
151  .add_property("expired", &Type::IsExpired)
152  .def(TfPyBoolBuiltinFuncName, &This::_NonZero)
153  .def(self == self)
154  .def(self != self)
155  ;
156 
157  class_<_Iterator<_ExtractItem> >
158  ((name + "_Iterator").c_str(), no_init)
159  .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
160  .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractItem>::GetNext)
161  ;
162 
163  class_<_Iterator<_ExtractKey> >
164  ((name + "_KeyIterator").c_str(), no_init)
165  .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
166  .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractKey>::GetNext)
167  ;
168 
169  class_<_Iterator<_ExtractValue> >
170  ((name + "_ValueIterator").c_str(), no_init)
171  .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
172  .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractValue>::GetNext)
173  ;
174  }
175 
176  static std::string _GetName()
177  {
178  std::string name = "MapEditProxy_" +
179  ArchGetDemangled<typename Type::Type>();
180  name = TfStringReplace(name, " ", "_");
181  name = TfStringReplace(name, ",", "_");
182  name = TfStringReplace(name, "::", "_");
183  name = TfStringReplace(name, "<", "_");
184  name = TfStringReplace(name, ">", "_");
185  return name;
186  }
187 
188  static std::string _GetRepr(const Type& x)
189  {
190  std::string arg;
191  if (x) {
192  arg = TfStringPrintf("<%s>", x._Location().c_str());
193  }
194  else {
195  arg = "<invalid>";
196  }
197  return TF_PY_REPR_PREFIX + _GetName() + "(" + arg + ")";
198  }
199 
200  static std::string _GetStr(const Type& x)
201  {
202  std::string result("{");
203  if (x && ! x.empty()) {
204  const_iterator i = x.begin(), n = x.end();
205  result += TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
206  while (++i != n) {
207  result +=", " + TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
208  }
209  }
210  result += "}";
211  return result;
212  }
213 
214  static mapped_type _GetItem(const Type& x, const key_type& key)
215  {
216  const_iterator i = x.find(key);
217  if (i == x.end()) {
219  return mapped_type();
220  }
221  else {
222  return i->second;
223  }
224  }
225 
226  static void _SetItem(Type& x, const key_type& key, const mapped_type& value)
227  {
228  std::pair<typename Type::iterator, bool> i =
229  x.insert(value_type(key, value));
230  if (! i.second && i.first != typename Type::iterator()) {
231  i.first->second = value;
232  }
233  }
234 
235  static void _DelItem(Type& x, const key_type& key)
236  {
237  x.erase(key);
238  }
239 
240  static bool _HasKey(const Type& x, const key_type& key)
241  {
242  return x.count(key) != 0;
243  }
244 
245  static _Iterator<_ExtractItem>
246  _GetItemIterator(const boost::python::object& x)
247  {
248  return _Iterator<_ExtractItem>(x);
249  }
250 
251  static _Iterator<_ExtractKey>
252  _GetKeyIterator(const boost::python::object& x)
253  {
254  return _Iterator<_ExtractKey>(x);
255  }
256 
257  static _Iterator<_ExtractValue>
258  _GetValueIterator(const boost::python::object& x)
259  {
260  return _Iterator<_ExtractValue>(x);
261  }
262 
263  static boost::python::object _PyGet(const Type& x, const key_type& key)
264  {
265  const_iterator i = x.find(key);
266  return i == x.end() ? boost::python::object() :
267  boost::python::object(i->second);
268  }
269 
270  static mapped_type _PyGetDefault(const Type& x, const key_type& key,
271  const mapped_type& def)
272  {
273  const_iterator i = x.find(key);
274  return i == x.end() ? def : i->second;
275  }
276 
277  template <class E>
278  static boost::python::list _Get(const Type& x)
279  {
280  boost::python::list result;
281  for (const_iterator i = x.begin(), n = x.end(); i != n; ++i) {
282  result.append(E::Get(i));
283  }
284  return result;
285  }
286 
287 #if PY_MAJOR_VERSION < 3
288  static boost::python::list _GetItems(const Type& x)
289  {
290  return _Get<_ExtractItem>(x);
291  }
292 
293  static boost::python::list _GetKeys(const Type& x)
294  {
295  return _Get<_ExtractKey>(x);
296  }
297 
298  static boost::python::list _GetValues(const Type& x)
299  {
300  return _Get<_ExtractValue>(x);
301  }
302 #endif
303 
304  static mapped_type _Pop(Type& x, const key_type& key)
305  {
306  iterator i = x.find(key);
307  if (i == x.end()) {
309  return mapped_type();
310  }
311  else {
312  mapped_type result = i->second;
313  x.erase(i);
314  return result;
315  }
316  }
317 
318  static boost::python::tuple _PopItem(Type& x)
319  {
320  if (x.empty()) {
321  TfPyThrowKeyError("MapEditProxy is empty");
322  return boost::python::tuple();
323  }
324  else {
325  iterator i = x.begin();
326  value_type result = *i;
327  x.erase(i);
328  return boost::python::make_tuple(result.first, result.second);
329  }
330  }
331 
332  static mapped_type _SetDefault(Type& x, const key_type& key,
333  const mapped_type& def)
334  {
335  const_iterator i = x.find(key);
336  if (i != x.end()) {
337  return i->second;
338  }
339  else {
340  return x[key] = def;
341  }
342  }
343 
344  static void _Update(Type& x, const std::vector<pair_type>& values)
345  {
346  SdfChangeBlock block;
347  TF_FOR_ALL(i, values) {
348  x[i->first] = i->second;
349  }
350  }
351 
352  static void _UpdateDict(Type& x, const boost::python::dict& d)
353  {
354  _UpdateList(x, d.items());
355  }
356 
357  static void _UpdateList(Type& x, const boost::python::list& pairs)
358  {
359  using namespace boost::python;
360 
361  std::vector<pair_type> values;
362  for (int i = 0, n = len(pairs); i != n; ++i) {
363  values.push_back(pair_type(
364  extract<key_type>(pairs[i][0])(),
365  extract<mapped_type>(pairs[i][1])()));
366  }
367  _Update(x, values);
368  }
369 
370  static void _Copy(Type& x, const typename Type::Type& other)
371  {
372  x = other;
373  }
374 
375  static bool _NonZero(const Type& x)
376  {
377  return static_cast<bool>(x);
378  }
379 };
380 
381 PXR_NAMESPACE_CLOSE_SCOPE
382 
383 #endif // PXR_USD_SDF_PY_MAP_EDIT_PROXY_H
TF_API std::string TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
A simple iterator adapter for STL containers.
Definitions of basic string utilities in tf.
TF_API void TfPyThrowKeyError(std::string const &msg)
Raises a python KeyError and throws a C++ exception.
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:138
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 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:59
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.