Skip to content

Commit

Permalink
Added support for PyPy building
Browse files Browse the repository at this point in the history
  • Loading branch information
igorcoding committed Aug 13, 2023
1 parent d1a9cc5 commit 6722f5b
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 39 deletions.
30 changes: 15 additions & 15 deletions .github/workflows/actions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ jobs:
strategy:
matrix:
os: [ ubuntu-latest, macos-latest ]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy3.10']
tarantool: ['1.10', '2']
exclude:
- os: macos-latest
tarantool: '1.10'
- os: macos-latest
tarantool: '2.7'
- python-version: 'pypy3.10'
tarantool: '1.10'

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install Tarantool ${{ matrix.tarantool }}
Expand Down Expand Up @@ -62,21 +62,21 @@ jobs:
- test

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive

- uses: actions/setup-python@v2
- uses: actions/setup-python@v4

- name: Install cibuildwheel
run: python -m pip install --upgrade cibuildwheel

- name: Build wheels
run: python -m cibuildwheel --output-dir wheelhouse
env:
CIBW_BUILD: "cp37-* cp38-* cp39-* cp310-* cp311-*"
CIBW_BUILD: "cp37-* cp38-* cp39-* cp310-* cp311-* pp310-*"

- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: wheels
path: ./wheelhouse/*.whl
Expand All @@ -92,19 +92,19 @@ jobs:
id: get_tag
run: echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
- run: echo "Current tag is ${{ steps.get_tag.outputs.TAG }}"
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: '3.10'

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel twine build
- uses: actions/download-artifact@v2
- uses: actions/download-artifact@v3
with:
name: wheels
path: wheels
Expand Down Expand Up @@ -133,12 +133,12 @@ jobs:
needs:
- test
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: '3.11'

Expand All @@ -151,7 +151,7 @@ jobs:
run: make docs

- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.4
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: gh-pages
folder: docs/_build/html
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
* Dropped support for Python 3.6

**New features:**
* Added building wheels for Python 3.11 and 3.12
* Added building wheels for Python 3.11 and initial support for 3.12
* Added support for PyPy 3.10. It's compiling and working, but there is an obvious performance downgrade compared to CPython.
* Now repr() of TarantoolTuple objects is being truncated to 50 fields

**Bug fixes:**
* Fixed an issue with encoding of update operations as tuples on PyPy
Expand All @@ -14,6 +16,7 @@
* Upgraded to Cython 3.0.0
* Using pyproject.toml for building spec
* Using black, isort & ruff for linting
* _testbase.py was moved to tests/_testbase.py

## v2.0.1
* Fixed an issue with encoding datetimes less than 01-01-1970 (fixes [#29](https://github.com/igorcoding/asynctnt/issues/29))
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ local:


debug: clean
ASYNCTNT_DEBUG=1 $(PYTHON) -m pip install -e .
ASYNCTNT_DEBUG=1 $(PYTHON) -m pip install -e '.[test]'


annotate:
Expand Down
2 changes: 1 addition & 1 deletion asynctnt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
TarantoolTuple,
)

__version__ = "2.1.0"
__version__ = "2.1.0a1"
94 changes: 84 additions & 10 deletions asynctnt/iproto/tupleobj/tupleobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,18 @@ ttuple_repr(AtntTupleObject *v)
{
Py_ssize_t i, n;
PyObject *keys_iter = NULL;
_PyUnicodeWriter writer;
int oversize = 0;

n = Py_SIZE(v);
if (n == 0) {
return PyUnicode_FromString("<TarantoolTuple>");
}

if (n >= 50) {
n = 50;
oversize = 1;
}

if (v->metadata != NULL) {
keys_iter = PyObject_GetIter(v->metadata->names);
if (keys_iter == NULL) {
Expand All @@ -384,6 +389,22 @@ ttuple_repr(AtntTupleObject *v)
return i > 0 ? PyUnicode_FromString("<TarantoolTuple ...>") : NULL;
}

#if defined(PYPY_VERSION)

// we must have a separate implementation for PyPy because _PyUnicodeWriter is a private API
// it may become available in the future, but for now we have to use a workaround
// by building strings using only public API
// but this may change in future and _PyUnicodeWriter will become public:
// https://github.com/python/cpython/issues/107076#issuecomment-1646840936

PyObject *part = NULL;
PyObject *parts = PyList_New(n);
if (parts == NULL) {
goto error;
}

#else
_PyUnicodeWriter writer;
_PyUnicodeWriter_Init(&writer);
writer.overallocate = 1;
writer.min_length = 12; /* <TarantoolTuple a=1> */
Expand All @@ -392,18 +413,14 @@ ttuple_repr(AtntTupleObject *v)
goto error;
}

#endif

for (i = 0; i < n; ++i) {
PyObject *key = NULL;
PyObject *key_repr = NULL;
PyObject *val_repr = NULL;
PyObject *i_obj = NULL;

if (i > 0) {
if (_PyUnicodeWriter_WriteChar(&writer, ' ') < 0) {
goto error;
}
}

if (Py_EnterRecursiveCall(" while getting the repr of a tarantool tuple")) {
goto error;
}
Expand Down Expand Up @@ -433,6 +450,25 @@ ttuple_repr(AtntTupleObject *v)
}
}

#if defined(PYPY_VERSION)

part = PyUnicode_FromFormat("%U=%U", key_repr, val_repr);
if (part == NULL) {
Py_DECREF(key_repr);
Py_DECREF(val_repr);
goto error;
}
PyList_SET_ITEM(parts, i, part);

#else
if (i > 0) {
if (_PyUnicodeWriter_WriteChar(&writer, ' ') < 0) {
Py_DECREF(key_repr);
Py_DECREF(val_repr);
goto error;
}
}

if (_PyUnicodeWriter_WriteStr(&writer, key_repr) < 0) {
Py_DECREF(key_repr);
Py_DECREF(val_repr);
Expand All @@ -450,20 +486,58 @@ ttuple_repr(AtntTupleObject *v)
goto error;
}
Py_DECREF(val_repr);
#endif
}

writer.overallocate = 0;
if (_PyUnicodeWriter_WriteChar(&writer, '>') < 0) {
PyObject *result = NULL;

#if defined(PYPY_VERSION)
PyObject *space = NULL;
PyObject *parts_joined = NULL;

space = PyUnicode_FromString(" ");
if (space == NULL) {
goto error;
}
parts_joined = PyUnicode_Join(space, parts);
if (parts_joined == NULL) {
Py_DECREF(space);
goto error;
}
Py_DECREF(space);
Py_XDECREF(parts);

if (oversize) {
result = PyUnicode_FromFormat("<TarantoolTuple %U ...>", parts_joined);
} else {
result = PyUnicode_FromFormat("<TarantoolTuple %U>", parts_joined);
}
Py_XDECREF(parts_joined);
#else
writer.overallocate = 0;
if (oversize) {
if (_PyUnicodeWriter_WriteASCIIString(&writer, " ...>", 5) < 0) {
goto error;
}
} else {
if (_PyUnicodeWriter_WriteChar(&writer, '>') < 0) {
goto error;
}
}
result = _PyUnicodeWriter_Finish(&writer);
#endif

Py_XDECREF(keys_iter);
Py_ReprLeave((PyObject *)v);
return _PyUnicodeWriter_Finish(&writer);
return result;

error:
Py_XDECREF(keys_iter);
#if defined(PYPY_VERSION)
Py_XDECREF(parts);
#else
_PyUnicodeWriter_Dealloc(&writer);
#endif
Py_ReprLeave((PyObject *)v);
return NULL;
}
Expand Down
10 changes: 7 additions & 3 deletions bench/benchmark.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ def main():
["execute", ["select 1 as a, 2 as b"], {"parse_metadata": False}],
]

for use_uvloop in [True]:
for use_uvloop in [False, True]:
if use_uvloop:
import uvloop
try:
import uvloop
except ImportError:
print("No uvloop installed. Skipping.")
continue

asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
else:
Expand Down Expand Up @@ -77,7 +81,7 @@ async def bulk_f():
await getattr(conn, method)(*args, **kwargs)

start = datetime.datetime.now()
coros = [bulk_f() for _ in range(b)]
coros = [asyncio.create_task(bulk_f()) for _ in range(b)]

await asyncio.wait(coros)
end = datetime.datetime.now()
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ test = [
'isort',
'black',
'ruff',
'uvloop>=0.12.3; platform_system != "Windows"',
'uvloop>=0.12.3; platform_system != "Windows" and python_version < "3.12" and platform.python_implementation != "PyPy"',
'pytest',
'pytest-cov',
'coverage[toml]',
'pytz',
'python-dateutil',
"Cython(>=3.0.0,<3.1.0)", # for coverage
]

docs = [
Expand Down
2 changes: 1 addition & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
import unittest

from asynctnt._testbase import TarantoolTestCase
from ._testbase import TarantoolTestCase

CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion tests/test_connect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import uuid

import asynctnt
from asynctnt._testbase import check_version
from asynctnt.connection import ConnectionState
from asynctnt.exceptions import (
ErrorCode,
Expand All @@ -11,6 +10,7 @@
)
from asynctnt.instance import TarantoolSyncInstance
from tests import BaseTarantoolTestCase
from tests._testbase import check_version


class ConnectTestCase(BaseTarantoolTestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_mp_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import pytz

from asynctnt import IProtoError
from asynctnt._testbase import ensure_version
from asynctnt.exceptions import ErrorCode, TarantoolDatabaseError
from tests import BaseTarantoolTestCase
from tests._testbase import ensure_version


class MpExtTestCase(BaseTarantoolTestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_op_push.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import asynctnt
from asynctnt import PushIterator, Response
from asynctnt._testbase import ensure_version
from asynctnt.exceptions import TarantoolDatabaseError, TarantoolNotConnectedError
from tests import BaseTarantoolTestCase
from tests._testbase import ensure_version


class PushTestCase(BaseTarantoolTestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_op_sql_execute.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from asynctnt import Response
from asynctnt._testbase import ensure_version
from tests import BaseTarantoolTestCase
from tests._testbase import ensure_version


class SQLExecuteTestCase(BaseTarantoolTestCase):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_op_sql_prepared.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from asynctnt import Response
from asynctnt._testbase import ensure_version
from asynctnt.prepared import PreparedStatement
from tests import BaseTarantoolTestCase
from tests._testbase import ensure_version


class SQLPreparedStatementTestCase(BaseTarantoolTestCase):
Expand Down
Loading

0 comments on commit 6722f5b

Please sign in to comment.