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 ////////////////////////////////////////////////////////////////////////
25 // This file is generated by a script.  Do not edit directly.  Edit the
26 // wrapVec.template.cpp file to make changes.
27 
28 #include "pxr/pxr.h"
29 #include "pxr/base/gf/vec2i.h"
30 
31 #include "pxr/base/gf/pyBufferUtils.h"
32 
33 #include "pxr/base/tf/py3Compat.h"
34 #include "pxr/base/tf/pyContainerConversions.h"
35 #include "pxr/base/tf/pyUtils.h"
36 #include "pxr/base/tf/stringUtils.h"
37 #include "pxr/base/tf/wrapTypeHelpers.h"
38 
39 
40 #include <boost/python/class.hpp>
41 #include <boost/python/def.hpp>
42 #include <boost/python/make_constructor.hpp>
43 #include <boost/python/operators.hpp>
44 #include <boost/python/overloads.hpp>
45 #include <boost/python/tuple.hpp>
46 #include <boost/python/slice.hpp>
47 
48 #include <boost/functional/hash.hpp>
49 
50 #include <string>
51 
52 using namespace boost::python;
53 
54 using std::string;
55 
56 PXR_NAMESPACE_USING_DIRECTIVE
57 
58 namespace {
59 
60 ////////////////////////////////////////////////////////////////////////
61 // Python buffer protocol support.
62 
63 #if PY_MAJOR_VERSION == 2
64 // Python's getreadbuf interface function.
65 static Py_ssize_t
getreadbuf(PyObject * self,Py_ssize_t segment,void ** ptrptr)66 getreadbuf(PyObject *self, Py_ssize_t segment, void **ptrptr) {
67     if (segment != 0) {
68         // Always one-segment.
69         PyErr_SetString(PyExc_ValueError, "accessed non-existent segment");
70         return -1;
71     }
72     GfVec2i &vec = extract<GfVec2i &>(self);
73     *ptrptr = static_cast<void *>(vec.data());
74     // Return size in bytes.
75     return sizeof(GfVec2i);
76 }
77 
78 // Python's getwritebuf interface function.
79 static Py_ssize_t
getwritebuf(PyObject * self,Py_ssize_t segment,void ** ptrptr)80 getwritebuf(PyObject *self, Py_ssize_t segment, void **ptrptr) {
81     PyErr_SetString(PyExc_ValueError, "writable buffers supported only with "
82                     "new-style buffer protocol.");
83     return -1;
84 }
85 
86 // Python's getsegcount interface function.
87 static Py_ssize_t
getsegcount(PyObject * self,Py_ssize_t * lenp)88 getsegcount(PyObject *self, Py_ssize_t *lenp) {
89     if (lenp)
90         *lenp = sizeof(GfVec2i);
91     return 1; // Always one contiguous segment.
92 }
93 
94 // Python's getcharbuf interface function.
95 static Py_ssize_t
getcharbuf(PyObject * self,Py_ssize_t segment,const char ** ptrptr)96 getcharbuf(PyObject *self, Py_ssize_t segment, const char **ptrptr) {
97     PyErr_SetString(PyExc_ValueError, "cannot treat binary data as text");
98     return -1;
99 }
100 #endif
101 
102 // Python's getbuffer interface function.
103 static int
getbuffer(PyObject * self,Py_buffer * view,int flags)104 getbuffer(PyObject *self, Py_buffer *view, int flags) {
105     if (view == NULL) {
106         PyErr_SetString(PyExc_ValueError, "NULL view in getbuffer");
107         return -1;
108     }
109 
110     // We don't support fortran order.
111     if ((flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) {
112         PyErr_SetString(PyExc_ValueError, "Fortran contiguity unsupported");
113         return -1;
114     }
115 
116     GfVec2i &vec = extract<GfVec2i &>(self);
117 
118     view->obj = self;
119     view->buf = static_cast<void *>(vec.data());
120     view->len = sizeof(GfVec2i);
121     view->readonly = 0;
122     view->itemsize = sizeof(int);
123     if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
124         view->format = Gf_GetPyBufferFmtFor<int>();
125     } else {
126         view->format = NULL;
127     }
128     if ((flags & PyBUF_ND) == PyBUF_ND) {
129         view->ndim = 1;
130         static Py_ssize_t shape = 2;
131         view->shape = &shape;
132     } else {
133         view->ndim = 0;
134         view->shape = NULL;
135     }
136     if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
137         static Py_ssize_t strides = sizeof(int);
138         view->strides = &strides;
139     } else {
140         view->strides = NULL;
141     }
142     view->suboffsets = NULL;
143     view->internal = NULL;
144 
145     Py_INCREF(self); // need to retain a reference to self.
146     return 0;
147 }
148 
149 // This structure serves to instantiate a PyBufferProcs instance with pointers
150 // to the right buffer protocol functions.
151 static PyBufferProcs bufferProcs = {
152 #if PY_MAJOR_VERSION == 2
153     (readbufferproc) getreadbuf,   /*bf_getreadbuffer*/
154     (writebufferproc) getwritebuf, /*bf_getwritebuffer*/
155     (segcountproc) getsegcount,    /*bf_getsegcount*/
156     (charbufferproc) getcharbuf,   /*bf_getcharbuffer*/
157 #endif
158     (getbufferproc) getbuffer,
159     (releasebufferproc) 0,
160 };
161 
162 // End python buffer protocol support.
163 ////////////////////////////////////////////////////////////////////////
164 
165 
__repr__(GfVec2i const & self)166 static string __repr__(GfVec2i const &self) {
167     string elems;
168     for (size_t i = 0; i < self.dimension; ++i)
169         elems += (i ? ", " : "") + TfPyRepr(self[i]);
170 
171     return TF_PY_REPR_PREFIX + "Vec2i(" + elems + ")";
172 }
173 
__hash__(GfVec2i const & self)174 static size_t __hash__(GfVec2i const &self) {
175     return boost::hash<GfVec2i>()(self);
176 }
177 
178 
179 
180 
181 static int
normalizeIndex(int index)182 normalizeIndex(int index) {
183     return TfPyNormalizeIndex(index, 2, true /*throw error*/);
184 }
185 
__len__(const GfVec2i & self)186 static int __len__(const GfVec2i &self) { return 2; }
187 
188 // Implements __getitem__ for a single index
__getitem__(const GfVec2i & self,int index)189 static int __getitem__(const GfVec2i &self, int index) {
190     return self[normalizeIndex(index)];
191 }
192 
193 // Implements __getitem__ for a slice
__getslice__(const GfVec2i & self,slice indices)194 static list __getslice__(const GfVec2i &self, slice indices) {
195     list result;
196 
197     const int* begin = self.data();
198     const int* end = begin + 2;
199 
200     slice::range<const int*> bounds;
201     try {
202         // This appears to be a typo in the boost headers.  The method
203         // name should be "get_indices".
204         //
205         bounds = indices.get_indicies<>(begin, end);
206     } catch (std::invalid_argument) {
207         return result;
208     }
209 
210     while (bounds.start != bounds.stop) {
211         result.append(*bounds.start);
212         bounds.start += bounds.step;
213     }
214     // Unlike STL ranges, bounds represents a *closed* interval.  This
215     // means that we must append exactly one more item at the end of
216     // the list.
217     //
218     result.append(*bounds.start);
219 
220     return result;
221 }
222 
__setitem__(GfVec2i & self,int index,int value)223 static void __setitem__(GfVec2i &self, int index, int value) {
224     self[normalizeIndex(index)] = value;
225 }
226 
227 // Handles refcounting & extraction for PySequence_GetItem.
_SequenceGetItem(PyObject * seq,Py_ssize_t i)228 static int _SequenceGetItem(PyObject *seq, Py_ssize_t i) {
229     boost::python::handle<> h(PySequence_GetItem(seq, i));
230     return extract<int>(boost::python::object(h));
231 }
232 
_SequenceCheckItem(PyObject * seq,Py_ssize_t i)233 static bool _SequenceCheckItem(PyObject *seq, Py_ssize_t i) {
234     boost::python::handle<> h(PySequence_GetItem(seq, i));
235     extract<int> e((boost::python::object(h)));
236     return e.check();
237 }
238 
__setslice__(GfVec2i & self,slice indices,object values)239 static void __setslice__(GfVec2i &self, slice indices, object values) {
240     // Verify our arguments
241     //
242     PyObject* valuesObj = values.ptr();
243 
244     if (!PySequence_Check(valuesObj)) {
245         TfPyThrowTypeError("value must be a sequence");
246     }
247 
248     int* begin = self.data();
249     int* end = begin + 2;
250 
251     Py_ssize_t sliceLength = -1;
252 
253     slice::range<int*> bounds;
254 
255     // Convince g++ that we're not using uninitialized values.
256     //
257     bounds.start = 0;
258     bounds.stop  = 0;
259     bounds.step  = 0;
260 
261     try {
262         // This appears to be a typo in the boost headers.  The method
263         // name should be "get_indices".
264         //
265         bounds = indices.get_indicies<>(begin, end);
266     } catch (std::invalid_argument) {
267         sliceLength = 0;
268     }
269 
270     // If sliceLength was not set in the exception handling code above,
271     // figure out how long it really is.
272     //
273     if (sliceLength == -1) {
274         sliceLength = ((bounds.stop - bounds.start) / bounds.step) + 1;
275     }
276 
277     if (PySequence_Length(valuesObj) != sliceLength) {
278         TfPyThrowValueError(
279             TfStringPrintf(
280                 "attempt to assign sequence of size %zd to slice of size %zd",
281                 PySequence_Length(valuesObj), sliceLength));
282     }
283 
284     // Short circuit for empty slices
285     //
286     if (sliceLength == 0) {
287         return;
288     }
289 
290     // Make sure that all items can be extracted before changing the GfVec2i.
291     //
292     for (Py_ssize_t i = 0; i < sliceLength; ++i) {
293         // This will throw a TypeError if any of the items cannot be converted.
294         _SequenceGetItem(valuesObj, i);
295     }
296 
297     for (Py_ssize_t i = 0; i < sliceLength; ++i) {
298         *bounds.start = _SequenceGetItem(valuesObj, i);
299         bounds.start += bounds.step;
300     }
301 }
302 
__contains__(const GfVec2i & self,int value)303 static bool __contains__(const GfVec2i &self, int value) {
304     for (size_t i = 0; i < 2; ++i) {
305         if (self[i] == value)
306             return true;
307     }
308     return false;
309 }
310 
311 #if PY_MAJOR_VERSION == 2
__truediv__(const GfVec2i & self,int value)312 static GfVec2i __truediv__(const GfVec2i &self, int value)
313 {
314     return self / value;
315 }
316 
__itruediv__(GfVec2i & self,int value)317 static GfVec2i __itruediv__(GfVec2i &self, int value)
318 {
319     return self /= value;
320 }
321 #endif
322 
323 template <class V>
__init__()324 static V *__init__() {
325     // Default contstructor zero-initializes from python.
326     return new V(0);
327 }
328 
329 struct FromPythonTuple {
FromPythonTuple__anon8895018e0111::FromPythonTuple330     FromPythonTuple() {
331         converter::registry::
332             push_back(&_convertible, &_construct,
333                       boost::python::type_id<GfVec2i>());
334     }
335 
336   private:
337 
_convertible__anon8895018e0111::FromPythonTuple338     static void *_convertible(PyObject *obj_ptr) {
339         // If this object is a GfVec already, disregard.
340         if (PyObject_HasAttrString(obj_ptr, "__isGfVec"))
341             return 0;
342 
343         typedef int Scalar;
344 
345         // XXX: Would like to allow general sequences, but currently clients
346         // depend on this behavior.
347         if ((PyTuple_Check(obj_ptr) || PyList_Check(obj_ptr)) &&
348             PySequence_Size(obj_ptr) == 2 &&
349             _SequenceCheckItem(obj_ptr, 0) &&
350             _SequenceCheckItem(obj_ptr, 1)) {
351             return obj_ptr;
352         }
353         return 0;
354     }
355 
_construct__anon8895018e0111::FromPythonTuple356     static void _construct(PyObject *obj_ptr, converter::
357                            rvalue_from_python_stage1_data *data) {
358         typedef int Scalar;
359         void *storage = ((converter::rvalue_from_python_storage<GfVec2i>*)data)
360 	    ->storage.bytes;
361         new (storage)
362 	    GfVec2i(
363                 _SequenceGetItem(obj_ptr, 0),
364                 _SequenceGetItem(obj_ptr, 1));
365         data->convertible = storage;
366     }
367 };
368 
369 // This adds support for python's builtin pickling library
370 // This is used by our Shake plugins which need to pickle entire classes
371 // (including code), which we don't support in pxml.
372 struct PickleSuite : boost::python::pickle_suite
373 {
getinitargs__anon8895018e0111::PickleSuite374     static boost::python::tuple getinitargs(const GfVec2i &v) {
375         return boost::python::make_tuple(v[0], v[1]);
376     }
377 };
378 
379 } // anonymous namespace
380 
wrapVec2i()381 void wrapVec2i()
382 {
383     typedef GfVec2i Vec;
384     typedef int Scalar;
385 
386     static const size_t _dimension = 2;
387     static const bool _true = true;
388 
389     def("Dot", (Scalar (*)( const Vec &, const Vec &))GfDot);
390 
391 
392     class_<GfVec2i> cls("Vec2i", no_init);
393     cls
394         .def("__init__", make_constructor(__init__<Vec>))
395 
396         // A tag indicating that this is a GfVec class, for internal use.
397         .def_readonly("__isGfVec", _true)
398 
399         .def_pickle(PickleSuite())
400 
401 
402         .def(init<Vec>())
403         .def(init<Scalar>())
404         .def(init<Scalar, Scalar>())
405 
406         .def(TfTypePythonClass())
407 
408         .def("__len__", __len__ )
409         .def("__getitem__", __getitem__ )
410         .def("__getitem__", __getslice__ )
411         .def("__setitem__", __setitem__ )
412         .def("__setitem__", __setslice__ )
413         .def("__contains__", __contains__ )
414 
415         .def_readonly("dimension", _dimension)
416 
417 
418         .def(self == self)
419         .def(self != self)
420         .def(self += self)
421         .def(self -= self)
422         .def(self *= double())
423         .def(self * double())
424         .def(double() * self)
425         .def(self /= int())
426         .def(self / int())
427         .def(-self)
428         .def(self + self)
429         .def(self - self)
430         .def(self * self)
431         .def(str(self))
432 
433 #if PY_MAJOR_VERSION == 2
434         // Needed only to support "from __future__ import division" in
435         // python 2. In python 3 builds boost::python adds this for us.
436         .def("__truediv__", __truediv__ )
437         .def("__itruediv__", __itruediv__ )
438 #endif
439 
440         .def("Axis", &Vec::Axis).staticmethod("Axis")
441 
442         .def("XAxis", &Vec::XAxis).staticmethod("XAxis")
443         .def("YAxis", &Vec::YAxis).staticmethod("YAxis")
444 
445         .def("GetDot", (Scalar (*)(const Vec &, const Vec &))GfDot)
446 
447 
448         .def("__repr__", __repr__)
449         .def("__hash__", __hash__)
450         ;
451     to_python_converter<std::vector<GfVec2i>,
452         TfPySequenceToPython<std::vector<GfVec2i> > >();
453 
454     // Install buffer protocol: set the tp_as_buffer slot to point to a
455     // structure of function pointers that implement the buffer protocol for
456     // this type, and set the type flags to indicate that this type supports the
457     // buffer protocol.
458     auto *typeObj = reinterpret_cast<PyTypeObject *>(cls.ptr());
459     typeObj->tp_as_buffer = &bufferProcs;
460     typeObj->tp_flags |= (TfPy_TPFLAGS_HAVE_NEWBUFFER |
461                           TfPy_TPFLAGS_HAVE_GETCHARBUFFER);
462 
463     // Allow appropriate tuples to be passed where Vecs are expected.
464     FromPythonTuple();
465 
466     // Allow conversion of lists of GfVec2i to std::vector<GfVec2i>
467     TfPyContainerConversions::from_python_sequence<
468         std::vector<GfVec2i>,
469         TfPyContainerConversions::variable_capacity_policy >();
470 }
471