فهرست منبع

express: Implement `copy.deepcopy()` for PointerToArray

It actually makes a unique copy of the underlying array.
rdb 3 سال پیش
والد
کامیت
e67cd74725

+ 1 - 0
doc/ReleaseNotes

@@ -71,6 +71,7 @@ Miscellaneous
 * Fix texture transforms sometimes not being flattened (#1392)
 * Fix support for `#pragma include <file.glsl>` in GLSL shaders
 * Fix `ShaderBuffer.prepare()` not doing anything
+* Implement deepcopy for PointerToArray
 * Fix bf-cbc encryption no longer working when building with OpenSSL 3.0
 * PandaNode bounds_type property was erroneously marked read-only
 * Fix warnings when copying OdeTriMeshGeom objects

+ 4 - 0
panda/src/express/pointerToArray.h

@@ -121,6 +121,8 @@ PUBLISHED:
 
   EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags));
   EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
+
+  EXTENSION(PointerToArray<Element> __deepcopy__(PyObject *memo) const);
 #endif
 
 #else  // CPPPARSER
@@ -279,6 +281,8 @@ PUBLISHED:
 
   EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
   EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
+
+  EXTENSION(ConstPointerToArray<Element> __deepcopy__(PyObject *memo) const);
 #endif
 
 #else  // CPPPARSER

+ 28 - 0
panda/src/express/pointerToArray_ext.I

@@ -510,6 +510,20 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const {
 #endif
 }
 
+/**
+ * A special Python method that is invoked by copy.deepcopy(pta).  This makes
+ * sure that there is truly a unique copy of the array.
+ */
+template<class Element>
+INLINE PointerToArray<Element> Extension<PointerToArray<Element> >::
+__deepcopy__(PyObject *memo) const {
+  PointerToArray<Element> copy;
+  if (!_this->is_null()) {
+    copy.v() = _this->v();
+  }
+  return copy;
+}
+
 /**
  * This is used to implement the buffer protocol, in order to allow efficient
  * access to the array data through a Python multiview object.
@@ -702,3 +716,17 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const {
   }
 #endif
 }
+
+/**
+ * A special Python method that is invoked by copy.deepcopy(pta).  This makes
+ * sure that there is truly a unique copy of the array.
+ */
+template<class Element>
+INLINE ConstPointerToArray<Element> Extension<ConstPointerToArray<Element> >::
+__deepcopy__(PyObject *memo) const {
+  PointerToArray<Element> copy;
+  if (!_this->is_null()) {
+    copy.v() = _this->v();
+  }
+  return copy;
+}

+ 4 - 0
panda/src/express/pointerToArray_ext.h

@@ -44,6 +44,8 @@ public:
 
   INLINE int __getbuffer__(PyObject *self, Py_buffer *view, int flags);
   INLINE void __releasebuffer__(PyObject *self, Py_buffer *view) const;
+
+  INLINE PointerToArray<Element> __deepcopy__(PyObject *memo) const;
 };
 
 template<>
@@ -81,6 +83,8 @@ public:
 
   INLINE int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
   INLINE void __releasebuffer__(PyObject *self, Py_buffer *view) const;
+
+  INLINE ConstPointerToArray<Element> __deepcopy__(PyObject *memo) const;
 };
 
 template<>

+ 60 - 0
tests/express/test_pointertoarray.py

@@ -69,3 +69,63 @@ def test_cpta_float_pickle():
         data_pta2 = loads(dumps(data_pta, proto))
         assert tuple(data_pta2) == (1.0, 2.0, 3.0)
         assert data_pta2.get_data() == data_pta.get_data()
+
+
+def test_pta_float_copy():
+    from panda3d.core import PTA_float
+    from copy import copy
+
+    null_pta = PTA_float()
+    assert copy(null_pta).is_null()
+
+    empty_pta = PTA_float([])
+    empty_pta_copy = copy(empty_pta)
+    assert not empty_pta_copy.is_null()
+    assert len(empty_pta_copy) == 0
+    assert empty_pta_copy.get_ref_count() == 2
+
+    data_pta = PTA_float([1.0, 2.0, 3.0])
+    data_pta_copy = copy(data_pta)
+    assert not data_pta_copy.is_null()
+    assert data_pta_copy.get_ref_count() == 2
+    assert tuple(data_pta_copy) == (1.0, 2.0, 3.0)
+
+
+def test_pta_float_deepcopy():
+    from panda3d.core import PTA_float
+    from copy import deepcopy
+
+    null_pta = PTA_float()
+    assert deepcopy(null_pta).is_null()
+
+    empty_pta = PTA_float([])
+    empty_pta_copy = deepcopy(empty_pta)
+    assert not empty_pta_copy.is_null()
+    assert len(empty_pta_copy) == 0
+    assert empty_pta_copy.get_ref_count() == 1
+
+    data_pta = PTA_float([1.0, 2.0, 3.0])
+    data_pta_copy = deepcopy(data_pta)
+    assert not data_pta_copy.is_null()
+    assert data_pta_copy.get_ref_count() == 1
+    assert tuple(data_pta_copy) == (1.0, 2.0, 3.0)
+
+
+def test_cpta_float_deepcopy():
+    from panda3d.core import PTA_float, CPTA_float
+    from copy import deepcopy
+
+    null_pta = CPTA_float(PTA_float())
+    assert deepcopy(null_pta).is_null()
+
+    empty_pta = CPTA_float([])
+    empty_pta_copy = deepcopy(empty_pta)
+    assert not empty_pta_copy.is_null()
+    assert len(empty_pta_copy) == 0
+    assert empty_pta_copy.get_ref_count() == 1
+
+    data_pta = CPTA_float([1.0, 2.0, 3.0])
+    data_pta_copy = deepcopy(data_pta)
+    assert not data_pta_copy.is_null()
+    assert data_pta_copy.get_ref_count() == 1
+    assert tuple(data_pta_copy) == (1.0, 2.0, 3.0)