From bb630dc419c5f725aa87d9563d23de832104b44b Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Thu, 9 Jan 2025 09:13:46 +0100 Subject: [PATCH] Remove build and support for Python 2 and Python3 < 3.8. Closes https://github.com/scoder/lupa/issues/276 Closes https://github.com/scoder/lupa/issues/267 Closes https://github.com/scoder/lupa/pull/277 --- .github/workflows/ci.yml | 38 +++---------------- .github/workflows/wheels.yml | 73 ++---------------------------------- lupa/_lupa.pyx | 60 +++++++---------------------- lupa/lock.pxi | 10 ----- setup.py | 40 -------------------- 5 files changed, 23 insertions(+), 198 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b465542..9cd1dd7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,19 +12,16 @@ jobs: matrix: os: - windows-2019 - - ubuntu-20.04 + - ubuntu-latest - macos-latest python-version: - - "2.7" + - "3.14-dev" + - "3.13" - "3.12" - "3.11" - "3.10" - "3.9" - "3.8" - - "3.7" - - "3.6" - - "pypy-2.7" - - "pypy-3.7" - "pypy-3.8" - "pypy-3.9" - "pypy-3.10" @@ -35,10 +32,6 @@ jobs: - "luajit-5.1" exclude: - - os: windows-2019 - python-version: "2.7" - - os: windows-2019 - python-version: pypy-2.7 - os: windows-2019 lua-version: lua5.2 - os: windows-2019 @@ -48,15 +41,6 @@ jobs: - os: windows-2019 lua-version: luajit-5.1 - - os: macos-latest - python-version: "2.7" - - os: macos-latest - python-version: "3.6" - - os: macos-latest - python-version: "3.7" - - os: macos-latest - python-version: pypy-3.7 - - os: macos-latest lua-version: lua5.2 - os: macos-latest @@ -81,25 +65,13 @@ jobs: run: git submodule update --init --recursive - name: Set up Python ${{ matrix.python-version }} - if: startsWith(matrix.python-version, '3.') || startsWith(matrix.python-version, 'pypy') || !startsWith(matrix.os, 'ubuntu') uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - name: Set up Python2 (Linux) - if: matrix.python-version == '2.7' && startsWith(matrix.os, 'ubuntu') - run: | - sudo ln -fs python2 /usr/bin/python - sudo apt-get update - sudo apt-get install python-setuptools python2.7 python2.7-dev - curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py - sudo python2 get-pip.py - ls -l /usr/bin/pip* /usr/local/bin/pip* - which pip - - name: Set up Python packages run: | - python -m pip install -U ${{ startsWith(matrix.python-version, '2.7') && '"pip<21" "setuptools<45"' || 'pip setuptools' }} + python -m pip install -U pip setuptools python -m pip install -U wheel tox virtualenv -r requirements.txt - name: Set up Lua ${{ matrix.lua-version }} @@ -107,7 +79,7 @@ jobs: run: sudo apt-get install lib${{ matrix.lua-version }}-dev - name: Build wheel - run: python setup.py sdist ${{ contains(matrix.python-version, '3.') && 'build_ext -j6' || '' }} bdist_wheel + run: python setup.py sdist build_ext -j6 bdist_wheel env: SETUP_OPTIONS: ${{ !contains(matrix.lua-version, 'luajit') && (contains(matrix.lua-version, 'bundle') && '--use-bundle' || '--no-luajit') || '' }} CFLAGS: ${{ env.CFLAGS }} ${{ env.CFLAGS_LTO }} diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index b6a0a926..ce47b51e 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -40,7 +40,7 @@ permissions: {} jobs: sdist: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest permissions: contents: write # to create GitHub release (softprops/action-gh-release) @@ -80,7 +80,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Install cibuildwheel # Nb. keep cibuildwheel version pin consistent with job below - run: pipx install cibuildwheel==2.16.5 + run: pipx install cibuildwheel==2.22.0 - id: set-matrix run: | MATRIX=$( @@ -129,7 +129,7 @@ jobs: ln -s /usr/local/bin/glibtoolize /usr/local/bin/libtoolize - name: Build wheels - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.22.0 with: only: ${{ matrix.only }} @@ -195,7 +195,7 @@ jobs: - name: Set up Python uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 with: - python-version: "3.9" + python-version: "3.12" - name: Install dependencies run: python -m pip install -r requirements.txt @@ -210,68 +210,3 @@ jobs: name: wheels-${{ matrix.image }} path: wheelhouse_*/*-m*linux*.whl # manylinux / musllinux if-no-files-found: ignore - - non-Linux: - strategy: - # Allows for matrix sub-jobs to fail without canceling the rest - fail-fast: false - - matrix: - os: - - macos-13 - #- windows-2019 - pyversion: - - "2.7" - - "3.6" - #- "pypy-3.7-v7.3.7" - #- "pypy-3.8-v7.3.7" - #- "pypy-3.9-v7.3.11" - #- "pypy-3.10-v7.3.13" - - exclude: - # outdated compilers and probably not worth supporting anymore - - os: windows-2019 - pyversion: "2.7" - - runs-on: ${{ matrix.os }} - env: - USE_BUNDLE: "true" - MACOSX_DEPLOYMENT_TARGET: "11.0" - LUPA_WITH_LUA_DLOPEN: ${{ startsWith(matrix.os, 'windows') && 'false' || 'true' }} - PYTHON_BIN_DIR: ${{ startsWith(matrix.pyversion, '2.') && '/Library/Frameworks/Python.framework/Versions/2.7/bin' || '' }} - - steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - - - name: Check out recursively - run: git submodule update --init --recursive - - - name: Set up Python - uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 - # macOS has Py2.7 installed system wide - if: matrix.pyversion != '2.7' - with: - python-version: ${{ matrix.pyversion }} - - - name: Install MacOS dependencies - if: startsWith(matrix.os, 'mac') - run: | - brew install automake libtool - ln -s /usr/local/bin/glibtoolize /usr/local/bin/libtoolize - - - name: Install dependencies - run: | - export PATH=$PYTHON_BIN_DIR:$PATH - python -m pip install setuptools wheel -r requirements.txt - - - name: Build wheels - run: | - export PATH=$PYTHON_BIN_DIR:$PATH - python setup.py --with-cython sdist ${{ contains(matrix.pyversion, '3.') && 'build_ext -j6' || '' }} bdist_wheel - - - name: Upload wheels - uses: actions/upload-artifact@694cdabd8bdb0f10b2cea11669e1bf5453eed0a6 # v4.2.0 - with: - name: wheels-${{ matrix.pyversion }}-${{ matrix.os }} - path: dist/*.whl - if-no-files-found: ignore diff --git a/lupa/_lupa.pyx b/lupa/_lupa.pyx index 935b9011..8f4f73f5 100644 --- a/lupa/_lupa.pyx +++ b/lupa/_lupa.pyx @@ -24,20 +24,7 @@ from cpython.method cimport ( from cpython.bytes cimport PyBytes_FromFormat #from libc.stdint cimport uintptr_t -cdef extern from *: - """ - #if PY_VERSION_HEX < 0x03040000 && defined(_MSC_VER) - #ifndef _MSC_STDINT_H_ - #ifdef _WIN64 // [ - typedef unsigned __int64 uintptr_t; - #else // _WIN64 ][ - typedef _W64 unsigned int uintptr_t; - #endif // _WIN64 ] - #endif - #else - #include - #endif - """ +cdef extern from "stdint.h": ctypedef size_t uintptr_t cdef const Py_ssize_t PY_SSIZE_T_MAX cdef const char CHAR_MIN, CHAR_MAX @@ -51,10 +38,7 @@ from sys import exc_info cdef object Mapping cdef object Sequence -try: - from collections.abc import Mapping, Sequence -except ImportError: - from collections import Mapping, Sequence # Py2 +from collections.abc import Mapping, Sequence cdef object wraps from functools import wraps @@ -75,12 +59,6 @@ DEF POBJECT = b"POBJECT" # as used by LunaticPython DEF LUPAOFH = b"LUPA_NUMBER_OVERFLOW_CALLBACK_FUNCTION" DEF PYREFST = b"LUPA_PYTHON_REFERENCES_TABLE" -cdef extern from *: - """ - #define IS_PY2 (PY_MAJOR_VERSION == 2) - """ - int IS_PY2 - cdef enum WrappedObjectFlags: # flags that determine the behaviour of a wrapped object: OBJ_AS_INDEX = 1 # prefers the getitem protocol (over getattr) @@ -165,7 +143,7 @@ def lua_type(obj): return 'userdata' else: lua_type_name = lua.lua_typename(L, ltype) - return lua_type_name if IS_PY2 else lua_type_name.decode('ascii') + return lua_type_name.decode('ascii') finally: lua.lua_settop(L, old_top) unlock_runtime(lua_object._runtime) @@ -235,7 +213,7 @@ cdef class LuaRuntime: Normally, it should return the now well-behaved object that can be converted/wrapped to a Lua type. If the object cannot be precisely represented in Lua, it should raise an ``OverflowError``. - + * ``max_memory``: max memory usage this LuaRuntime can use in bytes. If max_memory is None, the default lua allocator is used and calls to ``set_max_memory(limit)`` will fail with a ``LuaMemoryError``. @@ -656,12 +634,12 @@ cdef class LuaRuntime: luaL_openlib(L, "python", py_lib, 0) # lib lua.lua_pushlightuserdata(L, self) # lib udata lua.lua_pushcclosure(L, py_args, 1) # lib function - lua.lua_setfield(L, -2, "args") # lib + lua.lua_setfield(L, -2, "args") # lib # register our own object metatable lua.luaL_newmetatable(L, POBJECT) # lib metatbl luaL_openlib(L, NULL, py_object_lib, 0) - lua.lua_pop(L, 1) # lib + lua.lua_pop(L, 1) # lib # create and store the python references table lua.lua_newtable(L) # lib tbl @@ -669,7 +647,7 @@ cdef class LuaRuntime: lua.lua_pushlstring(L, "v", 1) # lib tbl metatbl "v" lua.lua_setfield(L, -2, "__mode") # lib tbl metatbl lua.lua_setmetatable(L, -2) # lib tbl - lua.lua_setfield(L, lua.LUA_REGISTRYINDEX, PYREFST) # lib + lua.lua_setfield(L, lua.LUA_REGISTRYINDEX, PYREFST) # lib # register global names in the module self.register_py_object(b'Py_None', b'none', None) @@ -818,17 +796,14 @@ cdef tuple unpack_lua_table(LuaRuntime runtime, lua_State* L): while lua.lua_next(L, -2): # key value key = py_from_lua(runtime, L, -2) value = py_from_lua(runtime, L, -1) - if isinstance(key, (int, long)) and not isinstance(key, bool): + if isinstance(key, int) and not isinstance(key, bool): index = key if index < 1 or index > length: raise IndexError("table index out of range") cpython.ref.Py_INCREF(value) cpython.tuple.PyTuple_SET_ITEM(args, index-1, value) elif isinstance(key, bytes): - if IS_PY2: - kwargs[key] = value - else: - kwargs[(key).decode(source_encoding)] = value + kwargs[(key).decode(source_encoding)] = value elif isinstance(key, unicode): kwargs[key] = value else: @@ -1508,21 +1483,14 @@ cdef object py_from_lua(LuaRuntime runtime, lua_State *L, int n): elif lua_type == lua.LUA_TNUMBER: if lua.LUA_VERSION_NUM >= 503: if lua.lua_isinteger(L, n): - integer = lua.lua_tointeger(L, n) - if IS_PY2 and (sizeof(lua.lua_Integer) <= sizeof(long) or LONG_MIN <= integer <= LONG_MAX): - return integer - else: - return integer + return lua.lua_tointeger(L, n) else: return lua.lua_tonumber(L, n) else: number = lua.lua_tonumber(L, n) integer = number if number == integer: - if IS_PY2 and (sizeof(lua.lua_Integer) <= sizeof(long) or LONG_MIN <= integer <= LONG_MAX): - return integer - else: - return integer + return integer else: return number elif lua_type == lua.LUA_TSTRING: @@ -1632,7 +1600,7 @@ cdef int py_to_lua(LuaRuntime runtime, lua_State *L, object o, bint wrap_none=Fa elif type(o) is float: lua.lua_pushnumber(L, cpython.float.PyFloat_AS_DOUBLE(o)) pushed_values_count = 1 - elif isinstance(o, (long, int)): + elif isinstance(o, int): try: lua.lua_pushinteger(L, o) pushed_values_count = 1 @@ -2013,7 +1981,7 @@ cdef void* _lua_alloc_restricted(void* ud, void* ptr, size_t old_size, size_t ne return NULL elif new_size == old_size: return ptr - + if memory_status.limit > 0 and new_size > old_size and memory_status.limit <= memory_status.used + new_size - old_size: # reached the limit # print("REACHED LIMIT") return NULL @@ -2085,7 +2053,7 @@ cdef int py_object_gc_with_gil(py_object *py_obj, lua_State* L) noexcept with gi return 0 finally: py_obj.obj = NULL - + cdef int py_object_gc(lua_State* L) noexcept nogil: if not lua.lua_isuserdata(L, 1): return 0 diff --git a/lupa/lock.pxi b/lupa/lock.pxi index 2dcc47f9..4cdf5d2c 100644 --- a/lupa/lock.pxi +++ b/lupa/lock.pxi @@ -2,19 +2,9 @@ from cpython cimport pythread cdef extern from *: - # Compatibility definitions for Python """ - #if PY_VERSION_HEX >= 0x030700a2 typedef unsigned long pythread_t; - #else - typedef long pythread_t; - #endif """ - - # Just let Cython understand that pythread_t is - # a long type, but be aware that it is actually - # signed for versions of Python prior to 3.7.0a2 and - # unsigned for later versions ctypedef unsigned long pythread_t diff --git a/setup.py b/setup.py index a54313a7..011a851e 100644 --- a/setup.py +++ b/setup.py @@ -75,8 +75,6 @@ def cmd_output(command): def decode_path_output(s): - if sys.version_info[0] < 3: - return s # no need to decode, and safer not to do it # we don't really know in which encoding pkgconfig # outputs its results, so we try to guess for encoding in (sys.getfilesystemencoding(), @@ -422,34 +420,6 @@ def prepare_extensions(use_cython=True): if cythonize is not None: ext_modules = cythonize(ext_modules) - # Fix compiler warning due to missing pragma-push in Cython 3.0.9. - for ext in ext_modules: - for source_file in ext.sources: - if not os.path.basename(source_file).startswith('lua') or not source_file.endswith('.c'): - continue - with open(source_file, 'rb') as f: - lines = f.readlines() - if b'Generated by Cython 3.0.9' not in lines[0]: - continue - - modified = False - temp_file = source_file + ".tmp" - with open(temp_file, 'wb') as f: - last_was_push = False - for line in lines: - if b'#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"' in line and not last_was_push: - f.write(b"#pragma GCC diagnostic push\n") - modified = True - last_was_push = b'#pragma GCC diagnostic push' in line - f.write(line) - - if modified: - print("Fixed Cython 3.0.9 generated source file " + source_file) - os.unlink(source_file) - os.rename(temp_file, source_file) - else: - os.unlink(temp_file) - return ext_modules, ext_libraries @@ -509,17 +479,7 @@ def write_file(filename, content): 'Intended Audience :: Information Technology', 'License :: OSI Approved :: MIT License', 'Programming Language :: Cython', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', 'Programming Language :: Lua', 'Programming Language :: Other Scripting Engines', 'Operating System :: OS Independent',