Loading...
Searching...
No Matches
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"
33#include "pxr/base/tf/pyUtils.h"
35#include <boost/python.hpp>
36
37PXR_NAMESPACE_OPEN_SCOPE
38
39template <class T>
40class SdfPyWrapMapEditProxy {
41public:
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
55private:
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("values", &This::_GetValueIterator)
130 .def("keys", &This::_GetKeyIterator)
131 .def("items", &This::_GetItemIterator)
132 .def("clear", &Type::clear)
133 .def("get", &This::_PyGet)
134 .def("get", &This::_PyGetDefault)
135 .def("pop", &This::_Pop)
136 .def("popitem", &This::_PopItem)
137 .def("setdefault", &This::_SetDefault)
138 .def("update", &This::_UpdateDict)
139 .def("update", &This::_UpdateList)
140 .def("copy", &This::_Copy)
141 .add_property("expired", &Type::IsExpired)
142 .def("__bool__", &This::_IsValid)
143 .def(self == self)
144 .def(self != self)
145 ;
146
147 class_<_Iterator<_ExtractItem> >
148 ((name + "_Iterator").c_str(), no_init)
149 .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy)
150 .def("__next__", &This::template _Iterator<_ExtractItem>::GetNext)
151 ;
152
153 class_<_Iterator<_ExtractKey> >
154 ((name + "_KeyIterator").c_str(), no_init)
155 .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy)
156 .def("__next__", &This::template _Iterator<_ExtractKey>::GetNext)
157 ;
158
159 class_<_Iterator<_ExtractValue> >
160 ((name + "_ValueIterator").c_str(), no_init)
161 .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy)
162 .def("__next__", &This::template _Iterator<_ExtractValue>::GetNext)
163 ;
164 }
165
166 static std::string _GetName()
167 {
168 std::string name = "MapEditProxy_" +
169 ArchGetDemangled<typename Type::Type>();
170 name = TfStringReplace(name, " ", "_");
171 name = TfStringReplace(name, ",", "_");
172 name = TfStringReplace(name, "::", "_");
173 name = TfStringReplace(name, "<", "_");
174 name = TfStringReplace(name, ">", "_");
175 return name;
176 }
177
178 static std::string _GetRepr(const Type& x)
179 {
180 std::string arg;
181 if (x) {
182 arg = TfStringPrintf("<%s>", x._Location().c_str());
183 }
184 else {
185 arg = "<invalid>";
186 }
187 return TF_PY_REPR_PREFIX + _GetName() + "(" + arg + ")";
188 }
189
190 static std::string _GetStr(const Type& x)
191 {
192 std::string result("{");
193 if (x && ! x.empty()) {
194 const_iterator i = x.begin(), n = x.end();
195 result += TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
196 while (++i != n) {
197 result +=", " + TfPyRepr(i->first) + ": " + TfPyRepr(i->second);
198 }
199 }
200 result += "}";
201 return result;
202 }
203
204 static mapped_type _GetItem(const Type& x, const key_type& key)
205 {
206 const_iterator i = x.find(key);
207 if (i == x.end()) {
209 return mapped_type();
210 }
211 else {
212 return i->second;
213 }
214 }
215
216 static void _SetItem(Type& x, const key_type& key, const mapped_type& value)
217 {
218 std::pair<typename Type::iterator, bool> i =
219 x.insert(value_type(key, value));
220 if (! i.second && i.first != typename Type::iterator()) {
221 i.first->second = value;
222 }
223 }
224
225 static void _DelItem(Type& x, const key_type& key)
226 {
227 x.erase(key);
228 }
229
230 static bool _HasKey(const Type& x, const key_type& key)
231 {
232 return x.count(key) != 0;
233 }
234
235 static _Iterator<_ExtractItem>
236 _GetItemIterator(const boost::python::object& x)
237 {
238 return _Iterator<_ExtractItem>(x);
239 }
240
241 static _Iterator<_ExtractKey>
242 _GetKeyIterator(const boost::python::object& x)
243 {
244 return _Iterator<_ExtractKey>(x);
245 }
246
247 static _Iterator<_ExtractValue>
248 _GetValueIterator(const boost::python::object& x)
249 {
250 return _Iterator<_ExtractValue>(x);
251 }
252
253 static boost::python::object _PyGet(const Type& x, const key_type& key)
254 {
255 const_iterator i = x.find(key);
256 return i == x.end() ? boost::python::object() :
257 boost::python::object(i->second);
258 }
259
260 static mapped_type _PyGetDefault(const Type& x, const key_type& key,
261 const mapped_type& def)
262 {
263 const_iterator i = x.find(key);
264 return i == x.end() ? def : i->second;
265 }
266
267 template <class E>
268 static boost::python::list _Get(const Type& x)
269 {
270 boost::python::list result;
271 for (const_iterator i = x.begin(), n = x.end(); i != n; ++i) {
272 result.append(E::Get(i));
273 }
274 return result;
275 }
276
277 static mapped_type _Pop(Type& x, const key_type& key)
278 {
279 iterator i = x.find(key);
280 if (i == x.end()) {
282 return mapped_type();
283 }
284 else {
285 mapped_type result = i->second;
286 x.erase(i);
287 return result;
288 }
289 }
290
291 static boost::python::tuple _PopItem(Type& x)
292 {
293 if (x.empty()) {
294 TfPyThrowKeyError("MapEditProxy is empty");
295 return boost::python::tuple();
296 }
297 else {
298 iterator i = x.begin();
299 value_type result = *i;
300 x.erase(i);
301 return boost::python::make_tuple(result.first, result.second);
302 }
303 }
304
305 static mapped_type _SetDefault(Type& x, const key_type& key,
306 const mapped_type& def)
307 {
308 const_iterator i = x.find(key);
309 if (i != x.end()) {
310 return i->second;
311 }
312 else {
313 return x[key] = def;
314 }
315 }
316
317 static void _Update(Type& x, const std::vector<pair_type>& values)
318 {
319 SdfChangeBlock block;
320 TF_FOR_ALL(i, values) {
321 x[i->first] = i->second;
322 }
323 }
324
325 static void _UpdateDict(Type& x, const boost::python::dict& d)
326 {
327 _UpdateList(x, d.items());
328 }
329
330 static void _UpdateList(Type& x, const boost::python::list& pairs)
331 {
332 using namespace boost::python;
333
334 std::vector<pair_type> values;
335 for (int i = 0, n = len(pairs); i != n; ++i) {
336 values.push_back(pair_type(
337 extract<key_type>(pairs[i][0])(),
338 extract<mapped_type>(pairs[i][1])()));
339 }
340 _Update(x, values);
341 }
342
343 static void _Copy(Type& x, const typename Type::Type& other)
344 {
345 x = other;
346 }
347
348 static bool _IsValid(const Type& x)
349 {
350 return static_cast<bool>(x);
351 }
352};
353
354PXR_NAMESPACE_CLOSE_SCOPE
355
356#endif // PXR_USD_SDF_PY_MAP_EDIT_PROXY_H
A simple iterator adapter for STL containers.
Miscellaneous Utilities for dealing with script.
TF_API void TfPyThrowStopIteration(const char *msg)
Raises a Python StopIteration with the given error msg and throws a boost::python::error_already_set ...
TF_API void TfPyThrowKeyError(const char *msg)
Raises a Python KeyError with the given error msg and throws a boost::python::error_already_set excep...
#define TF_PY_REPR_PREFIX
A macro which expands to the proper repr prefix for a library.
Definition: pyUtils.h:59
std::string TfPyRepr(T const &t)
Return repr(t).
Definition: pyUtils.h:180
DANGER DANGER DANGER
Definition: changeBlock.h:73
Demangle C++ typenames generated by the typeid() facility.
#define TF_FOR_ALL(iter, c)
Macro for iterating over a container.
Definition: iterator.h:390
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.
TF_API std::string TfStringPrintf(const char *fmt,...)
Returns a string formed by a printf()-like specification.
Definitions of basic string utilities in tf.