// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #ifndef PXR_USD_SDF_PY_CHILDREN_VIEW_H #define PXR_USD_SDF_PY_CHILDREN_VIEW_H /// \file sdf/pyChildrenView.h #include "pxr/pxr.h" #include "pxr/usd/sdf/childrenView.h" #include "pxr/base/arch/demangle.h" #include "pxr/base/tf/pyUtils.h" #include "pxr/base/tf/stringUtils.h" #include PXR_NAMESPACE_OPEN_SCOPE template class SdfPyWrapChildrenView { public: typedef _View View; typedef typename View::ChildPolicy ChildPolicy; typedef typename View::Predicate Predicate; typedef typename View::key_type key_type; typedef typename View::value_type value_type; typedef typename View::const_iterator const_iterator; typedef SdfPyWrapChildrenView This; SdfPyWrapChildrenView() { TfPyWrapOnce(&This::_Wrap); } private: struct _ExtractItem { static boost::python::object Get(const View& x, const const_iterator& i) { return boost::python::make_tuple(x.key(i), *i); } }; struct _ExtractKey { static boost::python::object Get(const View& x, const const_iterator& i) { return boost::python::object(x.key(i)); } }; struct _ExtractValue { static boost::python::object Get(const View& x, const const_iterator& i) { return boost::python::object(*i); } }; template class _Iterator { public: _Iterator(const boost::python::object& object) : _object(object), _owner(boost::python::extract(object)), _cur(_owner.begin()), _end(_owner.end()) { // Do nothing } _Iterator GetCopy() const { return *this; } boost::python::object GetNext() { if (_cur == _end) { TfPyThrowStopIteration("End of ChildrenProxy iteration"); } boost::python::object result = E::Get(_owner, _cur); ++_cur; return result; } private: boost::python::object _object; const View& _owner; const_iterator _cur; const_iterator _end; }; static void _Wrap() { using namespace boost::python; std::string name = _GetName(); // Note: Using the value iterator for the __iter__ method is not // consistent with Python dicts (which iterate over keys). // However, we're emulating TfPyKeyedVector, which iterates // over values as a vector would. scope thisScope = class_(name.c_str(), no_init) .def("__repr__", &This::_GetRepr) .def("__len__", &View::size) .def("__getitem__", &This::_GetItemByKey) .def("__getitem__", &This::_GetItemByIndex) .def("get", &This::_PyGet) .def("__contains__", &This::_HasKey) .def("__contains__", &This::_HasValue) .def("__iter__", &This::_GetValueIterator) #if PY_MAJOR_VERSION < 3 .def("has_key", &This::_HasKey) .def("itervalues", &This::_GetValueIterator) .def("iterkeys", &This::_GetKeyIterator) .def("iteritems", &This::_GetItemIterator) .def("items", &This::_GetItems) .def("keys", &This::_GetKeys) .def("values", &This::_GetValues) #else .def("items", &This::_GetItemIterator) .def("keys", &This::_GetKeyIterator) .def("values", &This::_GetValueIterator) #endif .def("index", &This::_FindIndexByKey) .def("index", &This::_FindIndexByValue) .def(self == self) .def(self != self) ; class_<_Iterator<_ExtractItem> > ((name + "_Iterator").c_str(), no_init) .def("__iter__", &This::template _Iterator<_ExtractItem>::GetCopy) .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractItem>::GetNext) ; class_<_Iterator<_ExtractKey> > ((name + "_KeyIterator").c_str(), no_init) .def("__iter__", &This::template _Iterator<_ExtractKey>::GetCopy) .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractKey>::GetNext) ; class_<_Iterator<_ExtractValue> > ((name + "_ValueIterator").c_str(), no_init) .def("__iter__", &This::template _Iterator<_ExtractValue>::GetCopy) .def(TfPyIteratorNextMethodName, &This::template _Iterator<_ExtractValue>::GetNext) ; } static std::string _GetName() { std::string name = "ChildrenView_" + ArchGetDemangled() + "_" + ArchGetDemangled(); name = TfStringReplace(name, " ", "_"); name = TfStringReplace(name, ",", "_"); name = TfStringReplace(name, "::", "_"); name = TfStringReplace(name, "<", "_"); name = TfStringReplace(name, ">", "_"); return name; } static std::string _GetRepr(const View& x) { std::string result("{"); if (! x.empty()) { const_iterator i = x.begin(), n = x.end(); result += TfPyRepr(x.key(i)) + ": " + TfPyRepr(*i); while (++i != n) { result += ", " + TfPyRepr(x.key(i)) + ": " + TfPyRepr(*i); } } result += "}"; return result; } static value_type _GetItemByKey(const View& x, const key_type& key) { const_iterator i = x.find(key); if (i == x.end()) { TfPyThrowIndexError(TfPyRepr(key)); return value_type(); } else { return *i; } } static value_type _GetItemByIndex(const View& x, size_t index) { if (index >= x.size()) { TfPyThrowIndexError("list index out of range"); } return x[index]; } static boost::python::object _PyGet(const View& x, const key_type& key) { const_iterator i = x.find(key); return i == x.end() ? boost::python::object() : boost::python::object(*i); } static bool _HasKey(const View& x, const key_type& key) { return x.find(key) != x.end(); } static bool _HasValue(const View& x, const value_type& value) { return x.find(value) != x.end(); } static _Iterator<_ExtractItem> _GetItemIterator(const boost::python::object& x) { return _Iterator<_ExtractItem>(x); } static _Iterator<_ExtractKey> _GetKeyIterator(const boost::python::object& x) { return _Iterator<_ExtractKey>(x); } static _Iterator<_ExtractValue> _GetValueIterator(const boost::python::object& x) { return _Iterator<_ExtractValue>(x); } template static boost::python::list _Get(const View& x) { boost::python::list result; for (const_iterator i = x.begin(), n = x.end(); i != n; ++i) { result.append(E::Get(x, i)); } return result; } #if PY_MAJOR_VERSION < 3 static boost::python::list _GetItems(const View& x) { return _Get<_ExtractItem>(x); } static boost::python::list _GetKeys(const View& x) { return _Get<_ExtractKey>(x); } static boost::python::list _GetValues(const View& x) { return _Get<_ExtractValue>(x); } #endif static int _FindIndexByKey(const View& x, const key_type& key) { size_t i = std::distance(x.begin(), x.find(key)); return i == x.size() ? -1 : i; } static int _FindIndexByValue(const View& x, const value_type& value) { size_t i = std::distance(x.begin(), x.find(value)); return i == x.size() ? -1 : i; } }; PXR_NAMESPACE_CLOSE_SCOPE #endif // PXR_USD_SDF_PY_CHILDREN_VIEW_H