Skip to content

Commit fbbcf51

Browse files
committed
[GR-54334] Support pandas 2
PullRequest: graalpython/3353
2 parents 40edc74 + dffbb29 commit fbbcf51

File tree

12 files changed

+224
-3
lines changed

12 files changed

+224
-3
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_misc.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,17 @@ class TestMisc(CPyExtTestCase):
165165
cmpfunc=unhandled_error_compare
166166
)
167167

168+
test_PyImport_GetModule = CPyExtFunction(
169+
lambda args: sys.modules.get(args[0]),
170+
lambda: (
171+
("os",),
172+
),
173+
resultspec="O",
174+
argspec="O",
175+
arguments=["PyObject* name"],
176+
cmpfunc=unhandled_error_compare
177+
)
178+
168179
test_PyTruffle_Intrinsic_Pmovmskb = CPyExtFunction(
169180
lambda args: True,
170181
lambda: (

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,11 +2853,14 @@ static int getCpuCount() {
28532853
abstract static class SysconfNode extends PythonUnaryBuiltinNode {
28542854

28552855
public static final TruffleString T_SC_CLK_TCK = tsLiteral("SC_CLK_TCK");
2856+
public static final TruffleString T_SC_NPROCESSORS_ONLN = tsLiteral("SC_NPROCESSORS_ONLN");
28562857
public static final int SC_CLK_TCK = 2;
2858+
public static final int SC_NPROCESSORS_ONLN = 84;
28572859
public static final EconomicMapStorage SYSCONF_NAMES = EconomicMapStorage.create();
28582860
static {
28592861
// TODO populate from constants
28602862
SYSCONF_NAMES.putUncachedWithJavaEq(T_SC_CLK_TCK, SC_CLK_TCK);
2863+
SYSCONF_NAMES.putUncachedWithJavaEq(T_SC_NPROCESSORS_ONLN, SC_NPROCESSORS_ONLN);
28612864
}
28622865

28632866
@Specialization
@@ -2885,6 +2888,8 @@ static int sysconf(VirtualFrame frame, Object arg,
28852888
if (id == SC_CLK_TCK) {
28862889
return 100; // it's 100 on most default kernel configs. TODO: use real value through
28872890
// NFI
2891+
} else if (id == SC_NPROCESSORS_ONLN) {
2892+
return CpuCountNode.getCpuCount();
28882893
}
28892894
throw constructAndRaiseNode.get(inliningTarget).raiseOSError(frame, OSErrorEnum.EINVAL);
28902895
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextImportBuiltins.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,26 @@
5252
import static com.oracle.graal.python.nodes.BuiltinNames.T_GLOBALS;
5353
import static com.oracle.graal.python.nodes.BuiltinNames.T_LOCALS;
5454
import static com.oracle.graal.python.nodes.BuiltinNames.T___IMPORT__;
55+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___INITIALIZING__;
56+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___SPEC__;
57+
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
5558

5659
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApi5BuiltinNode;
5760
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
5861
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiNullaryBuiltinNode;
5962
import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiUnaryBuiltinNode;
63+
import com.oracle.graal.python.builtins.objects.PNone;
64+
import com.oracle.graal.python.builtins.objects.dict.PDict;
6065
import com.oracle.graal.python.builtins.objects.function.PKeyword;
66+
import com.oracle.graal.python.lib.PyObjectCallMethodObjArgs;
6167
import com.oracle.graal.python.lib.PyObjectGetAttr;
68+
import com.oracle.graal.python.lib.PyObjectGetItem;
69+
import com.oracle.graal.python.lib.PyObjectIsTrueNode;
6270
import com.oracle.graal.python.nodes.call.CallNode;
6371
import com.oracle.graal.python.nodes.statement.AbstractImportNode;
72+
import com.oracle.graal.python.runtime.PythonContext;
73+
import com.oracle.graal.python.runtime.exception.PException;
74+
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
6475
import com.oracle.truffle.api.dsl.Bind;
6576
import com.oracle.truffle.api.dsl.Cached;
6677
import com.oracle.truffle.api.dsl.Specialization;
@@ -103,4 +114,47 @@ Object importModuleLevelObject(TruffleString name, Object globals, Object locals
103114
});
104115
}
105116
}
117+
118+
@CApiBuiltin(ret = PyObjectTransfer, args = {PyObject}, call = Direct)
119+
abstract static class PyImport_GetModule extends CApiUnaryBuiltinNode {
120+
121+
private static final TruffleString T__LOCK_UNLOCK_MODULE = tsLiteral("_lock_unlock_module");
122+
123+
@Specialization
124+
Object getModule(Object name,
125+
@Bind("this") Node inliningTarget,
126+
@Cached PyObjectGetItem getItem,
127+
@Cached PyObjectGetAttr getAttr,
128+
@Cached PyObjectIsTrueNode isTrueNode) {
129+
PythonContext context = PythonContext.get(inliningTarget);
130+
PDict modules = context.getSysModules();
131+
Object m;
132+
try {
133+
m = getItem.execute(null, inliningTarget, modules, name);
134+
} catch (PException e) {
135+
return context.getNativeNull();
136+
}
137+
if (m != PNone.NONE) {
138+
boolean initializing = false;
139+
try {
140+
Object spec = getAttr.execute(null, inliningTarget, m, T___SPEC__);
141+
Object initializingObj = getAttr.execute(null, inliningTarget, spec, T___INITIALIZING__);
142+
if (isTrueNode.execute(null, inliningTarget, initializingObj)) {
143+
initializing = true;
144+
}
145+
} catch (PException e) {
146+
// ignore
147+
}
148+
if (initializing) {
149+
waitForInitialization(name, context);
150+
}
151+
}
152+
return m;
153+
}
154+
155+
@TruffleBoundary
156+
private static void waitForInitialization(Object name, PythonContext context) {
157+
PyObjectCallMethodObjArgs.executeUncached(context.getImportlib(), T__LOCK_UNLOCK_MODULE, name);
158+
}
159+
}
106160
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,6 @@ public final class CApiFunction {
770770
@CApiBuiltin(name = "PyImport_GetImporter", ret = PyObject, args = {PyObject}, call = NotImplemented)
771771
@CApiBuiltin(name = "PyImport_GetMagicNumber", ret = Long, args = {}, call = NotImplemented)
772772
@CApiBuiltin(name = "PyImport_GetMagicTag", ret = ConstCharPtrAsTruffleString, args = {}, call = NotImplemented)
773-
@CApiBuiltin(name = "PyImport_GetModule", ret = PyObject, args = {PyObject}, call = NotImplemented)
774773
@CApiBuiltin(name = "PyImport_ImportFrozenModule", ret = Int, args = {ConstCharPtrAsTruffleString}, call = NotImplemented)
775774
@CApiBuiltin(name = "PyImport_ImportFrozenModuleObject", ret = Int, args = {PyObject}, call = NotImplemented)
776775
@CApiBuiltin(name = "PyImport_ReloadModule", ret = PyObject, args = {PyObject}, call = NotImplemented)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialAttributeNames.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ public abstract class SpecialAttributeNames {
114114

115115
public static final TruffleString T___CACHED__ = tsLiteral("__cached__");
116116

117+
public static final TruffleString T___INITIALIZING__ = tsLiteral("__initializing__");
118+
117119
public static final String J___TEXT_SIGNATURE__ = "__text_signature__";
118120
public static final TruffleString T___TEXT_SIGNATURE__ = tsLiteral(J___TEXT_SIGNATURE__);
119121

graalpython/lib-graalpython/patches/Cython/metadata.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
version = '== 3.0.10'
33
patch = 'Cython-3.0.10.patch'
44

5-
# Prefer pre-3 version for now
65
[[rules]]
76
version = '== 0.29.37'
87
patch = 'Cython-0.29.37.patch'
9-
install-priority = 2
108

119
[[rules]]
1210
version = '== 0.29.32'
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
diff --git a/setup.py b/setup.py
2+
index 3a55a00..0c6f89a 100644
3+
--- a/setup.py
4+
+++ b/setup.py
5+
@@ -11,7 +11,8 @@ from skbuild import setup
6+
# Blosc version
7+
VERSION = open("VERSION").read().strip()
8+
# Create the version.py file
9+
-open("blosc2/version.py", "w").write(f'__version__ = "{VERSION}"\n')
10+
+with open("blosc2/version.py", "w") as f:
11+
+ f.write(f'__version__ = "{VERSION}"\n')
12+
13+
14+
def exclude_pkgconfig(cmake_manifest):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[[rules]]
2+
patch = 'blosc2.patch'

graalpython/lib-graalpython/patches/pandas/metadata.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
[[rules]]
2+
version = '== 2.2.2'
3+
patch = 'pandas-2.2.2.patch'
4+
dist-type = 'sdist'
5+
6+
[[rules]]
7+
version = '== 2.0.3'
8+
patch = 'pandas-2.0.3.patch'
9+
dist-type = 'sdist'
10+
111
[[rules]]
212
version = '== 1.5.2'
313
patch = 'pandas-1.5.2.patch'
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
diff --git a/pandas/_libs/src/klib/khash_python.h b/pandas/_libs/src/klib/khash_python.h
2+
index 56afea0..14025b7 100644
3+
--- a/pandas/_libs/src/klib/khash_python.h
4+
+++ b/pandas/_libs/src/klib/khash_python.h
5+
@@ -178,28 +178,30 @@ int PANDAS_INLINE floatobject_cmp(PyFloatObject* a, PyFloatObject* b){
6+
// PyObject_RichCompareBool for complexobjects has a different behavior
7+
// needs to be replaced
8+
int PANDAS_INLINE complexobject_cmp(PyComplexObject* a, PyComplexObject* b){
9+
+ Py_complex a_cval = PyComplex_AsCComplex((PyObject*)a);
10+
+ Py_complex b_cval = PyComplex_AsCComplex((PyObject*)b);
11+
return (
12+
- Py_IS_NAN(a->cval.real) &&
13+
- Py_IS_NAN(b->cval.real) &&
14+
- Py_IS_NAN(a->cval.imag) &&
15+
- Py_IS_NAN(b->cval.imag)
16+
+ Py_IS_NAN(a_cval.real) &&
17+
+ Py_IS_NAN(b_cval.real) &&
18+
+ Py_IS_NAN(a_cval.imag) &&
19+
+ Py_IS_NAN(b_cval.imag)
20+
)
21+
||
22+
(
23+
- Py_IS_NAN(a->cval.real) &&
24+
- Py_IS_NAN(b->cval.real) &&
25+
- a->cval.imag == b->cval.imag
26+
+ Py_IS_NAN(a_cval.real) &&
27+
+ Py_IS_NAN(b_cval.real) &&
28+
+ a_cval.imag == b_cval.imag
29+
)
30+
||
31+
(
32+
- a->cval.real == b->cval.real &&
33+
- Py_IS_NAN(a->cval.imag) &&
34+
- Py_IS_NAN(b->cval.imag)
35+
+ a_cval.real == b_cval.real &&
36+
+ Py_IS_NAN(a_cval.imag) &&
37+
+ Py_IS_NAN(b_cval.imag)
38+
)
39+
||
40+
(
41+
- a->cval.real == b->cval.real &&
42+
- a->cval.imag == b->cval.imag
43+
+ a_cval.real == b_cval.real &&
44+
+ a_cval.imag == b_cval.imag
45+
);
46+
}
47+
48+
@@ -276,8 +278,9 @@ Py_hash_t PANDAS_INLINE floatobject_hash(PyFloatObject* key) {
49+
50+
// replaces _Py_HashDouble with _Pandas_HashDouble
51+
Py_hash_t PANDAS_INLINE complexobject_hash(PyComplexObject* key) {
52+
- Py_uhash_t realhash = (Py_uhash_t)_Pandas_HashDouble(key->cval.real);
53+
- Py_uhash_t imaghash = (Py_uhash_t)_Pandas_HashDouble(key->cval.imag);
54+
+ Py_complex cval = PyComplex_AsCComplex((PyObject*)key);
55+
+ Py_uhash_t realhash = (Py_uhash_t)_Pandas_HashDouble(cval.real);
56+
+ Py_uhash_t imaghash = (Py_uhash_t)_Pandas_HashDouble(cval.imag);
57+
if (realhash == (Py_uhash_t)-1 || imaghash == (Py_uhash_t)-1) {
58+
return -1;
59+
}
60+
diff --git a/setup.py b/setup.py
61+
index b6dfcc5..2446bcc 100755
62+
--- a/setup.py
63+
+++ b/setup.py
64+
@@ -421,7 +421,7 @@ def maybe_cythonize(extensions, *args, **kwargs):
65+
parser.add_argument("--parallel", "-j", type=int, default=1)
66+
parsed, _ = parser.parse_known_args()
67+
68+
- kwargs["nthreads"] = parsed.parallel
69+
+ kwargs["nthreads"] = 1 # parsed.parallel
70+
build_ext.render_templates(_pxifiles)
71+
return cythonize(extensions, *args, **kwargs)
72+

0 commit comments

Comments
 (0)