Skip to content

Commit

Permalink
Trac #33029: Feature and doctest tag for runtime cython
Browse files Browse the repository at this point in the history
While updating the sagemath Debian package I noticed that when running
the doctests for the installed sagemath package I get many failing tests
such as the one below if library development files are not installed (in
the example libm4ri-dev is not installed). The sagemath packages should
not depend on lib*-dev packages, but sagemath is looking for pkgconfig
files which are in these packages. Could this check for pkgconfig files
in the test suite be avoided?

{{{
sage -t --long --random-seed=0 sage/src/sage/arith/long.pxd
**********************************************************************
File "sage/src/sage/arith/long.pxd", line 116, in
sage.arith.long.integer_check_long
Failed example:
    cython('''
    from sage.arith.long cimport *
    from sage.rings.integer cimport smallInteger
    def check_long(x):
        cdef long value
        cdef int err
        cdef bint c = integer_check_long(x, &value, &err)
        if c:
            if err == 0:
                return value
            elif err == ERR_OVERFLOW:
                raise OverflowError("integer_check_long: overflow")
        elif err == ERR_TYPE:
            raise TypeError("integer_check_long: wrong type")
        elif err == ERR_INDEX:
            raise TypeError("integer_check_long: bad __index__")
        assert False
    from libc.limits cimport LONG_MIN, LONG_MAX
    def long_min():
        return smallInteger(LONG_MIN)
    def long_max():
        return smallInteger(LONG_MAX)
    ''')
Exception raised:
    Traceback (most recent call last):
      File "sage/misc/cachefunc.pyx", line 996, in
sage.misc.cachefunc.CachedFunction.__call__
(build/cythonized/sage/misc/cachefunc.c:5970)
        return self.cache[k]
    KeyError: ((), ())

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/usr/lib/python3/dist-packages/sage/doctest/forker.py", line
718, in _run
        self.compile_and_execute(example, compiler, test.globs)
      File "/usr/lib/python3/dist-packages/sage/doctest/forker.py", line
1137, in compile_and_execute
        exec(compiled, globs)
      File "<doctest sage.arith.long.integer_check_long[0]>", line 1, in
<module>
        cython('''
      File "sage/misc/lazy_import.pyx", line 362, in
sage.misc.lazy_import.LazyImport.__call__
(build/cythonized/sage/misc/lazy_import.c:4049)
        return self.get_object()(*args, **kwds)
      File "/usr/lib/python3/dist-packages/sage/misc/cython.py", line
661, in cython_compile
        return cython_import_all(tmpfile, get_globals(), **kwds)
      File "/usr/lib/python3/dist-packages/sage/misc/cython.py", line
551, in cython_import_all
        m = cython_import(filename, **kwds)
      File "/usr/lib/python3/dist-packages/sage/misc/cython.py", line
526, in cython_import
        name, build_dir = cython(filename, **kwds)
      File "/usr/lib/python3/dist-packages/sage/misc/cython.py", line
284, in cython
        standard_libs, standard_libdirs, standard_includes, aliases =
_standard_libs_libdirs_incdirs_aliases()
      File "sage/misc/cachefunc.pyx", line 1001, in
sage.misc.cachefunc.CachedFunction.__call__
(build/cythonized/sage/misc/cachefunc.c:6098)
        w = self.f(*args, **kwds)
      File "/usr/lib/python3/dist-packages/sage/misc/cython.py", line
50, in _standard_libs_libdirs_incdirs_aliases
        aliases = cython_aliases()
      File "/usr/lib/python3/dist-packages/sage/env.py", line 475, in
cython_aliases
        aliases[var + "CFLAGS"] = pkgconfig.cflags(lib).split()
      File "/usr/lib/python3/dist-packages/pkgconfig/pkgconfig.py", line
144, in cflags
        _raise_if_not_exists(package)
      File "/usr/lib/python3/dist-packages/pkgconfig/pkgconfig.py", line
103, in _raise_if_not_exists
        raise PackageNotFoundError(package)
    pkgconfig.pkgconfig.PackageNotFoundError: m4ri not found
}}}

URL: https://trac.sagemath.org/33029
Reported by: thansen
Ticket author(s): Matthias Koeppe
Reviewer(s): Sébastien Labbé
  • Loading branch information
Release Manager committed Jul 1, 2022
2 parents be2bda4 + 1440273 commit b5d2fca
Show file tree
Hide file tree
Showing 27 changed files with 212 additions and 179 deletions.
4 changes: 2 additions & 2 deletions src/sage/arith/long.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ cdef inline bint integer_check_long(x, long* value, int* err) except -1:
We create a pure Python wrapper of this function::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.arith.long cimport *
....: from sage.rings.integer cimport smallInteger
....: def check_long(x):
Expand Down Expand Up @@ -273,7 +273,7 @@ cdef inline bint is_small_python_int(obj):
EXAMPLES::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.arith.long cimport is_small_python_int
....: def is_small_wrapper(x):
....: return is_small_python_int(x)
Expand Down
4 changes: 2 additions & 2 deletions src/sage/cpython/cython_metaclass.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ In Python, this would be ``meta.__init__(cls, name, bases, dict)``.
EXAMPLES::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: cimport sage.cpython.cython_metaclass
....: cdef class MyCustomType():
....: def __getmetaclass__(_):
Expand Down Expand Up @@ -98,7 +98,7 @@ TESTS:
Check that a proper exception is raised if ``__getmetaclass__``
returns a non-type::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: cimport sage.cpython.cython_metaclass
....: cdef class MyCustomType():
....: def __getmetaclass__(_):
Expand Down
12 changes: 6 additions & 6 deletions src/sage/cpython/getattr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -406,13 +406,13 @@ def dir_with_other_class(self, *cls):
Check that objects without dicts are well handled::
sage: cython("cdef class A:\n cdef public int a")
sage: cython("cdef class B:\n cdef public int b")
sage: x = A()
sage: x.a = 1
sage: hasattr(x,'__dict__')
sage: cython("cdef class A:\n cdef public int a") # optional - sage.misc.cython
sage: cython("cdef class B:\n cdef public int b") # optional - sage.misc.cython
sage: x = A() # optional - sage.misc.cython
sage: x.a = 1 # optional - sage.misc.cython
sage: hasattr(x,'__dict__') # optional - sage.misc.cython
False
sage: dir_with_other_class(x, B)
sage: dir_with_other_class(x, B) # optional - sage.misc.cython
[..., 'a', 'b']
TESTS:
Expand Down
2 changes: 1 addition & 1 deletion src/sage/cpython/string.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ TESTS:
Check that this can be used outside of Sage (see :trac:`25549`)::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.cpython.string cimport char_to_str
....: print(char_to_str("hello world!"))
....: ''')
Expand Down
2 changes: 1 addition & 1 deletion src/sage/cpython/wrapperdescr.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ cdef inline wrapperbase* get_slotdef(wrapper_descriptor slotwrapper) except NULL
TESTS::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.cpython.wrapperdescr cimport get_slotdef
....: from cpython.long cimport PyLong_FromVoidPtr
....: def py_get_slotdef(slotwrapper):
Expand Down
2 changes: 1 addition & 1 deletion src/sage/docs/instancedoc.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ EXAMPLES::
For a Cython ``cdef class``, a decorator cannot be used. Instead, call
:func:`instancedoc` as a function after defining the class::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.misc.instancedoc import instancedoc
....: cdef class Y:
....: "Class docstring"
Expand Down
2 changes: 1 addition & 1 deletion src/sage/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ def cython_aliases(required_modules=None,
We can use ``cython.parallel`` regardless of whether OpenMP is supported.
This will run in parallel, if OpenMP is supported::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: #distutils: extra_compile_args = OPENMP_CFLAGS
....: #distutils: extra_link_args = OPENMP_CFLAGS
....: from cython.parallel import prange
Expand Down
6 changes: 3 additions & 3 deletions src/sage/ext/memory_allocator.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ cdef class MemoryAllocator:
TESTS::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.ext.memory_allocator cimport MemoryAllocator
....: cdef MemoryAllocator mem = MemoryAllocator()
....: cdef void* ptr
Expand Down Expand Up @@ -85,7 +85,7 @@ cdef class MemoryAllocator:
TESTS::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.ext.memory_allocator cimport MemoryAllocator
....: def foo():
....: cdef MemoryAllocator mem = MemoryAllocator()
Expand Down Expand Up @@ -120,7 +120,7 @@ cdef class MemoryAllocator:
TESTS::
sage: cython('''
sage: cython(''' # optional - sage.misc.cython
....: from sage.ext.memory_allocator cimport MemoryAllocator
....: def foo():
....: cdef MemoryAllocator mem = MemoryAllocator()
Expand Down
2 changes: 2 additions & 0 deletions src/sage/ext/memory_allocator.pyx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# sage.doctest: optional - sage.misc.cython

from cysignals.memory cimport *
from sage.misc.superseded import deprecation

Expand Down
29 changes: 29 additions & 0 deletions src/sage/features/cython.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
r"""
Features for testing the presence of ``cython``
"""

from . import CythonFeature


class sage__misc__cython(CythonFeature):
r"""
A :class:`~sage.features.Feature` which describes whether :mod:`sage.misc.cython`
is available and functional.
"""
def __init__(self):
r"""
TESTS::
sage: from sage.features import CythonFeature
sage: from sage.features.cython import sage__misc__cython
sage: isinstance(sage__misc__cython(), CythonFeature)
True
"""
# It suffices to use a trivial CythonFeature because CythonFeature
# is implemented via sage.misc.cython.
CythonFeature.__init__(self, "sage.misc.cython", test_code="")


def all_features():
return [sage__misc__cython()]
4 changes: 2 additions & 2 deletions src/sage/graphs/connectivity.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2712,7 +2712,7 @@ cdef class _Component:
....: 'comp.add_edge(3)',
....: 'comp.finish_tric_or_poly(4)',
....: 'print(comp)']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
Polygon: 2 3 4
"""
self.mem = MemoryAllocator()
Expand Down Expand Up @@ -2759,7 +2759,7 @@ cdef class _Component:
....: 'comp.add_edge(3)',
....: 'comp.finish_tric_or_poly(4)',
....: 'print(comp)']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
Polygon: 2 3 4
"""
if self.component_type == 0:
Expand Down
10 changes: 5 additions & 5 deletions src/sage/graphs/graph_decompositions/fast_digraph.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ cdef class FastDigraph:
....: 'cdef FastDigraph F = FastDigraph(G)',
....: 'cdef int i',
....: 'print([F.degree[i] for i in range(F.n)])']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
[1, 2, 1]
"""
if D.order() > 8*sizeof(int):
Expand Down Expand Up @@ -99,7 +99,7 @@ cdef class FastDigraph:
....: 'from sage.graphs.graph import Graph',
....: 'from sage.graphs.graph_decompositions.fast_digraph cimport FastDigraph',
....: 'FastDigraph(Graph([(0, 1), (1, 2)])).print_adjacency_matrix()']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
010
101
010
Expand Down Expand Up @@ -129,7 +129,7 @@ cdef inline int compute_out_neighborhood_cardinality(FastDigraph g, int S):
....: 'cdef FastDigraph F = FastDigraph(Graph([(0, 1), (1, 2)]))',
....: 'cdef int i',
....: 'print([compute_out_neighborhood_cardinality(F, 1<<i) for i in range(F.n)])']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
[1, 2, 1]
"""
cdef int i
Expand All @@ -153,7 +153,7 @@ cdef inline int popcount32(int i):
....: 'from sage.graphs.graph_decompositions.fast_digraph cimport popcount32',
....: 'cdef int i',
....: 'print([popcount32(i) for i in range(16)])']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
[0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4]
"""
i = i - ((i >> 1) & 0x55555555)
Expand Down Expand Up @@ -199,7 +199,7 @@ cdef inline int slow_popcount32(int i):
....: 'from sage.graphs.graph_decompositions.fast_digraph cimport slow_popcount32',
....: 'cdef int i',
....: 'print(all(popcount32(i) == slow_popcount32(i) for i in range(16)))']
sage: cython(os.linesep.join(cython_code))
sage: cython(os.linesep.join(cython_code)) # optional - sage.misc.cython
True
"""
# Slow popcount for 32bits integers
Expand Down
Loading

0 comments on commit b5d2fca

Please sign in to comment.