git: ac1b668fc0c0 - 2024Q3 - devel/py-Levenshtein: fix build with libc++ 19

From: Dimitry Andric <dim_at_FreeBSD.org>
Date: Sat, 05 Oct 2024 13:26:07 UTC
The branch 2024Q3 has been updated by dim:

URL: https://cgit.FreeBSD.org/ports/commit/?id=ac1b668fc0c031a9e736a810b5b20665d7ca46c8

commit ac1b668fc0c031a9e736a810b5b20665d7ca46c8
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2024-09-16 12:11:44 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2024-10-05 13:25:53 +0000

    devel/py-Levenshtein: fix build with libc++ 19
    
    As noted in the libc++ 19 release notes [1], std::char_traits<> is now
    only provided for char, char8_t, char16_t, char32_t and wchar_t, and any
    instantiation for other types will fail.
    
    This causes ports using devel/py-Levenshtein to fail to compile with
    clang 19 and libc++ 19, resulting in errors similar to:
    
      /usr/include/c++/v1/string:820:42: error: implicit instantiation of undefined template 'std::char_traits<unsigned int>'
        820 |   static_assert(is_same<_CharT, typename traits_type::char_type>::value,
            |                                          ^
      /wrkdirs/usr/ports/devel/py-Levenshtein/work-py311/Levenshtein-0.22.0/src/Levenshtein/Levenshtein-c/_levenshtein.hpp:144:43: note: in instantiation of template class 'std::basic_string<unsigned int>' requested here
        144 | static inline std::basic_string<uint32_t> lev_greedy_median(const std::vector<RF_String>& strings,
            |                                           ^
      /usr/include/c++/v1/__fwd/string.h:23:29: note: template is declared here
         23 | struct _LIBCPP_TEMPLATE_VIS char_traits;
            |                             ^
    
    Unfortunately py-Levenshtein and its embedded copy of rapidfuzz-cpp make
    heavy use of the no-longer-existing `std::basic_string<uint8_t>`, so I
    had to do quite a lots of search and replace operations, replacing these
    with equivalent `std::vector` types.
    
    This is similar to the fixes for devel/rapidfuzz-cpp in bug 281193, and
    for devel/py-rapidfuzz in bug 281194.
    
    [1] https://libcxx.llvm.org/ReleaseNotes/19.html#deprecations-and-removals
    
    PR:             281534
    Approved by:    maintainer timeout (2 weeks)
    MFH:            2024Q3
    
    (cherry picked from commit 849cc48702b5e5f5e4a7931a6acd9f87c3e40893)
---
 ...-cpp_rapidfuzz_details_SplittedSentenceView.hpp |  36 ++++++++
 ...tch-extern_rapidfuzz-cpp_rapidfuzz_distance.hpp |  53 +++++++++++
 ...z-cpp_rapidfuzz_distance_DamerauLevenshtein.hpp |  11 +++
 ...rn_rapidfuzz-cpp_rapidfuzz_distance_Hamming.hpp |  11 +++
 ...xtern_rapidfuzz-cpp_rapidfuzz_distance_Jaro.hpp |  11 +++
 ...apidfuzz-cpp_rapidfuzz_distance_JaroWinkler.hpp |  11 +++
 ...ern_rapidfuzz-cpp_rapidfuzz_distance_LCSseq.hpp |  11 +++
 ...apidfuzz-cpp_rapidfuzz_distance_Levenshtein.hpp |  11 +++
 ...extern_rapidfuzz-cpp_rapidfuzz_distance_OSA.hpp |  11 +++
 ...rn_rapidfuzz-cpp_rapidfuzz_distance_Postfix.hpp |  11 +++
 ...ern_rapidfuzz-cpp_rapidfuzz_distance_Prefix.hpp |  11 +++
 .../patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.hpp  | 100 +++++++++++++++++++++
 .../patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.impl |  20 +++++
 ...src_Levenshtein_Levenshtein-c___levenshtein.cpp |  16 ++++
 ...src_Levenshtein_Levenshtein-c___levenshtein.hpp |  69 ++++++++++++++
 .../patch-src_Levenshtein_levenshtein__cpp.cxx     |  74 +++++++++++++++
 .../patch-src_Levenshtein_levenshtein__cpp.pyx     |  30 +++++++
 17 files changed, 497 insertions(+)

diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_details_SplittedSentenceView.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_details_SplittedSentenceView.hpp
new file mode 100644
index 000000000000..546673980790
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_details_SplittedSentenceView.hpp
@@ -0,0 +1,36 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/details/SplittedSentenceView.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/details/SplittedSentenceView.hpp
+@@ -34,7 +34,7 @@ class SplittedSentenceView { (public)
+         return m_sentence.size();
+     }
+ 
+-    std::basic_string<CharT> join() const;
++    std::vector<CharT> join() const;
+ 
+     const RangeVec<InputIt>& words() const
+     {
+@@ -68,19 +68,19 @@ template <typename InputIt>
+ }
+ 
+ template <typename InputIt>
+-auto SplittedSentenceView<InputIt>::join() const -> std::basic_string<CharT>
++auto SplittedSentenceView<InputIt>::join() const -> std::vector<CharT>
+ {
+     if (m_sentence.empty()) {
+-        return std::basic_string<CharT>();
++        return std::vector<CharT>();
+     }
+ 
+     auto sentence_iter = m_sentence.begin();
+-    std::basic_string<CharT> joined(sentence_iter->begin(), sentence_iter->end());
+-    const std::basic_string<CharT> whitespace{0x20};
++    std::vector<CharT> joined(sentence_iter->begin(), sentence_iter->end());
++    const std::vector<CharT> whitespace{0x20};
+     ++sentence_iter;
+     for (; sentence_iter != m_sentence.end(); ++sentence_iter) {
+         joined.append(whitespace)
+-            .append(std::basic_string<CharT>(sentence_iter->begin(), sentence_iter->end()));
++            .append(std::vector<CharT>(sentence_iter->begin(), sentence_iter->end()));
+     }
+     return joined;
+ }
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance.hpp
new file mode 100644
index 000000000000..602c5e34b65e
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance.hpp
@@ -0,0 +1,53 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance.hpp
+@@ -16,13 +16,13 @@ template <typename CharT, typename InputIt1, typename 
+ namespace rapidfuzz {
+ 
+ template <typename CharT, typename InputIt1, typename InputIt2>
+-std::basic_string<CharT> editops_apply(const Editops& ops, InputIt1 first1, InputIt1 last1, InputIt2 first2,
+-                                       InputIt2 last2)
++std::vector<CharT> editops_apply(const Editops& ops, InputIt1 first1, InputIt1 last1, InputIt2 first2,
++                                 InputIt2 last2)
+ {
+     auto len1 = static_cast<size_t>(std::distance(first1, last1));
+     auto len2 = static_cast<size_t>(std::distance(first2, last2));
+ 
+-    std::basic_string<CharT> res_str;
++    std::vector<CharT> res_str;
+     res_str.resize(len1 + len2);
+     size_t src_pos = 0;
+     size_t dest_pos = 0;
+@@ -62,20 +62,20 @@ template <typename CharT, typename Sentence1, typename
+ }
+ 
+ template <typename CharT, typename Sentence1, typename Sentence2>
+-std::basic_string<CharT> editops_apply(const Editops& ops, const Sentence1& s1, const Sentence2& s2)
++std::vector<CharT> editops_apply(const Editops& ops, const Sentence1& s1, const Sentence2& s2)
+ {
+     return editops_apply<CharT>(ops, detail::to_begin(s1), detail::to_end(s1), detail::to_begin(s2),
+                                 detail::to_end(s2));
+ }
+ 
+ template <typename CharT, typename InputIt1, typename InputIt2>
+-std::basic_string<CharT> opcodes_apply(const Opcodes& ops, InputIt1 first1, InputIt1 last1, InputIt2 first2,
+-                                       InputIt2 last2)
++std::vector<CharT> opcodes_apply(const Opcodes& ops, InputIt1 first1, InputIt1 last1, InputIt2 first2,
++                                 InputIt2 last2)
+ {
+     auto len1 = static_cast<size_t>(std::distance(first1, last1));
+     auto len2 = static_cast<size_t>(std::distance(first2, last2));
+ 
+-    std::basic_string<CharT> res_str;
++    std::vector<CharT> res_str;
+     res_str.resize(len1 + len2);
+     size_t dest_pos = 0;
+ 
+@@ -101,7 +101,7 @@ template <typename CharT, typename Sentence1, typename
+ }
+ 
+ template <typename CharT, typename Sentence1, typename Sentence2>
+-std::basic_string<CharT> opcodes_apply(const Opcodes& ops, const Sentence1& s1, const Sentence2& s2)
++std::vector<CharT> opcodes_apply(const Opcodes& ops, const Sentence1& s1, const Sentence2& s2)
+ {
+     return opcodes_apply<CharT>(ops, detail::to_begin(s1), detail::to_end(s1), detail::to_begin(s2),
+                                 detail::to_end(s2));
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_DamerauLevenshtein.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_DamerauLevenshtein.hpp
new file mode 100644
index 000000000000..95b23aadc2c2
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_DamerauLevenshtein.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/DamerauLevenshtein.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/DamerauLevenshtein.hpp
+@@ -140,7 +140,7 @@ struct CachedDamerauLevenshtein : public detail::Cache
+         return damerau_levenshtein_distance(s1, s2, score_cutoff);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+ };
+ 
+ template <typename Sentence1>
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Hamming.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Hamming.hpp
new file mode 100644
index 000000000000..7c225ec047fa
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Hamming.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/Hamming.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/Hamming.hpp
+@@ -159,7 +159,7 @@ struct CachedHamming : public detail::CachedDistanceBa
+         return detail::Hamming::distance(s1, s2, pad, score_cutoff, score_hint);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     bool pad;
+ };
+ 
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Jaro.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Jaro.hpp
new file mode 100644
index 000000000000..d6ba8bc5a57e
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Jaro.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/Jaro.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/Jaro.hpp
+@@ -88,7 +88,7 @@ struct CachedJaro : public detail::CachedSimilarityBas
+         return detail::jaro_similarity(PM, detail::Range(s1), s2, score_cutoff);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     detail::BlockPatternMatchVector PM;
+ };
+ 
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_JaroWinkler.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_JaroWinkler.hpp
new file mode 100644
index 000000000000..a20d6b3579f5
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_JaroWinkler.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/JaroWinkler.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/JaroWinkler.hpp
+@@ -103,7 +103,7 @@ struct CachedJaroWinkler : public detail::CachedSimila
+     }
+ 
+     double prefix_weight;
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     detail::BlockPatternMatchVector PM;
+ };
+ 
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_LCSseq.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_LCSseq.hpp
new file mode 100644
index 000000000000..0aa3b4472549
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_LCSseq.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/LCSseq.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/LCSseq.hpp
+@@ -224,7 +224,7 @@ struct CachedLCSseq (private)
+         return detail::lcs_seq_similarity(PM, detail::Range(s1), s2, score_cutoff);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     detail::BlockPatternMatchVector PM;
+ };
+ 
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Levenshtein.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Levenshtein.hpp
new file mode 100644
index 000000000000..058fbc79a5e0
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Levenshtein.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/Levenshtein.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/Levenshtein.hpp
+@@ -476,7 +476,7 @@ struct CachedLevenshtein : public detail::CachedDistan
+         return detail::generalized_levenshtein_distance(detail::Range(s1), s2, weights, score_cutoff);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     detail::BlockPatternMatchVector PM;
+     LevenshteinWeightTable weights;
+ };
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_OSA.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_OSA.hpp
new file mode 100644
index 000000000000..55a42cf4a3ec
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_OSA.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/OSA.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/OSA.hpp
+@@ -267,7 +267,7 @@ struct CachedOSA (private)
+         return (res <= score_cutoff) ? res : score_cutoff + 1;
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     detail::BlockPatternMatchVector PM;
+ };
+ 
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Postfix.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Postfix.hpp
new file mode 100644
index 000000000000..65b02611d17d
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Postfix.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/Postfix.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/Postfix.hpp
+@@ -91,7 +91,7 @@ struct CachedPostfix : public detail::CachedSimilarity
+         return detail::Postfix::similarity(s1, s2, score_cutoff, score_hint);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+ };
+ 
+ template <typename Sentence1>
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Prefix.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Prefix.hpp
new file mode 100644
index 000000000000..feb0c3bdb25f
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_distance_Prefix.hpp
@@ -0,0 +1,11 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/distance/Prefix.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/distance/Prefix.hpp
+@@ -91,7 +91,7 @@ struct CachedPrefix : public detail::CachedSimilarityB
+         return detail::Prefix::similarity(s1, s2, score_cutoff, score_cutoff);
+     }
+ 
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+ };
+ 
+ template <typename Sentence1>
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.hpp b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.hpp
new file mode 100644
index 000000000000..51653b042b35
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.hpp
@@ -0,0 +1,100 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/fuzz.hpp.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/fuzz.hpp
+@@ -186,7 +186,7 @@ struct CachedPartialRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     rapidfuzz::detail::CharSet<CharT1> s1_char_set;
+     CachedRatio<CharT1> cached_ratio;
+ };
+@@ -296,7 +296,7 @@ struct CachedTokenSortRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1_sorted;
++    std::vector<CharT1> s1_sorted;
+     CachedRatio<CharT1> cached_ratio;
+ };
+ 
+@@ -354,7 +354,7 @@ struct CachedPartialTokenSortRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1_sorted;
++    std::vector<CharT1> s1_sorted;
+     CachedPartialRatio<CharT1> cached_partial_ratio;
+ };
+ 
+@@ -422,8 +422,8 @@ struct CachedTokenSetRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1;
+-    detail::SplittedSentenceView<typename std::basic_string<CharT1>::iterator> tokens_s1;
++    std::vector<CharT1> s1;
++    detail::SplittedSentenceView<typename std::vector<CharT1>::iterator> tokens_s1;
+ };
+ 
+ template <typename Sentence1>
+@@ -479,8 +479,8 @@ struct CachedPartialTokenSetRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1;
+-    detail::SplittedSentenceView<typename std::basic_string<CharT1>::iterator> tokens_s1;
++    std::vector<CharT1> s1;
++    detail::SplittedSentenceView<typename std::vector<CharT1>::iterator> tokens_s1;
+ };
+ 
+ template <typename Sentence1>
+@@ -539,9 +539,9 @@ struct CachedTokenRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1;
+-    detail::SplittedSentenceView<typename std::basic_string<CharT1>::iterator> s1_tokens;
+-    std::basic_string<CharT1> s1_sorted;
++    std::vector<CharT1> s1;
++    detail::SplittedSentenceView<typename std::vector<CharT1>::iterator> s1_tokens;
++    std::vector<CharT1> s1_sorted;
+     CachedRatio<CharT1> cached_ratio_s1_sorted;
+ };
+ 
+@@ -601,9 +601,9 @@ struct CachedPartialTokenRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1;
+-    detail::SplittedSentenceView<typename std::basic_string<CharT1>::iterator> tokens_s1;
+-    std::basic_string<CharT1> s1_sorted;
++    std::vector<CharT1> s1;
++    detail::SplittedSentenceView<typename std::vector<CharT1>::iterator> tokens_s1;
++    std::vector<CharT1> s1_sorted;
+ };
+ 
+ template <typename Sentence1>
+@@ -659,10 +659,10 @@ struct CachedWRatio { (private)
+ private:
+     // todo somehow implement this using other ratios with creating PatternMatchVector
+     // multiple times
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     CachedPartialRatio<CharT1> cached_partial_ratio;
+-    detail::SplittedSentenceView<typename std::basic_string<CharT1>::iterator> tokens_s1;
+-    std::basic_string<CharT1> s1_sorted;
++    detail::SplittedSentenceView<typename std::vector<CharT1>::iterator> tokens_s1;
++    std::vector<CharT1> s1_sorted;
+     rapidfuzz::detail::BlockPatternMatchVector blockmap_s1_sorted;
+ };
+ 
+@@ -774,7 +774,7 @@ struct CachedQRatio { (private)
+     double similarity(const Sentence2& s2, double score_cutoff = 0.0, double score_hint = 0.0) const;
+ 
+ private:
+-    std::basic_string<CharT1> s1;
++    std::vector<CharT1> s1;
+     CachedRatio<CharT1> cached_ratio;
+ };
+ 
diff --git a/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.impl b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.impl
new file mode 100644
index 000000000000..69c076798516
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-extern_rapidfuzz-cpp_rapidfuzz_fuzz.impl
@@ -0,0 +1,20 @@
+--- extern/rapidfuzz-cpp/rapidfuzz/fuzz.impl.orig	2023-09-26 11:15:29 UTC
++++ extern/rapidfuzz-cpp/rapidfuzz/fuzz.impl
+@@ -613,7 +613,7 @@ template <typename CharT1, typename InputIt1, typename
+ 
+ // todo this is a temporary solution until WRatio is properly implemented using other scorers
+ template <typename CharT1, typename InputIt1, typename InputIt2>
+-double token_ratio(const std::basic_string<CharT1>& s1_sorted,
++double token_ratio(const std::vector<CharT1>& s1_sorted,
+                    const rapidfuzz::detail::SplittedSentenceView<InputIt1>& tokens_s1,
+                    const detail::BlockPatternMatchVector& blockmap_s1_sorted, InputIt2 first2, InputIt2 last2,
+                    double score_cutoff)
+@@ -729,7 +729,7 @@ template <typename CharT1, typename InputIt1, typename
+ 
+ namespace fuzz_detail {
+ template <typename CharT1, typename InputIt1, typename InputIt2>
+-double partial_token_ratio(const std::basic_string<CharT1>& s1_sorted,
++double partial_token_ratio(const std::vector<CharT1>& s1_sorted,
+                            const rapidfuzz::detail::SplittedSentenceView<InputIt1>& tokens_s1,
+                            InputIt2 first2, InputIt2 last2, double score_cutoff)
+ {
diff --git a/devel/py-Levenshtein/files/patch-src_Levenshtein_Levenshtein-c___levenshtein.cpp b/devel/py-Levenshtein/files/patch-src_Levenshtein_Levenshtein-c___levenshtein.cpp
new file mode 100644
index 000000000000..6e2fd484a0b4
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-src_Levenshtein_Levenshtein-c___levenshtein.cpp
@@ -0,0 +1,16 @@
+--- src/Levenshtein/Levenshtein-c/_levenshtein.cpp.orig	2023-09-26 11:15:28 UTC
++++ src/Levenshtein/Levenshtein-c/_levenshtein.cpp
+@@ -119,10 +119,10 @@ class SymMap { (public)
+     }
+ };
+ 
+-std::basic_string<uint32_t> lev_quick_median(const std::vector<RF_String>& strings,
+-                                             const std::vector<double>& weights)
++std::vector<uint32_t> lev_quick_median(const std::vector<RF_String>& strings,
++                                       const std::vector<double>& weights)
+ {
+-    std::basic_string<uint32_t> median; /* the resulting string */
++    std::vector<uint32_t> median; /* the resulting string */
+ 
+     /* first check whether the result would be an empty string
+      * and compute resulting string length */
diff --git a/devel/py-Levenshtein/files/patch-src_Levenshtein_Levenshtein-c___levenshtein.hpp b/devel/py-Levenshtein/files/patch-src_Levenshtein_Levenshtein-c___levenshtein.hpp
new file mode 100644
index 000000000000..3d610f82b43b
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-src_Levenshtein_Levenshtein-c___levenshtein.hpp
@@ -0,0 +1,69 @@
+--- src/Levenshtein/Levenshtein-c/_levenshtein.hpp.orig	2023-09-26 11:15:28 UTC
++++ src/Levenshtein/Levenshtein-c/_levenshtein.hpp
+@@ -141,10 +141,10 @@ static inline std::vector<uint32_t> make_symlist(const
+  * Returns: The generalized median, as a newly allocated string; its length
+  *          is stored in @medlength.
+  **/
+-static inline std::basic_string<uint32_t> lev_greedy_median(const std::vector<RF_String>& strings,
+-                                                            const std::vector<double>& weights)
++static inline std::vector<uint32_t> lev_greedy_median(const std::vector<RF_String>& strings,
++                                                      const std::vector<double>& weights)
+ {
+-    std::basic_string<uint32_t> result_median;
++    std::vector<uint32_t> result_median;
+ 
+     /* find all symbols */
+     std::vector<uint32_t> symlist = make_symlist(strings);
+@@ -335,13 +335,13 @@ static inline double finish_distance_computations(cons
+  *
+  * Returns: The improved generalized median
+  **/
+-static inline std::basic_string<uint32_t> lev_median_improve(const RF_String& string,
+-                                                             const std::vector<RF_String>& strings,
+-                                                             const std::vector<double>& weights)
++static inline std::vector<uint32_t> lev_median_improve(const RF_String& string,
++                                                       const std::vector<RF_String>& strings,
++                                                       const std::vector<double>& weights)
+ {
+     /* find all symbols */
+     std::vector<uint32_t> symlist = make_symlist(strings);
+-    if (symlist.empty()) return std::basic_string<uint32_t>();
++    if (symlist.empty()) return std::vector<uint32_t>();
+ 
+     /* allocate and initialize per-string matrix rows and a common work buffer */
+     std::vector<std::unique_ptr<size_t[]>> rows(strings.size());
+@@ -459,11 +459,11 @@ static inline std::basic_string<uint32_t> lev_median_i
+         }
+     }
+ 
+-    return std::basic_string<uint32_t>(median, medlen);
++    return std::vector<uint32_t>(median, median + medlen);
+ }
+ 
+-std::basic_string<uint32_t> lev_quick_median(const std::vector<RF_String>& strings,
+-                                             const std::vector<double>& weights);
++std::vector<uint32_t> lev_quick_median(const std::vector<RF_String>& strings,
++                                       const std::vector<double>& weights);
+ 
+ /**
+  * lev_set_median:
+@@ -477,8 +477,8 @@ std::basic_string<uint32_t> lev_quick_median(const std
+  *
+  * Returns: The set median
+  **/
+-static inline std::basic_string<uint32_t> lev_set_median(const std::vector<RF_String>& strings,
+-                                                         const std::vector<double>& weights)
++static inline std::vector<uint32_t> lev_set_median(const std::vector<RF_String>& strings,
++                                                   const std::vector<double>& weights)
+ {
+     size_t minidx = 0;
+     double mindist = std::numeric_limits<double>::max();
+@@ -521,7 +521,7 @@ static inline std::basic_string<uint32_t> lev_set_medi
+     }
+ 
+     return visit(strings[minidx], [&](auto s1) {
+-        return std::basic_string<uint32_t>(std::begin(s1), std::end(s1));
++        return std::vector<uint32_t>(std::begin(s1), std::end(s1));
+     });
+ }
+ 
diff --git a/devel/py-Levenshtein/files/patch-src_Levenshtein_levenshtein__cpp.cxx b/devel/py-Levenshtein/files/patch-src_Levenshtein_levenshtein__cpp.cxx
new file mode 100644
index 000000000000..a35655413ec2
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-src_Levenshtein_levenshtein__cpp.cxx
@@ -0,0 +1,74 @@
+--- src/Levenshtein/levenshtein_cpp.cxx.orig	2023-09-26 11:15:40 UTC
++++ src/Levenshtein/levenshtein_cpp.cxx
+@@ -3094,7 +3094,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_cpp_median(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_strlist, PyObject *__pyx_v_wlist) {
+   std::vector<double>  __pyx_v_weights;
+   std::vector<RF_String>  __pyx_v_strings;
+-  std::basic_string<uint32_t>  __pyx_v_median;
++  std::vector<uint32_t>  __pyx_v_median;
+   PyObject *__pyx_r = NULL;
+   __Pyx_RefNannyDeclarations
+   int __pyx_t_1;
+@@ -3104,7 +3104,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+   PyObject *__pyx_t_5 = NULL;
+   std::vector<double>  __pyx_t_6;
+   std::vector<RF_String>  __pyx_t_7;
+-  std::basic_string<uint32_t>  __pyx_t_8;
++  std::vector<uint32_t>  __pyx_t_8;
+   int __pyx_lineno = 0;
+   const char *__pyx_filename = NULL;
+   int __pyx_clineno = 0;
+@@ -3345,7 +3345,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_cpp_2quickmedian(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_strlist, PyObject *__pyx_v_wlist) {
+   std::vector<double>  __pyx_v_weights;
+   std::vector<RF_String>  __pyx_v_strings;
+-  std::basic_string<uint32_t>  __pyx_v_median;
++  std::vector<uint32_t>  __pyx_v_median;
+   PyObject *__pyx_r = NULL;
+   __Pyx_RefNannyDeclarations
+   int __pyx_t_1;
+@@ -3355,7 +3355,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+   PyObject *__pyx_t_5 = NULL;
+   std::vector<double>  __pyx_t_6;
+   std::vector<RF_String>  __pyx_t_7;
+-  std::basic_string<uint32_t>  __pyx_t_8;
++  std::vector<uint32_t>  __pyx_t_8;
+   int __pyx_lineno = 0;
+   const char *__pyx_filename = NULL;
+   int __pyx_clineno = 0;
+@@ -3612,7 +3612,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+   std::vector<double>  __pyx_v_weights;
+   RF_String __pyx_v_query;
+   std::vector<RF_String>  __pyx_v_strings;
+-  std::basic_string<uint32_t>  __pyx_v_median;
++  std::vector<uint32_t>  __pyx_v_median;
+   PyObject *__pyx_r = NULL;
+   __Pyx_RefNannyDeclarations
+   int __pyx_t_1;
+@@ -3623,7 +3623,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+   std::vector<double>  __pyx_t_6;
+   RF_String __pyx_t_7;
+   std::vector<RF_String>  __pyx_t_8;
+-  std::basic_string<uint32_t>  __pyx_t_9;
++  std::vector<uint32_t>  __pyx_t_9;
+   int __pyx_lineno = 0;
+   const char *__pyx_filename = NULL;
+   int __pyx_clineno = 0;
+@@ -3874,7 +3874,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_cpp_6setmedian(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_strlist, PyObject *__pyx_v_wlist) {
+   std::vector<double>  __pyx_v_weights;
+   std::vector<RF_String>  __pyx_v_strings;
+-  std::basic_string<uint32_t>  __pyx_v_median;
++  std::vector<uint32_t>  __pyx_v_median;
+   PyObject *__pyx_r = NULL;
+   __Pyx_RefNannyDeclarations
+   int __pyx_t_1;
+@@ -3884,7 +3884,7 @@ static PyObject *__pyx_pf_11Levenshtein_15levenshtein_
+   PyObject *__pyx_t_5 = NULL;
+   std::vector<double>  __pyx_t_6;
+   std::vector<RF_String>  __pyx_t_7;
+-  std::basic_string<uint32_t>  __pyx_t_8;
++  std::vector<uint32_t>  __pyx_t_8;
+   int __pyx_lineno = 0;
+   const char *__pyx_filename = NULL;
+   int __pyx_clineno = 0;
diff --git a/devel/py-Levenshtein/files/patch-src_Levenshtein_levenshtein__cpp.pyx b/devel/py-Levenshtein/files/patch-src_Levenshtein_levenshtein__cpp.pyx
new file mode 100644
index 000000000000..8feb0af43ca8
--- /dev/null
+++ b/devel/py-Levenshtein/files/patch-src_Levenshtein_levenshtein__cpp.pyx
@@ -0,0 +1,30 @@
+--- src/Levenshtein/levenshtein_cpp.pyx.orig	2023-09-26 11:15:28 UTC
++++ src/Levenshtein/levenshtein_cpp.pyx
+@@ -12,10 +12,10 @@ cdef extern from "<string>" namespace "std" nogil:
+     object PyUnicode_FromKindAndData(int kind, const void *buffer, Py_ssize_t size)
+ 
+ cdef extern from "<string>" namespace "std" nogil:
+-    cdef cppclass basic_string[T]:
++    cdef cppclass vector[T]:
+         ctypedef size_t size_type
+ 
+-        basic_string() except +
++        vector() except +
+ 
+         void resize(size_type) except +
+ 
+@@ -25,10 +25,10 @@ cdef extern from "_levenshtein.hpp":
+         size_type size()
+ 
+ cdef extern from "_levenshtein.hpp":
+-    cdef basic_string[uint32_t] lev_greedy_median(const vector[RF_String]& strings, const vector[double]& weights) except +
+-    cdef basic_string[uint32_t] lev_median_improve(const RF_String& string, const vector[RF_String]& strings, const vector[double]& weights) except +
+-    cdef basic_string[uint32_t] lev_quick_median(const vector[RF_String]& strings, const vector[double]& weights) except +
+-    cdef basic_string[uint32_t] lev_set_median(const vector[RF_String]& strings, const vector[double]& weights) except +
++    cdef vector[uint32_t] lev_greedy_median(const vector[RF_String]& strings, const vector[double]& weights) except +
++    cdef vector[uint32_t] lev_median_improve(const RF_String& string, const vector[RF_String]& strings, const vector[double]& weights) except +
++    cdef vector[uint32_t] lev_quick_median(const vector[RF_String]& strings, const vector[double]& weights) except +
++    cdef vector[uint32_t] lev_set_median(const vector[RF_String]& strings, const vector[double]& weights) except +
+ 
+     cdef double lev_set_distance(const vector[RF_String]& strings1, const vector[RF_String]& strings2) except +
+     cdef double lev_edit_seq_distance(const vector[RF_String]& strings1, const vector[RF_String]& strings2) except +