diff --git a/sklearn/tree/_tree.pyx b/sklearn/tree/_tree.pyx index 72e98b33b847f..3176d9c1a7abf 100644 --- a/sklearn/tree/_tree.pyx +++ b/sklearn/tree/_tree.pyx @@ -708,11 +708,9 @@ cdef class Tree: if self._resize_c(self.capacity) != 0: raise MemoryError("resizing tree to %d" % self.capacity) - cdef Node[::1] node_memory_view = node_ndarray - cdef DOUBLE_t[:, :, ::1] value_memory_view = value_ndarray - nodes = memcpy(self.nodes, &node_memory_view[0], + nodes = memcpy(self.nodes, cnp.PyArray_DATA(node_ndarray), self.capacity * sizeof(Node)) - value = memcpy(self.value, &value_memory_view[0, 0, 0], + value = memcpy(self.value, cnp.PyArray_DATA(value_ndarray), self.capacity * self.value_stride * sizeof(double)) cdef int _resize(self, SIZE_t capacity) nogil except -1: diff --git a/sklearn/tree/tests/test_tree.py b/sklearn/tree/tests/test_tree.py index 715101a72219a..9b1a29f02ead7 100644 --- a/sklearn/tree/tests/test_tree.py +++ b/sklearn/tree/tests/test_tree.py @@ -2406,3 +2406,22 @@ def test_splitter_serializable(Splitter): splitter_back = pickle.loads(splitter_serialize) assert splitter_back.max_features == max_features assert isinstance(splitter_back, Splitter) + + +def test_tree_deserialization_from_read_only_buffer(tmpdir): + """Check that Trees can be deserialized with read only buffers. + + Non-regression test for gh-25584. + """ + pickle_path = str(tmpdir.join("clf.joblib")) + clf = DecisionTreeClassifier(random_state=0) + clf.fit(X_small, y_small) + + joblib.dump(clf, pickle_path) + loaded_clf = joblib.load(pickle_path, mmap_mode="r") + + assert_tree_equal( + loaded_clf.tree_, + clf.tree_, + "The trees of the original and loaded classifiers are not equal.", + )