Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python - build abi3 wheels in cibuildwheel #1206

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ include c/enc/*.h
include c/include/brotli/*.h
include LICENSE
include MANIFEST.in
include python/_brotli.cc
include python/_brotli.c
K0lb3 marked this conversation as resolved.
Show resolved Hide resolved
include python/bro.py
include python/brotli.py
include python/brotli.pyi
include python/py.typed
include python/README.md
include python/tests/*
include README.md
Expand Down
113 changes: 107 additions & 6 deletions python/_brotli.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@
#if PY_MAJOR_VERSION >= 3
#define PyInt_Check PyLong_Check
#define PyInt_AsLong PyLong_AsLong

#ifdef Py_LIMITED_API
// macro functions are version specific and therefore not compatible with the stable api
// therefore we map them here to the functions
#define PyList_GET_ITEM PyList_GetItem
#define PyList_SET_ITEM PyList_SetItem
#define PyBytes_AS_STRING PyBytes_AsString
// Py_buffer is only available in stable api 3.10+
// as we want to support 3.6+ we need to define a dummy struct
// to not break compatibility with Python 2
// len is of type int, as Py_ssize_t clean is 3.7+
typedef struct {
void *buf;
int len;
} Py_buffer;
static void PyBuffer_Release(Py_buffer *view) {
view->buf = NULL;
view->len = -1;
}
#endif
#else
#define Py_ARRAY_LENGTH(array) (sizeof(array) / sizeof((array)[0]))
#endif
Expand Down Expand Up @@ -356,12 +376,17 @@ typedef struct {
static void brotli_Compressor_dealloc(brotli_Compressor* self) {
BrotliEncoderDestroyInstance(self->enc);
#if PY_MAJOR_VERSION >= 3
#ifdef Py_LIMITED_API
PyObject_Del((PyObject*)self);
#else
Py_TYPE(self)->tp_free((PyObject*)self);
#endif
#else
self->ob_type->tp_free((PyObject*)self);
#endif
}

#ifndef Py_LIMITED_API
static PyObject* brotli_Compressor_new(PyTypeObject *type, PyObject *args, PyObject *keywds) {
brotli_Compressor *self;
self = (brotli_Compressor *)type->tp_alloc(type, 0);
Expand All @@ -372,8 +397,12 @@ static PyObject* brotli_Compressor_new(PyTypeObject *type, PyObject *args, PyObj

return (PyObject *)self;
}
#endif

static int brotli_Compressor_init(brotli_Compressor *self, PyObject *args, PyObject *keywds) {
#ifdef Py_LIMITED_API
self->enc = BrotliEncoderCreateInstance(0, 0, 0);
#endif
BrotliEncoderMode mode = (BrotliEncoderMode) -1;
int quality = -1;
int lgwin = -1;
Expand Down Expand Up @@ -431,7 +460,11 @@ static PyObject* brotli_Compressor_process(brotli_Compressor *self, PyObject *ar
int ok;

#if PY_MAJOR_VERSION >= 3
#ifdef Py_LIMITED_API
ok = PyArg_ParseTuple(args, "y*:process", &input.buf, &input.len);
#else
ok = PyArg_ParseTuple(args, "y*:process", &input);
#endif
#else
ok = PyArg_ParseTuple(args, "s*:process", &input);
#endif
Expand Down Expand Up @@ -546,6 +579,25 @@ static PyMethodDef brotli_Compressor_methods[] = {
{NULL} /* Sentinel */
};

#ifdef Py_LIMITED_API
static PyType_Slot brotli_Compressor_slots[] = {
{Py_tp_dealloc, (void *)brotli_Compressor_dealloc},
{Py_tp_doc, (void *)brotli_Compressor_doc},
{Py_tp_members, brotli_Compressor_members},
{Py_tp_methods, brotli_Compressor_methods},
{Py_tp_new, (void *)PyType_GenericNew},
{Py_tp_init, (void *)brotli_Compressor_init},
{0, NULL}
};

static PyType_Spec brotli_Compressor_Spec = {
"brotli.Compressor", // const char* name;
sizeof(brotli_Compressor), // int basicsize;
0, // int itemsize;
Py_TPFLAGS_DEFAULT, // unsigned int flags;
brotli_Compressor_slots, // PyType_Slot *slots;
};
#else
static PyTypeObject brotli_CompressorType = {
#if PY_MAJOR_VERSION >= 3
PyVarObject_HEAD_INIT(NULL, 0)
Expand Down Expand Up @@ -591,6 +643,7 @@ static PyTypeObject brotli_CompressorType = {
0, /* tp_alloc */
brotli_Compressor_new, /* tp_new */
};
#endif

static PyObject* decompress_stream(BrotliDecoderState* dec,
uint8_t* input, size_t input_length) {
Expand Down Expand Up @@ -660,12 +713,17 @@ typedef struct {
static void brotli_Decompressor_dealloc(brotli_Decompressor* self) {
BrotliDecoderDestroyInstance(self->dec);
#if PY_MAJOR_VERSION >= 3
#ifdef Py_LIMITED_API
PyObject_Del((PyObject*)self);
#else
Py_TYPE(self)->tp_free((PyObject*)self);
#endif
#else
self->ob_type->tp_free((PyObject*)self);
#endif
}

#ifndef Py_LIMITED_API
static PyObject* brotli_Decompressor_new(PyTypeObject *type, PyObject *args, PyObject *keywds) {
brotli_Decompressor *self;
self = (brotli_Decompressor *)type->tp_alloc(type, 0);
Expand All @@ -676,8 +734,12 @@ static PyObject* brotli_Decompressor_new(PyTypeObject *type, PyObject *args, PyO

return (PyObject *)self;
}
#endif

static int brotli_Decompressor_init(brotli_Decompressor *self, PyObject *args, PyObject *keywds) {
#ifdef Py_LIMITED_API
self->dec = BrotliDecoderCreateInstance(0, 0, 0);
#endif
int ok;

static const char *kwlist[] = {NULL};
Expand Down Expand Up @@ -718,7 +780,11 @@ static PyObject* brotli_Decompressor_process(brotli_Decompressor *self, PyObject
int ok;

#if PY_MAJOR_VERSION >= 3
#ifdef Py_LIMITED_API
ok = PyArg_ParseTuple(args, "y*:process", &input.buf, &input.len);
#else
ok = PyArg_ParseTuple(args, "y*:process", &input);
#endif
#else
ok = PyArg_ParseTuple(args, "s*:process", &input);
#endif
Expand Down Expand Up @@ -783,6 +849,25 @@ static PyMethodDef brotli_Decompressor_methods[] = {
{NULL} /* Sentinel */
};

#ifdef Py_LIMITED_API
static PyType_Slot brotli_Decompressor_slots[] = {
{Py_tp_dealloc, (void *)brotli_Decompressor_dealloc},
{Py_tp_doc, (void *)brotli_Decompressor_doc},
{Py_tp_members, brotli_Decompressor_members},
{Py_tp_methods, brotli_Decompressor_methods},
{Py_tp_new, (void *)PyType_GenericNew},
{Py_tp_init, (void *)brotli_Decompressor_init},
{0, NULL}
};

static PyType_Spec brotli_Decompressor_Spec = {
"brotli.Decompressor", // const char* name;
sizeof(brotli_Decompressor), // int basicsize;
0, // int itemsize;
Py_TPFLAGS_DEFAULT, // unsigned int flags;
brotli_Decompressor_slots, // PyType_Slot *slots;
};
#else
static PyTypeObject brotli_DecompressorType = {
#if PY_MAJOR_VERSION >= 3
PyVarObject_HEAD_INIT(NULL, 0)
Expand Down Expand Up @@ -828,6 +913,7 @@ static PyTypeObject brotli_DecompressorType = {
0, /* tp_alloc */
brotli_Decompressor_new, /* tp_new */
};
#endif

PyDoc_STRVAR(brotli_decompress__doc__,
"Decompress a compressed byte string.\n"
Expand Down Expand Up @@ -861,8 +947,13 @@ static PyObject* brotli_decompress(PyObject *self, PyObject *args, PyObject *key
int ok;

#if PY_MAJOR_VERSION >= 3
#ifdef Py_LIMITED_API
ok = PyArg_ParseTupleAndKeywords(args, keywds, "y#|:decompress",
(char**) kwlist, &input.buf, &input.len);
#else
ok = PyArg_ParseTupleAndKeywords(args, keywds, "y*|:decompress",
(char**) kwlist, &input);
#endif
#else
ok = PyArg_ParseTupleAndKeywords(args, keywds, "s*|:decompress",
(char**) kwlist, &input);
Expand Down Expand Up @@ -959,17 +1050,27 @@ PyMODINIT_FUNC INIT_BROTLI(void) {
PyModule_AddObject(m, "error", BrotliError);
}

if (PyType_Ready(&brotli_CompressorType) < 0) {
#ifdef Py_LIMITED_API
PyTypeObject* brotli_CompressorType_ref = (PyTypeObject *) PyType_FromSpec(&brotli_Compressor_Spec);
#else
PyTypeObject* brotli_CompressorType_ref = &brotli_CompressorType;
#endif
if (PyType_Ready(brotli_CompressorType_ref) < 0) {
RETURN_NULL;
}
Py_INCREF(&brotli_CompressorType);
PyModule_AddObject(m, "Compressor", (PyObject *)&brotli_CompressorType);
Py_INCREF(brotli_CompressorType_ref);
PyModule_AddObject(m, "Compressor", (PyObject *)brotli_CompressorType_ref);

if (PyType_Ready(&brotli_DecompressorType) < 0) {
#ifdef Py_LIMITED_API
PyTypeObject* brotli_DecompressorType_ref = (PyTypeObject *) PyType_FromSpec(&brotli_Decompressor_Spec);
#else
PyTypeObject* brotli_DecompressorType_ref = &brotli_DecompressorType;
#endif
if (PyType_Ready(brotli_DecompressorType_ref) < 0) {
RETURN_NULL;
}
Py_INCREF(&brotli_DecompressorType);
PyModule_AddObject(m, "Decompressor", (PyObject *)&brotli_DecompressorType);
Py_INCREF(brotli_DecompressorType_ref);
PyModule_AddObject(m, "Decompressor", (PyObject *)brotli_DecompressorType_ref);

PyModule_AddIntConstant(m, "MODE_GENERIC", (int) BROTLI_MODE_GENERIC);
PyModule_AddIntConstant(m, "MODE_TEXT", (int) BROTLI_MODE_TEXT);
Expand Down
42 changes: 20 additions & 22 deletions python/brotli.py → python/brotli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@

"""Functions to compress and decompress data using the Brotli library."""

import _brotli
from ._brotli import (
# The library version.
__version__,
# The compression mode.
MODE_GENERIC,
MODE_TEXT,
MODE_FONT,
# The Compressor object.
Compressor,
# The Decompressor object.
Decompressor,
# Decompress a compressed byte string.
decompress,
# Raised if compression or decompression fails.
error,
)


version = __version__

# The library version.
version = __version__ = _brotli.__version__

# The compression mode.
MODE_GENERIC = _brotli.MODE_GENERIC
MODE_TEXT = _brotli.MODE_TEXT
MODE_FONT = _brotli.MODE_FONT

# The Compressor object.
Compressor = _brotli.Compressor

# The Decompressor object.
Decompressor = _brotli.Decompressor

# Compress a byte string.
def compress(string, mode=MODE_GENERIC, quality=11, lgwin=22, lgblock=0):
Expand All @@ -46,12 +51,5 @@ def compress(string, mode=MODE_GENERIC, quality=11, lgwin=22, lgblock=0):
Raises:
brotli.error: If arguments are invalid, or compressor fails.
"""
compressor = Compressor(mode=mode, quality=quality, lgwin=lgwin,
lgblock=lgblock)
compressor = Compressor(mode=mode, quality=quality, lgwin=lgwin, lgblock=lgblock)
return compressor.process(string) + compressor.finish()

# Decompress a compressed byte string.
decompress = _brotli.decompress

# Raised if compression or decompression fails.
error = _brotli.error
Loading