From d33a4b68fcefefee3ea5d2fcb40ccf5b4185adb8 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 20 Sep 2015 22:21:18 +0200 Subject: [PATCH] Add test script that all symbols imported by python-sys are exported from the python .so --- .travis.yml | 4 +- Makefile | 1 + python27-sys/src/objectabstract.rs | 2 - python3-sys/src/import.rs | 4 +- python3-sys/src/iterobject.rs | 1 - python3-sys/src/listobject.rs | 1 - python3-sys/src/modsupport.rs | 1 + python3-sys/src/objimpl.rs | 1 + python3-sys/src/pyerrors.rs | 4 +- tests/check_symbols.py | 84 ++++++++++++++++++++++++++++++ 10 files changed, 92 insertions(+), 11 deletions(-) create mode 100755 tests/check_symbols.py diff --git a/.travis.yml b/.travis.yml index c6f8d31b..dca4a816 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,15 +5,17 @@ python: - "3.4" env: - RUST_VERSION=nightly +sudo: false install: + - python -c "import sysconfig; print('\n'.join(map(repr,sorted(sysconfig.get_config_vars().items()))))" - mkdir ~/rust-installer - curl -sL https://static.rust-lang.org/rustup.sh -o ~/rust-installer/rustup.sh - sh ~/rust-installer/rustup.sh --prefix=~/rust --spec=$RUST_VERSION -y --disable-sudo - export PATH="$HOME/rust/bin:$PATH" - export PYTHON_LIB=$(python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))") + - find $PYTHON_LIB - export LIBRARY_PATH="$LIBRARY_PATH:$PYTHON_LIB" - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PYTHON_LIB:$HOME/rust/lib" - - export PYTHON_3_NO_PKG_CONFIG=1 - rustc -V script: - make test extensions diff --git a/Makefile b/Makefile index e077b0c1..836178dd 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ build: test: build cargo test $(CARGO_FLAGS) + python$(PY) tests/check_symbols.py doc: build cargo doc --no-deps $(CARGO_FLAGS) diff --git a/python27-sys/src/objectabstract.rs b/python27-sys/src/objectabstract.rs index f408b004..7434c9cd 100644 --- a/python27-sys/src/objectabstract.rs +++ b/python27-sys/src/objectabstract.rs @@ -68,8 +68,6 @@ extern "C" { pub fn PyBuffer_GetPointer(view: *mut Py_buffer, indices: *mut Py_ssize_t) -> *mut c_void; - pub fn PyBuffer_SizeFromFormat(arg1: *const c_char) - -> c_int; pub fn PyBuffer_ToContiguous(buf: *mut c_void, view: *mut Py_buffer, len: Py_ssize_t, fort: c_char) -> c_int; diff --git a/python3-sys/src/import.rs b/python3-sys/src/import.rs index 7d971b78..3f439396 100644 --- a/python3-sys/src/import.rs +++ b/python3-sys/src/import.rs @@ -1,5 +1,5 @@ use libc::{c_char, c_int, c_long}; -use object::{PyObject, PyTypeObject}; +use object::PyObject; extern "C" { pub fn PyImport_GetMagicNumber() -> c_long; @@ -60,8 +60,6 @@ extern "C" { -> c_int; pub fn PyImport_ImportFrozenModule(name: *const c_char) -> c_int; - - pub static mut PyNullImporter_Type: *mut PyTypeObject; pub fn PyImport_AppendInittab(name: *const c_char, initfunc: diff --git a/python3-sys/src/iterobject.rs b/python3-sys/src/iterobject.rs index ce4f9fd4..7021648d 100644 --- a/python3-sys/src/iterobject.rs +++ b/python3-sys/src/iterobject.rs @@ -4,7 +4,6 @@ use object::*; extern "C" { pub static mut PySeqIter_Type: PyTypeObject; pub static mut PyCallIter_Type: PyTypeObject; - pub static mut PyCmpWrapper_Type: PyTypeObject; pub fn PySeqIter_New(arg1: *mut PyObject) -> *mut PyObject; pub fn PyCallIter_New(arg1: *mut PyObject, arg2: *mut PyObject) diff --git a/python3-sys/src/listobject.rs b/python3-sys/src/listobject.rs index b40d1c9e..49a7dffe 100644 --- a/python3-sys/src/listobject.rs +++ b/python3-sys/src/listobject.rs @@ -6,7 +6,6 @@ extern "C" { pub static mut PyList_Type: PyTypeObject; pub static mut PyListIter_Type: PyTypeObject; pub static mut PyListRevIter_Type: PyTypeObject; - pub static mut PySortWrapper_Type: PyTypeObject; } #[inline(always)] diff --git a/python3-sys/src/modsupport.rs b/python3-sys/src/modsupport.rs index ad05f236..c87ac310 100644 --- a/python3-sys/src/modsupport.rs +++ b/python3-sys/src/modsupport.rs @@ -2,6 +2,7 @@ use libc::{c_char, c_int, c_long}; use pyport::Py_ssize_t; use object::PyObject; use moduleobject::PyModuleDef; +use methodobject::PyMethodDef; extern "C" { pub fn PyArg_Parse(arg1: *mut PyObject, arg2: *const c_char, ...) diff --git a/python3-sys/src/objimpl.rs b/python3-sys/src/objimpl.rs index 3a3385e4..838de566 100644 --- a/python3-sys/src/objimpl.rs +++ b/python3-sys/src/objimpl.rs @@ -10,6 +10,7 @@ extern "C" { -> *mut c_void; pub fn PyObject_Free(ptr: *mut c_void) -> (); + #[cfg(Py_3_4)] pub fn _Py_GetAllocatedBlocks() -> Py_ssize_t; pub fn PyObject_Init(arg1: *mut PyObject, arg2: *mut PyTypeObject) -> *mut PyObject; diff --git a/python3-sys/src/pyerrors.rs b/python3-sys/src/pyerrors.rs index 322ee58e..60c902b7 100644 --- a/python3-sys/src/pyerrors.rs +++ b/python3-sys/src/pyerrors.rs @@ -125,6 +125,7 @@ extern "C" { pub fn PyErr_SetFromErrnoWithFilenameObject(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject; + #[cfg(Py_3_4)] pub fn PyErr_SetFromErrnoWithFilenameObjects(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) @@ -134,9 +135,6 @@ extern "C" { -> *mut PyObject; pub fn PyErr_Format(exception: *mut PyObject, format: *const c_char, ...) -> *mut PyObject; - pub fn PyErr_SetExcWithArgsKwargs(arg1: *mut PyObject, - arg2: *mut PyObject, - arg3: *mut PyObject) -> *mut PyObject; pub fn PyErr_SetImportError(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject) -> *mut PyObject; pub fn PyErr_BadInternalCall() -> (); diff --git a/tests/check_symbols.py b/tests/check_symbols.py new file mode 100755 index 00000000..5b1a706d --- /dev/null +++ b/tests/check_symbols.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +import sysconfig +import subprocess +import json +import os +import sys + +os.chdir(os.path.dirname(__file__)) + +so_files = [ + sysconfig.get_config_var("LIBDIR")+"/"+sysconfig.get_config_var("LDLIBRARY"), + sysconfig.get_config_var("LIBPL")+"/"+sysconfig.get_config_var("LDLIBRARY") +] +so_file = None +for name in so_files: + if os.path.isfile(name): + so_file = name +if not so_file: + print('Could not find %r' % so_files) + sys.exit(1) + +so_symbols = set() +for line in subprocess.check_output(['readelf', '-Ws', so_file]).splitlines(): + if line: + so_symbols.add(line.decode('utf-8').split()[-1]) + +assert 'PyList_Type' in so_symbols +assert 'PyList_New' in so_symbols + +cfgs = [] +if sys.version_info.major == 3: + sys_lib = 'python3-sys' + for i in range(4, sys.version_info.minor+1): + cfgs += ['--cfg', 'Py_3_{}'.format(i)] +else: + sys_lib = 'python27-sys' + +interesting_config_flags = [ + "Py_USING_UNICODE", + "Py_UNICODE_WIDE", + "WITH_THREAD", + "Py_DEBUG", + "Py_REF_DEBUG", + "Py_TRACE_REFS", + "COUNT_ALLOCS" +] +for name in interesting_config_flags: + if sysconfig.get_config_var(name): + cfgs += ['--cfg', 'py_sys_config="{}"'.format(name)] +interesting_config_values = ['Py_UNICODE_SIZE'] +for name in interesting_config_values: + cfgs += ['--cfg', 'py_sys_config="{}_{}"'.format(name, sysconfig.get_config_var(name))] + + +json_output = subprocess.check_output(['rustc', '-Z', 'ast-json', '../{}/src/lib.rs'.format(sys_lib)] + cfgs) +doc = json.loads(json_output.decode('utf-8')) +foreign_symbols = set() +def visit(node): + if isinstance(node, dict): + node_node = node.get('node', None) + if isinstance(node_node, dict) and node_node.get('variant') in ('ForeignItemStatic', 'ForeignItemFn'): + foreign_symbols.add(node['ident']) + for v in node.values(): + visit(v) + elif isinstance(node, list): + for v in node: + visit(v) + elif isinstance(node, (int, type(u''), bool, type(None))): + pass + else: + raise Exception('Unsupported node type {}'.format(type(node))) +visit(doc) + +assert 'PyList_Type' in foreign_symbols +assert 'PyList_New' in foreign_symbols + +names = sorted(foreign_symbols - so_symbols) +if names: + print('Symbols missing in {}:'.format(so_file)) + print('\n'.join(names)) + sys.exit(1) +else: + print('Symbols in {} OK.'.format(so_file)) +