~popey/+junk/usd

« back to all changes in this revision

Viewing changes to USD/pxr/usd/lib/sdf/pyListProxy.h

  • Committer: Alan Pope
  • Date: 2016-09-29 12:05:28 UTC
  • Revision ID: alan@popey.com-20160929120528-32j3uk1x0dgaorip
Initial attempt to snap

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
/// \file sdf/pyListProxy.h
 
25
 
 
26
#ifndef SDF_PYLISTPROXY_H
 
27
#define SDF_PYLISTPROXY_H
 
28
 
 
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"
 
36
#include <stdexcept>
 
37
#include <boost/python.hpp>
 
38
#include <boost/python/slice.hpp>
 
39
 
 
40
template <class T>
 
41
class SdfPyWrapListProxy {
 
42
public:
 
43
    typedef T Type;
 
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;
 
48
 
 
49
    SdfPyWrapListProxy()
 
50
    {
 
51
        TfPyWrapOnce<Type>(&This::_Wrap);
 
52
    }
 
53
 
 
54
private:
 
55
    static void _Wrap()
 
56
    {
 
57
        using namespace boost::python;
 
58
 
 
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)
 
80
            .def(self == self)
 
81
            .def(self != self)
 
82
            .def(self <  self)
 
83
            .def(self <= self)
 
84
            .def(self >  self)
 
85
            .def(self >= self)
 
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>())
 
92
            ;
 
93
    }
 
94
 
 
95
    static std::string _GetName()
 
96
    {
 
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, ">", "_");
 
104
        return name;
 
105
    }
 
106
 
 
107
    static std::string _GetStr(const Type& x)
 
108
    {
 
109
        return TfPyRepr(static_cast<value_vector_type>(x));
 
110
    }
 
111
 
 
112
    static value_type _GetItemIndex(const Type& x, int index)
 
113
    {
 
114
        return x[TfPyNormalizeIndex(index, x._GetSize(), true)];
 
115
    }
 
116
 
 
117
    static boost::python::list _GetItemSlice(const Type& x,
 
118
                                             const boost::python::slice& index)
 
119
    {
 
120
        using namespace boost::python;
 
121
 
 
122
        list result;
 
123
 
 
124
        if (x._Validate()) {
 
125
            try {
 
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);
 
130
                }
 
131
                result.append(*range.start);
 
132
            }
 
133
            catch (const std::invalid_argument&) {
 
134
                // Ignore.
 
135
            }
 
136
        }
 
137
 
 
138
        return result;
 
139
    }
 
140
 
 
141
    static void _SetItemIndex(Type& x, int index, const value_type& value)
 
142
    {
 
143
        x[TfPyNormalizeIndex(index, x._GetSize(), true)] = value;
 
144
    }
 
145
 
 
146
    static void _SetItemSlice(Type& x, const boost::python::slice& index,
 
147
                              const value_vector_type& values)
 
148
    {
 
149
        using namespace boost::python;
 
150
 
 
151
        if (not x._Validate()) {
 
152
            return;
 
153
        }
 
154
 
 
155
        // Get the range and the number of items in the slice.
 
156
        size_t start, step, count;
 
157
        try {
 
158
            slice::range<typename Type::iterator> range =
 
159
                index.get_indicies(x.begin(), x.end());
 
160
            start = range.start - x.begin();
 
161
            step  = range.step;
 
162
            count = 1 + (range.stop - range.start) / range.step;
 
163
        }
 
164
        catch (const std::invalid_argument&) {
 
165
            // Empty range.
 
166
            extract<int> e(index.start());
 
167
            start = e.check() ? TfPyNormalizeIndex(e(), x._GetSize(), true) : 0;
 
168
            step  = 0;
 
169
            count = 0;
 
170
        }
 
171
 
 
172
        if (TfPyIsNone(index.step())) {
 
173
            // Replace contiguous sequence with values.
 
174
            x._Edit(start, count, values);
 
175
        }
 
176
        else {
 
177
            // Replace exactly the selected items.
 
178
            if (count != values.size()) {
 
179
                TfPyThrowValueError(
 
180
                    TfStringPrintf("attempt to assign sequence of size %zd "
 
181
                                   "to extended slice of size %zd",
 
182
                                   values.size(), count).c_str());
 
183
            }
 
184
            else if (step == 1) {
 
185
                x._Edit(start, count, values);
 
186
            }
 
187
            else {
 
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]));
 
191
                }
 
192
            }
 
193
        }
 
194
    }
 
195
 
 
196
    static void _DelItemIndex(Type& x, int i)
 
197
    {
 
198
        x._Edit(TfPyNormalizeIndex(i, x._GetSize(), true),
 
199
                1, value_vector_type());
 
200
    }
 
201
 
 
202
    static void _DelItemSlice(Type& x, const boost::python::slice& index)
 
203
    {
 
204
        using namespace boost::python;
 
205
 
 
206
        if (x._Validate()) {
 
207
            try {
 
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;
 
214
 
 
215
                // Erase items.
 
216
                if (step == 1) {
 
217
                    x._Edit(start, count, value_vector_type());
 
218
                }
 
219
                else {
 
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);
 
224
                    }
 
225
                }
 
226
            }
 
227
            catch (const std::invalid_argument&) {
 
228
                // Empty slice -- do nothing.
 
229
            }
 
230
        }
 
231
    }
 
232
 
 
233
    static int _FindIndex(const Type& x, const value_type& value)
 
234
    {
 
235
        if (x._Validate()) {
 
236
            return static_cast<int>(x.Find(value));
 
237
        }
 
238
        else {
 
239
            return -1;
 
240
        }
 
241
    }
 
242
 
 
243
    static void _Insert(Type& x, int index, const value_type& value)
 
244
    {
 
245
        if (index < 0) {
 
246
            index += x._GetSize();
 
247
        }
 
248
        if (index < 0 or index > static_cast<int>(x._GetSize())) {
 
249
            TfPyThrowIndexError("list index out of range");
 
250
        }
 
251
        x._Edit(index, 0, value_vector_type(1, value));
 
252
    }
 
253
 
 
254
    static bool _IsExpired(const Type& x)
 
255
    {
 
256
        return x.IsExpired();
 
257
    }
 
258
};
 
259
 
 
260
#endif