diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 0714f1176e9..7efa2196cb5 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -47,7 +47,7 @@ jobs: make sync-direct-runtime-deps git diff --exit-code -- requirements/runtime-deps.in - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.11 - name: Cache PyPI @@ -166,7 +166,7 @@ jobs: submodules: true - name: Setup Python ${{ matrix.pyver }} id: python-install - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: allow-prereleases: true python-version: ${{ matrix.pyver }} @@ -265,7 +265,7 @@ jobs: submodules: true - name: Setup Python 3.13.2 id: python-install - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.13.2 cache: pip @@ -332,7 +332,7 @@ jobs: with: submodules: true - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 - name: Update pip, wheel, setuptools, build, twine run: | python -m pip install -U pip wheel setuptools build twine @@ -423,7 +423,7 @@ jobs: fi shell: bash - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Update pip, wheel, setuptools, build, twine diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index ef1b86cfa69..8a56a2b7b80 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: days-before-stale: 30 any-of-labels: needs-info diff --git a/.github/workflows/update-pre-commit.yml b/.github/workflows/update-pre-commit.yml index e2426524529..4616f7abc7d 100644 --- a/.github/workflows/update-pre-commit.yml +++ b/.github/workflows/update-pre-commit.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v5 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.9 - name: Install dependencies diff --git a/CHANGES/11464.feature.rst b/CHANGES/11464.feature.rst new file mode 100644 index 00000000000..12ebf117883 --- /dev/null +++ b/CHANGES/11464.feature.rst @@ -0,0 +1 @@ +Implemented support for free-threading builds of CPython -- by :user:`kumaraditya303`. diff --git a/Makefile b/Makefile index dc49c1592ff..099d1cf0af1 100644 --- a/Makefile +++ b/Makefile @@ -59,14 +59,14 @@ aiohttp/_find_header.c: $(call to-hash,aiohttp/hdrs.py ./tools/gen.py) # Special case for reader since we want to be able to disable # the extension with AIOHTTP_NO_EXTENSIONS aiohttp/_websocket/reader_c.c: aiohttp/_websocket/reader_c.py - cython -3 -o $@ $< -I aiohttp -Werror + cython -3 -X freethreading_compatible=True -o $@ $< -I aiohttp -Werror # _find_headers generator creates _headers.pyi as well aiohttp/%.c: aiohttp/%.pyx $(call to-hash,$(CYS)) aiohttp/_find_header.c - cython -3 -o $@ $< -I aiohttp -Werror + cython -3 -X freethreading_compatible=True -o $@ $< -I aiohttp -Werror aiohttp/_websocket/%.c: aiohttp/_websocket/%.pyx $(call to-hash,$(CYS)) - cython -3 -o $@ $< -I aiohttp -Werror + cython -3 -X freethreading_compatible=True -o $@ $< -I aiohttp -Werror vendor/llhttp/node_modules: vendor/llhttp/package.json cd vendor/llhttp; npm ci diff --git a/aiohttp/_http_parser.pyx b/aiohttp/_http_parser.pyx index f5015b297b0..d35b07d0a49 100644 --- a/aiohttp/_http_parser.pyx +++ b/aiohttp/_http_parser.pyx @@ -1,5 +1,3 @@ -#cython: language_level=3 -# # Based on https://github.com/MagicStack/httptools # diff --git a/aiohttp/_http_writer.pyx b/aiohttp/_http_writer.pyx index 4a3ae1f9e68..7989c186c89 100644 --- a/aiohttp/_http_writer.pyx +++ b/aiohttp/_http_writer.pyx @@ -8,7 +8,6 @@ from libc.string cimport memcpy from multidict import istr DEF BUF_SIZE = 16 * 1024 # 16KiB -cdef char BUFFER[BUF_SIZE] cdef object _istr = istr @@ -19,16 +18,17 @@ cdef struct Writer: char *buf Py_ssize_t size Py_ssize_t pos + bint heap_allocated - -cdef inline void _init_writer(Writer* writer): - writer.buf = &BUFFER[0] +cdef inline void _init_writer(Writer* writer, char *buf): + writer.buf = buf writer.size = BUF_SIZE writer.pos = 0 + writer.heap_allocated = 0 cdef inline void _release_writer(Writer* writer): - if writer.buf != BUFFER: + if writer.heap_allocated: PyMem_Free(writer.buf) @@ -39,7 +39,7 @@ cdef inline int _write_byte(Writer* writer, uint8_t ch): if writer.pos == writer.size: # reallocate size = writer.size + BUF_SIZE - if writer.buf == BUFFER: + if not writer.heap_allocated: buf = PyMem_Malloc(size) if buf == NULL: PyErr_NoMemory() @@ -52,6 +52,7 @@ cdef inline int _write_byte(Writer* writer, uint8_t ch): return -1 writer.buf = buf writer.size = size + writer.heap_allocated = 1 writer.buf[writer.pos] = ch writer.pos += 1 return 0 @@ -125,8 +126,9 @@ def _serialize_headers(str status_line, headers): cdef Writer writer cdef object key cdef object val + cdef char buf[BUF_SIZE] - _init_writer(&writer) + _init_writer(&writer, buf) try: if _write_str(&writer, status_line) < 0: