summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2021-04-15 23:50:26 +0200
committerStefan Behnel <stefan_ml@behnel.de>2021-04-15 23:50:26 +0200
commit8f99b3abf4dd963fb9dd80a3370913233ef1f35c (patch)
treedb9aa4ead6756b48784dfcc7cff663f8b6edb3bf
parent7f29f26424e5ff9eccc6c74298bd000a6692bfc5 (diff)
parentdd5558b65f8b19d6e5b789ad2c0ded6b9d5664d9 (diff)
downloadcython-8f99b3abf4dd963fb9dd80a3370913233ef1f35c.tar.gz
Merge branch 'master' into clean_up_capi_features
-rw-r--r--.gitignore3
-rw-r--r--.travis.yml17
-rw-r--r--CHANGES.rst343
-rw-r--r--Cython/Build/Dependencies.py15
-rw-r--r--Cython/Compiler/AnalysedTreeTransforms.py8
-rw-r--r--Cython/Compiler/Buffer.py8
-rw-r--r--Cython/Compiler/Builtin.py9
-rw-r--r--Cython/Compiler/Code.py11
-rw-r--r--Cython/Compiler/CythonScope.py2
-rw-r--r--Cython/Compiler/ExprNodes.py36
-rw-r--r--Cython/Compiler/FlowControl.py4
-rw-r--r--Cython/Compiler/FusedNode.py4
-rw-r--r--Cython/Compiler/MemoryView.py8
-rw-r--r--Cython/Compiler/ModuleNode.py4
-rw-r--r--Cython/Compiler/Nodes.py55
-rw-r--r--Cython/Compiler/Optimize.py50
-rw-r--r--Cython/Compiler/ParseTreeTransforms.py14
-rw-r--r--Cython/Compiler/Parsing.py44
-rw-r--r--Cython/Compiler/Pipeline.py18
-rw-r--r--Cython/Compiler/PyrexTypes.py23
-rw-r--r--Cython/Compiler/Symtab.py4
-rw-r--r--Cython/Compiler/TreePath.py11
-rw-r--r--Cython/Compiler/UtilityCode.py4
-rw-r--r--Cython/Compiler/Visitor.py4
-rw-r--r--Cython/Debugger/Tests/test_libcython_in_gdb.py2
-rw-r--r--Cython/Includes/cpython/array.pxd12
-rw-r--r--Cython/Includes/cpython/cellobject.pxd35
-rw-r--r--Cython/Includes/cpython/codecs.pxd121
-rw-r--r--Cython/Includes/cpython/conversion.pxd36
-rw-r--r--Cython/Includes/cpython/datetime.pxd28
-rw-r--r--Cython/Includes/cpython/fileobject.pxd57
-rw-r--r--Cython/Includes/cpython/long.pxd4
-rw-r--r--Cython/Includes/cpython/pycapsule.pxd13
-rw-r--r--Cython/Includes/cpython/time.pxd51
-rw-r--r--Cython/Includes/libc/time.pxd5
-rw-r--r--Cython/Includes/numpy/__init__.pxd23
-rw-r--r--Cython/Includes/posix/fcntl.pxd1
-rw-r--r--Cython/Utility/Builtins.c4
-rw-r--r--Cython/Utility/Coroutine.c44
-rw-r--r--Cython/Utility/CppSupport.cpp3
-rw-r--r--Cython/Utility/CythonFunction.c54
-rw-r--r--Cython/Utility/ImportExport.c5
-rw-r--r--Cython/Utility/MemoryView.pyx4
-rw-r--r--Cython/Utility/MemoryView_C.c6
-rw-r--r--Cython/Utility/ModuleSetupCode.c13
-rw-r--r--Cython/Utility/ObjectHandling.c123
-rw-r--r--Cython/Utility/Optimize.c363
-rw-r--r--Cython/Utility/TypeConversion.c46
-rw-r--r--Cython/Utility/arrayarray.h8
-rw-r--r--Cython/Utils.py4
-rw-r--r--README.rst6
-rw-r--r--appveyor.yml1
-rw-r--r--appveyor/install.ps111
-rw-r--r--doc-requirements.txt2
-rw-r--r--docs/conf.py6
-rw-r--r--docs/examples/Cython Magics.ipynb2
-rw-r--r--docs/examples/README.rst2
-rw-r--r--docs/examples/userguide/external_C_code/platform_adaptation.pyx1
-rw-r--r--docs/index.rst2
-rw-r--r--docs/make.bat2
-rw-r--r--docs/src/donating.rst31
-rw-r--r--docs/src/quickstart/overview.rst2
-rw-r--r--docs/src/reference/directives.rst2
-rw-r--r--docs/src/reference/extension_types.rst2
-rw-r--r--docs/src/reference/language_basics.rst2
-rw-r--r--docs/src/tutorial/appendix.rst4
-rw-r--r--docs/src/tutorial/clibraries.rst2
-rw-r--r--docs/src/tutorial/external.rst2
-rw-r--r--docs/src/tutorial/readings.rst2
-rw-r--r--docs/src/userguide/extension_types.rst5
-rw-r--r--docs/src/userguide/external_C_code.rst32
-rw-r--r--docs/src/userguide/glossary.rst10
-rw-r--r--docs/src/userguide/language_basics.rst9
-rw-r--r--docs/src/userguide/numpy_tutorial.rst2
-rw-r--r--docs/src/userguide/sharing_declarations.rst2
-rw-r--r--docs/src/userguide/wrapping_CPlusPlus.rst34
-rw-r--r--pylintrc2
-rwxr-xr-xruntests.py53
-rw-r--r--setup.cfg4
-rwxr-xr-xsetup.py1
-rw-r--r--test-requirements-27.txt62
-rw-r--r--test-requirements-cpython.txt3
-rw-r--r--tests/buffers/bufaccess.pyx5
-rw-r--r--tests/buffers/buffmt.pyx24
-rw-r--r--tests/build/common_include_dir.srctree7
-rw-r--r--tests/build/cythonize_pep420_namespace.srctree17
-rw-r--r--tests/compile/cast_ctypedef_array_T518.pyx2
-rw-r--r--tests/compile/cimport_package_module_T4.pyx2
-rw-r--r--tests/compile/cimportfrom_T248.pyx2
-rw-r--r--tests/compile/complex_annotations.pyx7
-rw-r--r--tests/compile/complex_decorators.pyx10
-rw-r--r--tests/compile/cpp_templates.pyx2
-rw-r--r--tests/compile/cpp_templates_nested.pyx18
-rw-r--r--tests/compile/ctypedef_public_class_T355.pyx2
-rw-r--r--tests/compile/ellipsis_T488.pyx2
-rw-r--r--tests/compile/weakref_T276.pyx2
-rw-r--r--tests/errors/bufaccess_noassignT444.pyx2
-rw-r--r--tests/errors/buffertypedef_T117.pyx2
-rw-r--r--tests/errors/callingnonexisting_T307.pyx2
-rw-r--r--tests/errors/cdef_class_properties_decorated.pyx2
-rw-r--r--tests/errors/cdef_members_T517.pyx2
-rw-r--r--tests/errors/compile_time_unraisable_T370.pyx2
-rw-r--r--tests/errors/cpdef_vars.pyx24
-rw-r--r--tests/errors/declareafteruse_T158.pyx37
-rw-r--r--tests/errors/e2_packedstruct_T290.pyx2
-rw-r--r--tests/errors/e_cdef_keywords_T241.pyx2
-rw-r--r--tests/errors/e_decorators.pyx9
-rw-r--r--tests/errors/e_tuple_args_T692.py2
-rw-r--r--tests/errors/fused_types.pyx1
-rw-r--r--tests/errors/missing_baseclass_in_predecl_T262.pyx2
-rw-r--r--tests/errors/missing_self_in_cpdef_method_T156.pyx2
-rw-r--r--tests/errors/missing_self_in_cpdef_method_T165.pyx2
-rw-r--r--tests/errors/notcimportedT418.pyx2
-rw-r--r--tests/errors/pxd_cdef_class_declaration_T286.pyx2
-rw-r--r--tests/errors/pyobjcastdisallow_T313.pyx2
-rw-r--r--tests/errors/return_outside_function_T135.pyx2
-rw-r--r--tests/errors/typoT304.pyx2
-rw-r--r--tests/errors/uninitialized_lhs.pyx2
-rw-r--r--tests/memoryview/memoryview.pyx1
-rw-r--r--tests/memoryview/memoryviewattrs.pyx22
-rw-r--r--tests/memoryview/memslice.pyx74
-rw-r--r--tests/memoryview/numpy_memoryview.pyx45
-rw-r--r--tests/run/always_allow_keywords_T295.pyx2
-rw-r--r--tests/run/args_unpacking_in_closure_T658.pyx2
-rw-r--r--tests/run/argument_unpacking_closure_T736.py2
-rw-r--r--tests/run/arithmetic_analyse_types.pyx2
-rw-r--r--tests/run/bad_c_struct_T252.pyx2
-rw-r--r--tests/run/bint_binop_T145.pyx2
-rw-r--r--tests/run/bint_property_T354.pyx2
-rw-r--r--tests/run/bound_builtin_methods_T589.pyx2
-rw-r--r--tests/run/builtin_abs.pyx2
-rw-r--r--tests/run/builtin_float.py208
-rw-r--r--tests/run/builtin_methods_return_values.pyx2
-rw-r--r--tests/run/builtin_subtype_methods_T653.pyx2
-rw-r--r--tests/run/builtin_subtype_methods_cy3.pyx2
-rw-r--r--tests/run/builtin_type_inheritance_T608.pyx2
-rw-r--r--tests/run/builtin_types_none_T166.pyx2
-rw-r--r--tests/run/c_int_types_T255.pyx2
-rw-r--r--tests/run/c_type_methods_T236.pyx2
-rw-r--r--tests/run/cascaded_list_unpacking_T467.pyx2
-rw-r--r--tests/run/cascaded_typed_assignments_T466.pyx2
-rw-r--r--tests/run/cdef_bool_T227.pyx2
-rw-r--r--tests/run/cdef_class_field.pyx2
-rw-r--r--tests/run/cdef_class_property_decorator_T264.pyx2
-rw-r--r--tests/run/cdef_decorator_directives_T183.pyx2
-rw-r--r--tests/run/cdef_locals_decorator_T477.pyx2
-rw-r--r--tests/run/cdef_members_T517.pyx2
-rw-r--r--tests/run/cdef_methods_T462.pyx2
-rw-r--r--tests/run/cdef_setitem_T284.pyx2
-rw-r--r--tests/run/cfunc_call_tuple_args_T408.pyx2
-rw-r--r--tests/run/cfunc_convert.pyx36
-rw-r--r--tests/run/char_constants_T99.pyx2
-rw-r--r--tests/run/charcomparisonT412.pyx2
-rw-r--r--tests/run/charptr_comparison_T582.pyx2
-rw-r--r--tests/run/cimport.srctree10
-rw-r--r--tests/run/cimport_cython_T505.pyx2
-rw-r--r--tests/run/class_attribute_init_values_T18.pyx2
-rw-r--r--tests/run/class_func_in_control_structures_T87.pyx2
-rw-r--r--tests/run/class_scope_del_T684.py2
-rw-r--r--tests/run/classdecorators_T336.pyx2
-rw-r--r--tests/run/closure_class_T596.pyx2
-rw-r--r--tests/run/closure_decorators_T478.pyx2
-rw-r--r--tests/run/closure_inside_cdef_T554.pyx2
-rw-r--r--tests/run/closure_name_mangling_T537.pyx2
-rw-r--r--tests/run/closure_names.pyx2
-rw-r--r--tests/run/closures_T82.pyx2
-rw-r--r--tests/run/cmethod_inline_T474.pyx2
-rw-r--r--tests/run/complex_cast_T445.pyx2
-rw-r--r--tests/run/complex_coercion_sideeffects_T693.pyx2
-rw-r--r--tests/run/complex_int_T446.pyx2
-rw-r--r--tests/run/complex_numbers_T305.pyx2
-rw-r--r--tests/run/complex_numbers_T305_long_double.pyx2
-rw-r--r--tests/run/complex_numbers_c89_T398.pyx2
-rw-r--r--tests/run/complex_numbers_c89_T398_long_double.pyx2
-rw-r--r--tests/run/complex_numbers_c99_T398.pyx2
-rw-r--r--tests/run/complex_numbers_cxx_T398.pyx2
-rw-r--r--tests/run/contains_T455.pyx2
-rw-r--r--tests/run/coverage_cmd.srctree2
-rw-r--r--tests/run/cpdef_enums.pyx6
-rw-r--r--tests/run/cpdef_method_override.pyx2
-rw-r--r--tests/run/cpdef_temps_T411.pyx2
-rw-r--r--tests/run/cpp_nested_classes.pyx18
-rw-r--r--tests/run/cpp_stl_conversion.pyx2
-rw-r--r--tests/run/crashT245.pyx2
-rw-r--r--tests/run/cstringmul.pyx12
-rw-r--r--tests/run/ctypedef_int_types_T333.pyx2
-rw-r--r--tests/run/cython_includes.pyx4
-rw-r--r--tests/run/datetime_pxd.pyx32
-rw-r--r--tests/run/decorators_T593.pyx2
-rw-r--r--tests/run/decorators_py_T593.py2
-rw-r--r--tests/run/default_args_T674.py2
-rw-r--r--tests/run/dict.pyx19
-rw-r--r--tests/run/division_T384.pyx2
-rw-r--r--tests/run/duplicate_keyword_in_call.py2
-rw-r--r--tests/run/duplicate_utilitycode_from_pyx.srctree29
-rw-r--r--tests/run/dynamic_args.pyx2
-rw-r--r--tests/run/ellipsis_T488.pyx2
-rw-r--r--tests/run/empty_for_loop_T208.pyx2
-rw-r--r--tests/run/enumerate_T316.pyx2
-rw-r--r--tests/run/ext_instance_type_T232.pyx2
-rw-r--r--tests/run/extended_unpacking_T235.pyx2
-rw-r--r--tests/run/extended_unpacking_T409.pyx2
-rw-r--r--tests/run/extern_builtins_T258.pyx2
-rw-r--r--tests/run/file_encoding_T740.py2
-rw-r--r--tests/run/final_method_T586.pyx2
-rw-r--r--tests/run/float_floor_division_T260.pyx2
-rw-r--r--tests/run/float_len_T480.pyx2
-rw-r--r--tests/run/for_from_float_T254.pyx2
-rw-r--r--tests/run/for_from_pyvar_loop_T601.pyx2
-rw-r--r--tests/run/for_in_break_continue_T533.pyx2
-rw-r--r--tests/run/for_in_range_T372.pyx2
-rw-r--r--tests/run/funcexc_iter_T228.pyx2
-rw-r--r--tests/run/function_as_method_T494.pyx2
-rw-r--r--tests/run/function_as_method_py_T494.py2
-rw-r--r--tests/run/function_binding_T494.pyx2
-rw-r--r--tests/run/function_self.py91
-rw-r--r--tests/run/fused_types.pyx4
-rw-r--r--tests/run/generator_expressions_and_locals.pyx2
-rw-r--r--tests/run/generators_GH1731.pyx2
-rw-r--r--tests/run/generators_py35.py2
-rw-r--r--tests/run/genexpr_T491.pyx2
-rw-r--r--tests/run/genexpr_T715.pyx2
-rw-r--r--tests/run/genexpr_iterable_lookup_T600.pyx2
-rw-r--r--tests/run/hash_T326.pyx2
-rw-r--r--tests/run/ifelseexpr_T267.pyx2
-rw-r--r--tests/run/import_error_T734.py2
-rw-r--r--tests/run/in_list_with_side_effects_T544.pyx2
-rw-r--r--tests/run/int_float_builtins_as_casts_T400.pyx2
-rw-r--r--tests/run/int_float_builtins_as_casts_T400_long_double.pyx2
-rw-r--r--tests/run/intern_T431.pyx2
-rw-r--r--tests/run/ipow_crash_T562.pyx2
-rw-r--r--tests/run/kwargs_passthrough.pyx44
-rw-r--r--tests/run/lambda_T195.pyx2
-rw-r--r--tests/run/lambda_T723.pyx2
-rw-r--r--tests/run/lambda_class_T605.pyx2
-rw-r--r--tests/run/lambda_module_T603.pyx2
-rw-r--r--tests/run/large_consts_T237.pyx2
-rw-r--r--tests/run/letnode_T766.pyx2
-rw-r--r--tests/run/list_comp_in_closure_T598.pyx2
-rw-r--r--tests/run/locals_T732.pyx2
-rw-r--r--tests/run/locals_expressions_T430.pyx2
-rw-r--r--tests/run/locals_rebind_T429.pyx2
-rw-r--r--tests/run/method_module_name_T422.pyx2
-rw-r--r--tests/run/methodmangling_T5.py2
-rw-r--r--tests/run/non_dict_kwargs_T470.pyx2
-rw-r--r--tests/run/numpy_ValueError_T172.pyx2
-rw-r--r--tests/run/numpy_bufacc_T155.pyx2
-rw-r--r--tests/run/numpy_test.pyx20
-rw-r--r--tests/run/packedstruct_T290.pyx2
-rw-r--r--tests/run/parallel_swap_assign_T425.pyx2
-rw-r--r--tests/run/posonly.py12
-rw-r--r--tests/run/property_decorator_T593.py2
-rw-r--r--tests/run/ptr_warning_T714.pyx2
-rw-r--r--tests/run/pure_cdef_class_property_decorator_T264.pxd2
-rw-r--r--tests/run/pure_cdef_class_property_decorator_T264.py2
-rw-r--r--tests/run/pxd_argument_names.srctree2
-rw-r--r--tests/run/pyclass_scope_T671.py2
-rw-r--r--tests/run/pyfunction_redefine_T489.pyx2
-rw-r--r--tests/run/pyobjcast_T313.pyx2
-rw-r--r--tests/run/raise_memory_error_T650.pyx2
-rw-r--r--tests/run/range_optimisation_T203.pyx2
-rw-r--r--tests/run/self_in_ext_type_closure.pyx2
-rw-r--r--tests/run/set.pyx8
-rw-r--r--tests/run/short_circuit_T404.pyx2
-rw-r--r--tests/run/special_methods_T561.pyx4
-rw-r--r--tests/run/special_methods_T561_py2.pyx2
-rw-r--r--tests/run/special_methods_T561_py3.pyx2
-rw-r--r--tests/run/ssize_t_T399.pyx2
-rw-r--r--tests/run/starred_target_T664.pyx2
-rw-r--r--tests/run/str_char_coercion_T412.pyx2
-rw-r--r--tests/run/temp_alloc_T409.pyx2
-rw-r--r--tests/run/temp_sideeffects_T654.pyx2
-rw-r--r--tests/run/test_asyncgen.py82
-rw-r--r--tests/run/test_exceptions.pyx13
-rw-r--r--tests/run/test_fstring.pyx4
-rw-r--r--tests/run/test_genericclass.py150
-rw-r--r--tests/run/test_unicode.pyx18
-rw-r--r--tests/run/time_pxd.pyx59
-rw-r--r--tests/run/tp_new.pyx2
-rw-r--r--tests/run/tp_new_T454.pyx2
-rw-r--r--tests/run/tupleunpack_T298.pyx2
-rw-r--r--tests/run/tupleunpack_T712.pyx2
-rw-r--r--tests/run/type_inference_T768.pyx2
-rw-r--r--tests/run/type_inference_T768_cpp.pyx2
-rw-r--r--tests/run/type_slots_int_long_T287.pyx2
-rw-r--r--tests/run/typeddefaultargT373.pyx2
-rw-r--r--tests/run/typedfieldbug_T303.pyx2
-rw-r--r--tests/run/typetest_T417.pyx2
-rw-r--r--tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx2
-rw-r--r--tests/run/unsignedbehaviour_T184.pyx2
-rw-r--r--tests/run/with_statement_module_level_T536.pyx2
291 files changed, 2794 insertions, 799 deletions
diff --git a/.gitignore b/.gitignore
index fd5461a8c..9da27c0f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,3 +55,6 @@ MANIFEST
# Komodo EDIT/IDE project files
/*.komodoproject
+
+# Visual Studio Code files
+.vscode
diff --git a/.travis.yml b/.travis.yml
index b0c57e637..81a6120c5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,9 +17,10 @@ cache:
- $HOME/.ccache
python:
+ - 3.9
- 3.8
- 2.7
- - 3.9-dev
+ - 3.10-dev
- 3.7
- 3.6
- 3.5
@@ -44,14 +45,14 @@ matrix:
- os: osx
osx_image: xcode10.3
env: PY=2 MACOSX_DEPLOYMENT_TARGET=10.9
- python: 2
+ python: 2.7
language: c
compiler: clang
cache: false
- os: osx
osx_image: xcode10.3
env: PY=3 MACOSX_DEPLOYMENT_TARGET=10.9
- python: 3
+ python: 3.9
language: c
compiler: clang
cache: false
@@ -115,7 +116,6 @@ matrix:
- env: BACKEND=c EXCLUDE="--listfile=tests/pypy_bugs.txt bugs"
- env: BACKEND=c EXCLUDE="--listfile=tests/pypy_bugs.txt --listfile=tests/pypy2_bugs.txt bugs"
-
before_install:
- |
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
@@ -137,8 +137,8 @@ before_install:
conda --version || exit 1
#conda install --quiet --yes nomkl --file=test-requirements.txt --file=test-requirements-cpython.txt
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
- which clang && clang --version && export CC=clang || true
- which clang++ && clang++ --version && export CXX="clang++ -stdlib=libc++" || true
+ which clang && clang --version && export CC="clang -Wno-deprecated-declarations" || true
+ which clang++ && clang++ --version && export CXX="clang++ -stdlib=libc++ -Wno-deprecated-declarations" || true
fi
fi
@@ -152,7 +152,8 @@ before_install:
install:
- python -c 'import sys; print("Python %s" % (sys.version,))'
- - if [ -n "${TRAVIS_PYTHON_VERSION##*-dev}" ]; then pip install -r test-requirements.txt $( [ -z "${TRAVIS_PYTHON_VERSION##pypy*}" -o -z "${TRAVIS_PYTHON_VERSION##3.[4789]*}" ] || echo " -r test-requirements-cpython.txt" ) ; fi
+ - if [ -z "${TRAVIS_PYTHON_VERSION##2.7}" ]; then [ "$TRAVIS_OS_NAME" == "osx" -a "$PY" == "3" ] || pip install -r test-requirements-27.txt ; fi
+ - if [ -n "${TRAVIS_PYTHON_VERSION##*-dev}" -a -n "${TRAVIS_PYTHON_VERSION##2.7}" ]; then pip install -r test-requirements.txt $( [ -z "${TRAVIS_PYTHON_VERSION##pypy*}" -o -z "${TRAVIS_PYTHON_VERSION##3.[47891]*}" ] || echo " -r test-requirements-cpython.txt" ) ; fi
# - CFLAGS="-O2 -ggdb -Wall -Wextra $(python -c 'import sys; print("-fno-strict-aliasing" if sys.version_info[0] == 2 else "")')" python setup.py build
before_script: ccache -s || true
@@ -164,7 +165,7 @@ script:
else
STYLE_ARGS=--no-code-style;
if $PYTHON_DBG -V >&2; then CFLAGS="-O0 -ggdb" $PYTHON_DBG runtests.py -vv --no-code-style Debugger --backends=$BACKEND; fi;
- if [ -z "${BACKEND##*cpp*}" -a -n "${TRAVIS_PYTHON_VERSION##*-dev}" ]; then pip install pythran; fi;
+ if [ -z "${BACKEND##*cpp*}" -a -n "${TRAVIS_PYTHON_VERSION##*-dev}" ]; then pip install pythran==0.9.7; fi;
if [ "$BACKEND" != "cpp" -a -n "${TRAVIS_PYTHON_VERSION##2*}" -a -n "${TRAVIS_PYTHON_VERSION##pypy*}" -a -n "${TRAVIS_PYTHON_VERSION##*-dev}" -a -n "${TRAVIS_PYTHON_VERSION##*3.4}" ]; then pip install mypy; fi;
fi
# Need to clear the ccache? Try something like this:
diff --git a/CHANGES.rst b/CHANGES.rst
index 28d887599..41becd976 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -8,51 +8,88 @@ Cython Changelog
Features added
--------------
-* ``__class_getitem__`` (PEP-560) is supported for cdef classes.
- Patch by Kmol Yuan. (Github issue #3764)
+* ``__class_getitem__`` (`PEP-560`_) is supported for cdef classes.
+ Patch by Kmol Yuan. (Github issue :issue:`3764`)
+
+* ``__mro_entries__`` (`PEP-560`_) is supported for Python classes.
+ Patch by David Woods. (Github issue :issue:`3537`)
* ``cython.array`` supports simple, non-strided views.
- (Github issue #3775)
+ (Github issue :issue:`3775`)
* The destructor is now called for fields in C++ structs.
- Patch by David Woods. (Github issue #3226)
+ Patch by David Woods. (Github issue :issue:`3226`)
* ``asyncio.iscoroutinefunction()`` now recognises coroutine functions
also when compiled by Cython.
- Patch by Pedro Marques da Luz. (Github issue #2273)
+ Patch by Pedro Marques da Luz. (Github issue :issue:`2273`)
+
+* ``float(…)`` is optimised for string arguments (str/bytes/bytearray).
* Docstrings of ``cpdef`` enums are now copied to the enum class.
- Patch by matham. (Github issue #3805)
+ Patch by matham. (Github issue :issue:`3805`)
* The type ``cython.Py_hash_t`` is available in Python mode.
+* The ``cpython.fileobject`` C-API declarations were added.
+ Patch by Zackery Spytz. (Github issue :issue:`3906`)
+
+* A new module ``cpython.time`` was added with some low-level alternatives to
+ Python's ``time`` module.
+ Patch by Brock Mendel. (Github issue :issue:`3767`)
+
* The value ``PyBUF_MAX_NDIM`` was added to the ``cpython.buffer`` module.
- Patch by John Kirkham. (Github issue #3811)
+ Patch by John Kirkham. (Github issue :issue:`3811`)
+
+* "Declaration after use" is now an error for variables.
+ Patch by David Woods. (Github issue :issue:`3976`)
Bugs fixed
----------
* Inline functions and other code in ``.pxd`` files could accidentally
inherit the compiler directives of the ``.pyx`` file that imported them.
- Patch by David Woods. (Github issue #1071)
+ Patch by David Woods. (Github issue :issue:`1071`)
+
+* Some issues were resolved that could lead to duplicated C names.
+ Patch by David Woods. (Github issue :issue:`3716`, :issue:`3741`, :issue:`3734`)
* ``ndarray.shape`` failed to compile with Pythran and recent NumPy.
- Patch by Serge Guelton. (Github issue #3762)
+ Patch by Serge Guelton. (Github issue :issue:`3762`)
* Casting to ctuples is now allowed.
- Patch by David Woods. (Github issue #3808)
+ Patch by David Woods. (Github issue :issue:`3808`)
+
+* Nested C++ types were not usable through ctypedefs.
+ Patch by Vadim Pushtaev. (Github issue :issue:`4039`)
+
+* Cython compiled functions always provided a ``__self__`` attribute, regardless
+ of being used as a method or not.
+ Patch by David Woods. (Github issue :issue:`4036`)
+
+* A reference leak on import failures was resolved.
+ Patch by Max Bachmann. (Github issue :issue:`4056`)
* A C compiler warning about unused code was resolved.
- (Github issue #3763)
+ (Github issue :issue:`3763`)
* A C compiler warning about enum value casting was resolved in GCC.
- (Github issue #2749)
+ (Github issue :issue:`2749`)
+
+* Some C compiler warninge were resolved.
+ Patches by Max Bachmann. (Github issue :issue:`4053`, :issue:`4059`, :issue:`4054`)
* A compile failure for C++ enums in Py3.4 / MSVC was resolved.
- Patch by Ashwin Srinath. (Github issue #3782)
+ Patch by Ashwin Srinath. (Github issue :issue:`3782`)
+
+* An unsupported C-API call in PyPy was fixed.
+ Patch by Max Bachmann. (Github issue :issue:`4055`)
* The Cython ``CodeWriter`` mishandled no-argument ``return`` statements.
- Patch by Tao He. (Github issue #3795)
+ Patch by Tao He. (Github issue :issue:`3795`)
+
+* ``complex`` wasn't supported in PEP-484 type annotations.
+ Patch by David Woods. (Github issue :issue:`3949`)
3.0.0 alpha 6 (2020-07-31)
@@ -70,51 +107,51 @@ Features added
0.29.20), or the reversed method (``__radd__``) can be implemented in
addition to an existing two-sided operator method (``__add__``) to get a
backwards compatible implementation.
- (Github issue #2056)
+ (Github issue :issue:`2056`)
* No/single argument functions now accept keyword arguments by default in order
to comply with Python semantics. The marginally faster calling conventions
``METH_NOARGS`` and ``METH_O`` that reject keyword arguments are still available
with the directive ``@cython.always_allow_keywords(False)``.
- (Github issue #3090)
+ (Github issue :issue:`3090`)
* For-in-loop iteration over ``bytearray`` and memory views is optimised.
- Patch by David Woods. (Github issue #2227)
+ Patch by David Woods. (Github issue :issue:`2227`)
* Type inference now works for memory views and slices.
- Patch by David Woods. (Github issue #2227)
+ Patch by David Woods. (Github issue :issue:`2227`)
* The ``@returns()`` decorator propagates exceptions by default for suitable C
return types when no ``@exceptval()`` is defined.
- (Github issues #3625, #3664)
+ (Github issues :issue:`3625`, :issue:`3664`)
* A low-level inline function ``total_seconds(timedelta)`` was added to
``cpython.datetime`` to bypass the Python method call. Note that this function
is not guaranteed to give exactly the same results for very large time intervals.
- Patch by Brock Mendel. (Github issue #3616)
+ Patch by Brock Mendel. (Github issue :issue:`3616`)
* Type inference now understands that ``a, *b = x`` assigns a list to ``b``.
* Limited API support was improved.
- Patches by Matthias Braun. (Github issues #3693, #3707)
+ Patches by Matthias Braun. (Github issues :issue:`3693`, :issue:`3707`)
* The Cython ``CodeWriter`` can now handle more syntax constructs.
- Patch by Tao He. (Github issue #3514)
+ Patch by Tao He. (Github issue :issue:`3514`)
Bugs fixed
----------
* The construct ``for x in cpp_function_call()`` failed to compile.
- Patch by David Woods. (Github issue #3663)
+ Patch by David Woods. (Github issue :issue:`3663`)
* C++ references failed to compile when used as Python object indexes.
- Patch by David Woods. (Github issue #3754)
+ Patch by David Woods. (Github issue :issue:`3754`)
* The C++ ``typeid()`` function was allowed in C mode.
- Patch by Celelibi. (Github issue #3637)
+ Patch by Celelibi. (Github issue :issue:`3637`)
* ``repr()`` was assumed to return ``str`` instead of ``unicode`` with ``language_level=3``.
- (Github issue #3736)
+ (Github issue :issue:`3736`)
* Includes all bug-fixes from the 0.29.21 release.
@@ -131,43 +168,42 @@ Other changes
homeless builtins, to help with debugging, and in order to avoid a CPython
warning according to https://bugs.python.org/issue20204
-
3.0.0 alpha 5 (2020-05-19)
==========================
Features added
--------------
-* ``.pxd`` files can now be versioned by adding an extension like "``.cython-30.pxd``"
- to prevent older Cython versions (than 3.0 in this case) from picking them up.
- (Github issue #3577)
+* ``.pxd`` files can now be :ref:`versioned <versioning>` by adding an
+ extension like "``.cython-30.pxd``" to prevent older Cython versions (than
+ 3.0 in this case) from picking them up. (Github issue :issue:`3577`)
* Several macros/functions declared in the NumPy API are now usable without
holding the GIL.
-* ``libc.math`` was extended to include all C99 function declarations.
- Patch by Dean Scarff. (Github issue #3570)
+* `libc.math` was extended to include all C99 function declarations.
+ Patch by Dean Scarff. (Github issue :issue:`3570`)
Bugs fixed
----------
* Several issues with arithmetic overflow handling were resolved, including
undefined behaviour in C.
- Patch by Sam Sneddon. (Github issue #3588)
+ Patch by Sam Sneddon. (Github issue :issue:`3588`)
* The improved GIL handling in ``nogil`` functions introduced in 3.0a3
could fail to acquire the GIL in some cases on function exit.
- (Github issue #3590 etc.)
+ (Github issue :issue:`3590` etc.)
* A reference leak when processing keyword arguments in Py2 was resolved,
that appeared in 3.0a1.
- (Github issue #3578)
+ (Github issue :issue:`3578`)
* The outdated getbuffer/releasebuffer implementations in the NumPy
declarations were removed so that buffers declared as ``ndarray``
now use the normal implementation in NumPy.
-* Includes all bug-fixes from the 0.29.18 release.
+* Includes all bug-fixes from the :ref:0.29.18 release.
3.0.0 alpha 4 (2020-05-05)
@@ -201,15 +237,15 @@ Bugs fixed
C-API functions with an error held.
* Complex buffer item types of structs of arrays could fail to validate.
- Patch by Leo and smutch. (Github issue #1407)
+ Patch by Leo and smutch. (Github issue :issue:`1407`)
* When importing the old Cython ``build_ext`` integration with distutils, the
additional command line arguments leaked into the regular command.
- Patch by Kamekameha. (Github issue #2209)
+ Patch by Kamekameha. (Github issue :issue:`2209`)
* The improved GIL handling in ``nogil`` functions introduced in 3.0a3
could generate invalid C code.
- (Github issue #3558)
+ (Github issue :issue:`3558`)
* ``PyEval_InitThreads()`` is no longer used in Py3.7+ where it is a no-op.
@@ -219,7 +255,7 @@ Other changes
-------------
* The C property feature has been rewritten and now requires C property methods
- to be declared ``inline``.
+ to be declared ``inline`` (:issue:`3571`).
3.0.0 alpha 3 (2020-04-27)
@@ -230,17 +266,17 @@ Features added
* ``nogil`` functions now avoid acquiring the GIL on function exit if possible
even if they contain ``with gil`` blocks.
- (Github issue #3554)
+ (Github issue :issue:`3554`)
* Python private name mangling now falls back to unmangled names for non-Python
globals, since double-underscore names are not uncommon in C. Unmangled Python
names are also still found as a legacy fallback but produce a warning.
- Patch by David Woods. (Github issue #3548)
+ Patch by David Woods. (Github issue :issue:`3548`)
Bugs fixed
----------
-* Includes all bug-fixes from the 0.29.17 release.
+* Includes all bug-fixes from the :ref:0.29.17 release.
3.0.0 alpha 2 (2020-04-23)
@@ -251,29 +287,29 @@ Features added
* ``std::move()`` is now used in C++ mode for internal temp variables to
make them work without copying values.
- Patch by David Woods. (Github issues #3253, 1612)
+ Patch by David Woods. (Github issues :issue:`3253`, :issue:`1612`)
-* ``__class_getitem__`` is supported for types on item access (PEP-560).
- Patch by msg555. (Github issue #2753)
+* ``__class_getitem__`` is supported for types on item access (`PEP-560`_).
+ Patch by msg555. (Github issue :issue:`2753`)
-* The simplified Py3.6 customisation of class creation is implemented (PEP-487).
+* The simplified Py3.6 customisation of class creation is implemented (`PEP-487`_).
(Github issue #2781)
* Conditional blocks in Python code that depend on ``cython.compiled`` are
eliminated at an earlier stage, which gives more freedom in writing
replacement Python code.
- Patch by David Woods. (Github issue #3507)
+ Patch by David Woods. (Github issue :issue:`3507`)
* ``numpy.import_array()`` is automatically called if ``numpy`` has been cimported
and it has not been called in the module code. This is intended as a hidden
fail-safe so user code should continue to call ``numpy.import_array``.
- Patch by David Woods. (Github issue #3524)
+ Patch by David Woods. (Github issue :issue:`3524`)
* The Cython AST code serialiser class ``CodeWriter`` in ``Cython.CodeWriter``
supports more syntax nodes.
* The fastcall/vectorcall protocols are used for several internal Python calls.
- (Github issue #3540)
+ (Github issue :issue:`3540`)
Bugs fixed
----------
@@ -281,23 +317,23 @@ Bugs fixed
* With ``language_level=3/3str``, Python classes without explicit base class
are now new-style (type) classes also in Py2. Previously, they were created
as old-style (non-type) classes.
- (Github issue #3530)
+ (Github issue :issue:`3530`)
* C++ ``typeid()`` failed for fused types.
- Patch by David Woods. (Github issue #3203)
+ Patch by David Woods. (Github issue :issue:`3203`)
* ``__arg`` argument names in methods were not mangled with the class name.
- Patch by David Woods. (Github issue #1382)
+ Patch by David Woods. (Github issue :issue:`1382`)
* Creating an empty unicode slice with large bounds could crash.
- Patch by Sam Sneddon. (Github issue #3531)
+ Patch by Sam Sneddon. (Github issue :issue:`3531`)
* Decoding an empty bytes/char* slice with large bounds could crash.
- Patch by Sam Sneddon. (Github issue #3534)
+ Patch by Sam Sneddon. (Github issue :issue:`3534`)
* Temporary buffer indexing variables were not released and could show up in
C compiler warnings, e.g. in generators.
- Patch by David Woods. (Github issues #3430, #3522)
+ Patch by David Woods. (Github issues :issue:`3430`, :issue:`3522`)
* Several C compiler warnings were fixed.
@@ -308,113 +344,117 @@ Bugs fixed
Features added
--------------
-* Cython functions now use the PEP-590 vectorcall protocol in Py3.7+.
- Patch by Jeroen Demeyer. (Github issue #2263)
+* Cython functions now use the `PEP-590`_ vectorcall protocol in Py3.7+.
+ Patch by Jeroen Demeyer. (Github issue :issue:`2263`)
-* Unicode identifiers are supported in Cython code (PEP 3131).
- Patch by David Woods. (Github issue #2601)
+* Unicode identifiers are supported in Cython code (`PEP-3131`_).
+ Patch by David Woods. (Github issue :issue:`2601`)
* Unicode module names and imports are supported.
- Patch by David Woods. (Github issue #3119)
+ Patch by David Woods. (Github issue :issue:`3119`)
-* Annotations are no longer parsed, keeping them as strings following PEP-563.
- Patch by David Woods. (Github issue #3285)
+* Annotations are no longer parsed, keeping them as strings following `PEP-563`_.
+ Patch by David Woods. (Github issue :issue:`3285`)
* Preliminary support for the CPython's ``Py_LIMITED_API`` (stable ABI) is
available by setting the ``CYTHON_LIMITED_API`` C macro. Note that the
support is currently in an early stage and many features do not yet work.
- Patches by Eddie Elizondo and David Woods. (Github issues #3223, #3311, #3501)
+ You currently still have to define ``Py_LIMITED_API`` externally in order
+ to restrict the API usage. This will change when the feature stabilises.
+ Patches by Eddie Elizondo and David Woods. (Github issues :issue:`3223`,
+ :issue:`3311`, :issue:`3501`)
* The dispatch to fused functions is now linear in the number of arguments,
which makes it much faster, often 2x or more, and several times faster for
larger fused types with many specialisations.
- Patch by will-ca. (Github issue #1385)
+ Patch by will-ca. (Github issue :issue:`1385`)
* ``with gil/nogil`` statements can be conditional based on compile-time
constants, e.g. fused type checks.
- Patch by Noam Hershtig. (Github issue #2579)
+ Patch by Noam Hershtig. (Github issue :issue:`2579`)
* ``const`` can be used together with fused types.
- Patch by Thomas Vincent. (Github issue #1772)
+ Patch by Thomas Vincent. (Github issue :issue:`1772`)
* Reimports of already imported modules are substantially faster.
- (Github issue #2854)
+ (Github issue :issue:`2854`)
-* Positional-only arguments are supported in Python functions (PEP-570).
- Patch by Josh Tobin. (Github issue #2915)
+* Positional-only arguments are supported in Python functions (`PEP-570`_).
+ Patch by Josh Tobin. (Github issue :issue:`2915`)
* The ``volatile`` C modifier is supported in Cython code.
Patch by Jeroen Demeyer. (Github issue #1667)
* ``@cython.trashcan(True)`` can be used on an extension type to enable the
- CPython trashcan. This allows deallocating deeply recursive objects without
- overflowing the stack. Patch by Jeroen Demeyer. (Github issue #2842)
+ CPython :ref:`trashcan`. This allows deallocating deeply recursive objects
+ without overflowing the stack. Patch by Jeroen Demeyer. (Github issue :issue:`2842`)
* Inlined properties can be defined for external extension types.
- Patch by Matti Picus. (Github issue #2640)
+ Patch by Matti Picus. (Github issue :issue:`2640`, redone later in :issue:`3571`)
* The ``str()`` builtin now calls ``PyObject_Str()`` instead of going
through a Python call.
- Patch by William Ayd. (Github issue #3279)
+ Patch by William Ayd. (Github issue :issue:`3279`)
* String concatenation can now happen in place if possible, by extending the
existing string rather than always creating a new one.
- Patch by David Woods. (Github issue #3453)
+ Patch by David Woods. (Github issue :issue:`3453`)
* Multiplication of Python numbers with small constant integers is faster.
- (Github issue #2808)
+ (Github issue :issue:`2808`)
* Some list copying is avoided internally when a new list needs to be created
but we already have a fresh one.
- (Github issue #3494)
+ (Github issue :issue:`3494`)
* Extension types that do not need their own ``tp_new`` implementation (because
they have no object attributes etc.) directly inherit the implementation of
their parent type if possible.
- (Github issue #1555)
+ (Github issue :issue:`1555`)
* The attributes ``gen.gi_frame`` and ``coro.cr_frame`` of Cython compiled
generators and coroutines now return an actual frame object for introspection.
- (Github issue #2306)
+ (Github issue :issue:`2306`)
* Several declarations in ``cpython.*``, ``libc.*`` and ``libcpp.*`` were added.
Patches by Jeroen Demeyer, Matthew Edwards, Chris Gyurgyik, Jerome Kieffer
and Zackery Spytz.
- (Github issues #3468, #3332, #3202, #3188, #3179, #2891, #2826, #2713)
+ (Github issues :issue:`3468`, :issue:`3332`, :issue:`3202`, :issue:`3188`,
+ :issue:`3179`, :issue:`2891`, :issue:`2826`, :issue:`2713`)
* Deprecated NumPy API usages were removed from ``numpy.pxd``.
- Patch by Matti Picus. (Github issue #3365)
+ Patch by Matti Picus. (Github issue :issue:`3365`)
* ``cython.inline()`` now sets the ``NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION``
C macro automatically when ``numpy`` is imported in the code, to avoid C compiler
warnings about deprecated NumPy C-API usage.
* The builtin ``abs()`` function can now be used on C numbers in nogil code.
- Patch by Elliott Sales de Andrade. (Github issue #2748)
+ Patch by Elliott Sales de Andrade. (Github issue :issue:`2748`)
-* PEP-479 (``generator_stop``) is now enabled by default with language level 3.
- (Github issue #2580)
+* `PEP-479`_ (``generator_stop``) is now enabled by default with language level 3.
+ (Github issue :issue:`2580`)
* The ``cython.view.array`` type supports inheritance.
- Patch by David Woods. (Github issue #3413)
+ Patch by David Woods. (Github issue :issue:`3413`)
* Code annotation accepts a new debugging argument ``--annotate-fullc`` that
will include the complete syntax highlighted C file in the HTML output.
- (Github issue #2855)
+ (Github issue :issue:`2855`)
* ``--no-capture`` added to ``runtests.py`` to prevent stdout/stderr capturing
during srctree tests.
- Patch by Matti Picus. (Github issue #2701)
+ Patch by Matti Picus. (Github issue :issue:`2701`)
* ``--no-docstrings`` option added to ``cythonize`` script.
- Original patch by mo-han. (Github issue #2889)
+ Original patch by mo-han. (Github issue :issue:`2889`)
* ``cygdb`` gives better error messages when it fails to initialise the
Python runtime support in gdb.
- Patch by Volker Weissmann. (Github issue #3489)
+ Patch by Volker Weissmann. (Github issue :issue:`3489`)
* The Pythran ``shape`` attribute is supported.
- Patch by Serge Guelton. (Github issue #3307)
+ Patch by Serge Guelton. (Github issue :issue:`3307`)
Bugs fixed
----------
@@ -426,7 +466,7 @@ Bugs fixed
* Fused argument types were not correctly handled in type annotations and
``cython.locals()``.
- Patch by David Woods. (Github issues #3391, #3142)
+ Patch by David Woods. (Github issues :issue:`3391`, :issue:`3142`)
* Diverging from the usual behaviour, ``len(memoryview)``, ``len(char*)``
and ``len(Py_UNICODE*)`` returned an unsigned ``size_t`` value. They now
@@ -435,59 +475,59 @@ Bugs fixed
* Nested dict literals in function call kwargs could incorrectly raise an
error about duplicate keyword arguments, which are allowed when passing
them from dict literals.
- (Github issue #2963)
+ (Github issue :issue:`2963`)
* Item access (subscripting) with integer indices/keys always tried the
Sequence protocol before the Mapping protocol, which diverged from Python
semantics. It now passes through the Mapping protocol first when supported.
- (Github issue #1807)
+ (Github issue :issue:`1807`)
* Name lookups in class bodies no longer go through an attribute lookup.
- Patch by Jeroen Demeyer. (Github issue #3100)
+ Patch by Jeroen Demeyer. (Github issue :issue:`3100`)
* Broadcast assignments to a multi-dimensional memory view slice could end
up in the wrong places when the underlying memory view is known to be
contiguous but the slice is not.
- (Github issue #2941)
+ (Github issue :issue:`2941`)
* Pickling unbound methods of Python classes failed.
- Patch by Pierre Glaser. (Github issue #2972)
+ Patch by Pierre Glaser. (Github issue :issue:`2972`)
* The ``Py_hash_t`` type failed to accept arbitrary "index" values.
- (Github issue #2752)
+ (Github issue :issue:`2752`)
* The first function line number of functions with decorators pointed to the
signature line and not the first decorator line, as in Python.
- Patch by Felix Kohlgrüber. (Github issue #2536)
+ Patch by Felix Kohlgrüber. (Github issue :issue:`2536`)
* Constant integer expressions that used a negative exponent were evaluated
as integer 0 instead of the expected float value.
- Patch by Kryštof Pilnáček. (Github issue #2133)
+ Patch by Kryštof Pilnáček. (Github issue :issue:`2133`)
* The ``cython.declare()`` and ``cython.cast()`` functions could fail in pure mode.
- Patch by Dmitry Shesterkin. (Github issue #3244)
+ Patch by Dmitry Shesterkin. (Github issue :issue:`3244`)
* ``__doc__`` was not available inside of the class body during class creation.
- (Github issue #1635)
+ (Github issue :issue:`1635`)
* Setting ``language_level=2`` in a file did not work if ``language_level=3``
was enabled globally before.
- Patch by Jeroen Demeyer. (Github issue #2791)
+ Patch by Jeroen Demeyer. (Github issue :issue:`2791`)
* ``__init__.pyx`` files were not always considered as package indicators.
- (Github issue #2665)
+ (Github issue :issue:`2665`)
* Compiling package ``__init__`` files could fail under Windows due to an
- undefined export symbol. (Github issue #2968)
+ undefined export symbol. (Github issue :issue:`2968`)
* A C compiler cast warning was resolved.
- Patch by Michael Buesch. (Github issue #2775)
+ Patch by Michael Buesch. (Github issue :issue:`2775`)
* Binding staticmethods of Cython functions were not behaving like Python methods.
- Patch by Jeroen Demeyer. (Github issue #3106, #3102)
+ Patch by Jeroen Demeyer. (Github issue :issue:`3106`, :issue:`3102`)
* Memoryviews failed to compile when the ``cache_builtins`` feature was disabled.
- Patch by David Woods. (Github issue #3406)
+ Patch by David Woods. (Github issue :issue:`3406`)
Other changes
-------------
@@ -496,55 +536,124 @@ Other changes
but with ``str`` literals (also in Python 2.7). This is a backwards incompatible
change from the previous default of Python 2 semantics. The previous behaviour
is available through the directive ``language_level=2``.
- (Github issue #2565)
+ (Github issue :issue:`2565`)
* Cython no longer generates ``__qualname__`` attributes for classes in Python
2.x since they are problematic there and not correctly maintained for subclasses.
- Patch by Jeroen Demeyer. (Github issue #2772)
+ Patch by Jeroen Demeyer. (Github issue :issue:`2772`)
* Source file fingerprinting now uses SHA-1 instead of MD5 since the latter
tends to be slower and less widely supported these days.
- (Github issue #2790)
+ (Github issue :issue:`2790`)
* The long deprecated include files ``python_*``, ``stdio``, ``stdlib`` and
``stl`` in ``Cython/Includes/Deprecated/`` were removed. Use the ``libc.*``
and ``cpython.*`` pxd modules instead.
- Patch by Jeroen Demeyer. (Github issue #2904)
+ Patch by Jeroen Demeyer. (Github issue :issue:`2904`)
* The search order for include files was changed. Previously it was
``include_directories``, ``Cython/Includes``, ``sys.path``. Now it is
``include_directories``, ``sys.path``, ``Cython/Includes``. This was done to
allow third-party ``*.pxd`` files to override the ones in Cython.
- Patch by Matti Picus. (Github issue #2905)
+ Patch by Matti Picus. (Github issue :issue:`2905`)
* The command line parser was rewritten and modernised using ``argparse``.
- Patch by Egor Dranischnikow. (Github issue #2952, #3001)
+ Patch by Egor Dranischnikow. (Github issue :issue:`2952`, :issue:`3001`)
* Dotted filenames for qualified module names (``pkg.mod.pyx``) are deprecated.
Use the normal Python package directory layout instead.
- (Github issue #2686)
+ (Github issue :issue:`2686`)
* Binary Linux wheels now follow the manylinux2010 standard.
- Patch by Alexey Stepanov. (Github issue #3355)
+ Patch by Alexey Stepanov. (Github issue :issue:`3355`)
* Support for Python 2.6 was removed.
+.. _`PEP-560`: https://www.python.org/dev/peps/pep-0560
+.. _`PEP-570`: https://www.python.org/dev/peps/pep-0570
+.. _`PEP-487`: https://www.python.org/dev/peps/pep-0487
+.. _`PEP-590`: https://www.python.org/dev/peps/pep-0590
+.. _`PEP-3131`: https://www.python.org/dev/peps/pep-3131
+.. _`PEP-563`: https://www.python.org/dev/peps/pep-0563
+.. _`PEP-479`: https://www.python.org/dev/peps/pep-0479
+
+
+0.29.23 (2021-04-14)
+====================
+
+Bugs fixed
+----------
+
+* Some problems with Python 3.10 were resolved.
+ Patches by Victor Stinner and David Woods. (Github issues #4046, #4100)
+
+* An incorrect "optimisation" was removed that allowed changes to a keyword
+ dict to leak into keyword arguments passed into a function.
+ Patch by Peng Weikang. (Github issue #3227)
+
+* Multiplied str constants could end up as bytes constants with language_level=2.
+ Patch by Alphadelta14 and David Woods. (Github issue #3951)
+
+* ``PY_SSIZE_T_CLEAN`` does not get defined any more if it is already defined.
+ Patch by Andrew Jones. (Github issue #4104)
-0.29.22 (2020-??-??)
+
+0.29.22 (2021-02-20)
====================
+Features added
+--------------
+
+* Some declarations were added to the provided pxd includes.
+ Patches by Zackery Spytz and John Kirkham.
+ (Github issues #3811, #3882, #3899, #3901)
+
Bugs fixed
----------
+* A crash when calling certain functions in Py3.9 and later was resolved.
+ (Github issue #3917)
+
+* ``const`` memory views of structs failed to compile.
+ (Github issue #2251)
+
+* ``const`` template declarations could not be nested.
+ Patch by Ashwin Srinath. (Github issue #1355)
+
+* The declarations in the ``cpython.pycapsule`` module were missing their
+ ``const`` modifiers and generated incorrect C code.
+ Patch by Warren Weckesser. (Github issue #3964)
+
+* Casts to memory views failed for fused dtypes.
+ Patch by David Woods. (Github issue #3881)
+
* ``repr()`` was assumed to return ``str`` instead of ``unicode`` with ``language_level=3``.
(Github issue #3736)
+* Calling ``cpdef`` functions from cimported modules crashed the compiler.
+ Patch by David Woods. (Github issue #4000)
+
* Cython no longer validates the ABI size of the NumPy classes it compiled against.
See the discussion in https://github.com/numpy/numpy/pull/432
* A C compiler warning about enum value casting was resolved in GCC.
(Github issue #2749)
+* Coverage reporting in the annotated HTML file failed in Py3.9.
+ Patch by Nick Pope. (Github issue #3865)
+
+* The embedding code now reports Python errors as exit status.
+
+* Long type declarations could lead to (harmless) random changes in the
+ C file when used in auto-generated Python wrappers or pickled classes.
+
+Other changes
+-------------
+
+* Variables defined as ``cpdef`` now generate a warning since this
+ is currently useless and thus does not do what users would expect.
+ Patch by David Woods. (Github issue #3959)
+
0.29.21 (2020-07-09)
====================
@@ -3468,7 +3577,7 @@ Features added
* Extension type inheritance from builtin types, such as "cdef class MyUnicode(unicode)", now works without further external type redeclarations (which are also strongly discouraged now and continue to issue a warning).
-* GDB support. http://docs.cython.org/src/userguide/debugging.html
+* GDB support. https://docs.cython.org/src/userguide/debugging.html
* A new build system with support for inline distutils directives, correct dependency tracking, and parallel compilation. https://github.com/cython/cython/wiki/enhancements-distutils_preprocessing
diff --git a/Cython/Build/Dependencies.py b/Cython/Build/Dependencies.py
index e03046d49..46a763c37 100644
--- a/Cython/Build/Dependencies.py
+++ b/Cython/Build/Dependencies.py
@@ -613,10 +613,10 @@ class DependencyTree(object):
@cached_method
def immediate_dependencies(self, filename):
- all = set([filename])
- all.update(self.cimported_files(filename))
- all.update(self.included_files(filename))
- return all
+ all_deps = {filename}
+ all_deps.update(self.cimported_files(filename))
+ all_deps.update(self.included_files(filename))
+ return all_deps
def all_dependencies(self, filename):
return self.transitive_merge(filename, self.immediate_dependencies, set.union)
@@ -759,7 +759,7 @@ def create_extension_list(patterns, exclude=None, ctx=None, aliases=None, quiet=
return [], {}
elif isinstance(patterns, basestring) or not isinstance(patterns, Iterable):
patterns = [patterns]
- explicit_modules = set([m.name for m in patterns if isinstance(m, Extension)])
+ explicit_modules = {m.name for m in patterns if isinstance(m, Extension)}
seen = set()
deps = create_dependency_tree(ctx, quiet=quiet)
to_exclude = set()
@@ -948,6 +948,11 @@ def cythonize(module_list, exclude=None, nthreads=0, aliases=None, quiet=False,
See examples in :ref:`determining_where_to_add_types` or
:ref:`primes`.
+
+ :param annotate-fullc: If ``True`` will produce a colorized HTML version of
+ the source which includes entire generated C/C++-code.
+
+
:param compiler_directives: Allow to set compiler directives in the ``setup.py`` like this:
``compiler_directives={'embedsignature': True}``.
See :ref:`compiler-directives`.
diff --git a/Cython/Compiler/AnalysedTreeTransforms.py b/Cython/Compiler/AnalysedTreeTransforms.py
index 07bf31f3e..d4941606e 100644
--- a/Cython/Compiler/AnalysedTreeTransforms.py
+++ b/Cython/Compiler/AnalysedTreeTransforms.py
@@ -10,9 +10,9 @@ from . import Symtab
class AutoTestDictTransform(ScopeTrackingTransform):
# Handles autotestdict directive
- blacklist = ['__cinit__', '__dealloc__', '__richcmp__',
- '__nonzero__', '__bool__',
- '__len__', '__contains__']
+ excludelist = ['__cinit__', '__dealloc__', '__richcmp__',
+ '__nonzero__', '__bool__',
+ '__len__', '__contains__']
def visit_ModuleNode(self, node):
if node.is_pxd:
@@ -81,7 +81,7 @@ class AutoTestDictTransform(ScopeTrackingTransform):
name = node.entry.name
else:
name = node.name
- if self.scope_type == 'cclass' and name in self.blacklist:
+ if self.scope_type == 'cclass' and name in self.excludelist:
return node
if self.scope_type == 'pyclass':
class_name = self.scope_node.name
diff --git a/Cython/Compiler/Buffer.py b/Cython/Compiler/Buffer.py
index 79687163c..ce8503626 100644
--- a/Cython/Compiler/Buffer.py
+++ b/Cython/Compiler/Buffer.py
@@ -669,9 +669,11 @@ def get_type_information_cname(code, dtype, maxdepth=None):
if dtype.is_simple_buffer_dtype():
structinfo_name = "NULL"
elif dtype.is_struct:
- fields = dtype.scope.var_entries
- # Must pre-call all used types in order not to recurse utility code
- # writing.
+ struct_scope = dtype.scope
+ if dtype.is_cv_qualified:
+ struct_scope = struct_scope.base_type_scope
+ # Must pre-call all used types in order not to recurse during utility code writing.
+ fields = struct_scope.var_entries
assert len(fields) > 0
types = [get_type_information_cname(code, f.type, maxdepth - 1)
for f in fields]
diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py
index fe132c19d..4e606b2d9 100644
--- a/Cython/Compiler/Builtin.py
+++ b/Cython/Compiler/Builtin.py
@@ -346,15 +346,15 @@ builtin_types_table = [
]
-types_that_construct_their_instance = set([
+types_that_construct_their_instance = frozenset({
# some builtin types do not always return an instance of
# themselves - these do:
'type', 'bool', 'long', 'float', 'complex',
'bytes', 'unicode', 'bytearray',
- 'tuple', 'list', 'dict', 'set', 'frozenset'
+ 'tuple', 'list', 'dict', 'set', 'frozenset',
# 'str', # only in Py3.x
# 'file', # only in Py2.x
-])
+})
builtin_structs_table = [
@@ -430,7 +430,7 @@ def init_builtins():
global list_type, tuple_type, dict_type, set_type, frozenset_type
global bytes_type, str_type, unicode_type, basestring_type, slice_type
- global float_type, bool_type, type_type, complex_type, bytearray_type
+ global float_type, long_type, bool_type, type_type, complex_type, bytearray_type
type_type = builtin_scope.lookup('type').type
list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type
@@ -444,6 +444,7 @@ def init_builtins():
basestring_type = builtin_scope.lookup('basestring').type
bytearray_type = builtin_scope.lookup('bytearray').type
float_type = builtin_scope.lookup('float').type
+ long_type = builtin_scope.lookup('long').type
bool_type = builtin_scope.lookup('bool').type
complex_type = builtin_scope.lookup('complex').type
diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py
index 571254b18..9968a6336 100644
--- a/Cython/Compiler/Code.py
+++ b/Cython/Compiler/Code.py
@@ -100,12 +100,12 @@ uncachable_builtins = [
'_', # e.g. used by gettext
]
-special_py_methods = set([
+special_py_methods = cython.declare(frozenset, frozenset((
'__cinit__', '__dealloc__', '__richcmp__', '__next__',
'__await__', '__aiter__', '__anext__',
'__getreadbuffer__', '__getwritebuffer__', '__getsegcount__',
- '__getcharbuffer__', '__getbuffer__', '__releasebuffer__'
-])
+ '__getcharbuffer__', '__getbuffer__', '__releasebuffer__',
+)))
modifier_output_mapper = {
'inline': 'CYTHON_INLINE'
@@ -382,7 +382,7 @@ class UtilityCodeBase(object):
elif name == 'substitute':
# don't want to pass "naming" or "tempita" to the constructor
# since these will have been handled
- values = values - set(['naming', 'tempita'])
+ values = values - {'naming', 'tempita'}
if not values:
continue
elif not values:
@@ -2412,7 +2412,8 @@ class CCodeWriter(object):
return self.error_goto_if("!%s" % cname, pos)
def error_goto_if_neg(self, cname, pos):
- return self.error_goto_if("%s < 0" % cname, pos)
+ # Add extra parentheses to silence clang warnings about constant conditions.
+ return self.error_goto_if("(%s < 0)" % cname, pos)
def error_goto_if_PyErr(self, pos):
return self.error_goto_if("PyErr_Occurred()", pos)
diff --git a/Cython/Compiler/CythonScope.py b/Cython/Compiler/CythonScope.py
index 8085d1890..bb9e74aa6 100644
--- a/Cython/Compiler/CythonScope.py
+++ b/Cython/Compiler/CythonScope.py
@@ -125,7 +125,7 @@ class CythonScope(ModuleScope):
view_utility_scope = MemoryView.view_utility_code.declare_in_scope(
self.viewscope, cython_scope=self,
- whitelist=MemoryView.view_utility_whitelist)
+ allowlist=MemoryView.view_utility_allowlist)
# Marks the types as being cython_builtin_type so that they can be
# extended from without Cython attempting to import cython.view
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index e50fb2363..2714d3e4d 100644
--- a/Cython/Compiler/ExprNodes.py
+++ b/Cython/Compiler/ExprNodes.py
@@ -183,7 +183,7 @@ def infer_sequence_item_type(env, seq_node, index_node=None, seq_type=None):
else:
return item.infer_type(env)
# if we're lucky, all items have the same type
- item_types = set([item.infer_type(env) for item in seq_node.args])
+ item_types = {item.infer_type(env) for item in seq_node.args}
if len(item_types) == 1:
return item_types.pop()
return None
@@ -6214,7 +6214,7 @@ class PyMethodCallNode(SimpleCallNode):
# not an attribute itself, but might have been assigned from one (e.g. bound method)
for assignment in self.function.cf_state:
value = assignment.rhs
- if value and value.is_attribute and value.obj.type.is_pyobject:
+ if value and value.is_attribute and value.obj.type and value.obj.type.is_pyobject:
if attribute_is_likely_method(value):
likely_method = 'likely'
break
@@ -6535,8 +6535,10 @@ class GeneralCallNode(CallNode):
len(pos_args)))
return None
- matched_args = set([ arg.name for arg in declared_args[:len(pos_args)]
- if arg.name ])
+ matched_args = {
+ arg.name for arg in declared_args[:len(pos_args)]
+ if arg.name
+ }
unmatched_args = declared_args[len(pos_args):]
matched_kwargs_count = 0
args = list(pos_args)
@@ -6754,22 +6756,13 @@ class MergedDictNode(ExprNode):
return dict_type
def analyse_types(self, env):
- args = [
+ self.keyword_args = [
arg.analyse_types(env).coerce_to_pyobject(env).as_none_safe_node(
# FIXME: CPython's error message starts with the runtime function name
'argument after ** must be a mapping, not NoneType')
for arg in self.keyword_args
]
- if len(args) == 1 and args[0].type is dict_type:
- # strip this intermediate node and use the bare dict
- arg = args[0]
- if arg.is_name and arg.entry.is_arg and len(arg.entry.cf_assignments) == 1:
- # passing **kwargs through to function call => allow NULL
- arg.allow_null = True
- return arg
-
- self.keyword_args = args
return self
def may_be_none(self):
@@ -6938,7 +6931,11 @@ class AttributeNode(ExprNode):
# FIXME: this is way too redundant with analyse_types()
node = self.analyse_as_cimported_attribute_node(env, target=False)
if node is not None:
- return node.entry.type
+ if node.entry.type and node.entry.type.is_cfunction:
+ # special-case - function converted to pointer
+ return PyrexTypes.CPtrType(node.entry.type)
+ else:
+ return node.entry.type
node = self.analyse_as_type_attribute(env)
if node is not None:
return node.entry.type
@@ -8756,7 +8753,7 @@ class SetNode(ExprNode):
return False
def calculate_constant_result(self):
- self.constant_result = set([arg.constant_result for arg in self.args])
+ self.constant_result = {arg.constant_result for arg in self.args}
def compile_time_value(self, denv):
values = [arg.compile_time_value(denv) for arg in self.args]
@@ -11806,10 +11803,10 @@ _find_formatting_types = re.compile(
br")").findall
# These format conversion types can never trigger a Unicode string conversion in Py2.
-_safe_bytes_formats = set([
+_safe_bytes_formats = frozenset({
# 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):
@@ -13857,6 +13854,9 @@ class AnnotationNode(ExprNode):
warning(annotation.pos,
"Strings should no longer be used for type declarations. Use 'cython.int' etc. directly.",
level=1)
+ elif arg_type is not None and arg_type.is_complex:
+ # creating utility code needs to be special-cased for complex types
+ arg_type.create_declaration_utility_code(env)
if arg_type is not None:
if explicit_pytype and not explicit_ctype and not arg_type.is_pyobject:
warning(annotation.pos,
diff --git a/Cython/Compiler/FlowControl.py b/Cython/Compiler/FlowControl.py
index 97fd8314f..5b51be0db 100644
--- a/Cython/Compiler/FlowControl.py
+++ b/Cython/Compiler/FlowControl.py
@@ -52,7 +52,7 @@ class ControlBlock(object):
stats = [Assignment(a), NameReference(a), NameReference(c),
Assignment(b)]
gen = {Entry(a): Assignment(a), Entry(b): Assignment(b)}
- bounded = set([Entry(a), Entry(c)])
+ bounded = {Entry(a), Entry(c)}
"""
@@ -203,7 +203,7 @@ class ControlFlow(object):
def normalize(self):
"""Delete unreachable and orphan blocks."""
- queue = set([self.entry_point])
+ queue = {self.entry_point}
visited = set()
while queue:
root = queue.pop()
diff --git a/Cython/Compiler/FusedNode.py b/Cython/Compiler/FusedNode.py
index 3252929e4..918a05990 100644
--- a/Cython/Compiler/FusedNode.py
+++ b/Cython/Compiler/FusedNode.py
@@ -414,7 +414,7 @@ class FusedCFuncDefNode(StatListNode):
if itemsize == -1 or itemsize == {{sizeof_dtype}}:
memslice = {{coerce_from_py_func}}(arg, 0)
if memslice.memview:
- __PYX_XDEC_MEMVIEW(&memslice, 1)
+ __PYX_XCLEAR_MEMVIEW(&memslice, 1)
# print 'found a match for the buffer through format parsing'
%s
break
@@ -493,7 +493,7 @@ class FusedCFuncDefNode(StatListNode):
ctypedef struct {{memviewslice_cname}}:
void *memview
- void __PYX_XDEC_MEMVIEW({{memviewslice_cname}} *, int have_gil)
+ void __PYX_XCLEAR_MEMVIEW({{memviewslice_cname}} *, int have_gil)
bint __pyx_memoryview_check(object)
""")
diff --git a/Cython/Compiler/MemoryView.py b/Cython/Compiler/MemoryView.py
index a82b5534e..7f4c043c9 100644
--- a/Cython/Compiler/MemoryView.py
+++ b/Cython/Compiler/MemoryView.py
@@ -100,6 +100,12 @@ def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code,
def put_assign_to_memviewslice(lhs_cname, rhs, rhs_cname, memviewslicetype, code,
have_gil=False, first_assignment=False):
+ if lhs_cname == rhs_cname:
+ # self assignment is tricky because memoryview xdecref clears the memoryview
+ # thus invalidating both sides of the assignment. Therefore make it actually do nothing
+ code.putln("/* memoryview self assignment no-op */")
+ return
+
if not first_assignment:
code.put_xdecref(lhs_cname, memviewslicetype,
have_gil=have_gil)
@@ -851,7 +857,7 @@ view_utility_code = load_memview_cy_utility(
copy_contents_new_utility,
ModuleNode.capsule_utility_code],
)
-view_utility_whitelist = ('array', 'memoryview', 'array_cwrapper',
+view_utility_allowlist = ('array', 'memoryview', 'array_cwrapper',
'generic', 'strided', 'indirect', 'contiguous',
'indirect_contiguous')
diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py
index a9e68d735..41c959796 100644
--- a/Cython/Compiler/ModuleNode.py
+++ b/Cython/Compiler/ModuleNode.py
@@ -705,7 +705,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("END: Cython Metadata */")
code.putln("")
+ code.putln("#ifndef PY_SSIZE_T_CLEAN")
code.putln("#define PY_SSIZE_T_CLEAN")
+ code.putln("#endif /* PY_SSIZE_T_CLEAN */")
self._put_setup_code(code, "InitLimitedAPI")
for inc in sorted(env.c_includes.values(), key=IncludeCode.sortkey):
@@ -1834,7 +1836,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("Py_CLEAR(p->%s.obj);" % entry.cname)
if cclass_entry.cname == '__pyx_memoryviewslice':
- code.putln("__PYX_XDEC_MEMVIEW(&p->from_slice, 1);")
+ code.putln("__PYX_XCLEAR_MEMVIEW(&p->from_slice, 1);")
code.putln("return 0;")
code.putln("}")
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index 37263ff2b..2cddd065a 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -115,9 +115,11 @@ class VerboseCodeWriter(type):
class CheckAnalysers(type):
"""Metaclass to check that type analysis functions return a node.
"""
- methods = set(['analyse_types',
- 'analyse_expressions',
- 'analyse_target_types'])
+ methods = frozenset({
+ 'analyse_types',
+ 'analyse_expressions',
+ 'analyse_target_types',
+ })
def __new__(cls, name, bases, attrs):
from types import FunctionType
@@ -1044,7 +1046,10 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
scope = env
for item in self.module_path:
entry = scope.lookup(item)
- if entry is not None and entry.is_cpp_class:
+ if entry is not None and (
+ entry.is_cpp_class or
+ entry.is_type and entry.type.is_cpp_class
+ ):
scope = entry.type.scope
else:
scope = None
@@ -1078,6 +1083,8 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
type = PyrexTypes.TemplatePlaceholderType(self.name)
else:
error(self.pos, "'%s' is not a type identifier" % self.name)
+ if type and type.is_fused and env.fused_to_specific:
+ type = type.specialize(env.fused_to_specific)
if self.complex:
if not type.is_numeric or type.is_complex:
error(self.pos, "can only complexify c numeric types")
@@ -1419,6 +1426,9 @@ class CVarDefNode(StatNode):
self.entry.type.create_to_py_utility_code(env)
self.entry.create_wrapper = True
else:
+ if self.overridable:
+ warning(self.pos, "cpdef variables will not be supported in Cython 3; "
+ "currently they are no different from cdef variables", 2)
if self.directive_locals:
error(self.pos, "Decorators can only be followed by functions")
self.entry = dest_scope.declare_var(
@@ -1781,6 +1791,9 @@ class FuncDefNode(StatNode, BlockNode):
error(type_node.pos, "Previous declaration here")
else:
arg.type = other_type
+ if arg.type.is_complex:
+ # utility code for complex types is special-cased and also important to ensure that it's run
+ arg.type.create_declaration_utility_code(env)
return arg
def need_gil_acquisition(self, lenv):
@@ -4755,6 +4768,7 @@ class PyClassDefNode(ClassDefNode):
# entry Symtab.Entry
# scope PyClassScope
# decorators [DecoratorNode] list of decorators or None
+ # bases ExprNode Expression that evaluates to a tuple of base classes
#
# The following subnodes are constructed internally:
#
@@ -4762,15 +4776,18 @@ class PyClassDefNode(ClassDefNode):
# dict DictNode Class dictionary or Py3 namespace
# classobj ClassNode Class object
# target NameNode Variable to assign class object to
+ # orig_bases None or ExprNode "bases" before transformation by PEP560 __mro_entries__,
+ # used to create the __orig_bases__ attribute
child_attrs = ["doc_node", "body", "dict", "metaclass", "mkw", "bases", "class_result",
- "target", "class_cell", "decorators"]
+ "target", "class_cell", "decorators", "orig_bases"]
decorators = None
class_result = None
is_py3_style_class = False # Python3 style class (kwargs)
metaclass = None
mkw = None
doc_node = None
+ orig_bases = None
def __init__(self, pos, name, bases, doc, body, decorators=None,
keyword_args=None, force_py3_semantics=False):
@@ -4896,7 +4913,22 @@ class PyClassDefNode(ClassDefNode):
self.body.analyse_declarations(cenv)
self.class_result.analyse_annotations(cenv)
+ update_bases_functype = PyrexTypes.CFuncType(
+ PyrexTypes.py_object_type, [
+ PyrexTypes.CFuncTypeArg("bases", PyrexTypes.py_object_type, None)
+ ])
+
def analyse_expressions(self, env):
+ if self.bases and not (self.bases.is_sequence_constructor and len(self.bases.args) == 0):
+ from .ExprNodes import PythonCapiCallNode, CloneNode
+ # handle the Python 3.7 __mro_entries__ transformation
+ orig_bases = self.bases.analyse_expressions(env)
+ self.bases = PythonCapiCallNode(orig_bases.pos,
+ function_name="__Pyx_PEP560_update_bases",
+ func_type=self.update_bases_functype,
+ utility_code=UtilityCode.load_cached('Py3UpdateBases', 'ObjectHandling.c'),
+ args=[CloneNode(orig_bases)])
+ self.orig_bases = orig_bases
if self.bases:
self.bases = self.bases.analyse_expressions(env)
if self.mkw:
@@ -4919,6 +4951,8 @@ class PyClassDefNode(ClassDefNode):
code.mark_pos(self.pos)
code.pyclass_stack.append(self)
cenv = self.scope
+ if self.orig_bases:
+ self.orig_bases.generate_evaluation_code(code)
if self.bases:
self.bases.generate_evaluation_code(code)
if self.mkw:
@@ -4926,6 +4960,17 @@ class PyClassDefNode(ClassDefNode):
if self.metaclass:
self.metaclass.generate_evaluation_code(code)
self.dict.generate_evaluation_code(code)
+ if self.orig_bases:
+ # update __orig_bases__ if needed
+ code.putln("if (%s != %s) {" % (self.bases.result(), self.orig_bases.result()))
+ code.putln(
+ code.error_goto_if_neg('PyDict_SetItemString(%s, "__orig_bases__", %s)' % (
+ self.dict.result(), self.orig_bases.result()),
+ self.pos
+ ))
+ code.putln("}")
+ self.orig_bases.generate_disposal_code(code)
+ self.orig_bases.free_temps(code)
cenv.namespace_cname = cenv.class_obj_cname = self.dict.result()
class_cell = self.class_cell
diff --git a/Cython/Compiler/Optimize.py b/Cython/Compiler/Optimize.py
index b511e757a..25d654330 100644
--- a/Cython/Compiler/Optimize.py
+++ b/Cython/Compiler/Optimize.py
@@ -1236,7 +1236,7 @@ class SwitchTransform(Visitor.EnvTransform):
# integers on iteration, whereas Py2 returns 1-char byte
# strings
characters = string_literal.value
- characters = list(set([ characters[i:i+1] for i in range(len(characters)) ]))
+ characters = list({ characters[i:i+1] for i in range(len(characters)) })
characters.sort()
return [ ExprNodes.CharNode(string_literal.pos, value=charval,
constant_result=charval)
@@ -1248,7 +1248,8 @@ class SwitchTransform(Visitor.EnvTransform):
return self.NO_MATCH
elif common_var is not None and not is_common_value(var, common_var):
return self.NO_MATCH
- elif not (var.type.is_int or var.type.is_enum) or sum([not (cond.type.is_int or cond.type.is_enum) for cond in conditions]):
+ elif not (var.type.is_int or var.type.is_enum) or any(
+ [not (cond.type.is_int or cond.type.is_enum) for cond in conditions]):
return self.NO_MATCH
return not_in, var, conditions
@@ -2189,12 +2190,13 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
func_arg = arg.args[0]
if func_arg.type is Builtin.float_type:
return func_arg.as_none_safe_node("float() argument must be a string or a number, not 'NoneType'")
- elif func_arg.type.is_pyobject:
+ elif func_arg.type.is_pyobject and arg.function.cname == "__Pyx_PyObject_AsDouble":
return ExprNodes.PythonCapiCallNode(
node.pos, '__Pyx_PyNumber_Float', self.PyNumber_Float_func_type,
args=[func_arg],
py_name='float',
is_temp=node.is_temp,
+ utility_code = UtilityCode.load_cached("pynumber_float", "TypeConversion.c"),
result_is_used=node.result_is_used,
).coerce_to(node.type, self.current_env())
return node
@@ -2619,6 +2621,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
elif len(pos_args) != 1:
self._error_wrong_arg_count('float', node, pos_args, '0 or 1')
return node
+
func_arg = pos_args[0]
if isinstance(func_arg, ExprNodes.CoerceToPyTypeNode):
func_arg = func_arg.arg
@@ -2627,12 +2630,37 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
elif node.type.assignable_from(func_arg.type) or func_arg.type.is_numeric:
return ExprNodes.TypecastNode(
node.pos, operand=func_arg, type=node.type)
+
+ arg = None
+ if func_arg.type is Builtin.bytes_type:
+ cfunc_name = "__Pyx_PyBytes_AsDouble"
+ utility_code_name = 'pybytes_as_double'
+ elif func_arg.type is Builtin.bytearray_type:
+ cfunc_name = "__Pyx_PyByteArray_AsDouble"
+ utility_code_name = 'pybytes_as_double'
+ elif func_arg.type is Builtin.unicode_type:
+ cfunc_name = "__Pyx_PyUnicode_AsDouble"
+ utility_code_name = 'pyunicode_as_double'
+ elif func_arg.type is Builtin.str_type:
+ cfunc_name = "__Pyx_PyString_AsDouble"
+ utility_code_name = 'pystring_as_double'
+ elif func_arg.type is Builtin.long_type:
+ cfunc_name = "PyLong_AsDouble"
+ else:
+ arg = func_arg # no need for an additional None check
+ cfunc_name = "__Pyx_PyObject_AsDouble"
+ utility_code_name = 'pyobject_as_double'
+
+ if arg is None:
+ arg = func_arg.as_none_safe_node(
+ "float() argument must be a string or a number, not 'NoneType'")
+
return ExprNodes.PythonCapiCallNode(
- node.pos, "__Pyx_PyObject_AsDouble",
+ node.pos, cfunc_name,
self.PyObject_AsDouble_func_type,
- args = pos_args,
+ args = [arg],
is_temp = node.is_temp,
- utility_code = load_c_utility('pyobject_as_double'),
+ utility_code = load_c_utility(utility_code_name) if utility_code_name else None,
py_name = "float")
PyNumber_Int_func_type = PyrexTypes.CFuncType(
@@ -2723,7 +2751,7 @@ class OptimizeBuiltinCalls(Visitor.NodeRefCleanupMixin,
Builtin.dict_type: "PyDict_Size",
}.get
- _ext_types_with_pysize = set(["cpython.array.array"])
+ _ext_types_with_pysize = {"cpython.array.array"}
def _handle_simple_function_len(self, node, function, pos_args):
"""Replace len(char*) by the equivalent call to strlen(),
@@ -4398,6 +4426,7 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
string_node.unicode_value = encoded_string(
string_node.unicode_value * multiplier,
string_node.unicode_value.encoding)
+ build_string = encoded_string if string_node.value.is_unicode else bytes_literal
elif isinstance(string_node, ExprNodes.UnicodeNode):
if string_node.bytes_value is not None:
string_node.bytes_value = bytes_literal(
@@ -4405,9 +4434,14 @@ class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations):
string_node.bytes_value.encoding)
else:
assert False, "unknown string node type: %s" % type(string_node)
- string_node.constant_result = string_node.value = build_string(
+ string_node.value = build_string(
string_node.value * multiplier,
string_node.value.encoding)
+ # follow constant-folding and use unicode_value in preference
+ if isinstance(string_node, ExprNodes.StringNode) and string_node.unicode_value is not None:
+ string_node.constant_result = string_node.unicode_value
+ else:
+ string_node.constant_result = string_node.value
return string_node
def _calculate_constant_seq(self, node, sequence_node, factor):
diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py
index eb9001a68..330208840 100644
--- a/Cython/Compiler/ParseTreeTransforms.py
+++ b/Cython/Compiler/ParseTreeTransforms.py
@@ -685,17 +685,19 @@ class InterpretCompilerDirectives(CythonTransform):
'operator.comma' : ExprNodes.c_binop_constructor(','),
}
- special_methods = set(['declare', 'union', 'struct', 'typedef',
- 'sizeof', 'cast', 'pointer', 'compiled',
- 'NULL', 'fused_type', 'parallel'])
+ special_methods = {
+ 'declare', 'union', 'struct', 'typedef',
+ 'sizeof', 'cast', 'pointer', 'compiled',
+ 'NULL', 'fused_type', 'parallel',
+ }
special_methods.update(unop_method_nodes)
- valid_parallel_directives = set([
+ valid_parallel_directives = {
"parallel",
"prange",
"threadid",
#"threadsavailable",
- ])
+ }
def __init__(self, context, compilation_directive_defaults):
super(InterpretCompilerDirectives, self).__init__(context)
@@ -2161,7 +2163,7 @@ if VALUE is not None:
entry = self.current_env().lookup(node.name)
if (entry is None or entry.visibility != 'extern'
and not entry.scope.is_c_class_scope):
- warning(node.pos, "cdef variable '%s' declared after it is used" % node.name, 2)
+ error(node.pos, "cdef variable '%s' declared after it is used" % node.name)
self.visitchildren(node)
return node
diff --git a/Cython/Compiler/Parsing.py b/Cython/Compiler/Parsing.py
index 55e98a34b..45641a7d3 100644
--- a/Cython/Compiler/Parsing.py
+++ b/Cython/Compiler/Parsing.py
@@ -257,10 +257,10 @@ def p_cmp_op(s):
op = '!='
return op
-comparison_ops = cython.declare(set, set([
+comparison_ops = cython.declare(frozenset, frozenset((
'<', '>', '==', '>=', '<=', '<>', '!=',
'in', 'is', 'not'
-]))
+)))
#expr: xor_expr ('|' xor_expr)*
@@ -829,7 +829,7 @@ def p_cat_string_literal(s):
continue
elif next_kind != kind:
# concatenating f strings and normal strings is allowed and leads to an f string
- if set([kind, next_kind]) in (set(['f', 'u']), set(['f', ''])):
+ if {kind, next_kind} in ({'f', 'u'}, {'f', ''}):
kind = 'f'
else:
error(pos, "Cannot mix string literals of different types, expected %s'', got %s''" % (
@@ -1486,8 +1486,8 @@ def p_genexp(s, expr):
expr.pos, expr = ExprNodes.YieldExprNode(expr.pos, arg=expr)))
return ExprNodes.GeneratorExpressionNode(expr.pos, loop=loop)
-expr_terminators = cython.declare(set, set([
- ')', ']', '}', ':', '=', 'NEWLINE']))
+expr_terminators = cython.declare(frozenset, frozenset((
+ ')', ']', '}', ':', '=', 'NEWLINE')))
#-------------------------------------------------------
@@ -1792,7 +1792,8 @@ def p_from_import_statement(s, first_statement = 0):
items = items)
-imported_name_kinds = cython.declare(set, set(['class', 'struct', 'union']))
+imported_name_kinds = cython.declare(frozenset, frozenset((
+ 'class', 'struct', 'union')))
def p_imported_name(s, is_cimport):
pos = s.position()
@@ -1839,7 +1840,8 @@ def p_assert_statement(s):
return Nodes.AssertStatNode(pos, condition=cond, value=value)
-statement_terminators = cython.declare(set, set([';', 'NEWLINE', 'EOF']))
+statement_terminators = cython.declare(frozenset, frozenset((
+ ';', 'NEWLINE', 'EOF')))
def p_if_statement(s):
# s.sy == 'if'
@@ -1949,7 +1951,8 @@ def p_for_from_step(s):
else:
return None
-inequality_relations = cython.declare(set, set(['<', '<=', '>', '>=']))
+inequality_relations = cython.declare(frozenset, frozenset((
+ '<', '<=', '>', '>=')))
def p_target(s, terminator):
pos = s.position()
@@ -2463,8 +2466,8 @@ def p_calling_convention(s):
return ""
-calling_convention_words = cython.declare(
- set, set(["__stdcall", "__cdecl", "__fastcall"]))
+calling_convention_words = cython.declare(frozenset, frozenset((
+ "__stdcall", "__cdecl", "__fastcall")))
def p_c_complex_base_type(s, templates = None):
@@ -2705,7 +2708,7 @@ def looking_at_expr(s):
s.put_back(*saved)
elif s.sy == '[':
s.next()
- is_type = s.sy == ']'
+ is_type = s.sy == ']' or not looking_at_expr(s) # could be a nested template type
s.put_back(*saved)
dotted_path.reverse()
@@ -2743,8 +2746,8 @@ def looking_at_call(s):
s.start_line, s.start_col = position
return result
-basic_c_type_names = cython.declare(
- set, set(["void", "char", "int", "float", "double", "bint"]))
+basic_c_type_names = cython.declare(frozenset, frozenset((
+ "void", "char", "int", "float", "double", "bint")))
special_basic_c_types = cython.declare(dict, {
# name : (signed, longness)
@@ -2758,8 +2761,8 @@ special_basic_c_types = cython.declare(dict, {
"Py_tss_t" : (1, 0),
})
-sign_and_longness_words = cython.declare(
- set, set(["short", "long", "signed", "unsigned"]))
+sign_and_longness_words = cython.declare(frozenset, frozenset((
+ "short", "long", "signed", "unsigned")))
base_type_start_words = cython.declare(
set,
@@ -2767,8 +2770,8 @@ base_type_start_words = cython.declare(
| sign_and_longness_words
| set(special_basic_c_types))
-struct_enum_union = cython.declare(
- set, set(["struct", "union", "enum", "packed"]))
+struct_enum_union = cython.declare(frozenset, frozenset((
+ "struct", "union", "enum", "packed")))
def p_sign_and_longness(s):
signed = 1
@@ -2853,13 +2856,13 @@ def p_c_func_declarator(s, pos, ctx, base, cmethod_flag):
exception_value = exc_val, exception_check = exc_check,
nogil = nogil or ctx.nogil or with_gil, with_gil = with_gil)
-supported_overloaded_operators = cython.declare(set, set([
+supported_overloaded_operators = cython.declare(frozenset, frozenset((
'+', '-', '*', '/', '%',
'++', '--', '~', '|', '&', '^', '<<', '>>', ',',
'==', '!=', '>=', '>', '<=', '<',
'[]', '()', '!', '=',
'bool',
-]))
+)))
def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
assignable, nonempty):
@@ -2981,7 +2984,8 @@ def p_exception_value_clause(s):
exc_val = p_test(s)
return exc_val, exc_check
-c_arg_list_terminators = cython.declare(set, set(['*', '**', '.', ')', ':', '/']))
+c_arg_list_terminators = cython.declare(frozenset, frozenset((
+ '*', '**', '.', ')', ':', '/')))
def p_c_arg_list(s, ctx = Ctx(), in_pyfunc = 0, cmethod_flag = 0,
nonempty_declarators = 0, kw_only = 0, annotated = 1):
diff --git a/Cython/Compiler/Pipeline.py b/Cython/Compiler/Pipeline.py
index b7f512e7e..4e8e98c71 100644
--- a/Cython/Compiler/Pipeline.py
+++ b/Cython/Compiler/Pipeline.py
@@ -285,11 +285,25 @@ def create_pyx_as_pxd_pipeline(context, result):
FlattenInListTransform,
WithTransform
])
+ from .Visitor import VisitorTransform
+ class SetInPxdTransform(VisitorTransform):
+ # A number of nodes have an "in_pxd" attribute which affects AnalyseDeclarationsTransform
+ # (for example controlling pickling generation). Set it, to make sure we don't mix them up with
+ # the importing main module.
+ # FIXME: This should be done closer to the parsing step.
+ def visit_StatNode(self, node):
+ if hasattr(node, "in_pxd"):
+ node.in_pxd = True
+ self.visitchildren(node)
+ return node
+
+ visit_Node = VisitorTransform.recurse_to_children
+
for stage in pyx_pipeline:
pipeline.append(stage)
if isinstance(stage, AnalyseDeclarationsTransform):
- # This is the last stage we need.
- break
+ pipeline.insert(-1, SetInPxdTransform())
+ break # This is the last stage we need.
def fake_pxd(root):
for entry in root.scope.entries.values():
if not entry.in_cinclude:
diff --git a/Cython/Compiler/PyrexTypes.py b/Cython/Compiler/PyrexTypes.py
index 8824f5167..7e7154c00 100644
--- a/Cython/Compiler/PyrexTypes.py
+++ b/Cython/Compiler/PyrexTypes.py
@@ -1099,7 +1099,7 @@ class MemoryViewSliceType(PyrexType):
# decref however did look to always apply for memoryview slices
# with "have_gil" set to True by default
def generate_xdecref(self, code, cname, nanny, have_gil):
- code.putln("__PYX_XDEC_MEMVIEW(&%s, %d);" % (cname, int(have_gil)))
+ code.putln("__PYX_XCLEAR_MEMVIEW(&%s, %d);" % (cname, int(have_gil)))
def generate_decref(self, code, cname, nanny, have_gil):
# Fall back to xdecref since we don't care to have a separate decref version for this.
@@ -1339,14 +1339,14 @@ class PyObjectType(PyrexType):
return cname
-builtin_types_that_cannot_create_refcycles = set([
+builtin_types_that_cannot_create_refcycles = frozenset({
'object', 'bool', 'int', 'long', 'float', 'complex',
- 'bytearray', 'bytes', 'unicode', 'str', 'basestring'
-])
+ 'bytearray', 'bytes', 'unicode', 'str', 'basestring',
+})
-builtin_types_with_trashcan = set([
+builtin_types_with_trashcan = frozenset({
'dict', 'list', 'set', 'frozenset', 'tuple', 'type',
-])
+})
class BuiltinObjectType(PyObjectType):
@@ -3252,7 +3252,16 @@ class CFuncType(CType):
if not self.can_coerce_to_pyobject(env):
return False
from .UtilityCode import CythonUtilityCode
- to_py_function = "__Pyx_CFunc_%s_to_py" % type_identifier(self, pyrex=True)
+
+ # include argument names into the c function name to ensure cname is unique
+ # between functions with identical types but different argument names
+ from .Symtab import punycodify_name
+ def arg_name_part(arg):
+ return "%s%s" % (len(arg.name), punycodify_name(arg.name)) if arg.name else "0"
+ arg_names = [ arg_name_part(arg) for arg in self.args ]
+ arg_names = "_".join(arg_names)
+ safe_typename = type_identifier(self, pyrex=True)
+ to_py_function = "__Pyx_CFunc_%s_to_py_%s" % (safe_typename, arg_names)
for arg in self.args:
if not arg.type.is_pyobject and not arg.type.create_from_py_utility_code(env):
diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py
index 090468d07..9dfeb87bd 100644
--- a/Cython/Compiler/Symtab.py
+++ b/Cython/Compiler/Symtab.py
@@ -387,11 +387,11 @@ class Scope(object):
def __deepcopy__(self, memo):
return self
- def merge_in(self, other, merge_unused=True, whitelist=None):
+ def merge_in(self, other, merge_unused=True, allowlist=None):
# Use with care...
entries = []
for name, entry in other.entries.items():
- if not whitelist or name in whitelist:
+ if not allowlist or name in allowlist:
if entry.used or merge_unused:
entries.append((name, entry))
diff --git a/Cython/Compiler/TreePath.py b/Cython/Compiler/TreePath.py
index 272570a03..858590555 100644
--- a/Cython/Compiler/TreePath.py
+++ b/Cython/Compiler/TreePath.py
@@ -10,6 +10,12 @@ from __future__ import absolute_import
import re
import operator
+import sys
+
+if sys.version_info[0] >= 3:
+ _unicode = str
+else:
+ _unicode = unicode
path_tokenizer = re.compile(
r"("
@@ -167,6 +173,11 @@ def handle_attribute(next, token):
continue
if attr_value == value:
yield attr_value
+ elif (isinstance(attr_value, bytes) and isinstance(value, _unicode) and
+ attr_value == value.encode()):
+ # allow a bytes-to-string comparison too
+ yield attr_value
+
return select
diff --git a/Cython/Compiler/UtilityCode.py b/Cython/Compiler/UtilityCode.py
index 756f0f4d7..c58c8623c 100644
--- a/Cython/Compiler/UtilityCode.py
+++ b/Cython/Compiler/UtilityCode.py
@@ -199,7 +199,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
return util.proto, util.impl # keep line numbers => no lstrip()
def declare_in_scope(self, dest_scope, used=False, cython_scope=None,
- whitelist=None):
+ allowlist=None):
"""
Declare all entries from the utility code in dest_scope. Code will only
be included for used entries. If module_name is given, declare the
@@ -218,7 +218,7 @@ class CythonUtilityCode(Code.UtilityCodeBase):
entry.used = used
original_scope = tree.scope
- dest_scope.merge_in(original_scope, merge_unused=True, whitelist=whitelist)
+ dest_scope.merge_in(original_scope, merge_unused=True, allowlist=allowlist)
tree.scope = dest_scope
for dep in self.requires:
diff --git a/Cython/Compiler/Visitor.py b/Cython/Compiler/Visitor.py
index 368c38058..0cf5ee1eb 100644
--- a/Cython/Compiler/Visitor.py
+++ b/Cython/Compiler/Visitor.py
@@ -834,8 +834,8 @@ class PrintTree(TreeVisitor):
result += "(name=\"%s\")" % node.name
elif isinstance(node, ExprNodes.AttributeNode):
result += "(type=%s, attribute=\"%s\")" % (repr(node.type), node.attribute)
- elif isinstance(node, ExprNodes.ConstNode):
- result += "(type=%s, value=\"%s\")" % (repr(node.type), node.value)
+ elif isinstance(node, (ExprNodes.ConstNode, ExprNodes.PyConstNode)):
+ result += "(type=%s, value=%r)" % (repr(node.type), node.value)
elif isinstance(node, ExprNodes.ExprNode):
t = node.type
result += "(type=%s)" % repr(t)
diff --git a/Cython/Debugger/Tests/test_libcython_in_gdb.py b/Cython/Debugger/Tests/test_libcython_in_gdb.py
index be662d12b..bb06c2905 100644
--- a/Cython/Debugger/Tests/test_libcython_in_gdb.py
+++ b/Cython/Debugger/Tests/test_libcython_in_gdb.py
@@ -134,7 +134,7 @@ class TestDebugInformationClasses(DebugTestCase):
self.assertEqual(self.spam_func.arguments, ['a'])
self.assertEqual(self.spam_func.step_into_functions,
- set(['puts', 'some_c_function']))
+ {'puts', 'some_c_function'})
expected_lineno = test_libcython.source_to_lineno['def spam(a=0):']
self.assertEqual(self.spam_func.lineno, expected_lineno)
diff --git a/Cython/Includes/cpython/array.pxd b/Cython/Includes/cpython/array.pxd
index 8a2673cde..8431f7b66 100644
--- a/Cython/Includes/cpython/array.pxd
+++ b/Cython/Includes/cpython/array.pxd
@@ -46,6 +46,18 @@
: 2012-05-02 andreasvc
: (see revision control)
"""
+
+cdef extern from *:
+ """
+ #if CYTHON_COMPILING_IN_PYPY
+ #ifdef _MSC_VER
+ #pragma message ("This module uses CPython specific internals of 'array.array', which are not available in PyPy.")
+ #else
+ #warning This module uses CPython specific internals of 'array.array', which are not available in PyPy.
+ #endif
+ #endif
+ """
+
from libc.string cimport memset, memcpy
from cpython.object cimport Py_SIZE
diff --git a/Cython/Includes/cpython/cellobject.pxd b/Cython/Includes/cpython/cellobject.pxd
new file mode 100644
index 000000000..5e3dd3d63
--- /dev/null
+++ b/Cython/Includes/cpython/cellobject.pxd
@@ -0,0 +1,35 @@
+from .object cimport PyObject
+
+cdef extern from "Python.h":
+
+ ############################################################################
+ # Cell Objects
+ ############################################################################
+
+ bint PyCell_Check(object ob)
+ # Return true if ob is a cell object; ob must not be NULL.
+
+ object PyCell_New(PyObject* ob)
+ # Return value: New reference.
+ # Create and return a new cell object containing the value ob. The
+ # parameter may be NULL.
+
+ object PyCell_Get(object cell)
+ # Return value: New reference.
+ # Return the contents of the cell object cell.
+
+ object PyCell_GET(object cell)
+ # Return value: Borrowed reference.
+ # Return the contents of the cell object cell, but without checking that
+ # cell is non-NULL and is a cell object.
+
+ int PyCell_Set(object cell, PyObject* value) except? -1
+ # Set the contents of the cell object cell to value. This releases the
+ # reference to any current content of the cell. value may be NULL. cell
+ # must be non-NULL; if it is not a cell object, -1 will be returned. On
+ # success, 0 will be returned.
+
+ void PyCell_SET(object cell, PyObject* value)
+ # Sets the value of the cell object cell to value. No reference counts are
+ # adjusted, and no checks are made for safety; cell must be non-NULL and
+ # must be a cell object.
diff --git a/Cython/Includes/cpython/codecs.pxd b/Cython/Includes/cpython/codecs.pxd
new file mode 100644
index 000000000..f2ca7d244
--- /dev/null
+++ b/Cython/Includes/cpython/codecs.pxd
@@ -0,0 +1,121 @@
+cdef extern from "Python.h":
+
+ ###########################################################################
+ # Codec registry and support functions
+ ###########################################################################
+
+ int PyCodec_Register(object search_function)
+ # Register a new codec search function.
+
+ # As side effect, this tries to load the encodings package, if not yet
+ # done, to make sure that it is always first in the list of search
+ # functions.
+
+ int PyCodec_KnownEncoding(const char *encoding)
+ # Return 1 or 0 depending on whether there is a registered codec for the
+ # given encoding. This function always succeeds.
+
+ object PyCodec_Encode(object o, const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Generic codec based encoding API.
+
+ # o is passed through the encoder function found for the given encoding
+ # using the error handling method defined by errors. errors may be NULL
+ # to use the default method defined for the codec. Raises a LookupError
+ # if no encoder can be found.
+
+ object PyCodec_Decode(object o, const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Generic codec based decoding API.
+
+ # o is passed through the decoder function found for the given encoding
+ # using the error handling method defined by errors. errors may be NULL
+ # to use the default method defined for the codec. Raises a LookupError
+ # if no encoder can be found.
+
+
+ # Codec lookup API
+
+ # In the following functions, the encoding string is looked up converted
+ # to all lower-case characters, which makes encodings looked up through
+ # this mechanism effectively case-insensitive. If no codec is found, a
+ # KeyError is set and NULL returned.
+
+ object PyCodec_Encoder(const char *encoding)
+ # Return value: New reference.
+ # Get an encoder function for the given encoding.
+
+ object PyCodec_Decoder(const char *encoding)
+ # Return value: New reference.
+ # Get a decoder function for the given encoding.
+
+ object PyCodec_IncrementalEncoder(const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Get an IncrementalEncoder object for the given encoding.
+
+ object PyCodec_IncrementalDecoder(const char *encoding, const char *errors)
+ # Return value: New reference.
+ # Get an IncrementalDecoder object for the given encoding.
+
+ object PyCodec_StreamReader(const char *encoding, object stream, const char *errors)
+ # Return value: New reference.
+ # Get a StreamReader factory function for the given encoding.
+
+ object PyCodec_StreamWriter(const char *encoding, object stream, const char *errors)
+ # Return value: New reference.
+ # Get a StreamWriter factory function for the given encoding.
+
+
+ # Registry API for Unicode encoding error handlers
+
+ int PyCodec_RegisterError(const char *name, object error) except? -1
+ # Register the error handling callback function error under the given
+ # name. This callback function will be called by a codec when it
+ # encounters unencodable characters/undecodable bytes and name is
+ # specified as the error parameter in the call to the encode/decode
+ # function.
+
+ # The callback gets a single argument, an instance of
+ # UnicodeEncodeError, UnicodeDecodeError or UnicodeTranslateError that
+ # holds information about the problematic sequence of characters or bytes
+ # and their offset in the original string (see Unicode Exception Objects
+ # for functions to extract this information). The callback must either
+ # raise the given exception, or return a two-item tuple containing the
+ # replacement for the problematic sequence, and an integer giving the
+ # offset in the original string at which encoding/decoding should be
+ # resumed.
+
+ # Return 0 on success, -1 on error.
+
+ object PyCodec_LookupError(const char *name)
+ # Return value: New reference.
+ # Lookup the error handling callback function registered under name. As a
+ # special case NULL can be passed, in which case the error handling
+ # callback for "strict" will be returned.
+
+ object PyCodec_StrictErrors(object exc)
+ # Return value: Always NULL.
+ # Raise exc as an exception.
+
+ object PyCodec_IgnoreErrors(object exc)
+ # Return value: New reference.
+ # Ignore the unicode error, skipping the faulty input.
+
+ object PyCodec_ReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with "?" or "U+FFFD".
+
+ object PyCodec_XMLCharRefReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with XML character references.
+
+ object PyCodec_BackslashReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with backslash escapes ("\x", "\u"
+ # and "\U").
+
+ object PyCodec_NameReplaceErrors(object exc)
+ # Return value: New reference.
+ # Replace the unicode encode error with "\N{...}" escapes.
+
+ # New in version 3.5.
diff --git a/Cython/Includes/cpython/conversion.pxd b/Cython/Includes/cpython/conversion.pxd
new file mode 100644
index 000000000..18e2c3d1a
--- /dev/null
+++ b/Cython/Includes/cpython/conversion.pxd
@@ -0,0 +1,36 @@
+# From https://docs.python.org/3/c-api/conversion.html
+
+from .object cimport PyObject
+
+cdef extern from "Python.h":
+ ctypedef struct va_list
+
+ int PyOS_snprintf(char *str, size_t size, const char *format, ...)
+ # Output not more than size bytes to str according to the format
+ # string format and the extra arguments. See the Unix man page snprintf(2).
+
+ int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
+ # Output not more than size bytes to str according to the format
+ # string format and the variable argument list va. Unix man page vsnprintf(2).
+
+ double PyOS_string_to_double(const char *s, char **endptr, PyObject *overflow_exception) except? -1.0
+ # Convert a string s to a double, raising a Python exception on failure. The set of
+ # accepted strings corresponds to the set of strings accepted by Python’s float()
+ # constructor, except that s must not have leading or trailing whitespace.
+ # The conversion is independent of the current locale.
+
+ enum:
+ Py_DTSF_SIGN
+ Py_DTSF_ADD_DOT_0
+ Py_DTSF_ALT
+
+ char* PyOS_double_to_string(double val, char format_code, int precision, int flags, int *ptype) except NULL
+ # Convert a double val to a string using supplied format_code, precision, and flags.
+
+ int PyOS_stricmp(const char *s1, const char *s2)
+ # Case insensitive comparison of strings. The function works almost identically
+ # to strcmp() except that it ignores the case.
+
+ int PyOS_strnicmp(const char *s1, const char *s2, Py_ssize_t size)
+ # Case insensitive comparison of strings. The function works almost identically
+ # to strncmp() except that it ignores the case.
diff --git a/Cython/Includes/cpython/datetime.pxd b/Cython/Includes/cpython/datetime.pxd
index 26782be55..83fa20ab7 100644
--- a/Cython/Includes/cpython/datetime.pxd
+++ b/Cython/Includes/cpython/datetime.pxd
@@ -24,7 +24,33 @@ cdef extern from "datetime.h":
pass
ctypedef extern class datetime.datetime[object PyDateTime_DateTime]:
- pass
+ @property
+ cdef inline int year(self):
+ return PyDateTime_GET_YEAR(self)
+
+ @property
+ cdef inline int month(self):
+ return PyDateTime_GET_MONTH(self)
+
+ @property
+ cdef inline int day(self):
+ return PyDateTime_GET_DAY(self)
+
+ @property
+ cdef inline int hour(self):
+ return PyDateTime_DATE_GET_HOUR(self)
+
+ @property
+ cdef inline int minute(self):
+ return PyDateTime_DATE_GET_MINUTE(self)
+
+ @property
+ cdef inline int second(self):
+ return PyDateTime_DATE_GET_SECOND(self)
+
+ @property
+ cdef inline int microsecond(self):
+ return PyDateTime_DATE_GET_MICROSECOND(self)
ctypedef extern class datetime.timedelta[object PyDateTime_Delta]:
pass
diff --git a/Cython/Includes/cpython/fileobject.pxd b/Cython/Includes/cpython/fileobject.pxd
new file mode 100644
index 000000000..e52cd33f5
--- /dev/null
+++ b/Cython/Includes/cpython/fileobject.pxd
@@ -0,0 +1,57 @@
+"""
+From https://docs.python.org/3.9/c-api/file.html
+
+These APIs are a minimal emulation of the Python 2 C API for built-in file objects,
+which used to rely on the buffered I/O (FILE*) support from the C standard library.
+In Python 3, files and streams use the new io module, which defines several layers
+over the low-level unbuffered I/O of the operating system. The functions described
+below are convenience C wrappers over these new APIs, and meant mostly for internal
+error reporting in the interpreter;
+
+third-party code is advised to access the io APIs instead.
+"""
+
+cdef extern from "Python.h":
+
+ ###########################################################################
+ # File Objects
+ ###########################################################################
+
+ object PyFile_FromFd(int fd, const char *name, const char *mode, int buffering,
+ const char *encoding, const char *errors, const char *newline, int closefd)
+ # Return value: New reference.
+ # Create a Python file object from the file descriptor of an already
+ # opened file fd. The arguments name, encoding, errors and newline can be
+ # NULL to use the defaults; buffering can be -1 to use the default. name
+ # is ignored and kept for backward compatibility. Return NULL on failure.
+ # For a more comprehensive description of the arguments, please refer to
+ # the io.open() function documentation.
+
+ # Warning: Since Python streams have their own buffering layer, mixing
+ # them with OS-level file descriptors can produce various issues (such as
+ # unexpected ordering of data).
+
+ # Changed in version 3.2: Ignore name attribute.
+
+ object PyFile_GetLine(object p, int n)
+ # Return value: New reference.
+ # Equivalent to p.readline([n]), this function reads one line from the
+ # object p. p may be a file object or any object with a readline()
+ # method. If n is 0, exactly one line is read, regardless of the length of
+ # the line. If n is greater than 0, no more than n bytes will be read from
+ # the file; a partial line can be returned. In both cases, an empty string
+ # is returned if the end of the file is reached immediately. If n is less
+ # than 0, however, one line is read regardless of length, but EOFError is
+ # raised if the end of the file is reached immediately.
+
+ int PyFile_WriteObject(object obj, object p, int flags) except? -1
+ # Write object obj to file object p. The only supported flag for flags
+ # is Py_PRINT_RAW; if given, the str() of the object is written instead of
+ # the repr(). Return 0 on success or -1 on failure; the appropriate
+ # exception will be set.
+
+ int PyFile_WriteString(const char *s, object p) except? -1
+ # Write string s to file object p. Return 0 on success or -1 on failure;
+ # the appropriate exception will be set.
+
+ enum: Py_PRINT_RAW
diff --git a/Cython/Includes/cpython/long.pxd b/Cython/Includes/cpython/long.pxd
index eb8140d41..f65cd0073 100644
--- a/Cython/Includes/cpython/long.pxd
+++ b/Cython/Includes/cpython/long.pxd
@@ -89,7 +89,7 @@ cdef extern from "Python.h":
# Return a C long representation of the contents of pylong. If
# pylong is greater than LONG_MAX, an OverflowError is raised.
- # long PyLong_AsLongAndOverflow(object pylong, int *overflow) except? -1
+ long PyLong_AsLongAndOverflow(object pylong, int *overflow) except? -1
# Return a C long representation of the contents of pylong. If pylong is
# greater than LONG_MAX or less than LONG_MIN, set *overflow to 1 or -1,
# respectively, and return -1; otherwise, set *overflow to 0. If any other
@@ -97,7 +97,7 @@ cdef extern from "Python.h":
# be returned and *overflow will be 0.
# New in version 2.7.
- # PY_LONG_LONG PyLong_AsLongLongAndOverflow(object pylong, int *overflow) except? -1
+ PY_LONG_LONG PyLong_AsLongLongAndOverflow(object pylong, int *overflow) except? -1
# Return a C long long representation of the contents of pylong. If pylong
# is greater than PY_LLONG_MAX or less than PY_LLONG_MIN, set *overflow to
# 1 or -1, respectively, and return -1; otherwise, set *overflow to 0. If
diff --git a/Cython/Includes/cpython/pycapsule.pxd b/Cython/Includes/cpython/pycapsule.pxd
index 449f369a2..c3d12c749 100644
--- a/Cython/Includes/cpython/pycapsule.pxd
+++ b/Cython/Includes/cpython/pycapsule.pxd
@@ -1,7 +1,6 @@
# available since Python 3.1!
-# note all char* in the below functions are actually const char*
cdef extern from "Python.h":
@@ -25,7 +24,7 @@ cdef extern from "Python.h":
# Return true if its argument is a PyCapsule.
- object PyCapsule_New(void *pointer, char *name,
+ object PyCapsule_New(void *pointer, const char *name,
PyCapsule_Destructor destructor)
# Return value: New reference.
#
@@ -48,7 +47,7 @@ cdef extern from "Python.h":
# PyCapsule_Import().
- void* PyCapsule_GetPointer(object capsule, char *name) except? NULL
+ void* PyCapsule_GetPointer(object capsule, const char *name) except? NULL
# Retrieve the pointer stored in the capsule. On failure, set an
# exception and return NULL.
#
@@ -67,7 +66,7 @@ cdef extern from "Python.h":
# or PyErr_Occurred() to disambiguate.
- char* PyCapsule_GetName(object capsule) except? NULL
+ const char* PyCapsule_GetName(object capsule) except? NULL
# Return the current name stored in the capsule. On failure, set
# an exception and return NULL.
#
@@ -85,7 +84,7 @@ cdef extern from "Python.h":
# PyErr_Occurred() to disambiguate.
- bint PyCapsule_IsValid(object capsule, char *name)
+ bint PyCapsule_IsValid(object capsule, const char *name)
# Determines whether or not capsule is a valid capsule. A valid
# capsule is non-NULL, passes PyCapsule_CheckExact(), has a
# non-NULL pointer stored in it, and its internal name matches the
@@ -115,7 +114,7 @@ cdef extern from "Python.h":
# failure.
- int PyCapsule_SetName(object capsule, char *name) except -1
+ int PyCapsule_SetName(object capsule, const char *name) except -1
# Set the name inside capsule to name. If non-NULL, the name must
# outlive the capsule. If the previous name stored in the capsule
# was not NULL, no attempt is made to free it.
@@ -129,7 +128,7 @@ cdef extern from "Python.h":
# success. Return nonzero and set an exception on failure.
- void* PyCapsule_Import(char *name, int no_block) except? NULL
+ void* PyCapsule_Import(const char *name, int no_block) except? NULL
# Import a pointer to a C object from a capsule attribute in a
# module. The name parameter should specify the full name to the
# attribute, as in module.attribute. The name stored in the
diff --git a/Cython/Includes/cpython/time.pxd b/Cython/Includes/cpython/time.pxd
new file mode 100644
index 000000000..076abd931
--- /dev/null
+++ b/Cython/Includes/cpython/time.pxd
@@ -0,0 +1,51 @@
+"""
+Cython implementation of (parts of) the standard library time module.
+"""
+
+from libc.stdint cimport int64_t
+from cpython.exc cimport PyErr_SetFromErrno
+
+cdef extern from "Python.h":
+ ctypedef int64_t _PyTime_t
+ _PyTime_t _PyTime_GetSystemClock() nogil
+ double _PyTime_AsSecondsDouble(_PyTime_t t) nogil
+
+from libc.time cimport (
+ tm,
+ time_t,
+ localtime as libc_localtime,
+)
+
+
+cdef inline double time() nogil:
+ cdef:
+ _PyTime_t tic
+
+ tic = _PyTime_GetSystemClock()
+ return _PyTime_AsSecondsDouble(tic)
+
+
+cdef inline int _raise_from_errno() except -1 with gil:
+ PyErr_SetFromErrno(RuntimeError)
+ return <int> -1 # Let the C compiler know that this function always raises.
+
+
+cdef inline tm localtime() nogil except *:
+ """
+ Analogue to the stdlib time.localtime. The returned struct
+ has some entries that the stdlib version does not: tm_gmtoff, tm_zone
+ """
+ cdef:
+ time_t tic = <time_t>time()
+ tm* result
+
+ result = libc_localtime(&tic)
+ if result is NULL:
+ _raise_from_errno()
+ # Fix 0-based date values (and the 1900-based year).
+ # See tmtotuple() in https://github.com/python/cpython/blob/master/Modules/timemodule.c
+ result.tm_year += 1900
+ result.tm_mon += 1
+ result.tm_wday = (result.tm_wday + 6) % 7
+ result.tm_yday += 1
+ return result[0]
diff --git a/Cython/Includes/libc/time.pxd b/Cython/Includes/libc/time.pxd
index c195a53e4..318212eea 100644
--- a/Cython/Includes/libc/time.pxd
+++ b/Cython/Includes/libc/time.pxd
@@ -20,8 +20,9 @@ cdef extern from "<time.h>" nogil:
int tm_wday
int tm_yday
int tm_isdst
- char *tm_zone
- long tm_gmtoff
+ # GNU specific extensions
+ #char *tm_zone
+ #long tm_gmtoff
int daylight # global state
long timezone
diff --git a/Cython/Includes/numpy/__init__.pxd b/Cython/Includes/numpy/__init__.pxd
index 0a2ce8654..3d9aff71b 100644
--- a/Cython/Includes/numpy/__init__.pxd
+++ b/Cython/Includes/numpy/__init__.pxd
@@ -812,6 +812,29 @@ cdef extern from "numpy/ndarraytypes.h":
int64_t num
cdef extern from "numpy/arrayscalars.h":
+
+ # abstract types
+ ctypedef class numpy.generic [object PyObject]:
+ pass
+ ctypedef class numpy.number [object PyObject]:
+ pass
+ ctypedef class numpy.integer [object PyObject]:
+ pass
+ ctypedef class numpy.signedinteger [object PyObject]:
+ pass
+ ctypedef class numpy.unsignedinteger [object PyObject]:
+ pass
+ ctypedef class numpy.inexact [object PyObject]:
+ pass
+ ctypedef class numpy.floating [object PyObject]:
+ pass
+ ctypedef class numpy.complexfloating [object PyObject]:
+ pass
+ ctypedef class numpy.flexible [object PyObject]:
+ pass
+ ctypedef class numpy.character [object PyObject]:
+ pass
+
ctypedef struct PyDatetimeScalarObject:
# PyObject_HEAD
npy_datetime obval
diff --git a/Cython/Includes/posix/fcntl.pxd b/Cython/Includes/posix/fcntl.pxd
index 768fcdbf3..9afc33a36 100644
--- a/Cython/Includes/posix/fcntl.pxd
+++ b/Cython/Includes/posix/fcntl.pxd
@@ -24,6 +24,7 @@ cdef extern from "<fcntl.h>" nogil:
enum: SEEK_END
enum: O_CREAT
+ enum: O_DIRECT
enum: O_EXCL
enum: O_NOCTTY
enum: O_TRUNC
diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c
index 7dcd48dc0..fc5a8441e 100644
--- a/Cython/Utility/Builtins.c
+++ b/Cython/Utility/Builtins.c
@@ -461,9 +461,9 @@ static CYTHON_INLINE PyObject* __Pyx_PyFrozenSet_New(PyObject* it) {
result = PyFrozenSet_New(it);
if (unlikely(!result))
return NULL;
- if (likely(PySet_GET_SIZE(result)))
+ if ((PY_VERSION_HEX >= 0x031000A1) || likely(PySet_GET_SIZE(result)))
return result;
- // empty frozenset is a singleton
+ // empty frozenset is a singleton (on Python <3.10)
// seems wasteful, but CPython does the same
Py_DECREF(result);
#endif
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index 340bc34f9..6cd1b78b4 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -797,6 +797,32 @@ PyObject *__Pyx_Coroutine_MethodReturn(CYTHON_UNUSED PyObject* gen, PyObject *re
return retval;
}
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
+static CYTHON_INLINE
+PyObject *__Pyx_PyGen_Send(PyGenObject *gen, PyObject *arg) {
+#if PY_VERSION_HEX <= 0x030A00A1
+ return _PyGen_Send(gen, arg);
+#else
+ PyObject *result;
+ // PyIter_Send() asserts non-NULL arg
+ if (PyIter_Send((PyObject*)gen, arg ? arg : Py_None, &result) == PYGEN_RETURN) {
+ if (PyAsyncGen_CheckExact(gen)) {
+ assert(result == Py_None);
+ PyErr_SetNone(PyExc_StopAsyncIteration);
+ }
+ else if (result == Py_None) {
+ PyErr_SetNone(PyExc_StopIteration);
+ }
+ else {
+ _PyGen_SetStopIterationValue(result);
+ }
+ Py_CLEAR(result);
+ }
+ return result;
+#endif
+}
+#endif
+
static CYTHON_INLINE
PyObject *__Pyx_Coroutine_FinishDelegation(__pyx_CoroutineObject *gen) {
PyObject *ret;
@@ -838,13 +864,13 @@ static PyObject *__Pyx_Coroutine_Send(PyObject *self, PyObject *value) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
// _PyGen_Send() is not exported before Py3.6
if (PyGen_CheckExact(yf)) {
- ret = _PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
+ ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
} else
#endif
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03050000 && defined(PyCoro_CheckExact) && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
// _PyGen_Send() is not exported before Py3.6
if (PyCoro_CheckExact(yf)) {
- ret = _PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
+ ret = __Pyx_PyGen_Send((PyGenObject*)yf, value == Py_None ? NULL : value);
} else
#endif
{
@@ -939,7 +965,7 @@ static PyObject *__Pyx_Generator_Next(PyObject *self) {
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x03030000 && (defined(__linux__) || PY_VERSION_HEX >= 0x030600B3)
// _PyGen_Send() is not exported before Py3.6
if (PyGen_CheckExact(yf)) {
- ret = _PyGen_Send((PyGenObject*)yf, NULL);
+ ret = __Pyx_PyGen_Send((PyGenObject*)yf, NULL);
} else
#endif
#ifdef __Pyx_Coroutine_USED
@@ -1140,7 +1166,7 @@ static void __Pyx_Coroutine_dealloc(PyObject *self) {
if (unlikely(PyObject_CallFinalizerFromDealloc(self)))
#else
Py_TYPE(gen)->tp_del(self);
- if (unlikely(self->ob_refcnt > 0))
+ if (unlikely(Py_REFCNT(self) > 0))
#endif
{
// resurrected. :(
@@ -1174,7 +1200,7 @@ static void __Pyx_Coroutine_del(PyObject *self) {
#if !CYTHON_USE_TP_FINALIZE
// Temporarily resurrect the object.
assert(self->ob_refcnt == 0);
- self->ob_refcnt = 1;
+ __Pyx_SET_REFCNT(self, 1);
#endif
__Pyx_PyThreadState_assign
@@ -1255,7 +1281,7 @@ static void __Pyx_Coroutine_del(PyObject *self) {
#if !CYTHON_USE_TP_FINALIZE
// Undo the temporary resurrection; can't use DECREF here, it would
// cause a recursive call.
- assert(self->ob_refcnt > 0);
+ assert(Py_REFCNT(self) > 0);
if (likely(--self->ob_refcnt == 0)) {
// this is the normal path out
return;
@@ -1264,12 +1290,12 @@ static void __Pyx_Coroutine_del(PyObject *self) {
// close() resurrected it! Make it look like the original Py_DECREF
// never happened.
{
- Py_ssize_t refcnt = self->ob_refcnt;
+ Py_ssize_t refcnt = Py_REFCNT(self);
_Py_NewReference(self);
- self->ob_refcnt = refcnt;
+ __Pyx_SET_REFCNT(self, refcnt);
}
#if CYTHON_COMPILING_IN_CPYTHON
- assert(PyType_IS_GC(self->ob_type) &&
+ assert(PyType_IS_GC(Py_TYPE(self)) &&
_Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
// If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
diff --git a/Cython/Utility/CppSupport.cpp b/Cython/Utility/CppSupport.cpp
index a4e63b7ff..37d3384b0 100644
--- a/Cython/Utility/CppSupport.cpp
+++ b/Cython/Utility/CppSupport.cpp
@@ -61,7 +61,8 @@ auto __Pyx_pythran_to_python(T &&value) -> decltype(to_python(
////////////// MoveIfSupported.proto //////////////////
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1600)
+ // move should be defined for these versions of MSVC, but __cplusplus isn't set usefully
#include <utility>
#define __PYX_STD_MOVE_IF_SUPPORTED(x) std::move(x)
#else
diff --git a/Cython/Utility/CythonFunction.c b/Cython/Utility/CythonFunction.c
index 8874d3806..b3021b944 100644
--- a/Cython/Utility/CythonFunction.c
+++ b/Cython/Utility/CythonFunction.c
@@ -221,18 +221,6 @@ __Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, CYTHO
}
static PyObject *
-__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure)
-{
- PyObject *self;
-
- self = m->func_closure;
- if (self == NULL)
- self = Py_None;
- Py_INCREF(self);
- return self;
-}
-
-static PyObject *
__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context)
{
if (unlikely(op->func_dict == NULL)) {
@@ -398,8 +386,9 @@ __Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, CYTHON_UNUSED void
static PyObject *
__Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) {
int is_coroutine;
- if (op->func_is_coroutine)
+ if (op->func_is_coroutine) {
return __Pyx_NewRef(op->func_is_coroutine);
+ }
is_coroutine = op->flags & __Pyx_CYFUNCTION_COROUTINE;
#if PY_VERSION_HEX >= 0x03050000
@@ -413,11 +402,12 @@ __Pyx_CyFunction_get_is_coroutine(__pyx_CyFunctionObject *op, CYTHON_UNUSED void
if (unlikely(!module)) goto ignore;
op->func_is_coroutine = __Pyx_PyObject_GetAttrStr(module, marker);
Py_DECREF(module);
- if (unlikely(!op->func_is_coroutine)) goto ignore;
- return __Pyx_NewRef(op->func_is_coroutine);
- }
+ if (likely(op->func_is_coroutine)) {
+ return __Pyx_NewRef(op->func_is_coroutine);
+ }
ignore:
- PyErr_Clear();
+ PyErr_Clear();
+ }
#endif
op->func_is_coroutine = __Pyx_PyBool_FromLong(is_coroutine);
@@ -455,7 +445,6 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
{(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
{(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0},
{(char *) "__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0},
- {(char *) "__self__", (getter)__Pyx_CyFunction_get_self, 0, 0, 0},
{(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
{(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0},
{(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0},
@@ -742,7 +731,7 @@ static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, P
__pyx_vectorcallfunc vc = __Pyx_CyFunction_func_vectorcall(cyfunc);
if (vc) {
#if CYTHON_ASSUME_SAFE_MACROS
- return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), PyTuple_GET_SIZE(args), kw);
+ return __Pyx_PyVectorcall_FastCallDict(func, vc, &PyTuple_GET_ITEM(args, 0), (size_t)PyTuple_GET_SIZE(args), kw);
#else
// avoid unused function warning
(void) &__Pyx_PyVectorcall_FastCallDict;
@@ -1439,6 +1428,18 @@ bad:
return result;
}
+static PyObject *
+__Pyx_FusedFunction_get_self(__pyx_FusedFunctionObject *m, CYTHON_UNUSED void *closure)
+{
+ PyObject *self = m->self;
+ if (unlikely(!self)) {
+ PyErr_SetString(PyExc_AttributeError, "'function' object has no attribute '__self__'");
+ } else {
+ Py_INCREF(self);
+ }
+ return self;
+}
+
static PyMemberDef __pyx_FusedFunction_members[] = {
{(char *) "__signatures__",
T_OBJECT,
@@ -1448,6 +1449,15 @@ static PyMemberDef __pyx_FusedFunction_members[] = {
{0, 0, 0, 0, 0},
};
+static PyGetSetDef __pyx_FusedFunction_getsets[] = {
+ {(char *) "__self__", (getter)__Pyx_FusedFunction_get_self, 0, 0, 0},
+ // __doc__ is None for the fused function type, but we need it to be
+ // a descriptor for the instance's __doc__, so rebuild the descriptor in our subclass
+ // (all other descriptors are inherited)
+ {(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0},
+ {0, 0, 0, 0, 0}
+};
+
#if CYTHON_USE_TYPE_SPECS
static PyType_Slot __pyx_FusedFunctionType_slots[] = {
{Py_tp_dealloc, (void *)__pyx_FusedFunction_dealloc},
@@ -1455,7 +1465,7 @@ static PyType_Slot __pyx_FusedFunctionType_slots[] = {
{Py_tp_traverse, (void *)__pyx_FusedFunction_traverse},
{Py_tp_clear, (void *)__pyx_FusedFunction_clear},
{Py_tp_members, (void *)__pyx_FusedFunction_members},
- {Py_tp_getset, (void *)__pyx_CyFunction_getsets},
+ {Py_tp_getset, (void *)__pyx_FusedFunction_getsets},
{Py_tp_descr_get, (void *)__pyx_FusedFunction_descr_get},
{Py_mp_subscript, (void *)__pyx_FusedFunction_getitem},
{0, 0},
@@ -1511,9 +1521,7 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
0, /*tp_iternext*/
0, /*tp_methods*/
__pyx_FusedFunction_members, /*tp_members*/
- // __doc__ is None for the fused function type, but we need it to be
- // a descriptor for the instance's __doc__, so rebuild descriptors in our subclass
- __pyx_CyFunction_getsets, /*tp_getset*/
+ __pyx_FusedFunction_getsets, /*tp_getset*/
// NOTE: tp_base may be changed later during module initialisation when importing CyFunction across modules.
&__pyx_CyFunctionType_type, /*tp_base*/
0, /*tp_dict*/
diff --git a/Cython/Utility/ImportExport.c b/Cython/Utility/ImportExport.c
index 3c54f877e..523de2010 100644
--- a/Cython/Utility/ImportExport.c
+++ b/Cython/Utility/ImportExport.c
@@ -25,8 +25,7 @@ static PyObject *__Pyx__ImportDottedModule_Error(PyObject *name, PyObject *parts
if (likely(PyTuple_GET_SIZE(parts_tuple) == count)) {
partial_name = name;
} else {
- PyObject *sep;
- PyObject *slice = PySequence_GetSlice(parts_tuple, 0, count);
+ slice = PySequence_GetSlice(parts_tuple, 0, count);
if (unlikely(!slice))
goto bad;
sep = PyUnicode_FromStringAndSize(".", 1);
@@ -59,7 +58,7 @@ bad:
#if PY_MAJOR_VERSION >= 3
static PyObject *__Pyx__ImportDottedModule_Lookup(PyObject *name) {
PyObject *imported_module;
-#if PY_VERSION_HEX < 0x030700A1
+#if PY_VERSION_HEX < 0x030700A1 || (CYTHON_COMPILING_IN_PYPY && PYPY_VERSION_NUM < 0x07030400)
PyObject *modules = PyImport_GetModuleDict();
if (unlikely(!modules))
return NULL;
diff --git a/Cython/Utility/MemoryView.pyx b/Cython/Utility/MemoryView.pyx
index 829e30d2a..1496755f1 100644
--- a/Cython/Utility/MemoryView.pyx
+++ b/Cython/Utility/MemoryView.pyx
@@ -56,7 +56,7 @@ cdef extern from *:
Py_ssize_t suboffsets[{{max_dims}}]
void __PYX_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
- void __PYX_XDEC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
+ void __PYX_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice, int have_gil)
ctypedef struct __pyx_buffer "Py_buffer":
PyObject *obj
@@ -987,7 +987,7 @@ cdef class _memoryviewslice(memoryview):
cdef int (*to_dtype_func)(char *, object) except 0
def __dealloc__(self):
- __PYX_XDEC_MEMVIEW(&self.from_slice, 1)
+ __PYX_XCLEAR_MEMVIEW(&self.from_slice, 1)
cdef convert_item_to_object(self, char *itemp):
if self.to_object_func != NULL:
diff --git a/Cython/Utility/MemoryView_C.c b/Cython/Utility/MemoryView_C.c
index c6d6601ed..078f634ba 100644
--- a/Cython/Utility/MemoryView_C.c
+++ b/Cython/Utility/MemoryView_C.c
@@ -113,9 +113,9 @@ static CYTHON_INLINE int __pyx_sub_acquisition_count_locked(
#define __pyx_get_slice_count_pointer(memview) (memview->acquisition_count_aligned_p)
#define __pyx_get_slice_count(memview) (*__pyx_get_slice_count_pointer(memview))
#define __PYX_INC_MEMVIEW(slice, have_gil) __Pyx_INC_MEMVIEW(slice, have_gil, __LINE__)
-#define __PYX_XDEC_MEMVIEW(slice, have_gil) __Pyx_XDEC_MEMVIEW(slice, have_gil, __LINE__)
+#define __PYX_XCLEAR_MEMVIEW(slice, have_gil) __Pyx_XCLEAR_MEMVIEW(slice, have_gil, __LINE__)
static CYTHON_INLINE void __Pyx_INC_MEMVIEW({{memviewslice_name}} *, int, int);
-static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *, int, int);
+static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *, int, int);
/////////////// MemviewSliceIndex.proto ///////////////
@@ -512,7 +512,7 @@ __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno)
}
}
-static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
+static CYTHON_INLINE void __Pyx_XCLEAR_MEMVIEW({{memviewslice_name}} *memslice,
int have_gil, int lineno) {
__pyx_atomic_int_type old_acquisition_count;
struct {{memview_struct_name}} *memview = memslice->memview;
diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c
index 758ef1ef6..4ddc9da05 100644
--- a/Cython/Utility/ModuleSetupCode.c
+++ b/Cython/Utility/ModuleSetupCode.c
@@ -174,8 +174,9 @@
#define CYTHON_USE_TYPE_SPECS 1
#undef CYTHON_USE_PYTYPE_LOOKUP
#define CYTHON_USE_PYTYPE_LOOKUP 0
- #undef CYTHON_USE_PYLIST_INTERNALS
+ #undef CYTHON_USE_ASYNC_SLOTS
#define CYTHON_USE_ASYNC_SLOTS 0
+ #undef CYTHON_USE_PYLIST_INTERNALS
#define CYTHON_USE_PYLIST_INTERNALS 0
#undef CYTHON_USE_UNICODE_INTERNALS
#define CYTHON_USE_UNICODE_INTERNALS 0
@@ -585,15 +586,15 @@ class __Pyx_FakeReference {
#if CYTHON_VECTORCALL
#define __pyx_vectorcallfunc vectorcallfunc
#define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET PY_VECTORCALL_ARGUMENTS_OFFSET
- #define __Pyx_PyVectorcall_NARGS(n) PyVectorcall_NARGS(n)
+ #define __Pyx_PyVectorcall_NARGS(n) PyVectorcall_NARGS((size_t)(n))
#elif CYTHON_BACKPORT_VECTORCALL
typedef PyObject *(*__pyx_vectorcallfunc)(PyObject *callable, PyObject *const *args,
size_t nargsf, PyObject *kwnames);
#define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET ((size_t)1 << (8 * sizeof(size_t) - 1))
- #define __Pyx_PyVectorcall_NARGS(n) ((n) & ~__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET)
+ #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(((size_t)(n)) & ~__Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET))
#else
#define __Pyx_PY_VECTORCALL_ARGUMENTS_OFFSET 0
- #define __Pyx_PyVectorcall_NARGS(n) (n)
+ #define __Pyx_PyVectorcall_NARGS(n) ((Py_ssize_t)(n))
#endif
// PEP-573: PyCFunction holds reference to defining class (PyCMethodObject)
@@ -791,7 +792,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict,
#define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u)
#define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i)
#define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u)
- #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u)
+ #define __Pyx_PyUnicode_KIND(u) ((int)PyUnicode_KIND(u))
#define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u)
#define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i)
#define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch)
@@ -809,7 +810,7 @@ static CYTHON_INLINE PyObject * __Pyx_PyDict_GetItemStrWithError(PyObject *dict,
#define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u)
#define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i]))
#define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111)
- #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE))
+ #define __Pyx_PyUnicode_KIND(u) ((int)sizeof(Py_UNICODE))
#define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u))
// (void)(k) => avoid unused variable warning due to macro:
#define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i]))
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index d9dd7ffae..bd6e438da 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -1024,6 +1024,94 @@ static PyObject *__Pyx_CreateClass(PyObject *bases, PyObject *dict, PyObject *na
return result;
}
+/////////////// Py3UpdateBases.proto ///////////////
+
+static PyObject* __Pyx_PEP560_update_bases(PyObject *bases); /* proto */
+
+/////////////// Py3UpdateBases /////////////////////
+//@requires: PyObjectCallOneArg
+//@requires: PyObjectGetAttrStrNoError
+
+/* Shamelessly adapted from cpython/bltinmodule.c update_bases */
+static PyObject*
+__Pyx_PEP560_update_bases(PyObject *bases)
+{
+ Py_ssize_t i, j, size_bases;
+ PyObject *base, *meth, *new_base, *result, *new_bases = NULL;
+ /*assert(PyTuple_Check(bases));*/
+
+ size_bases = PyTuple_GET_SIZE(bases);
+ for (i = 0; i < size_bases; i++) {
+ // original code in CPython: base = args[i];
+ base = PyTuple_GET_ITEM(bases, i);
+ if (PyType_Check(base)) {
+ if (new_bases) {
+ // If we already have made a replacement, then we append every normal base,
+ // otherwise just skip it.
+ if (PyList_Append(new_bases, base) < 0) {
+ goto error;
+ }
+ }
+ continue;
+ }
+ // original code in CPython:
+ // if (_PyObject_LookupAttrId(base, &PyId___mro_entries__, &meth) < 0) {
+ meth = __Pyx_PyObject_GetAttrStrNoError(base, PYIDENT("__mro_entries__"));
+ if (!meth && PyErr_Occurred()) {
+ goto error;
+ }
+ if (!meth) {
+ if (new_bases) {
+ if (PyList_Append(new_bases, base) < 0) {
+ goto error;
+ }
+ }
+ continue;
+ }
+ new_base = __Pyx_PyObject_CallOneArg(meth, bases);
+ Py_DECREF(meth);
+ if (!new_base) {
+ goto error;
+ }
+ if (!PyTuple_Check(new_base)) {
+ PyErr_SetString(PyExc_TypeError,
+ "__mro_entries__ must return a tuple");
+ Py_DECREF(new_base);
+ goto error;
+ }
+ if (!new_bases) {
+ // If this is a first successful replacement, create new_bases list and
+ // copy previously encountered bases.
+ if (!(new_bases = PyList_New(i))) {
+ goto error;
+ }
+ for (j = 0; j < i; j++) {
+ // original code in CPython: base = args[j];
+ base = PyTuple_GET_ITEM(bases, j);
+ PyList_SET_ITEM(new_bases, j, base);
+ Py_INCREF(base);
+ }
+ }
+ j = PyList_GET_SIZE(new_bases);
+ if (PyList_SetSlice(new_bases, j, j, new_base) < 0) {
+ goto error;
+ }
+ Py_DECREF(new_base);
+ }
+ if (!new_bases) {
+ // unlike the CPython implementation, always return a new reference
+ Py_INCREF(bases);
+ return bases;
+ }
+ result = PyList_AsTuple(new_bases);
+ Py_DECREF(new_bases);
+ return result;
+
+error:
+ Py_XDECREF(new_bases);
+ return NULL;
+}
+
/////////////// Py3ClassCreate.proto ///////////////
static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname,
@@ -1983,13 +2071,13 @@ static CYTHON_INLINE PyObject* __Pyx_CallUnboundCMethod1(__Pyx_CachedCFunction*
// Not using #ifdefs for PY_VERSION_HEX to avoid C compiler warnings about unused functions.
if (flag == METH_O) {
return (*(cfunc->func))(self, arg);
- } else if (PY_VERSION_HEX >= 0x030600B1 && flag == METH_FASTCALL) {
- if (PY_VERSION_HEX >= 0x030700A0) {
+ } else if ((PY_VERSION_HEX >= 0x030600B1) && flag == METH_FASTCALL) {
+ if ((PY_VERSION_HEX >= 0x030700A0)) {
return (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)cfunc->func)(self, &arg, 1);
} else {
return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL);
}
- } else if (PY_VERSION_HEX >= 0x030700A0 && flag == (METH_FASTCALL | METH_KEYWORDS)) {
+ } else if ((PY_VERSION_HEX >= 0x030700A0) && flag == (METH_FASTCALL | METH_KEYWORDS)) {
return (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)cfunc->func)(self, &arg, 1, NULL);
}
}
@@ -2104,7 +2192,7 @@ bad:
/////////////// PyObjectFastCall.proto ///////////////
#define __Pyx_PyObject_FastCall(func, args, nargs) __Pyx_PyObject_FastCallDict(func, args, nargs, NULL)
-static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); /*proto*/
+static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, size_t nargs, PyObject *kwargs); /*proto*/
/////////////// PyObjectFastCall ///////////////
//@requires: PyObjectCall
@@ -2112,23 +2200,23 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObj
//@requires: PyObjectCallMethO
//@substitute: naming
-static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) {
+static PyObject* __Pyx_PyObject_FastCall_fallback(PyObject *func, PyObject **args, size_t nargs, PyObject *kwargs) {
PyObject *argstuple;
PyObject *result;
- Py_ssize_t i;
+ size_t i;
argstuple = PyTuple_New(nargs);
if (unlikely(!argstuple)) return NULL;
for (i = 0; i < nargs; i++) {
Py_INCREF(args[i]);
- PyTuple_SET_ITEM(argstuple, i, args[i]);
+ PyTuple_SET_ITEM(argstuple, (Py_ssize_t)i, args[i]);
}
result = __Pyx_PyObject_Call(func, argstuple, kwargs);
Py_DECREF(argstuple);
return result;
}
-static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t _nargs, PyObject *kwargs) {
+static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObject **args, size_t _nargs, PyObject *kwargs) {
// Special fast paths for 0 and 1 arguments
// NOTE: in many cases, this is called with a constant value for nargs
// which is known at compile-time. So the branches below will typically
@@ -2182,20 +2270,20 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_FastCallDict(PyObject *func, PyObj
#if CYTHON_VECTORCALL
vectorcallfunc f = _PyVectorcall_Function(func);
if (f) {
- return f(func, args, nargs, kwargs);
+ return f(func, args, (size_t)nargs, kwargs);
}
#elif defined(__Pyx_CyFunction_USED) && CYTHON_BACKPORT_VECTORCALL
// exclude fused functions for now
if (__Pyx_CyFunction_CheckExact(func)) {
__pyx_vectorcallfunc f = __Pyx_CyFunction_func_vectorcall(func);
- if (f) return f(func, args, nargs, kwargs);
+ if (f) return f(func, args, (size_t)nargs, kwargs);
}
#endif
if (nargs == 0) {
return __Pyx_PyObject_Call(func, $empty_tuple, kwargs);
}
- return __Pyx_PyObject_FastCall_fallback(func, args, nargs, kwargs);
+ return __Pyx_PyObject_FastCall_fallback(func, args, (size_t)nargs, kwargs);
}
@@ -2274,7 +2362,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg
#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) {
PyObject *result;
- ternaryfunc call = func->ob_type->tp_call;
+ ternaryfunc call = Py_TYPE(func)->tp_call;
if (unlikely(!call))
return PyObject_Call(func, arg, kw);
@@ -2560,14 +2648,14 @@ static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) {
/////////////// PyVectorcallFastCallDict.proto ///////////////
#if CYTHON_METH_FASTCALL
-static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, Py_ssize_t nargs, PyObject *kw);
+static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw);
#endif
/////////////// PyVectorcallFastCallDict ///////////////
#if CYTHON_METH_FASTCALL
// Slow path when kw is non-empty
-static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, Py_ssize_t nargs, PyObject *kw)
+static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw)
{
// Code based on _PyObject_FastCallDict() and _PyStack_UnpackDict() from CPython
PyObject *res = NULL;
@@ -2575,17 +2663,18 @@ static PyObject *__Pyx_PyVectorcall_FastCallDict_kw(PyObject *func, __pyx_vector
PyObject **newargs;
PyObject **kwvalues;
Py_ssize_t i, pos;
+ size_t j;
PyObject *key, *value;
unsigned long keys_are_strings;
Py_ssize_t nkw = PyDict_GET_SIZE(kw);
// Copy positional arguments
- newargs = (PyObject **)PyMem_Malloc((nargs + nkw) * sizeof(args[0]));
+ newargs = (PyObject **)PyMem_Malloc((nargs + (size_t)nkw) * sizeof(args[0]));
if (unlikely(newargs == NULL)) {
PyErr_NoMemory();
return NULL;
}
- for (i = 0; i < nargs; i++) newargs[i] = args[i];
+ for (j = 0; j < nargs; j++) newargs[j] = args[j];
// Copy keyword arguments
kwnames = PyTuple_New(nkw);
@@ -2620,7 +2709,7 @@ cleanup:
return res;
}
-static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, Py_ssize_t nargs, PyObject *kw)
+static CYTHON_INLINE PyObject *__Pyx_PyVectorcall_FastCallDict(PyObject *func, __pyx_vectorcallfunc vc, PyObject *const *args, size_t nargs, PyObject *kw)
{
if (likely(kw == NULL) || PyDict_GET_SIZE(kw) == 0) {
return vc(func, args, nargs, NULL);
diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c
index 971ec3bca..f9637b670 100644
--- a/Cython/Utility/Optimize.c
+++ b/Cython/Utility/Optimize.c
@@ -591,51 +591,366 @@ static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */
PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
#else
#define __Pyx_PyObject_AsDouble(obj) \
-((likely(PyFloat_CheckExact(obj))) ? \
- PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
+((likely(PyFloat_CheckExact(obj))) ? PyFloat_AS_DOUBLE(obj) : \
+ likely(PyLong_CheckExact(obj)) ? \
+ PyLong_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
#endif
/////////////// pyobject_as_double ///////////////
+//@requires: pybytes_as_double
+//@requires: pyunicode_as_double
//@requires: ObjectHandling.c::PyObjectCallOneArg
static double __Pyx__PyObject_AsDouble(PyObject* obj) {
- PyObject* float_value;
+ if (PyUnicode_CheckExact(obj)) {
+ return __Pyx_PyUnicode_AsDouble(obj);
+ } else if (PyBytes_CheckExact(obj)) {
+ return __Pyx_PyBytes_AsDouble(obj);
+ } else if (PyByteArray_CheckExact(obj)) {
+ return __Pyx_PyByteArray_AsDouble(obj);
+ } else {
+ PyObject* float_value;
#if !CYTHON_USE_TYPE_SLOTS
- float_value = PyNumber_Float(obj); if ((0)) goto bad;
- // avoid "unused" warnings
- (void)__Pyx_PyObject_CallOneArg;
+ float_value = PyNumber_Float(obj); if ((0)) goto bad;
+ // avoid "unused" warnings
+ (void)__Pyx_PyObject_CallOneArg;
#else
- PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
- if (likely(nb) && likely(nb->nb_float)) {
- float_value = nb->nb_float(obj);
- if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) {
- __Pyx_TypeName float_value_type_name = __Pyx_PyType_GetName(Py_TYPE(float_value));
- PyErr_Format(PyExc_TypeError,
- "__float__ returned non-float (type " __Pyx_FMT_TYPENAME ")",
- float_value_type_name);
- __Pyx_DECREF_TypeName(float_value_type_name);
- Py_DECREF(float_value);
- goto bad;
+ PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
+ if (likely(nb) && likely(nb->nb_float)) {
+ float_value = nb->nb_float(obj);
+ if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) {
+ __Pyx_TypeName float_value_type_name = __Pyx_PyType_GetName(Py_TYPE(float_value));
+ PyErr_Format(PyExc_TypeError,
+ "__float__ returned non-float (type " __Pyx_FMT_TYPENAME ")",
+ float_value_type_name);
+ __Pyx_DECREF_TypeName(float_value_type_name);
+ Py_DECREF(float_value);
+ goto bad;
+ }
+ } else {
+ float_value = __Pyx_PyObject_CallOneArg((PyObject*)&PyFloat_Type, obj);
}
- } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) {
-#if PY_MAJOR_VERSION >= 3
- float_value = PyFloat_FromString(obj);
-#else
- float_value = PyFloat_FromString(obj, 0);
#endif
+ if (likely(float_value)) {
+ double value = PyFloat_AS_DOUBLE(float_value);
+ Py_DECREF(float_value);
+ return value;
+ }
+ }
+bad:
+ return (double)-1;
+}
+
+
+/////////////// pystring_as_double.proto ///////////////
+//@requires: pyunicode_as_double
+//@requires: pybytes_as_double
+
+static CYTHON_INLINE double __Pyx_PyString_AsDouble(PyObject *obj) {
+ #if PY_MAJOR_VERSION >= 3
+ (void)__Pyx_PyBytes_AsDouble;
+ return __Pyx_PyUnicode_AsDouble(obj);
+ #else
+ (void)__Pyx_PyUnicode_AsDouble;
+ return __Pyx_PyBytes_AsDouble(obj);
+ #endif
+}
+
+
+/////////////// pyunicode_as_double.proto ///////////////
+
+static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj);/*proto*/
+
+/////////////// pyunicode_as_double.proto ///////////////
+//@requires: pybytes_as_double
+
+#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+static const char* __Pyx__PyUnicode_AsDouble_Copy(const void* data, const int kind, char* buffer, Py_ssize_t start, Py_ssize_t end) {
+ int last_was_punctuation;
+ Py_ssize_t i;
+ // number must not start with punctuation
+ last_was_punctuation = 1;
+ for (i=start; i <= end; i++) {
+ Py_UCS4 chr = PyUnicode_READ(kind, data, i);
+ int is_punctuation = (chr == '_') | (chr == '.');
+ *buffer = (char)chr;
+ // reject sequences of '_' and '.'
+ buffer += (chr != '_');
+ if (unlikely(chr > 127)) goto parse_failure;
+ if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure;
+ last_was_punctuation = is_punctuation;
+ }
+ if (unlikely(last_was_punctuation)) goto parse_failure;
+ *buffer = '\0';
+ return buffer;
+
+parse_failure:
+ return NULL;
+}
+
+static double __Pyx__PyUnicode_AsDouble_inf_nan(const void* data, int kind, Py_ssize_t start, Py_ssize_t length) {
+ int matches = 1;
+ Py_UCS4 chr;
+ Py_UCS4 sign = PyUnicode_READ(kind, data, start);
+ int is_signed = (sign == '-') | (sign == '+');
+ start += is_signed;
+ length -= is_signed;
+
+ switch (PyUnicode_READ(kind, data, start)) {
+ #ifdef Py_NAN
+ case 'n':
+ case 'N':
+ if (unlikely(length != 3)) goto parse_failure;
+ chr = PyUnicode_READ(kind, data, start+1);
+ matches &= (chr == 'a') | (chr == 'A');
+ chr = PyUnicode_READ(kind, data, start+2);
+ matches &= (chr == 'n') | (chr == 'N');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_NAN : Py_NAN;
+ #endif
+ case 'i':
+ case 'I':
+ if (unlikely(length < 3)) goto parse_failure;
+ chr = PyUnicode_READ(kind, data, start+1);
+ matches &= (chr == 'n') | (chr == 'N');
+ chr = PyUnicode_READ(kind, data, start+2);
+ matches &= (chr == 'f') | (chr == 'F');
+ if (likely(length == 3 && matches))
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ if (unlikely(length != 8)) goto parse_failure;
+ chr = PyUnicode_READ(kind, data, start+3);
+ matches &= (chr == 'i') | (chr == 'I');
+ chr = PyUnicode_READ(kind, data, start+4);
+ matches &= (chr == 'n') | (chr == 'N');
+ chr = PyUnicode_READ(kind, data, start+5);
+ matches &= (chr == 'i') | (chr == 'I');
+ chr = PyUnicode_READ(kind, data, start+6);
+ matches &= (chr == 't') | (chr == 'T');
+ chr = PyUnicode_READ(kind, data, start+7);
+ matches &= (chr == 'y') | (chr == 'Y');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ break;
+ default:
+ goto parse_failure;
+ }
+ return 0.0;
+parse_failure:
+ return -1.0;
+}
+
+static double __Pyx_PyUnicode_AsDouble_WithSpaces(PyObject *obj) {
+ double value;
+ const char *last;
+ char *end;
+ Py_ssize_t start, length = PyUnicode_GET_LENGTH(obj);
+ const int kind = PyUnicode_KIND(obj);
+ const void* data = PyUnicode_DATA(obj);
+
+ // strip spaces at start and end
+ start = 0;
+ while (Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, start)))
+ start++;
+ while (start < length - 1 && Py_UNICODE_ISSPACE(PyUnicode_READ(kind, data, length - 1)))
+ length--;
+ length -= start;
+ if (unlikely(length <= 0)) goto fallback;
+
+ // parse NaN / inf
+ value = __Pyx__PyUnicode_AsDouble_inf_nan(data, kind, start, length);
+ if (unlikely(value == -1.0)) goto fallback;
+ if (value != 0.0) return value;
+
+ if (length < 40) {
+ char number[40];
+ last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length);
+ if (unlikely(!last)) goto fallback;
+ value = PyOS_string_to_double(number, &end, NULL);
} else {
- float_value = __Pyx_PyObject_CallOneArg((PyObject*)&PyFloat_Type, obj);
+ char *number = (char*) PyMem_Malloc((length + 1) * sizeof(char));
+ if (unlikely(!number)) goto fallback;
+ last = __Pyx__PyUnicode_AsDouble_Copy(data, kind, number, start, start + length);
+ if (unlikely(!last)) {
+ PyMem_Free(number);
+ goto fallback;
+ }
+ value = PyOS_string_to_double(number, &end, NULL);
+ PyMem_Free(number);
+ }
+ if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) {
+ return value;
+ }
+fallback:
+ return __Pyx_SlowPyString_AsDouble(obj);
+}
+#endif
+
+static CYTHON_INLINE double __Pyx_PyUnicode_AsDouble(PyObject *obj) {
+ // Currently not optimised for Py2.7.
+#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
+ if (unlikely(PyUnicode_READY(obj) == -1))
+ return (double)-1;
+ if (likely(PyUnicode_IS_ASCII(obj))) {
+ const char *s;
+ Py_ssize_t length;
+ s = PyUnicode_AsUTF8AndSize(obj, &length);
+ return __Pyx__PyBytes_AsDouble(obj, s, length);
}
+ return __Pyx_PyUnicode_AsDouble_WithSpaces(obj);
+#else
+ return __Pyx_SlowPyString_AsDouble(obj);
+#endif
+}
+
+
+/////////////// pybytes_as_double.proto ///////////////
+
+static double __Pyx_SlowPyString_AsDouble(PyObject *obj);/*proto*/
+static double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length);/*proto*/
+
+static CYTHON_INLINE double __Pyx_PyBytes_AsDouble(PyObject *obj) {
+ return __Pyx__PyBytes_AsDouble(obj, PyBytes_AS_STRING(obj), PyBytes_GET_SIZE(obj));
+}
+static CYTHON_INLINE double __Pyx_PyByteArray_AsDouble(PyObject *obj) {
+ return __Pyx__PyBytes_AsDouble(obj, PyByteArray_AS_STRING(obj), PyByteArray_GET_SIZE(obj));
+}
+
+
+/////////////// pybytes_as_double ///////////////
+
+static double __Pyx_SlowPyString_AsDouble(PyObject *obj) {
+ PyObject *float_value;
+#if PY_MAJOR_VERSION >= 3
+ float_value = PyFloat_FromString(obj);
+#else
+ float_value = PyFloat_FromString(obj, 0);
#endif
if (likely(float_value)) {
double value = PyFloat_AS_DOUBLE(float_value);
Py_DECREF(float_value);
return value;
}
-bad:
return (double)-1;
}
+static const char* __Pyx__PyBytes_AsDouble_Copy(const char* start, char* buffer, Py_ssize_t length) {
+ // number must not start with punctuation
+ int last_was_punctuation = 1;
+ Py_ssize_t i;
+ for (i=0; i < length; i++) {
+ char chr = start[i];
+ int is_punctuation = (chr == '_') | (chr == '.') | (chr == 'e') | (chr == 'E');
+ *buffer = chr;
+ buffer += (chr != '_');
+ // reject sequences of '_' and '.'
+ if (unlikely(last_was_punctuation & is_punctuation)) goto parse_failure;
+ last_was_punctuation = is_punctuation;
+ }
+ if (unlikely(last_was_punctuation)) goto parse_failure;
+ *buffer = '\0';
+ return buffer;
+
+parse_failure:
+ return NULL;
+}
+
+static double __Pyx__PyBytes_AsDouble_inf_nan(const char* start, Py_ssize_t length) {
+ int matches = 1;
+ char sign = start[0];
+ int is_signed = (sign == '+') | (sign == '-');
+ start += is_signed;
+ length -= is_signed;
+
+ switch (start[0]) {
+ #ifdef Py_NAN
+ case 'n':
+ case 'N':
+ if (unlikely(length != 3)) goto parse_failure;
+ matches &= (start[1] == 'a' || start[1] == 'A');
+ matches &= (start[2] == 'n' || start[2] == 'N');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_NAN : Py_NAN;
+ #endif
+ case 'i':
+ case 'I':
+ if (unlikely(length < 3)) goto parse_failure;
+ matches &= (start[1] == 'n' || start[1] == 'N');
+ matches &= (start[2] == 'f' || start[2] == 'F');
+ if (likely(length == 3 && matches))
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ if (unlikely(length != 8)) goto parse_failure;
+ matches &= (start[3] == 'i' || start[3] == 'I');
+ matches &= (start[4] == 'n' || start[4] == 'N');
+ matches &= (start[5] == 'i' || start[5] == 'I');
+ matches &= (start[6] == 't' || start[6] == 'T');
+ matches &= (start[7] == 'y' || start[7] == 'Y');
+ if (unlikely(!matches)) goto parse_failure;
+ return (sign == '-') ? -Py_HUGE_VAL : Py_HUGE_VAL;
+ case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ break;
+ default:
+ goto parse_failure;
+ }
+ return 0.0;
+parse_failure:
+ return -1.0;
+}
+
+static CYTHON_INLINE int __Pyx__PyBytes_AsDouble_IsSpace(char ch) {
+ // see Py_ISSPACE() in CPython
+ // https://github.com/python/cpython/blob/master/Python/pyctype.c
+ return (ch == 0x20) | !((ch < 0x9) | (ch > 0xd));
+}
+
+static CYTHON_UNUSED double __Pyx__PyBytes_AsDouble(PyObject *obj, const char* start, Py_ssize_t length) {
+ double value;
+ Py_ssize_t i, digits;
+ const char *last = start + length;
+ char *end;
+
+ // strip spaces at start and end
+ while (__Pyx__PyBytes_AsDouble_IsSpace(*start))
+ start++;
+ while (start < last - 1 && __Pyx__PyBytes_AsDouble_IsSpace(last[-1]))
+ last--;
+ length = last - start;
+ if (unlikely(length <= 0)) goto fallback;
+
+ // parse NaN / inf
+ value = __Pyx__PyBytes_AsDouble_inf_nan(start, length);
+ if (unlikely(value == -1.0)) goto fallback;
+ if (value != 0.0) return value;
+
+ // look for underscores
+ digits = 0;
+ for (i=0; i < length; digits += start[i++] != '_');
+
+ if (likely(digits == length)) {
+ value = PyOS_string_to_double(start, &end, NULL);
+ } else if (digits < 40) {
+ char number[40];
+ last = __Pyx__PyBytes_AsDouble_Copy(start, number, length);
+ if (unlikely(!last)) goto fallback;
+ value = PyOS_string_to_double(number, &end, NULL);
+ } else {
+ char *number = (char*) PyMem_Malloc((digits + 1) * sizeof(char));
+ if (unlikely(!number)) goto fallback;
+ last = __Pyx__PyBytes_AsDouble_Copy(start, number, length);
+ if (unlikely(!last)) {
+ PyMem_Free(number);
+ goto fallback;
+ }
+ value = PyOS_string_to_double(number, &end, NULL);
+ PyMem_Free(number);
+ }
+ if (likely(end == last) || (value == (double)-1 && PyErr_Occurred())) {
+ return value;
+ }
+fallback:
+ return __Pyx_SlowPyString_AsDouble(obj);
+}
+
/////////////// PyNumberPow2.proto ///////////////
diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c
index 1eecfe5cc..99e668545 100644
--- a/Cython/Utility/TypeConversion.c
+++ b/Cython/Utility/TypeConversion.c
@@ -126,7 +126,8 @@ static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*);
#else
#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x))
#endif
-#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x))
+// __Pyx_PyNumber_Float is now in it's own section since it has dependencies (needed to make
+// string conversion work the same in all circumstances)
#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
static int __Pyx_sys_getdefaultencoding_not_ascii;
@@ -463,6 +464,27 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
return PyInt_FromSize_t(ival);
}
+/////////////// pynumber_float.proto ///////////////
+
+static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj); /* proto */
+#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : __Pyx__PyNumber_Float(x))
+
+/////////////// pynumber_float ///////////////
+//@requires: Optimize.c::pybytes_as_double
+//@requires: Optimize.c::pyunicode_as_double
+
+static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) {
+ // obj is PyFloat is handled in the calling macro
+ if (PyUnicode_CheckExact(obj)) {
+ return PyFloat_FromDouble(__Pyx_PyUnicode_AsDouble(obj));
+ } else if (PyBytes_CheckExact(obj)) {
+ return PyFloat_FromDouble(__Pyx_PyBytes_AsDouble(obj));
+ } else if (PyByteArray_CheckExact(obj)) {
+ return PyFloat_FromDouble(__Pyx_PyByteArray_AsDouble(obj));
+ } else {
+ return PyNumber_Float(obj);
+ }
+}
/////////////// GCCDiagnostics.proto ///////////////
@@ -902,7 +924,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
const int is_unsigned = neg_one > const_zero;
#if PY_MAJOR_VERSION < 3
if (likely(PyInt_Check(x))) {
- if (sizeof({{TYPE}}) < sizeof(long)) {
+ if ((sizeof({{TYPE}}) < sizeof(long))) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, long, PyInt_AS_LONG(x))
} else {
long val = PyInt_AS_LONG(x);
@@ -922,10 +944,10 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0])
{{for _size in (2, 3, 4)}}
case {{_size}}:
- if (8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT) {
- if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
+ if ((8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT)) {
+ if ((8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
- } else if (8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT) {
+ } else if ((8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT)) {
return ({{TYPE}}) {{pylong_join(_size, 'digits', TYPE)}};
}
}
@@ -947,10 +969,10 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
goto raise_neg_overflow;
}
#endif
- if (sizeof({{TYPE}}) <= sizeof(unsigned long)) {
+ if ((sizeof({{TYPE}}) <= sizeof(unsigned long))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned long, PyLong_AsUnsignedLong(x))
#ifdef HAVE_LONG_LONG
- } else if (sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG)) {
+ } else if ((sizeof({{TYPE}}) <= sizeof(unsigned PY_LONG_LONG))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x))
#endif
}
@@ -965,10 +987,10 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
{{for _size in (2, 3, 4)}}
{{for _case in (-_size, _size)}}
case {{_case}}:
- if (8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT) {
- if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
+ if ((8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT)) {
+ if ((8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
- } else if (8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT) {
+ } else if ((8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT)) {
return ({{TYPE}}) ({{'((%s)-1)*' % TYPE if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}});
}
}
@@ -977,10 +999,10 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
{{endfor}}
}
#endif
- if (sizeof({{TYPE}}) <= sizeof(long)) {
+ if ((sizeof({{TYPE}}) <= sizeof(long))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, long, PyLong_AsLong(x))
#ifdef HAVE_LONG_LONG
- } else if (sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG)) {
+ } else if ((sizeof({{TYPE}}) <= sizeof(PY_LONG_LONG))) {
__PYX_VERIFY_RETURN_INT_EXC({{TYPE}}, PY_LONG_LONG, PyLong_AsLongLong(x))
#endif
}
diff --git a/Cython/Utility/arrayarray.h b/Cython/Utility/arrayarray.h
index 61a883fc4..a9e492378 100644
--- a/Cython/Utility/arrayarray.h
+++ b/Cython/Utility/arrayarray.h
@@ -88,7 +88,7 @@ static CYTHON_INLINE PyObject * newarrayobject(PyTypeObject *type, Py_ssize_t si
op->ob_descr = descr;
op->allocated = size;
op->weakreflist = NULL;
- op->ob_size = size;
+ __Pyx_SET_SIZE(op, size);
if (size <= 0) {
op->data.ob_item = NULL;
}
@@ -116,7 +116,7 @@ static CYTHON_INLINE int resize(arrayobject *self, Py_ssize_t n) {
return -1;
}
self->data.ob_item = (char*) items;
- self->ob_size = n;
+ __Pyx_SET_SIZE(self, n);
self->allocated = n;
return 0;
}
@@ -126,7 +126,7 @@ static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
void *items = (void*) self->data.ob_item;
Py_ssize_t newsize;
if (n < self->allocated && n*4 > self->allocated) {
- self->ob_size = n;
+ __Pyx_SET_SIZE(self, n);
return 0;
}
newsize = n + (n / 2) + 1;
@@ -140,7 +140,7 @@ static CYTHON_INLINE int resize_smart(arrayobject *self, Py_ssize_t n) {
return -1;
}
self->data.ob_item = (char*) items;
- self->ob_size = n;
+ __Pyx_SET_SIZE(self, n);
self->allocated = newsize;
return 0;
}
diff --git a/Cython/Utils.py b/Cython/Utils.py
index 389647362..c8f716467 100644
--- a/Cython/Utils.py
+++ b/Cython/Utils.py
@@ -156,9 +156,7 @@ def check_package_dir(dir_path, package_names):
for dirname in package_names:
dir_path = os.path.join(dir_path, dirname)
has_init = contains_init(dir_path)
- if not namespace and not has_init:
- return None, False
- elif has_init:
+ if has_init:
namespace = False
return dir_path, namespace
diff --git a/README.rst b/README.rst
index e1c718c27..6b9c9f773 100644
--- a/README.rst
+++ b/README.rst
@@ -15,7 +15,7 @@ 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: https://cython.org/
-* Documentation: http://docs.cython.org/
+* Documentation: https://docs.cython.org/
* Github repository: https://github.com/cython/cython
* Wiki: https://github.com/cython/cython/wiki
@@ -31,7 +31,7 @@ If you already have a C compiler, just run following command::
pip install Cython
-otherwise, see `the installation page <http://docs.cython.org/en/latest/src/quickstart/install.html>`_.
+otherwise, see `the installation page <https://docs.cython.org/en/latest/src/quickstart/install.html>`_.
License:
@@ -85,7 +85,7 @@ 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/>`_.
+The latest version of Pyrex can be found `here <https://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/>`_.
| Greg Ewing, Computer Science Dept
| University of Canterbury
diff --git a/appveyor.yml b/appveyor.yml
index 68d5f733d..8148e517c 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -104,6 +104,7 @@ branches:
only:
- master
- release
+ - 0.29.x
init:
- "ECHO Python %PYTHON_VERSION% (%PYTHON_ARCH%bit) from %PYTHON%"
diff --git a/appveyor/install.ps1 b/appveyor/install.ps1
index 6a8fc6ad9..6dc32f40a 100644
--- a/appveyor/install.ps1
+++ b/appveyor/install.ps1
@@ -48,12 +48,14 @@ function InstallPython ($python_version, $architecture, $python_home) {
$installer_exe = ($py_major + $py_minor) -as [int] -ge 35
if ($installer_exe) {
$arch_suffix = @{"32"="";"64"="-amd64"}[$architecture]
- $filename = "python-" + $python_version + $arch_suffix + ".exe"
+ $dl_filename = "python-" + $python_version + $arch_suffix + ".exe"
+ $filename = "python-" + $py_major + "." + $py_minor + $arch_suffix + ".exe"
} else {
$arch_suffix = @{"32"="";"64"=".amd64"}[$architecture]
- $filename = "python-" + $python_version + $arch_suffix + ".msi"
+ $dl_filename = "python-" + $python_version + $arch_suffix + ".msi"
+ $filename = "python-" + $py_major + "." + $py_minor + $arch_suffix + ".msi"
}
- $url = $PYTHON_BASE_URL + $python_version + "/" + $filename
+ $url = $PYTHON_BASE_URL + $python_version + "/" + $dl_filename
$filepath = Download $url $filename $DOWNLOADS
Write-Host "Installing" $filename "to" $python_home
if ($installer_exe) {
@@ -99,7 +101,8 @@ function InstallPipPackage ($python_home, $package) {
}
function main () {
- InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON
+ $full_version = $env:PYTHON_VERSION + ".0"
+ InstallPython $full_version $env:PYTHON_ARCH $env:PYTHON
InstallPip $env:PYTHON
InstallPipPackage $env:PYTHON setuptools
InstallPipPackage $env:PYTHON wheel
diff --git a/doc-requirements.txt b/doc-requirements.txt
new file mode 100644
index 000000000..2494b1d37
--- /dev/null
+++ b/doc-requirements.txt
@@ -0,0 +1,2 @@
+sphinx==3.5.3
+sphinx-issues==1.2.0
diff --git a/docs/conf.py b/docs/conf.py
index c20a57574..5ffc995f9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -44,7 +44,8 @@ extensions = [
'sphinx.ext.imgmath',
'sphinx.ext.todo',
'sphinx.ext.intersphinx',
- 'sphinx.ext.autodoc'
+ 'sphinx.ext.autodoc',
+ 'sphinx_issues', # if this is missing, pip install sphinx-issues
]
try: import rst2pdf
@@ -135,6 +136,9 @@ intersphinx_mapping = {'python': ('https://docs.python.org/3/', None)}
# The output image format. The default is 'png'. It should be either 'png' or 'svg'.
imgmath_image_format = "svg"
+# For sphinx-issues
+
+issues_github_path = "cython/cython"
# -- Options for HTML output ---------------------------------------------------
diff --git a/docs/examples/Cython Magics.ipynb b/docs/examples/Cython Magics.ipynb
index 0a8c8f56f..9bbf934c8 100644
--- a/docs/examples/Cython Magics.ipynb
+++ b/docs/examples/Cython Magics.ipynb
@@ -356,7 +356,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
- "You can similarly use the `-I/--include` flag to add include directories to the search path, and `-c/--compile-args` to add extra flags that are passed to Cython via the `extra_compile_args` of the distutils `Extension` class. Please see [the Cython docs on C library usage](http://docs.cython.org/src/tutorial/clibraries.html) for more details on the use of these flags."
+ "You can similarly use the `-I/--include` flag to add include directories to the search path, and `-c/--compile-args` to add extra flags that are passed to Cython via the `extra_compile_args` of the distutils `Extension` class. Please see [the Cython docs on C library usage](https://docs.cython.org/src/tutorial/clibraries.html) for more details on the use of these flags."
]
}
],
diff --git a/docs/examples/README.rst b/docs/examples/README.rst
index e246c96bc..f998f4f33 100644
--- a/docs/examples/README.rst
+++ b/docs/examples/README.rst
@@ -1,3 +1,5 @@
+:orphan:
+
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`.
diff --git a/docs/examples/userguide/external_C_code/platform_adaptation.pyx b/docs/examples/userguide/external_C_code/platform_adaptation.pyx
index 99953e29e..fa193f83d 100644
--- a/docs/examples/userguide/external_C_code/platform_adaptation.pyx
+++ b/docs/examples/userguide/external_C_code/platform_adaptation.pyx
@@ -1,6 +1,7 @@
cdef extern from *:
"""
#if defined(_WIN32) || defined(MS_WINDOWS) || defined(_MSC_VER)
+ #define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define myapp_sleep(m) Sleep(m)
#else
diff --git a/docs/index.rst b/docs/index.rst
index 7dc6ac525..0103d8d9f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -10,4 +10,6 @@ Also see the `Cython project homepage <https://cython.org/>`_.
src/quickstart/index
src/tutorial/index
src/userguide/index
+ src/reference/index
+ Contributing <CONTRIBUTING>
src/changes
diff --git a/docs/make.bat b/docs/make.bat
index fb25acc6a..3e719777d 100644
--- a/docs/make.bat
+++ b/docs/make.bat
@@ -56,7 +56,7 @@ if errorlevel 9009 (
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
- echo.http://sphinx-doc.org/
+ echo.https://sphinx-doc.org/
exit /b 1
)
diff --git a/docs/src/donating.rst b/docs/src/donating.rst
index 2be5f178f..3d12a8691 100644
--- a/docs/src/donating.rst
+++ b/docs/src/donating.rst
@@ -1,12 +1,13 @@
+:orphan:
+
🌷️ Thank you for your interest in supporting Cython! 🌷️
=========================================================
Managing, maintaining and advancing a project as large as Cython takes
-**a lot of time and dedication**. This is really a full-time job that
-is currently done by **Stefan Behnel**, paid by users just like you.
+**a lot of time and dedication**.
**Your support can make a difference**
-for improving a great tool that helps you every day!
+for a great tool that helps you every day!
Please consider signing a subscription for continuous project support via
@@ -19,5 +20,25 @@ or donating via
* `PayPal <https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HLS9JEYD4ETB6&source=url>`_
Note that PayPal takes 5 - 15% fees for small non-EUR payments,
-which is money that you pay without helping us.
-Consider signing up for a GitHub Sponsors subscription instead.
+which is money that *you pay without helping us*.
+Consider signing up for a GitHub Sponsors subscription instead,
+which is currently free of additional charges.
+
+
+Legal Notice for Donations
+--------------------------
+
+Any donation that you make to the Cython project is voluntary and
+is not a fee for any services, goods, or advantages. By making
+a donation to the Cython project, you acknowledge that we have the
+right to use the money you donate in any lawful way and for any
+lawful purpose we see fit and we are not obligated to disclose
+the way and purpose to any party unless required by applicable
+law. Although Cython is free software, to the best of our knowledge
+the Cython project does not have any tax exempt status. The Cython
+project is neither a registered non-profit corporation nor a
+registered charity in any country. Your donation may or may not
+be tax-deductible; please consult your tax advisor in this matter.
+We will not publish or disclose your name and/or e-mail address
+without your consent, unless required by applicable law. Your
+donation is non-refundable.
diff --git a/docs/src/quickstart/overview.rst b/docs/src/quickstart/overview.rst
index 05829b8ad..1a378e837 100644
--- a/docs/src/quickstart/overview.rst
+++ b/docs/src/quickstart/overview.rst
@@ -47,7 +47,7 @@ language.
The Cython compiler, https://cython.org/.
.. [IronPython] Jim Hugunin et al., https://archive.codeplex.com/?p=IronPython.
.. [Jython] J. Huginin, B. Warsaw, F. Bock, et al.,
- Jython: Python for the Java platform, http://www.jython.org.
+ Jython: Python for the Java platform, https://www.jython.org.
.. [PyPy] The PyPy Group, PyPy: a Python implementation written in Python,
https://pypy.org/.
.. [Pyrex] G. Ewing, Pyrex: C-Extensions for Python,
diff --git a/docs/src/reference/directives.rst b/docs/src/reference/directives.rst
index f527536a8..46d7fa9c4 100644
--- a/docs/src/reference/directives.rst
+++ b/docs/src/reference/directives.rst
@@ -1,3 +1,5 @@
+:orphan:
+
Compiler Directives
===================
diff --git a/docs/src/reference/extension_types.rst b/docs/src/reference/extension_types.rst
index ea26f38a0..3c5cc828d 100644
--- a/docs/src/reference/extension_types.rst
+++ b/docs/src/reference/extension_types.rst
@@ -1,3 +1,5 @@
+:orphan:
+
.. highlight:: cython
***************
diff --git a/docs/src/reference/language_basics.rst b/docs/src/reference/language_basics.rst
index bd8b1e38c..8d7cd0b06 100644
--- a/docs/src/reference/language_basics.rst
+++ b/docs/src/reference/language_basics.rst
@@ -1,3 +1,5 @@
+:orphan:
+
.. highlight:: cython
diff --git a/docs/src/tutorial/appendix.rst b/docs/src/tutorial/appendix.rst
index c76d6f6c3..82f225bbf 100644
--- a/docs/src/tutorial/appendix.rst
+++ b/docs/src/tutorial/appendix.rst
@@ -2,7 +2,7 @@ Appendix: Installing MinGW on Windows
=====================================
1. Download the MinGW installer from
- http://www.mingw.org/wiki/HOWTO_Install_the_MinGW_GCC_Compiler_Suite.
+ https://www.mingw.org/wiki/HOWTO_Install_the_MinGW_GCC_Compiler_Suite.
(As of this
writing, the download link is a bit difficult to find; it's under
"About" in the menu on the left-hand side). You want the file
@@ -32,7 +32,7 @@ Python 3.8+
-----------
Since Python 3.8, the search paths of DLL dependencies has been reset.
-(`changelog <https://docs.python.org/3/whatsnew/3.8.html#changes-in-the-python-api>`_)
+(`changelog <https://docs.python.org/3/whatsnew/3.8.html#bpo-36085-whatsnew>`_)
Only the system paths, the directory containing the DLL or PYD file
are searched for load-time dependencies.
diff --git a/docs/src/tutorial/clibraries.rst b/docs/src/tutorial/clibraries.rst
index ff0a7b9d3..08c491d36 100644
--- a/docs/src/tutorial/clibraries.rst
+++ b/docs/src/tutorial/clibraries.rst
@@ -24,7 +24,7 @@ decide to use its double ended queue implementation. To make the
handling easier, however, you decide to wrap it in a Python extension
type that can encapsulate all memory management.
-.. [CAlg] Simon Howard, C Algorithms library, http://c-algorithms.sourceforge.net/
+.. [CAlg] Simon Howard, C Algorithms library, https://fragglet.github.io/c-algorithms/
Defining external declarations
diff --git a/docs/src/tutorial/external.rst b/docs/src/tutorial/external.rst
index 42b1ed0c2..83ec75375 100644
--- a/docs/src/tutorial/external.rst
+++ b/docs/src/tutorial/external.rst
@@ -30,6 +30,8 @@ your code is being compiled with, you can do this:
.. literalinclude:: ../../examples/tutorial/external/py_version_hex.pyx
+.. _libc.math:
+
Cython also provides declarations for the C math library:
.. literalinclude:: ../../examples/tutorial/external/libc_sin.pyx
diff --git a/docs/src/tutorial/readings.rst b/docs/src/tutorial/readings.rst
index c419b3d72..80ed26e66 100644
--- a/docs/src/tutorial/readings.rst
+++ b/docs/src/tutorial/readings.rst
@@ -1,7 +1,7 @@
Further reading
===============
-The main documentation is located at http://docs.cython.org/. Some
+The main documentation is located at https://docs.cython.org/. Some
recent features might not have documentation written yet, in such
cases some notes can usually be found in the form of a Cython
Enhancement Proposal (CEP) on https://github.com/cython/cython/wiki/enhancements.
diff --git a/docs/src/userguide/extension_types.rst b/docs/src/userguide/extension_types.rst
index f8f7f4f70..e7f95a7ab 100644
--- a/docs/src/userguide/extension_types.rst
+++ b/docs/src/userguide/extension_types.rst
@@ -669,6 +669,8 @@ objects from memory. Clearing is implemented in the ``tp_clear`` slot.
As we just explained, it is sufficient that one object in the cycle
implements ``tp_clear``.
+.. _trashcan:
+
Enabling the deallocation trashcan
----------------------------------
@@ -965,7 +967,8 @@ C inline properties
Similar to Python property attributes, Cython provides a way to declare C-level
properties on external extension types. This is often used to shadow Python
attributes through faster C level data access, but can also be used to add certain
-functionality to existing types when using them from Cython.
+functionality to existing types when using them from Cython. The declarations
+must use `cdef inline`.
For example, the above ``complex`` type could also be declared like this:
diff --git a/docs/src/userguide/external_C_code.rst b/docs/src/userguide/external_C_code.rst
index c3b763c12..4b8ddd8a0 100644
--- a/docs/src/userguide/external_C_code.rst
+++ b/docs/src/userguide/external_C_code.rst
@@ -223,6 +223,38 @@ See also use of :ref:`external_extension_types`.
Note that in all the cases below, you refer to the type in Cython code simply
as :c:type:`Foo`, not ``struct Foo``.
+Pointers
+--------
+When interacting with a C-api there may be functions that require pointers as arguments.
+Pointers are variables that contain a memory address to another variable.
+
+For example::
+
+ cdef extern from "<my_lib.h>":
+ cdef void increase_by_one(int *my_var)
+
+This function takes a pointer to an integer as argument. Knowing the address of the
+integer allows the function to modify the value in place, so that the caller can see
+the changes afterwards. In order to get the address from an existing variable,
+use the ``&`` operator::
+
+ cdef int some_int = 42
+ cdef int *some_int_pointer = &some_int
+ increase_by_one(some_int_pointer)
+ # Or without creating the extra variable
+ increase_by_one(&some_int)
+ print(some_int) # prints 44 (== 42+1+1)
+
+If you want to manipulate the variable the pointer points to, you can access it by
+referencing its first element like you would in python ``my_pointer[0]``. For example::
+
+ cdef void increase_by_one(int *my_var):
+ my_var[0] += 1
+
+For a deeper introduction to pointers, you can read `this tutorial at tutorialspoint
+<https://www.tutorialspoint.com/cprogramming/c_pointers.htm>`_. For differences between
+Cython and C syntax for manipulating pointers, see :ref:`statements_and_expressions`.
+
Accessing Python/C API routines
---------------------------------
diff --git a/docs/src/userguide/glossary.rst b/docs/src/userguide/glossary.rst
index 9a9aab52b..1ccbb4408 100644
--- a/docs/src/userguide/glossary.rst
+++ b/docs/src/userguide/glossary.rst
@@ -1,10 +1,12 @@
.. glossary::
+Glossary
+========
+
Extension type
"Extension type" can refer to either a Cython class defined with ``cdef class`` or more generally to any Python type that is ultimately implemented as a native C struct (including the built-in types like `int` or `dict`).
- Dynamic allocation
- Heap allocation
+ Dynamic allocation or Heap allocation
A C variable allocated with ``malloc`` (in C) or ``new`` (in C++) is
`allocated dynamically/heap allocated <https://en.wikipedia.org/wiki/C_dynamic_memory_allocation>`_.
Its lifetime is until the user deletes it explicitly (with ``free`` in C or ``del`` in C++).
@@ -19,9 +21,9 @@
Python object
When using Python, the contents of every variable is a Python object
(including Cython extension types). Key features of Python objects are that
- they are passed _by reference_ and that their lifetime is _managed_ automatically
+ they are passed *by reference* and that their lifetime is *managed* automatically
so that they are destroyed when no more references exist to them.
- In Cython, they are distinct from C types, which are passed _by value_ and whose
+ In Cython, they are distinct from C types, which are passed *by value* and whose
lifetime is managed depending on whether they are allocated on the stack or heap.
To explicitly declare a Python object variable in Cython use ``cdef object abc``.
Internally in C, they are referred to as ``PyObject*``.
diff --git a/docs/src/userguide/language_basics.rst b/docs/src/userguide/language_basics.rst
index c422bddd6..402cd14ba 100644
--- a/docs/src/userguide/language_basics.rst
+++ b/docs/src/userguide/language_basics.rst
@@ -139,10 +139,11 @@ For example::
cdef list foo = []
-This requires an *exact* match of the class, it does not allow
-subclasses. This allows Cython to optimize code by accessing
-internals of the builtin class.
-For this kind of typing, Cython uses internally a C variable of type ``PyObject*``.
+This requires an *exact* match of the class, it does not allow subclasses.
+This allows Cython to optimize code by accessing internals of the builtin class,
+which is the main reason for declaring builtin types in the first place.
+
+For declared builtin types, Cython uses internally a C variable of type ``PyObject*``.
The Python types int, long, and float are not available for static
typing and instead interpreted as C ``int``, ``long``, and ``float``
respectively, as statically typing variables with these Python
diff --git a/docs/src/userguide/numpy_tutorial.rst b/docs/src/userguide/numpy_tutorial.rst
index a89cf86e2..f34b2a0da 100644
--- a/docs/src/userguide/numpy_tutorial.rst
+++ b/docs/src/userguide/numpy_tutorial.rst
@@ -61,7 +61,7 @@ Using Cython consists of these steps:
However there are several options to automate these steps:
-1. The `SAGE <http://sagemath.org>`_ mathematics software system provides
+1. The `SAGE <https://sagemath.org>`_ mathematics software system provides
excellent support for using Cython and NumPy from an interactive command
line or through a notebook interface (like
Maple/Mathematica). See `this documentation
diff --git a/docs/src/userguide/sharing_declarations.rst b/docs/src/userguide/sharing_declarations.rst
index 32cbee924..70e29e2b2 100644
--- a/docs/src/userguide/sharing_declarations.rst
+++ b/docs/src/userguide/sharing_declarations.rst
@@ -227,6 +227,8 @@ Some things to note about this example:
when you try to use them from a dependent package.
To prevent this, include ``zip_safe=False`` in the arguments to ``setup()``.
+.. _versioning:
+
Versioning
==========
diff --git a/docs/src/userguide/wrapping_CPlusPlus.rst b/docs/src/userguide/wrapping_CPlusPlus.rst
index eed01687f..1d8a25835 100644
--- a/docs/src/userguide/wrapping_CPlusPlus.rst
+++ b/docs/src/userguide/wrapping_CPlusPlus.rst
@@ -331,19 +331,27 @@ arguments) or by an explicit cast, e.g.:
The following coercions are available:
-+------------------+----------------+-----------------+
-| Python type => | *C++ type* | => Python type |
-+==================+================+=================+
-| bytes | std::string | bytes |
-+------------------+----------------+-----------------+
-| iterable | std::vector | list |
-+------------------+----------------+-----------------+
-| iterable | std::list | list |
-+------------------+----------------+-----------------+
-| iterable | std::set | set |
-+------------------+----------------+-----------------+
-| iterable (len 2) | std::pair | tuple (len 2) |
-+------------------+----------------+-----------------+
++------------------+------------------------+-----------------+
+| Python type => | *C++ type* | => Python type |
++==================+========================+=================+
+| bytes | std::string | bytes |
++------------------+------------------------+-----------------+
+| iterable | std::vector | list |
++------------------+------------------------+-----------------+
+| iterable | std::list | list |
++------------------+------------------------+-----------------+
+| iterable | std::set | set |
++------------------+------------------------+-----------------+
+| iterable | std::unordered_set | set |
++------------------+------------------------+-----------------+
+| mapping | std::map | dict |
++------------------+------------------------+-----------------+
+| mapping | std::unordered_map | dict |
++------------------+------------------------+-----------------+
+| iterable (len 2) | std::pair | tuple (len 2) |
++------------------+------------------------+-----------------+
+| complex | std::complex | complex |
++------------------+------------------------+-----------------+
All conversions create a new container and copy the data into it.
The items in the containers are converted to a corresponding type
diff --git a/pylintrc b/pylintrc
index a0d8d22fc..5785282fe 100644
--- a/pylintrc
+++ b/pylintrc
@@ -10,7 +10,7 @@
# Profiled execution.
profile=no
-# Add files or directories to the blacklist. They should be base names, not
+# Add files or directories to the ignorelist. They should be base names, not
# paths.
ignore=.git,.gitmarker
diff --git a/runtests.py b/runtests.py
index 174ca27b3..91f190951 100755
--- a/runtests.py
+++ b/runtests.py
@@ -438,12 +438,14 @@ VER_DEP_MODULES = {
'run.mod__spec__',
'run.pep526_variable_annotations', # typing module
'run.test_exceptions', # copied from Py3.7+
+ 'run.time_pxd', # _PyTime_GetSystemClock doesn't exist in 3.4
]),
}
INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]
CFLAGS = os.getenv('CFLAGS', '').split()
CCACHE = os.getenv('CYTHON_RUNTESTS_CCACHE', '').split()
+CDEFS = []
TEST_SUPPORT_DIR = 'testsupport'
BACKENDS = ['c', 'cpp']
@@ -609,7 +611,7 @@ class Stats(object):
if not self.test_times:
return
lines = ['Times:\n']
- for metric, t in sorted(self.test_times.items()):
+ for metric, t in sorted(self.test_times.items(), key=operator.itemgetter(1), reverse=True):
count = self.test_counts[metric]
top = self.top_tests[metric]
lines.append("%-12s: %8.2f sec (%4d, %6.3f / run) - slowest: %s\n" % (
@@ -1104,6 +1106,7 @@ class CythonCompileTestCase(unittest.TestCase):
build_extension.compiler = COMPILER
ext_compile_flags = CFLAGS[:]
+ ext_compile_defines = CDEFS[:]
if build_extension.compiler == 'mingw32':
ext_compile_flags.append('-Wno-format')
@@ -1118,6 +1121,7 @@ class CythonCompileTestCase(unittest.TestCase):
module,
sources=self.source_files(workdir, module, related_files),
extra_compile_args=ext_compile_flags,
+ define_macros=ext_compile_defines,
**extra_extension_args
)
@@ -1683,13 +1687,13 @@ def collect_doctests(path, module_prefix, suite, selectors, exclude_selectors):
return dirname not in ("Mac", "Distutils", "Plex", "Tempita")
def file_matches(filename):
filename, ext = os.path.splitext(filename)
- blacklist = ['libcython', 'libpython', 'test_libcython_in_gdb',
- 'TestLibCython']
+ excludelist = ['libcython', 'libpython', 'test_libcython_in_gdb',
+ 'TestLibCython']
return (ext == '.py' and not
'~' in filename and not
'#' in filename and not
filename.startswith('.') and not
- filename in blacklist)
+ filename in excludelist)
import doctest
for dirpath, dirnames, filenames in os.walk(path):
for dir in list(dirnames):
@@ -2237,14 +2241,16 @@ def main():
import multiprocessing
pool = multiprocessing.Pool(options.shard_count)
tasks = [(options, cmd_args, shard_num) for shard_num in range(options.shard_count)]
- errors = []
+ error_shards = []
+ failure_outputs = []
# NOTE: create process pool before time stamper thread to avoid forking issues.
total_time = time.time()
stats = Stats()
with time_stamper_thread(interval=keep_alive_interval):
- for shard_num, shard_stats, return_code in pool.imap_unordered(runtests_callback, tasks):
+ for shard_num, shard_stats, return_code, failure_output in pool.imap_unordered(runtests_callback, tasks):
if return_code != 0:
- errors.append(shard_num)
+ error_shards.append(shard_num)
+ failure_outputs.append(failure_output)
sys.stderr.write("FAILED (%s/%s)\n" % (shard_num, options.shard_count))
sys.stderr.write("ALL DONE (%s/%s)\n" % (shard_num, options.shard_count))
stats.update(shard_stats)
@@ -2252,14 +2258,16 @@ def main():
pool.join()
total_time = time.time() - total_time
sys.stderr.write("Sharded tests run in %d seconds (%.1f minutes)\n" % (round(total_time), total_time / 60.))
- if errors:
- sys.stderr.write("Errors for shards %s\n" % ", ".join([str(e) for e in errors]))
+ if error_shards:
+ sys.stderr.write("Errors found in shards %s\n" % ", ".join([str(e) for e in error_shards]))
+ for failure_output in zip(error_shards, failure_outputs):
+ sys.stderr.write("\nErrors from shard %s:\n%s" % failure_output)
return_code = 1
else:
return_code = 0
else:
with time_stamper_thread(interval=keep_alive_interval):
- _, stats, return_code = runtests(options, cmd_args, coverage)
+ _, stats, return_code, _ = runtests(options, cmd_args, coverage)
if coverage:
if options.shard_count > 1 and options.shard_num == -1:
@@ -2438,7 +2446,7 @@ def runtests(options, cmd_args, coverage=None):
build_in_temp=True,
pyxbuild_dir=os.path.join(WORKDIR, "support"))
sys.path.insert(0, os.path.split(libpath)[0])
- CFLAGS.append("-DCYTHON_REFNANNY=1")
+ CDEFS.append(('CYTHON_REFNANNY', '1'))
if options.limited_api:
CFLAGS.append("-DCYTHON_LIMITED_API=1")
@@ -2638,10 +2646,27 @@ def runtests(options, cmd_args, coverage=None):
import refnanny
sys.stderr.write("\n".join([repr(x) for x in refnanny.reflog]))
- if options.exit_ok:
- return options.shard_num, stats, 0
+ result_code = 0 if options.exit_ok else not result.wasSuccessful()
+
+ if xml_output_dir:
+ failure_output = ""
else:
- return options.shard_num, stats, not result.wasSuccessful()
+ failure_output = "".join(collect_failure_output(result))
+
+ return options.shard_num, stats, result_code, failure_output
+
+
+def collect_failure_output(result):
+ """Extract test error/failure output from a TextTestResult."""
+ failure_output = []
+ for flavour, errors in (("ERROR", result.errors), ("FAIL", result.failures)):
+ for test, err in errors:
+ failure_output.append("%s\n%s: %s\n%s\n%s\n" % (
+ result.separator1,
+ flavour, result.getDescription(test),
+ result.separator2,
+ err))
+ return failure_output
if __name__ == '__main__':
diff --git a/setup.cfg b/setup.cfg
index 791495a94..25db8b4bd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -37,3 +37,7 @@ omit = Test*
[bdist_wheel]
universal = 1
+[metadata]
+license_files =
+ LICENSE.txt
+ COPYING.txt
diff --git a/setup.py b/setup.py
index 528a92bb7..d9d98e66e 100755
--- a/setup.py
+++ b/setup.py
@@ -279,6 +279,7 @@ def run_build():
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
+ "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Programming Language :: C",
diff --git a/test-requirements-27.txt b/test-requirements-27.txt
new file mode 100644
index 000000000..a3ad0439e
--- /dev/null
+++ b/test-requirements-27.txt
@@ -0,0 +1,62 @@
+attrs==20.3.0
+backports-abc==0.5
+backports.functools-lru-cache==1.6.3
+backports.shutil-get-terminal-size==1.0.0
+bleach==3.3.0
+configparser==4.0.2
+contextlib2==0.6.0.post1
+coverage==5.5
+decorator==4.4.2
+defusedxml==0.7.1
+entrypoints==0.3
+enum34==1.1.10
+functools32==3.2.3.post2
+futures==3.3.0
+importlib-metadata==2.1.1
+ipaddress==1.0.23
+ipykernel==4.10.1
+ipython==5.10.0
+ipython-genutils==0.2.0
+ipywidgets==7.6.3
+Jinja2==2.11.3
+jsonschema==3.2.0
+jupyter==1.0.0
+jupyter-client==5.3.5
+jupyter-console==5.2.0
+jupyter-core==4.6.3
+line-profiler==3.1.0
+MarkupSafe==1.1.1
+mistune==0.8.4
+nbconvert==5.6.1
+nbformat==4.4.0
+notebook==5.7.10
+numpy==1.16.6
+packaging==20.9
+pandocfilters==1.4.3
+pathlib2==2.3.5
+pexpect==4.8.0
+pickleshare==0.7.5
+prometheus-client==0.10.0
+prompt-toolkit==1.0.18
+ptyprocess==0.7.0
+pycodestyle==2.7.0
+Pygments==2.5.2
+pyparsing==2.4.7
+pyrsistent==0.15.7
+python-dateutil==2.8.1
+pyzmq==16.0.4
+qtconsole==4.7.7
+QtPy==1.9.0
+scandir==1.10.0
+Send2Trash==1.5.0
+simplegeneric==0.8.1
+singledispatch==3.6.1
+six==1.15.0
+terminado==0.8.3
+testpath==0.4.4
+tornado==5.1.1
+traitlets==4.3.3
+wcwidth==0.2.5
+webencodings==0.5.1
+widgetsnbextension==3.5.1
+zipp==1.2.0
diff --git a/test-requirements-cpython.txt b/test-requirements-cpython.txt
index db74d13ce..2ab863eaf 100644
--- a/test-requirements-cpython.txt
+++ b/test-requirements-cpython.txt
@@ -2,3 +2,6 @@ jupyter
line_profiler
# transitive dependency of jupyter (17.0+ lacks wheels for Py3.4)
pyzmq<17
+pyrsistent<0.16
+qtconsole<5
+decorator<5
diff --git a/tests/buffers/bufaccess.pyx b/tests/buffers/bufaccess.pyx
index db36efe78..6b0b4ac30 100644
--- a/tests/buffers/bufaccess.pyx
+++ b/tests/buffers/bufaccess.pyx
@@ -13,8 +13,6 @@ from cpython.object cimport PyObject
from cpython.ref cimport Py_INCREF, Py_DECREF
cimport cython
-__test__ = {}
-
import sys
#import re
exclude = []#re.compile('object').search]
@@ -27,8 +25,7 @@ if getattr(sys, 'pypy_version_info', None) is not None:
def testcase(func):
for e in exclude:
if e(func.__name__):
- return func
- __test__[func.__name__] = func.__doc__
+ func.__doc__ = "" # disable the test
return func
diff --git a/tests/buffers/buffmt.pyx b/tests/buffers/buffmt.pyx
index 0aa0cb325..0a9757270 100644
--- a/tests/buffers/buffmt.pyx
+++ b/tests/buffers/buffmt.pyx
@@ -3,10 +3,6 @@ import struct
# Tests buffer format string parsing.
-__test__ = {}
-def testcase(func):
- __test__[func.__name__] = func.__doc__
- return func
from libc cimport stdlib
@@ -56,7 +52,6 @@ cdef class MockBuffer:
info.format = self.format
info.itemsize = self.itemsize
-@testcase
def _int(fmt):
"""
>>> _int("i")
@@ -78,14 +73,12 @@ def _int(fmt):
"""
cdef object[int] buf = MockBuffer(fmt, sizeof(int))
-@testcase
def _ulong(fmt):
"""
>>> _ulong("L")
"""
cdef object[unsigned long] buf = MockBuffer(fmt, sizeof(unsigned long))
-@testcase
def wrongsize():
"""
>>> wrongsize()
@@ -96,7 +89,6 @@ def wrongsize():
"""
cdef object[float] buf = MockBuffer("f", 1)
-@testcase
def _obj(fmt):
"""
>>> _obj("O")
@@ -151,7 +143,6 @@ cdef struct UnpackedStruct4:
char d
int e, f, g
-@testcase
def char3int(fmt):
"""
>>> char3int("ciii")
@@ -185,7 +176,6 @@ def char3int(fmt):
cdef object[Char3Int, ndim=1] buf = obj
-@testcase
def long_string(fmt):
"""
>>> long_string("90198s")
@@ -194,7 +184,6 @@ def long_string(fmt):
cdef object[LongString, ndim=1] buf = obj
-@testcase
def unpacked_struct(fmt):
"""
Native formats:
@@ -218,7 +207,6 @@ def unpacked_struct(fmt):
cdef struct ComplexTest:
ComplexFloat a, b, c
-@testcase
def complex_test(fmt):
"""
>>> complex_test("ZfZfZf")
@@ -236,7 +224,6 @@ def complex_test(fmt):
cdef object[ComplexTest] buf1 = obj
-@testcase
def alignment_string(fmt, exc=None):
"""
>>> alignment_string("@i")
@@ -258,7 +245,6 @@ def alignment_string(fmt, exc=None):
print "fail"
-@testcase
def int_and_long_are_same():
"""
>>> int_and_long_are_same()
@@ -273,7 +259,6 @@ cdef struct MixedComplex:
double real
float imag
-@testcase
def mixed_complex_struct():
"""
Triggering a specific execution path for this case.
@@ -311,7 +296,6 @@ cdef packed struct PartiallyPackedStruct2:
char b
int c
-@testcase
def packed_struct(fmt):
"""
Assuming int is four bytes:
@@ -334,7 +318,6 @@ def packed_struct(fmt):
"""
cdef object[PackedStruct] buf = MockBuffer(fmt, sizeof(PackedStruct))
-@testcase
def partially_packed_struct(fmt):
"""
Assuming int is four bytes:
@@ -362,7 +345,6 @@ def partially_packed_struct(fmt):
cdef object[PartiallyPackedStruct] buf = MockBuffer(
fmt, sizeof(PartiallyPackedStruct))
-@testcase
def partially_packed_struct_2(fmt):
"""
Assuming int is four bytes:
@@ -380,7 +362,7 @@ def partially_packed_struct_2(fmt):
Traceback (most recent call last):
...
ValueError: Buffer dtype mismatch; next field is at offset 8 but 5 expected
-
+
>>> partially_packed_struct_2("ccici")
Traceback (most recent call last):
...
@@ -398,7 +380,6 @@ cdef packed struct PackedStructWithCharArrays:
char[3] d
-@testcase
def packed_struct_with_strings(fmt):
"""
>>> packed_struct_with_strings("T{f:a:i:b:5s:c:3s:d:}")
@@ -430,7 +411,6 @@ ctypedef struct PackedStructWithNDArrays:
float d
-@testcase
def packed_struct_with_arrays(fmt):
"""
>>> packed_struct_with_arrays("T{(16)d:a:(16)d:b:d:c:}")
@@ -440,7 +420,6 @@ def packed_struct_with_arrays(fmt):
fmt, sizeof(PackedStructWithArrays))
-@testcase
def unpacked_struct_with_arrays(fmt):
"""
>>> if struct.calcsize('P') == 8: # 64 bit
@@ -453,7 +432,6 @@ def unpacked_struct_with_arrays(fmt):
fmt, sizeof(UnpackedStructWithArrays))
-@testcase
def packed_struct_with_ndarrays(fmt):
"""
>>> packed_struct_with_ndarrays("T{d:a:(2,2)d:b:f:c:f:d:}")
diff --git a/tests/build/common_include_dir.srctree b/tests/build/common_include_dir.srctree
index 8867c4621..0b3e4f36f 100644
--- a/tests/build/common_include_dir.srctree
+++ b/tests/build/common_include_dir.srctree
@@ -16,13 +16,18 @@ PYTHON fake_grep.py -c '#include "common/AddTraceback_impl_.*h"' c.c
import sys
from Cython.Build.Dependencies import cythonize
+import platform
+import os
from distutils.core import setup
+# os x on Travis specifically seems to crash with nthreads>0
+osx_on_travis = (platform.system() == "Darwin" and os.getenv("TRAVIS"))
+
# Test concurrent safety if multiprocessing is available.
# (In particular, TravisCI does not support spawning processes from tests.)
nthreads = 0
-if not hasattr(sys, 'pypy_version_info'):
+if not (hasattr(sys, 'pypy_version_info') or osx_on_travis):
try:
import multiprocessing
multiprocessing.Pool(2).close()
diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree
index 6a031e417..99649376a 100644
--- a/tests/build/cythonize_pep420_namespace.srctree
+++ b/tests/build/cythonize_pep420_namespace.srctree
@@ -10,7 +10,8 @@ from distutils.core import setup, Extension
setup(
ext_modules=cythonize([
Extension("nsp.m1.a", ["nsp/m1/a.pyx"]),
- Extension("nsp.m2.b", ["nsp/m2/b.pyx"])
+ Extension("nsp.m2.b", ["nsp/m2/b.pyx"]),
+ Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]),
]),
)
@@ -31,14 +32,28 @@ cdef class A:
######## nsp/m2/b.pyx ########
from nsp.m1.a cimport A
+from nsp.m3.c.d cimport D
cdef class B(A):
pass
+######## nsp/m3/__init__.py ########
+
+######## nsp/m3/c/d.pyx ########
+
+cdef class D:
+ pass
+
+######## nsp/m3/c/d.pxd ########
+
+cdef class D:
+ pass
+
######## runner.py ########
from nsp.m1.a import A
from nsp.m2.b import B
+from nsp.m3.c.d import D
a = A()
b = B()
diff --git a/tests/compile/cast_ctypedef_array_T518.pyx b/tests/compile/cast_ctypedef_array_T518.pyx
index a62f4cf4c..6a52374c3 100644
--- a/tests/compile/cast_ctypedef_array_T518.pyx
+++ b/tests/compile/cast_ctypedef_array_T518.pyx
@@ -1,4 +1,4 @@
-# ticket: 518
+# ticket: t518
# mode: compile
cdef extern from "cast_ctypedef_array_T518_helper.h":
diff --git a/tests/compile/cimport_package_module_T4.pyx b/tests/compile/cimport_package_module_T4.pyx
index 28403f122..717f0bf8f 100644
--- a/tests/compile/cimport_package_module_T4.pyx
+++ b/tests/compile/cimport_package_module_T4.pyx
@@ -1,4 +1,4 @@
-# ticket: 4
+# ticket: t4
# mode: compile
from a cimport b
diff --git a/tests/compile/cimportfrom_T248.pyx b/tests/compile/cimportfrom_T248.pyx
index 13796baf1..1be252f3c 100644
--- a/tests/compile/cimportfrom_T248.pyx
+++ b/tests/compile/cimportfrom_T248.pyx
@@ -1,4 +1,4 @@
-# ticket: 248
+# ticket: t248
# mode: compile
from ewing8 cimport (Foo,
diff --git a/tests/compile/complex_annotations.pyx b/tests/compile/complex_annotations.pyx
new file mode 100644
index 000000000..5d95611ac
--- /dev/null
+++ b/tests/compile/complex_annotations.pyx
@@ -0,0 +1,7 @@
+# mode: compile
+
+# Complex numbers defined in annotations weren't having their utility code imported directly
+# leading to compile-errors that the type wasn't defined. The test is intentionally minimal since
+# anything more thorough ends up creating the utility code
+cdef f(x: complex):
+ pass
diff --git a/tests/compile/complex_decorators.pyx b/tests/compile/complex_decorators.pyx
new file mode 100644
index 000000000..e8d65244d
--- /dev/null
+++ b/tests/compile/complex_decorators.pyx
@@ -0,0 +1,10 @@
+# mode: compile
+
+cimport cython
+
+# Complex numbers defined in "cython.locals" weren't having their utility code imported directly
+# leading to compile-errors that the type wasn't defined. The test is intentionally minimal since
+# anything more thorough ends up creating the utility code
+@cython.locals(x=complex)
+cdef f(x):
+ pass
diff --git a/tests/compile/cpp_templates.pyx b/tests/compile/cpp_templates.pyx
index cab981e38..7952a1610 100644
--- a/tests/compile/cpp_templates.pyx
+++ b/tests/compile/cpp_templates.pyx
@@ -1,6 +1,6 @@
# tag: cpp
# mode: compile
-# ticket: 767
+# ticket: t767
cdef extern from "templates.h":
cdef cppclass TemplateTest1[T]:
diff --git a/tests/compile/cpp_templates_nested.pyx b/tests/compile/cpp_templates_nested.pyx
new file mode 100644
index 000000000..3466389f5
--- /dev/null
+++ b/tests/compile/cpp_templates_nested.pyx
@@ -0,0 +1,18 @@
+# tag: cpp
+# mode: compile
+
+from libcpp.vector cimport vector
+
+cdef extern from *:
+ cdef cppclass Foo[T]:
+ pass
+
+ cdef cppclass Bar:
+ pass
+
+cdef vector[vector[int]] a
+cdef vector[vector[const int]] b
+cdef vector[vector[vector[int]]] c
+cdef vector[vector[vector[const int]]] d
+cdef Foo[Foo[Bar]] e
+cdef Foo[Foo[const Bar]] f
diff --git a/tests/compile/ctypedef_public_class_T355.pyx b/tests/compile/ctypedef_public_class_T355.pyx
index 505f9d67f..ceb2d65e4 100644
--- a/tests/compile/ctypedef_public_class_T355.pyx
+++ b/tests/compile/ctypedef_public_class_T355.pyx
@@ -1,4 +1,4 @@
-# ticket: 355
+# ticket: t355
# mode: compile
ctypedef public class Time [type MyTime_Type, object MyTimeObject]:
diff --git a/tests/compile/ellipsis_T488.pyx b/tests/compile/ellipsis_T488.pyx
index d90d21634..804b18497 100644
--- a/tests/compile/ellipsis_T488.pyx
+++ b/tests/compile/ellipsis_T488.pyx
@@ -1,4 +1,4 @@
-# ticket: 488
+# ticket: t488
# mode: compile
#from ... import foo
diff --git a/tests/compile/weakref_T276.pyx b/tests/compile/weakref_T276.pyx
index d56f67303..7fbc52819 100644
--- a/tests/compile/weakref_T276.pyx
+++ b/tests/compile/weakref_T276.pyx
@@ -1,4 +1,4 @@
-# ticket: 276
+# ticket: t276
# mode: compile
__doc__ = u"""
diff --git a/tests/errors/bufaccess_noassignT444.pyx b/tests/errors/bufaccess_noassignT444.pyx
index 44d2ebd0b..c618106fb 100644
--- a/tests/errors/bufaccess_noassignT444.pyx
+++ b/tests/errors/bufaccess_noassignT444.pyx
@@ -1,4 +1,4 @@
-# ticket: 444
+# ticket: t444
# mode: error
def test():
diff --git a/tests/errors/buffertypedef_T117.pyx b/tests/errors/buffertypedef_T117.pyx
index d88a3895b..cefa79939 100644
--- a/tests/errors/buffertypedef_T117.pyx
+++ b/tests/errors/buffertypedef_T117.pyx
@@ -1,4 +1,4 @@
-# ticket: 117
+# ticket: t117
# mode: error
ctypedef object[float] mybuffer
diff --git a/tests/errors/callingnonexisting_T307.pyx b/tests/errors/callingnonexisting_T307.pyx
index e9409fcab..ac767e581 100644
--- a/tests/errors/callingnonexisting_T307.pyx
+++ b/tests/errors/callingnonexisting_T307.pyx
@@ -1,4 +1,4 @@
-# ticket: 307
+# ticket: t307
# mode: error
nonexisting(3, with_kw_arg=4)
diff --git a/tests/errors/cdef_class_properties_decorated.pyx b/tests/errors/cdef_class_properties_decorated.pyx
index 7485d8891..f796b7128 100644
--- a/tests/errors/cdef_class_properties_decorated.pyx
+++ b/tests/errors/cdef_class_properties_decorated.pyx
@@ -1,5 +1,5 @@
# mode: error
-# ticket: 264
+# ticket: t264
# tag: property, decorator
diff --git a/tests/errors/cdef_members_T517.pyx b/tests/errors/cdef_members_T517.pyx
index 9bd3b111c..34bfd79fd 100644
--- a/tests/errors/cdef_members_T517.pyx
+++ b/tests/errors/cdef_members_T517.pyx
@@ -1,4 +1,4 @@
-# ticket: 517
+# ticket: t517
# mode: error
ctypedef void* VoidP
diff --git a/tests/errors/compile_time_unraisable_T370.pyx b/tests/errors/compile_time_unraisable_T370.pyx
index 963f280fb..d22f0c6c0 100644
--- a/tests/errors/compile_time_unraisable_T370.pyx
+++ b/tests/errors/compile_time_unraisable_T370.pyx
@@ -1,4 +1,4 @@
-# ticket: 370
+# ticket: t370
# mode: error
cdef int raiseit():
diff --git a/tests/errors/cpdef_vars.pyx b/tests/errors/cpdef_vars.pyx
new file mode 100644
index 000000000..f356decfc
--- /dev/null
+++ b/tests/errors/cpdef_vars.pyx
@@ -0,0 +1,24 @@
+# tag: warnings
+
+cpdef str a = "123"
+cpdef b = 2
+
+cdef class C:
+ cpdef float c
+
+def func():
+ """
+ >>> c = func()
+ >>> isinstance(c, C) or c
+ True
+ """
+ cpdef d = C()
+ return d
+
+
+_WARNINGS = """
+3:6: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+4:6: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+7:10: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+15:10: cpdef variables will not be supported in Cython 3; currently they are no different from cdef variables
+"""
diff --git a/tests/errors/declareafteruse_T158.pyx b/tests/errors/declareafteruse_T158.pyx
index 34e5f097e..a6ff6da13 100644
--- a/tests/errors/declareafteruse_T158.pyx
+++ b/tests/errors/declareafteruse_T158.pyx
@@ -1,4 +1,4 @@
-# ticket: 158
+# ticket: t158
# mode: error
def mult_decl_test():
@@ -52,26 +52,19 @@ cdef int *baz
print var[0][0]
cdef unsigned long long[100][100] var
-# in 0.11.1 these are warnings
-FUTURE_ERRORS = u"""
-6:13: cdef variable 's' declared after it is used
-6:16: cdef variable 'vv' declared after it is used
-11:14: cdef variable 'i' declared after it is used
-17:14: cdef variable 'i' declared after it is used
-23:14: cdef variable 'i' declared after it is used
-26:9: cdef variable 's' declared after it is used
-32:17: cdef variable 't' declared after it is used
-36:13: cdef variable 'r' declared after it is used
-42:17: cdef variable 't' declared after it is used
-49:10: cdef variable 'baz' declared after it is used
-52:24: cdef variable 'var' declared after it is used
-"""
-
-syntax error
-
_ERRORS = u"""
-42:17: cdef variable 't' declared after it is used
-49:10: cdef variable 'baz' declared after it is used
-52:24: cdef variable 'var' declared after it is used
-70:7: Syntax error in simple statement list
+5:17: local variable 'vv' referenced before assignment
+6:17: local variable 's' referenced before assignment
+7:13: cdef variable 's' declared after it is used
+7:16: cdef variable 'vv' declared after it is used
+12:14: cdef variable 'i' declared after it is used
+18:14: cdef variable 'i' declared after it is used
+24:14: cdef variable 'i' declared after it is used
+27:9: cdef variable 's' declared after it is used
+33:17: cdef variable 't' declared after it is used
+43:17: cdef variable 't' declared after it is used
+50:10: cdef variable 'baz' declared after it is used
+53:34: cdef variable 'var' declared after it is used
"""
+# FIXME not detected
+#37:13: cdef variable 'r' declared after it is used
diff --git a/tests/errors/e2_packedstruct_T290.pyx b/tests/errors/e2_packedstruct_T290.pyx
index 1a0f40f18..084b36d71 100644
--- a/tests/errors/e2_packedstruct_T290.pyx
+++ b/tests/errors/e2_packedstruct_T290.pyx
@@ -1,4 +1,4 @@
-# ticket: 290
+# ticket: t290
# mode: error
cdef packed foo:
diff --git a/tests/errors/e_cdef_keywords_T241.pyx b/tests/errors/e_cdef_keywords_T241.pyx
index 87524ebdd..28a2783fe 100644
--- a/tests/errors/e_cdef_keywords_T241.pyx
+++ b/tests/errors/e_cdef_keywords_T241.pyx
@@ -1,4 +1,4 @@
-# ticket: 241
+# ticket: t241
# mode: error
cdef some_function(x, y):
diff --git a/tests/errors/e_decorators.pyx b/tests/errors/e_decorators.pyx
index 5abc1fc29..33ef2355d 100644
--- a/tests/errors/e_decorators.pyx
+++ b/tests/errors/e_decorators.pyx
@@ -1,13 +1,12 @@
# mode: error
-_ERRORS = u"""
-4:4 Expected a newline after decorator
-"""
-
-
class A:
pass
@A().a
def f():
pass
+
+_ERRORS = u"""
+6:4: Expected a newline after decorator
+"""
diff --git a/tests/errors/e_tuple_args_T692.py b/tests/errors/e_tuple_args_T692.py
index 6b8dc73d6..3ca30519b 100644
--- a/tests/errors/e_tuple_args_T692.py
+++ b/tests/errors/e_tuple_args_T692.py
@@ -1,4 +1,4 @@
-# ticket: 692
+# ticket: t692
# mode: error
def func((a, b)):
diff --git a/tests/errors/fused_types.pyx b/tests/errors/fused_types.pyx
index 13ef8784e..378ac5506 100644
--- a/tests/errors/fused_types.pyx
+++ b/tests/errors/fused_types.pyx
@@ -99,6 +99,7 @@ _ERRORS = u"""
37:6: Invalid base type for memoryview slice: int *
40:0: Fused lambdas not allowed
43:5: Fused types not allowed here
+43:21: cdef variable 'x' declared after it is used
46:9: Fused types not allowed here
61:0: Invalid use of fused types, type cannot be specialized
61:29: ambiguous overloaded method
diff --git a/tests/errors/missing_baseclass_in_predecl_T262.pyx b/tests/errors/missing_baseclass_in_predecl_T262.pyx
index ece07b155..907f072f5 100644
--- a/tests/errors/missing_baseclass_in_predecl_T262.pyx
+++ b/tests/errors/missing_baseclass_in_predecl_T262.pyx
@@ -1,4 +1,4 @@
-# ticket: 262
+# ticket: t262
# mode: error
cdef class Album
diff --git a/tests/errors/missing_self_in_cpdef_method_T156.pyx b/tests/errors/missing_self_in_cpdef_method_T156.pyx
index 21241a221..e8b0c5369 100644
--- a/tests/errors/missing_self_in_cpdef_method_T156.pyx
+++ b/tests/errors/missing_self_in_cpdef_method_T156.pyx
@@ -1,4 +1,4 @@
-# ticket: 156
+# ticket: t156
# mode: error
cdef class B:
diff --git a/tests/errors/missing_self_in_cpdef_method_T165.pyx b/tests/errors/missing_self_in_cpdef_method_T165.pyx
index 6a95922d5..89763cd2a 100644
--- a/tests/errors/missing_self_in_cpdef_method_T165.pyx
+++ b/tests/errors/missing_self_in_cpdef_method_T165.pyx
@@ -1,4 +1,4 @@
-# ticket: 165
+# ticket: t165
# mode: error
cdef class A:
diff --git a/tests/errors/notcimportedT418.pyx b/tests/errors/notcimportedT418.pyx
index 980d66555..c2821fb83 100644
--- a/tests/errors/notcimportedT418.pyx
+++ b/tests/errors/notcimportedT418.pyx
@@ -1,4 +1,4 @@
-# ticket: 418
+# ticket: t418
# mode: error
import somemod.child
diff --git a/tests/errors/pxd_cdef_class_declaration_T286.pyx b/tests/errors/pxd_cdef_class_declaration_T286.pyx
index 0c968f701..b1a8bc844 100644
--- a/tests/errors/pxd_cdef_class_declaration_T286.pyx
+++ b/tests/errors/pxd_cdef_class_declaration_T286.pyx
@@ -1,4 +1,4 @@
-# ticket: 286
+# ticket: t286
# mode: error
cdef class A:
diff --git a/tests/errors/pyobjcastdisallow_T313.pyx b/tests/errors/pyobjcastdisallow_T313.pyx
index 5048719d8..30973380f 100644
--- a/tests/errors/pyobjcastdisallow_T313.pyx
+++ b/tests/errors/pyobjcastdisallow_T313.pyx
@@ -1,4 +1,4 @@
-# ticket: 313
+# ticket: t313
# mode: error
a = 3
diff --git a/tests/errors/return_outside_function_T135.pyx b/tests/errors/return_outside_function_T135.pyx
index d7432ca50..4788c2a72 100644
--- a/tests/errors/return_outside_function_T135.pyx
+++ b/tests/errors/return_outside_function_T135.pyx
@@ -1,5 +1,5 @@
# cython: remove_unreachable=False
-# ticket: 135
+# ticket: t135
# mode: error
def _runtime_True():
diff --git a/tests/errors/typoT304.pyx b/tests/errors/typoT304.pyx
index 7c736c898..2de5573d4 100644
--- a/tests/errors/typoT304.pyx
+++ b/tests/errors/typoT304.pyx
@@ -1,4 +1,4 @@
-# ticket: 304
+# ticket: t304
# mode: error
def f():
diff --git a/tests/errors/uninitialized_lhs.pyx b/tests/errors/uninitialized_lhs.pyx
index 5d5ece854..8550761a4 100644
--- a/tests/errors/uninitialized_lhs.pyx
+++ b/tests/errors/uninitialized_lhs.pyx
@@ -1,7 +1,7 @@
# cython: warn.maybe_uninitialized=True
# mode: error
# tag: werror
-# ticket: 739
+# ticket: t739
def index_lhs(a):
cdef object idx
diff --git a/tests/memoryview/memoryview.pyx b/tests/memoryview/memoryview.pyx
index 79b5ac978..273a1fa68 100644
--- a/tests/memoryview/memoryview.pyx
+++ b/tests/memoryview/memoryview.pyx
@@ -157,6 +157,7 @@ def assignmvs():
cdef int[:] mv3
mv1 = array((10,), itemsize=sizeof(int), format='i')
mv2 = mv1
+ mv1 = mv1
mv1 = mv2
mv3 = mv2
diff --git a/tests/memoryview/memoryviewattrs.pyx b/tests/memoryview/memoryviewattrs.pyx
index 66bc9da56..7322424c3 100644
--- a/tests/memoryview/memoryviewattrs.pyx
+++ b/tests/memoryview/memoryviewattrs.pyx
@@ -1,13 +1,6 @@
# mode: run
# tag: numpy
-__test__ = {}
-
-def testcase(func):
- __test__[func.__name__] = func.__doc__
- return func
-
-
cimport cython
from cython.view cimport array
@@ -15,7 +8,6 @@ import numpy as np
cimport numpy as np
-@testcase
def test_shape_stride_suboffset():
u'''
>>> test_shape_stride_suboffset()
@@ -49,7 +41,6 @@ def test_shape_stride_suboffset():
print c_contig.suboffsets[0], c_contig.suboffsets[1], c_contig.suboffsets[2]
-@testcase
def test_copy_to():
u'''
>>> test_copy_to()
@@ -72,7 +63,6 @@ def test_copy_to():
print ' '.join(str(to_data[i]) for i in range(2*2*2))
-@testcase
def test_overlapping_copy():
"""
>>> test_overlapping_copy()
@@ -88,7 +78,6 @@ def test_overlapping_copy():
assert slice[i] == 10 - 1 - i
-@testcase
def test_copy_return_type():
"""
>>> test_copy_return_type()
@@ -103,7 +92,6 @@ def test_copy_return_type():
print(f_contig[2, 2])
-@testcase
def test_partly_overlapping():
"""
>>> test_partly_overlapping()
@@ -119,7 +107,6 @@ def test_partly_overlapping():
for i in range(5):
assert slice2[i] == i + 4
-@testcase
@cython.nonecheck(True)
def test_nonecheck1():
u'''
@@ -131,7 +118,6 @@ def test_nonecheck1():
cdef int[:,:,:] uninitialized
print uninitialized.is_c_contig()
-@testcase
@cython.nonecheck(True)
def test_nonecheck2():
u'''
@@ -143,7 +129,6 @@ def test_nonecheck2():
cdef int[:,:,:] uninitialized
print uninitialized.is_f_contig()
-@testcase
@cython.nonecheck(True)
def test_nonecheck3():
u'''
@@ -155,7 +140,6 @@ def test_nonecheck3():
cdef int[:,:,:] uninitialized
uninitialized.copy()
-@testcase
@cython.nonecheck(True)
def test_nonecheck4():
u'''
@@ -167,7 +151,6 @@ def test_nonecheck4():
cdef int[:,:,:] uninitialized
uninitialized.copy_fortran()
-@testcase
@cython.nonecheck(True)
def test_nonecheck5():
u'''
@@ -179,7 +162,6 @@ def test_nonecheck5():
cdef int[:,:,:] uninitialized
uninitialized._data
-@testcase
def test_copy_mismatch():
u'''
>>> test_copy_mismatch()
@@ -193,7 +175,6 @@ def test_copy_mismatch():
mv1[...] = mv2
-@testcase
def test_is_contiguous():
u"""
>>> test_is_contiguous()
@@ -222,7 +203,6 @@ def test_is_contiguous():
print 'strided', strided[::2].is_c_contig()
-@testcase
def call():
u'''
>>> call()
@@ -265,7 +245,6 @@ def call():
assert len(mv3) == 3
-@testcase
def two_dee():
u'''
>>> two_dee()
@@ -313,7 +292,6 @@ def two_dee():
print (<long*>mv3._data)[0] , (<long*>mv3._data)[1] , (<long*>mv3._data)[2] , (<long*>mv3._data)[3]
-@testcase
def fort_two_dee():
u'''
>>> fort_two_dee()
diff --git a/tests/memoryview/memslice.pyx b/tests/memoryview/memslice.pyx
index 639b1f3dc..d68ee43fe 100644
--- a/tests/memoryview/memslice.pyx
+++ b/tests/memoryview/memslice.pyx
@@ -1159,9 +1159,21 @@ def basic_struct(MyStruct[:] buf):
"""
See also buffmt.pyx
- >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)])) # , writable=False))
+ >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
1 2 3 4 5
- >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii")) # , writable=False))
+ >>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii"))
+ 1 2 3 4 5
+ """
+ print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e
+
+@testcase
+def const_struct(const MyStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False))
+ 1 2 3 4 5
+ >>> const_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii", writable=False))
1 2 3 4 5
"""
print buf[0].a, buf[0].b, buf[0].c, buf[0].d, buf[0].e
@@ -1171,9 +1183,21 @@ def nested_struct(NestedStruct[:] buf):
"""
See also buffmt.pyx
- >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) # , writable=False))
+ >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
+ 1 2 3 4 5
+ >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i"))
+ 1 2 3 4 5
+ """
+ print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z
+
+@testcase
+def const_nested_struct(const NestedStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False))
1 2 3 4 5
- >>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i")) # , writable=False))
+ >>> const_nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i", writable=False))
1 2 3 4 5
"""
print buf[0].x.a, buf[0].x.b, buf[0].y.a, buf[0].y.b, buf[0].z
@@ -1183,11 +1207,26 @@ def packed_struct(PackedStruct[:] buf):
"""
See also buffmt.pyx
- >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)])) # , writable=False))
+ >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)]))
+ 1 2
+ >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}"))
+ 1 2
+ >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}"))
+ 1 2
+
+ """
+ print buf[0].a, buf[0].b
+
+@testcase
+def const_packed_struct(const PackedStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], writable=False))
1 2
- >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}")) # , writable=False))
+ >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}", writable=False))
1 2
- >>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}")) # , writable=False))
+ >>> const_packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}", writable=False))
1 2
"""
@@ -1198,11 +1237,26 @@ def nested_packed_struct(NestedPackedStruct[:] buf):
"""
See also buffmt.pyx
- >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)])) # , writable=False))
+ >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
+ 1 2 3 4 5
+ >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i"))
+ 1 2 3 4 5
+ >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i"))
+ 1 2 3 4 5
+ """
+ print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c
+
+
+@testcase
+def const_nested_packed_struct(const NestedPackedStruct[:] buf):
+ """
+ See also buffmt.pyx
+
+ >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], writable=False))
1 2 3 4 5
- >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i")) # , writable=False))
+ >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i", writable=False))
1 2 3 4 5
- >>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i")) # , writable=False))
+ >>> const_nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i", writable=False))
1 2 3 4 5
"""
print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c
diff --git a/tests/memoryview/numpy_memoryview.pyx b/tests/memoryview/numpy_memoryview.pyx
index 0d6f9e12f..6860fafeb 100644
--- a/tests/memoryview/numpy_memoryview.pyx
+++ b/tests/memoryview/numpy_memoryview.pyx
@@ -17,6 +17,10 @@ include "../buffers/mockbuffers.pxi"
ctypedef np.int32_t dtype_t
+IS_PYPY = hasattr(sys, 'pypy_version_info')
+NUMPY_VERSION = tuple(int(v) for v in np.__version__.split('.')[:2])
+print(NUMPY_VERSION)
+
def get_array():
# We need to type our array to get a __pyx_get_buffer() that typechecks
# for np.ndarray and calls __getbuffer__ in numpy.pxd
@@ -32,22 +36,13 @@ def ae(*args):
if x != args[0]:
raise AssertionError(args)
-__test__ = {}
-
-def testcase(f):
- __test__[f.__name__] = f.__doc__
- return f
-
-def testcase_numpy_1_5(f):
- major, minor, *rest = np.__version__.split('.')
- if (int(major), int(minor)) >= (1, 5):
- __test__[f.__name__] = f.__doc__
+def testcase_no_pypy(f, _is_pypy=hasattr(sys, "pypy_version_info")):
+ if _is_pypy:
+ f.__doc__ = "" # disable the tests
return f
-
def gc_collect_if_required():
- major, minor, *rest = np.__version__.split('.')
- if (int(major), int(minor)) >= (1, 14):
+ if NUMPY_VERSION >= (1, 14) or IS_PYPY:
import gc
gc.collect()
@@ -56,7 +51,6 @@ def gc_collect_if_required():
### Test slicing memoryview slices
#
-@testcase
def test_partial_slicing(array):
"""
>>> test_partial_slicing(a)
@@ -72,7 +66,6 @@ def test_partial_slicing(array):
ae(b.strides[0], c.strides[0], obj.strides[0])
ae(b.strides[1], c.strides[1], obj.strides[1])
-@testcase
def test_ellipsis(array):
"""
>>> test_ellipsis(a)
@@ -114,7 +107,6 @@ def test_ellipsis(array):
#
### Test slicing memoryview objects
#
-@testcase
def test_partial_slicing_memoryview(array):
"""
>>> test_partial_slicing_memoryview(a)
@@ -131,7 +123,6 @@ def test_partial_slicing_memoryview(array):
ae(b.strides[0], c.strides[0], obj.strides[0])
ae(b.strides[1], c.strides[1], obj.strides[1])
-@testcase
def test_ellipsis_memoryview(array):
"""
>>> test_ellipsis_memoryview(a)
@@ -172,7 +163,6 @@ def test_ellipsis_memoryview(array):
ae(e.strides[0], e_obj.strides[0])
-@testcase
def test_transpose():
"""
>>> test_transpose()
@@ -203,7 +193,6 @@ def test_transpose():
print a[3, 2], a.T[2, 3], a_obj[3, 2], a_obj.T[2, 3], numpy_obj[3, 2], numpy_obj.T[2, 3]
-@testcase
def test_transpose_type(a):
"""
>>> a = np.zeros((5, 10), dtype=np.float64)
@@ -216,12 +205,8 @@ def test_transpose_type(a):
print m_transpose[6, 4]
-@testcase_numpy_1_5
def test_numpy_like_attributes(cyarray):
"""
- For some reason this fails in numpy 1.4, with shape () and strides (40, 8)
- instead of 20, 4 on my machine. Investigate this.
-
>>> cyarray = create_array(shape=(8, 5), mode="c")
>>> test_numpy_like_attributes(cyarray)
>>> test_numpy_like_attributes(cyarray.memview)
@@ -237,7 +222,6 @@ def test_numpy_like_attributes(cyarray):
cdef int[:, :] mslice = numarray
assert (<object> mslice).base is numarray
-@testcase_numpy_1_5
def test_copy_and_contig_attributes(a):
"""
>>> a = np.arange(20, dtype=np.int32).reshape(5, 4)
@@ -274,7 +258,7 @@ def build_numarray(array array):
def index(array array):
print build_numarray(array)[3, 2]
-@testcase_numpy_1_5
+@testcase_no_pypy
def test_coerce_to_numpy():
"""
Test coercion to NumPy arrays, especially with automatically
@@ -355,6 +339,7 @@ def test_coerce_to_numpy():
'e': 800,
}
+
smallstructs[idx] = { 'a': 600, 'b': 700 }
nestedstructs[idx] = {
@@ -412,7 +397,7 @@ def test_coerce_to_numpy():
index(<td_h_ushort[:4, :5]> <td_h_ushort *> h_ushorts)
-@testcase_numpy_1_5
+@testcase_no_pypy
def test_memslice_getbuffer():
"""
>>> test_memslice_getbuffer(); gc_collect_if_required()
@@ -451,7 +436,6 @@ cdef packed struct StructArray:
int a[4]
signed char b[5]
-@testcase_numpy_1_5
def test_memslice_structarray(data, dtype):
"""
>>> def b(s): return s.encode('ascii')
@@ -507,7 +491,6 @@ def test_memslice_structarray(data, dtype):
print myslice[i].a[j]
print myslice[i].b.decode('ASCII')
-@testcase_numpy_1_5
def test_structarray_errors(StructArray[:] a):
"""
>>> dtype = np.dtype([('a', '4i'), ('b', '5b')])
@@ -554,7 +537,6 @@ def stringstructtest(StringStruct[:] view):
def stringtest(String[:] view):
pass
-@testcase_numpy_1_5
def test_string_invalid_dims():
"""
>>> def b(s): return s.encode('ascii')
@@ -575,7 +557,6 @@ ctypedef struct AttributesStruct:
float attrib2
StringStruct attrib3
-@testcase_numpy_1_5
def test_struct_attributes():
"""
>>> test_struct_attributes()
@@ -631,7 +612,6 @@ cdef class SuboffsetsNoStridesBuffer(Buffer):
getbuffer(self, info)
info.suboffsets = self._shape
-@testcase
def test_null_strides(Buffer buffer_obj):
"""
>>> test_null_strides(Buffer())
@@ -651,7 +631,6 @@ def test_null_strides(Buffer buffer_obj):
assert m2[i, j] == buffer_obj.m[i, j], (i, j, m2[i, j], buffer_obj.m[i, j])
assert m3[i, j] == buffer_obj.m[i, j]
-@testcase
def test_null_strides_error(buffer_obj):
"""
>>> test_null_strides_error(Buffer())
@@ -725,7 +704,6 @@ ctypedef struct SameTypeAfterArraysStructSimple:
double b[16]
double c
-@testcase
def same_type_after_arrays_simple():
"""
>>> same_type_after_arrays_simple()
@@ -747,7 +725,6 @@ ctypedef struct SameTypeAfterArraysStructComposite:
double h[4]
int i
-@testcase
def same_type_after_arrays_composite():
"""
>>> same_type_after_arrays_composite() if sys.version_info[:2] >= (3, 5) else None
diff --git a/tests/run/always_allow_keywords_T295.pyx b/tests/run/always_allow_keywords_T295.pyx
index aabae5b36..8e6e07739 100644
--- a/tests/run/always_allow_keywords_T295.pyx
+++ b/tests/run/always_allow_keywords_T295.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 295
+# ticket: t295
cimport cython
diff --git a/tests/run/args_unpacking_in_closure_T658.pyx b/tests/run/args_unpacking_in_closure_T658.pyx
index 98b57743b..b52d689c9 100644
--- a/tests/run/args_unpacking_in_closure_T658.pyx
+++ b/tests/run/args_unpacking_in_closure_T658.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 658
+# ticket: t658
def outer(int x, *args, **kwargs):
"""
diff --git a/tests/run/argument_unpacking_closure_T736.py b/tests/run/argument_unpacking_closure_T736.py
index 6c83d7026..80c824417 100644
--- a/tests/run/argument_unpacking_closure_T736.py
+++ b/tests/run/argument_unpacking_closure_T736.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 736
+# ticket: t736
# tag: default arguments, closure
def default_args_for_closure(a=1, b=2):
diff --git a/tests/run/arithmetic_analyse_types.pyx b/tests/run/arithmetic_analyse_types.pyx
index 7d5e41666..c8c7f7ac8 100644
--- a/tests/run/arithmetic_analyse_types.pyx
+++ b/tests/run/arithmetic_analyse_types.pyx
@@ -1,4 +1,4 @@
-# ticket: 676
+# ticket: t676
# tag: cpp
from cython cimport typeof
diff --git a/tests/run/bad_c_struct_T252.pyx b/tests/run/bad_c_struct_T252.pyx
index 247a55202..57b1155c2 100644
--- a/tests/run/bad_c_struct_T252.pyx
+++ b/tests/run/bad_c_struct_T252.pyx
@@ -1,4 +1,4 @@
-# ticket: 252
+# ticket: t252
cdef cf(default=None):
return default
diff --git a/tests/run/bint_binop_T145.pyx b/tests/run/bint_binop_T145.pyx
index c6df52303..f0f0ef560 100644
--- a/tests/run/bint_binop_T145.pyx
+++ b/tests/run/bint_binop_T145.pyx
@@ -1,4 +1,4 @@
-# ticket: 145
+# ticket: t145
cimport cython
diff --git a/tests/run/bint_property_T354.pyx b/tests/run/bint_property_T354.pyx
index 5a461ac76..ef4c623ee 100644
--- a/tests/run/bint_property_T354.pyx
+++ b/tests/run/bint_property_T354.pyx
@@ -1,4 +1,4 @@
-# ticket: 354
+# ticket: t354
cdef class Test:
"""
diff --git a/tests/run/bound_builtin_methods_T589.pyx b/tests/run/bound_builtin_methods_T589.pyx
index 18a517cbd..1d2fb9f66 100644
--- a/tests/run/bound_builtin_methods_T589.pyx
+++ b/tests/run/bound_builtin_methods_T589.pyx
@@ -1,4 +1,4 @@
-# ticket: 589
+# ticket: t589
cimport cython
diff --git a/tests/run/builtin_abs.pyx b/tests/run/builtin_abs.pyx
index 5b35eb886..59f3a93c4 100644
--- a/tests/run/builtin_abs.pyx
+++ b/tests/run/builtin_abs.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 698
+# ticket: t698
# distutils: extra_compile_args=-fwrapv
cdef extern from *:
diff --git a/tests/run/builtin_float.py b/tests/run/builtin_float.py
index a5a7615d9..dc31223bb 100644
--- a/tests/run/builtin_float.py
+++ b/tests/run/builtin_float.py
@@ -1,3 +1,19 @@
+# mode: run
+# tag: pure3.0
+
+import cython
+import sys
+
+def fix_underscores(s):
+ if sys.version_info < (3, 6) or getattr(sys, 'pypy_version_info', (9, 9)) < (3, 7, 4):
+ # Py2 float() does not support PEP-515 underscore literals
+ if isinstance(s, bytes):
+ if not cython.compiled and b'_' in s:
+ return s.replace(b'_', b'')
+ elif '_' in s:
+ return s.replace('_', '')
+ return s
+
def empty_float():
"""
@@ -26,3 +42,195 @@ def float_call_conjugate():
"""
x = float(1.5).conjugate()
return x
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_bytes(s: bytes):
+ """
+ >>> from_bytes(b"123")
+ 123.0
+ >>> from_bytes(b"123.25")
+ 123.25
+ >>> from_bytes(fix_underscores(b"98_5_6.2_1"))
+ 9856.21
+ >>> from_bytes(fix_underscores(b"12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387"))
+ 1.2413112312318938e+47
+ >>> from_bytes(b"123E100")
+ 1.23e+102
+ >>> from_bytes(b"12__._3") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12__._3...
+ >>> from_bytes(b"_12.3") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ..._12.3...
+ >>> from_bytes(b"12.3_") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12.3_...
+ >>> from_bytes(b"na_n") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...na_n...
+ >>> from_bytes(None) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError...
+ """
+ return float(s)
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_bytes_literals():
+ """
+ >>> from_bytes_literals()
+ (123.0, 123.23, 123.76, 1e+100)
+ """
+ return float(b"123"), float(b"123.23"), float(fix_underscores(b"12_3.7_6")), float(b"1e100")
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_bytearray(s: bytearray):
+ """
+ >>> from_bytearray(bytearray(b"123"))
+ 123.0
+ >>> from_bytearray(bytearray(b"123.25"))
+ 123.25
+ >>> from_bytearray(bytearray(fix_underscores(b"98_5_6.2_1")))
+ 9856.21
+ >>> from_bytearray(bytearray(fix_underscores(b"12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387")))
+ 1.2413112312318938e+47
+ >>> from_bytearray(bytearray(b"123E100"))
+ 1.23e+102
+ >>> from_bytearray(bytearray(b"12__._3")) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12__._3...
+ >>> from_bytearray(bytearray(b"_12.3")) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ..._12.3...
+ >>> from_bytearray(bytearray(b"12.3_")) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12.3_...
+ >>> from_bytearray(bytearray(b"in_f")) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...in_f...
+ >>> from_bytearray(None) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError...
+ """
+ return float(s)
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_str(s: 'str'):
+ """
+ >>> from_str("123")
+ 123.0
+ >>> from_str("123.25")
+ 123.25
+ >>> from_str(fix_underscores("3_21.2_5"))
+ 321.25
+ >>> from_str(fix_underscores("12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387"))
+ 1.2413112312318938e+47
+ >>> from_str("123E100")
+ 1.23e+102
+ >>> from_str("12__._3") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12__._3...
+ >>> from_str("_12.3") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ..._12.3...
+ >>> from_str("12.3_") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12.3_...
+ >>> from_str("n_an") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...n_an...
+ >>> from_str(None) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError...
+ """
+ return float(s)
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_str_literals():
+ """
+ >>> from_str_literals()
+ (123.0, 123.23, 124.23, 1e+100)
+ """
+ return float("123"), float("123.23"), float(fix_underscores("1_2_4.2_3")), float("1e100")
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_unicode(s: 'unicode'):
+ """
+ >>> from_unicode(u"123")
+ 123.0
+ >>> from_unicode(u"123.25")
+ 123.25
+ >>> from_unicode(fix_underscores(u"12_4.8_5"))
+ 124.85
+ >>> from_unicode(fix_underscores(u"12_4_131_123123_1893798127398123_19238712_128937198237.8222113_519879812387"))
+ 1.2413112312318938e+47
+ >>> from_unicode(u"123E100")
+ 1.23e+102
+ >>> from_unicode(u"123.23\\N{PUNCTUATION SPACE}")
+ 123.23
+ >>> from_unicode(u"\\N{PUNCTUATION SPACE} 123.23 \\N{PUNCTUATION SPACE}")
+ 123.23
+ >>> from_unicode(fix_underscores(u"\\N{PUNCTUATION SPACE} 12_3.2_3 \\N{PUNCTUATION SPACE}"))
+ 123.23
+ >>> from_unicode(u"\\N{PUNCTUATION SPACE} " * 25 + u"123.54 " + u"\\N{PUNCTUATION SPACE} " * 22) # >= 40 chars
+ 123.54
+ >>> from_unicode(fix_underscores(u"\\N{PUNCTUATION SPACE} " * 25 + u"1_23.5_4 " + u"\\N{PUNCTUATION SPACE} " * 22))
+ 123.54
+ >>> from_unicode(u"\\N{PUNCTUATION SPACE} " + u"123.54 " * 2 + u"\\N{PUNCTUATION SPACE}") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...123.54 123.54...
+ >>> from_unicode(u"\\N{PUNCTUATION SPACE} " * 25 + u"123.54 " * 2 + u"\\N{PUNCTUATION SPACE} " * 22) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...123.54 123.54...
+ >>> from_unicode(u"_12__._3") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ..._12__._3...
+ >>> from_unicode(u"_12.3") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ..._12.3...
+ >>> from_unicode(u"12.3_") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...12.3_...
+ >>> from_unicode(u"i_nf") # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ValueError: ...i_nf...
+ >>> from_unicode(None) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError...
+ """
+ return float(s)
+
+
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//CoerceToPyTypeNode//PythonCapiCallNode",
+)
+def from_unicode_literals():
+ """
+ >>> from_unicode_literals()
+ (123.0, 123.23, 123.45, 1e+100, 123.23)
+ """
+ return float(u"123"), float(u"123.23"), float(fix_underscores(u"12_3.4_5")), float(u"1e100"), float(u"123.23\N{PUNCTUATION SPACE}")
diff --git a/tests/run/builtin_methods_return_values.pyx b/tests/run/builtin_methods_return_values.pyx
index 50f1427ca..09a25273c 100644
--- a/tests/run/builtin_methods_return_values.pyx
+++ b/tests/run/builtin_methods_return_values.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: list, set, builtins
-# ticket: 688
+# ticket: t688
_set = set
diff --git a/tests/run/builtin_subtype_methods_T653.pyx b/tests/run/builtin_subtype_methods_T653.pyx
index bcfda81f0..522cffff8 100644
--- a/tests/run/builtin_subtype_methods_T653.pyx
+++ b/tests/run/builtin_subtype_methods_T653.pyx
@@ -1,6 +1,6 @@
#cython: language_level=2
# mode: run
-# ticket: 653
+# ticket: t653
cimport cython
diff --git a/tests/run/builtin_subtype_methods_cy3.pyx b/tests/run/builtin_subtype_methods_cy3.pyx
index 1cff75fb7..1f54ac598 100644
--- a/tests/run/builtin_subtype_methods_cy3.pyx
+++ b/tests/run/builtin_subtype_methods_cy3.pyx
@@ -1,6 +1,6 @@
# cython: language_level=3
# mode: run
-# ticket: 653
+# ticket: t653
class DictPySubtype(dict):
diff --git a/tests/run/builtin_type_inheritance_T608.pyx b/tests/run/builtin_type_inheritance_T608.pyx
index 67e97ec1e..1214b6841 100644
--- a/tests/run/builtin_type_inheritance_T608.pyx
+++ b/tests/run/builtin_type_inheritance_T608.pyx
@@ -1,4 +1,4 @@
-# ticket: 608
+# ticket: t608
cdef class MyInt(int):
"""
diff --git a/tests/run/builtin_types_none_T166.pyx b/tests/run/builtin_types_none_T166.pyx
index 33cabffa8..276f52724 100644
--- a/tests/run/builtin_types_none_T166.pyx
+++ b/tests/run/builtin_types_none_T166.pyx
@@ -1,4 +1,4 @@
-# ticket: 166
+# ticket: t166
__doc__ = u"""
>>> l = None
diff --git a/tests/run/c_int_types_T255.pyx b/tests/run/c_int_types_T255.pyx
index a9224f500..58b7839d9 100644
--- a/tests/run/c_int_types_T255.pyx
+++ b/tests/run/c_int_types_T255.pyx
@@ -1,4 +1,4 @@
-# ticket: 255
+# ticket: t255
__doc__ = u""
diff --git a/tests/run/c_type_methods_T236.pyx b/tests/run/c_type_methods_T236.pyx
index 53f20e661..b1ef5d023 100644
--- a/tests/run/c_type_methods_T236.pyx
+++ b/tests/run/c_type_methods_T236.pyx
@@ -1,4 +1,4 @@
-# ticket: 236
+# ticket: t236
import sys
diff --git a/tests/run/cascaded_list_unpacking_T467.pyx b/tests/run/cascaded_list_unpacking_T467.pyx
index 3008bddaf..fc0963d0d 100644
--- a/tests/run/cascaded_list_unpacking_T467.pyx
+++ b/tests/run/cascaded_list_unpacking_T467.pyx
@@ -1,4 +1,4 @@
-# ticket: 467
+# ticket: t467
def simple_parallel_assignment_from_call():
"""
diff --git a/tests/run/cascaded_typed_assignments_T466.pyx b/tests/run/cascaded_typed_assignments_T466.pyx
index eef9d5b7c..c2081bf91 100644
--- a/tests/run/cascaded_typed_assignments_T466.pyx
+++ b/tests/run/cascaded_typed_assignments_T466.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 466
+# ticket: t466
# extension to T409
cimport cython
diff --git a/tests/run/cdef_bool_T227.pyx b/tests/run/cdef_bool_T227.pyx
index 889963951..be403e695 100644
--- a/tests/run/cdef_bool_T227.pyx
+++ b/tests/run/cdef_bool_T227.pyx
@@ -1,4 +1,4 @@
-# ticket: 227
+# ticket: t227
from cpython.bool cimport bool
diff --git a/tests/run/cdef_class_field.pyx b/tests/run/cdef_class_field.pyx
index 9fb745ecb..5012bab89 100644
--- a/tests/run/cdef_class_field.pyx
+++ b/tests/run/cdef_class_field.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: exttype
-# ticket: 677
+# ticket: t677
"""
>>> str(Foo(4))
diff --git a/tests/run/cdef_class_property_decorator_T264.pyx b/tests/run/cdef_class_property_decorator_T264.pyx
index 421f762bc..b53bd7ec1 100644
--- a/tests/run/cdef_class_property_decorator_T264.pyx
+++ b/tests/run/cdef_class_property_decorator_T264.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 264
+# ticket: t264
# tag: property, decorator
my_property = property
diff --git a/tests/run/cdef_decorator_directives_T183.pyx b/tests/run/cdef_decorator_directives_T183.pyx
index 84b05a8df..dc362b255 100644
--- a/tests/run/cdef_decorator_directives_T183.pyx
+++ b/tests/run/cdef_decorator_directives_T183.pyx
@@ -1,4 +1,4 @@
-# ticket: 183
+# ticket: t183
cimport cython
diff --git a/tests/run/cdef_locals_decorator_T477.pyx b/tests/run/cdef_locals_decorator_T477.pyx
index 2b40d05ad..5af71e748 100644
--- a/tests/run/cdef_locals_decorator_T477.pyx
+++ b/tests/run/cdef_locals_decorator_T477.pyx
@@ -1,4 +1,4 @@
-# ticket: 477
+# ticket: t477
import cython
@cython.locals(x=double)
diff --git a/tests/run/cdef_members_T517.pyx b/tests/run/cdef_members_T517.pyx
index d69d72ca4..389879f67 100644
--- a/tests/run/cdef_members_T517.pyx
+++ b/tests/run/cdef_members_T517.pyx
@@ -1,4 +1,4 @@
-# ticket: 517
+# ticket: t517
#cython: embedsignature=True
__doc__ = u"""
diff --git a/tests/run/cdef_methods_T462.pyx b/tests/run/cdef_methods_T462.pyx
index dde15adbc..80bfa4b6f 100644
--- a/tests/run/cdef_methods_T462.pyx
+++ b/tests/run/cdef_methods_T462.pyx
@@ -1,4 +1,4 @@
-# ticket: 462
+# ticket: t462
cimport cython
diff --git a/tests/run/cdef_setitem_T284.pyx b/tests/run/cdef_setitem_T284.pyx
index 2c885d5be..389b8c409 100644
--- a/tests/run/cdef_setitem_T284.pyx
+++ b/tests/run/cdef_setitem_T284.pyx
@@ -1,4 +1,4 @@
-# ticket: 284
+# ticket: t284
def no_cdef():
"""
diff --git a/tests/run/cfunc_call_tuple_args_T408.pyx b/tests/run/cfunc_call_tuple_args_T408.pyx
index 165329737..e32eb036c 100644
--- a/tests/run/cfunc_call_tuple_args_T408.pyx
+++ b/tests/run/cfunc_call_tuple_args_T408.pyx
@@ -1,4 +1,4 @@
-# ticket: 408
+# ticket: t408
__doc__ = """
>>> call_with_tuple(1, 1.2, 'test', [1,2,3])
diff --git a/tests/run/cfunc_convert.pyx b/tests/run/cfunc_convert.pyx
index 3275fae33..6db0765d4 100644
--- a/tests/run/cfunc_convert.pyx
+++ b/tests/run/cfunc_convert.pyx
@@ -230,3 +230,39 @@ def test_cdef_class_params(a, b):
TypeError: Argument 'b' has incorrect type (expected cfunc_convert.B, got cfunc_convert.A)
"""
return (<object>test_cdef_class_params_cfunc)(a, b)
+
+# There were a few cases where duplicate utility code definitions (i.e. with the same name)
+# could be generated, causing C compile errors. This file tests them.
+
+cdef cfunc_dup_f1(x, r):
+ return "f1"
+
+cdef cfunc_dup_f2(x1, r):
+ return "f2"
+
+def make_map():
+ """
+ https://github.com/cython/cython/issues/3716
+ This is testing the generation of wrappers for f1 and f2
+ >>> for k, f in make_map().items():
+ ... print(k == f(0, 0)) # in both cases the functions should just return their name
+ True
+ True
+
+ # Test passing of keyword arguments
+ >>> print(make_map()['f1'](x=1, r=2))
+ f1
+ >>> make_map()['f1'](x1=1, r=2) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError: ...
+ >>> print(make_map()['f2'](x1=1, r=2))
+ f2
+ >>> make_map()['f2'](x=1, r=2) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError: ...
+ """
+ cdef map = {
+ "f1": cfunc_dup_f1,
+ "f2": cfunc_dup_f2,
+ }
+ return map
diff --git a/tests/run/char_constants_T99.pyx b/tests/run/char_constants_T99.pyx
index aa2550b52..241b461a1 100644
--- a/tests/run/char_constants_T99.pyx
+++ b/tests/run/char_constants_T99.pyx
@@ -1,4 +1,4 @@
-# ticket: 99
+# ticket: t99
cdef char c = 'c'
cdef char* s = 'abcdef'
diff --git a/tests/run/charcomparisonT412.pyx b/tests/run/charcomparisonT412.pyx
index b9316a36c..97afb4769 100644
--- a/tests/run/charcomparisonT412.pyx
+++ b/tests/run/charcomparisonT412.pyx
@@ -1,4 +1,4 @@
-# ticket: 412
+# ticket: t412
def f():
"""
diff --git a/tests/run/charptr_comparison_T582.pyx b/tests/run/charptr_comparison_T582.pyx
index 3701921cf..1e5e43cd2 100644
--- a/tests/run/charptr_comparison_T582.pyx
+++ b/tests/run/charptr_comparison_T582.pyx
@@ -1,4 +1,4 @@
-# ticket: 582
+# ticket: t582
cimport cython
diff --git a/tests/run/cimport.srctree b/tests/run/cimport.srctree
index 2d142fbb1..9811dd5e2 100644
--- a/tests/run/cimport.srctree
+++ b/tests/run/cimport.srctree
@@ -48,7 +48,15 @@ from other cimport (
print(A, foo(10))
cimport other
-print(other.A, other.foo(10))
+
+cdef call_fooptr(int (*fptr)(int)):
+ return fptr(10)
+
+def call_other_foo():
+ x = other.foo # GH4000 - failed because other was untyped
+ return call_fooptr(x) # check that x is correctly resolved as a function pointer
+
+print(other.A, other.foo(10), call_other_foo())
from pkg cimport sub
cdef sub.my_int a = 100
diff --git a/tests/run/cimport_cython_T505.pyx b/tests/run/cimport_cython_T505.pyx
index 20d2daf3a..69229856f 100644
--- a/tests/run/cimport_cython_T505.pyx
+++ b/tests/run/cimport_cython_T505.pyx
@@ -1,4 +1,4 @@
-# ticket: 505
+# ticket: t505
cimport cython
diff --git a/tests/run/class_attribute_init_values_T18.pyx b/tests/run/class_attribute_init_values_T18.pyx
index 5e12f665f..7887853df 100644
--- a/tests/run/class_attribute_init_values_T18.pyx
+++ b/tests/run/class_attribute_init_values_T18.pyx
@@ -1,4 +1,4 @@
-# ticket: 18
+# ticket: t18
__doc__ = u"""
>>> f = PyFoo()
diff --git a/tests/run/class_func_in_control_structures_T87.pyx b/tests/run/class_func_in_control_structures_T87.pyx
index 5c23ceff9..14ee440a0 100644
--- a/tests/run/class_func_in_control_structures_T87.pyx
+++ b/tests/run/class_func_in_control_structures_T87.pyx
@@ -1,4 +1,4 @@
-# ticket: 87
+# ticket: t87
__doc__ = u"""
>>> d = Defined()
diff --git a/tests/run/class_scope_del_T684.py b/tests/run/class_scope_del_T684.py
index 43368f333..f52b31864 100644
--- a/tests/run/class_scope_del_T684.py
+++ b/tests/run/class_scope_del_T684.py
@@ -1,6 +1,6 @@
# mode:run
# tag: class, scope, del
-# ticket: 684
+# ticket: t684
class DelInClass(object):
"""
diff --git a/tests/run/classdecorators_T336.pyx b/tests/run/classdecorators_T336.pyx
index c29c1cbaa..b56e08c07 100644
--- a/tests/run/classdecorators_T336.pyx
+++ b/tests/run/classdecorators_T336.pyx
@@ -1,4 +1,4 @@
-# ticket: 336
+# ticket: t336
__doc__ = u"""
>>> print('\\n'.join(calls))
diff --git a/tests/run/closure_class_T596.pyx b/tests/run/closure_class_T596.pyx
index 6a92d9f82..7808a8d9e 100644
--- a/tests/run/closure_class_T596.pyx
+++ b/tests/run/closure_class_T596.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 596
+# ticket: t596
def simple(a, b):
"""
diff --git a/tests/run/closure_decorators_T478.pyx b/tests/run/closure_decorators_T478.pyx
index e1c5f4918..1bccdcc19 100644
--- a/tests/run/closure_decorators_T478.pyx
+++ b/tests/run/closure_decorators_T478.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 478
+# ticket: t478
__doc__ = """
>>> Num(13).is_prime()
diff --git a/tests/run/closure_inside_cdef_T554.pyx b/tests/run/closure_inside_cdef_T554.pyx
index 3a112868d..3406259b5 100644
--- a/tests/run/closure_inside_cdef_T554.pyx
+++ b/tests/run/closure_inside_cdef_T554.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 554
+# ticket: t554
def call_f(x):
"""
diff --git a/tests/run/closure_name_mangling_T537.pyx b/tests/run/closure_name_mangling_T537.pyx
index 0324109ec..148f9f1ae 100644
--- a/tests/run/closure_name_mangling_T537.pyx
+++ b/tests/run/closure_name_mangling_T537.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 537
+# ticket: t537
__doc__ = u"""
>>> f1 = nested1()
diff --git a/tests/run/closure_names.pyx b/tests/run/closure_names.pyx
index b6d253983..0ceb320d5 100644
--- a/tests/run/closure_names.pyx
+++ b/tests/run/closure_names.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: gh-1797
+# ticket: 1797
def func():
diff --git a/tests/run/closures_T82.pyx b/tests/run/closures_T82.pyx
index 85ce9043e..c8a228a19 100644
--- a/tests/run/closures_T82.pyx
+++ b/tests/run/closures_T82.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 82
+# ticket: t82
# preparse: id
# preparse: def_to_cdef
diff --git a/tests/run/cmethod_inline_T474.pyx b/tests/run/cmethod_inline_T474.pyx
index ddc33a62b..d09db3bf4 100644
--- a/tests/run/cmethod_inline_T474.pyx
+++ b/tests/run/cmethod_inline_T474.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 474
+# ticket: t474
cimport cython
diff --git a/tests/run/complex_cast_T445.pyx b/tests/run/complex_cast_T445.pyx
index 62709c9c1..b4069ec9d 100644
--- a/tests/run/complex_cast_T445.pyx
+++ b/tests/run/complex_cast_T445.pyx
@@ -1,4 +1,4 @@
-# ticket: 445
+# ticket: t445
def complex_double_cast(double x, double complex z):
"""
diff --git a/tests/run/complex_coercion_sideeffects_T693.pyx b/tests/run/complex_coercion_sideeffects_T693.pyx
index 92b1f94a9..18a9575dc 100644
--- a/tests/run/complex_coercion_sideeffects_T693.pyx
+++ b/tests/run/complex_coercion_sideeffects_T693.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 693
+# ticket: t693
cdef double complex func(double complex x):
print "hello"
diff --git a/tests/run/complex_int_T446.pyx b/tests/run/complex_int_T446.pyx
index a26eaa546..16e991c7c 100644
--- a/tests/run/complex_int_T446.pyx
+++ b/tests/run/complex_int_T446.pyx
@@ -1,4 +1,4 @@
-# ticket: 446
+# ticket: t446
import cython
diff --git a/tests/run/complex_numbers_T305.pyx b/tests/run/complex_numbers_T305.pyx
index 310b7233e..acbc0a5fa 100644
--- a/tests/run/complex_numbers_T305.pyx
+++ b/tests/run/complex_numbers_T305.pyx
@@ -1,4 +1,4 @@
-# ticket: 305
+# ticket: t305
from cpython.object cimport Py_EQ, Py_NE
diff --git a/tests/run/complex_numbers_T305_long_double.pyx b/tests/run/complex_numbers_T305_long_double.pyx
index 891d44271..9bc1e73fb 100644
--- a/tests/run/complex_numbers_T305_long_double.pyx
+++ b/tests/run/complex_numbers_T305_long_double.pyx
@@ -1,4 +1,4 @@
-# ticket: 305
+# ticket: t305
cimport cython
diff --git a/tests/run/complex_numbers_c89_T398.pyx b/tests/run/complex_numbers_c89_T398.pyx
index 7d680a167..546d37c31 100644
--- a/tests/run/complex_numbers_c89_T398.pyx
+++ b/tests/run/complex_numbers_c89_T398.pyx
@@ -1,4 +1,4 @@
-# ticket: 398
+# ticket: t398
cdef extern from "complex_numbers_c89_T398.h": pass
include "complex_numbers_T305.pyx"
diff --git a/tests/run/complex_numbers_c89_T398_long_double.pyx b/tests/run/complex_numbers_c89_T398_long_double.pyx
index 91450e22b..9ac1607e4 100644
--- a/tests/run/complex_numbers_c89_T398_long_double.pyx
+++ b/tests/run/complex_numbers_c89_T398_long_double.pyx
@@ -1,4 +1,4 @@
-# ticket: 398
+# ticket: t398
cdef extern from "complex_numbers_c89_T398.h": pass
include "complex_numbers_T305_long_double.pyx"
diff --git a/tests/run/complex_numbers_c99_T398.pyx b/tests/run/complex_numbers_c99_T398.pyx
index 762c24b02..332029cab 100644
--- a/tests/run/complex_numbers_c99_T398.pyx
+++ b/tests/run/complex_numbers_c99_T398.pyx
@@ -1,4 +1,4 @@
-# ticket: 398
+# ticket: t398
cdef extern from "complex_numbers_c99_T398.h": pass
include "complex_numbers_T305.pyx"
diff --git a/tests/run/complex_numbers_cxx_T398.pyx b/tests/run/complex_numbers_cxx_T398.pyx
index 9b9b69a73..f5e535ab7 100644
--- a/tests/run/complex_numbers_cxx_T398.pyx
+++ b/tests/run/complex_numbers_cxx_T398.pyx
@@ -1,4 +1,4 @@
-# ticket: 398
+# ticket: t398
cdef extern from "complex_numbers_cxx_T398.h": pass
include "complex_numbers_T305.pyx"
diff --git a/tests/run/contains_T455.pyx b/tests/run/contains_T455.pyx
index 5caed0b86..8bb087acf 100644
--- a/tests/run/contains_T455.pyx
+++ b/tests/run/contains_T455.pyx
@@ -1,4 +1,4 @@
-# ticket: 455
+# ticket: t455
def in_sequence(x, seq):
"""
diff --git a/tests/run/coverage_cmd.srctree b/tests/run/coverage_cmd.srctree
index bb1c650db..70408409c 100644
--- a/tests/run/coverage_cmd.srctree
+++ b/tests/run/coverage_cmd.srctree
@@ -206,7 +206,7 @@ def run_json_report():
'pkg/coverage_test_py.py',
'pkg/coverage_test_pyx.pyx',
]:
- report = files[filename]
+ report = files[filename.replace('/', os.sep)]
summary = report['summary']
assert summary['missing_lines'] == 2, summary
assert summary['excluded_lines'] == 2, summary
diff --git a/tests/run/cpdef_enums.pyx b/tests/run/cpdef_enums.pyx
index 3e342bbb3..d93e19582 100644
--- a/tests/run/cpdef_enums.pyx
+++ b/tests/run/cpdef_enums.pyx
@@ -39,10 +39,10 @@ True
Traceback (most recent call last):
NameError: ...name 'RANK_3' is not defined
->>> set(PyxEnum) == set([TWO, THREE, FIVE])
+>>> set(PyxEnum) == {TWO, THREE, FIVE}
True
->>> str(PyxEnum.TWO)
-'PyxEnum.TWO'
+>>> str(PyxEnum.TWO).split(".")[-1] # Py3.10 changed the output here
+'TWO'
>>> PyxEnum.TWO + PyxEnum.THREE == PyxEnum.FIVE
True
>>> PyxEnum(2) is PyxEnum["TWO"] is PyxEnum.TWO
diff --git a/tests/run/cpdef_method_override.pyx b/tests/run/cpdef_method_override.pyx
index 97aafe562..aadef67a6 100644
--- a/tests/run/cpdef_method_override.pyx
+++ b/tests/run/cpdef_method_override.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: cpdef
-# ticket: gh-1771
+# ticket: 1771
def _call_method(cls):
obj = cls()
diff --git a/tests/run/cpdef_temps_T411.pyx b/tests/run/cpdef_temps_T411.pyx
index 061d9ef13..66f08331d 100644
--- a/tests/run/cpdef_temps_T411.pyx
+++ b/tests/run/cpdef_temps_T411.pyx
@@ -1,4 +1,4 @@
-# ticket: 411
+# ticket: t411
cdef class A:
"""
diff --git a/tests/run/cpp_nested_classes.pyx b/tests/run/cpp_nested_classes.pyx
index 6008b2379..98ea514f1 100644
--- a/tests/run/cpp_nested_classes.pyx
+++ b/tests/run/cpp_nested_classes.pyx
@@ -26,6 +26,10 @@ cdef extern from "cpp_nested_classes_support.h":
pass
+ctypedef A AliasA1
+ctypedef AliasA1 AliasA2
+
+
def test_nested_classes():
"""
>>> test_nested_classes()
@@ -47,6 +51,20 @@ def test_nested_typedef(py_x):
cdef A.my_int x = py_x
assert A.negate(x) == -py_x
+def test_typedef_for_nested(py_x):
+ """
+ >>> test_typedef_for_nested(5)
+ """
+ cdef AliasA1.my_int x = py_x
+ assert A.negate(x) == -py_x
+
+def test_typedef_for_nested_deep(py_x):
+ """
+ >>> test_typedef_for_nested_deep(5)
+ """
+ cdef AliasA2.my_int x = py_x
+ assert A.negate(x) == -py_x
+
def test_typed_nested_typedef(x):
"""
>>> test_typed_nested_typedef(4)
diff --git a/tests/run/cpp_stl_conversion.pyx b/tests/run/cpp_stl_conversion.pyx
index 5278c677a..ccebc700e 100644
--- a/tests/run/cpp_stl_conversion.pyx
+++ b/tests/run/cpp_stl_conversion.pyx
@@ -15,7 +15,7 @@ py_set = set
py_xrange = xrange
py_unicode = unicode
-cdef string add_strings(string a, string b):
+cdef string add_strings(string a, string b) except *:
return a + b
def normalize(bytes b):
diff --git a/tests/run/crashT245.pyx b/tests/run/crashT245.pyx
index 862deca37..0ef9cb447 100644
--- a/tests/run/crashT245.pyx
+++ b/tests/run/crashT245.pyx
@@ -1,4 +1,4 @@
-# ticket: 245
+# ticket: t245
cimport crashT245_pxd
diff --git a/tests/run/cstringmul.pyx b/tests/run/cstringmul.pyx
index 1c3b79302..1932e8d61 100644
--- a/tests/run/cstringmul.pyx
+++ b/tests/run/cstringmul.pyx
@@ -31,3 +31,15 @@ grail_long = 700 * "tomato"
uspam = u"eggs" * 4
ugrail = 7 * u"tomato"
ugrail_long = 700 * u"tomato"
+
+cimport cython
+
+@cython.test_assert_path_exists("//StringNode[@value = '-----']")
+@cython.test_assert_path_exists("//StringNode[@unicode_value = '-----']")
+def gh3951():
+ """
+ Bug occurs with language_level=2 and affects StringNode.value
+ >>> gh3951()
+ '-----'
+ """
+ return "-"*5
diff --git a/tests/run/ctypedef_int_types_T333.pyx b/tests/run/ctypedef_int_types_T333.pyx
index 3f1a99f69..b0a47d484 100644
--- a/tests/run/ctypedef_int_types_T333.pyx
+++ b/tests/run/ctypedef_int_types_T333.pyx
@@ -1,4 +1,4 @@
-# ticket: 333
+# ticket: t333
#cython: autotestdict=True
# -------------------------------------------------------------------
diff --git a/tests/run/cython_includes.pyx b/tests/run/cython_includes.pyx
index c67fd10fd..1fcc575ec 100644
--- a/tests/run/cython_includes.pyx
+++ b/tests/run/cython_includes.pyx
@@ -10,12 +10,16 @@ cimport cpython.bool
cimport cpython.buffer
cimport cpython.bytearray
cimport cpython.bytes
+cimport cpython.cellobject
cimport cpython.ceval
cimport cpython.cobject
+cimport cpython.codecs
cimport cpython.complex
+cimport cpython.conversion
cimport cpython.datetime
cimport cpython.dict
cimport cpython.exc
+cimport cpython.fileobject
cimport cpython.float
cimport cpython.function
cimport cpython.genobject
diff --git a/tests/run/datetime_pxd.pyx b/tests/run/datetime_pxd.pyx
index 09e579ba7..8d1931399 100644
--- a/tests/run/datetime_pxd.pyx
+++ b/tests/run/datetime_pxd.pyx
@@ -1,8 +1,6 @@
# coding: utf-8
-#cimport cpython.datetime as cy_datetime
-#from datetime import time, date, datetime, timedelta, tzinfo
-
+cimport cython
from cpython.datetime cimport import_datetime, timedelta
from cpython.datetime cimport time_new, date_new, datetime_new, timedelta_new
@@ -212,3 +210,31 @@ def test_timedelta_total_seconds():
pytd = now - py_datetime.datetime(1970, 1, 1)
return total_seconds(td), pytd.total_seconds()
+
+
+@cython.test_fail_if_path_exists(
+ "//CoerceFromPyTypeNode",
+ "//AttributeNode",
+)
+def test_datetime_attrs_inlined(datetime dt):
+ # GH#3737
+ """
+ >>> from datetime import datetime
+ >>> py_dt = datetime(2020, 8, 18, 4, 9)
+ >>> dt = test_datetime_attrs_inlined(py_dt)
+ >>> dt[:5]
+ (2020, 8, 18, 4, 9)
+ >>> dt[5] == py_dt.second or (dt[5], py_dt.second)
+ True
+ >>> dt[6] == py_dt.microsecond or (dt[6], py_dt.microsecond)
+ True
+ """
+ return (
+ dt.year,
+ dt.month,
+ dt.day,
+ dt.hour,
+ dt.minute,
+ dt.second,
+ dt.microsecond,
+ )
diff --git a/tests/run/decorators_T593.pyx b/tests/run/decorators_T593.pyx
index d63bcb704..824e5fb2a 100644
--- a/tests/run/decorators_T593.pyx
+++ b/tests/run/decorators_T593.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 593
+# ticket: t593
# tag: property, decorator
"""
diff --git a/tests/run/decorators_py_T593.py b/tests/run/decorators_py_T593.py
index 98cffa79f..339e575de 100644
--- a/tests/run/decorators_py_T593.py
+++ b/tests/run/decorators_py_T593.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 593
+# ticket: t593
# tag: property, decorator
"""
diff --git a/tests/run/default_args_T674.py b/tests/run/default_args_T674.py
index 1ca9381bc..7acf84048 100644
--- a/tests/run/default_args_T674.py
+++ b/tests/run/default_args_T674.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 674
+# ticket: t674
def test_inner(a):
"""
diff --git a/tests/run/dict.pyx b/tests/run/dict.pyx
index d51cef7da..691b78635 100644
--- a/tests/run/dict.pyx
+++ b/tests/run/dict.pyx
@@ -117,3 +117,22 @@ def item_creation_sideeffect(L, sideeffect, unhashable):
[2, 4, 5]
"""
return {1:2, sideeffect(2): 3, 3: 4, unhashable(4): 5, sideeffect(5): 6}
+
+
+def dict_unpacking_not_for_arg_create_a_copy():
+ """
+ >>> dict_unpacking_not_for_arg_create_a_copy()
+ [('a', 'modified'), ('b', 'original')]
+ [('a', 'original'), ('b', 'original')]
+ """
+ data = {'a': 'original', 'b': 'original'}
+
+ func = lambda: {**data}
+
+ call_once = func()
+ call_once['a'] = 'modified'
+
+ call_twice = func()
+
+ print(sorted(call_once.items()))
+ print(sorted(call_twice.items()))
diff --git a/tests/run/division_T384.pyx b/tests/run/division_T384.pyx
index 301dc3a61..5da5475fd 100644
--- a/tests/run/division_T384.pyx
+++ b/tests/run/division_T384.pyx
@@ -1,4 +1,4 @@
-# ticket: 384
+# ticket: t384
"""
>>> test(3)
diff --git a/tests/run/duplicate_keyword_in_call.py b/tests/run/duplicate_keyword_in_call.py
index e3d041d76..aba5772c3 100644
--- a/tests/run/duplicate_keyword_in_call.py
+++ b/tests/run/duplicate_keyword_in_call.py
@@ -1,6 +1,6 @@
# mode: run
# tag: kwargs, call
-# ticket: 717
+# ticket: t717
def f(**kwargs):
return sorted(kwargs.items())
diff --git a/tests/run/duplicate_utilitycode_from_pyx.srctree b/tests/run/duplicate_utilitycode_from_pyx.srctree
new file mode 100644
index 000000000..c539af7a6
--- /dev/null
+++ b/tests/run/duplicate_utilitycode_from_pyx.srctree
@@ -0,0 +1,29 @@
+
+
+PYTHON setup.py build_ext --inplace
+PYTHON -c "import modb; modb.ClassB()"
+
+#################### moda.pyx ####################
+
+cdef class ClassA:
+ cdef int[2] a
+
+#################### modb.pyx #####################
+
+from moda cimport ClassA
+
+cdef class ClassB(ClassA):
+ cdef int[2] b
+
+###################### setup.py ###################
+
+from setuptools import setup
+from Cython.Build import cythonize
+import Cython.Compiler.Options
+
+Cython.Compiler.Options.cimport_from_pyx = True
+
+setup(
+ ext_modules = cythonize(["moda.pyx", "modb.pyx"],
+ compiler_directives={'language_level': 3})
+)
diff --git a/tests/run/dynamic_args.pyx b/tests/run/dynamic_args.pyx
index 900671028..1205b06b0 100644
--- a/tests/run/dynamic_args.pyx
+++ b/tests/run/dynamic_args.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 674
+# ticket: t674
cdef class Foo:
cdef str name
diff --git a/tests/run/ellipsis_T488.pyx b/tests/run/ellipsis_T488.pyx
index e7892dbc9..ab04b317c 100644
--- a/tests/run/ellipsis_T488.pyx
+++ b/tests/run/ellipsis_T488.pyx
@@ -1,4 +1,4 @@
-# ticket: 488
+# ticket: t488
"""
>>> test()
diff --git a/tests/run/empty_for_loop_T208.pyx b/tests/run/empty_for_loop_T208.pyx
index 88a134f25..70b3be512 100644
--- a/tests/run/empty_for_loop_T208.pyx
+++ b/tests/run/empty_for_loop_T208.pyx
@@ -1,4 +1,4 @@
-# ticket: 208
+# ticket: t208
def go_py_empty():
"""
diff --git a/tests/run/enumerate_T316.pyx b/tests/run/enumerate_T316.pyx
index f148e1a22..89755b76b 100644
--- a/tests/run/enumerate_T316.pyx
+++ b/tests/run/enumerate_T316.pyx
@@ -1,4 +1,4 @@
-# ticket: 316
+# ticket: t316
cimport cython
diff --git a/tests/run/ext_instance_type_T232.pyx b/tests/run/ext_instance_type_T232.pyx
index 9538a9b96..c089b1603 100644
--- a/tests/run/ext_instance_type_T232.pyx
+++ b/tests/run/ext_instance_type_T232.pyx
@@ -1,4 +1,4 @@
-# ticket: 232
+# ticket: t232
cdef class MyExt:
cdef object attr
diff --git a/tests/run/extended_unpacking_T235.pyx b/tests/run/extended_unpacking_T235.pyx
index 2388e2587..8d38120a1 100644
--- a/tests/run/extended_unpacking_T235.pyx
+++ b/tests/run/extended_unpacking_T235.pyx
@@ -1,4 +1,4 @@
-# ticket: 235
+# ticket: t235
__doc__ = u"""
>>> class FakeSeq(object):
diff --git a/tests/run/extended_unpacking_T409.pyx b/tests/run/extended_unpacking_T409.pyx
index 1198a15f3..7c3b71d51 100644
--- a/tests/run/extended_unpacking_T409.pyx
+++ b/tests/run/extended_unpacking_T409.pyx
@@ -1,4 +1,4 @@
-# ticket: 409
+# ticket: t409
def simple():
"""
diff --git a/tests/run/extern_builtins_T258.pyx b/tests/run/extern_builtins_T258.pyx
index d732931dd..1c6ea9843 100644
--- a/tests/run/extern_builtins_T258.pyx
+++ b/tests/run/extern_builtins_T258.pyx
@@ -1,4 +1,4 @@
-# ticket: 258
+# ticket: t258
cdef extern from "Python.h":
diff --git a/tests/run/file_encoding_T740.py b/tests/run/file_encoding_T740.py
index f61973353..a71b04be9 100644
--- a/tests/run/file_encoding_T740.py
+++ b/tests/run/file_encoding_T740.py
@@ -1,6 +1,6 @@
# encoding: koi8-r
# mode: run
-# ticket: 740
+# ticket: t740
"""
>>> wtf
'wtf'
diff --git a/tests/run/final_method_T586.pyx b/tests/run/final_method_T586.pyx
index 8fa1ba25c..f50bb8aa8 100644
--- a/tests/run/final_method_T586.pyx
+++ b/tests/run/final_method_T586.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 568
+# ticket: t568
cimport cython
diff --git a/tests/run/float_floor_division_T260.pyx b/tests/run/float_floor_division_T260.pyx
index 66f6f83f7..58d13a157 100644
--- a/tests/run/float_floor_division_T260.pyx
+++ b/tests/run/float_floor_division_T260.pyx
@@ -1,4 +1,4 @@
-# ticket: 260
+# ticket: t260
def floor_div_float(double a, double b):
"""
diff --git a/tests/run/float_len_T480.pyx b/tests/run/float_len_T480.pyx
index efb456c54..4f623030a 100644
--- a/tests/run/float_len_T480.pyx
+++ b/tests/run/float_len_T480.pyx
@@ -1,4 +1,4 @@
-# ticket: 480
+# ticket: t480
def f(x):
return x
diff --git a/tests/run/for_from_float_T254.pyx b/tests/run/for_from_float_T254.pyx
index 0ea153a9c..bf07f42b6 100644
--- a/tests/run/for_from_float_T254.pyx
+++ b/tests/run/for_from_float_T254.pyx
@@ -1,4 +1,4 @@
-# ticket: 254
+# ticket: t254
def double_target(a, b):
"""
diff --git a/tests/run/for_from_pyvar_loop_T601.pyx b/tests/run/for_from_pyvar_loop_T601.pyx
index 2d5890d9b..949fcef06 100644
--- a/tests/run/for_from_pyvar_loop_T601.pyx
+++ b/tests/run/for_from_pyvar_loop_T601.pyx
@@ -1,4 +1,4 @@
-# ticket: 601
+# ticket: t601
cdef unsigned long size2():
return 3
diff --git a/tests/run/for_in_break_continue_T533.pyx b/tests/run/for_in_break_continue_T533.pyx
index 0baa9fa49..32f646aaf 100644
--- a/tests/run/for_in_break_continue_T533.pyx
+++ b/tests/run/for_in_break_continue_T533.pyx
@@ -1,4 +1,4 @@
-# ticket: 533
+# ticket: t533
def for_in():
"""
diff --git a/tests/run/for_in_range_T372.pyx b/tests/run/for_in_range_T372.pyx
index bff686295..11ef4b592 100644
--- a/tests/run/for_in_range_T372.pyx
+++ b/tests/run/for_in_range_T372.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 372
+# ticket: t372
cimport cython
diff --git a/tests/run/funcexc_iter_T228.pyx b/tests/run/funcexc_iter_T228.pyx
index 0c5bde250..4b81166f6 100644
--- a/tests/run/funcexc_iter_T228.pyx
+++ b/tests/run/funcexc_iter_T228.pyx
@@ -1,4 +1,4 @@
-# ticket: 228
+# ticket: t228
__doc__ = u"""
>>> def py_iterator():
diff --git a/tests/run/function_as_method_T494.pyx b/tests/run/function_as_method_T494.pyx
index 0c0307ea2..92deafc6d 100644
--- a/tests/run/function_as_method_T494.pyx
+++ b/tests/run/function_as_method_T494.pyx
@@ -1,4 +1,4 @@
-# ticket: 494
+# ticket: t494
# cython: binding=True
__doc__ = """
diff --git a/tests/run/function_as_method_py_T494.py b/tests/run/function_as_method_py_T494.py
index d94813784..5317d8848 100644
--- a/tests/run/function_as_method_py_T494.py
+++ b/tests/run/function_as_method_py_T494.py
@@ -1,4 +1,4 @@
-# ticket: 494
+# ticket: t494
__doc__ = """
>>> A.foo = foo
diff --git a/tests/run/function_binding_T494.pyx b/tests/run/function_binding_T494.pyx
index b41221e2c..86c64c9c0 100644
--- a/tests/run/function_binding_T494.pyx
+++ b/tests/run/function_binding_T494.pyx
@@ -1,4 +1,4 @@
-# ticket: 494
+# ticket: t494
cimport cython
diff --git a/tests/run/function_self.py b/tests/run/function_self.py
new file mode 100644
index 000000000..e4796c46b
--- /dev/null
+++ b/tests/run/function_self.py
@@ -0,0 +1,91 @@
+# mode: run
+# tag: pure2.7
+
+# cython: binding=True
+
+import cython
+import sys
+
+def regular(x):
+ """
+ >>> hasattr(regular, "__self__")
+ False
+ >>> nested = regular(10)
+ >>> hasattr(nested, "__self__")
+ False
+ """
+ def nested(y):
+ return x+y
+ return nested
+
+@cython.locals(x=cython.floating)
+def fused(x):
+ """
+ >>> nested = fused(10.)
+ >>> hasattr(nested, "__self__")
+ False
+
+ #>>> hasattr(fused, "__self__") # FIXME this fails for fused functions
+ #False
+ >>> fused.__self__ # but this is OK
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'function' object has no attribute '__self__'
+ """
+ def nested_in_fused(y):
+ return x+y
+ return nested_in_fused
+
+# FIXME - doesn't currently work at all
+#def get_nested_fused(x):
+# @cython.locals(x=cython.floating)
+# def nested_fused(y):
+# return x+y
+# return nested_fused
+
+class C:
+ """
+ >>> c = C()
+ >>> c.regular.__self__ is c
+ True
+ >>> c.fused.__self__ is c
+ True
+ """
+ def regular(self):
+ pass
+
+ @cython.locals(x=cython.floating)
+ def fused(self, x):
+ return x
+
+__doc__ = ""
+if sys.version_info[0] > 2 or cython.compiled:
+ __doc__ += """
+ >>> hasattr(C.regular, "__self__") # __self__==None on pure-python 2
+ False
+ >>> C.fused.__self__ # returns None on pure-python 2
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'function' object has no attribute '__self__'
+ """
+
+if cython.compiled:
+ __doc__ = """
+ >>> fused['double'].__self__
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'function' object has no attribute '__self__'
+
+ >>> C.fused['double'].__self__
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'function' object has no attribute '__self__'
+
+ >>> c = C()
+ >>> c.fused['double'].__self__ is c
+ True
+
+ # The PR that changed __self__ also changed how __doc__ is set up slightly
+ >>> fused['double'].__doc__ == fused.__doc__ and isinstance(fused.__doc__, str)
+ True
+ """
diff --git a/tests/run/fused_types.pyx b/tests/run/fused_types.pyx
index 3dddb7e14..3a0009bdd 100644
--- a/tests/run/fused_types.pyx
+++ b/tests/run/fused_types.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 1772
+# ticket: t1772
cimport cython
from cython.view cimport array
@@ -328,6 +328,8 @@ def test_fused_memslice_dtype(cython.floating[:] array):
cdef cython.floating[:] otherarray = array[0:100:1]
print cython.typeof(array), cython.typeof(otherarray), \
array[5], otherarray[6]
+ cdef cython.floating value;
+ cdef cython.floating[:] test_cast = <cython.floating[:1:1]>&value
def test_fused_memslice_dtype_repeated(cython.floating[:] array1, cython.floating[:] array2):
"""
diff --git a/tests/run/generator_expressions_and_locals.pyx b/tests/run/generator_expressions_and_locals.pyx
index 7a87164ff..a239f9b29 100644
--- a/tests/run/generator_expressions_and_locals.pyx
+++ b/tests/run/generator_expressions_and_locals.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: genexpr, locals
-# ticket: 715
+# ticket: t715
def genexpr_not_in_locals():
"""
diff --git a/tests/run/generators_GH1731.pyx b/tests/run/generators_GH1731.pyx
index 99cae90ca..77b0877f2 100644
--- a/tests/run/generators_GH1731.pyx
+++ b/tests/run/generators_GH1731.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: gh1731
+# ticket: 1731
def cygen():
diff --git a/tests/run/generators_py35.py b/tests/run/generators_py35.py
index afb60f67f..0d9d5f86c 100644
--- a/tests/run/generators_py35.py
+++ b/tests/run/generators_py35.py
@@ -30,7 +30,7 @@ def anno_gen(x: 'int') -> 'float':
>>> next(gen)
2.0
>>> ret, arg = sorted(anno_gen.__annotations__.items())
- >>> print(ret[0]); print(str(ret[1]).strip("'")) # strip makes it pass with/without PEP563
+ >>> print(ret[0]); print(str(ret[1]).strip("'")) # strip makes it pass with/without PEP563
return
float
>>> print(arg[0]); print(str(arg[1]).strip("'"))
diff --git a/tests/run/genexpr_T491.pyx b/tests/run/genexpr_T491.pyx
index 7fa6c1754..7640b3518 100644
--- a/tests/run/genexpr_T491.pyx
+++ b/tests/run/genexpr_T491.pyx
@@ -1,4 +1,4 @@
-# ticket: 491
+# ticket: t491
def test_genexpr():
"""
diff --git a/tests/run/genexpr_T715.pyx b/tests/run/genexpr_T715.pyx
index 2c6f5d6c8..028a93128 100644
--- a/tests/run/genexpr_T715.pyx
+++ b/tests/run/genexpr_T715.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 715
+# ticket: t715
# tag: genexpr, comprehension
def t715(*items):
diff --git a/tests/run/genexpr_iterable_lookup_T600.pyx b/tests/run/genexpr_iterable_lookup_T600.pyx
index 220098a1f..945652717 100644
--- a/tests/run/genexpr_iterable_lookup_T600.pyx
+++ b/tests/run/genexpr_iterable_lookup_T600.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 600
+# ticket: t600
# tag: genexpr
# cython: language_level=3
diff --git a/tests/run/hash_T326.pyx b/tests/run/hash_T326.pyx
index 11184837f..bc9566879 100644
--- a/tests/run/hash_T326.pyx
+++ b/tests/run/hash_T326.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 326
+# ticket: t326
# tag: hash
diff --git a/tests/run/ifelseexpr_T267.pyx b/tests/run/ifelseexpr_T267.pyx
index 24dabc442..973c1979a 100644
--- a/tests/run/ifelseexpr_T267.pyx
+++ b/tests/run/ifelseexpr_T267.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: condexpr
-# ticket: 267
+# ticket: t267
cimport cython
diff --git a/tests/run/import_error_T734.py b/tests/run/import_error_T734.py
index 4138fba1c..efcd79944 100644
--- a/tests/run/import_error_T734.py
+++ b/tests/run/import_error_T734.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 734
+# ticket: t734
def test_import_error():
"""
diff --git a/tests/run/in_list_with_side_effects_T544.pyx b/tests/run/in_list_with_side_effects_T544.pyx
index 3bb3954c3..4a75f206a 100644
--- a/tests/run/in_list_with_side_effects_T544.pyx
+++ b/tests/run/in_list_with_side_effects_T544.pyx
@@ -1,4 +1,4 @@
-# ticket: 544
+# ticket: t544
def count(i=[0]):
i[0] += 1
diff --git a/tests/run/int_float_builtins_as_casts_T400.pyx b/tests/run/int_float_builtins_as_casts_T400.pyx
index 6d02eff36..99d1796ed 100644
--- a/tests/run/int_float_builtins_as_casts_T400.pyx
+++ b/tests/run/int_float_builtins_as_casts_T400.pyx
@@ -1,4 +1,4 @@
-# ticket: 400
+# ticket: t400
cimport cython
diff --git a/tests/run/int_float_builtins_as_casts_T400_long_double.pyx b/tests/run/int_float_builtins_as_casts_T400_long_double.pyx
index d7e61f43b..776434ee8 100644
--- a/tests/run/int_float_builtins_as_casts_T400_long_double.pyx
+++ b/tests/run/int_float_builtins_as_casts_T400_long_double.pyx
@@ -1,4 +1,4 @@
-# ticket: 400
+# ticket: t400
cimport cython
diff --git a/tests/run/intern_T431.pyx b/tests/run/intern_T431.pyx
index 5851d9741..6b7ef0516 100644
--- a/tests/run/intern_T431.pyx
+++ b/tests/run/intern_T431.pyx
@@ -1,4 +1,4 @@
-# ticket: 431
+# ticket: t431
__doc__ = u"""
>>> s == s_interned
diff --git a/tests/run/ipow_crash_T562.pyx b/tests/run/ipow_crash_T562.pyx
index 6fea958b5..7b074ea5d 100644
--- a/tests/run/ipow_crash_T562.pyx
+++ b/tests/run/ipow_crash_T562.pyx
@@ -1,4 +1,4 @@
-# ticket: 562
+# ticket: t562
class IPOW:
"""
diff --git a/tests/run/kwargs_passthrough.pyx b/tests/run/kwargs_passthrough.pyx
index 704638a55..c09b6cba4 100644
--- a/tests/run/kwargs_passthrough.pyx
+++ b/tests/run/kwargs_passthrough.pyx
@@ -1,7 +1,6 @@
-cimport cython
+import cython
-
-@cython.test_fail_if_path_exists('//MergedDictNode')
+#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_passthrough(f):
"""
>>> def f(a=1): return a
@@ -80,7 +79,7 @@ def wrap_passthrough_more(f):
return wrapper
-@cython.test_fail_if_path_exists('//MergedDictNode')
+#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_passthrough2(f):
"""
>>> def f(a=1): return a
@@ -99,7 +98,7 @@ def wrap_passthrough2(f):
return wrapper
-@cython.test_fail_if_path_exists('//MergedDictNode')
+#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_modify(f):
"""
>>> def f(a=1, test=2):
@@ -123,7 +122,7 @@ def wrap_modify(f):
return wrapper
-@cython.test_fail_if_path_exists('//MergedDictNode')
+#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_modify_mix(f):
"""
>>> def f(a=1, test=2):
@@ -139,6 +138,18 @@ def wrap_modify_mix(f):
>>> wrapped(a=2, test=3)
CALLED
(2, 1)
+
+ >>> def py_modify(**kwargs):
+ ... print(sorted(kwargs.items()))
+ ... kwargs['new'] = len(kwargs)
+ ... return kwargs
+
+ >>> wrapped_modify = wrap_modify_mix(py_modify)
+ >>> sorted(wrapped_modify(a=1).items())
+ CALLED
+ [('a', 1)]
+ [('a', 1), ('test', 1)]
+ [('a', 1), ('new', 2), ('test', 1)]
"""
def wrapper(*args, **kwargs):
print("CALLED")
@@ -175,7 +186,21 @@ def wrap_modify_func(f):
return wrapper
-@cython.test_assert_path_exists('//MergedDictNode')
+def modify_in_function():
+ """
+ >>> modify_in_function()
+ {'foo': 'bar'}
+ {'foo': 'bar'}
+ """
+ def inner(**kwds):
+ kwds['foo'] = 'modified'
+ d = {'foo': 'bar'}
+ print(d)
+ inner(**d)
+ print(d)
+
+
+#@cython.test_assert_path_exists('//MergedDictNode')
def wrap_modify_func_mix(f):
"""
>>> def f(a=1, test=2):
@@ -203,12 +228,11 @@ def wrap_modify_func_mix(f):
return wrapper
-@cython.test_fail_if_path_exists('//MergedDictNode')
+#@cython.test_fail_if_path_exists('//MergedDictNode')
def wrap_reassign(f):
"""
>>> def f(a=1, test=2):
... return a, test
-
>>> wrapped = wrap_reassign(f)
>>> wrapped(1)
CALLED
@@ -227,7 +251,7 @@ def wrap_reassign(f):
return wrapper
-@cython.test_fail_if_path_exists('//MergedDictNode')
+#@cython.test_fail_if_path_exists('//MergedDictNode')
def kwargs_metaclass(**kwargs):
"""
>>> K = kwargs_metaclass()
diff --git a/tests/run/lambda_T195.pyx b/tests/run/lambda_T195.pyx
index fdbde9982..bfae08fea 100644
--- a/tests/run/lambda_T195.pyx
+++ b/tests/run/lambda_T195.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: lambda
-# ticket: 195
+# ticket: t195
__doc__ = u"""
#>>> py_identity = lambda x:x
diff --git a/tests/run/lambda_T723.pyx b/tests/run/lambda_T723.pyx
index e746a3f58..39ae66851 100644
--- a/tests/run/lambda_T723.pyx
+++ b/tests/run/lambda_T723.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 723
+# ticket: t723
# tag: lambda
def t723(a):
diff --git a/tests/run/lambda_class_T605.pyx b/tests/run/lambda_class_T605.pyx
index 82e1ff8a7..2efe77e7c 100644
--- a/tests/run/lambda_class_T605.pyx
+++ b/tests/run/lambda_class_T605.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: lambda
-# ticket: 605
+# ticket: t605
cdef int cdef_CONST = 123
CONST = 456
diff --git a/tests/run/lambda_module_T603.pyx b/tests/run/lambda_module_T603.pyx
index 245f86937..c92fce5df 100644
--- a/tests/run/lambda_module_T603.pyx
+++ b/tests/run/lambda_module_T603.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: lambda
-# ticket: 603
+# ticket: t603
# Module scope lambda functions
diff --git a/tests/run/large_consts_T237.pyx b/tests/run/large_consts_T237.pyx
index f11a24541..7c448401f 100644
--- a/tests/run/large_consts_T237.pyx
+++ b/tests/run/large_consts_T237.pyx
@@ -1,4 +1,4 @@
-# ticket: 237
+# ticket: t237
#def add_large_c():
# cdef unsigned long long val = 2**30 + 2**30
# return val
diff --git a/tests/run/letnode_T766.pyx b/tests/run/letnode_T766.pyx
index 337808ee4..0f2d53e0b 100644
--- a/tests/run/letnode_T766.pyx
+++ b/tests/run/letnode_T766.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 766
+# ticket: t766
# tag: letnode
def test_letnode_range(int n):
diff --git a/tests/run/list_comp_in_closure_T598.pyx b/tests/run/list_comp_in_closure_T598.pyx
index 3f418add1..45b572ac0 100644
--- a/tests/run/list_comp_in_closure_T598.pyx
+++ b/tests/run/list_comp_in_closure_T598.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: closures
-# ticket: 598
+# ticket: t598
# cython: language_level=3
def list_comp_in_closure():
diff --git a/tests/run/locals_T732.pyx b/tests/run/locals_T732.pyx
index 6b3307523..6ce8c7447 100644
--- a/tests/run/locals_T732.pyx
+++ b/tests/run/locals_T732.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 731
+# ticket: t731
# tag: locals, vars, dir
cimport cython
diff --git a/tests/run/locals_expressions_T430.pyx b/tests/run/locals_expressions_T430.pyx
index a0f8a0d62..a0e9dff3e 100644
--- a/tests/run/locals_expressions_T430.pyx
+++ b/tests/run/locals_expressions_T430.pyx
@@ -1,4 +1,4 @@
-# ticket: 430
+# ticket: t430
__doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items())
diff --git a/tests/run/locals_rebind_T429.pyx b/tests/run/locals_rebind_T429.pyx
index 9b3f06a5a..e84a13947 100644
--- a/tests/run/locals_rebind_T429.pyx
+++ b/tests/run/locals_rebind_T429.pyx
@@ -1,4 +1,4 @@
-# ticket: 429
+# ticket: t429
__doc__ = u"""
>>> sorted( get_locals(1,2,3, k=5) .items())
diff --git a/tests/run/method_module_name_T422.pyx b/tests/run/method_module_name_T422.pyx
index fbefa2144..731cd1b30 100644
--- a/tests/run/method_module_name_T422.pyx
+++ b/tests/run/method_module_name_T422.pyx
@@ -1,4 +1,4 @@
-# ticket: 422
+# ticket: t422
"""
>>> Foo.incr.__module__ is not None
diff --git a/tests/run/methodmangling_T5.py b/tests/run/methodmangling_T5.py
index 4d2cfe1d8..9e2b7c63a 100644
--- a/tests/run/methodmangling_T5.py
+++ b/tests/run/methodmangling_T5.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 5
+# ticket: t5
# A small number of extra tests checking:
# 1) this works correctly with pure-Python-mode decorators - methodmangling_pure.py.
diff --git a/tests/run/non_dict_kwargs_T470.pyx b/tests/run/non_dict_kwargs_T470.pyx
index b60d56210..be6f8c67b 100644
--- a/tests/run/non_dict_kwargs_T470.pyx
+++ b/tests/run/non_dict_kwargs_T470.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 470
+# ticket: t470
def func(**kwargs):
diff --git a/tests/run/numpy_ValueError_T172.pyx b/tests/run/numpy_ValueError_T172.pyx
index 66558eefc..233048ce7 100644
--- a/tests/run/numpy_ValueError_T172.pyx
+++ b/tests/run/numpy_ValueError_T172.pyx
@@ -1,4 +1,4 @@
-# ticket: 172
+# ticket: t172
# tag: numpy
__doc__ = u"""
diff --git a/tests/run/numpy_bufacc_T155.pyx b/tests/run/numpy_bufacc_T155.pyx
index 17a8525fd..2c637ebc4 100644
--- a/tests/run/numpy_bufacc_T155.pyx
+++ b/tests/run/numpy_bufacc_T155.pyx
@@ -1,4 +1,4 @@
-# ticket: 155
+# ticket: t155
# tag: numpy
"""
diff --git a/tests/run/numpy_test.pyx b/tests/run/numpy_test.pyx
index e81547c32..d2718a463 100644
--- a/tests/run/numpy_test.pyx
+++ b/tests/run/numpy_test.pyx
@@ -10,16 +10,10 @@ def little_endian():
cdef int endian_detector = 1
return (<char*>&endian_detector)[0] != 0
-__test__ = {}
def testcase(f):
- __test__[f.__name__] = f.__doc__
- return f
-
-def testcase_have_buffer_interface(f):
- major, minor, *rest = np.__version__.split('.')
- if (int(major), int(minor)) >= (1, 5):
- __test__[f.__name__] = f.__doc__
+ # testcase decorator now does nothing (following changes to doctest)
+ # but is a useful indicator of what functions are designed as tests
return f
if little_endian():
@@ -180,7 +174,7 @@ try:
('a', np.dtype('i,i')),\
('b', np.dtype('i,i'))\
])))) # doctest: +NORMALIZE_WHITESPACE
- array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))],
+ array([((0, 0), (0, 0)), ((1, 2), (1, 4)), ((1, 2), (1, 4))],
dtype=[('a', [('f0', '!i4'), ('f1', '!i4')]), ('b', [('f0', '!i4'), ('f1', '!i4')])])
>>> print(test_nested_dtypes(np.zeros((3,), dtype=np.dtype([\
@@ -233,7 +227,7 @@ try:
8,16
>>> test_point_record() # doctest: +NORMALIZE_WHITESPACE
- array([(0., 0.), (1., -1.), (2., -2.)],
+ array([(0., 0.), (1., -1.), (2., -2.)],
dtype=[('x', '!f8'), ('y', '!f8')])
"""
@@ -267,8 +261,6 @@ try:
except:
__doc__ = u""
-__test__[__name__] = __doc__
-
def assert_dtype_sizes():
assert sizeof(np.int8_t) == 1
@@ -679,7 +671,6 @@ def get_Foo_array():
data[5].b = 9.0
return np.asarray(<Foo[:]>data).copy()
-@testcase_have_buffer_interface
def test_fused_ndarray(fused_ndarray a):
"""
>>> import cython
@@ -728,9 +719,6 @@ cpdef test_fused_cpdef_ndarray(fused_ndarray a):
else:
print b[5]
-testcase_have_buffer_interface(test_fused_cpdef_ndarray)
-
-@testcase_have_buffer_interface
def test_fused_cpdef_ndarray_cdef_call():
"""
>>> test_fused_cpdef_ndarray_cdef_call()
diff --git a/tests/run/packedstruct_T290.pyx b/tests/run/packedstruct_T290.pyx
index 203008ca7..d9381567e 100644
--- a/tests/run/packedstruct_T290.pyx
+++ b/tests/run/packedstruct_T290.pyx
@@ -1,4 +1,4 @@
-# ticket: 290
+# ticket: t290
"""
>>> f()
diff --git a/tests/run/parallel_swap_assign_T425.pyx b/tests/run/parallel_swap_assign_T425.pyx
index fb7d1ac29..b6e7e233d 100644
--- a/tests/run/parallel_swap_assign_T425.pyx
+++ b/tests/run/parallel_swap_assign_T425.pyx
@@ -1,4 +1,4 @@
-# ticket: 425
+# ticket: t425
cimport cython
diff --git a/tests/run/posonly.py b/tests/run/posonly.py
index 29c6aef7c..6ea0c3127 100644
--- a/tests/run/posonly.py
+++ b/tests/run/posonly.py
@@ -264,7 +264,7 @@ class TestPosonlyMethods(object):
Got type error
>>> TestPosonlyMethods().f(1, b=2) # doctest: +ELLIPSIS
Traceback (most recent call last):
- TypeError: f() got ... keyword argument... 'b'
+ TypeError: ...f() got ... keyword argument... 'b'
"""
def f(self, a, b, /):
return a, b
@@ -316,10 +316,10 @@ def test_closures1(x,y):
10
>>> test_closures1(1,2)(3) # doctest: +ELLIPSIS
Traceback (most recent call last):
- TypeError: g() ... positional argument...
+ TypeError: ...g() ... positional argument...
>>> test_closures1(1,2)(3,4,5) # doctest: +ELLIPSIS
Traceback (most recent call last):
- TypeError: g() ... positional argument...
+ TypeError: ...g() ... positional argument...
"""
def g(x2,/,y2):
return x + y + x2 + y2
@@ -341,10 +341,10 @@ def test_closures3(x,/,y):
10
>>> test_closures3(1,2)(3) # doctest: +ELLIPSIS
Traceback (most recent call last):
- TypeError: g() ... positional argument...
+ TypeError: ...g() ... positional argument...
>>> test_closures3(1,2)(3,4,5) # doctest: +ELLIPSIS
Traceback (most recent call last):
- TypeError: g() ... positional argument...
+ TypeError: ...g() ... positional argument...
"""
def g(x2,/,y2):
return x + y + x2 + y2
@@ -562,7 +562,7 @@ class TestExtensionClass:
(1, 2, 4)
>>> t.f(1, 2, 5, c=6) # doctest: +ELLIPSIS
Traceback (most recent call last):
- TypeError: f() got multiple values for ...argument 'c'
+ TypeError: ...f() got multiple values for ...argument 'c'
"""
def f(self, a, b, /, c=3):
return (a,b,c)
diff --git a/tests/run/property_decorator_T593.py b/tests/run/property_decorator_T593.py
index 45ddb57a8..d34db8951 100644
--- a/tests/run/property_decorator_T593.py
+++ b/tests/run/property_decorator_T593.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 593
+# ticket: t593
# tag: property, decorator
my_property = property
diff --git a/tests/run/ptr_warning_T714.pyx b/tests/run/ptr_warning_T714.pyx
index 3ec8b5b12..3bd330525 100644
--- a/tests/run/ptr_warning_T714.pyx
+++ b/tests/run/ptr_warning_T714.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: werror
-# ticket: 714
+# ticket: t714
def test_ptr():
"""
diff --git a/tests/run/pure_cdef_class_property_decorator_T264.pxd b/tests/run/pure_cdef_class_property_decorator_T264.pxd
index 4c1d879cf..e5e616a00 100644
--- a/tests/run/pure_cdef_class_property_decorator_T264.pxd
+++ b/tests/run/pure_cdef_class_property_decorator_T264.pxd
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 264
+# ticket: t264
# tag: property, decorator
cdef class Prop:
diff --git a/tests/run/pure_cdef_class_property_decorator_T264.py b/tests/run/pure_cdef_class_property_decorator_T264.py
index 70f299b4f..8ca2fc7b2 100644
--- a/tests/run/pure_cdef_class_property_decorator_T264.py
+++ b/tests/run/pure_cdef_class_property_decorator_T264.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 264
+# ticket: t264
# tag: property, decorator
class Prop(object):
diff --git a/tests/run/pxd_argument_names.srctree b/tests/run/pxd_argument_names.srctree
index 885643609..94262ef92 100644
--- a/tests/run/pxd_argument_names.srctree
+++ b/tests/run/pxd_argument_names.srctree
@@ -1,5 +1,5 @@
# mode: run
-# ticket: gh1888
+# ticket: 1888
PYTHON setup.py build_ext --inplace
PYTHON -c "import a; a.test()"
diff --git a/tests/run/pyclass_scope_T671.py b/tests/run/pyclass_scope_T671.py
index 911268e22..00a10de11 100644
--- a/tests/run/pyclass_scope_T671.py
+++ b/tests/run/pyclass_scope_T671.py
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 671
+# ticket: t671
A = 1234
diff --git a/tests/run/pyfunction_redefine_T489.pyx b/tests/run/pyfunction_redefine_T489.pyx
index cf393407f..5931ff1b6 100644
--- a/tests/run/pyfunction_redefine_T489.pyx
+++ b/tests/run/pyfunction_redefine_T489.pyx
@@ -1,4 +1,4 @@
-# ticket: 489
+# ticket: t489
"""
>>> xxx
diff --git a/tests/run/pyobjcast_T313.pyx b/tests/run/pyobjcast_T313.pyx
index fb4ef80a0..0e5fc7e8e 100644
--- a/tests/run/pyobjcast_T313.pyx
+++ b/tests/run/pyobjcast_T313.pyx
@@ -1,4 +1,4 @@
-# ticket: 313
+# ticket: t313
# Ensure casting still works to void*
"""
diff --git a/tests/run/raise_memory_error_T650.pyx b/tests/run/raise_memory_error_T650.pyx
index 76b1ef4ab..8bced08e0 100644
--- a/tests/run/raise_memory_error_T650.pyx
+++ b/tests/run/raise_memory_error_T650.pyx
@@ -1,4 +1,4 @@
-# ticket: 650
+# ticket: t650
cimport cython
diff --git a/tests/run/range_optimisation_T203.pyx b/tests/run/range_optimisation_T203.pyx
index 880d8952d..bf8c0c978 100644
--- a/tests/run/range_optimisation_T203.pyx
+++ b/tests/run/range_optimisation_T203.pyx
@@ -1,4 +1,4 @@
-# ticket: 203
+# ticket: t203
cdef int get_bound(int m):
print u"get_bound(%s)"%m
diff --git a/tests/run/self_in_ext_type_closure.pyx b/tests/run/self_in_ext_type_closure.pyx
index efb116659..ae45cce76 100644
--- a/tests/run/self_in_ext_type_closure.pyx
+++ b/tests/run/self_in_ext_type_closure.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 742
+# ticket: t742
import cython
diff --git a/tests/run/set.pyx b/tests/run/set.pyx
index d0bed081c..b49eaa1ed 100644
--- a/tests/run/set.pyx
+++ b/tests/run/set.pyx
@@ -417,7 +417,8 @@ def test_empty_frozenset():
True
>>> len(s)
0
- >>> s is frozenset() # singleton!
+ >>> import sys
+ >>> sys.version_info >= (3, 10) or s is frozenset() # singleton (in Python < 3.10)!
True
"""
return frozenset()
@@ -430,7 +431,8 @@ def test_empty_frozenset():
)
def test_singleton_empty_frozenset():
"""
- >>> test_singleton_empty_frozenset() # from CPython's test_set.py
+ >>> import sys
+ >>> test_singleton_empty_frozenset() if sys.version_info < (3, 10) else 1 # from CPython's test_set.py
1
"""
f = frozenset()
@@ -438,7 +440,7 @@ def test_singleton_empty_frozenset():
frozenset(), frozenset([]), frozenset(()), frozenset(''),
frozenset(range(0)), frozenset(frozenset()),
frozenset(f), f]
- return len(set(map(id, efs)))
+ return len(set(map(id, efs))) # note, only a singleton in Python <3.10
def sorted(it):
diff --git a/tests/run/short_circuit_T404.pyx b/tests/run/short_circuit_T404.pyx
index 09affaf7a..dbb24820e 100644
--- a/tests/run/short_circuit_T404.pyx
+++ b/tests/run/short_circuit_T404.pyx
@@ -1,4 +1,4 @@
-# ticket: 404
+# ticket: t404
cdef long foo(long x):
print "foo(%s)" % x
diff --git a/tests/run/special_methods_T561.pyx b/tests/run/special_methods_T561.pyx
index 350d452f4..d585f35d0 100644
--- a/tests/run/special_methods_T561.pyx
+++ b/tests/run/special_methods_T561.pyx
@@ -1,6 +1,6 @@
# mode: run
-# ticket: 561
-# ticket: 3
+# ticket: tt561
+# ticket: tt3
# The patch in #561 changes code generation for most special methods
# to remove the Cython-generated wrapper and let PyType_Ready()
diff --git a/tests/run/special_methods_T561_py2.pyx b/tests/run/special_methods_T561_py2.pyx
index 285f820f6..9781376b3 100644
--- a/tests/run/special_methods_T561_py2.pyx
+++ b/tests/run/special_methods_T561_py2.pyx
@@ -1,4 +1,4 @@
-# ticket: 561
+# ticket: t561
# tag: py2
# This file tests the behavior of special methods under Python 2
# after #561. (Only methods whose behavior differs between Python 2 and 3
diff --git a/tests/run/special_methods_T561_py3.pyx b/tests/run/special_methods_T561_py3.pyx
index 932002254..0a5f53547 100644
--- a/tests/run/special_methods_T561_py3.pyx
+++ b/tests/run/special_methods_T561_py3.pyx
@@ -1,4 +1,4 @@
-# ticket: 561
+# ticket: t561
# tag: py3
# This file tests the behavior of special methods under Python 3
# after #561. (Only methods whose behavior differs between Python 2 and 3
diff --git a/tests/run/ssize_t_T399.pyx b/tests/run/ssize_t_T399.pyx
index 4a8f65d68..265a3c924 100644
--- a/tests/run/ssize_t_T399.pyx
+++ b/tests/run/ssize_t_T399.pyx
@@ -1,4 +1,4 @@
-# ticket: 399
+# ticket: t399
__doc__ = u"""
>>> test(-2)
diff --git a/tests/run/starred_target_T664.pyx b/tests/run/starred_target_T664.pyx
index 0d291c648..5a88d5ab2 100644
--- a/tests/run/starred_target_T664.pyx
+++ b/tests/run/starred_target_T664.pyx
@@ -1,4 +1,4 @@
-# ticket: 664
+# ticket: t664
def assign():
"""
diff --git a/tests/run/str_char_coercion_T412.pyx b/tests/run/str_char_coercion_T412.pyx
index 6a470e2b7..c1c0ba709 100644
--- a/tests/run/str_char_coercion_T412.pyx
+++ b/tests/run/str_char_coercion_T412.pyx
@@ -1,4 +1,4 @@
-# ticket: 412
+# ticket: t412
cdef int i = 'x'
cdef char c = 'x'
diff --git a/tests/run/temp_alloc_T409.pyx b/tests/run/temp_alloc_T409.pyx
index 383e1ef6f..425b7064b 100644
--- a/tests/run/temp_alloc_T409.pyx
+++ b/tests/run/temp_alloc_T409.pyx
@@ -1,4 +1,4 @@
-# ticket: 409
+# ticket: t409
# Extracted from sage/plot/plot3d/index_face_set.pyx:502
# Turns out to be a bug in implementation of PEP 3132 (Extended Iterable Unpacking)
diff --git a/tests/run/temp_sideeffects_T654.pyx b/tests/run/temp_sideeffects_T654.pyx
index 8a00f7e5b..fe8f03fee 100644
--- a/tests/run/temp_sideeffects_T654.pyx
+++ b/tests/run/temp_sideeffects_T654.pyx
@@ -1,4 +1,4 @@
-# ticket: 654
+# ticket: t654
# function call arguments
diff --git a/tests/run/test_asyncgen.py b/tests/run/test_asyncgen.py
index 9b95a6201..410d4fe0b 100644
--- a/tests/run/test_asyncgen.py
+++ b/tests/run/test_asyncgen.py
@@ -534,9 +534,9 @@ class AsyncGenAsyncioTest(unittest.TestCase):
def test_async_gen_asyncio_01(self):
async def gen():
yield 1
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
yield 2
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
return
yield 3
@@ -546,7 +546,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
def test_async_gen_asyncio_02(self):
async def gen():
yield 1
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
yield 2
1 / ZERO
yield 3
@@ -560,7 +560,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
class Gen:
async def __aiter__(self):
yield 1
- await asyncio.sleep(0.01, loop=loop)
+ await asyncio.sleep(0.01)
yield 2
res = loop.run_until_complete(self.to_list(Gen()))
@@ -569,13 +569,13 @@ class AsyncGenAsyncioTest(unittest.TestCase):
def test_async_gen_asyncio_anext_04(self):
async def foo():
yield 1
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
try:
yield 2
yield 3
except ZeroDivisionError:
yield 1000
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
yield 4
async def run1():
@@ -726,7 +726,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
yield 1
1 / ZERO
finally:
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
yield 12
async def run():
@@ -749,8 +749,8 @@ class AsyncGenAsyncioTest(unittest.TestCase):
yield 1
1 / ZERO
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE += 1
DONE += 1000
@@ -776,8 +776,8 @@ class AsyncGenAsyncioTest(unittest.TestCase):
DONE += 1000
yield 2
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE += 1
DONE += 1000
@@ -792,7 +792,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
# Silence ResourceWarnings
fut.cancel()
- self.loop.run_until_complete(asyncio.sleep(0.01, loop=self.loop))
+ self.loop.run_until_complete(asyncio.sleep(0.01))
@needs_py36_asyncio
def test_async_gen_asyncio_gc_aclose_09(self):
@@ -804,8 +804,8 @@ class AsyncGenAsyncioTest(unittest.TestCase):
while True:
yield 1
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE = 1
async def run():
@@ -814,7 +814,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
await g.__anext__()
del g
- await asyncio.sleep(0.2, loop=self.loop)
+ await asyncio.sleep(0.2)
self.loop.run_until_complete(run())
self.assertEqual(DONE, 1)
@@ -932,15 +932,15 @@ class AsyncGenAsyncioTest(unittest.TestCase):
async def gen():
nonlocal DONE
try:
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
v = yield 1
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
yield v * 2
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
return
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE = 1
async def run():
@@ -962,21 +962,21 @@ class AsyncGenAsyncioTest(unittest.TestCase):
DONE = 0
async def sleep_n_crash(delay):
- await asyncio.sleep(delay, loop=self.loop)
+ await asyncio.sleep(delay)
1 / ZERO
async def gen():
nonlocal DONE
try:
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
v = yield 1
await sleep_n_crash(0.01)
DONE += 1000
yield v * 2
finally:
assert sys.exc_info()[0] == ZeroDivisionError
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE += 1
async def run():
@@ -995,7 +995,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
DONE = 0
async def sleep_n_crash(delay):
- fut = asyncio.ensure_future(asyncio.sleep(delay, loop=self.loop),
+ fut = asyncio.ensure_future(asyncio.sleep(delay),
loop=self.loop)
self.loop.call_later(delay / 2, lambda: fut.cancel())
return await fut
@@ -1003,14 +1003,14 @@ class AsyncGenAsyncioTest(unittest.TestCase):
async def gen():
nonlocal DONE
try:
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
v = yield 1
await sleep_n_crash(0.01)
DONE += 1000
yield v * 2
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE = 1
async def run():
@@ -1049,18 +1049,18 @@ class AsyncGenAsyncioTest(unittest.TestCase):
async def gen():
nonlocal DONE
try:
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
try:
v = yield 1
except FooEr:
v = 1000
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
yield v * 2
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
# return
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE = 1
async def run():
@@ -1085,7 +1085,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
pass
async def sleep_n_crash(delay):
- fut = asyncio.ensure_future(asyncio.sleep(delay, loop=self.loop),
+ fut = asyncio.ensure_future(asyncio.sleep(delay),
loop=self.loop)
self.loop.call_later(delay / 2, lambda: fut.cancel())
return await fut
@@ -1093,17 +1093,17 @@ class AsyncGenAsyncioTest(unittest.TestCase):
async def gen():
nonlocal DONE
try:
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
try:
v = yield 1
except FooEr:
await sleep_n_crash(0.01)
yield v * 2
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
# return
finally:
- await asyncio.sleep(0.01, loop=self.loop)
- await asyncio.sleep(0.01, loop=self.loop)
+ await asyncio.sleep(0.01)
+ await asyncio.sleep(0.01)
DONE = 1
async def run():
@@ -1203,10 +1203,10 @@ class AsyncGenAsyncioTest(unittest.TestCase):
async def waiter(timeout):
nonlocal finalized
try:
- await asyncio.sleep(timeout, loop=self.loop)
+ await asyncio.sleep(timeout)
yield 1
finally:
- await asyncio.sleep(0, loop=self.loop)
+ await asyncio.sleep(0)
finalized += 1
async def wait():
@@ -1216,7 +1216,7 @@ class AsyncGenAsyncioTest(unittest.TestCase):
t1 = self.loop.create_task(wait())
t2 = self.loop.create_task(wait())
- self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
+ self.loop.run_until_complete(asyncio.sleep(0.1))
# Silence warnings
diff --git a/tests/run/test_exceptions.pyx b/tests/run/test_exceptions.pyx
index 14a127db2..d47c9c4db 100644
--- a/tests/run/test_exceptions.pyx
+++ b/tests/run/test_exceptions.pyx
@@ -13,11 +13,16 @@ import pickle
import weakref
import errno
-from test.support import (TESTFN, captured_stderr, check_impl_detail,
- check_warnings, gc_collect,
+from test.support import (captured_stderr, check_impl_detail, gc_collect,
# no_tracing, cpython_only,
- unlink, import_module, script_helper,
- SuppressCrashReport)
+ script_helper, SuppressCrashReport)
+try:
+ from test.support.os_helper import TESTFN, unlink
+ from test.support.warnings_helper import check_warnings
+ from test.support.import_helper import import_module
+except ImportError:
+ # Python 3.9 and older
+ from test.support import check_warnings, TESTFN, unlink, import_module
no_tracing = unittest.skip("For nested functions, Cython generates a C call without recursion checks.")
diff --git a/tests/run/test_fstring.pyx b/tests/run/test_fstring.pyx
index f2e0825be..a670e2ccb 100644
--- a/tests/run/test_fstring.pyx
+++ b/tests/run/test_fstring.pyx
@@ -55,10 +55,10 @@ class TestCase(CythonTest):
def assertEqual(self, first, second, msg=None):
# strip u'' string prefixes in Py2
if first != second and isinstance(first, unicode):
- stripped_first = first.replace("u'", "'").replace('u"', '"')
+ stripped_first = first.replace(u"u'", u"'").replace(u'u"', u'"')
if stripped_first == second:
first = stripped_first
- elif stripped_first.decode('unicode_escape') == second:
+ elif u'\\' in stripped_first and stripped_first.decode('unicode_escape') == second:
first = stripped_first.decode('unicode_escape')
super(TestCase, self).assertEqual(first, second, msg)
diff --git a/tests/run/test_genericclass.py b/tests/run/test_genericclass.py
index e6313cb84..e52fc2dc7 100644
--- a/tests/run/test_genericclass.py
+++ b/tests/run/test_genericclass.py
@@ -4,9 +4,159 @@
# COPIED FROM CPython 3.7
+import contextlib
import unittest
import sys
+class TestMROEntry(unittest.TestCase):
+ def test_mro_entry_signature(self):
+ tested = []
+ class B: ...
+ class C:
+ def __mro_entries__(self, *args, **kwargs):
+ tested.extend([args, kwargs])
+ return (C,)
+ c = C()
+ self.assertEqual(tested, [])
+ class D(B, c): ...
+ self.assertEqual(tested[0], ((B, c),))
+ self.assertEqual(tested[1], {})
+
+ def test_mro_entry(self):
+ tested = []
+ class A: ...
+ class B: ...
+ class C:
+ def __mro_entries__(self, bases):
+ tested.append(bases)
+ return (self.__class__,)
+ c = C()
+ self.assertEqual(tested, [])
+ class D(A, c, B): ...
+ self.assertEqual(tested[-1], (A, c, B))
+ self.assertEqual(D.__bases__, (A, C, B))
+ self.assertEqual(D.__orig_bases__, (A, c, B))
+ self.assertEqual(D.__mro__, (D, A, C, B, object))
+ d = D()
+ class E(d): ...
+ self.assertEqual(tested[-1], (d,))
+ self.assertEqual(E.__bases__, (D,))
+
+ def test_mro_entry_none(self):
+ tested = []
+ class A: ...
+ class B: ...
+ class C:
+ def __mro_entries__(self, bases):
+ tested.append(bases)
+ return ()
+ c = C()
+ self.assertEqual(tested, [])
+ class D(A, c, B): ...
+ self.assertEqual(tested[-1], (A, c, B))
+ self.assertEqual(D.__bases__, (A, B))
+ self.assertEqual(D.__orig_bases__, (A, c, B))
+ self.assertEqual(D.__mro__, (D, A, B, object))
+ class E(c): ...
+ self.assertEqual(tested[-1], (c,))
+ if sys.version_info[0] > 2:
+ # not all of it works on Python 2
+ self.assertEqual(E.__bases__, (object,))
+ self.assertEqual(E.__orig_bases__, (c,))
+ if sys.version_info[0] > 2:
+ # not all of it works on Python 2
+ self.assertEqual(E.__mro__, (E, object))
+
+ def test_mro_entry_with_builtins(self):
+ tested = []
+ class A: ...
+ class C:
+ def __mro_entries__(self, bases):
+ tested.append(bases)
+ return (dict,)
+ c = C()
+ self.assertEqual(tested, [])
+ class D(A, c): ...
+ self.assertEqual(tested[-1], (A, c))
+ self.assertEqual(D.__bases__, (A, dict))
+ self.assertEqual(D.__orig_bases__, (A, c))
+ self.assertEqual(D.__mro__, (D, A, dict, object))
+
+ def test_mro_entry_with_builtins_2(self):
+ tested = []
+ class C:
+ def __mro_entries__(self, bases):
+ tested.append(bases)
+ return (C,)
+ c = C()
+ self.assertEqual(tested, [])
+ class D(c, dict): ...
+ self.assertEqual(tested[-1], (c, dict))
+ self.assertEqual(D.__bases__, (C, dict))
+ self.assertEqual(D.__orig_bases__, (c, dict))
+ self.assertEqual(D.__mro__, (D, C, dict, object))
+
+ def test_mro_entry_errors(self):
+ class C_too_many:
+ def __mro_entries__(self, bases, something, other):
+ return ()
+ c = C_too_many()
+ with self.assertRaises(TypeError):
+ class D(c): ...
+ class C_too_few:
+ def __mro_entries__(self):
+ return ()
+ d = C_too_few()
+ with self.assertRaises(TypeError):
+ class D(d): ...
+
+ def test_mro_entry_errors_2(self):
+ class C_not_callable:
+ __mro_entries__ = "Surprise!"
+ c = C_not_callable()
+ with self.assertRaises(TypeError):
+ class D(c): ...
+ class C_not_tuple:
+ def __mro_entries__(self):
+ return object
+ c = C_not_tuple()
+ with self.assertRaises(TypeError):
+ class D(c): ...
+
+ def test_mro_entry_metaclass(self):
+ meta_args = []
+ class Meta(type):
+ def __new__(mcls, name, bases, ns):
+ meta_args.extend([mcls, name, bases, ns])
+ return super().__new__(mcls, name, bases, ns)
+ class A: ...
+ class C:
+ def __mro_entries__(self, bases):
+ return (A,)
+ c = C()
+ class D(c, metaclass=Meta):
+ x = 1
+ self.assertEqual(meta_args[0], Meta)
+ self.assertEqual(meta_args[1], 'D')
+ self.assertEqual(meta_args[2], (A,))
+ self.assertEqual(meta_args[3]['x'], 1)
+ self.assertEqual(D.__bases__, (A,))
+ self.assertEqual(D.__orig_bases__, (c,))
+ self.assertEqual(D.__mro__, (D, A, object))
+ self.assertEqual(D.__class__, Meta)
+
+ @unittest.skipIf(sys.version_info < (3, 7), "'type' checks for __mro_entries__ not implemented")
+ def test_mro_entry_type_call(self):
+ # Substitution should _not_ happen in direct type call
+ class C:
+ def __mro_entries__(self, bases):
+ return ()
+ c = C()
+ with self.assertRaisesRegex(TypeError,
+ "MRO entry resolution; "
+ "use types.new_class()"):
+ type('Bad', (c,), {})
+
class TestClassGetitem(unittest.TestCase):
# BEGIN - Additional tests from cython
diff --git a/tests/run/test_unicode.pyx b/tests/run/test_unicode.pyx
index 742103a36..2386b5124 100644
--- a/tests/run/test_unicode.pyx
+++ b/tests/run/test_unicode.pyx
@@ -1469,19 +1469,19 @@ class UnicodeTest(CommonTest,
class Str(str, enum.Enum):
ABC = 'abc'
# Testing Unicode formatting strings...
- self.assertEqual("%s, %s" % (Str.ABC, Str.ABC),
- 'Str.ABC, Str.ABC')
- self.assertEqual("%s, %s, %d, %i, %u, %f, %5.2f" %
+ self.assertEqual(("%s, %s" % (Str.ABC, Str.ABC)).replace("Str.", ""),
+ 'ABC, ABC')
+ self.assertEqual(("%s, %s, %d, %i, %u, %f, %5.2f" %
(Str.ABC, Str.ABC,
Int.IDES, Int.IDES, Int.IDES,
- Float.PI, Float.PI),
- 'Str.ABC, Str.ABC, 15, 15, 15, 3.141593, 3.14')
+ Float.PI, Float.PI)).replace("Str.", ""),
+ 'ABC, ABC, 15, 15, 15, 3.141593, 3.14')
# formatting jobs delegated from the string implementation:
- self.assertEqual('...%(foo)s...' % {'foo':Str.ABC},
- '...Str.ABC...')
- self.assertEqual('...%(foo)s...' % {'foo':Int.IDES},
- '...Int.IDES...')
+ self.assertEqual(('...%(foo)s...' % {'foo':Str.ABC}).replace("Str.", ""),
+ '...ABC...')
+ self.assertEqual(('...%(foo)s...' % {'foo':Int.IDES}).replace("Int.", ""),
+ '...IDES...')
self.assertEqual('...%(foo)i...' % {'foo':Int.IDES},
'...15...')
self.assertEqual('...%(foo)d...' % {'foo':Int.IDES},
diff --git a/tests/run/time_pxd.pyx b/tests/run/time_pxd.pyx
new file mode 100644
index 000000000..91e6e8d24
--- /dev/null
+++ b/tests/run/time_pxd.pyx
@@ -0,0 +1,59 @@
+# mode: run
+# tag: py3only,pytime
+
+import time
+
+from cpython cimport time as ctime
+
+
+def test_time():
+ """
+ >>> tic1, tic2, tic3 = test_time()
+ >>> tic1 <= tic3 # sanity check
+ True
+ >>> tic1 <= tic2
+ True
+ >>> tic2 <= tic3
+ True
+ """
+ # check that ctime.time() matches time.time() to within call-time tolerance
+ tic1 = time.time()
+ tic2 = ctime.time()
+ tic3 = time.time()
+
+ return tic1, tic2, tic3
+
+
+def test_localtime():
+ """
+ >>> ltp, ltc = test_localtime()
+ >>> ltp.tm_year == ltc['tm_year'] or (ltp.tm_year, ltc['tm_year'])
+ True
+ >>> ltp.tm_mon == ltc['tm_mon'] or (ltp.tm_mon, ltc['tm_mon'])
+ True
+ >>> ltp.tm_mday == ltc['tm_mday'] or (ltp.tm_mday, ltc['tm_mday'])
+ True
+ >>> ltp.tm_hour == ltc['tm_hour'] or (ltp.tm_hour, ltc['tm_hour'])
+ True
+ >>> ltp.tm_min == ltc['tm_min'] or (ltp.tm_min, ltc['tm_min'])
+ True
+ >>> ltp.tm_sec == ltc['tm_sec'] or (ltp.tm_sec, ltc['tm_sec'])
+ True
+ >>> ltp.tm_wday == ltc['tm_wday'] or (ltp.tm_wday, ltc['tm_wday'])
+ True
+ >>> ltp.tm_yday == ltc['tm_yday'] or (ltp.tm_yday, ltc['tm_yday'])
+ True
+ >>> ltp.tm_isdst == ltc['tm_isdst'] or (ltp.tm_isdst, ltc['tm_isdst'])
+ True
+ """
+ ltp = time.localtime()
+ ltc = ctime.localtime()
+
+ if ltp.tm_sec != ltc.tm_sec:
+ # If the time.localtime call is just before the end of a second and the
+ # ctime.localtime call is just after the beginning of the next second,
+ # re-call. This should not occur twice in a row.
+ ltp = time.localtime()
+ ltc = ctime.localtime()
+
+ return ltp, ltc
diff --git a/tests/run/tp_new.pyx b/tests/run/tp_new.pyx
index 0da1c0bcc..45b52259f 100644
--- a/tests/run/tp_new.pyx
+++ b/tests/run/tp_new.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: exttype, tpnew
-# ticket: 808
+# ticket: t808
cimport cython
diff --git a/tests/run/tp_new_T454.pyx b/tests/run/tp_new_T454.pyx
index 893ef9b1b..d3401442c 100644
--- a/tests/run/tp_new_T454.pyx
+++ b/tests/run/tp_new_T454.pyx
@@ -1,4 +1,4 @@
-# ticket: 454
+# ticket: t454
cimport cython
diff --git a/tests/run/tupleunpack_T298.pyx b/tests/run/tupleunpack_T298.pyx
index 7763b1fc7..7e3150243 100644
--- a/tests/run/tupleunpack_T298.pyx
+++ b/tests/run/tupleunpack_T298.pyx
@@ -1,4 +1,4 @@
-# ticket: 298
+# ticket: t298
"""
>>> func()
diff --git a/tests/run/tupleunpack_T712.pyx b/tests/run/tupleunpack_T712.pyx
index 24d750849..73b3c1446 100644
--- a/tests/run/tupleunpack_T712.pyx
+++ b/tests/run/tupleunpack_T712.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 712
+# ticket: t712
def single_from_string():
"""
diff --git a/tests/run/type_inference_T768.pyx b/tests/run/type_inference_T768.pyx
index cb7b9eccb..8f1f2e61e 100644
--- a/tests/run/type_inference_T768.pyx
+++ b/tests/run/type_inference_T768.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 768
+# ticket: t768
from cython cimport typeof
def type_inference_del_int():
diff --git a/tests/run/type_inference_T768_cpp.pyx b/tests/run/type_inference_T768_cpp.pyx
index 56fad4dab..295351914 100644
--- a/tests/run/type_inference_T768_cpp.pyx
+++ b/tests/run/type_inference_T768_cpp.pyx
@@ -1,6 +1,6 @@
# mode: run
# tag: cpp
-# ticket: 768
+# ticket: t768
from cython cimport typeof
cdef extern from "shapes.h" namespace "shapes":
diff --git a/tests/run/type_slots_int_long_T287.pyx b/tests/run/type_slots_int_long_T287.pyx
index 2426225b5..7b66125b9 100644
--- a/tests/run/type_slots_int_long_T287.pyx
+++ b/tests/run/type_slots_int_long_T287.pyx
@@ -1,4 +1,4 @@
-# ticket: 287
+# ticket: t287
__doc__ = u"""
>>> print( "%d" % Int() )
diff --git a/tests/run/typeddefaultargT373.pyx b/tests/run/typeddefaultargT373.pyx
index 98ac85c3a..d817c97c7 100644
--- a/tests/run/typeddefaultargT373.pyx
+++ b/tests/run/typeddefaultargT373.pyx
@@ -1,4 +1,4 @@
-# ticket: 373
+# ticket: t373
import math
diff --git a/tests/run/typedfieldbug_T303.pyx b/tests/run/typedfieldbug_T303.pyx
index 4298a1cce..e1790c574 100644
--- a/tests/run/typedfieldbug_T303.pyx
+++ b/tests/run/typedfieldbug_T303.pyx
@@ -1,5 +1,5 @@
# mode: run
-# ticket: 303
+# ticket: t303
__doc__ = """
>>> try: readonly()
diff --git a/tests/run/typetest_T417.pyx b/tests/run/typetest_T417.pyx
index 7d7b24902..622b35416 100644
--- a/tests/run/typetest_T417.pyx
+++ b/tests/run/typetest_T417.pyx
@@ -1,4 +1,4 @@
-# ticket: 417
+# ticket: t417
#cython: autotestdict=True
cdef class Foo:
diff --git a/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx b/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx
index fb611511b..09df291f5 100644
--- a/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx
+++ b/tests/run/unsigned_char_ptr_bytes_conversion_T359.pyx
@@ -1,4 +1,4 @@
-# ticket: 359
+# ticket: t359
cdef unsigned char* some_c_unstring = 'test toast taste'
diff --git a/tests/run/unsignedbehaviour_T184.pyx b/tests/run/unsignedbehaviour_T184.pyx
index 9cbf65fc1..4dcb86398 100644
--- a/tests/run/unsignedbehaviour_T184.pyx
+++ b/tests/run/unsignedbehaviour_T184.pyx
@@ -1,4 +1,4 @@
-# ticket: 184
+# ticket: t184
"""
>>> c_call()
diff --git a/tests/run/with_statement_module_level_T536.pyx b/tests/run/with_statement_module_level_T536.pyx
index 506c362f9..a18925f46 100644
--- a/tests/run/with_statement_module_level_T536.pyx
+++ b/tests/run/with_statement_module_level_T536.pyx
@@ -1,4 +1,4 @@
-# ticket: 536
+# ticket: t536
__doc__ = """
>>> inner_result