2
// Copyright 2016 Pixar
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:
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.
14
// You may obtain a copy of the Apache License at
16
// http://www.apache.org/licenses/LICENSE-2.0
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.
24
/// \file sdf/pyListProxy.h
26
#ifndef SDF_PYLISTPROXY_H
27
#define SDF_PYLISTPROXY_H
29
#include "pxr/usd/sdf/changeBlock.h"
30
#include "pxr/usd/sdf/listProxy.h"
31
#include "pxr/base/arch/demangle.h"
32
#include "pxr/base/tf/pyLock.h"
33
#include "pxr/base/tf/pyUtils.h"
34
#include "pxr/base/tf/pyResultConversions.h"
35
#include "pxr/base/tf/stringUtils.h"
37
#include <boost/python.hpp>
38
#include <boost/python/slice.hpp>
41
class SdfPyWrapListProxy {
44
typedef typename Type::TypePolicy TypePolicy;
45
typedef typename Type::value_type value_type;
46
typedef typename Type::value_vector_type value_vector_type;
47
typedef SdfPyWrapListProxy<Type> This;
51
TfPyWrapOnce<Type>(&This::_Wrap);
57
using namespace boost::python;
59
class_<Type>(_GetName().c_str(), no_init)
60
.def("__str__", &This::_GetStr)
61
.def("__len__", &Type::size)
62
.def("__getitem__", &This::_GetItemIndex)
63
.def("__getitem__", &This::_GetItemSlice)
64
.def("__setitem__", &This::_SetItemIndex)
65
.def("__setitem__", &This::_SetItemSlice)
66
.def("__delitem__", &This::_DelItemIndex)
67
.def("__delitem__", &This::_DelItemSlice)
68
.def("__delitem__", &Type::Remove)
69
.def("count", &Type::Count)
70
.def("copy", &Type::operator value_vector_type,
71
return_value_policy<TfPySequenceToList>())
72
.def("index", &This::_FindIndex)
73
.def("clear", &Type::clear)
74
.def("insert", &This::_Insert)
75
.def("append", &Type::push_back)
76
.def("remove", &Type::Remove)
77
.def("replace", &Type::Replace)
78
.def("ApplyList", &Type::ApplyList)
79
.add_property("expired", &This::_IsExpired)
86
.def(self == other<value_vector_type>())
87
.def(self != other<value_vector_type>())
88
.def(self < other<value_vector_type>())
89
.def(self <= other<value_vector_type>())
90
.def(self > other<value_vector_type>())
91
.def(self >= other<value_vector_type>())
95
static std::string _GetName()
97
std::string name = "ListProxy_" +
98
ArchGetDemangled<TypePolicy>();
99
name = TfStringReplace(name, " ", "_");
100
name = TfStringReplace(name, ",", "_");
101
name = TfStringReplace(name, "::", "_");
102
name = TfStringReplace(name, "<", "_");
103
name = TfStringReplace(name, ">", "_");
107
static std::string _GetStr(const Type& x)
109
return TfPyRepr(static_cast<value_vector_type>(x));
112
static value_type _GetItemIndex(const Type& x, int index)
114
return x[TfPyNormalizeIndex(index, x._GetSize(), true)];
117
static boost::python::list _GetItemSlice(const Type& x,
118
const boost::python::slice& index)
120
using namespace boost::python;
126
slice::range<typename Type::const_iterator> range =
127
index.get_indicies(x.begin(), x.end());
128
for (; range.start != range.stop; range.start += range.step) {
129
result.append(*range.start);
131
result.append(*range.start);
133
catch (const std::invalid_argument&) {
141
static void _SetItemIndex(Type& x, int index, const value_type& value)
143
x[TfPyNormalizeIndex(index, x._GetSize(), true)] = value;
146
static void _SetItemSlice(Type& x, const boost::python::slice& index,
147
const value_vector_type& values)
149
using namespace boost::python;
151
if (not x._Validate()) {
155
// Get the range and the number of items in the slice.
156
size_t start, step, count;
158
slice::range<typename Type::iterator> range =
159
index.get_indicies(x.begin(), x.end());
160
start = range.start - x.begin();
162
count = 1 + (range.stop - range.start) / range.step;
164
catch (const std::invalid_argument&) {
166
extract<int> e(index.start());
167
start = e.check() ? TfPyNormalizeIndex(e(), x._GetSize(), true) : 0;
172
if (TfPyIsNone(index.step())) {
173
// Replace contiguous sequence with values.
174
x._Edit(start, count, values);
177
// Replace exactly the selected items.
178
if (count != values.size()) {
180
TfStringPrintf("attempt to assign sequence of size %zd "
181
"to extended slice of size %zd",
182
values.size(), count).c_str());
184
else if (step == 1) {
185
x._Edit(start, count, values);
188
SdfChangeBlock block;
189
for (size_t i = 0, j = start; i != count; j += step, ++i) {
190
x._Edit(j, 1, value_vector_type(1, values[i]));
196
static void _DelItemIndex(Type& x, int i)
198
x._Edit(TfPyNormalizeIndex(i, x._GetSize(), true),
199
1, value_vector_type());
202
static void _DelItemSlice(Type& x, const boost::python::slice& index)
204
using namespace boost::python;
208
// Get the range and the number of items in the slice.
209
slice::range<typename Type::iterator> range =
210
index.get_indicies(x.begin(), x.end());
211
size_t start = range.start - x.begin();
212
size_t step = range.step;
213
size_t count = 1 + (range.stop - range.start) / range.step;
217
x._Edit(start, count, value_vector_type());
220
SdfChangeBlock block;
221
value_vector_type empty;
222
for (size_t j = start; count > 0; j += step - 1, --count) {
223
x._Edit(j, 1, empty);
227
catch (const std::invalid_argument&) {
228
// Empty slice -- do nothing.
233
static int _FindIndex(const Type& x, const value_type& value)
236
return static_cast<int>(x.Find(value));
243
static void _Insert(Type& x, int index, const value_type& value)
246
index += x._GetSize();
248
if (index < 0 or index > static_cast<int>(x._GetSize())) {
249
TfPyThrowIndexError("list index out of range");
251
x._Edit(index, 0, value_vector_type(1, value));
254
static bool _IsExpired(const Type& x)
256
return x.IsExpired();