diff --git a/.github/workflows/build-and-test.yaml b/.github/workflows/build-and-test.yaml new file mode 100644 index 0000000..c8cce1b --- /dev/null +++ b/.github/workflows/build-and-test.yaml @@ -0,0 +1,43 @@ +name: Build/Test + +on: + workflow_call: + workflow_dispatch: + inputs: + part: + required: false + default: '' + +jobs: + build: + name: Build the library and run tests + strategy: + matrix: + os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, ubuntu-24.04-arm] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + if [[ "${{ matrix.os }}" =~ "ubuntu" ]]; then + sudo apt update + sudo apt install -y python3-pytest cython3 + else + brew install pytest python-setuptools + git clone --single-branch --branch 3.1.x https://github.com/cython/cython.git + cd cython + sudo python3 setup.py install + cd .. + fi + + - name: Build and install library + run: | + python3 setup.py build_ext + sudo python3 setup.py install + + - name: Run tests + run: | + pytest-3 . diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 0000000..0689df6 --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,8 @@ +name: PR + +on: + pull_request: + +jobs: + build: + uses: ./.github/workflows/build-and-test.yaml diff --git a/setup.py b/setup.py index ef9f7cf..c62861c 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import shutil import sys from setuptools import setup, Extension -from setuptools.command.build import build +from setuptools.command.build_ext import build_ext from Cython.Build import cythonize extension_modules = [ @@ -21,7 +21,7 @@ with open (os.path.join (base_path, "requirements.txt")) as reqs: requirements = reqs.read () -class CustomBuild(build): +class CustomBuild(build_ext): def run(self): super().run() suffix = '.dll' if 'win' in sys.platform.lower() else '.so' @@ -45,7 +45,7 @@ def run(self): test_suite = "tests", install_requires = requirements, zip_safe = False, - cmdclass = {'build': CustomBuild}, + cmdclass = {'build_ext': CustomBuild}, ext_modules = cythonize (extension_modules, include_path = include_dirs, language_level = 3, annotate = True, compiler_directives = {'embedsignature': True}), diff --git a/zser/defs.h b/zser/defs.h index e976192..8e4116b 100644 --- a/zser/defs.h +++ b/zser/defs.h @@ -27,6 +27,11 @@ STR_NEW (unsigned int code, size_t len, const void *ptr) b->length = len; b->hash = -1; b->state.compact = 0; + +#if PY_MINOR_VERSION <= 11 + b->state.ready = 1; +#endif + b->state.interned = 0; // SSTATE_NOT_INTERNED if (code == 3) { @@ -39,6 +44,14 @@ STR_NEW (unsigned int code, size_t len, const void *ptr) { b->state.ascii = 0; b->state.kind = code; + +#if PY_MINOR_VERSION <= 11 + if (code == sizeof (wchar_t)) + { + b->wstr = (wchar_t *)p->data.any; + c->wstr_length = b->length; + } +#endif } return ((PyObject *)p); @@ -52,6 +65,9 @@ STR_FINI (PyObject *obj) PyUnicodeObject *p = (PyUnicodeObject *)obj; p->data.any = NULL; p->_base.utf8 = NULL; +#if PY_MINOR_VERSION <= 11 + p->_base._base.wstr = NULL; +#endif } static int diff --git a/zser/zser.pyx b/zser/zser.pyx index d7f6ec5..e29e5d4 100644 --- a/zser/zser.pyx +++ b/zser/zser.pyx @@ -62,7 +62,7 @@ cdef size_t[6] _BASIC_SIZES = [sizeof (char), sizeof (short), # Basic types that may be stored inline in lists, sets, dicts and descriptors. ctypedef fused cnum: - char + signed char unsigned char short unsigned short @@ -105,7 +105,7 @@ cdef union fn_caster: # Special object used for detecting misses in dict lookups. cdef object _SENTINEL = object () -cdef inline bint _is_inline_code (unsigned int code) noexcept: +cdef inline bint _is_inline_code (unsigned int code) : return code <= tpcode.FLOAT64 cdef inline size_t _get_padding (size_t off, size_t size): @@ -131,7 +131,7 @@ cdef _pack_cnum (Packer xm, int code, cnum value, bint tag): def _pack_int (Packer xm, value, tag): if INT8_MIN <= value <= INT8_MAX: - _pack_cnum[char] (xm, tpcode.INT8, value, tag) + _pack_cnum[cy.schar] (xm, tpcode.INT8, value, tag) elif INT16_MIN <= value <= INT16_MAX: _pack_cnum[short] (xm, tpcode.INT16, value, tag) elif INT32_MIN <= value <= INT32_MAX: @@ -834,7 +834,7 @@ cdef class Proxy: cdef unsigned int ilen if code == tpcode.INT8: - return _cnum_unpack[char] (self, offset, 0) + return _cnum_unpack[cy.schar] (self, offset, 0) elif code == tpcode.INT16: return _cnum_unpack[short] (self, offset, 0) elif code == tpcode.INT32: @@ -921,7 +921,7 @@ cdef class Proxy: cdef inline object _builtin_read (void *buf, Py_ssize_t pos, unsigned int code): if code == tpcode.INT8: - return (buf)[pos] + return (buf)[pos] elif code == tpcode.INT16: return (buf)[pos] elif code == tpcode.INT32: @@ -935,7 +935,7 @@ cdef inline object _builtin_read (void *buf, Py_ssize_t pos, cdef inline void _builtin_write (void *buf, Py_ssize_t pos, object obj, unsigned int code): if code == tpcode.INT8: - (buf)[pos] = obj + (buf)[pos] = obj elif code == tpcode.INT16: (buf)[pos] = obj elif code == tpcode.INT32: @@ -989,7 +989,7 @@ cdef inline object _builtin_aadd_impl (cnum *ptr, object val): cdef inline object _builtin_aadd (void *buf, Py_ssize_t pos, object val, unsigned int code): if code == tpcode.INT8: - return _builtin_aadd_impl[char] (buf + pos, val) + return _builtin_aadd_impl[cy.schar] (buf + pos, val) elif code == tpcode.INT16: return _builtin_aadd_impl[short] (buf + pos, val) elif code == tpcode.INT32: @@ -1004,7 +1004,7 @@ cdef inline object _builtin_aadd (void *buf, Py_ssize_t pos, cdef object _builtin_acas (void *buf, Py_ssize_t pos, object exp, object nval, unsigned int code): if code == tpcode.INT8: - return _builtin_acas_impl[char] (buf + pos, exp, nval) + return _builtin_acas_impl[cy.schar] (buf + pos, exp, nval) elif code == tpcode.INT16: return _builtin_acas_impl[short] (buf + pos, exp, nval) elif code == tpcode.INT32: @@ -1538,13 +1538,13 @@ cdef _ProxyStr_mul (x, y): TYPE_PATCH (ProxyStr, _ProxyStr_add, _ProxyStr_mod, _ProxyStr_mul) -cdef inline size_t _rotate_hash (size_t code, size_t nbits) noexcept: +cdef inline size_t _rotate_hash (size_t code, size_t nbits) : return (code << nbits) | (code >> (sizeof (size_t) * 8 - nbits)) -cdef inline size_t _mix_hash (size_t h1, size_t h2) noexcept: +cdef inline size_t _mix_hash (size_t h1, size_t h2) : return _rotate_hash (h1, 5) ^ h2 -cdef inline size_t _hash_buf (const void *ptr, size_t nbytes) noexcept: +cdef inline size_t _hash_buf (const void *ptr, size_t nbytes) : cdef size_t ret ret = nbytes @@ -1554,7 +1554,7 @@ cdef inline size_t _hash_buf (const void *ptr, size_t nbytes) noexcept: return ret if ret != 0 else WORD_MAX -cdef inline size_t _hash_str (str sobj) noexcept: +cdef inline size_t _hash_str (str sobj) : cdef unsigned int kind kind = STR_KIND (sobj) @@ -1562,7 +1562,7 @@ cdef inline size_t _hash_str (str sobj) noexcept: kind = 1 return _hash_buf (PyUnicode_DATA (sobj), len (sobj) * kind) -cdef inline size_t _hash_flt (double flt) noexcept: +cdef inline size_t _hash_flt (double flt) : cdef double ipart if modf (flt, &ipart) == 0: @@ -1624,7 +1624,7 @@ def xhash (obj, seed = 0): ####################################### -cdef inline Py_ssize_t _cfloat_diff (cfloat x, cfloat y) noexcept: +cdef inline Py_ssize_t _cfloat_diff (cfloat x, cfloat y) : cdef double ret ret = x - y @@ -1706,7 +1706,7 @@ cdef int _cnum_find_sorted (const unsigned char *ptr, size_t n, obj, @cy.cdivision (True) @cy.nogil -cdef size_t _find_hidx (hidx_type hidxs, size_t hval, size_t n) noexcept: +cdef size_t _find_hidx (hidx_type hidxs, size_t hval, size_t n) : cdef size_t i, step, tmp i = 0 @@ -1779,7 +1779,7 @@ cdef size_t _find_obj_by_hidx (hidx_type hidxs, size_t ix, size_t n, ################################ # Functions on sets. -cdef inline bint _cnum_lt (cnum x, cnum y) noexcept: +cdef inline bint _cnum_lt (cnum x, cnum y) : if cnum is double or cnum is float: return _cfloat_diff (x, y) < 0 else: @@ -1920,7 +1920,7 @@ cdef class ProxySet: p2 = (ix2.proxy.base + ix2.offset) if ix1.code == tpcode.INT8: - _cnum_set_union[char] (p1, ix1.size, p2, ix2.size, out, 0) + _cnum_set_union[cy.schar] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT16: _cnum_set_union[short] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT32: @@ -1950,7 +1950,7 @@ cdef class ProxySet: p2 = (ix2.proxy.base + ix2.offset) if ix1.code == tpcode.INT8: - _cnum_set_intersection[char] (p1, ix1.size, p2, ix2.size, out, 0) + _cnum_set_intersection[cy.schar] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT16: _cnum_set_intersection[short] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT32: @@ -1980,7 +1980,7 @@ cdef class ProxySet: p2 = (ix2.proxy.base + ix2.offset) if ix1.code == tpcode.INT8: - _cnum_set_difference[char] (p1, ix1.size, p2, ix2.size, out, 0) + _cnum_set_difference[cy.schar] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT16: _cnum_set_difference[short] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT32: @@ -2010,7 +2010,7 @@ cdef class ProxySet: p2 = (ix2.proxy.base + ix2.offset) if ix1.code == tpcode.INT8: - _cnum_set_symdiff[char] (p1, ix1.size, p2, ix2.size, out, 0) + _cnum_set_symdiff[cy.schar] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT16: _cnum_set_symdiff[short] (p1, ix1.size, p2, ix2.size, out, 0) elif ix1.code == tpcode.INT32: @@ -2042,7 +2042,7 @@ cdef class ProxySet: ptr = (proxy.base + indices.offset) if code == tpcode.INT8: - return _cnum_find_sorted[char] (ptr, n, value, 0, 0) + return _cnum_find_sorted[cy.schar] (ptr, n, value, 0, 0) elif code == tpcode.INT16: return _cnum_find_sorted[short] (ptr, n, value, 0, 0) elif code == tpcode.INT32: @@ -2211,7 +2211,7 @@ cdef class ProxySet: if ix1.size > ix2.size: ret = False elif self.indices.code == tpcode.INT8: - ret = _cnum_set_includes[char] (p2, ix2.size, p1, ix1.size, 0) + ret = _cnum_set_includes[cy.schar] (p2, ix2.size, p1, ix1.size, 0) elif self.indices.code == tpcode.INT16: ret = _cnum_set_includes[short] (p2, ix2.size, p1, ix1.size, 0) elif self.indices.code == tpcode.INT32: