diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 63c292646773..54845b4955fb 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -881,7 +881,6 @@ add_library( src/strings/replace/backref_re.cu src/strings/replace/find_replace.cu src/strings/replace/multi.cu - src/strings/replace/multi_re.cu src/strings/replace/replace.cu src/strings/replace/replace_nulls.cu src/strings/replace/replace_re.cu diff --git a/cpp/include/cudf/strings/replace_re.hpp b/cpp/include/cudf/strings/replace_re.hpp index c83c65c42ab0..a4f3b098c3ed 100644 --- a/cpp/include/cudf/strings/replace_re.hpp +++ b/cpp/include/cudf/strings/replace_re.hpp @@ -49,32 +49,6 @@ std::unique_ptr replace_re( rmm::cuda_stream_view stream = cudf::get_default_stream(), rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref()); -/** - * @brief For each string, replaces any character sequence matching the given patterns - * with the corresponding string in the `replacements` column. - * - * @deprecated in 26.06. To be removed in a future release. - * - * Any null string entries return corresponding null output column entries. - * - * See the @ref md_regex "Regex Features" page for details on patterns supported by this API. - * - * @param input Strings instance for this operation - * @param patterns The regular expression patterns to search within each string - * @param replacements The strings used for replacement - * @param flags Regex flags for interpreting special characters in the patterns - * @param stream CUDA stream used for device memory operations and kernel launches - * @param mr Device memory resource used to allocate the returned column's device memory - * @return New strings column - */ -[[deprecated]] std::unique_ptr replace_re( - strings_column_view const& input, - std::vector const& patterns, - strings_column_view const& replacements, - regex_flags const flags = regex_flags::DEFAULT, - rmm::cuda_stream_view stream = cudf::get_default_stream(), - rmm::device_async_resource_ref mr = cudf::get_current_device_resource_ref()); - /** * @brief For each string, replaces any character sequence matching the given regex * using the replacement template for back-references. diff --git a/cpp/src/strings/replace/multi_re.cu b/cpp/src/strings/replace/multi_re.cu deleted file mode 100644 index b163c8b4fcf9..000000000000 --- a/cpp/src/strings/replace/multi_re.cu +++ /dev/null @@ -1,213 +0,0 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "strings/regex/regex.cuh" -#include "strings/regex/regex_program_impl.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include - -namespace cudf { -namespace strings { -namespace detail { -namespace { -// this is a [begin,end) pair of character positions when a substring is matched -using found_range = cuda::std::pair; - -/** - * @brief This functor handles replacing strings by applying the compiled regex patterns - * and inserting the corresponding new string within the matched range of characters. - */ -struct replace_multi_regex_fn { - column_device_view const d_strings; - device_span progs; // array of regex progs - found_range* d_found_ranges; // working array matched (begin,end) values - column_device_view const d_repls; // replacement strings - size_type* d_sizes{}; - char* d_chars{}; - cudf::detail::input_offsetalator d_offsets; - - __device__ void operator()(size_type idx) - { - if (d_strings.is_null(idx)) { - if (!d_chars) { d_sizes[idx] = 0; } - return; - } - - auto const number_of_patterns = static_cast(progs.size()); - - auto const d_str = d_strings.element(idx); - auto const nchars = d_str.length(); // number of characters in input string - auto nbytes = d_str.size_bytes(); // number of bytes in input string - auto in_ptr = d_str.data(); // input pointer - auto out_ptr = d_chars ? d_chars + d_offsets[idx] : nullptr; - auto itr = d_str.begin(); - auto last_pos = itr; - - found_range* d_ranges = d_found_ranges + (idx * number_of_patterns); - - // initialize the working ranges memory to -1's - thrust::fill(thrust::seq, d_ranges, d_ranges + number_of_patterns, found_range{-1, 1}); - - // process string one character at a time - while (itr.position() < nchars) { - // this minimizes the regex-find calls by only calling it for stale patterns - // -- those that have not previously matched up to this point (ch_pos) - for (size_type ptn_idx = 0; ptn_idx < number_of_patterns; ++ptn_idx) { - if (d_ranges[ptn_idx].first >= itr.position()) { // previously matched here - continue; // or later in the string - } - reprog_device prog = progs[ptn_idx]; - - auto const result = !prog.is_empty() ? prog.find(idx, d_str, itr) : cuda::std::nullopt; - d_ranges[ptn_idx] = - result ? found_range{result->first, result->second} : found_range{nchars, nchars}; - } - // all the ranges have been updated from each regex match; - // look for any that match at this character position (ch_pos) - auto const ptn_itr = - thrust::find_if(thrust::seq, - d_ranges, - d_ranges + number_of_patterns, - [ch_pos = itr.position()](auto range) { return range.first == ch_pos; }); - if (ptn_itr != d_ranges + number_of_patterns) { - // match found, compute and replace the string in the output - auto const ptn_idx = static_cast(cuda::std::distance(d_ranges, ptn_itr)); - - auto d_repl = d_repls.size() > 1 ? d_repls.element(ptn_idx) - : d_repls.element(0); - - auto const d_range = d_ranges[ptn_idx]; - auto const [start_pos, end_pos] = - match_positions_to_bytes({d_range.first, d_range.second}, d_str, last_pos); - nbytes += d_repl.size_bytes() - (end_pos - start_pos); - if (out_ptr) { // copy unmodified content plus new replacement string - out_ptr = copy_and_increment( - out_ptr, in_ptr + last_pos.byte_offset(), start_pos - last_pos.byte_offset()); - out_ptr = copy_string(out_ptr, d_repl); - } - last_pos += (d_range.second - last_pos.position()); - itr = last_pos - 1; - } - ++itr; - } - if (out_ptr) { // copy the remainder - thrust::copy_n(thrust::seq, - in_ptr + last_pos.byte_offset(), - d_str.size_bytes() - last_pos.byte_offset(), - out_ptr); - } else { - d_sizes[idx] = nbytes; - } - } -}; - -} // namespace - -std::unique_ptr replace_re(strings_column_view const& input, - std::vector const& patterns, - strings_column_view const& replacements, - regex_flags const flags, - rmm::cuda_stream_view stream, - rmm::device_async_resource_ref mr) -{ - if (input.is_empty()) { return make_empty_column(type_id::STRING); } - if (patterns.empty()) { // if no patterns; just return a copy - return std::make_unique(input.parent(), stream, mr); - } - - CUDF_EXPECTS(!replacements.has_nulls(), "Parameter replacements must not have any nulls"); - - // compile regexes into device objects - auto h_progs = std::vector>>( - patterns.size()); - std::transform( - patterns.begin(), patterns.end(), h_progs.begin(), [flags, stream](auto const& ptn) { - auto h_prog = regex_program::create(ptn, flags, capture_groups::NON_CAPTURE); - return regex_device_builder::create_prog_device(*h_prog, stream); - }); - - // get the longest regex for the dispatcher - auto const max_prog = - std::max_element(h_progs.begin(), h_progs.end(), [](auto const& lhs, auto const& rhs) { - return lhs->insts_counts() < rhs->insts_counts(); - }); - - auto d_max_prog = **max_prog; - auto const max_insts = d_max_prog.insts_counts(); - auto const buffer_size = d_max_prog.working_memory_size(input.size()); - auto d_buffer = rmm::device_buffer(buffer_size, stream); - - // copy all the reprog_device instances to a device memory array - auto progs = cudf::detail::make_empty_host_vector(h_progs.size(), stream); - std::transform(h_progs.begin(), - h_progs.end(), - std::back_inserter(progs), - [d_buffer = d_buffer.data(), size = input.size(), max_insts](auto& prog) { - prog->set_working_memory(d_buffer, size, max_insts); - return *prog; - }); - auto d_progs = - cudf::detail::make_device_uvector(progs, stream, cudf::get_current_device_resource_ref()); - - auto const d_strings = column_device_view::create(input.parent(), stream); - auto const d_repls = column_device_view::create(replacements.parent(), stream); - - auto found_ranges = rmm::device_uvector(d_progs.size() * input.size(), stream); - - auto [offsets_column, chars] = make_strings_children( - replace_multi_regex_fn{*d_strings, d_progs, found_ranges.data(), *d_repls}, - input.size(), - stream, - mr); - - stream.synchronize(); - - return make_strings_column(input.size(), - std::move(offsets_column), - chars.release(), - input.null_count(), - cudf::detail::copy_bitmask(input.parent(), stream, mr)); -} - -} // namespace detail - -// external API - -std::unique_ptr replace_re(strings_column_view const& strings, - std::vector const& patterns, - strings_column_view const& replacements, - regex_flags const flags, - rmm::cuda_stream_view stream, - rmm::device_async_resource_ref mr) -{ - CUDF_FUNC_RANGE(); - return detail::replace_re(strings, patterns, replacements, flags, stream, mr); -} - -} // namespace strings -} // namespace cudf diff --git a/java/src/main/java/ai/rapids/cudf/ColumnView.java b/java/src/main/java/ai/rapids/cudf/ColumnView.java index b6f391838487..95e561f2faae 100644 --- a/java/src/main/java/ai/rapids/cudf/ColumnView.java +++ b/java/src/main/java/ai/rapids/cudf/ColumnView.java @@ -3505,19 +3505,6 @@ public final ColumnVector replaceRegex(RegexProgram regexProg, Scalar repl, int regexProg.capture().nativeId, repl.getScalarHandle(), maxRepl)); } - /** - * For each string, replaces any character sequence matching any of the regular expression - * patterns with the corresponding replacement strings. - * - * @param patterns The regular expression patterns to search within each string. - * @param repls The string scalars to replace for each corresponding pattern match. - * @return A new column vector containing the string results. - */ - public final ColumnVector replaceMultiRegex(String[] patterns, ColumnView repls) { - return new ColumnVector(replaceMultiRegex(getNativeView(), patterns, - repls.getNativeView())); - } - /** * For each string, replaces any character sequence matching the given pattern * using the replace template for back-references. @@ -4806,16 +4793,6 @@ private static native long substringColumn(long columnView, long startColumn, lo private static native long replaceRegex(long columnView, String pattern, int flags, int capture, long repl, long maxRepl) throws CudfException; - /** - * Native method for multiple instance regular expression replacement. - * @param columnView native handle of the cudf::column_view being operated on. - * @param patterns native handle of the cudf::column_view containing the regex patterns. - * @param repls The replacement template for creating the output string. - * @return native handle of the resulting cudf column containing the string results. - */ - private static native long replaceMultiRegex(long columnView, String[] patterns, - long repls) throws CudfException; - /** * Native method for replacing any character sequence matching the given regex program * pattern using the replace template for back-references. diff --git a/java/src/main/native/src/ColumnViewJni.cpp b/java/src/main/native/src/ColumnViewJni.cpp index faeb7f2a14ea..76b69f978274 100644 --- a/java/src/main/native/src/ColumnViewJni.cpp +++ b/java/src/main/native/src/ColumnViewJni.cpp @@ -2013,25 +2013,6 @@ JNIEXPORT jlong JNICALL Java_ai_rapids_cudf_ColumnView_replaceRegex(JNIEnv* env, JNI_CATCH(env, 0); } -JNIEXPORT jlong JNICALL Java_ai_rapids_cudf_ColumnView_replaceMultiRegex( - JNIEnv* env, jclass, jlong j_column_view, jobjectArray j_patterns, jlong j_repls) -{ - JNI_NULL_CHECK(env, j_column_view, "column is null", 0); - JNI_NULL_CHECK(env, j_patterns, "patterns is null", 0); - JNI_NULL_CHECK(env, j_repls, "repls is null", 0); - JNI_TRY - { - cudf::jni::auto_set_device(env); - auto cv = reinterpret_cast(j_column_view); - cudf::strings_column_view scv(*cv); - cudf::jni::native_jstringArray patterns(env, j_patterns); - auto repl_cv = reinterpret_cast(j_repls); - cudf::strings_column_view repl_scv(*repl_cv); - return release_as_jlong(cudf::strings::replace_re(scv, patterns.as_cpp_vector(), repl_scv)); - } - JNI_CATCH(env, 0); -} - JNIEXPORT jlong JNICALL Java_ai_rapids_cudf_ColumnView_stringReplaceWithBackrefs(JNIEnv* env, jclass, diff --git a/java/src/test/java/ai/rapids/cudf/ColumnVectorTest.java b/java/src/test/java/ai/rapids/cudf/ColumnVectorTest.java index 4830f1b49b5e..406384f5490e 100644 --- a/java/src/test/java/ai/rapids/cudf/ColumnVectorTest.java +++ b/java/src/test/java/ai/rapids/cudf/ColumnVectorTest.java @@ -5268,18 +5268,6 @@ void testReplaceRegex() { } } - @Test - void testReplaceMultiRegex() { - try (ColumnVector v = - ColumnVector.fromStrings("title and Title with title", "nothing", null, "Title"); - ColumnVector repls = ColumnVector.fromStrings("Repl", "**"); - ColumnVector actual = v.replaceMultiRegex(new String[] { "[tT]itle", "and|th" }, repls); - ColumnVector expected = - ColumnVector.fromStrings("Repl ** Repl wi** Repl", "no**ing", null, "Repl")) { - assertColumnsAreEqual(expected, actual); - } - } - @Test void testStringReplaceWithBackrefs() { diff --git a/python/cudf/cudf/core/accessors/string.py b/python/cudf/cudf/core/accessors/string.py index 01ca1b37abf7..03f704510ed5 100644 --- a/python/cudf/cudf/core/accessors/string.py +++ b/python/cudf/cudf/core/accessors/string.py @@ -975,6 +975,7 @@ def replace( Number of replacements to make from the start. regex : bool, default True If True, assumes the pattern is a regular expression. + Raises ValueError if pat is not a string. If False, treats the pattern as a literal string. Returns @@ -1033,14 +1034,8 @@ def replace( ) if regex: - warnings.warn( - "regex support for multiple replace patterns " - "will be removed in a future version.", - FutureWarning, - ) - result = self._column.replace_re( - list(pat), - as_column(repl, dtype=DEFAULT_STRING_DTYPE), # type: ignore[arg-type] + raise ValueError( + "multiple pattern replace with regex=True is not supported" ) else: result = self._column.replace_multiple( diff --git a/python/cudf/cudf/core/column/string.py b/python/cudf/cudf/core/column/string.py index fd768b888bfd..2813c8ec81bd 100644 --- a/python/cudf/cudf/core/column/string.py +++ b/python/cudf/cudf/core/column/string.py @@ -1523,34 +1523,22 @@ def repeat_strings(self, repeats: int | ColumnBase) -> Self: def replace_re( self, - pattern: list[str] | str, - replacement: Self | str, + pattern: str, + replacement: str, max_replace_count: int = -1, ) -> Self: with self.access(mode="read", scope="internal"): - if isinstance(pattern, list) and isinstance( - replacement, type(self) - ): - plc_column = plc.strings.replace_re.replace_re( - self.plc_column, + plc_column = plc.strings.replace_re.replace_re( + self.plc_column, + plc.strings.regex_program.RegexProgram.create( pattern, - replacement.plc_column, - max_replace_count, - ) - elif isinstance(pattern, str) and isinstance(replacement, str): - plc_column = plc.strings.replace_re.replace_re( - self.plc_column, - plc.strings.regex_program.RegexProgram.create( - pattern, - plc.strings.regex_flags.RegexFlags.DEFAULT, - ), - plc.Scalar.from_py( - replacement, dtype=plc.DataType(plc.TypeId.STRING) - ), - max_replace_count, - ) - else: - raise ValueError("Invalid pattern and replacement types") + plc.strings.regex_flags.RegexFlags.DEFAULT, + ), + plc.Scalar.from_py( + replacement, dtype=plc.DataType(plc.TypeId.STRING) + ), + max_replace_count, + ) return cast( Self, ColumnBase.create(plc_column, self.dtype), diff --git a/python/pylibcudf/pylibcudf/libcudf/strings/replace_re.pxd b/python/pylibcudf/pylibcudf/libcudf/strings/replace_re.pxd index d3e958841abb..45e641bbb44f 100644 --- a/python/pylibcudf/pylibcudf/libcudf/strings/replace_re.pxd +++ b/python/pylibcudf/pylibcudf/libcudf/strings/replace_re.pxd @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 from libcpp.memory cimport unique_ptr from libcpp.string cimport string -from libcpp.vector cimport vector from pylibcudf.exception_handler cimport libcudf_exception_handler from pylibcudf.libcudf.column.column cimport column from pylibcudf.libcudf.column.column_view cimport column_view @@ -25,14 +24,6 @@ cdef extern from "cudf/strings/replace_re.hpp" namespace "cudf::strings" nogil: cudaStream_t stream, device_async_resource_ref mr) except +libcudf_exception_handler - cdef unique_ptr[column] replace_re( - column_view input, - vector[string] patterns, - column_view replacements, - regex_flags flags, - cudaStream_t stream, - device_async_resource_ref mr) except +libcudf_exception_handler - cdef unique_ptr[column] replace_with_backrefs( column_view input, regex_program prog, diff --git a/python/pylibcudf/pylibcudf/strings/replace_re.pxd b/python/pylibcudf/pylibcudf/strings/replace_re.pxd index 0d360f8de6f7..042fb248257e 100644 --- a/python/pylibcudf/pylibcudf/strings/replace_re.pxd +++ b/python/pylibcudf/pylibcudf/strings/replace_re.pxd @@ -8,21 +8,12 @@ from pylibcudf.strings.regex_flags cimport regex_flags from pylibcudf.strings.regex_program cimport RegexProgram from rmm.pylibrmm.memory_resource cimport DeviceMemoryResource -ctypedef fused Replacement: - Column - Scalar - -ctypedef fused Patterns: - RegexProgram - list - cpdef Column replace_re( Column input, - Patterns patterns, - Replacement replacement=*, + RegexProgram patterns, + Scalar replacement=*, size_type max_replace_count=*, - regex_flags flags=*, object stream = *, DeviceMemoryResource mr=* ) diff --git a/python/pylibcudf/pylibcudf/strings/replace_re.pyi b/python/pylibcudf/pylibcudf/strings/replace_re.pyi index 649709283234..6b79b066ee6e 100644 --- a/python/pylibcudf/pylibcudf/strings/replace_re.pyi +++ b/python/pylibcudf/pylibcudf/strings/replace_re.pyi @@ -1,17 +1,13 @@ # SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION. # SPDX-License-Identifier: Apache-2.0 -from typing import overload - from rmm.pylibrmm.memory_resource import DeviceMemoryResource from pylibcudf.column import Column from pylibcudf.scalar import Scalar -from pylibcudf.strings.regex_flags import RegexFlags from pylibcudf.strings.regex_program import RegexProgram from pylibcudf.utils import CudaStreamLike -@overload def replace_re( input: Column, pattern: RegexProgram, @@ -20,16 +16,6 @@ def replace_re( stream: CudaStreamLike | None = None, mr: DeviceMemoryResource | None = None, ) -> Column: ... -@overload -def replace_re( - input: Column, - patterns: list[str], - replacement: Column, - max_replace_count: int = -1, - flags: RegexFlags = RegexFlags.DEFAULT, - stream: CudaStreamLike | None = None, - mr: DeviceMemoryResource | None = None, -) -> Column: ... def replace_with_backrefs( input: Column, prog: RegexProgram, diff --git a/python/pylibcudf/pylibcudf/strings/replace_re.pyx b/python/pylibcudf/pylibcudf/strings/replace_re.pyx index 60e9c4c16660..2b266eb3eac9 100644 --- a/python/pylibcudf/pylibcudf/strings/replace_re.pyx +++ b/python/pylibcudf/pylibcudf/strings/replace_re.pyx @@ -4,7 +4,6 @@ from cython.operator cimport dereference from libcpp.memory cimport unique_ptr from libcpp.string cimport string from libcpp.utility cimport move -from libcpp.vector cimport vector from pylibcudf.column cimport Column from pylibcudf.libcudf.column.column cimport column from pylibcudf.libcudf.scalar.scalar cimport string_scalar @@ -14,7 +13,6 @@ from pylibcudf.libcudf.scalar.scalar_factories cimport ( from pylibcudf.libcudf.strings cimport replace_re as cpp_replace_re from pylibcudf.libcudf.types cimport size_type from pylibcudf.scalar cimport Scalar -from pylibcudf.strings.regex_flags cimport regex_flags from pylibcudf.strings.regex_program cimport RegexProgram from pylibcudf.utils cimport _get_stream, _get_memory_resource from rmm.pylibrmm.memory_resource cimport DeviceMemoryResource @@ -25,10 +23,9 @@ __all__ = ["replace_re", "replace_with_backrefs"] cpdef Column replace_re( Column input, - Patterns patterns, - Replacement replacement=None, + RegexProgram pattern, + Scalar replacement=None, size_type max_replace_count=-1, - regex_flags flags=regex_flags.DEFAULT, object stream=None, DeviceMemoryResource mr=None, ): @@ -42,21 +39,14 @@ cpdef Column replace_re( ---------- input : Column Strings instance for this operation. - patterns: RegexProgram or list[str] - If RegexProgram, the regex to match to each string. - If list[str], a list of regex strings to search within each string. - replacement : Scalar or Column - If Scalar, the string used to replace the matched sequence in each string. - ``patterns`` must be a RegexProgram. - If Column, the strings used for replacement. - ``patterns`` must be a list[str]. + pattern: RegexProgram + The regex to match to each string and replace. + replacement : Scalar + The string used to replace the matched sequence in each string. max_replace_count : int The maximum number of times to replace the matched pattern - within each string. ``patterns`` must be a RegexProgram. + within each string. Default replaces every substring that is matched. - flags : RegexFlags - Regex flags for interpreting special characters in the patterns. - ``patterns`` must be a list[str] Returns ------- @@ -64,49 +54,26 @@ cpdef Column replace_re( New strings column """ cdef unique_ptr[column] c_result - cdef vector[string] c_patterns cdef Stream _stream = _get_stream(stream) cdef cudaStream_t _cs = _stream.view().value() mr = _get_memory_resource(mr) - if Patterns is RegexProgram and Replacement is Scalar: - if replacement is None: - replacement = Scalar.from_libcudf( - cpp_make_string_scalar("".encode(), _stream.view().value(), mr.get_mr()) - ) - with nogil: - c_result = move( - cpp_replace_re.replace_re( - input.view(), - patterns.c_obj.get()[0], - dereference((replacement.get())), - max_replace_count, - _cs, - mr.get_mr() - ) - ) - - return Column.from_libcudf(move(c_result), _stream, mr) - elif Patterns is list and Replacement is Column: - c_patterns.reserve(len(patterns)) - for pattern in patterns: - c_patterns.push_back(pattern.encode()) - - with nogil: - c_result = move( - cpp_replace_re.replace_re( - input.view(), - c_patterns, - replacement.view(), - flags, - _cs, - mr.get_mr() - ) + if replacement is None: + replacement = Scalar.from_libcudf( + cpp_make_string_scalar("".encode(), _stream.view().value(), mr.get_mr()) + ) + with nogil: + c_result = move( + cpp_replace_re.replace_re( + input.view(), + pattern.c_obj.get()[0], + dereference((replacement.get())), + max_replace_count, + _cs, + mr.get_mr() ) - - return Column.from_libcudf(move(c_result), _stream, mr) - else: - raise TypeError("Must pass either a RegexProgram and a Scalar or a list") + ) + return Column.from_libcudf(move(c_result), _stream, mr) cpdef Column replace_with_backrefs( diff --git a/python/pylibcudf/tests/test_string_replace_re.py b/python/pylibcudf/tests/test_string_replace_re.py index ccc3b5087540..798c95bb7ce7 100644 --- a/python/pylibcudf/tests/test_string_replace_re.py +++ b/python/pylibcudf/tests/test_string_replace_re.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION. +# SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION. # SPDX-License-Identifier: Apache-2.0 import pyarrow as pa @@ -33,33 +33,6 @@ def test_replace_re_regex_program_scalar(max_replace_count): assert_column_eq(expect, got) -@pytest.mark.parametrize( - "flags", - [ - plc.strings.regex_flags.RegexFlags.DEFAULT, - plc.strings.regex_flags.RegexFlags.DOTALL, - ], -) -def test_replace_re_list_str_columns(flags): - arr = pa.array(["foo", "fuz", None]) - pats = ["oo", "uz"] - repls = ["a", "b"] - got = plc.strings.replace_re.replace_re( - plc.Column.from_arrow(arr), - pats, - plc.Column.from_arrow(pa.array(repls)), - flags=flags, - ) - expect = arr - for pat, repl in zip(pats, repls, strict=True): - expect = pc.replace_substring_regex( - expect, - pat, - repl, - ) - assert_column_eq(expect, got) - - def test_replace_with_backrefs(): arr = pa.array(["Z756", None]) got = plc.strings.replace_re.replace_with_backrefs(