diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index ae2d574..62ee5c5 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -19,15 +19,15 @@ permissions: jobs: linux: name: Build for Linux - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -52,12 +52,12 @@ jobs: runs-on: windows-2019 strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -82,12 +82,12 @@ jobs: runs-on: macos-11 strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/python-test-linux.yml b/.github/workflows/python-test-linux.yml index 1f2f564..bc1c9c5 100644 --- a/.github/workflows/python-test-linux.yml +++ b/.github/workflows/python-test-linux.yml @@ -10,17 +10,49 @@ on: branches: [ "main" ] jobs: + build-legacy: + runs-on: ubuntu-20.04 + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.8", "3.9"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install flake8 pytest build + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --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 + - name: Build package + run: | + python -m build + pip install dist/*.whl + - name: Test with pytest + run: | + python -m pip install typing-extensions + pytest + build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/python-test-macos.yml b/.github/workflows/python-test-macos.yml index 5be5445..55d5488 100644 --- a/.github/workflows/python-test-macos.yml +++ b/.github/workflows/python-test-macos.yml @@ -10,17 +10,49 @@ on: branches: [ "main" ] jobs: + build-legacy: + runs-on: macos-15-intel + strategy: + fail-fast: false + matrix: + python-version: ["3.7", "3.8", "3.9"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install flake8 pytest build + - name: Lint with flake8 + run: | + # stop the build if there are Python syntax errors or undefined names + flake8 . --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 + - name: Build package + run: | + python -m build + pip install dist/*.whl + - name: Test with pytest + run: | + python -m pip install typing-extensions + pytest + build: runs-on: macos-latest strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/python-test-windows.yml b/.github/workflows/python-test-windows.yml index b75374a..eb3545b 100644 --- a/.github/workflows/python-test-windows.yml +++ b/.github/workflows/python-test-windows.yml @@ -15,12 +15,12 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/pyproject.toml b/pyproject.toml index e4e7076..d806e6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,6 @@ [build-system] -requires = [ - # mesonpy, version 0.13.0 which isn't released yet - "meson-python @ git+https://github.com/mesonbuild/meson-python.git@61bb2b3315f4e312558778022ca6e87ffaed2700", -] -build-backend = 'mesonpy' +build-backend = "mesonpy" +requires = ["meson-python"] [project] name = "extype" @@ -19,3 +16,11 @@ dynamic = ["version"] [tool.cibuildwheel] skip = "pp*" build-frontend = "build" + +[dependency-groups] +dev = [ + "meson>=1.10.1", + "meson-python>=0.17.1", + "ninja>=1.11.1.4", +] +test = ["pytest>=7.4.4", "typing-extensions>=4.7.1"] diff --git a/src/extype/core.pyi b/src/extype/core.pyi index 59e8468..4f8804d 100644 --- a/src/extype/core.pyi +++ b/src/extype/core.pyi @@ -1,11 +1,16 @@ -from typing import Type, Dict, Any -from . import Protocol +from typing import Type, Dict, Any, TYPE_CHECKING +if TYPE_CHECKING: + from .extension_utils import Protocol def get_type_dict(typ: Type) -> Dict[str, Any]: ... -def implement_protocol_on_type(typ: Type, protocols: Protocol): ... +def implement_protocol_on_type(typ: Type, protocols: "Protocol"): ... def enable_magic_method(typ: Type, method: str): ... + + +if TYPE_CHECKING: + del Protocol diff --git a/src/extype/extype.cpp b/src/extype/extype.cpp index 601b71f..671ccde 100644 --- a/src/extype/extype.cpp +++ b/src/extype/extype.cpp @@ -275,8 +275,24 @@ static PyObject *get_type_dict(PyObject *self, PyObject *args) PyTypeObject *type; PyArg_ParseTuple(args, "O", &type); - Py_INCREF(type->tp_dict); - return type->tp_dict; +#if PY_VERSION_HEX >= 0x030C0000 + + auto dict = PyType_GetDict(type); + +#else + + auto dict = type->tp_dict; + +#endif + + if (dict == NULL) + { + PyErr_SetString(PyExc_RuntimeError, "type dict was null"); + return NULL; + } + + Py_INCREF(dict); + return dict; } static MagicMethodLookupResult get_magic_method_slot(PyTypeObject *type, char const *name_str) @@ -563,6 +579,7 @@ static PyObject *enable_magic_method(PyObject *self, PyObject *args) if (slot == NULL) { + PyErr_SetString(PyExc_RuntimeError, "slot was null"); PyErr_SetString(PyExc_RuntimeError, "slot was null"); return NULL; } diff --git a/test.py b/test.py index 5c5fc82..354927e 100644 --- a/test.py +++ b/test.py @@ -1,5 +1,6 @@ from extype.core import * -from extype import extension, extend_type_with, Protocol +from extype.extension_utils import Protocol +from extype import extension, extend_type_with def _(): diff --git a/tests/test_protocol_detection.py b/tests/test_protocol_detection.py index 8612fc7..8331a87 100644 --- a/tests/test_protocol_detection.py +++ b/tests/test_protocol_detection.py @@ -1,4 +1,4 @@ -from extype import * +from extype import extension, extend_type_with def test_length_function():