Commit f35173fb authored by gabrieldemarmiesse's avatar gabrieldemarmiesse

Now all the files in the example directory are tested.

parent 45df4830
This example directory is organized like the ``Cython/docs/src/`` directory,
with one directory per ``.rst`` file. All files in this directory are tested
in the :file:`runtests.py` with the mode `compile`.
def say_hello_to(name):
print("Hello %s!" % name)
from distutils.core import setup from distutils.core import setup
from Cython.Build import cythonize from Cython.Build import cythonize
setup( setup(name='Hello world app',
ext_modules=cythonize("primes.pyx"), ext_modules=cythonize("hello.pyx"))
)
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
from libcpp.vector cimport vector from libcpp.vector cimport vector
def primes(int nb_primes): def primes(unsigned int nb_primes):
cdef int n, i cdef int n, i
cdef vector[int] p cdef vector[int] p
p.reserve(nb_primes) # allocate memory for 'nb_primes' elements. p.reserve(nb_primes) # allocate memory for 'nb_primes' elements.
......
import math
def great_circle(lon1, lat1, lon2, lat2):
radius = 3956 # miles
x = math.pi/180.0
a = (90.0 - lat1)*x
b = (90.0 - lat2)*x
theta = (lon2 - lon1)*x
c = math.acos(math.cos(a)*math.cos(b) + math.sin(a)*math.sin(b)*math.cos(theta))
return radius*c
import math
def great_circle(double lon1, double lat1, double lon2, double lat2):
cdef double radius = 3956 # miles
cdef double x = math.pi/180.0
cdef double a, b, theta, c
a = (90.0 - lat1)*x
b = (90.0 - lat2)*x
theta = (lon2 - lon1)*x
c = math.acos(math.cos(a)*math.cos(b) + math.sin(a)*math.sin(b)*math.cos(theta))
return radius*c
import math
def great_circle(lon1, lat1, lon2, lat2):
radius = 3956 # miles
x = math.pi/180.0
a = (90.0 - lat1)*x
b = (90.0 - lat2)*x
theta = (lon2 - lon1)*x
c = math.acos(math.cos(a)*math.cos(b) + math.sin(a)*math.sin(b)*math.cos(theta))
return radius*c
...@@ -37,20 +37,13 @@ The other methods are described in more detail in the :ref:`compilation` section ...@@ -37,20 +37,13 @@ The other methods are described in more detail in the :ref:`compilation` section
Building a Cython module using distutils Building a Cython module using distutils
---------------------------------------- ----------------------------------------
Imagine a simple "hello world" script in a file ``hello.pyx``:: Imagine a simple "hello world" script in a file ``hello.pyx``:
def say_hello_to(name): .. literalinclude:: ../../examples/quickstart/build/hello.pyx
print("Hello %s!" % name)
The following could be a corresponding ``setup.py`` script:: The following could be a corresponding ``setup.py`` script:
from distutils.core import setup .. literalinclude:: ../../examples/quickstart/build/setup.py
from Cython.Build import cythonize
setup(
name = 'Hello world app',
ext_modules = cythonize("hello.pyx"),
)
To build, run ``python setup.py build_ext --inplace``. Then simply To build, run ``python setup.py build_ext --inplace``. Then simply
start a Python session and do ``from hello import say_hello_to`` and start a Python session and do ``from hello import say_hello_to`` and
......
...@@ -97,7 +97,7 @@ Fibonacci Fun ...@@ -97,7 +97,7 @@ Fibonacci Fun
From the official Python tutorial a simple fibonacci function is defined as: From the official Python tutorial a simple fibonacci function is defined as:
.. literalinclude:: ../../examples/tutorial/fib1/fib.pyx .. literalinclude:: ../../examples/tutorial/cython_tutorial/fib.pyx
Now following the steps for the Hello World example we first rename the file Now following the steps for the Hello World example we first rename the file
to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the
...@@ -105,7 +105,7 @@ to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the ...@@ -105,7 +105,7 @@ to have a `.pyx` extension, lets say :file:`fib.pyx`, then we create the
that you need to change is the name of the Cython filename, and the resulting that you need to change is the name of the Cython filename, and the resulting
module name, doing this we have: module name, doing this we have:
.. literalinclude:: ../../examples/tutorial/fib1/setup.py .. literalinclude:: ../../examples/tutorial/cython_tutorial/setup.py
Build the extension with the same command used for the helloworld.pyx: Build the extension with the same command used for the helloworld.pyx:
...@@ -130,7 +130,7 @@ them as a Python list. ...@@ -130,7 +130,7 @@ them as a Python list.
:file:`primes.pyx`: :file:`primes.pyx`:
.. literalinclude:: ../../examples/tutorial/primes/primes.pyx .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes.pyx
:linenos: :linenos:
You'll see that it starts out just like a normal Python function definition, You'll see that it starts out just like a normal Python function definition,
...@@ -352,7 +352,7 @@ standard library. ...@@ -352,7 +352,7 @@ standard library.
how many elements you are going to put in the vector. For more details how many elements you are going to put in the vector. For more details
see `this page from cppreference <http://en.cppreference.com/w/cpp/container/vector>`_. see `this page from cppreference <http://en.cppreference.com/w/cpp/container/vector>`_.
.. literalinclude:: ../../examples/tutorial/primes/primes_cpp.pyx .. literalinclude:: ../../examples/tutorial/cython_tutorial/primes_cpp.pyx
:linenos: :linenos:
The first line is a compiler directive. It tells Cython to compile your code to C++. The first line is a compiler directive. It tells Cython to compile your code to C++.
......
...@@ -703,19 +703,19 @@ manage an array (allocate and deallocate) with NumPy (it can also be Python arra ...@@ -703,19 +703,19 @@ manage an array (allocate and deallocate) with NumPy (it can also be Python arra
anything that supports the buffer interface), but you want to perform computation on this anything that supports the buffer interface), but you want to perform computation on this
array with an external C function implemented in :file:`C_func_file.c`: array with an external C function implemented in :file:`C_func_file.c`:
.. literalinclude:: ../../examples/memoryviews/C_func_file.c .. literalinclude:: ../../examples/userguide/memoryviews/C_func_file.c
:linenos: :linenos:
This file comes with a header file called :file:`C_func_file.h` containing: This file comes with a header file called :file:`C_func_file.h` containing:
.. literalinclude:: ../../examples/memoryviews/C_func_file.h .. literalinclude:: ../../examples/userguide/memoryviews/C_func_file.h
:linenos: :linenos:
where ``arr`` points to the array and ``n`` is its size. where ``arr`` points to the array and ``n`` is its size.
You can call the function in a Cython file in the following way: You can call the function in a Cython file in the following way:
.. literalinclude:: ../../examples/memoryviews/memview_to_c.pyx .. literalinclude:: ../../examples/userguide/memoryviews/memview_to_c.pyx
:linenos: :linenos:
Several things to note: Several things to note:
......
...@@ -144,7 +144,7 @@ valid Python and valid Cython code. I'll refer to it as both ...@@ -144,7 +144,7 @@ valid Python and valid Cython code. I'll refer to it as both
:file:`convolve_py.py` for the Python version and :file:`convolve_cy.pyx` for the :file:`convolve_py.py` for the Python version and :file:`convolve_cy.pyx` for the
Cython version -- Cython uses ".pyx" as its file suffix. Cython version -- Cython uses ".pyx" as its file suffix.
.. literalinclude:: ../../examples/memoryviews/convolve_py.py .. literalinclude:: ../../examples/userguide/numpy_tutorial/convolve_py.py
:linenos: :linenos:
This should be compiled to produce :file:`convolve_cy.so` (for Linux systems). We This should be compiled to produce :file:`convolve_cy.so` (for Linux systems). We
...@@ -194,7 +194,7 @@ Adding types ...@@ -194,7 +194,7 @@ Adding types
To add types we use custom Cython syntax, so we are now breaking Python source To add types we use custom Cython syntax, so we are now breaking Python source
compatibility. Here's :file:`convolve_typed.pyx`. *Read the comments!* compatibility. Here's :file:`convolve_typed.pyx`. *Read the comments!*
.. literalinclude:: ../../examples/memoryviews/convolve_typed.pyx .. literalinclude:: ../../examples/userguide/numpy_tutorial/convolve_typed.pyx
:linenos: :linenos:
.. figure:: convolve_types_html.png .. figure:: convolve_types_html.png
...@@ -269,7 +269,7 @@ Here is how to use them in our code: ...@@ -269,7 +269,7 @@ Here is how to use them in our code:
:file:`convolve_memview.pyx` :file:`convolve_memview.pyx`
.. literalinclude:: ../../examples/memoryviews/convolve_memview.pyx .. literalinclude:: ../../examples/userguide/numpy_tutorial/convolve_memview.pyx
:linenos: :linenos:
Let's see how much faster accessing is now. Let's see how much faster accessing is now.
...@@ -381,7 +381,7 @@ our code. This is why, we must still declare manually the type of the ...@@ -381,7 +381,7 @@ our code. This is why, we must still declare manually the type of the
And actually, manually giving the type of the ``value`` variable will And actually, manually giving the type of the ``value`` variable will
be useful when using fused types. be useful when using fused types.
.. literalinclude:: ../../examples/memoryviews/convolve_infer_types.pyx .. literalinclude:: ../../examples/userguide/numpy_tutorial/convolve_infer_types.pyx
:linenos: :linenos:
We now do a speed test: We now do a speed test:
...@@ -416,7 +416,7 @@ know what NumPy data type we should use for our output array. ...@@ -416,7 +416,7 @@ know what NumPy data type we should use for our output array.
In this case, our function now works for ints, doubles and floats. In this case, our function now works for ints, doubles and floats.
.. literalinclude:: ../../examples/memoryviews/convolve_fused_types.pyx .. literalinclude:: ../../examples/userguide/numpy_tutorial/convolve_fused_types.pyx
:linenos: :linenos:
We can check that the output type is the right one:: We can check that the output type is the right one::
......
...@@ -16,6 +16,7 @@ import tempfile ...@@ -16,6 +16,7 @@ import tempfile
import traceback import traceback
import warnings import warnings
import zlib import zlib
import glob
try: try:
import platform import platform
...@@ -639,14 +640,14 @@ class TestBuilder(object): ...@@ -639,14 +640,14 @@ class TestBuilder(object):
expect_warnings = 'warnings' in tags['tag'] expect_warnings = 'warnings' in tags['tag']
if expect_errors: if expect_errors:
if 'cpp' in tags['tag'] and 'cpp' in self.languages: if skip_c(tags) and 'cpp' in self.languages:
languages = ['cpp'] languages = ['cpp']
else: else:
languages = self.languages[:1] languages = self.languages[:1]
else: else:
languages = self.languages languages = self.languages
if 'cpp' in tags['tag'] and 'c' in languages: if skip_c(tags) and 'c' in languages:
languages = list(languages) languages = list(languages)
languages.remove('c') languages.remove('c')
elif 'no-cpp' in tags['tag'] and 'cpp' in self.languages: elif 'no-cpp' in tags['tag'] and 'cpp' in self.languages:
...@@ -693,6 +694,22 @@ class TestBuilder(object): ...@@ -693,6 +694,22 @@ class TestBuilder(object):
pythran_dir=pythran_dir) pythran_dir=pythran_dir)
def skip_c(tags):
if 'cpp' in tags['tag']:
return True
# We don't want to create a distutils key in the
# dictionary so we check before looping.
if 'distutils' in tags:
for option in tags['distutils']:
splitted = option.split('=')
if len(splitted) == 2:
argument, value = splitted
if argument.strip() == 'language' and value.strip() == 'c++':
return True
return False
class CythonCompileTestCase(unittest.TestCase): class CythonCompileTestCase(unittest.TestCase):
def __init__(self, test_directory, workdir, module, tags, language='c', preparse='id', def __init__(self, test_directory, workdir, module, tags, language='c', preparse='id',
expect_errors=False, expect_warnings=False, annotate=False, cleanup_workdir=True, expect_errors=False, expect_warnings=False, annotate=False, cleanup_workdir=True,
...@@ -2139,12 +2156,13 @@ def runtests(options, cmd_args, coverage=None): ...@@ -2139,12 +2156,13 @@ def runtests(options, cmd_args, coverage=None):
options.pythran_dir, add_embedded_test=True) options.pythran_dir, add_embedded_test=True)
test_suite.addTest(filetests.build_suite()) test_suite.addTest(filetests.build_suite())
if options.examples and languages: if options.examples and languages:
filetests = TestBuilder(options.examples_dir, WORKDIR, selectors, exclude_selectors, for subdirectory in glob.glob(os.path.join(options.examples_dir, "*/")):
options, options.pyregr, languages, test_bugs, filetests = TestBuilder(subdirectory, WORKDIR, selectors, exclude_selectors,
options.language_level, common_utility_dir, options, options.pyregr, languages, test_bugs,
options.pythran_dir, options.language_level, common_utility_dir,
default_mode='compile') options.pythran_dir,
test_suite.addTest(filetests.build_suite()) default_mode='compile')
test_suite.addTest(filetests.build_suite())
if options.system_pyregr and languages: if options.system_pyregr and languages:
sys_pyregr_dir = os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test') sys_pyregr_dir = os.path.join(sys.prefix, 'lib', 'python'+sys.version[:3], 'test')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment