express: Implement copy.deepcopy() for PointerToArray

It actually makes a unique copy of the underlying array.
This commit is contained in:
rdb 2022-12-19 16:19:46 +01:00
parent 0ace26a938
commit e67cd74725
5 changed files with 97 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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<>

View File

@ -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)