Skip to content

Commit 70ef9c9

Browse files
committed
[GR-53367][GR-53368] Add patch for cffi 1.16.0 as requested by fsspec and datasets.
PullRequest: graalpython/3288
2 parents f654c98 + c5b8e88 commit 70ef9c9

File tree

4 files changed

+74
-47
lines changed

4 files changed

+74
-47
lines changed

graalpython/lib-graalpython/modules/autopatch_capi.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@
4444

4545

4646
def simple_replace(contents, match, replacement, assignment):
47-
"replaces the indexes in 'contents' described by the tuple 'group' with replacement"
48-
47+
"replaces the indexes in 'contents' described by the tuple 'group' with replacement, which may have backrefs"
48+
4949
start, end = match.span(1)
50-
return contents[:start] + replacement + contents[end:]
50+
return contents[:start] + match.expand(replacement) + contents[end:]
5151

5252

5353
def replace_pre(contents, match, replacement, assignment):
5454
"replaces a pre-increment/decrement"
55-
55+
5656
start, end = match.span(1)
5757
replacement = replacement.replace('%receiver', contents[start: end])
5858
start, end = match.span()
@@ -61,24 +61,24 @@ def replace_pre(contents, match, replacement, assignment):
6161

6262
def replace_field_access(contents, match, replacement, assignment):
6363
"replaces a field access, scanning backwards to determine the receiver"
64-
64+
6565
start, end = match.span(1)
6666
level = 0
67-
67+
6868
def consume_whitespace_backwards(idx):
6969
while idx > 0 and contents[idx].isspace():
7070
idx -= 1
7171
return idx
72-
72+
7373
def consume_whitespace_forward(idx):
7474
while idx < len(contents) and contents[idx].isspace():
7575
idx += 1
7676
return idx
77-
77+
7878
start = consume_whitespace_backwards(start - 1)
7979
if start < 1 or contents[start - 1: start + 1] != '->':
8080
return contents
81-
81+
8282
# scan backwards to capture the whole receiver
8383
idx = consume_whitespace_backwards(start - 2)
8484
empty = True
@@ -110,12 +110,12 @@ def consume_whitespace_forward(idx):
110110
else:
111111
idx += 1
112112
break
113-
113+
114114
receiver_start = consume_whitespace_forward(idx)
115115
receiver_string = contents[receiver_start: start - 1]
116-
116+
117117
if assignment is not None:
118-
118+
119119
# scan forwards to see if there's an assignment
120120
idx = consume_whitespace_forward(end)
121121
if contents[idx] == '=' and contents[idx+1] != '=':
@@ -139,11 +139,11 @@ def consume_whitespace_forward(idx):
139139
idx += 2
140140
else:
141141
idx += 1
142-
142+
143143
value_string = contents[value_start:idx]
144-
144+
145145
return contents[:receiver_start] + assignment.replace('%receiver', receiver_string).replace("%value", value_string) + contents[idx:]
146-
146+
147147
return contents[:receiver_start] + replacement.replace('%receiver', receiver_string) + contents[end:]
148148

149149

@@ -157,13 +157,16 @@ def consume_whitespace_forward(idx):
157157
r'\W(ob_item)\W': (replace_field_access, 'PySequence_Fast_ITEMS((PyObject*)%receiver)'),
158158
r'^\s*()(std::)?free\((const_cast<char \*>)?\(?\w+->m_ml->ml_doc\)?\);': (simple_replace, '//'),
159159
r'\W(m_ml\s*->\s*ml_doc)\W': (replace_field_access, 'PyObject_GetDoc((PyObject*)(%receiver))', 'PyObject_SetDoc((PyObject*)(%receiver), %value)'),
160+
r'\W(m_ml)\W': (replace_field_access, '_PyCFunction_GetMethodDef((PyObject*)(%receiver))'),
161+
r'\W(m_module)\W': (replace_field_access, '_PyCFunction_GetModule((PyObject*)(%receiver))'),
162+
r'(&PyTuple_GET_ITEM\(([\(\w](?:\w|->|\.|\(|\))*), 0\))': (simple_replace, r'PySequence_Fast_ITEMS(\2)'),
160163
# already defined by GraalPy:
161164
r'^\s*()#\s*define\s+Py_SET_TYPE\W': (simple_replace, '//'),
162165
r'^\s*()#\s*define\s+Py_SET_SIZE\W': (simple_replace, '//'),
163166
r'^\s*()#\s*define\s+Py_SET_REFCNT\W': (simple_replace, '//'),
164167
}
165168

166-
169+
167170
def auto_patch(path, dryrun):
168171
"reads the given file, applies all replacements, and writes back the result if there were changes"
169172

@@ -172,7 +175,7 @@ def auto_patch(path, dryrun):
172175
contents = f.read()
173176
except UnicodeDecodeError:
174177
return # may happen for binary files
175-
178+
176179
original = contents
177180
import re
178181
for pattern, (*ops,) in auto_replacements.items():

graalpython/lib-graalpython/patches/cffi/cffi-1.15.1.patch

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,3 @@
1-
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
2-
index 2cdb76b..ab91032 100644
3-
--- a/c/_cffi_backend.c
4-
+++ b/c/_cffi_backend.c
5-
@@ -5828,7 +5828,7 @@ static CTypeDescrObject *fb_prepare_ctype(struct funcbuilder_s *fb,
6-
fb->bufferp = NULL;
7-
fb->fct = NULL;
8-
9-
- pfargs = (CTypeDescrObject **)&PyTuple_GET_ITEM(fargs, 0);
10-
+ pfargs = (CTypeDescrObject **)PySequence_Fast_ITEMS(fargs);
11-
nargs = PyTuple_GET_SIZE(fargs);
12-
#if defined(MS_WIN32) && !defined(_WIN64)
13-
if (fabi == FFI_STDCALL)
14-
diff --git a/c/lib_obj.c b/c/lib_obj.c
15-
index 38bf3d5..9954f3b 100644
16-
--- a/c/lib_obj.c
17-
+++ b/c/lib_obj.c
18-
@@ -46,10 +46,10 @@ static struct CPyExtFunc_s *_cpyextfunc_get(PyObject *x)
19-
20-
fo = (PyCFunctionObject *)x;
21-
lo = (LibObject *)y;
22-
- if (lo->l_libname != fo->m_module)
23-
+ if (lo->l_libname != _PyCFunction_GetModule(fo))
24-
return NULL;
25-
26-
- return (struct CPyExtFunc_s *)(fo->m_ml);
27-
+ return (struct CPyExtFunc_s *)(_PyCFunction_GetMethodDef(fo));
28-
}
29-
30-
static PyObject *_cpyextfunc_type(LibObject *lib, struct CPyExtFunc_s *exf)
311
diff --git a/c/misc_thread_common.h b/c/misc_thread_common.h
322
index 66e2835..b48fd85 100644
333
--- a/c/misc_thread_common.h
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
index 7d29634b..bb440851 100644
2+
--- a/src/c/misc_thread_common.h
3+
+++ b/src/c/misc_thread_common.h
4+
@@ -344,45 +344,7 @@ static PyThreadState *get_current_ts(void)
5+
6+
static PyGILState_STATE gil_ensure(void)
7+
{
8+
- /* Called at the start of a callback. Replacement for
9+
- PyGILState_Ensure().
10+
- */
11+
- PyGILState_STATE result;
12+
- PyThreadState *ts = PyGILState_GetThisThreadState();
13+
- //fprintf(stderr, "%p: gil_ensure(), tstate=%p, tls=%p\n", get_cffi_tls(), ts, get_cffi_tls());
14+
-
15+
- if (ts != NULL) {
16+
- ts->gilstate_counter++;
17+
- if (ts != get_current_ts()) {
18+
- /* common case: 'ts' is our non-current thread state and
19+
- we have to make it current and acquire the GIL */
20+
- PyEval_RestoreThread(ts);
21+
- //fprintf(stderr, "%p: gil_ensure(), tstate=%p MADE CURRENT\n", get_cffi_tls(), ts);
22+
- return PyGILState_UNLOCKED;
23+
- }
24+
- else {
25+
- //fprintf(stderr, "%p: gil_ensure(), tstate=%p ALREADY CURRENT\n", get_cffi_tls(), ts);
26+
- return PyGILState_LOCKED;
27+
- }
28+
- }
29+
- else {
30+
- /* no thread state here so far. */
31+
- result = PyGILState_Ensure();
32+
- assert(result == PyGILState_UNLOCKED);
33+
-
34+
- ts = PyGILState_GetThisThreadState();
35+
- //fprintf(stderr, "%p: gil_ensure(), made a new tstate=%p\n", get_cffi_tls(), ts);
36+
- assert(ts != NULL);
37+
- assert(ts == get_current_ts());
38+
- assert(ts->gilstate_counter >= 1);
39+
-
40+
- /* Use the ThreadCanary mechanism to keep 'ts' alive until the
41+
- thread really shuts down */
42+
- thread_canary_register(ts);
43+
-
44+
- assert(ts == PyGILState_GetThisThreadState());
45+
- return result;
46+
- }
47+
+ return PyGILState_Ensure();
48+
}
49+
50+
static void gil_release(PyGILState_STATE oldstate)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
[[rules]]
22
version = '== 1.15.1'
33
patch = 'cffi-1.15.1.patch'
4+
5+
[[rules]]
6+
version = '== 1.16.0'
7+
patch = 'cffi-1.16.0.patch'

0 commit comments

Comments
 (0)