Imported Upstream version 0.28.1 upstream/0.28.1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 03:02:44 +0000 (12:02 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 03:02:44 +0000 (12:02 +0900)
44 files changed:
.gitignore
CHANGES.rst
Cython/Compiler/ExprNodes.py
Cython/Compiler/ModuleNode.py
Cython/Compiler/Optimize.py
Cython/Compiler/PyrexTypes.py
Cython/Debugger/libcython.py
Cython/Shadow.py
Cython/Utility/Builtins.c
Cython/Utility/MemoryView.pyx
Cython/Utility/ObjectHandling.c
Cython/Utility/Optimize.c
Demos/README.rst [new file with mode: 0644]
Demos/Readme_demos.rst [deleted file]
Demos/benchmarks/bpnn3.py
Demos/callback/README.rst [new file with mode: 0644]
Demos/callback/README.txt [deleted file]
Demos/embed/README [deleted file]
Demos/embed/README.rst [new file with mode: 0644]
Demos/freeze/README.rst [new file with mode: 0644]
Demos/freeze/README.txt [deleted file]
MANIFEST.in
Makefile
README.rst [new file with mode: 0644]
README.txt [deleted file]
bin/cython_freeze
docs/examples/tutorial/fib1/fib.pyx
docs/examples/tutorial/primes/primes.pyx
docs/src/quickstart/build.rst
docs/src/quickstart/cythonize.rst
docs/src/quickstart/install.rst
docs/src/tutorial/cython_tutorial.rst
docs/src/tutorial/htmlreport.png [new file with mode: 0644]
docs/src/tutorial/python_division.png [new file with mode: 0644]
docs/src/userguide/language_basics.rst
docs/src/userguide/numpy_tutorial.rst
pyximport/README [deleted file]
pyximport/README.rst [new file with mode: 0644]
runtests.py
tests/run/__getattribute_subclasses__.pyx
tests/run/bytes_formatting.pyx [new file with mode: 0644]
tests/run/cpp_classes.pyx
tests/run/cpp_smart_ptr.pyx
tests/run/dict_pop.pyx

index e8d805c59e8ac2a0db60af160a86a2c1256c9f64..9658e731b3958a087e7f42f6dec1ef92bf2b8428 100644 (file)
@@ -11,6 +11,7 @@ Cython/Compiler/*.c
 Cython/Plex/*.c
 Cython/Runtime/refnanny.c
 Cython/Tempita/*.c
+Cython/*.c
 
 Tools/*.elc
 
index e0d275d89398054a4ef5f7a3683c55c0ecc80970..cd271725ed683fd69e6845f33b7851b6b5a2723b 100644 (file)
@@ -2,6 +2,31 @@
 Cython Changelog
 ================
 
+0.28.1 (2018-03-18)
+===================
+
+Bugs fixed
+----------
+
+* ``PyFrozenSet_New()`` was accidentally used in PyPy where it is missing
+  from the C-API.
+
+* Assignment between some C++ templated types were incorrectly rejected
+  when the templates mix ``const`` with ``ctypedef``.
+  (Github issue #2148)
+
+* Undeclared C++ no-args constructors in subclasses could make the compilation
+  fail if the base class constructor was declared without ``nogil``.
+  (Github issue #2157)
+
+* Bytes %-formatting inferred ``basestring`` (bytes or unicode) as result type
+  in some cases where ``bytes`` would have been safe to infer.
+  (Github issue #2153)
+
+* ``None`` was accidentally disallowed as typed return value of ``dict.pop()``.
+  (Github issue #2152)
+
+
 0.28 (2018-03-13)
 =================
 
index 7e10c6d1af351c521f98b26267755dc56ab19a93..765b020e1a0bbffc69bfecf92bb04ab83865a735 100644 (file)
@@ -16,6 +16,7 @@ cython.declare(error=object, warning=object, warn_once=object, InternalError=obj
                bytearray_type=object, slice_type=object, _py_int_types=object,
                IS_PYTHON3=cython.bint)
 
+import re
 import sys
 import copy
 import os.path
@@ -1729,12 +1730,7 @@ class NewExprNode(AtomicExprNode):
             self.type = error_type
             return
         self.cpp_check(env)
-        constructor = type.scope.lookup(u'<init>')
-        if constructor is None:
-            func_type = PyrexTypes.CFuncType(
-                type, [], exception_check='+', nogil=True)
-            type.scope.declare_cfunction(u'<init>', func_type, self.pos)
-            constructor = type.scope.lookup(u'<init>')
+        constructor = type.get_constructor(self.pos)
         self.class_type = type
         self.entry = constructor
         self.type = constructor.type
@@ -11489,6 +11485,20 @@ class DivNode(NumBinopNode):
                 self.operand2.result())
 
 
+_find_formatting_types = re.compile(
+    br"%"
+    br"(?:%|"  # %%
+    br"(?:\([^)]+\))?"  # %(name)
+    br"[-+#,0-9 ]*([a-z])"  # %.2f  etc.
+    br")").findall
+
+# These format conversion types can never trigger a Unicode string conversion in Py2.
+_safe_bytes_formats = set([
+    # Excludes 's' and 'r', which can generate non-bytes strings.
+    b'd', b'i', b'o', b'u', b'x', b'X', b'e', b'E', b'f', b'F', b'g', b'G', b'c', b'b', b'a',
+])
+
+
 class ModNode(DivNode):
     #  '%' operator.
 
@@ -11498,7 +11508,7 @@ class ModNode(DivNode):
                 or NumBinopNode.is_py_operation_types(self, type1, type2))
 
     def infer_builtin_types_operation(self, type1, type2):
-        # b'%s' % xyz  raises an exception in Py3, so it's safe to infer the type for Py2
+        # b'%s' % xyz  raises an exception in Py3<3.5, so it's safe to infer the type for Py2 and later Py3's.
         if type1 is unicode_type:
             # None + xyz  may be implemented by RHS
             if type2.is_builtin_type or not self.operand1.may_be_none():
@@ -11508,6 +11518,11 @@ class ModNode(DivNode):
                 return type2
             elif type2.is_numeric:
                 return type1
+            elif self.operand1.is_string_literal:
+                if type1 is str_type or type1 is bytes_type:
+                    if set(_find_formatting_types(self.operand1.value)) <= _safe_bytes_formats:
+                        return type1
+                return basestring_type
             elif type1 is bytes_type and not type2.is_builtin_type:
                 return None   # RHS might implement '% operator differently in Py3
             else:
index 31266ec80e2be7fecb4b6cebc10ee15afc0c9a80..3e18010efe6b94cb36d50e666586d20b67552323 100644 (file)
@@ -2297,7 +2297,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
         code.putln("")
         # main module init code lives in Py_mod_exec function, not in PyInit function
-        code.putln("static int %s(PyObject *%s) CYTHON_SMALL_CODE " % (
+        code.putln("static int %s(PyObject *%s)" % (
             self.mod_init_func_cname(Naming.pymodule_exec_func_cname, env),
             Naming.pymodinit_module_arg))
         code.putln("#endif")  # PEP489
index 66c18013a1eecf39b51b29bdb9e798c904ac45fb..bf35cd5a50d3d07d50a20bcb3a02ad0b5eade72e 100644 (file)
@@ -3150,6 +3150,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
             node, function,
             "__Pyx_PyDict_Pop", self.PyDict_Pop_func_type,
             'pop', is_unbound_method, args,
+            may_return_none=True,
             utility_code=load_c_utility('py_dict_pop'))
 
     Pyx_PyInt_BinopInt_func_type = PyrexTypes.CFuncType(
index be28e48c235488a5109df539e3a201e4935a79bd..029b7a646cb456d68b838679bb7ece40fdbcaab9 100644 (file)
@@ -1595,6 +1595,12 @@ class CConstType(BaseType):
             self.to_py_function = self.const_base_type.to_py_function
             return True
 
+    def same_as_resolved_type(self, other_type):
+        if other_type.is_const:
+            return self.const_base_type.same_as_resolved_type(other_type.const_base_type)
+        # Accept const LHS <- non-const RHS.
+        return self.const_base_type.same_as_resolved_type(other_type)
+
     def __getattr__(self, name):
         return getattr(self.const_base_type, name)
 
@@ -3773,14 +3779,14 @@ class CppClassType(CType):
                 return 1
             # This messy logic is needed due to GH Issue #1852.
             elif (self.cname == other_type.cname and
-                  (self.template_type and other_type.template_type
-                   or self.templates
-                   or other_type.templates)):
+                    (self.template_type and other_type.template_type
+                     or self.templates
+                     or other_type.templates)):
                 if self.templates == other_type.templates:
                     return 1
                 for t1, t2 in zip(self.templates, other_type.templates):
                     if is_optional_template_param(t1) and is_optional_template_param(t2):
-                      break
+                        break
                     if not t1.same_as_resolved_type(t2):
                         return 0
                 return 1
@@ -3811,6 +3817,23 @@ class CppClassType(CType):
             func_type = func_type.base_type
         return func_type.return_type
 
+    def get_constructor(self, pos):
+        constructor = self.scope.lookup('<init>')
+        if constructor is not None:
+            return constructor
+
+        # Otherwise: automatically declare no-args default constructor.
+        # Make it "nogil" if the base classes allow it.
+        nogil = True
+        for base in self.base_classes:
+            base_constructor = base.scope.lookup('<init>')
+            if base_constructor and not base_constructor.type.nogil:
+                nogil = False
+                break
+
+        func_type = CFuncType(self, [], exception_check='+', nogil=nogil)
+        return self.scope.declare_cfunction(u'<init>', func_type, pos)
+
     def check_nullary_constructor(self, pos, msg="stack allocated"):
         constructor = self.scope.lookup(u'<init>')
         if constructor is not None and best_match([], constructor.all_alternatives()) is None:
index 42546efc43738d5b7f168c4b4a2c8c7d0ad91a7d..23153789b660d566525e4904b3675d27e6dea4a6 100644 (file)
@@ -900,7 +900,7 @@ class CythonInfo(CythonBase, libpython.PythonInfo):
 
     def lineno(self, frame):
         # Take care of the Python and Cython levels. We need to care for both
-        # as we can't simply dispath to 'py-step', since that would work for
+        # as we can't simply dispatch to 'py-step', since that would work for
         # stepping through Python code, but it would not step back into Cython-
         # related code. The C level should be dispatched to the 'step' command.
         if self.is_cython_function(frame):
index 35a13e6d22713d73bdbf1d57f5186edf2bf6f4a7..96d5b11195d0f0eaafcbd20d8531e23c54c8e5e6 100644 (file)
@@ -1,7 +1,7 @@
 # cython.* namespace for pure mode.
 from __future__ import absolute_import
 
-__version__ = "0.28"
+__version__ = "0.28.1"
 
 try:
     from __builtin__ import basestring
index 57f2a4f93ac3462fbfad42ef445c4a09ba7aab00..0820d989f117f79df36b82e832988ac1979a0b9c 100644 (file)
@@ -427,7 +427,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d) {
         return CALL_UNBOUND_METHOD(PyDict_Type, "viewitems", d);
 }
 
+
 //////////////////// pyfrozenset_new.proto ////////////////////
+
+static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it);
+
+//////////////////// pyfrozenset_new ////////////////////
 //@substitute: naming
 
 static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) {
index df83fe090cf59c69fbf1a07a247c658b42bf1517..965af7b513da08031b777efe73a79554d8abb6fb 100644 (file)
@@ -543,7 +543,7 @@ cdef class memoryview(object):
 
     __pyx_getbuffer = capsule(<void *> &__pyx_memoryview_getbuffer, "getbuffer(obj, view, flags)")
 
-    # Some properties that have the same sematics as in NumPy
+    # Some properties that have the same semantics as in NumPy
     @property
     def T(self):
         cdef _memoryviewslice result = memoryview_copy(self)
index 42210577ed87616b7aec48f61b181a90da53fe1f..21c5637c3dc4c36a3a0fba229bc82e15bebcbdeb 100644 (file)
@@ -1049,6 +1049,7 @@ static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict,
 static CYTHON_INLINE int __Pyx_PySet_ContainsTF(PyObject* key, PyObject* set, int eq); /* proto */
 
 /////////////// PySetContains ///////////////
+//@requires: Builtins.c::pyfrozenset_new
 
 static int __Pyx_PySet_ContainsUnhashable(PyObject *set, PyObject *key) {
     int result = -1;
@@ -1056,7 +1057,7 @@ static int __Pyx_PySet_ContainsUnhashable(PyObject *set, PyObject *key) {
         /* Convert key to frozenset */
         PyObject *tmpkey;
         PyErr_Clear();
-        tmpkey = PyFrozenSet_New(key);
+        tmpkey = __Pyx_PyFrozenSet_New(key);
         if (tmpkey != NULL) {
             result = PySet_Contains(set, tmpkey);
             Py_DECREF(tmpkey);
index a17d7cfe46f8110412856d04d8e23ed8a71bb81e..fa5a8d5e443bbc4ab710e5660cda81da39a24b97 100644 (file)
@@ -486,6 +486,7 @@ static CYTHON_INLINE int __Pyx_set_iter_next(
 }
 
 /////////////// py_set_discard_unhashable ///////////////
+//@requires: Builtins.c::pyfrozenset_new
 
 static int __Pyx_PySet_DiscardUnhashable(PyObject *set, PyObject *key) {
     PyObject *tmpkey;
@@ -494,7 +495,7 @@ static int __Pyx_PySet_DiscardUnhashable(PyObject *set, PyObject *key) {
     if (likely(!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)))
         return -1;
     PyErr_Clear();
-    tmpkey = PyFrozenSet_New(key);
+    tmpkey = __Pyx_PyFrozenSet_New(key);
     if (tmpkey == NULL)
         return -1;
     rv = PySet_Discard(set, tmpkey);
diff --git a/Demos/README.rst b/Demos/README.rst
new file mode 100644 (file)
index 0000000..959b71f
--- /dev/null
@@ -0,0 +1,35 @@
+To run demos do::
+
+    cd Demos
+    make test
+
+which runs ``run_primes.py``, ``run_numeric_demo.py``, ``run_spam.py``,
+``integrate_timing.py``, ``callback/runcheese.py`` and ``embed/embedded``
+
+For other demos::
+
+    cd libraries
+    python setup.py build_ext --inplace
+    python -c 'import call_mymath;print(call_mymath.call_sinc(1))'
+
+To run one of the benchmarks for 10 iterations to compare cython and python timings::
+
+    cd benchmarks
+    python setup.py build_ext --inplace
+    python nqueens.py -n 10
+    python -c 'import nqueens;print(nqueens.test_n_queens(10))'
+
+To demo ``cython/bin/cython_freeze``::
+
+    make
+    ./nCr 10 5
+    ./python
+
+* Build notes
+
+  * benchmarks/chaos.py requires cython 0.24 or newer
+
+  * embed and freeze work for python2, require cython 0.24 or higher
+    for python 3.5
+
+
diff --git a/Demos/Readme_demos.rst b/Demos/Readme_demos.rst
deleted file mode 100644 (file)
index f0eb8c1..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-* To run demos do::
-
-    cd Demos
-    make test
-
-  which runs run_primes.py, run_numeric_demo.py, run_spam.py,
-  integrate_timing.py, callback/runcheese.py and embed/embedded
-
-* For other demos::
-
-    cd libraries
-    python setup.py build_ext --inplace
-    python -c 'import call_mymath;print(call_mymath.call_sinc(1))'
-
-  To run one of the benchmarks for 10 iterations to compare cython and python timings::
-
-    cd benchmarks
-    python setup.py build_ext --inplace
-    python nqueens.py -n 10
-    python -c 'import nqueens;print(nqueens.test_n_queens(10))'
-
-  To demo cython/bin/cython_freeze::
-
-    make
-    ./nCr 10 5
-    ./python
-
-* Build notes
-
-  * benchmarks/chaos.py requires cython 0.24 or newer
-
-  * embed and freeze work for python2, require cython 0.24 or higher
-    for python 3.5
-
-
index 58d6bcbd7a7ce89fd2fb8dae7bd302b4ae829d95..362bc270395373748c542c9e1ae5cf8c91961f22 100644 (file)
@@ -41,7 +41,7 @@ class NN(object):
         # create weights
         self.wi = makeMatrix(self.ni, self.nh)
         self.wo = makeMatrix(self.nh, self.no)
-        # set them to random vaules
+        # set them to random values
         for i in range(self.ni):
             for j in range(self.nh):
                 self.wi[i][j] = rand(-2.0, 2.0)
diff --git a/Demos/callback/README.rst b/Demos/callback/README.rst
new file mode 100644 (file)
index 0000000..0003668
--- /dev/null
@@ -0,0 +1,12 @@
+This example demonstrates how you can wrap a C API
+that has a callback interface, so that you can
+pass Python functions to it as callbacks.
+
+The files ``cheesefinder.h`` and ``cheesefinder.c``
+represent the C library to be wrapped.
+
+The file ``cheese.pyx`` is the Cython module
+which wraps it.
+
+The file ``run_cheese.py`` demonstrates how to
+call the wrapper.
diff --git a/Demos/callback/README.txt b/Demos/callback/README.txt
deleted file mode 100644 (file)
index 8e8abdf..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-This example demonstrates how you can wrap a C API
-that has a callback interface, so that you can
-pass Python functions to it as callbacks.
-
-The files cheesefinder.h and cheesefinder.c
-represent the C library to be wrapped.
-
-The file cheese.pyx is the Pyrex module
-which wraps it.
-
-The file run_cheese.py demonstrates how to
-call the wrapper.
diff --git a/Demos/embed/README b/Demos/embed/README
deleted file mode 100644 (file)
index 9a16c8e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-This example demonstrates how Cython-generated code
-can be called directly from a main program written in C.
-
-The Windows makefiles were contributed by
-Duncan Booth <Duncan.Booth@SuttonCourtenay.org.uk>.
diff --git a/Demos/embed/README.rst b/Demos/embed/README.rst
new file mode 100644 (file)
index 0000000..4cf30db
--- /dev/null
@@ -0,0 +1,5 @@
+This example demonstrates how Cython-generated code
+can be called directly from a main program written in C.
+
+The Windows makefiles were contributed by
+Duncan Booth: Duncan.Booth@SuttonCourtenay.org.uk.
diff --git a/Demos/freeze/README.rst b/Demos/freeze/README.rst
new file mode 100644 (file)
index 0000000..31c4b4c
--- /dev/null
@@ -0,0 +1,111 @@
+NAME
+====
+
+**cython_freeze** - create a C file for embedding Cython modules
+
+
+SYNOPSIS
+========
+::
+
+    cython_freeze [-o outfile] [-p] module [...]
+
+
+DESCRIPTION
+===========
+
+**cython_freeze** generates a C source file to embed a Python interpreter
+with one or more Cython modules built in.  This allows one to create a single
+executable from Cython code, without having to have separate shared objects
+for each Cython module.  A major advantage of this approach is that it allows
+debugging with gprof(1), which does not work with shared objects.
+
+Unless ``-p`` is given, the first module's ``__name__`` is set to
+``"__main__"`` and is imported on startup; if ``-p`` is given, a normal Python
+interpreter is built, with the given modules built into the binary.
+
+Note that this method differs from ``cython --embed``.  The ``--embed`` options
+modifies the resulting C source file to include a ``main()`` function, so it
+can only be used on a single Cython module.  The advantage ``--embed`` is
+simplicity.  This module, on the other hand, can be used with multiple
+modules, but it requires another C source file to be created.
+
+
+OPTIONS
+=======
+::
+
+    -o FILE, --outfile=FILE   write output to FILE instead of standard output
+    -p, --pymain              do not automatically run the first module as __main__
+
+
+EXAMPLE
+=======
+
+In the ``Demos/freeze`` directory, there exist two Cython modules:
+
+* ``lcmath.pyx``: A module that interfaces with the -lm library.
+
+* ``combinatorics.pyx``: A module that implements n-choose-r using lcmath.
+
+Both modules have the Python idiom ``if __name__ == "__main__"``, which only
+execute if that module is the "main" module.  If run as main, lcmath prints the
+factorial of the argument, while combinatorics prints n-choose-r.
+
+The provided Makefile creates an executable, *nCr*, using combinatorics as the
+"main" module.  It basically performs the following (ignoring the compiler
+flags)::
+
+    $ cython_freeze combinatorics lcmath > nCr.c
+    $ cython combinatorics.pyx
+    $ cython lcmath.pyx
+    $ gcc -c nCr.c
+    $ gcc -c combinatorics.c
+    $ gcc -c lcmath.c
+    $ gcc nCr.o combinatorics.o lcmath.o -o nCr
+
+Because the combinatorics module was listed first, its ``__name__`` is set
+to ``"__main__"``, while lcmath's is set to ``"lcmath"``.  The executable now
+contains a Python interpreter and both Cython modules. ::
+
+    $ ./nCr
+    USAGE: ./nCr n r
+    Prints n-choose-r.
+    $ ./nCr 15812351235 12
+    5.10028093999e+113
+
+You may wish to build a normal Python interpreter, rather than having one
+module as "main".  This may happen if you want to use your module from an
+interactive shell or from another script, yet you still want it statically
+linked so you can profile it with gprof.  To do this, add the ``--pymain``
+flag to ``cython_freeze``.  In the Makefile, the *python* executable is built
+like this. ::
+
+    $ cython_freeze --pymain combinatorics lcmath -o python.c
+    $ gcc -c python.c
+    $ gcc python.o combinatorics.o lcmath.o -o python
+
+Now ``python`` is a normal Python interpreter, but the lcmath and combinatorics
+modules will be built into the executable. ::
+
+    $ ./python
+    Python 2.6.2 (release26-maint, Apr 19 2009, 01:58:18)
+    [GCC 4.3.3] on linux2
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>> import lcmath
+    >>> lcmath.factorial(155)
+    4.7891429014634364e+273
+
+
+PREREQUISITES
+=============
+
+Cython 0.11.2 (or newer, assuming the API does not change)
+
+
+SEE ALSO
+========
+
+* `Python <http://www.python.org>`_
+* `Cython <http://www.cython.org>`_
+* `freeze.py <http://wiki.python.org/moin/Freeze>`_
diff --git a/Demos/freeze/README.txt b/Demos/freeze/README.txt
deleted file mode 100644 (file)
index 18e0452..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-NAME
-====
-
-cython_freeze - create a C file for embedding Cython modules
-
-
-SYNOPSIS
-========
-
-cython_freeze [-o outfile] [-p] module [...]
-
-
-DESCRIPTION
-===========
-
-**cython_freeze** generates a C source file to embed a Python interpreter
-with one or more Cython modules built in.  This allows one to create a single
-executable from Cython code, without having to have separate shared objects
-for each Cython module.  A major advantage of this approach is that it allows
-debugging with gprof(1), which does not work with shared objects.
-
-Unless ``-p`` is given, the first module's ``__name__`` is set to
-``"__main__"`` and is imported on startup; if ``-p`` is given, a normal Python
-interpreter is built, with the given modules built into the binary.
-
-Note that this method differs from ``cython --embed``.  The ``--embed`` options
-modifies the resulting C source file to include a ``main()`` function, so it
-can only be used on a single Cython module.  The advantage ``--embed`` is
-simplicity.  This module, on the other hand, can be used with multiple
-modules, but it requires another C source file to be created.
-
-
-OPTIONS
-=======
-
--o FILE, --outfile=FILE   write output to FILE instead of standard output
--p, --pymain              do not automatically run the first module as __main__
-
-
-EXAMPLE
-=======
-
-In the Demos/freeze directory, there exist two Cython modules:
-
-lcmath.pyx
-    A module that interfaces with the -lm library.
-
-combinatorics.pyx
-    A module that implements n-choose-r using lcmath.
-
-Both modules have the Python idiom ``if __name__ == "__main__"``, which only
-execute if that module is the "main" module.  If run as main, lcmath prints the
-factorial of the argument, while combinatorics prints n-choose-r.
-
-The provided Makefile creates an executable, *nCr*, using combinatorics as the
-"main" module.  It basically performs the following (ignoring the compiler
-flags)::
-
-    $ cython_freeze combinatorics lcmath > nCr.c
-    $ cython combinatorics.pyx
-    $ cython lcmath.pyx
-    $ gcc -c nCr.c
-    $ gcc -c combinatorics.c
-    $ gcc -c lcmath.c
-    $ gcc nCr.o combinatorics.o lcmath.o -o nCr
-
-Because the combinatorics module was listed first, its ``__name__`` is set
-to ``"__main__"``, while lcmath's is set to ``"lcmath"``.  The executable now
-contains a Python interpreter and both Cython modules. ::
-
-    $ ./nCr
-    USAGE: ./nCr n r
-    Prints n-choose-r.
-    $ ./nCr 15812351235 12
-    5.10028093999e+113
-
-You may wish to build a normal Python interpreter, rather than having one
-module as "main".  This may happen if you want to use your module from an
-interactive shell or from another script, yet you still want it statically
-linked so you can profile it with gprof.  To do this, add the ``--pymain``
-flag to ``cython_freeze``.  In the Makefile, the *python* executable is built
-like this. ::
-
-    $ cython_freeze --pymain combinatorics lcmath -o python.c
-    $ gcc -c python.c
-    $ gcc python.o combinatorics.o lcmath.o -o python
-
-Now ``python`` is a normal Python interpreter, but the lcmath and combinatorics
-modules will be built into the executable. ::
-
-    $ ./python
-    Python 2.6.2 (release26-maint, Apr 19 2009, 01:58:18)
-    [GCC 4.3.3] on linux2
-    Type "help", "copyright", "credits" or "license" for more information.
-    >>> import lcmath
-    >>> lcmath.factorial(155)
-    4.7891429014634364e+273
-
-
-PREREQUISITES
-=============
-
-Cython 0.11.2 (or newer, assuming the API does not change)
-
-
-SEE ALSO
-========
-
-* `Python <http://www.python.org>`_
-* `Cython <http://www.cython.org>`_
-* `freeze.py <http://wiki.python.org/moin/Freeze>`_
index d1487aa70f8e1318f88efaf1c720a2d33b95826a..4332e35070bdf7e293269e8f4c493b29caa35392 100644 (file)
@@ -1,4 +1,4 @@
-include MANIFEST.in README.txt INSTALL.txt ToDo.txt USAGE.txt CHANGES.rst
+include MANIFEST.in README.rst INSTALL.txt ToDo.txt USAGE.txt CHANGES.rst
 include COPYING.txt LICENSE.txt 2to3-fixers.txt Makefile
 include .gitrev
 include pylintrc
index 668d48bd060094569c9912e0c87d39eff273581e..a9b93422b86542787bd6d32f44704f31a7a02fa0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -11,6 +11,11 @@ all:    local
 local:
        ${PYTHON} setup.py build_ext --inplace
 
+sdist: dist/Cython-$(VERSION).tar.gz
+
+dist/Cython-$(VERSION).tar.gz:
+       $(PYTHON) setup.py sdist
+
 TMPDIR = .repo_tmp
 .git: .gitrev
        rm -rf $(TMPDIR)
diff --git a/README.rst b/README.rst
new file mode 100644 (file)
index 0000000..cec3cd4
--- /dev/null
@@ -0,0 +1,78 @@
+Welcome to Cython!  
+==================
+
+Cython is a language that makes writing C extensions for
+the Python language as easy as Python itself.  Cython is based on the
+well-known Pyrex, but supports more cutting edge functionality and
+optimizations.
+
+The Cython language is very close to the Python language, but Cython
+additionally supports calling C functions and declaring C types on variables
+and class attributes.  This allows the compiler to generate very efficient C
+code from Cython code.
+
+This makes Cython the ideal language for wrapping external C libraries, and
+for fast C modules that speed up the execution of Python code.
+
+* Official website: http://cython.org/
+* Documentation: http://docs.cython.org/en/latest/
+* Github repository: https://github.com/cython/cython
+* Wiki: https://github.com/cython/cython/wiki
+
+
+Installation:
+-------------
+
+If you already have a C compiler, just do::
+
+   pip install Cython
+
+otherwise, see `the installation page <http://docs.cython.org/en/latest/src/quickstart/install.html>`_.
+
+
+LICENSE:
+--------
+
+The original Pyrex program was licensed "free of restrictions" (see below).
+Cython itself is licensed under the permissive **Apache License**.
+
+See `LICENSE.txt <https://github.com/cython/cython/blob/master/LICENSE.txt>`_.
+
+
+Get the full source history:
+----------------------------
+
+Note that Cython used to ship the full version control repository in its source
+distribution, but no longer does so due to space constraints.  To get the
+full source history, make sure you have git installed, then step into the
+base directory of the Cython source distribution and type::
+
+    make repo
+
+
+The following is from Pyrex:
+------------------------------------------------------
+This is a development version of Pyrex, a language
+for writing Python extension modules.
+
+For more info, see:
+
+* Doc/About.html for a description of the language
+* INSTALL.txt    for installation instructions
+* USAGE.txt      for usage instructions
+* Demos          for usage examples
+
+Comments, suggestions, bug reports, etc. are
+welcome!
+
+Copyright stuff: Pyrex is free of restrictions. You
+may use, redistribute, modify and distribute modified
+versions.
+
+The latest version of Pyrex can be found `here <http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_.
+
+| Greg Ewing, Computer Science Dept
+| University of Canterbury
+| Christchurch, New Zealand
+
+ A citizen of NewZealandCorp, a wholly-owned subsidiary of USA Inc.
diff --git a/README.txt b/README.txt
deleted file mode 100644 (file)
index 8c02758..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-Welcome to Cython!
-=================
-
-Cython (http://cython.org) is a language that makes writing C extensions for
-the Python language as easy as Python itself.  Cython is based on the
-well-known Pyrex, but supports more cutting edge functionality and
-optimizations.
-
-The Cython language is very close to the Python language, but Cython
-additionally supports calling C functions and declaring C types on variables
-and class attributes.  This allows the compiler to generate very efficient C
-code from Cython code.
-
-This makes Cython the ideal language for wrapping external C libraries, and
-for fast C modules that speed up the execution of Python code.
-
-LICENSE:
-
-The original Pyrex program was licensed "free of restrictions" (see
-below).  Cython itself is licensed under the permissive
-
-   Apache License
-
-See LICENSE.txt.
-
-
---------------------------
-
-Note that Cython used to ship the full version control repository in its source
-distribution, but no longer does so due to space constraints.  To get the
-full source history, make sure you have git installed, then step into the
-base directory of the Cython source distribution and type
-
-    make repo
-
-Alternatively, check out the latest developer repository from
-
-    https://github.com/cython/cython
-
-
-
-The following is from Pyrex:
-------------------------------------------------------
-This is a development version of Pyrex, a language
-for writing Python extension modules.
-
-For more info, see:
-
-    Doc/About.html for a description of the language
-    INSTALL.txt    for installation instructions
-    USAGE.txt      for usage instructions
-    Demos          for usage examples
-
-Comments, suggestions, bug reports, etc. are
-welcome!
-
-Copyright stuff: Pyrex is free of restrictions. You
-may use, redistribute, modify and distribute modified
-versions.
-
-The latest version of Pyrex can be found here:
-
-http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/
-
-Greg Ewing, Computer Science Dept, +--------------------------------------+
-University of Canterbury,          | A citizen of NewZealandCorp, a       |
-Christchurch, New Zealand          | wholly-owned subsidiary of USA Inc.  |
-greg@cosc.canterbury.ac.nz         +--------------------------------------+
index f22e072246da471a75bbcfb5a7265078211f6d43..e5cef758b1706ab0a1c49a014effb0c1bb20101b 100755 (executable)
@@ -3,7 +3,7 @@
 Create a C file for embedding one or more Cython source files.
 Requires Cython 0.11.2 (or perhaps newer).
 
-See Demos/freeze/README.txt for more details.
+See Demos/freeze/README.rst for more details.
 """
 from __future__ import print_function
 
index 043d71e5b3e48b9f1290a5659aaa7e96724299d5..473719cb3ee673488a49f163319c5cfb41813bf2 100644 (file)
@@ -1,6 +1,10 @@
+from __future__ import print_function
+
 def fib(n):
     """Print the Fibonacci series up to n."""
     a, b = 0, 1
     while b < n:
-        print b,
+        print(b, end=' ')
         a, b = b, a + b
+
+    print()
index 63c42a5c7f5f1267f71f49230f3e2d93d59e670d..96ecdb59ad906de39810610ad4fff226759882d7 100644 (file)
@@ -1,19 +1,23 @@
-def primes(int kmax):
-    cdef int n, k, i
+def primes(int nb_primes):
+    cdef int n, i, len_p
     cdef int p[1000]
-    result = []
-    if kmax > 1000:
-        kmax = 1000
-    k = 0
+    if nb_primes > 1000:
+        nb_primes = 1000
+
+    len_p = 0  # The current number of elements in p.
     n = 2
-    while k < kmax:
-        i = 0
-        while i < k and n % p[i] != 0:
-            i = i + 1
-        if i == k:
-            p[k] = n
-            k = k + 1
-            result.append(n)
-        n = n + 1
-    return result
+    while len_p < nb_primes:
+        # Is n prime?
+        for i in p[:len_p]:
+            if n % i == 0:
+                break
+
+        # If no break occurred in the loop, we have a prime.
+        else:
+            p[len_p] = n
+            len_p += 1
+        n += 1
 
+    # Let's return the result in a python list:
+    result_as_list  = [prime for prime in p[:len_p]]
+    return result_as_list
index 4cf68e13a758eacc184742c9fae5e18cd718bcc8..71a9e633fae5808beab48f4783e3c11c0b03617a 100644 (file)
@@ -4,24 +4,34 @@ Building Cython code
 Cython code must, unlike Python, be compiled. This happens in two stages:
 
  - A ``.pyx`` file is compiled by Cython to a ``.c`` file, containing
-   the code of a Python extension module
+   the code of a Python extension module.
  - The ``.c`` file is compiled by a C compiler to
    a ``.so`` file (or ``.pyd`` on Windows) which can be
    ``import``-ed directly into a Python session.
+   Distutils or setuptools take care of this part.
+   Although Cython can call them for you in certain cases.
+
+To understand fully the Cython + distutils/setuptools build process,
+one may want to read more about
+`distributing Python modules <https://docs.python.org/3/distributing/index.html>`_.
 
 There are several ways to build Cython code:
 
- - Write a distutils ``setup.py``. This is the normal and recommended way.
+ - Write a distutils/setuptools ``setup.py``. This is the normal and recommended way.
  - Use ``pyximport``, importing Cython ``.pyx`` files as if they
    were ``.py`` files (using distutils to compile and build in the background).
+   This method is easier than writing a ``setup.py``, but is not very flexible.
+   So you'll need to write a ``setup.py`` if, for example, you need certain compilations options.
  - Run the ``cython`` command-line utility manually to produce the ``.c`` file
    from the ``.pyx`` file, then manually compiling the ``.c`` file into a shared
    object library or DLL suitable for import from Python.
    (These manual steps are mostly for debugging and experimentation.)
  - Use the [Jupyter]_ notebook or the [Sage]_ notebook,
    both of which allow Cython code inline.
+   This is the easiest way to get started writing Cython code and running it.
 
-Currently, distutils is the most common way Cython files are built and distributed. The other methods are described in more detail in the :ref:`compilation` section of the reference manual.
+Currently, using distutils or setuptools is the most common way Cython files are built and distributed.
+The other methods are described in more detail in the :ref:`compilation` section of the reference manual.
 
 
 Building a Cython module using distutils
@@ -59,8 +69,8 @@ use pip:
     (venv)$ pip install jupyter
     (venv)$ jupyter notebook
 
-To enable support for Cython compilation, install Cython and load the
-``Cython`` extension from within the Jupyter notebook::
+To enable support for Cython compilation, install Cython as described in :ref:`the installation guide<install>`
+and load the ``Cython`` extension from within the Jupyter notebook::
 
     %load_ext Cython
 
index cc0b8cc113b21a78a0a0ecc92495ed2b56960b4c..98a8c9c51b8e947d07ad5cc74c4a8bc0abbfcd97 100644 (file)
@@ -3,11 +3,11 @@ Faster code via static typing
 
 Cython is a Python compiler.  This means that it can compile normal
 Python code without changes (with a few obvious exceptions of some as-yet
-unsupported language features).  However, for performance critical
-code, it is often helpful to add static type declarations, as they
-will allow Cython to step out of the dynamic nature of the Python code
-and generate simpler and faster C code - sometimes faster by orders of
-magnitude.
+unsupported language features, see :ref:`Cython limitations<cython-limitations>`).
+However, for performance critical code, it is often helpful to add
+static type declarations, as they will allow Cython to step out of the
+dynamic nature of the Python code and generate simpler and faster C code
+- sometimes faster by orders of magnitude.
 
 It must be noted, however, that type declarations can make the source
 code more verbose and thus less readable.  It is therefore discouraged
@@ -146,4 +146,10 @@ of ``f`` is known to be a C double.)  A notable exception, however, is
 *integer types used in arithmetic expressions*, as Cython is unable to ensure
 that an overflow would not occur (and so falls back to ``object`` in case
 Python's bignums are needed).  To allow inference of C integer types, set the
-``infer_types`` :ref:`directive <compiler-directives>` to ``True``.
+``infer_types`` :ref:`directive <compiler-directives>` to ``True``. This directive
+does a work similar to the ``auto`` keyword in C++ for the readers who are familiar
+with this language feature. It can be of great help to cut down on the need to type
+everything, but it also can lead to surprises. Especially if one isn't familiar with
+arithmetic expressions with c types. A quick overview of those
+can be found `here <https://www.eskimo.com/~scs/cclass/int/sx4cb.html>`_.
+
index 3a7083dd4d991ce26c4c10cc7df69bd2e989fa93..18495f28233d7f4d522b0a17b36dca6e7575cb2d 100644 (file)
@@ -1,3 +1,5 @@
+.. _install:
+
 Installing Cython
 =================
 
@@ -33,19 +35,17 @@ according to the system used:
 .. dagss tried other forms of ReST lists and they didn't look nice
 .. with rst2latex.
 
+The simplest way of installing Cython is by using ``pip``::
+
+  pip install Cython
+
+
 The newest Cython release can always be downloaded from
 http://cython.org.  Unpack the tarball or zip file, enter the
 directory, and then run::
 
   python setup.py install
 
-If you have ``pip`` set up on your system (e.g. in a virtualenv or a
-recent Python version), you should be able to fetch Cython from PyPI
-and install it using
-
-::
-
-  pip install Cython
 
 For one-time builds, e.g. for CI/testing, on platforms that are not covered
 by one of the wheel packages provided on PyPI, it is substantially faster
index 5cf85c7679c1c6098ce9f1661261bec1478f4a51..479011961f32a3ef153938f3d1fc55d424168f5a 100644 (file)
@@ -34,7 +34,7 @@ things in getting started is just figuring out how to compile your extension.
 
 So lets start with the canonical python hello world::
 
-    print "Hello World"
+    print("Hello World")
 
 Save this code in a file named :file:`helloworld.pyx`.  Now we need to create
 the :file:`setup.py`, which is like a python Makefile (for more information
@@ -85,7 +85,7 @@ Cython will still fail to compile a lot of Python modules, in which
 case the import mechanism will fall back to loading the Python source
 modules instead.  The .py import mechanism is installed like this::
 
-    >>> pyximport.install(pyimport = True)
+    >>> pyximport.install(pyimport=True)
 
 Note that it is not recommended to let :mod:`pyximport` build code
 on end user side as it hooks into their import system.  The best way
@@ -132,27 +132,98 @@ them as a Python list.
     :linenos:
 
 You'll see that it starts out just like a normal Python function definition,
-except that the parameter ``kmax`` is declared to be of type ``int`` . This
+except that the parameter ``nb_primes`` is declared to be of type ``int`` . This
 means that the object passed will be converted to a C integer (or a
 ``TypeError.`` will be raised if it can't be).
 
+Now, let's dig into the core of the function::
+
+    cdef int n, i, len_p
+    cdef int p[1000]
+
 Lines 2 and 3 use the ``cdef`` statement to define some local C variables.
-Line 4 creates a Python list which will be used to return the result. You'll
-notice that this is done exactly the same way it would be in Python. Because
-the variable result hasn't been given a type, it is assumed to hold a Python
-object.
+The result is stored in the C array ``p`` during processing,
+and will be copied into a Python list at the end (line 22).
+
+.. NOTE:: You cannot create very large arrays in this manner, because
+          they are allocated on the C function call stack, which is a
+          rather precious and scarce resource.
+          To request larger arrays,
+          or even arrays with a length only known at runtime,
+          you can learn how to make efficient use of
+          :ref:`C memory allocation <memory_allocation>`,
+          :ref:`Python arrays <array-array>`
+          or :ref:`NumPy arrays <memoryviews>` with Cython.
+
+::
+
+    if nb_primes > 1000:
+        nb_primes = 1000
+
+As in C, declaring a static array requires knowing the size at compile time.
+We make sure the user doesn't set a value above 1000 (or we would have a
+segmentation fault, just like in C).  ::
+
+    len_p = 0  # The number of elements in p
+    n = 2
+    while len_p < nb_primes:
 
 Lines 7-9 set up for a loop which will test candidate numbers for primeness
-until the required number of primes has been found. Lines 11-12, which try
-dividing a candidate by all the primes found so far, are of particular
-interest. Because no Python objects are referred to, the loop is translated
-entirely into C code, and thus runs very fast.
-
-When a prime is found, lines 14-15 add it to the p array for fast access by
-the testing loop, and line 16 adds it to the result list. Again, you'll notice
-that line 16 looks very much like a Python statement, and in fact it is, with
-the twist that the C parameter ``n`` is automatically converted to a Python
-object before being passed to the append method. Finally, at line 18, a normal
+until the required number of primes has been found. ::
+
+    # Is n prime?
+    for i in p[:len_p]:
+        if n % i == 0:
+            break
+
+Lines 11-12, which try dividing a candidate by all the primes found so far,
+are of particular interest. Because no Python objects are referred to,
+the loop is translated entirely into C code, and thus runs very fast.
+You will notice the way we iterate over the ``p`` C array.  ::
+
+    for i in p[:len_p]:
+
+The loop gets translated into a fast C loop and works just like iterating
+over a Python list or NumPy array.  If you don't slice the C array with
+``[:len_p]``, then Cython will loop over the 1000 elements of the array.
+
+::
+
+    # If no break occurred in the loop
+    else:
+        p[len_p] = n
+        len_p += 1
+    n += 1
+
+If no breaks occurred, it means that we found a prime, and the block of code
+after the ``else`` line 16 will be executed. We add the prime found to ``p``.
+If you find having an ``else`` after a for-loop strange, just know that it's a
+lesser known features of the Python language, and that Cython executes it at
+C speed for you.
+If the for-else syntax confuses you, see this excellent
+`blog post <https://shahriar.svbtle.com/pythons-else-clause-in-loops>`_.
+
+::
+
+    # Let's put the result in a python list:
+    result_as_list  = [prime for prime in p[:len_p]]
+    return result_as_list
+
+In line 22, before returning the result, we need to copy our C array into a
+Python list, because Python can't read C arrays.  Cython can automatically
+convert many C types from and to Python types, as described in the
+documentation on :ref:`type conversion <type-conversion>`, so we can use
+a simple list comprehension here to copy the C ``int`` values into a Python
+list of Python ``int`` objects, which Cython creates automatically along the way.
+You could also have iterated manually over the C array and used
+``result_as_list.append(prime)``, the result would have been the same.
+
+You'll notice we declare a Python list exactly the same way it would be in Python.
+Because the variable ``result_as_list`` hasn't been explicitly declared with a type,
+it is assumed to hold a Python object, and from the assignment, Cython also knows
+that the exact type is a Python list.
+
+Finally, at line 18, a normal
 Python return statement returns the result list.
 
 Compiling primes.pyx with the Cython compiler produces an extension module
@@ -165,10 +236,105 @@ which we can try out in the interactive interpreter as follows::
 See, it works! And if you're curious about how much work Cython has saved you,
 take a look at the C code generated for this module.
 
+
+Cython has a way to visualise where interaction with Python objects and
+Python's C-API is taking place. For this, pass the
+``annotate=True`` parameter to ``cythonize()``. It produces a HTML file. Let's see:
+
+.. figure:: htmlreport.png
+
+If a line is white, it means that the code generated doesn't interact
+with Python, so will run as fast as normal C code.  The darker the yellow, the more
+Python interaction there is in that line.  Those yellow lines will usually operate
+on Python objects, raise exceptions, or do other kinds of higher-level operations
+than what can easily be translated into simple and fast C code.
+The function declaration and return use the Python interpreter so it makes
+sense for those lines to be yellow. Same for the list comprehension because
+it involves the creation of a Python object. But the line ``if n % i == 0:``, why?
+We can examine the generated C code to understand:
+
+.. figure:: python_division.png
+
+We can see that some checks happen. Because Cython defaults to the
+Python behavior, the language will perform division checks at runtime,
+just like Python does. You can deactivate those checks by using the
+:ref:`compiler directives<compiler-directives>`.
+
+Now let's see if, even if we have division checks, we obtained a boost in speed.
+Let's write the same program, but Python-style::
+
+    def primes_python(nb_primes):
+        p = []
+        n = 2
+        while len(p) < nb_primes:
+            # Is n prime?
+            for i in p:
+                if n % i == 0:
+                    break
+
+            # If no break occurred in the loop
+            else:
+                p.append(n)
+            n += 1
+        return p
+
+
+It is also possible to take a plain ``.py`` file and to compile it with Cython.
+Let's take ``primes_python``, change the function name to ``primes_python_compiled`` and
+compile it with Cython (without changing the code). We will also change the name of the
+file to ``example_py_cy.py`` to differentiate it from the others.
+Now the ``setup.py`` looks like this::
+
+    from distutils.core import setup
+    from Cython.Build import cythonize
+
+    setup(
+        ext_modules=cythonize(['example.pyx',        # Cython code file with primes() function
+                               'example_py_cy.py'],  # Python code file with primes_python_compiled() function
+                              annotate=True),        # enables generation of the html annotation file
+    )
+
+Now we can ensure that those two programs output the same values::
+
+    >>> primes_python(1000) == primes(1000)
+    True
+    >>> primes_python_compiled(1000) == primes(1000)
+    True
+
+It's possible to compare the speed now::
+
+    python -m timeit -s 'from example_py import primes_python' 'primes_python(1000)'
+    10 loops, best of 3: 23 msec per loop
+
+    python -m timeit -s 'from example_py_cy import primes_python_compiled' 'primes_python_compiled(1000)'
+    100 loops, best of 3: 11.9 msec per loop
+
+    python -m timeit -s 'from example import primes' 'primes(1000)'
+    1000 loops, best of 3: 1.65 msec per loop
+
+The cythonize version of ``primes_python`` is 2 times faster than the Python one,
+without changing a single line of code.
+The Cython version is 13 times faster than the Python version! What could explain this?
+
+Multiple things:
+ * In this program, very little computation happen at each line.
+   So the overhead of the python interpreter is very important. It would be
+   very different if you were to do a lot computation at each line. Using NumPy for
+   example.
+ * Data locality. It's likely that a lot more can fit in CPU cache when using C than
+   when using Python. Because everything in python is an object, and every object is
+   implemented as a dictionary, this is not very cache friendly.
+
+Usually the speedups are between 2x to 1000x. It depends on how much you call
+the Python interpreter. As always, remember to profile before adding types
+everywhere. Adding types makes your code less readable, so use them with
+moderation.
+
+
 Language Details
 ================
 
 For more about the Cython language, see :ref:`language-basics`.
 To dive right in to using Cython in a numerical computation context,
-see :ref:`numpy_tutorial`.
+see :ref:`memoryviews`.
 
diff --git a/docs/src/tutorial/htmlreport.png b/docs/src/tutorial/htmlreport.png
new file mode 100644 (file)
index 0000000..4fc98f3
Binary files /dev/null and b/docs/src/tutorial/htmlreport.png differ
diff --git a/docs/src/tutorial/python_division.png b/docs/src/tutorial/python_division.png
new file mode 100644 (file)
index 0000000..617be94
Binary files /dev/null and b/docs/src/tutorial/python_division.png differ
index f99e94cbb4102556f3f152b2dbdcbd5b014a3da1..e33ba9b686ae91625d0e86468ed88e601ad95f05 100644 (file)
@@ -301,6 +301,10 @@ return value and raise it yourself, for example,::
         raise SpamError("Couldn't open the spam file")
 
 
+
+
+.. _type-conversion:
+
 Automatic type conversions
 ==========================
 
@@ -334,7 +338,7 @@ possibilities.
    a value for each of the union fields.  Cython 0.23 and later, however,
    will refuse to automatically convert a union with unsafe type
    combinations.  An example is a union of an ``int`` and a ``char*``,
-   in which case the pointer value may or be not be a valid pointer.
+   in which case the pointer value may or may not be a valid pointer.
 
 
 Caveats when using a Python string in a C context
index 4188a2c37e262824fab6b1e62f3070cd35b14c90..15977a8a37d679ec74b66cbc380dc99ef57317a8 100644 (file)
@@ -6,6 +6,13 @@
 Cython for NumPy users
 **************************
 
+.. NOTE:: Cython 0.16 introduced typed memoryviews as a successor to the NumPy
+          integration described here.  They are easier to use than the buffer syntax
+          below, have less overhead, and can be passed around without requiring the GIL.
+          They should be preferred to the syntax presented in this page.
+          See :ref:`Typed Memoryviews <memoryviews>`.
+
+
 This tutorial is aimed at NumPy users who have no experience with Cython at
 all. If you have some knowledge of Cython you may want to skip to the
 ''Efficient indexing'' section which explains the new improvements made in
diff --git a/pyximport/README b/pyximport/README
deleted file mode 100644 (file)
index 9395974..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
- == Pyximport ==
-
-Download: pyx-import-1.0.tar.gz
-<http://www.prescod.net/pyximport/pyximport-1.0.tar.gz>
-
-Pyrex is a compiler. Therefore it is natural that people tend to go
-through an edit/compile/test cycle with Pyrex modules. But my personal
-opinion is that one of the deep insights in Python's implementation is
-that a language can be compiled (Python modules are compiled to .pyc)
-files and hide that compilation process from the end-user so that they
-do not have to worry about it. Pyximport does this for Pyrex modules.
-For instance if you write a Pyrex module called "foo.pyx", with
-Pyximport you can import it in a regular Python module like this:
-
-
-import pyximport; pyximport.install()
-import foo
-
-Doing so will result in the compilation of foo.pyx (with appropriate
-exceptions if it has an error in it).
-
-If you would always like to import pyrex files without building them
-specially, you can also add the first line above to your sitecustomize.py.
-That will install the hook every time you run Python. Then you can use
-Pyrex modules just with simple import statements. I like to test my
-Pyrex modules like this:
-
-
-python -c "import foo"
-
-See help(pyximport.install) to learn its options for controlling the
-default behavior of "import" and "reload".
-
- == Dependency Handling ==
-
-In Pyximport 1.1 it is possible to declare that your module depends on
-multiple files, (likely ".h" and ".pxd" files). If your Pyrex module is
-named "foo" and thus has the filename "foo.pyx" then you should make
-another file in the same directory called "foo.pyxdep". The
-"modname.pyxdep" file can be a list of filenames or "globs" (like
-"*.pxd" or "include/*.h"). Each filename or glob must be on a separate
-line. Pyximport will check the file date for each of those files before
-deciding whether to rebuild the module. In order to keep track of the
-fact that the dependency has been handled, Pyximport updates the
-modification time of your ".pyx" source file. Future versions may do
-something more sophisticated like informing distutils of the
-dependencies directly.
-
- == Limitations ==
-
-Pyximport does not give you any control over how your Pyrex file is
-compiled. Usually the defaults are fine. You might run into problems if
-you wanted to write your program in half-C, half-Pyrex and build them
-into a single library. Pyximport 1.2 will probably do this.
-
-Pyximport does not hide the Distutils/GCC warnings and errors generated
-by the import process. Arguably this will give you better feedback if
-something went wrong and why. And if nothing went wrong it will give you
-the warm fuzzy that pyximport really did rebuild your module as it was
-supposed to.
-
- == For further thought and discussion ==
-
-"setup.py install" does not modify sitecustomize.py for you. Should it?
-Modifying Python's "standard interpreter" behaviour may be more than
-most people expect of a package they install..
-
-Pyximport puts your ".c" file beside your ".pyx" file (analogous to
-".pyc" beside ".py"). But it puts the platform-specific binary in a
-build directory as per normal for Distutils. If I could wave a magic
-wand and get Pyrex or distutils or whoever to put the build directory I
-might do it but not necessarily: having it at the top level is VERY
-HELPFUL for debugging Pyrex problems.
diff --git a/pyximport/README.rst b/pyximport/README.rst
new file mode 100644 (file)
index 0000000..0e91ac4
--- /dev/null
@@ -0,0 +1,71 @@
+Pyximport
+=========
+
+Cython is a compiler. Therefore it is natural that people tend to go
+through an edit/compile/test cycle with Cython modules. But my personal
+opinion is that one of the deep insights in Python's implementation is
+that a language can be compiled (Python modules are compiled to .pyc)
+files and hide that compilation process from the end-user so that they
+do not have to worry about it. Pyximport does this for Cython modules.
+For instance if you write a Cython module called ``foo.pyx``, with
+Pyximport you can import it in a regular Python module like this::
+
+    import pyximport; pyximport.install()
+    import foo
+
+Doing so will result in the compilation of ``foo.pyx`` (with appropriate
+exceptions if it has an error in it).
+
+If you would always like to import Cython files without building them
+specially, you can also add the first line above to your sitecustomize.py.
+That will install the hook every time you run Python. Then you can use
+Cython modules just with simple import statements. I like to test my
+Cython modules like this::
+
+    python -c "import foo"
+
+See help(pyximport.install) to learn its options for controlling the
+default behavior of ``import`` and ``reload``.
+
+Dependency Handling
+-------------------
+
+In Pyximport 1.1 it is possible to declare that your module depends on
+multiple files, (likely ``.h`` and ``.pxd`` files). If your Cython module is
+named ``foo`` and thus has the filename ``foo.pyx`` then you should make
+another file in the same directory called ``foo.pyxdep``. The
+``modname.pyxdep`` file can be a list of filenames or ``globs`` (like
+``*.pxd`` or ``include/*.h``). Each filename or glob must be on a separate
+line. Pyximport will check the file date for each of those files before
+deciding whether to rebuild the module. In order to keep track of the
+fact that the dependency has been handled, Pyximport updates the
+modification time of your ``.pyx`` source file. Future versions may do
+something more sophisticated like informing distutils of the
+dependencies directly.
+
+Limitations
+-----------
+Pyximport does not give you any control over how your Cython file is
+compiled. Usually the defaults are fine. You might run into problems if
+you wanted to write your program in half-C, half-Cython and build them
+into a single library. Pyximport 1.2 will probably do this.
+
+Pyximport does not hide the Distutils/GCC warnings and errors generated
+by the import process. Arguably this will give you better feedback if
+something went wrong and why. And if nothing went wrong it will give you
+the warm fuzzy that pyximport really did rebuild your module as it was
+supposed to.
+
+For further thought and discussion
+----------------------------------
+
+``setup.py install`` does not modify ``sitecustomize.py`` for you. Should it?
+Modifying Python's "standard interpreter" behaviour may be more than
+most people expect of a package they install..
+
+Pyximport puts your ``.c`` file beside your ``.pyx`` file (analogous to
+``.pyc`` beside ``.py``). But it puts the platform-specific binary in a
+build directory as per normal for Distutils. If I could wave a magic
+wand and get Cython or distutils or whoever to put the build directory I
+might do it but not necessarily: having it at the top level is VERY
+HELPFUL for debugging Cython problems.
index e5797a3ef7b24f881d992e60f1397c20a9109963..616d2a0a39484218b0e356a732fc34a1637fe280 100755 (executable)
@@ -215,10 +215,18 @@ def def_to_cdef(source):
 
     return '\n'.join(output)
 
+
+def exclude_extension_in_pyver(*versions):
+    def check(ext):
+        return EXCLUDE_EXT if sys.version_info[:2] in versions else ext
+    return check
+
+
 def update_linetrace_extension(ext):
     ext.define_macros.append(('CYTHON_TRACE', 1))
     return ext
 
+
 def update_numpy_extension(ext):
     import numpy
     from numpy.distutils.misc_util import get_info
@@ -339,6 +347,7 @@ EXT_EXTRAS = {
     'tag:openmp': update_openmp_extension,
     'tag:cpp11': update_cpp11_extension,
     'tag:trace' : update_linetrace_extension,
+    'tag:bytesformat':  exclude_extension_in_pyver((3, 3), (3, 4)),  # no %-bytes formatting
 }
 
 
index 0be2421095fb59b783a748b0d0ac9474545c3c98..61bb908280eb34917fe22cd177309d31b46dda2b 100644 (file)
@@ -208,7 +208,7 @@ cdef class boring_boring_getattr(boring_getattr):
 cdef class getattribute_boring_boring_getattr(boring_boring_getattr):
     """
     __getattribute__ is always tried first, then __getattr__, regardless of where
-    in the inheritance hiarchy they came from.
+    in the inheritance hierarchy they came from.
 
     >>> a = getattribute_boring_boring_getattr()
     >>> (a.getattr_called, a.getattribute_called)
@@ -253,7 +253,7 @@ cdef class getattribute_boring_boring_getattr(boring_boring_getattr):
 cdef class getattr_boring_boring_getattribute(boring_boring_getattribute):
     """
     __getattribute__ is always tried first, then __getattr__, regardless of where
-    in the inheritance hiarchy they came from.
+    in the inheritance hierarchy they came from.
 
     >>> a = getattr_boring_boring_getattribute()
     >>> (a.getattr_called, a.getattribute_called)
diff --git a/tests/run/bytes_formatting.pyx b/tests/run/bytes_formatting.pyx
new file mode 100644 (file)
index 0000000..ef75945
--- /dev/null
@@ -0,0 +1,34 @@
+# mode: run
+# tag: stringformat, bytesformat
+
+
+import sys
+IS_PY2 = sys.version_info[0] < 3
+
+
+if IS_PY2:
+    __doc__ = """
+>>> print(format_bytes_with_str(u'abc'))
+1 12170405abc6A
+"""
+
+
+def format_bytes():
+    """
+    >>> print(format_bytes())
+    1 121704056A
+    """
+    cdef bytes result = b'%d%3i%x%02X%02.0f%g%c' % (
+        1, 12, 23, 4, 5, 6, 65)
+    assert type(result) is bytes
+    return result.decode('ascii')
+
+
+def format_bytes_with_str(s):
+    """
+    >>> print(format_bytes_with_str(b'abc'))
+    1 12170405abc6A
+    """
+    result = b'%d%3i%x%02X%02.0f%s%g%c' % (
+        1, 12, 23, 4, 5, s, 6, 65)
+    return result if IS_PY2 else result.decode('ascii')
index 12f71ccf72bbfb17225783065e493a40c1144fb2..e423404f9954197ed87bcf9ef17dd6a7fbdfecf8 100644 (file)
@@ -9,7 +9,7 @@ cdef extern from "shapes.h" namespace "shapes":
         float area()
 
     cdef cppclass Ellipse(Shape):
-        Ellipse(int a, int b) except +
+        Ellipse(int a, int b) nogil except +
 
     cdef cppclass Circle(Ellipse):
         int radius
@@ -32,6 +32,7 @@ cdef extern from "shapes.h" namespace "shapes":
 
     int constructor_count, destructor_count
 
+
 def test_new_del():
     """
     >>> test_new_del()
@@ -45,6 +46,7 @@ def test_new_del():
     del rect, circ
     print constructor_count-c, destructor_count-d
 
+
 def test_default_constructor():
     """
     >>> test_default_constructor()
@@ -56,6 +58,20 @@ def test_default_constructor():
     finally:
         del shape
 
+
+def test_constructor_nogil():
+    """
+    >>> test_constructor_nogil()
+    True
+    """
+    with nogil:
+        shape = new Ellipse(4, 5)
+    try:
+        return 62 < shape.area() < 63 or shape.area()
+    finally:
+        del shape
+
+
 def test_rect_area(w, h):
     """
     >>> test_rect_area(3, 4)
@@ -67,6 +83,7 @@ def test_rect_area(w, h):
     finally:
         del rect
 
+
 def test_overload_bint_int():
     """
     >>> test_overload_bint_int()
@@ -83,6 +100,7 @@ def test_overload_bint_int():
         del rect1
         del rect2
 
+
 def test_square_area(w):
     """
     >>> test_square_area(15)
@@ -95,6 +113,7 @@ def test_square_area(w):
     finally:
         del sqr
 
+
 cdef double get_area(Rectangle s):
     return s.area()
 
@@ -110,6 +129,7 @@ def test_value_call(int w):
     finally:
         del sqr
 
+
 def get_destructor_count():
     return destructor_count
 
@@ -126,6 +146,7 @@ def test_stack_allocation(int w, int h):
     print rect.method(<int>5)
     return destructor_count
 
+
 cdef class EmptyHolder:
     cdef Empty empty
 
@@ -148,6 +169,7 @@ def test_class_member():
     assert destructor_count - start_destructor_count == 2, \
            destructor_count - start_destructor_count
 
+
 def test_derived_class_member():
     """
     >>> test_derived_class_member()
@@ -161,6 +183,7 @@ def test_derived_class_member():
     assert destructor_count - start_destructor_count == 2, \
            destructor_count - start_destructor_count
 
+
 cdef class TemplateClassMember:
     cdef vector[int] x
     cdef vector[vector[Empty]] vec
@@ -190,6 +213,9 @@ cdef int f(int x):
     return x
 
 def test_nested_del():
+    """
+    >>> test_nested_del()
+    """
     cdef vector[vector_int_ptr] v
     v.push_back(new vector[int]())
     del v[0]
index ac9242876704a4842376ffa0236230079e887b5c..7822e287b4e2e0288ea9678885f5ab3bb79e9556 100644 (file)
@@ -1,6 +1,6 @@
-# distutils: extra_compile_args=-std=c++0x
 # mode: run
-# tag: cpp, werror
+# tag: cpp, werror, cpp11
+# distutils: extra_compile_args=-std=c++0x
 
 from libcpp.memory cimport unique_ptr, shared_ptr, default_delete
 from libcpp cimport nullptr
@@ -12,6 +12,10 @@ cdef extern from "cpp_smart_ptr_helper.h":
     cdef cppclass FreePtr[T]:
         pass
 
+
+ctypedef const CountAllocDealloc const_CountAllocDealloc
+
+
 def test_unique_ptr():
     """
     >>> test_unique_ptr()
@@ -42,17 +46,18 @@ def test_unique_ptr():
     x_ptr3.reset()
     assert x_ptr3.get() == nullptr;
 
-def test_shared_ptr():
+
+def test_const_shared_ptr():
     """
-    >>> test_shared_ptr()
+    >>> test_const_shared_ptr()
     """
     cdef int alloc_count = 0, dealloc_count = 0
-    cdef shared_ptr[CountAllocDealloc] ptr = shared_ptr[CountAllocDealloc](
+    cdef shared_ptr[const CountAllocDealloc] ptr = shared_ptr[const_CountAllocDealloc](
         new CountAllocDealloc(&alloc_count, &dealloc_count))
     assert alloc_count == 1
     assert dealloc_count == 0
 
-    cdef shared_ptr[CountAllocDealloc] ptr2 = ptr
+    cdef shared_ptr[const CountAllocDealloc] ptr2 = ptr
     assert alloc_count == 1
     assert dealloc_count == 0
 
index f00b045c6f5dc7c3a9959ab5ba6f5636f9d2d3e5..1efd5b82221bd2b4c56ad5f8fcaa51de0de7e8f9 100644 (file)
@@ -1,3 +1,5 @@
+# mode: run
+# tag: dict, pop, builtins
 
 cimport cython
 
@@ -32,3 +34,25 @@ def dict_pop_default(dict d, key, default):
     (20, {})
     """
     return d.pop(key, default), d
+
+
+cdef class MyType:
+    cdef public int i
+    def __init__(self, i):
+        self.i = i
+
+
+@cython.test_assert_path_exists("//SingleAssignmentNode//PythonCapiCallNode")
+@cython.test_fail_if_path_exists("//SingleAssignmentNode//AttributeNode")
+def dict_pop_default_typed(dict d, key, default):
+    """
+    >>> d = {1: MyType(2)}
+    >>> dict_pop_default_typed(d, 1, None)
+    2
+    >>> dict_pop_default_typed(d, 3, None)
+    >>> dict_pop_default_typed(d, 3, "default")  # doctest: +ELLIPSIS
+    Traceback (most recent call last):
+    TypeError: Cannot convert str to ...MyType
+    """
+    cdef MyType x = d.pop(key, default)
+    return x.i if x is not None else None