Skip to content

Commit 7f6ba08

Browse files
committed
[GH-37] Basic support for module 'bz2'.
PullRequest: graalpython/365
2 parents aa4d9e2 + da10316 commit 7f6ba08

File tree

15 files changed

+1155
-26
lines changed

15 files changed

+1155
-26
lines changed

graalpython/com.oracle.graal.python.cext/modules/_bz2.c

Lines changed: 807 additions & 0 deletions
Large diffs are not rendered by default.

graalpython/com.oracle.graal.python.cext/modules/_memoryview.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2018, Oracle and/or its affiliates.
1+
/* Copyright (c) 2018, 2019, Oracle and/or its affiliates.
22
* Copyright (C) 1996-2017 Python Software Foundation
33
*
44
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -689,7 +689,7 @@ mbuf_add_view(_PyManagedBufferObject *mbuf, const Py_buffer *src)
689689
Py_INCREF(mbuf);
690690
mbuf->exports++;
691691

692-
return (PyObject *)mv;
692+
return (PyObject *)polyglot_from_PyMemoryViewObject(mv);
693693
}
694694

695695
/* Register an incomplete view: shape, strides, suboffsets and flags still
@@ -720,7 +720,7 @@ mbuf_add_incomplete_view(_PyManagedBufferObject *mbuf, const Py_buffer *src,
720720
Py_INCREF(mbuf);
721721
mbuf->exports++;
722722

723-
return (PyObject *)mv;
723+
return (PyObject *)polyglot_from_PyMemoryViewObject(mv);
724724
}
725725

726726
/* Expose a raw memory area as a view of contiguous bytes. flags can be
@@ -941,7 +941,7 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
941941
}
942942

943943
if (PyBuffer_IsContiguous(view, order))
944-
return (PyObject *)mv;
944+
return (PyObject *)polyglot_from_PyMemoryViewObject(mv);
945945

946946
if (buffertype == PyBUF_WRITE) {
947947
PyErr_SetString(PyExc_BufferError,
@@ -1403,7 +1403,7 @@ memory_cast(PyMemoryViewObject *self, PyObject *args, PyObject *kwds)
14031403
if (shape && cast_to_ND(mv, shape, (int)ndim) < 0)
14041404
goto error;
14051405

1406-
return (PyObject *)mv;
1406+
return (PyObject *)polyglot_from_PyMemoryViewObject(mv);
14071407

14081408
error:
14091409
Py_DECREF(mv);
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/* Copyright (c) 2019, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2017 Python Software Foundation
3+
*
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
*/
6+
/*[clinic input]
7+
preserve
8+
[clinic start generated code]*/
9+
10+
PyDoc_STRVAR(_bz2_BZ2Compressor_compress__doc__,
11+
"compress($self, data, /)\n"
12+
"--\n"
13+
"\n"
14+
"Provide data to the compressor object.\n"
15+
"\n"
16+
"Returns a chunk of compressed data if possible, or b\'\' otherwise.\n"
17+
"\n"
18+
"When you have finished providing data to the compressor, call the\n"
19+
"flush() method to finish the compression process.");
20+
21+
#define _BZ2_BZ2COMPRESSOR_COMPRESS_METHODDEF \
22+
{"compress", (PyCFunction)_bz2_BZ2Compressor_compress, METH_O, _bz2_BZ2Compressor_compress__doc__},
23+
24+
static PyObject *
25+
_bz2_BZ2Compressor_compress_impl(BZ2Compressor *self, Py_buffer *data);
26+
27+
static PyObject *
28+
_bz2_BZ2Compressor_compress(BZ2Compressor *self, PyObject *arg)
29+
{
30+
PyObject *return_value = NULL;
31+
Py_buffer data = {NULL, NULL};
32+
33+
if (!PyArg_Parse(arg, "y*:compress", &data)) {
34+
goto exit;
35+
}
36+
return_value = _bz2_BZ2Compressor_compress_impl(self, &data);
37+
38+
exit:
39+
/* Cleanup for data */
40+
if (data.obj) {
41+
PyBuffer_Release(&data);
42+
}
43+
44+
return return_value;
45+
}
46+
47+
PyDoc_STRVAR(_bz2_BZ2Compressor_flush__doc__,
48+
"flush($self, /)\n"
49+
"--\n"
50+
"\n"
51+
"Finish the compression process.\n"
52+
"\n"
53+
"Returns the compressed data left in internal buffers.\n"
54+
"\n"
55+
"The compressor object may not be used after this method is called.");
56+
57+
#define _BZ2_BZ2COMPRESSOR_FLUSH_METHODDEF \
58+
{"flush", (PyCFunction)_bz2_BZ2Compressor_flush, METH_NOARGS, _bz2_BZ2Compressor_flush__doc__},
59+
60+
static PyObject *
61+
_bz2_BZ2Compressor_flush_impl(BZ2Compressor *self);
62+
63+
static PyObject *
64+
_bz2_BZ2Compressor_flush(BZ2Compressor *self, PyObject *Py_UNUSED(ignored))
65+
{
66+
return _bz2_BZ2Compressor_flush_impl(self);
67+
}
68+
69+
PyDoc_STRVAR(_bz2_BZ2Compressor___init____doc__,
70+
"BZ2Compressor(compresslevel=9, /)\n"
71+
"--\n"
72+
"\n"
73+
"Create a compressor object for compressing data incrementally.\n"
74+
"\n"
75+
" compresslevel\n"
76+
" Compression level, as a number between 1 and 9.\n"
77+
"\n"
78+
"For one-shot compression, use the compress() function instead.");
79+
80+
static int
81+
_bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel);
82+
83+
static int
84+
_bz2_BZ2Compressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
85+
{
86+
int return_value = -1;
87+
int compresslevel = 9;
88+
89+
if ((Py_TYPE(self) == &BZ2Compressor_Type) &&
90+
!_PyArg_NoKeywords("BZ2Compressor", kwargs)) {
91+
goto exit;
92+
}
93+
if (!PyArg_ParseTuple(args, "|i:BZ2Compressor",
94+
&compresslevel)) {
95+
goto exit;
96+
}
97+
return_value = _bz2_BZ2Compressor___init___impl((BZ2Compressor *)self, compresslevel);
98+
99+
exit:
100+
return return_value;
101+
}
102+
103+
PyDoc_STRVAR(_bz2_BZ2Decompressor_decompress__doc__,
104+
"decompress($self, /, data, max_length=-1)\n"
105+
"--\n"
106+
"\n"
107+
"Decompress *data*, returning uncompressed data as bytes.\n"
108+
"\n"
109+
"If *max_length* is nonnegative, returns at most *max_length* bytes of\n"
110+
"decompressed data. If this limit is reached and further output can be\n"
111+
"produced, *self.needs_input* will be set to ``False``. In this case, the next\n"
112+
"call to *decompress()* may provide *data* as b\'\' to obtain more of the output.\n"
113+
"\n"
114+
"If all of the input data was decompressed and returned (either because this\n"
115+
"was less than *max_length* bytes, or because *max_length* was negative),\n"
116+
"*self.needs_input* will be set to True.\n"
117+
"\n"
118+
"Attempting to decompress data after the end of stream is reached raises an\n"
119+
"EOFError. Any data found after the end of the stream is ignored and saved in\n"
120+
"the unused_data attribute.");
121+
122+
#define _BZ2_BZ2DECOMPRESSOR_DECOMPRESS_METHODDEF \
123+
{"decompress", (PyCFunction)_bz2_BZ2Decompressor_decompress, METH_FASTCALL, _bz2_BZ2Decompressor_decompress__doc__},
124+
125+
static PyObject *
126+
_bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data,
127+
Py_ssize_t max_length);
128+
129+
static PyObject *
130+
_bz2_BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
131+
{
132+
PyObject *return_value = NULL;
133+
static const char * const _keywords[] = {"data", "max_length", NULL};
134+
static _PyArg_Parser _parser = {"y*|n:decompress", _keywords, 0};
135+
Py_buffer data = {NULL, NULL};
136+
Py_ssize_t max_length = -1;
137+
138+
if (!_PyArg_ParseStack(args, nargs, kwnames, &_parser,
139+
&data, &max_length)) {
140+
goto exit;
141+
}
142+
return_value = _bz2_BZ2Decompressor_decompress_impl(self, &data, max_length);
143+
144+
exit:
145+
/* Cleanup for data */
146+
if (data.obj) {
147+
PyBuffer_Release(&data);
148+
}
149+
150+
return return_value;
151+
}
152+
153+
PyDoc_STRVAR(_bz2_BZ2Decompressor___init____doc__,
154+
"BZ2Decompressor()\n"
155+
"--\n"
156+
"\n"
157+
"Create a decompressor object for decompressing data incrementally.\n"
158+
"\n"
159+
"For one-shot decompression, use the decompress() function instead.");
160+
161+
static int
162+
_bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self);
163+
164+
static int
165+
_bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
166+
{
167+
int return_value = -1;
168+
169+
if ((Py_TYPE(self) == &BZ2Decompressor_Type) &&
170+
!_PyArg_NoPositional("BZ2Decompressor", args)) {
171+
goto exit;
172+
}
173+
if ((Py_TYPE(self) == &BZ2Decompressor_Type) &&
174+
!_PyArg_NoKeywords("BZ2Decompressor", kwargs)) {
175+
goto exit;
176+
}
177+
return_value = _bz2_BZ2Decompressor___init___impl((BZ2Decompressor *)self);
178+
179+
exit:
180+
return return_value;
181+
}
182+
/*[clinic end generated code: output=7e57af0b368d3e55 input=a9049054013a1b77]*/

graalpython/com.oracle.graal.python.cext/src/bytesobject.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -280,3 +280,8 @@ UPCALL_ID(PyBytes_Join);
280280
PyObject *_PyBytes_Join(PyObject *sep, PyObject *x) {
281281
return UPCALL_CEXT_O(_jls_PyBytes_Join, native_to_java(sep), native_to_java(x));
282282
}
283+
284+
UPCALL_ID(_PyBytes_Resize);
285+
int _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) {
286+
return UPCALL_CEXT_I(_jls__PyBytes_Resize, native_to_java(*pv), newsize);
287+
}

graalpython/com.oracle.graal.python.cext/src/ceval.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -61,3 +61,13 @@ UPCALL_ID(PyThread_allocate_lock);
6161
void* PyThread_allocate_lock() {
6262
return UPCALL_CEXT_O(_jls_PyThread_allocate_lock);
6363
}
64+
65+
UPCALL_ID(PyThread_acquire_lock);
66+
int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag) {
67+
return UPCALL_CEXT_O(_jls_PyThread_acquire_lock, native_to_java(aLock), waitflag ? -1 : 0);
68+
}
69+
70+
UPCALL_ID(PyThread_release_lock);
71+
void PyThread_release_lock(PyThread_type_lock aLock) {
72+
UPCALL_CEXT_O(_jls_PyThread_release_lock, native_to_java(aLock));
73+
}

graalpython/com.oracle.graal.python.cext/src/exceptions.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -83,6 +83,7 @@ PyObject * PyExc_NotImplementedError = NULL;
8383
PyObject * PyExc_RecursionError = NULL;
8484
PyObject * PyExc_UnicodeEncodeError = NULL;
8585
PyObject * PyExc_GeneratorExit = NULL;
86+
PyObject * PyExc_EOFError = NULL;
8687

8788
void initialize_exceptions() {
8889
PyExc_AttributeError = PY_EXCEPTION("AttributeError");
@@ -122,6 +123,7 @@ void initialize_exceptions() {
122123
PyExc_NotImplementedError = PY_EXCEPTION("NotImplementedError");
123124
PyExc_UnicodeEncodeError = PY_EXCEPTION("UnicodeEncodeError");
124125
PyExc_GeneratorExit = PY_EXCEPTION("GeneratorExit");
126+
PyExc_EOFError = PY_EXCEPTION("EOFError");
125127
}
126128

127129

graalpython/com.oracle.graal.python.cext/src/modsupport.c

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -42,6 +42,19 @@
4242

4343
#include <stdio.h>
4444

45+
static int getbuffer(PyObject *arg, Py_buffer *view, const char **errmsg) {
46+
if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) {
47+
*errmsg = "bytes-like object";
48+
return -1;
49+
}
50+
// if (!PyBuffer_IsContiguous(view, 'C')) {
51+
// PyBuffer_Release(view);
52+
// *errmsg = "contiguous buffer";
53+
// return -1;
54+
// }
55+
return 0;
56+
}
57+
4558
typedef struct _positional_argstack {
4659
PyObject* argv;
4760
int argnum;
@@ -89,10 +102,15 @@ UPCALL_ID(__bool__);
89102
case 'y': \
90103
arg = PyTruffle_GetArg(v, kwds, kwdnames, rest_keywords_only); \
91104
if (format[format_idx + 1] == '*') { \
105+
Py_buffer* p = (Py_buffer*)PyTruffle_ArgN(output_idx); \
106+
const char* buf; \
92107
format_idx++; /* skip over '*' */ \
93-
PyErr_Format(PyExc_TypeError, "%c* not supported", c); \
94-
__return_code__; \
95-
return 0; \
108+
if (getbuffer(arg, p, &buf) < 0) { \
109+
PyErr_Format(PyExc_TypeError, "expected bytes, got %R", Py_TYPE(arg)); \
110+
__return_code__; \
111+
return 0; \
112+
} \
113+
PyTruffle_WriteOut(output_idx, Py_buffer, *p); \
96114
} else if (arg == Py_None) { \
97115
if (c == 'z') { \
98116
PyTruffle_WriteOut(output_idx, const char*, NULL); \
@@ -842,3 +860,36 @@ int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize
842860
#define PyArg_UnpackTuple _backup_PyArg_UnpackTuple
843861
#undef _backup_PyArg_UnpackTuple
844862
#endif
863+
864+
// taken from CPython 3.6.5 "Python/getargs.c"
865+
int _PyArg_NoKeywords(const char *funcname, PyObject *kw) {
866+
if (kw == NULL)
867+
return 1;
868+
if (!PyDict_CheckExact(kw)) {
869+
PyErr_BadInternalCall();
870+
return 0;
871+
}
872+
if (PyDict_Size(kw) == 0)
873+
return 1;
874+
875+
PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments",
876+
funcname);
877+
return 0;
878+
}
879+
880+
int
881+
_PyArg_NoPositional(const char *funcname, PyObject *args)
882+
{
883+
if (args == NULL)
884+
return 1;
885+
if (!PyTuple_CheckExact(args)) {
886+
PyErr_BadInternalCall();
887+
return 0;
888+
}
889+
if (PyTuple_GET_SIZE(args) == 0)
890+
return 1;
891+
892+
PyErr_Format(PyExc_TypeError, "%s does not take positional arguments",
893+
funcname);
894+
return 0;
895+
}

0 commit comments

Comments
 (0)