Skip to content

Commit

Permalink
add python 2.7 support
Browse files Browse the repository at this point in the history
  • Loading branch information
maxbachmann committed Aug 22, 2020
1 parent a780018 commit 10946df
Show file tree
Hide file tree
Showing 14 changed files with 239 additions and 229 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/pythonbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.5, 3.6, 3.7, 3.8]
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]

steps:
- uses: actions/checkout@v2
Expand All @@ -34,9 +34,9 @@ jobs:
run: |
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
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 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 src --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Run Unit Tests
run: |
Expand All @@ -53,7 +53,7 @@ jobs:
matrix:
os: [ubuntu-18.04, windows-latest, macos-latest]
env:
CIBW_SKIP: cp27-* pp27-*
CIBW_SKIP: cp27-win* pp27-win*

steps:
- uses: actions/checkout@v1
Expand Down
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ recursive-include src/rapidfuzz-cpp/extern/nonstd *

recursive-include extern/variant *
include src/py_utils.hpp
include src/py2_utils.hpp
include src/py3_utils.hpp
include src/rapidfuzz-cpp/LICENSE
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.10.0
0.11.0
6 changes: 5 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import sys

from os import path
from io import open

this_dir = path.abspath(path.dirname(__file__))
with open(path.join(this_dir, "VERSION"), encoding='utf-8') as version_file:
version = version_file.read().strip()
Expand Down Expand Up @@ -76,6 +78,8 @@ def build_extensions(self):
include_package_data=True,
zip_safe=False,
classifiers=[
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
Expand All @@ -84,5 +88,5 @@ def build_extensions(self):
"Programming Language :: Python :: 3.9",
"License :: OSI Approved :: MIT License",
],
python_requires=">=3.5",
python_requires=">=2.7",
)
40 changes: 40 additions & 0 deletions src/py2_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2020 Max Bachmann */

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <nonstd/string_view.hpp>
#include <variant/variant.hpp>

bool valid_str(PyObject* str, const char* name) {
if (!PyObject_TypeCheck(str, &PyString_Type)
&& !PyObject_TypeCheck(str, &PyUnicode_Type))
{
PyErr_Format(PyExc_TypeError, "%s must be a String, Unicode or None", name);
return false;
}
return true;
}

#define PY_INIT_MOD(name, doc, methods) \
PyMODINIT_FUNC init##name(void) { \
Py_InitModule3(#name, methods, doc); \
}

using python_string_view = mpark::variant<
nonstd::basic_string_view<uint8_t>,
nonstd::basic_string_view<Py_UNICODE>
>;

python_string_view decode_python_string(PyObject* py_str) {
if (PyObject_TypeCheck(py_str, &PyString_Type)) {
Py_ssize_t len = PyString_GET_SIZE(py_str);
uint8_t* str = reinterpret_cast<uint8_t*>(PyString_AS_STRING(py_str));
return nonstd::basic_string_view<uint8_t>(str, len);

} else {
Py_ssize_t len = PyUnicode_GET_SIZE(py_str);
Py_UNICODE* str = PyUnicode_AS_UNICODE(py_str);
return nonstd::basic_string_view<Py_UNICODE>(str, len);
}
}
56 changes: 56 additions & 0 deletions src/py3_utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: MIT */
/* Copyright © 2020 Max Bachmann */

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <nonstd/string_view.hpp>
#include <variant/variant.hpp>

#if PY_VERSION_HEX < 0x030C0000
#define PY_BELOW_3_12
#endif

bool valid_str(PyObject* str, const char* name) {
if (!PyUnicode_Check(str)) {
PyErr_Format(PyExc_TypeError, "%s must be a String or None", name);
return false;
}

// PyUnicode_READY deprecated in Python 3.10 removed in Python 3.12
#ifdef PY_BELOW_3_12
if (PyUnicode_READY(str)) {
return false;
}
#endif

return true;
}

#define PY_INIT_MOD(name, doc, methods) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, #name, doc, -1, methods, NULL, NULL, NULL, NULL}; \
PyMODINIT_FUNC PyInit_##name(void) { \
return PyModule_Create(&moduledef); \
}

using python_string_view = mpark::variant<
nonstd::basic_string_view<uint8_t>,
nonstd::basic_string_view<uint16_t>,
nonstd::basic_string_view<uint32_t>
>;

python_string_view decode_python_string(PyObject* py_str) {
Py_ssize_t len = PyUnicode_GET_LENGTH(py_str);
void* str = PyUnicode_DATA(py_str);

int str_kind = PyUnicode_KIND(py_str);

switch (str_kind) {
case PyUnicode_1BYTE_KIND:
return nonstd::basic_string_view<uint8_t>(static_cast<uint8_t*>(str), len);
case PyUnicode_2BYTE_KIND:
return nonstd::basic_string_view<uint16_t>(static_cast<uint16_t*>(str), len);
default:
return nonstd::basic_string_view<uint32_t>(static_cast<uint32_t*>(str), len);
}
}
Loading

0 comments on commit 10946df

Please sign in to comment.