Skip to content

Commit f487fa0

Browse files
committed
Add hints and descriptions for building C API.
1 parent 34157d1 commit f487fa0

File tree

8 files changed

+78
-9
lines changed

8 files changed

+78
-9
lines changed

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,41 @@ source <dir-to-venv>/bin/activate
3232

3333
In the venv multiple executables are available, like `python`, `python3` and `graalpython`.
3434

35+
### Using modules with C extensions
36+
37+
This Python implementation is able to load and run modules with C extensions.
38+
Supporting C extensions is one of the most difficult features for any Python
39+
implementation since it requires to be compatible to CPython's C API.
40+
41+
However, GraalVM's Python implementation is capable of executing C extensions and
42+
there is also no optimization boundary.
43+
44+
In order to be able to run C extensions, a user must first build the C API
45+
runtime library. It is recommended to build the C API in any case because
46+
it will only be used if necessary.
47+
The recommended way to do so is to create a venv (see [Create a virtual environment](#create-a-virtual-environment))
48+
and run everything within the venv.
49+
50+
If you don't want to create and use a venv, the C API can be built using
51+
following command:
52+
```
53+
mx python -m build_capi
54+
```
55+
56+
You can test if everything was built correctly by, for example, using
57+
a memoryvew object:
58+
```
59+
(your-venv) graalpython -c "print(repr(memoryview(b'')))"
60+
```
61+
62+
in the venv or
63+
64+
```
65+
mx python -c "print(repr(memoryview(b'')))"
66+
```
67+
68+
without a venv.
69+
3570
### Installing packages
3671

3772
At the moment not enough of the standard library is implemented to run the

graalpython/lib-graalpython/_sre.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,9 @@ def split(self, string, maxsplit=0):
513513
_tcompile = SRE_Pattern
514514

515515
def compile(pattern, flags, code, groups, groupindex, indexgroup):
516-
import _cpython_sre
516+
from build_capi import hint
517+
with hint("_cpython_sre"):
518+
import _cpython_sre
517519
return _cpython_sre.compile(pattern, flags, code, groups, groupindex, indexgroup)
518520

519521

@@ -524,7 +526,9 @@ def getcodesize(*args, **kwargs):
524526

525527
@__builtin__
526528
def getlower(char_ord, flags):
527-
import _cpython_sre
529+
from build_capi import hint
530+
with hint("_cpython_sre"):
531+
import _cpython_sre
528532
return _cpython_sre.getlower(char_ord, flags)
529533

530534

graalpython/lib-graalpython/memoryview.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -45,7 +45,9 @@
4545

4646

4747
def __memoryview_init(self, *args, **kwargs):
48-
import _memoryview
48+
from build_capi import hint
49+
with hint("_memoryview"):
50+
import _memoryview
4951
global c_memoryview_module
5052
c_memoryview_module = _memoryview
5153
PyTruffle_SetAttr(memoryview, "__init__", __memoryview_init2)

graalpython/lib-graalpython/mmap.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@
5454
from python_cext import register_capi_hook
5555

5656
def __register_buffer():
57-
import _mmap
57+
from build_capi import hint
58+
with hint("_mmap"):
59+
import _mmap
5860
_mmap.init_bufferprotocol(mmap)
5961

6062
register_capi_hook(__register_buffer)

graalpython/lib-graalpython/unicodedata.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@
4545
@__builtin__
4646
def __get_c_unicodedata():
4747
if c_unicodedata_module is None:
48-
import _cpython_unicodedata
48+
from build_capi import hint
49+
with hint("_cpython_unicodedata"):
50+
import _cpython_unicodedata
4951
global c_unicodedata_module
5052
c_unicodedata_module = _cpython_unicodedata
5153
return c_unicodedata_module

graalpython/lib-python/3/build_capi.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@
4343
import importlib.util
4444
import distutils.log as dlog
4545

46+
4647
capi_home = sys.graal_python_capi_home
4748
capi_module_home = sys.graal_python_capi_module_home
4849

49-
5050
def load_setup():
5151
spec = importlib.util.spec_from_file_location("setup.py", os.path.join(sys.graal_python_cext_src, "setup.py"))
5252
setup_module = importlib.util.module_from_spec(spec)
@@ -75,6 +75,24 @@ def clean(args=[]):
7575
return load_setup().clean(capi_home, capi_module_home)
7676

7777

78+
class CapiNotBuiltContextManager:
79+
def __init__(self, module_name):
80+
self.module_name = module_name
81+
82+
def __enter__(self):
83+
pass
84+
85+
def __exit__(self, typ, val, tb):
86+
if typ and issubclass(typ, ModuleNotFoundError):
87+
print("Could not locate module '%s'. Did you forget to build the C API using 'graalpython -m build_capi'?" % self.module_name)
88+
# this causes the exception to propagate in any case
89+
return False
90+
91+
92+
def hint(module_name):
93+
return CapiNotBuiltContextManager(module_name)
94+
95+
7896
if __name__ == "__main__":
7997
if "clean" in sys.argv:
8098
clean(sys.argv)

graalpython/lib-python/3/bz2.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@
1616
import _compression
1717
from threading import RLock
1818

19-
from _bz2 import BZ2Compressor, BZ2Decompressor
19+
# TRUFFLE CHANGE BEGIN
20+
from build_capi import hint
21+
with hint("_bz2"):
22+
from _bz2 import BZ2Compressor, BZ2Decompressor
23+
# TRUFFLE CHANGE END
2024

2125

2226
_MODE_CLOSED = 0

graalpython/lib-python/3/struct.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ def make_delegate(p):
1717
def delegate(*args ,**kwargs):
1818
global __cstruct
1919
if not __cstruct:
20-
import _struct as __cstruct
20+
from build_capi import hint
21+
with hint("_struct"):
22+
import _struct as __cstruct
2123
return getattr(__cstruct, p)(*args, **kwargs)
2224
delegate.__name__ = p
2325
return delegate

0 commit comments

Comments
 (0)