diff --git a/.github/workflows/pythonbuild.yml b/.github/workflows/pythonbuild.yml index 96a3369..31ab71a 100644 --- a/.github/workflows/pythonbuild.yml +++ b/.github/workflows/pythonbuild.yml @@ -8,47 +8,7 @@ on: - published jobs: - test_python: - name: linting and tests on Python ${{ matrix.python-version }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-18.04, macos-latest] - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] - - steps: - - uses: actions/checkout@v2 - with: - submodules: 'true' - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install wheel - - - name: Lint with flake8 - run: | - pip install flake8 - # stop the build if there are Python syntax errors or undefined names - flake8 src --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide - flake8 src --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - - name: Run Unit Tests - run: | - pip install . - pip install pytest hypothesis pandas - pytest - - build_wheels: - needs: [test_python] name: Build wheel on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: @@ -56,7 +16,9 @@ jobs: matrix: os: [ubuntu-18.04, windows-latest, macos-latest] env: - CIBW_SKIP: cp27-win* pp27-win* + CIBW_SKIP: cp27-* pp27-* + CIBW_TEST_REQUIRES: pytest hypothesis pandas + CIBW_TEST_COMMAND: pytest {package}/tests steps: - uses: actions/checkout@v1 @@ -70,7 +32,7 @@ jobs: - name: Install cibuildwheel run: | - python -m pip install git+https://github.com/joerick/cibuildwheel.git@f6eaa9f + python -m pip install cibuildwheel~=1.10.0 - name: Build wheels run: | python -m cibuildwheel --output-dir wheelhouse @@ -79,7 +41,6 @@ jobs: path: ./wheelhouse/*.whl build_wheels_manylinux1: - needs: [test_python] name: Build wheel with manylinux1 runs-on: ubuntu-18.04 strategy: @@ -88,6 +49,8 @@ jobs: CIBW_BUILD: cp* CIBW_MANYLINUX_X86_64_IMAGE: manylinux1 CIBW_MANYLINUX_I686_IMAGE: manylinux1 + CIBW_TEST_REQUIRES: pytest hypothesis pandas + CIBW_TEST_COMMAND: pytest {package}/tests steps: - uses: actions/checkout@v1 @@ -101,7 +64,7 @@ jobs: - name: Install cibuildwheel run: | - python -m pip install git+https://github.com/joerick/cibuildwheel.git@f6eaa9f + python -m pip install cibuildwheel~=1.10.0 - name: Build wheels run: | python -m cibuildwheel --output-dir wheelhouse @@ -109,76 +72,7 @@ jobs: with: path: ./wheelhouse/*.whl - build_wheels_python27_windows_64: - needs: [test_python] - name: Build wheel for python2.7 on windows-latest 64 bit - runs-on: windows-latest - env: - CIBW_BUILD: cp27-win_amd64 - DISTUTILS_USE_SDK: 1 - MSSdk: 1 - - steps: - - uses: actions/checkout@v1 - with: - submodules: 'true' - - - uses: actions/setup-python@v1 - name: Install Python - with: - python-version: '3.7' - - - name: Install cibuildwheel - run: | - python -m pip install git+https://github.com/joerick/cibuildwheel.git@f6eaa9f - - - uses: ilammy/msvc-dev-cmd@v1 - - - name: Build 64-bit wheel - run: python -m cibuildwheel --output-dir wheelhouse - - - uses: actions/upload-artifact@v2 - with: - path: ./wheelhouse/*.whl - - - build_wheels_python27_windows_32: - needs: [test_python] - name: Build wheel for python2.7 on windows-latest 32 bit - runs-on: windows-latest - env: - CIBW_BUILD: cp27-win32 pp27-win32 - DISTUTILS_USE_SDK: 1 - MSSdk: 1 - - steps: - - uses: actions/checkout@v1 - with: - submodules: 'true' - - - uses: actions/setup-python@v1 - name: Install Python - with: - python-version: '3.7' - - - name: Install cibuildwheel - run: | - python -m pip install git+https://github.com/joerick/cibuildwheel.git@f6eaa9f - - - uses: ilammy/msvc-dev-cmd@v1 - with: - arch: x86 - - - name: Build 64-bit wheel - run: python -m cibuildwheel --output-dir wheelhouse - - - uses: actions/upload-artifact@v2 - with: - path: ./wheelhouse/*.whl - - build_sdist: - needs: [test_python] name: Build source distribution runs-on: ubuntu-latest steps: @@ -205,7 +99,7 @@ jobs: deploy-wheels: if: github.event_name == 'release' && github.event.action == 'published' - needs: [build_wheels, build_wheels_manylinux1, build_wheels_python27_windows_64, build_wheels_python27_windows_32, build_sdist] + needs: [build_wheels, build_wheels_manylinux1, build_sdist] name: deploy wheels to pypi runs-on: ubuntu-18.04 diff --git a/README.md b/README.md index 273538c..a7902ff 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ RapidFuzz is a fast string matching library for Python and C++, which is using t ## Requirements -- Python 2.7 or later +- Python 3.5 or later - On Windows the [Visual C++ 2019 redistributable](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) is required ## Installation diff --git a/setup.cfg b/setup.cfg index cdd1b66..205a21c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,8 +11,6 @@ long_description_content_type = text/markdown license = MIT license_file = LICENSE classifiers = - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 @@ -27,7 +25,7 @@ include_package_data = True package_dir= =src packages = find: -python_requires = >=2.7 +python_requires = >=3.5 [options.packages.find] where=src diff --git a/src/cpp_fuzz.hpp b/src/cpp_fuzz.hpp index 9d6e453..2b6d781 100644 --- a/src/cpp_fuzz.hpp +++ b/src/cpp_fuzz.hpp @@ -21,13 +21,6 @@ private: char const* m_error; }; -#if PY_VERSION_HEX < PYTHON_VERSION(3, 0, 0) -enum StringKind{ - CHAR_STRING, - UNICODE_STRING -}; -#endif - struct proc_string { int kind; void* data; @@ -38,7 +31,6 @@ static proc_string convert_string(PyObject* py_str) { proc_string str = {0, NULL, 0}; -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) if (!PyUnicode_Check(py_str)) { throw PythonTypeError("choice must be a String or None"); } @@ -54,26 +46,10 @@ static proc_string convert_string(PyObject* py_str) str.kind = PyUnicode_KIND(py_str); str.data = PyUnicode_DATA(py_str); str.length = PyUnicode_GET_LENGTH(py_str); -#else /* Python 2 */ - if (PyObject_TypeCheck(py_str, &PyString_Type)) { - str.kind = CHAR_STRING; - str.length = PyString_GET_SIZE(py_str); - str.data = (void*)PyString_AS_STRING(py_str); - } - else if (PyObject_TypeCheck(py_str, &PyUnicode_Type)) { - str.kind = UNICODE_STRING; - str.length = PyUnicode_GET_SIZE(py_str); - str.data = (void*)PyUnicode_AS_UNICODE(py_str); - } - else { - throw PythonTypeError("choice must be a String, Unicode or None"); - } -#endif return str; } -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) #define RATIO_SINGLE(RATIO, RATIO_FUNC) \ template \ inline double RATIO##_single(proc_string s1, proc_string s2, double score_cutoff) \ @@ -99,30 +75,7 @@ inline double RATIO##_single(proc_string s1, proc_string s2, double score_cutoff ); \ } \ } -#else -#define RATIO_SINGLE(RATIO, RATIO_FUNC) \ -template \ -inline double RATIO##_single(proc_string s1, proc_string s2, double score_cutoff) \ -{ \ - switch(s2.kind){ \ - case CHAR_STRING: \ - return RATIO_FUNC( \ - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), \ - rapidfuzz::basic_string_view((uint8_t*)s2.data, s2.length), \ - score_cutoff \ - ); \ - default: \ - return RATIO_FUNC( \ - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), \ - rapidfuzz::basic_string_view((Py_UNICODE*)s2.data, s2.length), \ - score_cutoff \ - ); \ - } \ -} -#endif - -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) #define RATIO_IMPL(RATIO, RATIO_FUNC) \ double RATIO##_impl(PyObject* s1, PyObject* s2, double score_cutoff) \ { \ @@ -141,27 +94,7 @@ double RATIO##_impl(PyObject* s1, PyObject* s2, double score_cutoff) \ return RATIO##_single(c_s1, c_s2, score_cutoff); \ } \ } -#else -#define RATIO_IMPL(RATIO, RATIO_FUNC) \ -double RATIO##_impl(PyObject* s1, PyObject* s2, double score_cutoff) \ -{ \ - proc_string c_s1 = convert_string(s1); \ - if (c_s1.data == NULL) return 0.0; \ - \ - proc_string c_s2 = convert_string(s2); \ - if (c_s2.data == NULL) return 0.0; \ - \ - switch(c_s1.kind){ \ - case CHAR_STRING: \ - return RATIO##_single(c_s1, c_s2, score_cutoff); \ - default: \ - return RATIO##_single(c_s1, c_s2, score_cutoff); \ - } \ -} -#endif - -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) #define RATIO_SINGLE_DEFAULT_PROCESS(RATIO, RATIO_FUNC) \ template \ inline double RATIO##_single_default_process( \ @@ -200,39 +133,7 @@ inline double RATIO##_single_default_process( ); \ } \ } -#else -#define RATIO_SINGLE_DEFAULT_PROCESS(RATIO, RATIO_FUNC) \ -template \ -inline double RATIO##_single_default_process( \ - proc_string s1, proc_string s2, double score_cutoff) \ -{ \ - switch(s2.kind){ \ - case CHAR_STRING: \ - return RATIO_FUNC( \ - utils::default_process( \ - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length) \ - ), \ - utils::default_process( \ - rapidfuzz::basic_string_view((uint8_t*)s2.data, s2.length) \ - ), \ - score_cutoff \ - ); \ - default: \ - return RATIO_FUNC( \ - utils::default_process( \ - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length) \ - ), \ - utils::default_process( \ - rapidfuzz::basic_string_view((Py_UNICODE*)s2.data, s2.length) \ - ), \ - score_cutoff \ - ); \ - } \ -} -#endif - -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) #define RATIO_IMPL_DEFAULT_PROCESS(RATIO, RATIO_FUNC) \ double RATIO##_impl_default_process(PyObject* s1, PyObject* s2, double score_cutoff) { \ proc_string c_s1 = convert_string(s1); \ @@ -250,23 +151,6 @@ double RATIO##_impl_default_process(PyObject* s1, PyObject* s2, double score_cut return RATIO##_single_default_process(c_s1, c_s2, score_cutoff); \ } \ } -#else -#define RATIO_IMPL_DEFAULT_PROCESS(RATIO, RATIO_FUNC) \ -double RATIO##_impl_default_process(PyObject* s1, PyObject* s2, double score_cutoff) { \ - proc_string c_s1 = convert_string(s1); \ - if (c_s1.data == NULL) return 0.0; \ - \ - proc_string c_s2 = convert_string(s2); \ - if (c_s2.data == NULL) return 0.0; \ - \ - switch(c_s1.kind){ \ - case CHAR_STRING: \ - return RATIO##_single_default_process(c_s1, c_s2, score_cutoff); \ - default: \ - return RATIO##_single_default_process(c_s1, c_s2, score_cutoff); \ - } \ -} -#endif #define RATIO_DEF(RATIO, RATIO_FUNC) \ RATIO_SINGLE_DEFAULT_PROCESS(RATIO, RATIO_FUNC) \ diff --git a/src/cpp_process.hpp b/src/cpp_process.hpp index ac504c3..bed16d8 100644 --- a/src/cpp_process.hpp +++ b/src/cpp_process.hpp @@ -53,13 +53,6 @@ struct ExtractComp } }; -#if PY_VERSION_HEX < PYTHON_VERSION(3, 0, 0) -enum StringKind{ - CHAR_STRING, - UNICODE_STRING -}; -#endif - struct proc_string { int kind; void* data; @@ -70,7 +63,6 @@ static proc_string convert_string(PyObject* py_str) { proc_string str = {0, NULL, 0}; -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) if (!PyUnicode_Check(py_str)) { throw PythonTypeError("choice must be a String or None"); } @@ -86,21 +78,6 @@ static proc_string convert_string(PyObject* py_str) str.kind = PyUnicode_KIND(py_str); str.data = PyUnicode_DATA(py_str); str.length = PyUnicode_GET_LENGTH(py_str); -#else /* Python 2 */ - if (PyObject_TypeCheck(py_str, &PyString_Type)) { - str.kind = CHAR_STRING; - str.length = PyString_GET_SIZE(py_str); - str.data = (void*)PyString_AS_STRING(py_str); - } - else if (PyObject_TypeCheck(py_str, &PyUnicode_Type)) { - str.kind = UNICODE_STRING; - str.length = PyUnicode_GET_SIZE(py_str); - str.data = (void*)PyUnicode_AS_UNICODE(py_str); - } - else { - throw PythonTypeError("choice must be a String, Unicode or None"); - } -#endif return str; } @@ -130,7 +107,6 @@ static inline double cached_func_default_process( CachedScorer* ratio = (CachedScorer*)context; switch(str.kind){ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) case PyUnicode_1BYTE_KIND: return ratio->ratio( utils::default_process( @@ -149,20 +125,6 @@ static inline double cached_func_default_process( rapidfuzz::basic_string_view((uint32_t*)str.data, str.length)), score_cutoff ); -#else - case CHAR_STRING: - return ratio->ratio( - utils::default_process( - rapidfuzz::basic_string_view((uint8_t*)str.data, str.length)), - score_cutoff - ); - case UNICODE_STRING: - return ratio->ratio( - utils::default_process( - rapidfuzz::basic_string_view((Py_UNICODE*)str.data, str.length)), - score_cutoff - ); -#endif default: throw std::logic_error("Reached end of control flow in cached_func_default_process"); } @@ -175,7 +137,6 @@ static inline double cached_func(void* context, PyObject* py_str, double score_c CachedScorer* ratio = (CachedScorer*)context; switch(str.kind){ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) case PyUnicode_1BYTE_KIND: return ratio->ratio( rapidfuzz::basic_string_view((uint8_t*)str.data, str.length), @@ -191,18 +152,6 @@ static inline double cached_func(void* context, PyObject* py_str, double score_c rapidfuzz::basic_string_view((uint32_t*)str.data, str.length), score_cutoff ); -#else - case CHAR_STRING: - return ratio->ratio( - rapidfuzz::basic_string_view((uint8_t*)str.data, str.length), - score_cutoff - ); - case UNICODE_STRING: - return ratio->ratio( - rapidfuzz::basic_string_view((Py_UNICODE*)str.data, str.length), - score_cutoff - ); -#endif default: throw std::logic_error("Reached end of control flow in cached_func"); } @@ -231,19 +180,12 @@ static inline scorer_context cached_init(PyObject* py_str, int def_process, Args if (str.data == NULL) return {NULL, NULL, NULL}; switch(str.kind){ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) case PyUnicode_1BYTE_KIND: return get_scorer_context(str, def_process, args...); case PyUnicode_2BYTE_KIND: return get_scorer_context(str, def_process, args...); case PyUnicode_4BYTE_KIND: return get_scorer_context(str, def_process, args...); -#else - case CHAR_STRING: - return get_scorer_context(str, def_process, args...); - case UNICODE_STRING: - return get_scorer_context(str, def_process, args...); -#endif default: throw std::logic_error("Reached end of control flow in cached_init"); } diff --git a/src/cpp_string_metric.hpp b/src/cpp_string_metric.hpp index a31a6d9..5e3ef38 100644 --- a/src/cpp_string_metric.hpp +++ b/src/cpp_string_metric.hpp @@ -21,12 +21,6 @@ private: char const* m_error; }; -#if PY_VERSION_HEX < PYTHON_VERSION(3, 0, 0) -enum StringKind{ - CHAR_STRING, - UNICODE_STRING -}; -#endif struct proc_string { int kind; @@ -38,7 +32,6 @@ static proc_string convert_string(PyObject* py_str) { proc_string str = {0, NULL, 0}; -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) if (!PyUnicode_Check(py_str)) { throw PythonTypeError("choice must be a String or None"); } @@ -54,21 +47,6 @@ static proc_string convert_string(PyObject* py_str) str.kind = PyUnicode_KIND(py_str); str.data = PyUnicode_DATA(py_str); str.length = PyUnicode_GET_LENGTH(py_str); -#else /* Python 2 */ - if (PyObject_TypeCheck(py_str, &PyString_Type)) { - str.kind = CHAR_STRING; - str.length = PyString_GET_SIZE(py_str); - str.data = (void*)PyString_AS_STRING(py_str); - } - else if (PyObject_TypeCheck(py_str, &PyUnicode_Type)) { - str.kind = UNICODE_STRING; - str.length = PyUnicode_GET_SIZE(py_str); - str.data = (void*)PyUnicode_AS_UNICODE(py_str); - } - else { - throw PythonTypeError("choice must be a String, Unicode or None"); - } -#endif return str; } @@ -77,7 +55,6 @@ static proc_string convert_string(PyObject* py_str) * Levenshtein */ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) template size_t levenshtein_impl_inner(proc_string s1, proc_string s2, size_t insertion, size_t deletion, size_t substitution, size_t max) @@ -135,61 +112,11 @@ PyObject* levenshtein_impl(PyObject* s1, PyObject* s2, return PyLong_FromSize_t(result); } -#else - -template -size_t levenshtein_impl_inner(proc_string s1, proc_string s2, - size_t insertion, size_t deletion, size_t substitution, size_t max) -{ - switch(s2.kind){ - case CHAR_STRING: - return string_metric::levenshtein( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((uint8_t*)s2.data, s2.length), - {insertion, deletion, substitution}, max - ); - default: - return string_metric::levenshtein( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((Py_UNICODE*)s2.data, s2.length), - {insertion, deletion, substitution}, max - ); - } -} - -PyObject* levenshtein_impl(PyObject* s1, PyObject* s2, - size_t insertion, size_t deletion, size_t substitution, size_t max) -{ - size_t result = 0; - proc_string c_s1 = convert_string(s1); - if (c_s1.data == NULL) Py_RETURN_NONE; - - proc_string c_s2 = convert_string(s2); - if (c_s2.data == NULL) Py_RETURN_NONE; - - switch(c_s1.kind){ - case CHAR_STRING: - result = levenshtein_impl_inner( - c_s1, c_s2, insertion, deletion, substitution, max); - break; - default: - result = levenshtein_impl_inner( - c_s1, c_s2, insertion, deletion, substitution, max); - break; - } - - if (result == (std::size_t)-1) { - return PyLong_FromLong(-1); - } - return PyLong_FromSize_t(result); -} -#endif /* * Normalized Levenshtein */ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) template inline double normalized_levenshtein_impl_inner(proc_string s1, proc_string s2, size_t insertion, size_t deletion, size_t substitution, double score_cutoff) @@ -237,49 +164,8 @@ double normalized_levenshtein_impl(PyObject* s1, PyObject* s2, c_s1, c_s2, insertion, deletion, substitution, score_cutoff); } } -#else -template -inline double normalized_levenshtein_impl_inner(proc_string s1, proc_string s2, - size_t insertion, size_t deletion, size_t substitution, double score_cutoff) -{ - switch(s2.kind){ - case PyUnicode_1BYTE_KIND: - return string_metric::normalized_levenshtein( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((uint8_t*)s2.data, s2.length), - {insertion, deletion, substitution}, score_cutoff - ); - default: - return string_metric::normalized_levenshtein( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((Py_UNICODE*)s2.data, s2.length), - {insertion, deletion, substitution}, score_cutoff - ); - } -} - -double normalized_levenshtein_impl(PyObject* s1, PyObject* s2, - size_t insertion, size_t deletion, size_t substitution, double score_cutoff) -{ - proc_string c_s1 = convert_string(s1); - if (c_s1.data == NULL) return 0.0; - - proc_string c_s2 = convert_string(s2); - if (c_s2.data == NULL) return 0.0; - - switch(c_s1.kind){ - case PyUnicode_1BYTE_KIND: - return normalized_levenshtein_impl_inner( - c_s1, c_s2, insertion, deletion, substitution, score_cutoff); - default: - return normalized_levenshtein_impl_inner( - c_s1, c_s2, insertion, deletion, substitution, score_cutoff); - } -} -#endif -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) template inline double normalized_levenshtein_impl_inner_default_process(proc_string s1, proc_string s2, size_t insertion, size_t deletion, size_t substitution, double score_cutoff) @@ -337,61 +223,11 @@ double normalized_levenshtein_impl_default_process(PyObject* s1, PyObject* s2, c_s1, c_s2, insertion, deletion, substitution, score_cutoff); } } -#else -template -inline double normalized_levenshtein_impl_inner_default_process(proc_string s1, proc_string s2, - size_t insertion, size_t deletion, size_t substitution, double score_cutoff) -{ - switch(s2.kind){ - case PyUnicode_1BYTE_KIND: - return string_metric::levenshtein( - utils::default_process( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length) - ), - utils::default_process( - rapidfuzz::basic_string_view((uint8_t*)s1.data, s1.length) - ), - {insertion, deletion, substitution}, score_cutoff - ); - default: - return string_metric::levenshtein( - utils::default_process( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length) - ), - utils::default_process( - rapidfuzz::basic_string_view((Py_UNICODE*)s1.data, s1.length) - ), - {insertion, deletion, substitution}, score_cutoff - ); - } -} - -double normalized_levenshtein_impl_default_process(PyObject* s1, PyObject* s2, - size_t insertion, size_t deletion, size_t substitution, double score_cutoff) -{ - proc_string c_s1 = convert_string(s1); - if (c_s1.data == NULL) return 0.0; - - proc_string c_s2 = convert_string(s2); - if (c_s2.data == NULL) return 0.0; - - switch(c_s1.kind){ - case PyUnicode_1BYTE_KIND: - return normalized_levenshtein_impl_inner_default_process( - c_s1, c_s2, insertion, deletion, substitution, score_cutoff); - default: - return normalized_levenshtein_impl_inner_default_process( - c_s1, c_s2, insertion, deletion, substitution, score_cutoff); - } -} -#endif - /* * Hamming */ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) template size_t hamming_impl_inner(proc_string s1, proc_string s2, size_t max) { @@ -444,57 +280,11 @@ PyObject* hamming_impl(PyObject* s1, PyObject* s2, size_t max) return PyLong_FromSize_t(result); } -#else - -template -size_t hamming_impl_inner(proc_string s1, proc_string s2, size_t max) -{ - switch(s2.kind){ - case CHAR_STRING: - return string_metric::hamming( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((uint8_t*)s2.data, s2.length), - max - ); - default: - return string_metric::hamming( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((Py_UNICODE*)s2.data, s2.length), - max - ); - } -} - -PyObject* hamming_impl(PyObject* s1, PyObject* s2, size_t max) -{ - size_t result = 0; - proc_string c_s1 = convert_string(s1); - if (c_s1.data == NULL) Py_RETURN_NONE; - - proc_string c_s2 = convert_string(s2); - if (c_s2.data == NULL) Py_RETURN_NONE; - - switch(c_s1.kind){ - case CHAR_STRING: - result = hamming_impl_inner(c_s1, c_s2, max); - break; - default: - result = hamming_impl_inner(c_s1, c_s2, max); - break; - } - - if (result == (std::size_t)-1) { - return PyLong_FromLong(-1); - } - return PyLong_FromSize_t(result); -} -#endif /* * Normalized Hamming */ -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) template inline double normalized_hamming_impl_inner(proc_string s1, proc_string s2, double score_cutoff) { @@ -537,45 +327,7 @@ double normalized_hamming_impl(PyObject* s1, PyObject* s2, double score_cutoff) return normalized_hamming_impl_inner(c_s1, c_s2, score_cutoff); } } -#else -template -inline double normalized_hamming_impl_inner(proc_string s1, proc_string s2, double score_cutoff) -{ - switch(s2.kind){ - case PyUnicode_1BYTE_KIND: - return string_metric::normalized_hamming( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((uint8_t*)s2.data, s2.length), - score_cutoff - ); - default: - return string_metric::normalized_hamming( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length), - rapidfuzz::basic_string_view((Py_UNICODE*)s2.data, s2.length), - score_cutoff - ); - } -} -double normalized_hamming_impl(PyObject* s1, PyObject* s2, double score_cutoff) -{ - proc_string c_s1 = convert_string(s1); - if (c_s1.data == NULL) return 0.0; - - proc_string c_s2 = convert_string(s2); - if (c_s2.data == NULL) return 0.0; - - switch(c_s1.kind){ - case PyUnicode_1BYTE_KIND: - return normalized_hamming_impl_inner(c_s1, c_s2, score_cutoff); - default: - return normalized_hamming_impl_inner(c_s1, c_s2, score_cutoff); - } -} -#endif - - -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) template inline double normalized_hamming_impl_inner_default_process( proc_string s1, proc_string s2, double score_cutoff) @@ -629,48 +381,3 @@ double normalized_hamming_impl_default_process(PyObject* s1, PyObject* s2, doubl return normalized_hamming_impl_inner_default_process(c_s1, c_s2, score_cutoff); } } -#else -template -inline double normalized_hamming_impl_inner_default_process( - proc_string s1, proc_string s2, double score_cutoff) -{ - switch(s2.kind){ - case PyUnicode_1BYTE_KIND: - return string_metric::hamming( - utils::default_process( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length) - ), - utils::default_process( - rapidfuzz::basic_string_view((uint8_t*)s1.data, s1.length) - ), - score_cutoff - ); - default: - return string_metric::hamming( - utils::default_process( - rapidfuzz::basic_string_view((CharT*)s1.data, s1.length) - ), - utils::default_process( - rapidfuzz::basic_string_view((Py_UNICODE*)s1.data, s1.length) - ), - score_cutoff - ); - } -} - -double normalized_hamming_impl_default_process(PyObject* s1, PyObject* s2, double score_cutoff) -{ - proc_string c_s1 = convert_string(s1); - if (c_s1.data == NULL) return 0.0; - - proc_string c_s2 = convert_string(s2); - if (c_s2.data == NULL) return 0.0; - - switch(c_s1.kind){ - case PyUnicode_1BYTE_KIND: - return normalized_hamming_impl_inner_default_process(c_s1, c_s2, score_cutoff); - default: - return normalized_hamming_impl_inner_default_process(c_s1, c_s2, score_cutoff); - } -} -#endif \ No newline at end of file diff --git a/src/cpp_utils.hpp b/src/cpp_utils.hpp index 498f582..a903c26 100644 --- a/src/cpp_utils.hpp +++ b/src/cpp_utils.hpp @@ -19,8 +19,6 @@ private: char const* m_error; }; - -#if PY_VERSION_HEX >= PYTHON_VERSION(3, 0, 0) PyObject* default_process_impl(PyObject* sentence) { if (!PyUnicode_Check(sentence)) { throw PythonTypeError("sentence must be a String"); @@ -58,24 +56,3 @@ PyObject* default_process_impl(PyObject* sentence) { } } } -#else -PyObject* default_process_impl(PyObject* sentence) { - if (PyObject_TypeCheck(sentence, &PyString_Type)) { - Py_ssize_t len = PyString_GET_SIZE(sentence); - char* str = PyString_AS_STRING(sentence); - - auto proc_str = utils::default_process(rapidfuzz::basic_string_view(str, len)); - return PyString_FromStringAndSize(proc_str.data(), proc_str.size()); - } - else if (PyObject_TypeCheck(sentence, &PyUnicode_Type)) { - Py_ssize_t len = PyUnicode_GET_SIZE(sentence); - const Py_UNICODE* str = PyUnicode_AS_UNICODE(sentence); - - auto proc_str = utils::default_process(rapidfuzz::basic_string_view(str, len)); - return PyUnicode_FromUnicode(proc_str.data(), proc_str.size()); - } - else { - throw PythonTypeError("choice must be a String or Unicode"); - } -} -#endif \ No newline at end of file