summaryrefslogtreecommitdiffstats
path: root/venv/lib/python3.9/site-packages/numpy/f2py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.9/site-packages/numpy/f2py')
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/__init__.py186
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/__init__.pyi43
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/__main__.py5
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/__version__.py1
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/auxfuncs.py890
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/capi_maps.py880
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/cb_rules.py649
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/cfuncs.py1522
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/common_rules.py149
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/crackfortran.py3545
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/diagnose.py154
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/f2py2e.py704
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/f90mod_rules.py264
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/func2subr.py303
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/rules.py1571
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/setup.py71
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.c1422
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.h173
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/symbolic.py1510
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/__init__.py0
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f9034
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f906
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c230
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap1
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f9034
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f9041
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f9019
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f904
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/block_docstring/foo.f6
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/foo.f62
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh17797.f907
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh18335.f9017
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hi77.f3
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hiworld.f903
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/common/block.f11
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f9013
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f906
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f16
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f12
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f9013
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/operators.f9049
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f9011
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f9010
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f9010
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f904
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap1
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f909
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/kind/foo.f9020
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo.f5
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f908
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_free.f908
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/mod.modbin0 -> 412 bytes
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f9012
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f907
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_both.f9057
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f9015
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f9022
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f9023
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_real.f9023
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/quoted_character/foo.f14
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/regression/inout.f909
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo77.f45
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo90.f9048
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo77.f45
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo90.f9048
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo77.f56
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo90.f9059
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo77.f56
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo90.f9059
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo77.f45
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo90.f9048
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/size/foo.f9044
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/char.f9029
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/fixed_string.f9034
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/scalar_string.f909
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/string.f12
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f909
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_abstract_interface.py25
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_array_from_pyobj.py686
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_assumed_shape.py49
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_block_docstring.py17
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_callback.py230
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_character.py592
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_common.py18
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_compile_function.py117
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_crackfortran.py278
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_docs.py55
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2cmap.py15
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2py2e.py769
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_kind.py26
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_mixed.py33
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_module_doc.py27
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_parameter.py112
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_quoted_character.py16
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_regression.py66
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_character.py45
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_complex.py65
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_integer.py55
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_logical.py64
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_real.py109
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_semicolon_split.py74
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_size.py45
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_string.py100
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_symbolic.py494
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/test_value_attrspec.py14
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/tests/util.py419
-rw-r--r--venv/lib/python3.9/site-packages/numpy/f2py/use_rules.py113
107 files changed, 20271 insertions, 0 deletions
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/__init__.py b/venv/lib/python3.9/site-packages/numpy/f2py/__init__.py
new file mode 100644
index 00000000..dbe3df27
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/__init__.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python3
+"""Fortran to Python Interface Generator.
+
+"""
+__all__ = ['run_main', 'compile', 'get_include']
+
+import sys
+import subprocess
+import os
+
+from . import f2py2e
+from . import diagnose
+
+run_main = f2py2e.run_main
+main = f2py2e.main
+
+
+def compile(source,
+ modulename='untitled',
+ extra_args='',
+ verbose=True,
+ source_fn=None,
+ extension='.f',
+ full_output=False
+ ):
+ """
+ Build extension module from a Fortran 77 source string with f2py.
+
+ Parameters
+ ----------
+ source : str or bytes
+ Fortran source of module / subroutine to compile
+
+ .. versionchanged:: 1.16.0
+ Accept str as well as bytes
+
+ modulename : str, optional
+ The name of the compiled python module
+ extra_args : str or list, optional
+ Additional parameters passed to f2py
+
+ .. versionchanged:: 1.16.0
+ A list of args may also be provided.
+
+ verbose : bool, optional
+ Print f2py output to screen
+ source_fn : str, optional
+ Name of the file where the fortran source is written.
+ The default is to use a temporary file with the extension
+ provided by the ``extension`` parameter
+ extension : ``{'.f', '.f90'}``, optional
+ Filename extension if `source_fn` is not provided.
+ The extension tells which fortran standard is used.
+ The default is ``.f``, which implies F77 standard.
+
+ .. versionadded:: 1.11.0
+
+ full_output : bool, optional
+ If True, return a `subprocess.CompletedProcess` containing
+ the stdout and stderr of the compile process, instead of just
+ the status code.
+
+ .. versionadded:: 1.20.0
+
+
+ Returns
+ -------
+ result : int or `subprocess.CompletedProcess`
+ 0 on success, or a `subprocess.CompletedProcess` if
+ ``full_output=True``
+
+ Examples
+ --------
+ .. literalinclude:: ../../source/f2py/code/results/compile_session.dat
+ :language: python
+
+ """
+ import tempfile
+ import shlex
+
+ if source_fn is None:
+ f, fname = tempfile.mkstemp(suffix=extension)
+ # f is a file descriptor so need to close it
+ # carefully -- not with .close() directly
+ os.close(f)
+ else:
+ fname = source_fn
+
+ if not isinstance(source, str):
+ source = str(source, 'utf-8')
+ try:
+ with open(fname, 'w') as f:
+ f.write(source)
+
+ args = ['-c', '-m', modulename, f.name]
+
+ if isinstance(extra_args, str):
+ is_posix = (os.name == 'posix')
+ extra_args = shlex.split(extra_args, posix=is_posix)
+
+ args.extend(extra_args)
+
+ c = [sys.executable,
+ '-c',
+ 'import numpy.f2py as f2py2e;f2py2e.main()'] + args
+ try:
+ cp = subprocess.run(c, capture_output=True)
+ except OSError:
+ # preserve historic status code used by exec_command()
+ cp = subprocess.CompletedProcess(c, 127, stdout=b'', stderr=b'')
+ else:
+ if verbose:
+ print(cp.stdout.decode())
+ finally:
+ if source_fn is None:
+ os.remove(fname)
+
+ if full_output:
+ return cp
+ else:
+ return cp.returncode
+
+
+def get_include():
+ """
+ Return the directory that contains the ``fortranobject.c`` and ``.h`` files.
+
+ .. note::
+
+ This function is not needed when building an extension with
+ `numpy.distutils` directly from ``.f`` and/or ``.pyf`` files
+ in one go.
+
+ Python extension modules built with f2py-generated code need to use
+ ``fortranobject.c`` as a source file, and include the ``fortranobject.h``
+ header. This function can be used to obtain the directory containing
+ both of these files.
+
+ Returns
+ -------
+ include_path : str
+ Absolute path to the directory containing ``fortranobject.c`` and
+ ``fortranobject.h``.
+
+ Notes
+ -----
+ .. versionadded:: 1.21.1
+
+ Unless the build system you are using has specific support for f2py,
+ building a Python extension using a ``.pyf`` signature file is a two-step
+ process. For a module ``mymod``:
+
+ * Step 1: run ``python -m numpy.f2py mymod.pyf --quiet``. This
+ generates ``_mymodmodule.c`` and (if needed)
+ ``_fblas-f2pywrappers.f`` files next to ``mymod.pyf``.
+ * Step 2: build your Python extension module. This requires the
+ following source files:
+
+ * ``_mymodmodule.c``
+ * ``_mymod-f2pywrappers.f`` (if it was generated in Step 1)
+ * ``fortranobject.c``
+
+ See Also
+ --------
+ numpy.get_include : function that returns the numpy include directory
+
+ """
+ return os.path.join(os.path.dirname(__file__), 'src')
+
+
+def __getattr__(attr):
+
+ # Avoid importing things that aren't needed for building
+ # which might import the main numpy module
+ if attr == "test":
+ from numpy._pytesttester import PytestTester
+ test = PytestTester(__name__)
+ return test
+
+ else:
+ raise AttributeError("module {!r} has no attribute "
+ "{!r}".format(__name__, attr))
+
+
+def __dir__():
+ return list(globals().keys() | {"test"})
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/__init__.pyi b/venv/lib/python3.9/site-packages/numpy/f2py/__init__.pyi
new file mode 100644
index 00000000..6e3a82cf
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/__init__.pyi
@@ -0,0 +1,43 @@
+import os
+import subprocess
+from collections.abc import Iterable
+from typing import Literal as L, Any, overload, TypedDict
+
+from numpy._pytesttester import PytestTester
+
+class _F2PyDictBase(TypedDict):
+ csrc: list[str]
+ h: list[str]
+
+class _F2PyDict(_F2PyDictBase, total=False):
+ fsrc: list[str]
+ ltx: list[str]
+
+__all__: list[str]
+__path__: list[str]
+test: PytestTester
+
+def run_main(comline_list: Iterable[str]) -> dict[str, _F2PyDict]: ...
+
+@overload
+def compile( # type: ignore[misc]
+ source: str | bytes,
+ modulename: str = ...,
+ extra_args: str | list[str] = ...,
+ verbose: bool = ...,
+ source_fn: None | str | bytes | os.PathLike[Any] = ...,
+ extension: L[".f", ".f90"] = ...,
+ full_output: L[False] = ...,
+) -> int: ...
+@overload
+def compile(
+ source: str | bytes,
+ modulename: str = ...,
+ extra_args: str | list[str] = ...,
+ verbose: bool = ...,
+ source_fn: None | str | bytes | os.PathLike[Any] = ...,
+ extension: L[".f", ".f90"] = ...,
+ full_output: L[True] = ...,
+) -> subprocess.CompletedProcess[bytes]: ...
+
+def get_include() -> str: ...
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/__main__.py b/venv/lib/python3.9/site-packages/numpy/f2py/__main__.py
new file mode 100644
index 00000000..936a753a
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/__main__.py
@@ -0,0 +1,5 @@
+# See:
+# https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e
+from numpy.f2py.f2py2e import main
+
+main()
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/__version__.py b/venv/lib/python3.9/site-packages/numpy/f2py/__version__.py
new file mode 100644
index 00000000..e20d7c1d
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/__version__.py
@@ -0,0 +1 @@
+from numpy.version import version
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/auxfuncs.py b/venv/lib/python3.9/site-packages/numpy/f2py/auxfuncs.py
new file mode 100644
index 00000000..3f9b0cea
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/auxfuncs.py
@@ -0,0 +1,890 @@
+#!/usr/bin/env python3
+"""
+
+Auxiliary functions for f2py2e.
+
+Copyright 1999,2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy (BSD style) LICENSE.
+
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/07/24 19:01:55 $
+Pearu Peterson
+
+"""
+import pprint
+import sys
+import types
+from functools import reduce
+
+from . import __version__
+from . import cfuncs
+
+__all__ = [
+ 'applyrules', 'debugcapi', 'dictappend', 'errmess', 'gentitle',
+ 'getargs2', 'getcallprotoargument', 'getcallstatement',
+ 'getfortranname', 'getpymethoddef', 'getrestdoc', 'getusercode',
+ 'getusercode1', 'hasbody', 'hascallstatement', 'hascommon',
+ 'hasexternals', 'hasinitvalue', 'hasnote', 'hasresultnote',
+ 'isallocatable', 'isarray', 'isarrayofstrings',
+ 'ischaracter', 'ischaracterarray', 'ischaracter_or_characterarray',
+ 'iscomplex',
+ 'iscomplexarray', 'iscomplexfunction', 'iscomplexfunction_warn',
+ 'isdouble', 'isdummyroutine', 'isexternal', 'isfunction',
+ 'isfunction_wrap', 'isint1', 'isint1array', 'isinteger', 'isintent_aux',
+ 'isintent_c', 'isintent_callback', 'isintent_copy', 'isintent_dict',
+ 'isintent_hide', 'isintent_in', 'isintent_inout', 'isintent_inplace',
+ 'isintent_nothide', 'isintent_out', 'isintent_overwrite', 'islogical',
+ 'islogicalfunction', 'islong_complex', 'islong_double',
+ 'islong_doublefunction', 'islong_long', 'islong_longfunction',
+ 'ismodule', 'ismoduleroutine', 'isoptional', 'isprivate', 'isrequired',
+ 'isroutine', 'isscalar', 'issigned_long_longarray', 'isstring',
+ 'isstringarray', 'isstring_or_stringarray', 'isstringfunction',
+ 'issubroutine',
+ 'issubroutine_wrap', 'isthreadsafe', 'isunsigned', 'isunsigned_char',
+ 'isunsigned_chararray', 'isunsigned_long_long',
+ 'isunsigned_long_longarray', 'isunsigned_short',
+ 'isunsigned_shortarray', 'l_and', 'l_not', 'l_or', 'outmess',
+ 'replace', 'show', 'stripcomma', 'throw_error', 'isattr_value'
+]
+
+
+f2py_version = __version__.version
+
+
+errmess = sys.stderr.write
+show = pprint.pprint
+
+options = {}
+debugoptions = []
+wrapfuncs = 1
+
+
+def outmess(t):
+ if options.get('verbose', 1):
+ sys.stdout.write(t)
+
+
+def debugcapi(var):
+ return 'capi' in debugoptions
+
+
+def _ischaracter(var):
+ return 'typespec' in var and var['typespec'] == 'character' and \
+ not isexternal(var)
+
+
+def _isstring(var):
+ return 'typespec' in var and var['typespec'] == 'character' and \
+ not isexternal(var)
+
+
+def ischaracter_or_characterarray(var):
+ return _ischaracter(var) and 'charselector' not in var
+
+
+def ischaracter(var):
+ return ischaracter_or_characterarray(var) and not isarray(var)
+
+
+def ischaracterarray(var):
+ return ischaracter_or_characterarray(var) and isarray(var)
+
+
+def isstring_or_stringarray(var):
+ return _ischaracter(var) and 'charselector' in var
+
+
+def isstring(var):
+ return isstring_or_stringarray(var) and not isarray(var)
+
+
+def isstringarray(var):
+ return isstring_or_stringarray(var) and isarray(var)
+
+
+def isarrayofstrings(var): # obsolete?
+ # leaving out '*' for now so that `character*(*) a(m)` and `character
+ # a(m,*)` are treated differently. Luckily `character**` is illegal.
+ return isstringarray(var) and var['dimension'][-1] == '(*)'
+
+
+def isarray(var):
+ return 'dimension' in var and not isexternal(var)
+
+
+def isscalar(var):
+ return not (isarray(var) or isstring(var) or isexternal(var))
+
+
+def iscomplex(var):
+ return isscalar(var) and \
+ var.get('typespec') in ['complex', 'double complex']
+
+
+def islogical(var):
+ return isscalar(var) and var.get('typespec') == 'logical'
+
+
+def isinteger(var):
+ return isscalar(var) and var.get('typespec') == 'integer'
+
+
+def isreal(var):
+ return isscalar(var) and var.get('typespec') == 'real'
+
+
+def get_kind(var):
+ try:
+ return var['kindselector']['*']
+ except KeyError:
+ try:
+ return var['kindselector']['kind']
+ except KeyError:
+ pass
+
+
+def isint1(var):
+ return var.get('typespec') == 'integer' \
+ and get_kind(var) == '1' and not isarray(var)
+
+
+def islong_long(var):
+ if not isscalar(var):
+ return 0
+ if var.get('typespec') not in ['integer', 'logical']:
+ return 0
+ return get_kind(var) == '8'
+
+
+def isunsigned_char(var):
+ if not isscalar(var):
+ return 0
+ if var.get('typespec') != 'integer':
+ return 0
+ return get_kind(var) == '-1'
+
+
+def isunsigned_short(var):
+ if not isscalar(var):
+ return 0
+ if var.get('typespec') != 'integer':
+ return 0
+ return get_kind(var) == '-2'
+
+
+def isunsigned(var):
+ if not isscalar(var):
+ return 0
+ if var.get('typespec') != 'integer':
+ return 0
+ return get_kind(var) == '-4'
+
+
+def isunsigned_long_long(var):
+ if not isscalar(var):
+ return 0
+ if var.get('typespec') != 'integer':
+ return 0
+ return get_kind(var) == '-8'
+
+
+def isdouble(var):
+ if not isscalar(var):
+ return 0
+ if not var.get('typespec') == 'real':
+ return 0
+ return get_kind(var) == '8'
+
+
+def islong_double(var):
+ if not isscalar(var):
+ return 0
+ if not var.get('typespec') == 'real':
+ return 0
+ return get_kind(var) == '16'
+
+
+def islong_complex(var):
+ if not iscomplex(var):
+ return 0
+ return get_kind(var) == '32'
+
+
+def iscomplexarray(var):
+ return isarray(var) and \
+ var.get('typespec') in ['complex', 'double complex']
+
+
+def isint1array(var):
+ return isarray(var) and var.get('typespec') == 'integer' \
+ and get_kind(var) == '1'
+
+
+def isunsigned_chararray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '-1'
+
+
+def isunsigned_shortarray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '-2'
+
+
+def isunsignedarray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '-4'
+
+
+def isunsigned_long_longarray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '-8'
+
+
+def issigned_chararray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '1'
+
+
+def issigned_shortarray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '2'
+
+
+def issigned_array(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '4'
+
+
+def issigned_long_longarray(var):
+ return isarray(var) and var.get('typespec') in ['integer', 'logical']\
+ and get_kind(var) == '8'
+
+
+def isallocatable(var):
+ return 'attrspec' in var and 'allocatable' in var['attrspec']
+
+
+def ismutable(var):
+ return not ('dimension' not in var or isstring(var))
+
+
+def ismoduleroutine(rout):
+ return 'modulename' in rout
+
+
+def ismodule(rout):
+ return 'block' in rout and 'module' == rout['block']
+
+
+def isfunction(rout):
+ return 'block' in rout and 'function' == rout['block']
+
+
+def isfunction_wrap(rout):
+ if isintent_c(rout):
+ return 0
+ return wrapfuncs and isfunction(rout) and (not isexternal(rout))
+
+
+def issubroutine(rout):
+ return 'block' in rout and 'subroutine' == rout['block']
+
+
+def issubroutine_wrap(rout):
+ if isintent_c(rout):
+ return 0
+ return issubroutine(rout) and hasassumedshape(rout)
+
+def isattr_value(var):
+ return 'value' in var.get('attrspec', [])
+
+
+def hasassumedshape(rout):
+ if rout.get('hasassumedshape'):
+ return True
+ for a in rout['args']:
+ for d in rout['vars'].get(a, {}).get('dimension', []):
+ if d == ':':
+ rout['hasassumedshape'] = True
+ return True
+ return False
+
+
+def requiresf90wrapper(rout):
+ return ismoduleroutine(rout) or hasassumedshape(rout)
+
+
+def isroutine(rout):
+ return isfunction(rout) or issubroutine(rout)
+
+
+def islogicalfunction(rout):
+ if not isfunction(rout):
+ return 0
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if a in rout['vars']:
+ return islogical(rout['vars'][a])
+ return 0
+
+
+def islong_longfunction(rout):
+ if not isfunction(rout):
+ return 0
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if a in rout['vars']:
+ return islong_long(rout['vars'][a])
+ return 0
+
+
+def islong_doublefunction(rout):
+ if not isfunction(rout):
+ return 0
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if a in rout['vars']:
+ return islong_double(rout['vars'][a])
+ return 0
+
+
+def iscomplexfunction(rout):
+ if not isfunction(rout):
+ return 0
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if a in rout['vars']:
+ return iscomplex(rout['vars'][a])
+ return 0
+
+
+def iscomplexfunction_warn(rout):
+ if iscomplexfunction(rout):
+ outmess("""\
+ **************************************************************
+ Warning: code with a function returning complex value
+ may not work correctly with your Fortran compiler.
+ When using GNU gcc/g77 compilers, codes should work
+ correctly for callbacks with:
+ f2py -c -DF2PY_CB_RETURNCOMPLEX
+ **************************************************************\n""")
+ return 1
+ return 0
+
+
+def isstringfunction(rout):
+ if not isfunction(rout):
+ return 0
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if a in rout['vars']:
+ return isstring(rout['vars'][a])
+ return 0
+
+
+def hasexternals(rout):
+ return 'externals' in rout and rout['externals']
+
+
+def isthreadsafe(rout):
+ return 'f2pyenhancements' in rout and \
+ 'threadsafe' in rout['f2pyenhancements']
+
+
+def hasvariables(rout):
+ return 'vars' in rout and rout['vars']
+
+
+def isoptional(var):
+ return ('attrspec' in var and 'optional' in var['attrspec'] and
+ 'required' not in var['attrspec']) and isintent_nothide(var)
+
+
+def isexternal(var):
+ return 'attrspec' in var and 'external' in var['attrspec']
+
+
+def isrequired(var):
+ return not isoptional(var) and isintent_nothide(var)
+
+
+def isintent_in(var):
+ if 'intent' not in var:
+ return 1
+ if 'hide' in var['intent']:
+ return 0
+ if 'inplace' in var['intent']:
+ return 0
+ if 'in' in var['intent']:
+ return 1
+ if 'out' in var['intent']:
+ return 0
+ if 'inout' in var['intent']:
+ return 0
+ if 'outin' in var['intent']:
+ return 0
+ return 1
+
+
+def isintent_inout(var):
+ return ('intent' in var and ('inout' in var['intent'] or
+ 'outin' in var['intent']) and 'in' not in var['intent'] and
+ 'hide' not in var['intent'] and 'inplace' not in var['intent'])
+
+
+def isintent_out(var):
+ return 'out' in var.get('intent', [])
+
+
+def isintent_hide(var):
+ return ('intent' in var and ('hide' in var['intent'] or
+ ('out' in var['intent'] and 'in' not in var['intent'] and
+ (not l_or(isintent_inout, isintent_inplace)(var)))))
+
+
+def isintent_nothide(var):
+ return not isintent_hide(var)
+
+
+def isintent_c(var):
+ return 'c' in var.get('intent', [])
+
+
+def isintent_cache(var):
+ return 'cache' in var.get('intent', [])
+
+
+def isintent_copy(var):
+ return 'copy' in var.get('intent', [])
+
+
+def isintent_overwrite(var):
+ return 'overwrite' in var.get('intent', [])
+
+
+def isintent_callback(var):
+ return 'callback' in var.get('intent', [])
+
+
+def isintent_inplace(var):
+ return 'inplace' in var.get('intent', [])
+
+
+def isintent_aux(var):
+ return 'aux' in var.get('intent', [])
+
+
+def isintent_aligned4(var):
+ return 'aligned4' in var.get('intent', [])
+
+
+def isintent_aligned8(var):
+ return 'aligned8' in var.get('intent', [])
+
+
+def isintent_aligned16(var):
+ return 'aligned16' in var.get('intent', [])
+
+
+isintent_dict = {isintent_in: 'INTENT_IN', isintent_inout: 'INTENT_INOUT',
+ isintent_out: 'INTENT_OUT', isintent_hide: 'INTENT_HIDE',
+ isintent_cache: 'INTENT_CACHE',
+ isintent_c: 'INTENT_C', isoptional: 'OPTIONAL',
+ isintent_inplace: 'INTENT_INPLACE',
+ isintent_aligned4: 'INTENT_ALIGNED4',
+ isintent_aligned8: 'INTENT_ALIGNED8',
+ isintent_aligned16: 'INTENT_ALIGNED16',
+ }
+
+
+def isprivate(var):
+ return 'attrspec' in var and 'private' in var['attrspec']
+
+
+def hasinitvalue(var):
+ return '=' in var
+
+
+def hasinitvalueasstring(var):
+ if not hasinitvalue(var):
+ return 0
+ return var['='][0] in ['"', "'"]
+
+
+def hasnote(var):
+ return 'note' in var
+
+
+def hasresultnote(rout):
+ if not isfunction(rout):
+ return 0
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if a in rout['vars']:
+ return hasnote(rout['vars'][a])
+ return 0
+
+
+def hascommon(rout):
+ return 'common' in rout
+
+
+def containscommon(rout):
+ if hascommon(rout):
+ return 1
+ if hasbody(rout):
+ for b in rout['body']:
+ if containscommon(b):
+ return 1
+ return 0
+
+
+def containsmodule(block):
+ if ismodule(block):
+ return 1
+ if not hasbody(block):
+ return 0
+ for b in block['body']:
+ if containsmodule(b):
+ return 1
+ return 0
+
+
+def hasbody(rout):
+ return 'body' in rout
+
+
+def hascallstatement(rout):
+ return getcallstatement(rout) is not None
+
+
+def istrue(var):
+ return 1
+
+
+def isfalse(var):
+ return 0
+
+
+class F2PYError(Exception):
+ pass
+
+
+class throw_error:
+
+ def __init__(self, mess):
+ self.mess = mess
+
+ def __call__(self, var):
+ mess = '\n\n var = %s\n Message: %s\n' % (var, self.mess)
+ raise F2PYError(mess)
+
+
+def l_and(*f):
+ l1, l2 = 'lambda v', []
+ for i in range(len(f)):
+ l1 = '%s,f%d=f[%d]' % (l1, i, i)
+ l2.append('f%d(v)' % (i))
+ return eval('%s:%s' % (l1, ' and '.join(l2)))
+
+
+def l_or(*f):
+ l1, l2 = 'lambda v', []
+ for i in range(len(f)):
+ l1 = '%s,f%d=f[%d]' % (l1, i, i)
+ l2.append('f%d(v)' % (i))
+ return eval('%s:%s' % (l1, ' or '.join(l2)))
+
+
+def l_not(f):
+ return eval('lambda v,f=f:not f(v)')
+
+
+def isdummyroutine(rout):
+ try:
+ return rout['f2pyenhancements']['fortranname'] == ''
+ except KeyError:
+ return 0
+
+
+def getfortranname(rout):
+ try:
+ name = rout['f2pyenhancements']['fortranname']
+ if name == '':
+ raise KeyError
+ if not name:
+ errmess('Failed to use fortranname from %s\n' %
+ (rout['f2pyenhancements']))
+ raise KeyError
+ except KeyError:
+ name = rout['name']
+ return name
+
+
+def getmultilineblock(rout, blockname, comment=1, counter=0):
+ try:
+ r = rout['f2pyenhancements'].get(blockname)
+ except KeyError:
+ return
+ if not r:
+ return
+ if counter > 0 and isinstance(r, str):
+ return
+ if isinstance(r, list):
+ if counter >= len(r):
+ return
+ r = r[counter]
+ if r[:3] == "'''":
+ if comment:
+ r = '\t/* start ' + blockname + \
+ ' multiline (' + repr(counter) + ') */\n' + r[3:]
+ else:
+ r = r[3:]
+ if r[-3:] == "'''":
+ if comment:
+ r = r[:-3] + '\n\t/* end multiline (' + repr(counter) + ')*/'
+ else:
+ r = r[:-3]
+ else:
+ errmess("%s multiline block should end with `'''`: %s\n"
+ % (blockname, repr(r)))
+ return r
+
+
+def getcallstatement(rout):
+ return getmultilineblock(rout, 'callstatement')
+
+
+def getcallprotoargument(rout, cb_map={}):
+ r = getmultilineblock(rout, 'callprotoargument', comment=0)
+ if r:
+ return r
+ if hascallstatement(rout):
+ outmess(
+ 'warning: callstatement is defined without callprotoargument\n')
+ return
+ from .capi_maps import getctype
+ arg_types, arg_types2 = [], []
+ if l_and(isstringfunction, l_not(isfunction_wrap))(rout):
+ arg_types.extend(['char*', 'size_t'])
+ for n in rout['args']:
+ var = rout['vars'][n]
+ if isintent_callback(var):
+ continue
+ if n in cb_map:
+ ctype = cb_map[n] + '_typedef'
+ else:
+ ctype = getctype(var)
+ if l_and(isintent_c, l_or(isscalar, iscomplex))(var):
+ pass
+ elif isstring(var):
+ pass
+ else:
+ if not isattr_value(var):
+ ctype = ctype + '*'
+ if ((isstring(var)
+ or isarrayofstrings(var) # obsolete?
+ or isstringarray(var))):
+ arg_types2.append('size_t')
+ arg_types.append(ctype)
+
+ proto_args = ','.join(arg_types + arg_types2)
+ if not proto_args:
+ proto_args = 'void'
+ return proto_args
+
+
+def getusercode(rout):
+ return getmultilineblock(rout, 'usercode')
+
+
+def getusercode1(rout):
+ return getmultilineblock(rout, 'usercode', counter=1)
+
+
+def getpymethoddef(rout):
+ return getmultilineblock(rout, 'pymethoddef')
+
+
+def getargs(rout):
+ sortargs, args = [], []
+ if 'args' in rout:
+ args = rout['args']
+ if 'sortvars' in rout:
+ for a in rout['sortvars']:
+ if a in args:
+ sortargs.append(a)
+ for a in args:
+ if a not in sortargs:
+ sortargs.append(a)
+ else:
+ sortargs = rout['args']
+ return args, sortargs
+
+
+def getargs2(rout):
+ sortargs, args = [], rout.get('args', [])
+ auxvars = [a for a in rout['vars'].keys() if isintent_aux(rout['vars'][a])
+ and a not in args]
+ args = auxvars + args
+ if 'sortvars' in rout:
+ for a in rout['sortvars']:
+ if a in args:
+ sortargs.append(a)
+ for a in args:
+ if a not in sortargs:
+ sortargs.append(a)
+ else:
+ sortargs = auxvars + rout['args']
+ return args, sortargs
+
+
+def getrestdoc(rout):
+ if 'f2pymultilines' not in rout:
+ return None
+ k = None
+ if rout['block'] == 'python module':
+ k = rout['block'], rout['name']
+ return rout['f2pymultilines'].get(k, None)
+
+
+def gentitle(name):
+ ln = (80 - len(name) - 6) // 2
+ return '/*%s %s %s*/' % (ln * '*', name, ln * '*')
+
+
+def flatlist(lst):
+ if isinstance(lst, list):
+ return reduce(lambda x, y, f=flatlist: x + f(y), lst, [])
+ return [lst]
+
+
+def stripcomma(s):
+ if s and s[-1] == ',':
+ return s[:-1]
+ return s
+
+
+def replace(str, d, defaultsep=''):
+ if isinstance(d, list):
+ return [replace(str, _m, defaultsep) for _m in d]
+ if isinstance(str, list):
+ return [replace(_m, d, defaultsep) for _m in str]
+ for k in 2 * list(d.keys()):
+ if k == 'separatorsfor':
+ continue
+ if 'separatorsfor' in d and k in d['separatorsfor']:
+ sep = d['separatorsfor'][k]
+ else:
+ sep = defaultsep
+ if isinstance(d[k], list):
+ str = str.replace('#%s#' % (k), sep.join(flatlist(d[k])))
+ else:
+ str = str.replace('#%s#' % (k), d[k])
+ return str
+
+
+def dictappend(rd, ar):
+ if isinstance(ar, list):
+ for a in ar:
+ rd = dictappend(rd, a)
+ return rd
+ for k in ar.keys():
+ if k[0] == '_':
+ continue
+ if k in rd:
+ if isinstance(rd[k], str):
+ rd[k] = [rd[k]]
+ if isinstance(rd[k], list):
+ if isinstance(ar[k], list):
+ rd[k] = rd[k] + ar[k]
+ else:
+ rd[k].append(ar[k])
+ elif isinstance(rd[k], dict):
+ if isinstance(ar[k], dict):
+ if k == 'separatorsfor':
+ for k1 in ar[k].keys():
+ if k1 not in rd[k]:
+ rd[k][k1] = ar[k][k1]
+ else:
+ rd[k] = dictappend(rd[k], ar[k])
+ else:
+ rd[k] = ar[k]
+ return rd
+
+
+def applyrules(rules, d, var={}):
+ ret = {}
+ if isinstance(rules, list):
+ for r in rules:
+ rr = applyrules(r, d, var)
+ ret = dictappend(ret, rr)
+ if '_break' in rr:
+ break
+ return ret
+ if '_check' in rules and (not rules['_check'](var)):
+ return ret
+ if 'need' in rules:
+ res = applyrules({'needs': rules['need']}, d, var)
+ if 'needs' in res:
+ cfuncs.append_needs(res['needs'])
+
+ for k in rules.keys():
+ if k == 'separatorsfor':
+ ret[k] = rules[k]
+ continue
+ if isinstance(rules[k], str):
+ ret[k] = replace(rules[k], d)
+ elif isinstance(rules[k], list):
+ ret[k] = []
+ for i in rules[k]:
+ ar = applyrules({k: i}, d, var)
+ if k in ar:
+ ret[k].append(ar[k])
+ elif k[0] == '_':
+ continue
+ elif isinstance(rules[k], dict):
+ ret[k] = []
+ for k1 in rules[k].keys():
+ if isinstance(k1, types.FunctionType) and k1(var):
+ if isinstance(rules[k][k1], list):
+ for i in rules[k][k1]:
+ if isinstance(i, dict):
+ res = applyrules({'supertext': i}, d, var)
+ if 'supertext' in res:
+ i = res['supertext']
+ else:
+ i = ''
+ ret[k].append(replace(i, d))
+ else:
+ i = rules[k][k1]
+ if isinstance(i, dict):
+ res = applyrules({'supertext': i}, d)
+ if 'supertext' in res:
+ i = res['supertext']
+ else:
+ i = ''
+ ret[k].append(replace(i, d))
+ else:
+ errmess('applyrules: ignoring rule %s.\n' % repr(rules[k]))
+ if isinstance(ret[k], list):
+ if len(ret[k]) == 1:
+ ret[k] = ret[k][0]
+ if ret[k] == []:
+ del ret[k]
+ return ret
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/capi_maps.py b/venv/lib/python3.9/site-packages/numpy/f2py/capi_maps.py
new file mode 100644
index 00000000..aaae3a8e
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/capi_maps.py
@@ -0,0 +1,880 @@
+#!/usr/bin/env python3
+"""
+
+Copyright 1999,2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 10:57:33 $
+Pearu Peterson
+
+"""
+from . import __version__
+f2py_version = __version__.version
+
+import copy
+import re
+import os
+from .crackfortran import markoutercomma
+from . import cb_rules
+
+# The environment provided by auxfuncs.py is needed for some calls to eval.
+# As the needed functions cannot be determined by static inspection of the
+# code, it is safest to use import * pending a major refactoring of f2py.
+from .auxfuncs import *
+
+__all__ = [
+ 'getctype', 'getstrlength', 'getarrdims', 'getpydocsign',
+ 'getarrdocsign', 'getinit', 'sign2map', 'routsign2map', 'modsign2map',
+ 'cb_sign2map', 'cb_routsign2map', 'common_sign2map'
+]
+
+
+# Numarray and Numeric users should set this False
+using_newcore = True
+
+depargs = []
+lcb_map = {}
+lcb2_map = {}
+# forced casting: mainly caused by the fact that Python or Numeric
+# C/APIs do not support the corresponding C types.
+c2py_map = {'double': 'float',
+ 'float': 'float', # forced casting
+ 'long_double': 'float', # forced casting
+ 'char': 'int', # forced casting
+ 'signed_char': 'int', # forced casting
+ 'unsigned_char': 'int', # forced casting
+ 'short': 'int', # forced casting
+ 'unsigned_short': 'int', # forced casting
+ 'int': 'int', # forced casting
+ 'long': 'int',
+ 'long_long': 'long',
+ 'unsigned': 'int', # forced casting
+ 'complex_float': 'complex', # forced casting
+ 'complex_double': 'complex',
+ 'complex_long_double': 'complex', # forced casting
+ 'string': 'string',
+ 'character': 'bytes',
+ }
+c2capi_map = {'double': 'NPY_DOUBLE',
+ 'float': 'NPY_FLOAT',
+ 'long_double': 'NPY_DOUBLE', # forced casting
+ 'char': 'NPY_STRING',
+ 'unsigned_char': 'NPY_UBYTE',
+ 'signed_char': 'NPY_BYTE',
+ 'short': 'NPY_SHORT',
+ 'unsigned_short': 'NPY_USHORT',
+ 'int': 'NPY_INT',
+ 'unsigned': 'NPY_UINT',
+ 'long': 'NPY_LONG',
+ 'long_long': 'NPY_LONG', # forced casting
+ 'complex_float': 'NPY_CFLOAT',
+ 'complex_double': 'NPY_CDOUBLE',
+ 'complex_long_double': 'NPY_CDOUBLE', # forced casting
+ 'string': 'NPY_STRING',
+ 'character': 'NPY_CHAR'}
+
+# These new maps aren't used anywhere yet, but should be by default
+# unless building numeric or numarray extensions.
+if using_newcore:
+ c2capi_map = {'double': 'NPY_DOUBLE',
+ 'float': 'NPY_FLOAT',
+ 'long_double': 'NPY_LONGDOUBLE',
+ 'char': 'NPY_BYTE',
+ 'unsigned_char': 'NPY_UBYTE',
+ 'signed_char': 'NPY_BYTE',
+ 'short': 'NPY_SHORT',
+ 'unsigned_short': 'NPY_USHORT',
+ 'int': 'NPY_INT',
+ 'unsigned': 'NPY_UINT',
+ 'long': 'NPY_LONG',
+ 'unsigned_long': 'NPY_ULONG',
+ 'long_long': 'NPY_LONGLONG',
+ 'unsigned_long_long': 'NPY_ULONGLONG',
+ 'complex_float': 'NPY_CFLOAT',
+ 'complex_double': 'NPY_CDOUBLE',
+ 'complex_long_double': 'NPY_CDOUBLE',
+ 'string': 'NPY_STRING',
+ 'character': 'NPY_STRING'}
+
+c2pycode_map = {'double': 'd',
+ 'float': 'f',
+ 'long_double': 'd', # forced casting
+ 'char': '1',
+ 'signed_char': '1',
+ 'unsigned_char': 'b',
+ 'short': 's',
+ 'unsigned_short': 'w',
+ 'int': 'i',
+ 'unsigned': 'u',
+ 'long': 'l',
+ 'long_long': 'L',
+ 'complex_float': 'F',
+ 'complex_double': 'D',
+ 'complex_long_double': 'D', # forced casting
+ 'string': 'c',
+ 'character': 'c'
+ }
+
+if using_newcore:
+ c2pycode_map = {'double': 'd',
+ 'float': 'f',
+ 'long_double': 'g',
+ 'char': 'b',
+ 'unsigned_char': 'B',
+ 'signed_char': 'b',
+ 'short': 'h',
+ 'unsigned_short': 'H',
+ 'int': 'i',
+ 'unsigned': 'I',
+ 'long': 'l',
+ 'unsigned_long': 'L',
+ 'long_long': 'q',
+ 'unsigned_long_long': 'Q',
+ 'complex_float': 'F',
+ 'complex_double': 'D',
+ 'complex_long_double': 'G',
+ 'string': 'S',
+ 'character': 'c'}
+
+# https://docs.python.org/3/c-api/arg.html#building-values
+# c2buildvalue_map is NumPy agnostic, so no need to bother with using_newcore
+c2buildvalue_map = {'double': 'd',
+ 'float': 'f',
+ 'char': 'b',
+ 'signed_char': 'b',
+ 'short': 'h',
+ 'int': 'i',
+ 'long': 'l',
+ 'long_long': 'L',
+ 'complex_float': 'N',
+ 'complex_double': 'N',
+ 'complex_long_double': 'N',
+ 'string': 'y',
+ 'character': 'c'}
+
+f2cmap_all = {'real': {'': 'float', '4': 'float', '8': 'double',
+ '12': 'long_double', '16': 'long_double'},
+ 'integer': {'': 'int', '1': 'signed_char', '2': 'short',
+ '4': 'int', '8': 'long_long',
+ '-1': 'unsigned_char', '-2': 'unsigned_short',
+ '-4': 'unsigned', '-8': 'unsigned_long_long'},
+ 'complex': {'': 'complex_float', '8': 'complex_float',
+ '16': 'complex_double', '24': 'complex_long_double',
+ '32': 'complex_long_double'},
+ 'complexkind': {'': 'complex_float', '4': 'complex_float',
+ '8': 'complex_double', '12': 'complex_long_double',
+ '16': 'complex_long_double'},
+ 'logical': {'': 'int', '1': 'char', '2': 'short', '4': 'int',
+ '8': 'long_long'},
+ 'double complex': {'': 'complex_double'},
+ 'double precision': {'': 'double'},
+ 'byte': {'': 'char'},
+ }
+
+f2cmap_default = copy.deepcopy(f2cmap_all)
+
+f2cmap_mapped = []
+
+def load_f2cmap_file(f2cmap_file):
+ global f2cmap_all
+
+ f2cmap_all = copy.deepcopy(f2cmap_default)
+
+ if f2cmap_file is None:
+ # Default value
+ f2cmap_file = '.f2py_f2cmap'
+ if not os.path.isfile(f2cmap_file):
+ return
+
+ # User defined additions to f2cmap_all.
+ # f2cmap_file must contain a dictionary of dictionaries, only. For
+ # example, {'real':{'low':'float'}} means that Fortran 'real(low)' is
+ # interpreted as C 'float'. This feature is useful for F90/95 users if
+ # they use PARAMETERS in type specifications.
+ try:
+ outmess('Reading f2cmap from {!r} ...\n'.format(f2cmap_file))
+ with open(f2cmap_file, 'r') as f:
+ d = eval(f.read().lower(), {}, {})
+ for k, d1 in d.items():
+ for k1 in d1.keys():
+ d1[k1.lower()] = d1[k1]
+ d[k.lower()] = d[k]
+ for k in d.keys():
+ if k not in f2cmap_all:
+ f2cmap_all[k] = {}
+ for k1 in d[k].keys():
+ if d[k][k1] in c2py_map:
+ if k1 in f2cmap_all[k]:
+ outmess(
+ "\tWarning: redefinition of {'%s':{'%s':'%s'->'%s'}}\n" % (k, k1, f2cmap_all[k][k1], d[k][k1]))
+ f2cmap_all[k][k1] = d[k][k1]
+ outmess('\tMapping "%s(kind=%s)" to "%s"\n' %
+ (k, k1, d[k][k1]))
+ f2cmap_mapped.append(d[k][k1])
+ else:
+ errmess("\tIgnoring map {'%s':{'%s':'%s'}}: '%s' must be in %s\n" % (
+ k, k1, d[k][k1], d[k][k1], list(c2py_map.keys())))
+ outmess('Successfully applied user defined f2cmap changes\n')
+ except Exception as msg:
+ errmess(
+ 'Failed to apply user defined f2cmap changes: %s. Skipping.\n' % (msg))
+
+cformat_map = {'double': '%g',
+ 'float': '%g',
+ 'long_double': '%Lg',
+ 'char': '%d',
+ 'signed_char': '%d',
+ 'unsigned_char': '%hhu',
+ 'short': '%hd',
+ 'unsigned_short': '%hu',
+ 'int': '%d',
+ 'unsigned': '%u',
+ 'long': '%ld',
+ 'unsigned_long': '%lu',
+ 'long_long': '%ld',
+ 'complex_float': '(%g,%g)',
+ 'complex_double': '(%g,%g)',
+ 'complex_long_double': '(%Lg,%Lg)',
+ 'string': '\\"%s\\"',
+ 'character': "'%c'",
+ }
+
+# Auxiliary functions
+
+
+def getctype(var):
+ """
+ Determines C type
+ """
+ ctype = 'void'
+ if isfunction(var):
+ if 'result' in var:
+ a = var['result']
+ else:
+ a = var['name']
+ if a in var['vars']:
+ return getctype(var['vars'][a])
+ else:
+ errmess('getctype: function %s has no return value?!\n' % a)
+ elif issubroutine(var):
+ return ctype
+ elif ischaracter_or_characterarray(var):
+ return 'character'
+ elif isstring_or_stringarray(var):
+ return 'string'
+ elif 'typespec' in var and var['typespec'].lower() in f2cmap_all:
+ typespec = var['typespec'].lower()
+ f2cmap = f2cmap_all[typespec]
+ ctype = f2cmap[''] # default type
+ if 'kindselector' in var:
+ if '*' in var['kindselector']:
+ try:
+ ctype = f2cmap[var['kindselector']['*']]
+ except KeyError:
+ errmess('getctype: "%s %s %s" not supported.\n' %
+ (var['typespec'], '*', var['kindselector']['*']))
+ elif 'kind' in var['kindselector']:
+ if typespec + 'kind' in f2cmap_all:
+ f2cmap = f2cmap_all[typespec + 'kind']
+ try:
+ ctype = f2cmap[var['kindselector']['kind']]
+ except KeyError:
+ if typespec in f2cmap_all:
+ f2cmap = f2cmap_all[typespec]
+ try:
+ ctype = f2cmap[str(var['kindselector']['kind'])]
+ except KeyError:
+ errmess('getctype: "%s(kind=%s)" is mapped to C "%s" (to override define dict(%s = dict(%s="<C typespec>")) in %s/.f2py_f2cmap file).\n'
+ % (typespec, var['kindselector']['kind'], ctype,
+ typespec, var['kindselector']['kind'], os.getcwd()))
+ else:
+ if not isexternal(var):
+ errmess('getctype: No C-type found in "%s", assuming void.\n' % var)
+ return ctype
+
+
+def f2cexpr(expr):
+ """Rewrite Fortran expression as f2py supported C expression.
+
+ Due to the lack of a proper expression parser in f2py, this
+ function uses a heuristic approach that assumes that Fortran
+ arithmetic expressions are valid C arithmetic expressions when
+ mapping Fortran function calls to the corresponding C function/CPP
+ macros calls.
+
+ """
+ # TODO: support Fortran `len` function with optional kind parameter
+ expr = re.sub(r'\blen\b', 'f2py_slen', expr)
+ return expr
+
+
+def getstrlength(var):
+ if isstringfunction(var):
+ if 'result' in var:
+ a = var['result']
+ else:
+ a = var['name']
+ if a in var['vars']:
+ return getstrlength(var['vars'][a])
+ else:
+ errmess('getstrlength: function %s has no return value?!\n' % a)
+ if not isstring(var):
+ errmess(
+ 'getstrlength: expected a signature of a string but got: %s\n' % (repr(var)))
+ len = '1'
+ if 'charselector' in var:
+ a = var['charselector']
+ if '*' in a:
+ len = a['*']
+ elif 'len' in a:
+ len = f2cexpr(a['len'])
+ if re.match(r'\(\s*(\*|:)\s*\)', len) or re.match(r'(\*|:)', len):
+ if isintent_hide(var):
+ errmess('getstrlength:intent(hide): expected a string with defined length but got: %s\n' % (
+ repr(var)))
+ len = '-1'
+ return len
+
+
+def getarrdims(a, var, verbose=0):
+ ret = {}
+ if isstring(var) and not isarray(var):
+ ret['size'] = getstrlength(var)
+ ret['rank'] = '0'
+ ret['dims'] = ''
+ elif isscalar(var):
+ ret['size'] = '1'
+ ret['rank'] = '0'
+ ret['dims'] = ''
+ elif isarray(var):
+ dim = copy.copy(var['dimension'])
+ ret['size'] = '*'.join(dim)
+ try:
+ ret['size'] = repr(eval(ret['size']))
+ except Exception:
+ pass
+ ret['dims'] = ','.join(dim)
+ ret['rank'] = repr(len(dim))
+ ret['rank*[-1]'] = repr(len(dim) * [-1])[1:-1]
+ for i in range(len(dim)): # solve dim for dependencies
+ v = []
+ if dim[i] in depargs:
+ v = [dim[i]]
+ else:
+ for va in depargs:
+ if re.match(r'.*?\b%s\b.*' % va, dim[i]):
+ v.append(va)
+ for va in v:
+ if depargs.index(va) > depargs.index(a):
+ dim[i] = '*'
+ break
+ ret['setdims'], i = '', -1
+ for d in dim:
+ i = i + 1
+ if d not in ['*', ':', '(*)', '(:)']:
+ ret['setdims'] = '%s#varname#_Dims[%d]=%s,' % (
+ ret['setdims'], i, d)
+ if ret['setdims']:
+ ret['setdims'] = ret['setdims'][:-1]
+ ret['cbsetdims'], i = '', -1
+ for d in var['dimension']:
+ i = i + 1
+ if d not in ['*', ':', '(*)', '(:)']:
+ ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
+ ret['cbsetdims'], i, d)
+ elif isintent_in(var):
+ outmess('getarrdims:warning: assumed shape array, using 0 instead of %r\n'
+ % (d))
+ ret['cbsetdims'] = '%s#varname#_Dims[%d]=%s,' % (
+ ret['cbsetdims'], i, 0)
+ elif verbose:
+ errmess(
+ 'getarrdims: If in call-back function: array argument %s must have bounded dimensions: got %s\n' % (repr(a), repr(d)))
+ if ret['cbsetdims']:
+ ret['cbsetdims'] = ret['cbsetdims'][:-1]
+# if not isintent_c(var):
+# var['dimension'].reverse()
+ return ret
+
+
+def getpydocsign(a, var):
+ global lcb_map
+ if isfunction(var):
+ if 'result' in var:
+ af = var['result']
+ else:
+ af = var['name']
+ if af in var['vars']:
+ return getpydocsign(af, var['vars'][af])
+ else:
+ errmess('getctype: function %s has no return value?!\n' % af)
+ return '', ''
+ sig, sigout = a, a
+ opt = ''
+ if isintent_in(var):
+ opt = 'input'
+ elif isintent_inout(var):
+ opt = 'in/output'
+ out_a = a
+ if isintent_out(var):
+ for k in var['intent']:
+ if k[:4] == 'out=':
+ out_a = k[4:]
+ break
+ init = ''
+ ctype = getctype(var)
+
+ if hasinitvalue(var):
+ init, showinit = getinit(a, var)
+ init = ', optional\\n Default: %s' % showinit
+ if isscalar(var):
+ if isintent_inout(var):
+ sig = '%s : %s rank-0 array(%s,\'%s\')%s' % (a, opt, c2py_map[ctype],
+ c2pycode_map[ctype], init)
+ else:
+ sig = '%s : %s %s%s' % (a, opt, c2py_map[ctype], init)
+ sigout = '%s : %s' % (out_a, c2py_map[ctype])
+ elif isstring(var):
+ if isintent_inout(var):
+ sig = '%s : %s rank-0 array(string(len=%s),\'c\')%s' % (
+ a, opt, getstrlength(var), init)
+ else:
+ sig = '%s : %s string(len=%s)%s' % (
+ a, opt, getstrlength(var), init)
+ sigout = '%s : string(len=%s)' % (out_a, getstrlength(var))
+ elif isarray(var):
+ dim = var['dimension']
+ rank = repr(len(dim))
+ sig = '%s : %s rank-%s array(\'%s\') with bounds (%s)%s' % (a, opt, rank,
+ c2pycode_map[
+ ctype],
+ ','.join(dim), init)
+ if a == out_a:
+ sigout = '%s : rank-%s array(\'%s\') with bounds (%s)'\
+ % (a, rank, c2pycode_map[ctype], ','.join(dim))
+ else:
+ sigout = '%s : rank-%s array(\'%s\') with bounds (%s) and %s storage'\
+ % (out_a, rank, c2pycode_map[ctype], ','.join(dim), a)
+ elif isexternal(var):
+ ua = ''
+ if a in lcb_map and lcb_map[a] in lcb2_map and 'argname' in lcb2_map[lcb_map[a]]:
+ ua = lcb2_map[lcb_map[a]]['argname']
+ if not ua == a:
+ ua = ' => %s' % ua
+ else:
+ ua = ''
+ sig = '%s : call-back function%s' % (a, ua)
+ sigout = sig
+ else:
+ errmess(
+ 'getpydocsign: Could not resolve docsignature for "%s".\n' % a)
+ return sig, sigout
+
+
+def getarrdocsign(a, var):
+ ctype = getctype(var)
+ if isstring(var) and (not isarray(var)):
+ sig = '%s : rank-0 array(string(len=%s),\'c\')' % (a,
+ getstrlength(var))
+ elif isscalar(var):
+ sig = '%s : rank-0 array(%s,\'%s\')' % (a, c2py_map[ctype],
+ c2pycode_map[ctype],)
+ elif isarray(var):
+ dim = var['dimension']
+ rank = repr(len(dim))
+ sig = '%s : rank-%s array(\'%s\') with bounds (%s)' % (a, rank,
+ c2pycode_map[
+ ctype],
+ ','.join(dim))
+ return sig
+
+
+def getinit(a, var):
+ if isstring(var):
+ init, showinit = '""', "''"
+ else:
+ init, showinit = '', ''
+ if hasinitvalue(var):
+ init = var['=']
+ showinit = init
+ if iscomplex(var) or iscomplexarray(var):
+ ret = {}
+
+ try:
+ v = var["="]
+ if ',' in v:
+ ret['init.r'], ret['init.i'] = markoutercomma(
+ v[1:-1]).split('@,@')
+ else:
+ v = eval(v, {}, {})
+ ret['init.r'], ret['init.i'] = str(v.real), str(v.imag)
+ except Exception:
+ raise ValueError(
+ 'getinit: expected complex number `(r,i)\' but got `%s\' as initial value of %r.' % (init, a))
+ if isarray(var):
+ init = '(capi_c.r=%s,capi_c.i=%s,capi_c)' % (
+ ret['init.r'], ret['init.i'])
+ elif isstring(var):
+ if not init:
+ init, showinit = '""', "''"
+ if init[0] == "'":
+ init = '"%s"' % (init[1:-1].replace('"', '\\"'))
+ if init[0] == '"':
+ showinit = "'%s'" % (init[1:-1])
+ return init, showinit
+
+
+def get_elsize(var):
+ if isstring(var) or isstringarray(var):
+ elsize = getstrlength(var)
+ # override with user-specified length when available:
+ elsize = var['charselector'].get('f2py_len', elsize)
+ return elsize
+ if ischaracter(var) or ischaracterarray(var):
+ return '1'
+ # for numerical types, PyArray_New* functions ignore specified
+ # elsize, so we just return 1 and let elsize be determined at
+ # runtime, see fortranobject.c
+ return '1'
+
+
+def sign2map(a, var):
+ """
+ varname,ctype,atype
+ init,init.r,init.i,pytype
+ vardebuginfo,vardebugshowvalue,varshowvalue
+ varrformat
+
+ intent
+ """
+ out_a = a
+ if isintent_out(var):
+ for k in var['intent']:
+ if k[:4] == 'out=':
+ out_a = k[4:]
+ break
+ ret = {'varname': a, 'outvarname': out_a, 'ctype': getctype(var)}
+ intent_flags = []
+ for f, s in isintent_dict.items():
+ if f(var):
+ intent_flags.append('F2PY_%s' % s)
+ if intent_flags:
+ # TODO: Evaluate intent_flags here.
+ ret['intent'] = '|'.join(intent_flags)
+ else:
+ ret['intent'] = 'F2PY_INTENT_IN'
+ if isarray(var):
+ ret['varrformat'] = 'N'
+ elif ret['ctype'] in c2buildvalue_map:
+ ret['varrformat'] = c2buildvalue_map[ret['ctype']]
+ else:
+ ret['varrformat'] = 'O'
+ ret['init'], ret['showinit'] = getinit(a, var)
+ if hasinitvalue(var) and iscomplex(var) and not isarray(var):
+ ret['init.r'], ret['init.i'] = markoutercomma(
+ ret['init'][1:-1]).split('@,@')
+ if isexternal(var):
+ ret['cbnamekey'] = a
+ if a in lcb_map:
+ ret['cbname'] = lcb_map[a]
+ ret['maxnofargs'] = lcb2_map[lcb_map[a]]['maxnofargs']
+ ret['nofoptargs'] = lcb2_map[lcb_map[a]]['nofoptargs']
+ ret['cbdocstr'] = lcb2_map[lcb_map[a]]['docstr']
+ ret['cblatexdocstr'] = lcb2_map[lcb_map[a]]['latexdocstr']
+ else:
+ ret['cbname'] = a
+ errmess('sign2map: Confused: external %s is not in lcb_map%s.\n' % (
+ a, list(lcb_map.keys())))
+ if isstring(var):
+ ret['length'] = getstrlength(var)
+ if isarray(var):
+ ret = dictappend(ret, getarrdims(a, var))
+ dim = copy.copy(var['dimension'])
+ if ret['ctype'] in c2capi_map:
+ ret['atype'] = c2capi_map[ret['ctype']]
+ ret['elsize'] = get_elsize(var)
+ # Debug info
+ if debugcapi(var):
+ il = [isintent_in, 'input', isintent_out, 'output',
+ isintent_inout, 'inoutput', isrequired, 'required',
+ isoptional, 'optional', isintent_hide, 'hidden',
+ iscomplex, 'complex scalar',
+ l_and(isscalar, l_not(iscomplex)), 'scalar',
+ isstring, 'string', isarray, 'array',
+ iscomplexarray, 'complex array', isstringarray, 'string array',
+ iscomplexfunction, 'complex function',
+ l_and(isfunction, l_not(iscomplexfunction)), 'function',
+ isexternal, 'callback',
+ isintent_callback, 'callback',
+ isintent_aux, 'auxiliary',
+ ]
+ rl = []
+ for i in range(0, len(il), 2):
+ if il[i](var):
+ rl.append(il[i + 1])
+ if isstring(var):
+ rl.append('slen(%s)=%s' % (a, ret['length']))
+ if isarray(var):
+ ddim = ','.join(
+ map(lambda x, y: '%s|%s' % (x, y), var['dimension'], dim))
+ rl.append('dims(%s)' % ddim)
+ if isexternal(var):
+ ret['vardebuginfo'] = 'debug-capi:%s=>%s:%s' % (
+ a, ret['cbname'], ','.join(rl))
+ else:
+ ret['vardebuginfo'] = 'debug-capi:%s %s=%s:%s' % (
+ ret['ctype'], a, ret['showinit'], ','.join(rl))
+ if isscalar(var):
+ if ret['ctype'] in cformat_map:
+ ret['vardebugshowvalue'] = 'debug-capi:%s=%s' % (
+ a, cformat_map[ret['ctype']])
+ if isstring(var):
+ ret['vardebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
+ a, a)
+ if isexternal(var):
+ ret['vardebugshowvalue'] = 'debug-capi:%s=%%p' % (a)
+ if ret['ctype'] in cformat_map:
+ ret['varshowvalue'] = '#name#:%s=%s' % (a, cformat_map[ret['ctype']])
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isstring(var):
+ ret['varshowvalue'] = '#name#:slen(%s)=%%d %s=\\"%%s\\"' % (a, a)
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
+ if hasnote(var):
+ ret['note'] = var['note']
+ return ret
+
+
+def routsign2map(rout):
+ """
+ name,NAME,begintitle,endtitle
+ rname,ctype,rformat
+ routdebugshowvalue
+ """
+ global lcb_map
+ name = rout['name']
+ fname = getfortranname(rout)
+ ret = {'name': name,
+ 'texname': name.replace('_', '\\_'),
+ 'name_lower': name.lower(),
+ 'NAME': name.upper(),
+ 'begintitle': gentitle(name),
+ 'endtitle': gentitle('end of %s' % name),
+ 'fortranname': fname,
+ 'FORTRANNAME': fname.upper(),
+ 'callstatement': getcallstatement(rout) or '',
+ 'usercode': getusercode(rout) or '',
+ 'usercode1': getusercode1(rout) or '',
+ }
+ if '_' in fname:
+ ret['F_FUNC'] = 'F_FUNC_US'
+ else:
+ ret['F_FUNC'] = 'F_FUNC'
+ if '_' in name:
+ ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC_US'
+ else:
+ ret['F_WRAPPEDFUNC'] = 'F_WRAPPEDFUNC'
+ lcb_map = {}
+ if 'use' in rout:
+ for u in rout['use'].keys():
+ if u in cb_rules.cb_map:
+ for un in cb_rules.cb_map[u]:
+ ln = un[0]
+ if 'map' in rout['use'][u]:
+ for k in rout['use'][u]['map'].keys():
+ if rout['use'][u]['map'][k] == un[0]:
+ ln = k
+ break
+ lcb_map[ln] = un[1]
+ elif 'externals' in rout and rout['externals']:
+ errmess('routsign2map: Confused: function %s has externals %s but no "use" statement.\n' % (
+ ret['name'], repr(rout['externals'])))
+ ret['callprotoargument'] = getcallprotoargument(rout, lcb_map) or ''
+ if isfunction(rout):
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ ret['rname'] = a
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
+ ret['ctype'] = getctype(rout['vars'][a])
+ if hasresultnote(rout):
+ ret['resultnote'] = rout['vars'][a]['note']
+ rout['vars'][a]['note'] = ['See elsewhere.']
+ if ret['ctype'] in c2buildvalue_map:
+ ret['rformat'] = c2buildvalue_map[ret['ctype']]
+ else:
+ ret['rformat'] = 'O'
+ errmess('routsign2map: no c2buildvalue key for type %s\n' %
+ (repr(ret['ctype'])))
+ if debugcapi(rout):
+ if ret['ctype'] in cformat_map:
+ ret['routdebugshowvalue'] = 'debug-capi:%s=%s' % (
+ a, cformat_map[ret['ctype']])
+ if isstringfunction(rout):
+ ret['routdebugshowvalue'] = 'debug-capi:slen(%s)=%%d %s=\\"%%s\\"' % (
+ a, a)
+ if isstringfunction(rout):
+ ret['rlength'] = getstrlength(rout['vars'][a])
+ if ret['rlength'] == '-1':
+ errmess('routsign2map: expected explicit specification of the length of the string returned by the fortran function %s; taking 10.\n' % (
+ repr(rout['name'])))
+ ret['rlength'] = '10'
+ if hasnote(rout):
+ ret['note'] = rout['note']
+ rout['note'] = ['See elsewhere.']
+ return ret
+
+
+def modsign2map(m):
+ """
+ modulename
+ """
+ if ismodule(m):
+ ret = {'f90modulename': m['name'],
+ 'F90MODULENAME': m['name'].upper(),
+ 'texf90modulename': m['name'].replace('_', '\\_')}
+ else:
+ ret = {'modulename': m['name'],
+ 'MODULENAME': m['name'].upper(),
+ 'texmodulename': m['name'].replace('_', '\\_')}
+ ret['restdoc'] = getrestdoc(m) or []
+ if hasnote(m):
+ ret['note'] = m['note']
+ ret['usercode'] = getusercode(m) or ''
+ ret['usercode1'] = getusercode1(m) or ''
+ if m['body']:
+ ret['interface_usercode'] = getusercode(m['body'][0]) or ''
+ else:
+ ret['interface_usercode'] = ''
+ ret['pymethoddef'] = getpymethoddef(m) or ''
+ if 'coutput' in m:
+ ret['coutput'] = m['coutput']
+ if 'f2py_wrapper_output' in m:
+ ret['f2py_wrapper_output'] = m['f2py_wrapper_output']
+ return ret
+
+
+def cb_sign2map(a, var, index=None):
+ ret = {'varname': a}
+ ret['varname_i'] = ret['varname']
+ ret['ctype'] = getctype(var)
+ if ret['ctype'] in c2capi_map:
+ ret['atype'] = c2capi_map[ret['ctype']]
+ ret['elsize'] = get_elsize(var)
+ if ret['ctype'] in cformat_map:
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isarray(var):
+ ret = dictappend(ret, getarrdims(a, var))
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
+ if hasnote(var):
+ ret['note'] = var['note']
+ var['note'] = ['See elsewhere.']
+ return ret
+
+
+def cb_routsign2map(rout, um):
+ """
+ name,begintitle,endtitle,argname
+ ctype,rctype,maxnofargs,nofoptargs,returncptr
+ """
+ ret = {'name': 'cb_%s_in_%s' % (rout['name'], um),
+ 'returncptr': ''}
+ if isintent_callback(rout):
+ if '_' in rout['name']:
+ F_FUNC = 'F_FUNC_US'
+ else:
+ F_FUNC = 'F_FUNC'
+ ret['callbackname'] = '%s(%s,%s)' \
+ % (F_FUNC,
+ rout['name'].lower(),
+ rout['name'].upper(),
+ )
+ ret['static'] = 'extern'
+ else:
+ ret['callbackname'] = ret['name']
+ ret['static'] = 'static'
+ ret['argname'] = rout['name']
+ ret['begintitle'] = gentitle(ret['name'])
+ ret['endtitle'] = gentitle('end of %s' % ret['name'])
+ ret['ctype'] = getctype(rout)
+ ret['rctype'] = 'void'
+ if ret['ctype'] == 'string':
+ ret['rctype'] = 'void'
+ else:
+ ret['rctype'] = ret['ctype']
+ if ret['rctype'] != 'void':
+ if iscomplexfunction(rout):
+ ret['returncptr'] = """
+#ifdef F2PY_CB_RETURNCOMPLEX
+return_value=
+#endif
+"""
+ else:
+ ret['returncptr'] = 'return_value='
+ if ret['ctype'] in cformat_map:
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isstringfunction(rout):
+ ret['strlength'] = getstrlength(rout)
+ if isfunction(rout):
+ if 'result' in rout:
+ a = rout['result']
+ else:
+ a = rout['name']
+ if hasnote(rout['vars'][a]):
+ ret['note'] = rout['vars'][a]['note']
+ rout['vars'][a]['note'] = ['See elsewhere.']
+ ret['rname'] = a
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, rout)
+ if iscomplexfunction(rout):
+ ret['rctype'] = """
+#ifdef F2PY_CB_RETURNCOMPLEX
+#ctype#
+#else
+void
+#endif
+"""
+ else:
+ if hasnote(rout):
+ ret['note'] = rout['note']
+ rout['note'] = ['See elsewhere.']
+ nofargs = 0
+ nofoptargs = 0
+ if 'args' in rout and 'vars' in rout:
+ for a in rout['args']:
+ var = rout['vars'][a]
+ if l_or(isintent_in, isintent_inout)(var):
+ nofargs = nofargs + 1
+ if isoptional(var):
+ nofoptargs = nofoptargs + 1
+ ret['maxnofargs'] = repr(nofargs)
+ ret['nofoptargs'] = repr(nofoptargs)
+ if hasnote(rout) and isfunction(rout) and 'result' in rout:
+ ret['routnote'] = rout['note']
+ rout['note'] = ['See elsewhere.']
+ return ret
+
+
+def common_sign2map(a, var): # obsolute
+ ret = {'varname': a, 'ctype': getctype(var)}
+ if isstringarray(var):
+ ret['ctype'] = 'char'
+ if ret['ctype'] in c2capi_map:
+ ret['atype'] = c2capi_map[ret['ctype']]
+ ret['elsize'] = get_elsize(var)
+ if ret['ctype'] in cformat_map:
+ ret['showvalueformat'] = '%s' % (cformat_map[ret['ctype']])
+ if isarray(var):
+ ret = dictappend(ret, getarrdims(a, var))
+ elif isstring(var):
+ ret['size'] = getstrlength(var)
+ ret['rank'] = '1'
+ ret['pydocsign'], ret['pydocsignout'] = getpydocsign(a, var)
+ if hasnote(var):
+ ret['note'] = var['note']
+ var['note'] = ['See elsewhere.']
+ # for strings this returns 0-rank but actually is 1-rank
+ ret['arrdocstr'] = getarrdocsign(a, var)
+ return ret
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/cb_rules.py b/venv/lib/python3.9/site-packages/numpy/f2py/cb_rules.py
new file mode 100644
index 00000000..761831e0
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/cb_rules.py
@@ -0,0 +1,649 @@
+#!/usr/bin/env python3
+"""
+
+Build call-back mechanism for f2py2e.
+
+Copyright 2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/07/20 11:27:58 $
+Pearu Peterson
+
+"""
+from . import __version__
+from .auxfuncs import (
+ applyrules, debugcapi, dictappend, errmess, getargs, hasnote, isarray,
+ iscomplex, iscomplexarray, iscomplexfunction, isfunction, isintent_c,
+ isintent_hide, isintent_in, isintent_inout, isintent_nothide,
+ isintent_out, isoptional, isrequired, isscalar, isstring,
+ isstringfunction, issubroutine, l_and, l_not, l_or, outmess, replace,
+ stripcomma, throw_error
+)
+from . import cfuncs
+
+f2py_version = __version__.version
+
+
+################## Rules for callback function ##############
+
+cb_routine_rules = {
+ 'cbtypedefs': 'typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);',
+ 'body': """
+#begintitle#
+typedef struct {
+ PyObject *capi;
+ PyTupleObject *args_capi;
+ int nofargs;
+ jmp_buf jmpbuf;
+} #name#_t;
+
+#if defined(F2PY_THREAD_LOCAL_DECL) && !defined(F2PY_USE_PYTHON_TLS)
+
+static F2PY_THREAD_LOCAL_DECL #name#_t *_active_#name# = NULL;
+
+static #name#_t *swap_active_#name#(#name#_t *ptr) {
+ #name#_t *prev = _active_#name#;
+ _active_#name# = ptr;
+ return prev;
+}
+
+static #name#_t *get_active_#name#(void) {
+ return _active_#name#;
+}
+
+#else
+
+static #name#_t *swap_active_#name#(#name#_t *ptr) {
+ char *key = "__f2py_cb_#name#";
+ return (#name#_t *)F2PySwapThreadLocalCallbackPtr(key, ptr);
+}
+
+static #name#_t *get_active_#name#(void) {
+ char *key = "__f2py_cb_#name#";
+ return (#name#_t *)F2PyGetThreadLocalCallbackPtr(key);
+}
+
+#endif
+
+/*typedef #rctype#(*#name#_typedef)(#optargs_td##args_td##strarglens_td##noargs#);*/
+#static# #rctype# #callbackname# (#optargs##args##strarglens##noargs#) {
+ #name#_t cb_local = { NULL, NULL, 0 };
+ #name#_t *cb = NULL;
+ PyTupleObject *capi_arglist = NULL;
+ PyObject *capi_return = NULL;
+ PyObject *capi_tmp = NULL;
+ PyObject *capi_arglist_list = NULL;
+ int capi_j,capi_i = 0;
+ int capi_longjmp_ok = 1;
+#decl#
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_start_clock();
+#endif
+ cb = get_active_#name#();
+ if (cb == NULL) {
+ capi_longjmp_ok = 0;
+ cb = &cb_local;
+ }
+ capi_arglist = cb->args_capi;
+ CFUNCSMESS(\"cb:Call-back function #name# (maxnofargs=#maxnofargs#(-#nofoptargs#))\\n\");
+ CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
+ if (cb->capi==NULL) {
+ capi_longjmp_ok = 0;
+ cb->capi = PyObject_GetAttrString(#modulename#_module,\"#argname#\");
+ CFUNCSMESSPY(\"cb:#name#_capi=\",cb->capi);
+ }
+ if (cb->capi==NULL) {
+ PyErr_SetString(#modulename#_error,\"cb: Callback #argname# not defined (as an argument or module #modulename# attribute).\\n\");
+ goto capi_fail;
+ }
+ if (F2PyCapsule_Check(cb->capi)) {
+ #name#_typedef #name#_cptr;
+ #name#_cptr = F2PyCapsule_AsVoidPtr(cb->capi);
+ #returncptr#(*#name#_cptr)(#optargs_nm##args_nm##strarglens_nm#);
+ #return#
+ }
+ if (capi_arglist==NULL) {
+ capi_longjmp_ok = 0;
+ capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#argname#_extra_args\");
+ if (capi_tmp) {
+ capi_arglist = (PyTupleObject *)PySequence_Tuple(capi_tmp);
+ Py_DECREF(capi_tmp);
+ if (capi_arglist==NULL) {
+ PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#argname#_extra_args to tuple.\\n\");
+ goto capi_fail;
+ }
+ } else {
+ PyErr_Clear();
+ capi_arglist = (PyTupleObject *)Py_BuildValue(\"()\");
+ }
+ }
+ if (capi_arglist == NULL) {
+ PyErr_SetString(#modulename#_error,\"Callback #argname# argument list is not set.\\n\");
+ goto capi_fail;
+ }
+#setdims#
+#ifdef PYPY_VERSION
+#define CAPI_ARGLIST_SETITEM(idx, value) PyList_SetItem((PyObject *)capi_arglist_list, idx, value)
+ capi_arglist_list = PySequence_List(capi_arglist);
+ if (capi_arglist_list == NULL) goto capi_fail;
+#else
+#define CAPI_ARGLIST_SETITEM(idx, value) PyTuple_SetItem((PyObject *)capi_arglist, idx, value)
+#endif
+#pyobjfrom#
+#undef CAPI_ARGLIST_SETITEM
+#ifdef PYPY_VERSION
+ CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist_list);
+#else
+ CFUNCSMESSPY(\"cb:capi_arglist=\",capi_arglist);
+#endif
+ CFUNCSMESS(\"cb:Call-back calling Python function #argname#.\\n\");
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_start_call_clock();
+#endif
+#ifdef PYPY_VERSION
+ capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist_list);
+ Py_DECREF(capi_arglist_list);
+ capi_arglist_list = NULL;
+#else
+ capi_return = PyObject_CallObject(cb->capi,(PyObject *)capi_arglist);
+#endif
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_stop_call_clock();
+#endif
+ CFUNCSMESSPY(\"cb:capi_return=\",capi_return);
+ if (capi_return == NULL) {
+ fprintf(stderr,\"capi_return is NULL\\n\");
+ goto capi_fail;
+ }
+ if (capi_return == Py_None) {
+ Py_DECREF(capi_return);
+ capi_return = Py_BuildValue(\"()\");
+ }
+ else if (!PyTuple_Check(capi_return)) {
+ capi_return = Py_BuildValue(\"(N)\",capi_return);
+ }
+ capi_j = PyTuple_Size(capi_return);
+ capi_i = 0;
+#frompyobj#
+ CFUNCSMESS(\"cb:#name#:successful\\n\");
+ Py_DECREF(capi_return);
+#ifdef F2PY_REPORT_ATEXIT
+f2py_cb_stop_clock();
+#endif
+ goto capi_return_pt;
+capi_fail:
+ fprintf(stderr,\"Call-back #name# failed.\\n\");
+ Py_XDECREF(capi_return);
+ Py_XDECREF(capi_arglist_list);
+ if (capi_longjmp_ok) {
+ longjmp(cb->jmpbuf,-1);
+ }
+capi_return_pt:
+ ;
+#return#
+}
+#endtitle#
+""",
+ 'need': ['setjmp.h', 'CFUNCSMESS', 'F2PY_THREAD_LOCAL_DECL'],
+ 'maxnofargs': '#maxnofargs#',
+ 'nofoptargs': '#nofoptargs#',
+ 'docstr': """\
+ def #argname#(#docsignature#): return #docreturn#\\n\\
+#docstrsigns#""",
+ 'latexdocstr': """
+{{}\\verb@def #argname#(#latexdocsignature#): return #docreturn#@{}}
+#routnote#
+
+#latexdocstrsigns#""",
+ 'docstrshort': 'def #argname#(#docsignature#): return #docreturn#'
+}
+cb_rout_rules = [
+ { # Init
+ 'separatorsfor': {'decl': '\n',
+ 'args': ',', 'optargs': '', 'pyobjfrom': '\n', 'freemem': '\n',
+ 'args_td': ',', 'optargs_td': '',
+ 'args_nm': ',', 'optargs_nm': '',
+ 'frompyobj': '\n', 'setdims': '\n',
+ 'docstrsigns': '\\n"\n"',
+ 'latexdocstrsigns': '\n',
+ 'latexdocstrreq': '\n', 'latexdocstropt': '\n',
+ 'latexdocstrout': '\n', 'latexdocstrcbs': '\n',
+ },
+ 'decl': '/*decl*/', 'pyobjfrom': '/*pyobjfrom*/', 'frompyobj': '/*frompyobj*/',
+ 'args': [], 'optargs': '', 'return': '', 'strarglens': '', 'freemem': '/*freemem*/',
+ 'args_td': [], 'optargs_td': '', 'strarglens_td': '',
+ 'args_nm': [], 'optargs_nm': '', 'strarglens_nm': '',
+ 'noargs': '',
+ 'setdims': '/*setdims*/',
+ 'docstrsigns': '', 'latexdocstrsigns': '',
+ 'docstrreq': ' Required arguments:',
+ 'docstropt': ' Optional arguments:',
+ 'docstrout': ' Return objects:',
+ 'docstrcbs': ' Call-back functions:',
+ 'docreturn': '', 'docsign': '', 'docsignopt': '',
+ 'latexdocstrreq': '\\noindent Required arguments:',
+ 'latexdocstropt': '\\noindent Optional arguments:',
+ 'latexdocstrout': '\\noindent Return objects:',
+ 'latexdocstrcbs': '\\noindent Call-back functions:',
+ 'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
+ }, { # Function
+ 'decl': ' #ctype# return_value = 0;',
+ 'frompyobj': [
+ {debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'},
+ '''\
+ if (capi_j>capi_i) {
+ GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,
+ "#ctype#_from_pyobj failed in converting return_value of"
+ " call-back function #name# to C #ctype#\\n");
+ } else {
+ fprintf(stderr,"Warning: call-back function #name# did not provide"
+ " return value (index=%d, type=#ctype#)\\n",capi_i);
+ }''',
+ {debugcapi:
+ ' fprintf(stderr,"#showvalueformat#.\\n",return_value);'}
+ ],
+ 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'}, 'GETSCALARFROMPYTUPLE'],
+ 'return': ' return return_value;',
+ '_check': l_and(isfunction, l_not(isstringfunction), l_not(iscomplexfunction))
+ },
+ { # String function
+ 'pyobjfrom': {debugcapi: ' fprintf(stderr,"debug-capi:cb:#name#:%d:\\n",return_value_len);'},
+ 'args': '#ctype# return_value,int return_value_len',
+ 'args_nm': 'return_value,&return_value_len',
+ 'args_td': '#ctype# ,int',
+ 'frompyobj': [
+ {debugcapi: ' CFUNCSMESS("cb:Getting return_value->\\"");'},
+ """\
+ if (capi_j>capi_i) {
+ GETSTRFROMPYTUPLE(capi_return,capi_i++,return_value,return_value_len);
+ } else {
+ fprintf(stderr,"Warning: call-back function #name# did not provide"
+ " return value (index=%d, type=#ctype#)\\n",capi_i);
+ }""",
+ {debugcapi:
+ ' fprintf(stderr,"#showvalueformat#\\".\\n",return_value);'}
+ ],
+ 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
+ 'string.h', 'GETSTRFROMPYTUPLE'],
+ 'return': 'return;',
+ '_check': isstringfunction
+ },
+ { # Complex function
+ 'optargs': """
+#ifndef F2PY_CB_RETURNCOMPLEX
+#ctype# *return_value
+#endif
+""",
+ 'optargs_nm': """
+#ifndef F2PY_CB_RETURNCOMPLEX
+return_value
+#endif
+""",
+ 'optargs_td': """
+#ifndef F2PY_CB_RETURNCOMPLEX
+#ctype# *
+#endif
+""",
+ 'decl': """
+#ifdef F2PY_CB_RETURNCOMPLEX
+ #ctype# return_value = {0, 0};
+#endif
+""",
+ 'frompyobj': [
+ {debugcapi: ' CFUNCSMESS("cb:Getting return_value->");'},
+ """\
+ if (capi_j>capi_i) {
+#ifdef F2PY_CB_RETURNCOMPLEX
+ GETSCALARFROMPYTUPLE(capi_return,capi_i++,&return_value,#ctype#,
+ \"#ctype#_from_pyobj failed in converting return_value of call-back\"
+ \" function #name# to C #ctype#\\n\");
+#else
+ GETSCALARFROMPYTUPLE(capi_return,capi_i++,return_value,#ctype#,
+ \"#ctype#_from_pyobj failed in converting return_value of call-back\"
+ \" function #name# to C #ctype#\\n\");
+#endif
+ } else {
+ fprintf(stderr,
+ \"Warning: call-back function #name# did not provide\"
+ \" return value (index=%d, type=#ctype#)\\n\",capi_i);
+ }""",
+ {debugcapi: """\
+#ifdef F2PY_CB_RETURNCOMPLEX
+ fprintf(stderr,\"#showvalueformat#.\\n\",(return_value).r,(return_value).i);
+#else
+ fprintf(stderr,\"#showvalueformat#.\\n\",(*return_value).r,(*return_value).i);
+#endif
+"""}
+ ],
+ 'return': """
+#ifdef F2PY_CB_RETURNCOMPLEX
+ return return_value;
+#else
+ return;
+#endif
+""",
+ 'need': ['#ctype#_from_pyobj', {debugcapi: 'CFUNCSMESS'},
+ 'string.h', 'GETSCALARFROMPYTUPLE', '#ctype#'],
+ '_check': iscomplexfunction
+ },
+ {'docstrout': ' #pydocsignout#',
+ 'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {hasnote: '--- #note#'}],
+ 'docreturn': '#rname#,',
+ '_check': isfunction},
+ {'_check': issubroutine, 'return': 'return;'}
+]
+
+cb_arg_rules = [
+ { # Doc
+ 'docstropt': {l_and(isoptional, isintent_nothide): ' #pydocsign#'},
+ 'docstrreq': {l_and(isrequired, isintent_nothide): ' #pydocsign#'},
+ 'docstrout': {isintent_out: ' #pydocsignout#'},
+ 'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote: '--- #note#'}]},
+ 'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote: '--- #note#'}]},
+ 'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {l_and(hasnote, isintent_hide): '--- #note#',
+ l_and(hasnote, isintent_nothide): '--- See above.'}]},
+ 'docsign': {l_and(isrequired, isintent_nothide): '#varname#,'},
+ 'docsignopt': {l_and(isoptional, isintent_nothide): '#varname#,'},
+ 'depend': ''
+ },
+ {
+ 'args': {
+ l_and(isscalar, isintent_c): '#ctype# #varname_i#',
+ l_and(isscalar, l_not(isintent_c)): '#ctype# *#varname_i#_cb_capi',
+ isarray: '#ctype# *#varname_i#',
+ isstring: '#ctype# #varname_i#'
+ },
+ 'args_nm': {
+ l_and(isscalar, isintent_c): '#varname_i#',
+ l_and(isscalar, l_not(isintent_c)): '#varname_i#_cb_capi',
+ isarray: '#varname_i#',
+ isstring: '#varname_i#'
+ },
+ 'args_td': {
+ l_and(isscalar, isintent_c): '#ctype#',
+ l_and(isscalar, l_not(isintent_c)): '#ctype# *',
+ isarray: '#ctype# *',
+ isstring: '#ctype#'
+ },
+ 'need': {l_or(isscalar, isarray, isstring): '#ctype#'},
+ # untested with multiple args
+ 'strarglens': {isstring: ',int #varname_i#_cb_len'},
+ 'strarglens_td': {isstring: ',int'}, # untested with multiple args
+ # untested with multiple args
+ 'strarglens_nm': {isstring: ',#varname_i#_cb_len'},
+ },
+ { # Scalars
+ 'decl': {l_not(isintent_c): ' #ctype# #varname_i#=(*#varname_i#_cb_capi);'},
+ 'error': {l_and(isintent_c, isintent_out,
+ throw_error('intent(c,out) is forbidden for callback scalar arguments')):
+ ''},
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'},
+ {isintent_out:
+ ' if (capi_j>capi_i)\n GETSCALARFROMPYTUPLE(capi_return,capi_i++,#varname_i#_cb_capi,#ctype#,"#ctype#_from_pyobj failed in converting argument #varname# of call-back function #name# to C #ctype#\\n");'},
+ {l_and(debugcapi, l_and(l_not(iscomplex), isintent_c)):
+ ' fprintf(stderr,"#showvalueformat#.\\n",#varname_i#);'},
+ {l_and(debugcapi, l_and(l_not(iscomplex), l_not( isintent_c))):
+ ' fprintf(stderr,"#showvalueformat#.\\n",*#varname_i#_cb_capi);'},
+ {l_and(debugcapi, l_and(iscomplex, isintent_c)):
+ ' fprintf(stderr,"#showvalueformat#.\\n",(#varname_i#).r,(#varname_i#).i);'},
+ {l_and(debugcapi, l_and(iscomplex, l_not( isintent_c))):
+ ' fprintf(stderr,"#showvalueformat#.\\n",(*#varname_i#_cb_capi).r,(*#varname_i#_cb_capi).i);'},
+ ],
+ 'need': [{isintent_out: ['#ctype#_from_pyobj', 'GETSCALARFROMPYTUPLE']},
+ {debugcapi: 'CFUNCSMESS'}],
+ '_check': isscalar
+ }, {
+ 'pyobjfrom': [{isintent_in: """\
+ if (cb->nofargs>capi_i)
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1(#varname_i#)))
+ goto capi_fail;"""},
+ {isintent_inout: """\
+ if (cb->nofargs>capi_i)
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#_cb_capi)))
+ goto capi_fail;"""}],
+ 'need': [{isintent_in: 'pyobj_from_#ctype#1'},
+ {isintent_inout: 'pyarr_from_p_#ctype#1'},
+ {iscomplex: '#ctype#'}],
+ '_check': l_and(isscalar, isintent_nothide),
+ '_optional': ''
+ }, { # String
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->\\"");'},
+ """ if (capi_j>capi_i)
+ GETSTRFROMPYTUPLE(capi_return,capi_i++,#varname_i#,#varname_i#_cb_len);""",
+ {debugcapi:
+ ' fprintf(stderr,"#showvalueformat#\\":%d:.\\n",#varname_i#,#varname_i#_cb_len);'},
+ ],
+ 'need': ['#ctype#', 'GETSTRFROMPYTUPLE',
+ {debugcapi: 'CFUNCSMESS'}, 'string.h'],
+ '_check': l_and(isstring, isintent_out)
+ }, {
+ 'pyobjfrom': [
+ {debugcapi:
+ (' fprintf(stderr,"debug-capi:cb:#varname#=#showvalueformat#:'
+ '%d:\\n",#varname_i#,#varname_i#_cb_len);')},
+ {isintent_in: """\
+ if (cb->nofargs>capi_i)
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyobj_from_#ctype#1size(#varname_i#,#varname_i#_cb_len)))
+ goto capi_fail;"""},
+ {isintent_inout: """\
+ if (cb->nofargs>capi_i) {
+ int #varname_i#_cb_dims[] = {#varname_i#_cb_len};
+ if (CAPI_ARGLIST_SETITEM(capi_i++,pyarr_from_p_#ctype#1(#varname_i#,#varname_i#_cb_dims)))
+ goto capi_fail;
+ }"""}],
+ 'need': [{isintent_in: 'pyobj_from_#ctype#1size'},
+ {isintent_inout: 'pyarr_from_p_#ctype#1'}],
+ '_check': l_and(isstring, isintent_nothide),
+ '_optional': ''
+ },
+ # Array ...
+ {
+ 'decl': ' npy_intp #varname_i#_Dims[#rank#] = {#rank*[-1]#};',
+ 'setdims': ' #cbsetdims#;',
+ '_check': isarray,
+ '_depend': ''
+ },
+ {
+ 'pyobjfrom': [{debugcapi: ' fprintf(stderr,"debug-capi:cb:#varname#\\n");'},
+ {isintent_c: """\
+ if (cb->nofargs>capi_i) {
+ /* tmp_arr will be inserted to capi_arglist_list that will be
+ destroyed when leaving callback function wrapper together
+ with tmp_arr. */
+ PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,
+ #rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#,
+ NPY_ARRAY_CARRAY,NULL);
+""",
+ l_not(isintent_c): """\
+ if (cb->nofargs>capi_i) {
+ /* tmp_arr will be inserted to capi_arglist_list that will be
+ destroyed when leaving callback function wrapper together
+ with tmp_arr. */
+ PyArrayObject *tmp_arr = (PyArrayObject *)PyArray_New(&PyArray_Type,
+ #rank#,#varname_i#_Dims,#atype#,NULL,(char*)#varname_i#,#elsize#,
+ NPY_ARRAY_FARRAY,NULL);
+""",
+ },
+ """
+ if (tmp_arr==NULL)
+ goto capi_fail;
+ if (CAPI_ARGLIST_SETITEM(capi_i++,(PyObject *)tmp_arr))
+ goto capi_fail;
+}"""],
+ '_check': l_and(isarray, isintent_nothide, l_or(isintent_in, isintent_inout)),
+ '_optional': '',
+ }, {
+ 'frompyobj': [{debugcapi: ' CFUNCSMESS("cb:Getting #varname#->");'},
+ """ if (capi_j>capi_i) {
+ PyArrayObject *rv_cb_arr = NULL;
+ if ((capi_tmp = PyTuple_GetItem(capi_return,capi_i++))==NULL) goto capi_fail;
+ rv_cb_arr = array_from_pyobj(#atype#,#varname_i#_Dims,#rank#,F2PY_INTENT_IN""",
+ {isintent_c: '|F2PY_INTENT_C'},
+ """,capi_tmp);
+ if (rv_cb_arr == NULL) {
+ fprintf(stderr,\"rv_cb_arr is NULL\\n\");
+ goto capi_fail;
+ }
+ MEMCOPY(#varname_i#,PyArray_DATA(rv_cb_arr),PyArray_NBYTES(rv_cb_arr));
+ if (capi_tmp != (PyObject *)rv_cb_arr) {
+ Py_DECREF(rv_cb_arr);
+ }
+ }""",
+ {debugcapi: ' fprintf(stderr,"<-.\\n");'},
+ ],
+ 'need': ['MEMCOPY', {iscomplexarray: '#ctype#'}],
+ '_check': l_and(isarray, isintent_out)
+ }, {
+ 'docreturn': '#varname#,',
+ '_check': isintent_out
+ }
+]
+
+################## Build call-back module #############
+cb_map = {}
+
+
+def buildcallbacks(m):
+ cb_map[m['name']] = []
+ for bi in m['body']:
+ if bi['block'] == 'interface':
+ for b in bi['body']:
+ if b:
+ buildcallback(b, m['name'])
+ else:
+ errmess('warning: empty body for %s\n' % (m['name']))
+
+
+def buildcallback(rout, um):
+ from . import capi_maps
+
+ outmess(' Constructing call-back function "cb_%s_in_%s"\n' %
+ (rout['name'], um))
+ args, depargs = getargs(rout)
+ capi_maps.depargs = depargs
+ var = rout['vars']
+ vrd = capi_maps.cb_routsign2map(rout, um)
+ rd = dictappend({}, vrd)
+ cb_map[um].append([rout['name'], rd['name']])
+ for r in cb_rout_rules:
+ if ('_check' in r and r['_check'](rout)) or ('_check' not in r):
+ ar = applyrules(r, vrd, rout)
+ rd = dictappend(rd, ar)
+ savevrd = {}
+ for i, a in enumerate(args):
+ vrd = capi_maps.cb_sign2map(a, var[a], index=i)
+ savevrd[a] = vrd
+ for r in cb_arg_rules:
+ if '_depend' in r:
+ continue
+ if '_optional' in r and isoptional(var[a]):
+ continue
+ if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
+ ar = applyrules(r, vrd, var[a])
+ rd = dictappend(rd, ar)
+ if '_break' in r:
+ break
+ for a in args:
+ vrd = savevrd[a]
+ for r in cb_arg_rules:
+ if '_depend' in r:
+ continue
+ if ('_optional' not in r) or ('_optional' in r and isrequired(var[a])):
+ continue
+ if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
+ ar = applyrules(r, vrd, var[a])
+ rd = dictappend(rd, ar)
+ if '_break' in r:
+ break
+ for a in depargs:
+ vrd = savevrd[a]
+ for r in cb_arg_rules:
+ if '_depend' not in r:
+ continue
+ if '_optional' in r:
+ continue
+ if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
+ ar = applyrules(r, vrd, var[a])
+ rd = dictappend(rd, ar)
+ if '_break' in r:
+ break
+ if 'args' in rd and 'optargs' in rd:
+ if isinstance(rd['optargs'], list):
+ rd['optargs'] = rd['optargs'] + ["""
+#ifndef F2PY_CB_RETURNCOMPLEX
+,
+#endif
+"""]
+ rd['optargs_nm'] = rd['optargs_nm'] + ["""
+#ifndef F2PY_CB_RETURNCOMPLEX
+,
+#endif
+"""]
+ rd['optargs_td'] = rd['optargs_td'] + ["""
+#ifndef F2PY_CB_RETURNCOMPLEX
+,
+#endif
+"""]
+ if isinstance(rd['docreturn'], list):
+ rd['docreturn'] = stripcomma(
+ replace('#docreturn#', {'docreturn': rd['docreturn']}))
+ optargs = stripcomma(replace('#docsignopt#',
+ {'docsignopt': rd['docsignopt']}
+ ))
+ if optargs == '':
+ rd['docsignature'] = stripcomma(
+ replace('#docsign#', {'docsign': rd['docsign']}))
+ else:
+ rd['docsignature'] = replace('#docsign#[#docsignopt#]',
+ {'docsign': rd['docsign'],
+ 'docsignopt': optargs,
+ })
+ rd['latexdocsignature'] = rd['docsignature'].replace('_', '\\_')
+ rd['latexdocsignature'] = rd['latexdocsignature'].replace(',', ', ')
+ rd['docstrsigns'] = []
+ rd['latexdocstrsigns'] = []
+ for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']:
+ if k in rd and isinstance(rd[k], list):
+ rd['docstrsigns'] = rd['docstrsigns'] + rd[k]
+ k = 'latex' + k
+ if k in rd and isinstance(rd[k], list):
+ rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\
+ ['\\begin{description}'] + rd[k][1:] +\
+ ['\\end{description}']
+ if 'args' not in rd:
+ rd['args'] = ''
+ rd['args_td'] = ''
+ rd['args_nm'] = ''
+ if not (rd.get('args') or rd.get('optargs') or rd.get('strarglens')):
+ rd['noargs'] = 'void'
+
+ ar = applyrules(cb_routine_rules, rd)
+ cfuncs.callbacks[rd['name']] = ar['body']
+ if isinstance(ar['need'], str):
+ ar['need'] = [ar['need']]
+
+ if 'need' in rd:
+ for t in cfuncs.typedefs.keys():
+ if t in rd['need']:
+ ar['need'].append(t)
+
+ cfuncs.typedefs_generated[rd['name'] + '_typedef'] = ar['cbtypedefs']
+ ar['need'].append(rd['name'] + '_typedef')
+ cfuncs.needs[rd['name']] = ar['need']
+
+ capi_maps.lcb2_map[rd['name']] = {'maxnofargs': ar['maxnofargs'],
+ 'nofoptargs': ar['nofoptargs'],
+ 'docstr': ar['docstr'],
+ 'latexdocstr': ar['latexdocstr'],
+ 'argname': rd['argname']
+ }
+ outmess(' %s\n' % (ar['docstrshort']))
+ return
+################## Build call-back function #############
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/cfuncs.py b/venv/lib/python3.9/site-packages/numpy/f2py/cfuncs.py
new file mode 100644
index 00000000..74169256
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/cfuncs.py
@@ -0,0 +1,1522 @@
+#!/usr/bin/env python3
+"""
+
+C declarations, CPP macros, and C functions for f2py2e.
+Only required declarations/macros/functions will be used.
+
+Copyright 1999,2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 11:42:34 $
+Pearu Peterson
+
+"""
+import sys
+import copy
+
+from . import __version__
+
+f2py_version = __version__.version
+errmess = sys.stderr.write
+
+##################### Definitions ##################
+
+outneeds = {'includes0': [], 'includes': [], 'typedefs': [], 'typedefs_generated': [],
+ 'userincludes': [],
+ 'cppmacros': [], 'cfuncs': [], 'callbacks': [], 'f90modhooks': [],
+ 'commonhooks': []}
+needs = {}
+includes0 = {'includes0': '/*need_includes0*/'}
+includes = {'includes': '/*need_includes*/'}
+userincludes = {'userincludes': '/*need_userincludes*/'}
+typedefs = {'typedefs': '/*need_typedefs*/'}
+typedefs_generated = {'typedefs_generated': '/*need_typedefs_generated*/'}
+cppmacros = {'cppmacros': '/*need_cppmacros*/'}
+cfuncs = {'cfuncs': '/*need_cfuncs*/'}
+callbacks = {'callbacks': '/*need_callbacks*/'}
+f90modhooks = {'f90modhooks': '/*need_f90modhooks*/',
+ 'initf90modhooksstatic': '/*initf90modhooksstatic*/',
+ 'initf90modhooksdynamic': '/*initf90modhooksdynamic*/',
+ }
+commonhooks = {'commonhooks': '/*need_commonhooks*/',
+ 'initcommonhooks': '/*need_initcommonhooks*/',
+ }
+
+############ Includes ###################
+
+includes0['math.h'] = '#include <math.h>'
+includes0['string.h'] = '#include <string.h>'
+includes0['setjmp.h'] = '#include <setjmp.h>'
+
+includes['arrayobject.h'] = '''#define PY_ARRAY_UNIQUE_SYMBOL PyArray_API
+#include "arrayobject.h"'''
+
+includes['arrayobject.h'] = '#include "fortranobject.h"'
+includes['stdarg.h'] = '#include <stdarg.h>'
+
+############# Type definitions ###############
+
+typedefs['unsigned_char'] = 'typedef unsigned char unsigned_char;'
+typedefs['unsigned_short'] = 'typedef unsigned short unsigned_short;'
+typedefs['unsigned_long'] = 'typedef unsigned long unsigned_long;'
+typedefs['signed_char'] = 'typedef signed char signed_char;'
+typedefs['long_long'] = """\
+#if defined(NPY_OS_WIN32)
+typedef __int64 long_long;
+#else
+typedef long long long_long;
+typedef unsigned long long unsigned_long_long;
+#endif
+"""
+typedefs['unsigned_long_long'] = """\
+#if defined(NPY_OS_WIN32)
+typedef __uint64 long_long;
+#else
+typedef unsigned long long unsigned_long_long;
+#endif
+"""
+typedefs['long_double'] = """\
+#ifndef _LONG_DOUBLE
+typedef long double long_double;
+#endif
+"""
+typedefs[
+ 'complex_long_double'] = 'typedef struct {long double r,i;} complex_long_double;'
+typedefs['complex_float'] = 'typedef struct {float r,i;} complex_float;'
+typedefs['complex_double'] = 'typedef struct {double r,i;} complex_double;'
+typedefs['string'] = """typedef char * string;"""
+typedefs['character'] = """typedef char character;"""
+
+
+############### CPP macros ####################
+cppmacros['CFUNCSMESS'] = """\
+#ifdef DEBUGCFUNCS
+#define CFUNCSMESS(mess) fprintf(stderr,\"debug-capi:\"mess);
+#define CFUNCSMESSPY(mess,obj) CFUNCSMESS(mess) \\
+ PyObject_Print((PyObject *)obj,stderr,Py_PRINT_RAW);\\
+ fprintf(stderr,\"\\n\");
+#else
+#define CFUNCSMESS(mess)
+#define CFUNCSMESSPY(mess,obj)
+#endif
+"""
+cppmacros['F_FUNC'] = """\
+#if defined(PREPEND_FORTRAN)
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F
+#else
+#define F_FUNC(f,F) _##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) _##F##_
+#else
+#define F_FUNC(f,F) _##f##_
+#endif
+#endif
+#else
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F
+#else
+#define F_FUNC(f,F) f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_FUNC(f,F) F##_
+#else
+#define F_FUNC(f,F) f##_
+#endif
+#endif
+#endif
+#if defined(UNDERSCORE_G77)
+#define F_FUNC_US(f,F) F_FUNC(f##_,F##_)
+#else
+#define F_FUNC_US(f,F) F_FUNC(f,F)
+#endif
+"""
+cppmacros['F_WRAPPEDFUNC'] = """\
+#if defined(PREPEND_FORTRAN)
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) _F2PYWRAP##F
+#else
+#define F_WRAPPEDFUNC(f,F) _f2pywrap##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) _F2PYWRAP##F##_
+#else
+#define F_WRAPPEDFUNC(f,F) _f2pywrap##f##_
+#endif
+#endif
+#else
+#if defined(NO_APPEND_FORTRAN)
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) F2PYWRAP##F
+#else
+#define F_WRAPPEDFUNC(f,F) f2pywrap##f
+#endif
+#else
+#if defined(UPPERCASE_FORTRAN)
+#define F_WRAPPEDFUNC(f,F) F2PYWRAP##F##_
+#else
+#define F_WRAPPEDFUNC(f,F) f2pywrap##f##_
+#endif
+#endif
+#endif
+#if defined(UNDERSCORE_G77)
+#define F_WRAPPEDFUNC_US(f,F) F_WRAPPEDFUNC(f##_,F##_)
+#else
+#define F_WRAPPEDFUNC_US(f,F) F_WRAPPEDFUNC(f,F)
+#endif
+"""
+cppmacros['F_MODFUNC'] = """\
+#if defined(F90MOD2CCONV1) /*E.g. Compaq Fortran */
+#if defined(NO_APPEND_FORTRAN)
+#define F_MODFUNCNAME(m,f) $ ## m ## $ ## f
+#else
+#define F_MODFUNCNAME(m,f) $ ## m ## $ ## f ## _
+#endif
+#endif
+
+#if defined(F90MOD2CCONV2) /*E.g. IBM XL Fortran, not tested though */
+#if defined(NO_APPEND_FORTRAN)
+#define F_MODFUNCNAME(m,f) __ ## m ## _MOD_ ## f
+#else
+#define F_MODFUNCNAME(m,f) __ ## m ## _MOD_ ## f ## _
+#endif
+#endif
+
+#if defined(F90MOD2CCONV3) /*E.g. MIPSPro Compilers */
+#if defined(NO_APPEND_FORTRAN)
+#define F_MODFUNCNAME(m,f) f ## .in. ## m
+#else
+#define F_MODFUNCNAME(m,f) f ## .in. ## m ## _
+#endif
+#endif
+/*
+#if defined(UPPERCASE_FORTRAN)
+#define F_MODFUNC(m,M,f,F) F_MODFUNCNAME(M,F)
+#else
+#define F_MODFUNC(m,M,f,F) F_MODFUNCNAME(m,f)
+#endif
+*/
+
+#define F_MODFUNC(m,f) (*(f2pymodstruct##m##.##f))
+"""
+cppmacros['SWAPUNSAFE'] = """\
+#define SWAP(a,b) (size_t)(a) = ((size_t)(a) ^ (size_t)(b));\\
+ (size_t)(b) = ((size_t)(a) ^ (size_t)(b));\\
+ (size_t)(a) = ((size_t)(a) ^ (size_t)(b))
+"""
+cppmacros['SWAP'] = """\
+#define SWAP(a,b,t) {\\
+ t *c;\\
+ c = a;\\
+ a = b;\\
+ b = c;}
+"""
+# cppmacros['ISCONTIGUOUS']='#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) &
+# NPY_ARRAY_C_CONTIGUOUS)'
+cppmacros['PRINTPYOBJERR'] = """\
+#define PRINTPYOBJERR(obj)\\
+ fprintf(stderr,\"#modulename#.error is related to \");\\
+ PyObject_Print((PyObject *)obj,stderr,Py_PRINT_RAW);\\
+ fprintf(stderr,\"\\n\");
+"""
+cppmacros['MINMAX'] = """\
+#ifndef max
+#define max(a,b) ((a > b) ? (a) : (b))
+#endif
+#ifndef min
+#define min(a,b) ((a < b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a > b) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a,b) ((a < b) ? (a) : (b))
+#endif
+"""
+cppmacros['len..'] = """\
+/* See fortranobject.h for definitions. The macros here are provided for BC. */
+#define rank f2py_rank
+#define shape f2py_shape
+#define fshape f2py_shape
+#define len f2py_len
+#define flen f2py_flen
+#define slen f2py_slen
+#define size f2py_size
+"""
+cppmacros[
+ 'pyobj_from_char1'] = '#define pyobj_from_char1(v) (PyLong_FromLong(v))'
+cppmacros[
+ 'pyobj_from_short1'] = '#define pyobj_from_short1(v) (PyLong_FromLong(v))'
+needs['pyobj_from_int1'] = ['signed_char']
+cppmacros['pyobj_from_int1'] = '#define pyobj_from_int1(v) (PyLong_FromLong(v))'
+cppmacros[
+ 'pyobj_from_long1'] = '#define pyobj_from_long1(v) (PyLong_FromLong(v))'
+needs['pyobj_from_long_long1'] = ['long_long']
+cppmacros['pyobj_from_long_long1'] = """\
+#ifdef HAVE_LONG_LONG
+#define pyobj_from_long_long1(v) (PyLong_FromLongLong(v))
+#else
+#warning HAVE_LONG_LONG is not available. Redefining pyobj_from_long_long.
+#define pyobj_from_long_long1(v) (PyLong_FromLong(v))
+#endif
+"""
+needs['pyobj_from_long_double1'] = ['long_double']
+cppmacros[
+ 'pyobj_from_long_double1'] = '#define pyobj_from_long_double1(v) (PyFloat_FromDouble(v))'
+cppmacros[
+ 'pyobj_from_double1'] = '#define pyobj_from_double1(v) (PyFloat_FromDouble(v))'
+cppmacros[
+ 'pyobj_from_float1'] = '#define pyobj_from_float1(v) (PyFloat_FromDouble(v))'
+needs['pyobj_from_complex_long_double1'] = ['complex_long_double']
+cppmacros[
+ 'pyobj_from_complex_long_double1'] = '#define pyobj_from_complex_long_double1(v) (PyComplex_FromDoubles(v.r,v.i))'
+needs['pyobj_from_complex_double1'] = ['complex_double']
+cppmacros[
+ 'pyobj_from_complex_double1'] = '#define pyobj_from_complex_double1(v) (PyComplex_FromDoubles(v.r,v.i))'
+needs['pyobj_from_complex_float1'] = ['complex_float']
+cppmacros[
+ 'pyobj_from_complex_float1'] = '#define pyobj_from_complex_float1(v) (PyComplex_FromDoubles(v.r,v.i))'
+needs['pyobj_from_string1'] = ['string']
+cppmacros[
+ 'pyobj_from_string1'] = '#define pyobj_from_string1(v) (PyUnicode_FromString((char *)v))'
+needs['pyobj_from_string1size'] = ['string']
+cppmacros[
+ 'pyobj_from_string1size'] = '#define pyobj_from_string1size(v,len) (PyUnicode_FromStringAndSize((char *)v, len))'
+needs['TRYPYARRAYTEMPLATE'] = ['PRINTPYOBJERR']
+cppmacros['TRYPYARRAYTEMPLATE'] = """\
+/* New SciPy */
+#define TRYPYARRAYTEMPLATECHAR case NPY_STRING: *(char *)(PyArray_DATA(arr))=*v; break;
+#define TRYPYARRAYTEMPLATELONG case NPY_LONG: *(long *)(PyArray_DATA(arr))=*v; break;
+#define TRYPYARRAYTEMPLATEOBJECT case NPY_OBJECT: PyArray_SETITEM(arr,PyArray_DATA(arr),pyobj_from_ ## ctype ## 1(*v)); break;
+
+#define TRYPYARRAYTEMPLATE(ctype,typecode) \\
+ PyArrayObject *arr = NULL;\\
+ if (!obj) return -2;\\
+ if (!PyArray_Check(obj)) return -1;\\
+ if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\
+ if (PyArray_DESCR(arr)->type==typecode) {*(ctype *)(PyArray_DATA(arr))=*v; return 1;}\\
+ switch (PyArray_TYPE(arr)) {\\
+ case NPY_DOUBLE: *(npy_double *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_INT: *(npy_int *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_LONG: *(npy_long *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_FLOAT: *(npy_float *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_CDOUBLE: *(npy_double *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_CFLOAT: *(npy_float *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_BOOL: *(npy_bool *)(PyArray_DATA(arr))=(*v!=0); break;\\
+ case NPY_UBYTE: *(npy_ubyte *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_BYTE: *(npy_byte *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_SHORT: *(npy_short *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_USHORT: *(npy_ushort *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_UINT: *(npy_uint *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_ULONG: *(npy_ulong *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_LONGLONG: *(npy_longlong *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_ULONGLONG: *(npy_ulonglong *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_LONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_CLONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=*v; break;\\
+ case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_ ## ctype ## 1(*v)); break;\\
+ default: return -2;\\
+ };\\
+ return 1
+"""
+
+needs['TRYCOMPLEXPYARRAYTEMPLATE'] = ['PRINTPYOBJERR']
+cppmacros['TRYCOMPLEXPYARRAYTEMPLATE'] = """\
+#define TRYCOMPLEXPYARRAYTEMPLATEOBJECT case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_complex_ ## ctype ## 1((*v))); break;
+#define TRYCOMPLEXPYARRAYTEMPLATE(ctype,typecode)\\
+ PyArrayObject *arr = NULL;\\
+ if (!obj) return -2;\\
+ if (!PyArray_Check(obj)) return -1;\\
+ if (!(arr=(PyArrayObject *)obj)) {fprintf(stderr,\"TRYCOMPLEXPYARRAYTEMPLATE:\");PRINTPYOBJERR(obj);return 0;}\\
+ if (PyArray_DESCR(arr)->type==typecode) {\\
+ *(ctype *)(PyArray_DATA(arr))=(*v).r;\\
+ *(ctype *)(PyArray_DATA(arr)+sizeof(ctype))=(*v).i;\\
+ return 1;\\
+ }\\
+ switch (PyArray_TYPE(arr)) {\\
+ case NPY_CDOUBLE: *(npy_double *)(PyArray_DATA(arr))=(*v).r;\\
+ *(npy_double *)(PyArray_DATA(arr)+sizeof(npy_double))=(*v).i;\\
+ break;\\
+ case NPY_CFLOAT: *(npy_float *)(PyArray_DATA(arr))=(*v).r;\\
+ *(npy_float *)(PyArray_DATA(arr)+sizeof(npy_float))=(*v).i;\\
+ break;\\
+ case NPY_DOUBLE: *(npy_double *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_LONG: *(npy_long *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_FLOAT: *(npy_float *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_INT: *(npy_int *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_SHORT: *(npy_short *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_UBYTE: *(npy_ubyte *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_BYTE: *(npy_byte *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_BOOL: *(npy_bool *)(PyArray_DATA(arr))=((*v).r!=0 && (*v).i!=0); break;\\
+ case NPY_USHORT: *(npy_ushort *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_UINT: *(npy_uint *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_ULONG: *(npy_ulong *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_LONGLONG: *(npy_longlong *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_ULONGLONG: *(npy_ulonglong *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_LONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r; break;\\
+ case NPY_CLONGDOUBLE: *(npy_longdouble *)(PyArray_DATA(arr))=(*v).r;\\
+ *(npy_longdouble *)(PyArray_DATA(arr)+sizeof(npy_longdouble))=(*v).i;\\
+ break;\\
+ case NPY_OBJECT: PyArray_SETITEM(arr, PyArray_DATA(arr), pyobj_from_complex_ ## ctype ## 1((*v))); break;\\
+ default: return -2;\\
+ };\\
+ return -1;
+"""
+# cppmacros['NUMFROMARROBJ']="""\
+# define NUMFROMARROBJ(typenum,ctype) \\
+# if (PyArray_Check(obj)) arr = (PyArrayObject *)obj;\\
+# else arr = (PyArrayObject *)PyArray_ContiguousFromObject(obj,typenum,0,0);\\
+# if (arr) {\\
+# if (PyArray_TYPE(arr)==NPY_OBJECT) {\\
+# if (!ctype ## _from_pyobj(v,(PyArray_DESCR(arr)->getitem)(PyArray_DATA(arr)),\"\"))\\
+# goto capi_fail;\\
+# } else {\\
+# (PyArray_DESCR(arr)->cast[typenum])(PyArray_DATA(arr),1,(char*)v,1,1);\\
+# }\\
+# if ((PyObject *)arr != obj) { Py_DECREF(arr); }\\
+# return 1;\\
+# }
+# """
+# XXX: Note that CNUMFROMARROBJ is identical with NUMFROMARROBJ
+# cppmacros['CNUMFROMARROBJ']="""\
+# define CNUMFROMARROBJ(typenum,ctype) \\
+# if (PyArray_Check(obj)) arr = (PyArrayObject *)obj;\\
+# else arr = (PyArrayObject *)PyArray_ContiguousFromObject(obj,typenum,0,0);\\
+# if (arr) {\\
+# if (PyArray_TYPE(arr)==NPY_OBJECT) {\\
+# if (!ctype ## _from_pyobj(v,(PyArray_DESCR(arr)->getitem)(PyArray_DATA(arr)),\"\"))\\
+# goto capi_fail;\\
+# } else {\\
+# (PyArray_DESCR(arr)->cast[typenum])((void *)(PyArray_DATA(arr)),1,(void *)(v),1,1);\\
+# }\\
+# if ((PyObject *)arr != obj) { Py_DECREF(arr); }\\
+# return 1;\\
+# }
+# """
+
+
+needs['GETSTRFROMPYTUPLE'] = ['STRINGCOPYN', 'PRINTPYOBJERR']
+cppmacros['GETSTRFROMPYTUPLE'] = """\
+#define GETSTRFROMPYTUPLE(tuple,index,str,len) {\\
+ PyObject *rv_cb_str = PyTuple_GetItem((tuple),(index));\\
+ if (rv_cb_str == NULL)\\
+ goto capi_fail;\\
+ if (PyBytes_Check(rv_cb_str)) {\\
+ str[len-1]='\\0';\\
+ STRINGCOPYN((str),PyBytes_AS_STRING((PyBytesObject*)rv_cb_str),(len));\\
+ } else {\\
+ PRINTPYOBJERR(rv_cb_str);\\
+ PyErr_SetString(#modulename#_error,\"string object expected\");\\
+ goto capi_fail;\\
+ }\\
+ }
+"""
+cppmacros['GETSCALARFROMPYTUPLE'] = """\
+#define GETSCALARFROMPYTUPLE(tuple,index,var,ctype,mess) {\\
+ if ((capi_tmp = PyTuple_GetItem((tuple),(index)))==NULL) goto capi_fail;\\
+ if (!(ctype ## _from_pyobj((var),capi_tmp,mess)))\\
+ goto capi_fail;\\
+ }
+"""
+
+cppmacros['FAILNULL'] = """\\
+#define FAILNULL(p) do { \\
+ if ((p) == NULL) { \\
+ PyErr_SetString(PyExc_MemoryError, "NULL pointer found"); \\
+ goto capi_fail; \\
+ } \\
+} while (0)
+"""
+needs['MEMCOPY'] = ['string.h', 'FAILNULL']
+cppmacros['MEMCOPY'] = """\
+#define MEMCOPY(to,from,n)\\
+ do { FAILNULL(to); FAILNULL(from); (void)memcpy(to,from,n); } while (0)
+"""
+cppmacros['STRINGMALLOC'] = """\
+#define STRINGMALLOC(str,len)\\
+ if ((str = (string)malloc(len+1)) == NULL) {\\
+ PyErr_SetString(PyExc_MemoryError, \"out of memory\");\\
+ goto capi_fail;\\
+ } else {\\
+ (str)[len] = '\\0';\\
+ }
+"""
+cppmacros['STRINGFREE'] = """\
+#define STRINGFREE(str) do {if (!(str == NULL)) free(str);} while (0)
+"""
+needs['STRINGPADN'] = ['string.h']
+cppmacros['STRINGPADN'] = """\
+/*
+STRINGPADN replaces null values with padding values from the right.
+
+`to` must have size of at least N bytes.
+
+If the `to[N-1]` has null value, then replace it and all the
+preceding, nulls with the given padding.
+
+STRINGPADN(to, N, PADDING, NULLVALUE) is an inverse operation.
+*/
+#define STRINGPADN(to, N, NULLVALUE, PADDING) \\
+ do { \\
+ int _m = (N); \\
+ char *_to = (to); \\
+ for (_m -= 1; _m >= 0 && _to[_m] == NULLVALUE; _m--) { \\
+ _to[_m] = PADDING; \\
+ } \\
+ } while (0)
+"""
+needs['STRINGCOPYN'] = ['string.h', 'FAILNULL']
+cppmacros['STRINGCOPYN'] = """\
+/*
+STRINGCOPYN copies N bytes.
+
+`to` and `from` buffers must have sizes of at least N bytes.
+*/
+#define STRINGCOPYN(to,from,N) \\
+ do { \\
+ int _m = (N); \\
+ char *_to = (to); \\
+ char *_from = (from); \\
+ FAILNULL(_to); FAILNULL(_from); \\
+ (void)strncpy(_to, _from, _m); \\
+ } while (0)
+"""
+needs['STRINGCOPY'] = ['string.h', 'FAILNULL']
+cppmacros['STRINGCOPY'] = """\
+#define STRINGCOPY(to,from)\\
+ do { FAILNULL(to); FAILNULL(from); (void)strcpy(to,from); } while (0)
+"""
+cppmacros['CHECKGENERIC'] = """\
+#define CHECKGENERIC(check,tcheck,name) \\
+ if (!(check)) {\\
+ PyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\
+ /*goto capi_fail;*/\\
+ } else """
+cppmacros['CHECKARRAY'] = """\
+#define CHECKARRAY(check,tcheck,name) \\
+ if (!(check)) {\\
+ PyErr_SetString(#modulename#_error,\"(\"tcheck\") failed for \"name);\\
+ /*goto capi_fail;*/\\
+ } else """
+cppmacros['CHECKSTRING'] = """\
+#define CHECKSTRING(check,tcheck,name,show,var)\\
+ if (!(check)) {\\
+ char errstring[256];\\
+ sprintf(errstring, \"%s: \"show, \"(\"tcheck\") failed for \"name, slen(var), var);\\
+ PyErr_SetString(#modulename#_error, errstring);\\
+ /*goto capi_fail;*/\\
+ } else """
+cppmacros['CHECKSCALAR'] = """\
+#define CHECKSCALAR(check,tcheck,name,show,var)\\
+ if (!(check)) {\\
+ char errstring[256];\\
+ sprintf(errstring, \"%s: \"show, \"(\"tcheck\") failed for \"name, var);\\
+ PyErr_SetString(#modulename#_error,errstring);\\
+ /*goto capi_fail;*/\\
+ } else """
+# cppmacros['CHECKDIMS']="""\
+# define CHECKDIMS(dims,rank) \\
+# for (int i=0;i<(rank);i++)\\
+# if (dims[i]<0) {\\
+# fprintf(stderr,\"Unspecified array argument requires a complete dimension specification.\\n\");\\
+# goto capi_fail;\\
+# }
+# """
+cppmacros[
+ 'ARRSIZE'] = '#define ARRSIZE(dims,rank) (_PyArray_multiply_list(dims,rank))'
+cppmacros['OLDPYNUM'] = """\
+#ifdef OLDPYNUM
+#error You need to install NumPy version 0.13 or higher. See https://scipy.org/install.html
+#endif
+"""
+cppmacros["F2PY_THREAD_LOCAL_DECL"] = """\
+#ifndef F2PY_THREAD_LOCAL_DECL
+#if defined(_MSC_VER)
+#define F2PY_THREAD_LOCAL_DECL __declspec(thread)
+#elif defined(NPY_OS_MINGW)
+#define F2PY_THREAD_LOCAL_DECL __thread
+#elif defined(__STDC_VERSION__) \\
+ && (__STDC_VERSION__ >= 201112L) \\
+ && !defined(__STDC_NO_THREADS__) \\
+ && (!defined(__GLIBC__) || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 12)) \\
+ && !defined(NPY_OS_OPENBSD) && !defined(NPY_OS_HAIKU)
+/* __STDC_NO_THREADS__ was first defined in a maintenance release of glibc 2.12,
+ see https://lists.gnu.org/archive/html/commit-hurd/2012-07/msg00180.html,
+ so `!defined(__STDC_NO_THREADS__)` may give false positive for the existence
+ of `threads.h` when using an older release of glibc 2.12
+ See gh-19437 for details on OpenBSD */
+#include <threads.h>
+#define F2PY_THREAD_LOCAL_DECL thread_local
+#elif defined(__GNUC__) \\
+ && (__GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 4)))
+#define F2PY_THREAD_LOCAL_DECL __thread
+#endif
+#endif
+"""
+################# C functions ###############
+
+cfuncs['calcarrindex'] = """\
+static int calcarrindex(int *i,PyArrayObject *arr) {
+ int k,ii = i[0];
+ for (k=1; k < PyArray_NDIM(arr); k++)
+ ii += (ii*(PyArray_DIM(arr,k) - 1)+i[k]); /* assuming contiguous arr */
+ return ii;
+}"""
+cfuncs['calcarrindextr'] = """\
+static int calcarrindextr(int *i,PyArrayObject *arr) {
+ int k,ii = i[PyArray_NDIM(arr)-1];
+ for (k=1; k < PyArray_NDIM(arr); k++)
+ ii += (ii*(PyArray_DIM(arr,PyArray_NDIM(arr)-k-1) - 1)+i[PyArray_NDIM(arr)-k-1]); /* assuming contiguous arr */
+ return ii;
+}"""
+cfuncs['forcomb'] = """\
+static struct { int nd;npy_intp *d;int *i,*i_tr,tr; } forcombcache;
+static int initforcomb(npy_intp *dims,int nd,int tr) {
+ int k;
+ if (dims==NULL) return 0;
+ if (nd<0) return 0;
+ forcombcache.nd = nd;
+ forcombcache.d = dims;
+ forcombcache.tr = tr;
+ if ((forcombcache.i = (int *)malloc(sizeof(int)*nd))==NULL) return 0;
+ if ((forcombcache.i_tr = (int *)malloc(sizeof(int)*nd))==NULL) return 0;
+ for (k=1;k<nd;k++) {
+ forcombcache.i[k] = forcombcache.i_tr[nd-k-1] = 0;
+ }
+ forcombcache.i[0] = forcombcache.i_tr[nd-1] = -1;
+ return 1;
+}
+static int *nextforcomb(void) {
+ int j,*i,*i_tr,k;
+ int nd=forcombcache.nd;
+ if ((i=forcombcache.i) == NULL) return NULL;
+ if ((i_tr=forcombcache.i_tr) == NULL) return NULL;
+ if (forcombcache.d == NULL) return NULL;
+ i[0]++;
+ if (i[0]==forcombcache.d[0]) {
+ j=1;
+ while ((j<nd) && (i[j]==forcombcache.d[j]-1)) j++;
+ if (j==nd) {
+ free(i);
+ free(i_tr);
+ return NULL;
+ }
+ for (k=0;k<j;k++) i[k] = i_tr[nd-k-1] = 0;
+ i[j]++;
+ i_tr[nd-j-1]++;
+ } else
+ i_tr[nd-1]++;
+ if (forcombcache.tr) return i_tr;
+ return i;
+}"""
+needs['try_pyarr_from_string'] = ['STRINGCOPYN', 'PRINTPYOBJERR', 'string']
+cfuncs['try_pyarr_from_string'] = """\
+/*
+ try_pyarr_from_string copies str[:len(obj)] to the data of an `ndarray`.
+
+ If obj is an `ndarray`, it is assumed to be contiguous.
+
+ If the specified len==-1, str must be null-terminated.
+*/
+static int try_pyarr_from_string(PyObject *obj,
+ const string str, const int len) {
+#ifdef DEBUGCFUNCS
+fprintf(stderr, "try_pyarr_from_string(str='%s', len=%d, obj=%p)\\n",
+ (char*)str,len, obj);
+#endif
+ if (PyArray_Check(obj)) {
+ PyArrayObject *arr = (PyArrayObject *)obj;
+ assert(ISCONTIGUOUS(arr));
+ string buf = PyArray_DATA(arr);
+ npy_intp n = len;
+ if (n == -1) {
+ /* Assuming null-terminated str. */
+ n = strlen(str);
+ }
+ if (n > PyArray_NBYTES(arr)) {
+ n = PyArray_NBYTES(arr);
+ }
+ STRINGCOPYN(buf, str, n);
+ return 1;
+ }
+capi_fail:
+ PRINTPYOBJERR(obj);
+ PyErr_SetString(#modulename#_error, \"try_pyarr_from_string failed\");
+ return 0;
+}
+"""
+needs['string_from_pyobj'] = ['string', 'STRINGMALLOC', 'STRINGCOPYN']
+cfuncs['string_from_pyobj'] = """\
+/*
+ Create a new string buffer `str` of at most length `len` from a
+ Python string-like object `obj`.
+
+ The string buffer has given size (len) or the size of inistr when len==-1.
+
+ The string buffer is padded with blanks: in Fortran, trailing blanks
+ are insignificant contrary to C nulls.
+ */
+static int
+string_from_pyobj(string *str, int *len, const string inistr, PyObject *obj,
+ const char *errmess)
+{
+ PyObject *tmp = NULL;
+ string buf = NULL;
+ npy_intp n = -1;
+#ifdef DEBUGCFUNCS
+fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",
+ (char*)str, *len, (char *)inistr, obj);
+#endif
+ if (obj == Py_None) {
+ n = strlen(inistr);
+ buf = inistr;
+ }
+ else if (PyArray_Check(obj)) {
+ PyArrayObject *arr = (PyArrayObject *)obj;
+ if (!ISCONTIGUOUS(arr)) {
+ PyErr_SetString(PyExc_ValueError,
+ \"array object is non-contiguous.\");
+ goto capi_fail;
+ }
+ n = PyArray_NBYTES(arr);
+ buf = PyArray_DATA(arr);
+ n = strnlen(buf, n);
+ }
+ else {
+ if (PyBytes_Check(obj)) {
+ tmp = obj;
+ Py_INCREF(tmp);
+ }
+ else if (PyUnicode_Check(obj)) {
+ tmp = PyUnicode_AsASCIIString(obj);
+ }
+ else {
+ PyObject *tmp2;
+ tmp2 = PyObject_Str(obj);
+ if (tmp2) {
+ tmp = PyUnicode_AsASCIIString(tmp2);
+ Py_DECREF(tmp2);
+ }
+ else {
+ tmp = NULL;
+ }
+ }
+ if (tmp == NULL) goto capi_fail;
+ n = PyBytes_GET_SIZE(tmp);
+ buf = PyBytes_AS_STRING(tmp);
+ }
+ if (*len == -1) {
+ /* TODO: change the type of `len` so that we can remove this */
+ if (n > NPY_MAX_INT) {
+ PyErr_SetString(PyExc_OverflowError,
+ "object too large for a 32-bit int");
+ goto capi_fail;
+ }
+ *len = n;
+ }
+ else if (*len < n) {
+ /* discard the last (len-n) bytes of input buf */
+ n = *len;
+ }
+ if (n < 0 || *len < 0 || buf == NULL) {
+ goto capi_fail;
+ }
+ STRINGMALLOC(*str, *len); // *str is allocated with size (*len + 1)
+ if (n < *len) {
+ /*
+ Pad fixed-width string with nulls. The caller will replace
+ nulls with blanks when the corresponding argument is not
+ intent(c).
+ */
+ memset(*str + n, '\\0', *len - n);
+ }
+ STRINGCOPYN(*str, buf, n);
+ Py_XDECREF(tmp);
+ return 1;
+capi_fail:
+ Py_XDECREF(tmp);
+ {
+ PyObject* err = PyErr_Occurred();
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err, errmess);
+ }
+ return 0;
+}
+"""
+
+cfuncs['character_from_pyobj'] = """\
+static int
+character_from_pyobj(character* v, PyObject *obj, const char *errmess) {
+ if (PyBytes_Check(obj)) {
+ /* empty bytes has trailing null, so dereferencing is always safe */
+ *v = PyBytes_AS_STRING(obj)[0];
+ return 1;
+ } else if (PyUnicode_Check(obj)) {
+ PyObject* tmp = PyUnicode_AsASCIIString(obj);
+ if (tmp != NULL) {
+ *v = PyBytes_AS_STRING(tmp)[0];
+ Py_DECREF(tmp);
+ return 1;
+ }
+ } else if (PyArray_Check(obj)) {
+ PyArrayObject* arr = (PyArrayObject*)obj;
+ if (F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr)) {
+ *v = PyArray_BYTES(arr)[0];
+ return 1;
+ } else if (F2PY_IS_UNICODE_ARRAY(arr)) {
+ // TODO: update when numpy will support 1-byte and
+ // 2-byte unicode dtypes
+ PyObject* tmp = PyUnicode_FromKindAndData(
+ PyUnicode_4BYTE_KIND,
+ PyArray_BYTES(arr),
+ (PyArray_NBYTES(arr)>0?1:0));
+ if (tmp != NULL) {
+ if (character_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+ Py_DECREF(tmp);
+ }
+ }
+ } else if (PySequence_Check(obj)) {
+ PyObject* tmp = PySequence_GetItem(obj,0);
+ if (tmp != NULL) {
+ if (character_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+ Py_DECREF(tmp);
+ }
+ }
+ {
+ char mess[F2PY_MESSAGE_BUFFER_SIZE];
+ strcpy(mess, errmess);
+ PyObject* err = PyErr_Occurred();
+ if (err == NULL) {
+ err = PyExc_TypeError;
+ }
+ sprintf(mess + strlen(mess),
+ " -- expected str|bytes|sequence-of-str-or-bytes, got ");
+ f2py_describe(obj, mess + strlen(mess));
+ PyErr_SetString(err, mess);
+ }
+ return 0;
+}
+"""
+
+needs['char_from_pyobj'] = ['int_from_pyobj']
+cfuncs['char_from_pyobj'] = """\
+static int
+char_from_pyobj(char* v, PyObject *obj, const char *errmess) {
+ int i = 0;
+ if (int_from_pyobj(&i, obj, errmess)) {
+ *v = (char)i;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+needs['signed_char_from_pyobj'] = ['int_from_pyobj', 'signed_char']
+cfuncs['signed_char_from_pyobj'] = """\
+static int
+signed_char_from_pyobj(signed_char* v, PyObject *obj, const char *errmess) {
+ int i = 0;
+ if (int_from_pyobj(&i, obj, errmess)) {
+ *v = (signed_char)i;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+needs['short_from_pyobj'] = ['int_from_pyobj']
+cfuncs['short_from_pyobj'] = """\
+static int
+short_from_pyobj(short* v, PyObject *obj, const char *errmess) {
+ int i = 0;
+ if (int_from_pyobj(&i, obj, errmess)) {
+ *v = (short)i;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+cfuncs['int_from_pyobj'] = """\
+static int
+int_from_pyobj(int* v, PyObject *obj, const char *errmess)
+{
+ PyObject* tmp = NULL;
+
+ if (PyLong_Check(obj)) {
+ *v = Npy__PyLong_AsInt(obj);
+ return !(*v == -1 && PyErr_Occurred());
+ }
+
+ tmp = PyNumber_Long(obj);
+ if (tmp) {
+ *v = Npy__PyLong_AsInt(tmp);
+ Py_DECREF(tmp);
+ return !(*v == -1 && PyErr_Occurred());
+ }
+
+ if (PyComplex_Check(obj)) {
+ PyErr_Clear();
+ tmp = PyObject_GetAttrString(obj,\"real\");
+ }
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) {
+ /*pass*/;
+ }
+ else if (PySequence_Check(obj)) {
+ PyErr_Clear();
+ tmp = PySequence_GetItem(obj, 0);
+ }
+
+ if (tmp) {
+ if (int_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+ Py_DECREF(tmp);
+ }
+
+ {
+ PyObject* err = PyErr_Occurred();
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err, errmess);
+ }
+ return 0;
+}
+"""
+
+
+cfuncs['long_from_pyobj'] = """\
+static int
+long_from_pyobj(long* v, PyObject *obj, const char *errmess) {
+ PyObject* tmp = NULL;
+
+ if (PyLong_Check(obj)) {
+ *v = PyLong_AsLong(obj);
+ return !(*v == -1 && PyErr_Occurred());
+ }
+
+ tmp = PyNumber_Long(obj);
+ if (tmp) {
+ *v = PyLong_AsLong(tmp);
+ Py_DECREF(tmp);
+ return !(*v == -1 && PyErr_Occurred());
+ }
+
+ if (PyComplex_Check(obj)) {
+ PyErr_Clear();
+ tmp = PyObject_GetAttrString(obj,\"real\");
+ }
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) {
+ /*pass*/;
+ }
+ else if (PySequence_Check(obj)) {
+ PyErr_Clear();
+ tmp = PySequence_GetItem(obj, 0);
+ }
+
+ if (tmp) {
+ if (long_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+ Py_DECREF(tmp);
+ }
+ {
+ PyObject* err = PyErr_Occurred();
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err, errmess);
+ }
+ return 0;
+}
+"""
+
+
+needs['long_long_from_pyobj'] = ['long_long']
+cfuncs['long_long_from_pyobj'] = """\
+static int
+long_long_from_pyobj(long_long* v, PyObject *obj, const char *errmess)
+{
+ PyObject* tmp = NULL;
+
+ if (PyLong_Check(obj)) {
+ *v = PyLong_AsLongLong(obj);
+ return !(*v == -1 && PyErr_Occurred());
+ }
+
+ tmp = PyNumber_Long(obj);
+ if (tmp) {
+ *v = PyLong_AsLongLong(tmp);
+ Py_DECREF(tmp);
+ return !(*v == -1 && PyErr_Occurred());
+ }
+
+ if (PyComplex_Check(obj)) {
+ PyErr_Clear();
+ tmp = PyObject_GetAttrString(obj,\"real\");
+ }
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) {
+ /*pass*/;
+ }
+ else if (PySequence_Check(obj)) {
+ PyErr_Clear();
+ tmp = PySequence_GetItem(obj, 0);
+ }
+
+ if (tmp) {
+ if (long_long_from_pyobj(v, tmp, errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+ Py_DECREF(tmp);
+ }
+ {
+ PyObject* err = PyErr_Occurred();
+ if (err == NULL) {
+ err = #modulename#_error;
+ }
+ PyErr_SetString(err,errmess);
+ }
+ return 0;
+}
+"""
+
+
+needs['long_double_from_pyobj'] = ['double_from_pyobj', 'long_double']
+cfuncs['long_double_from_pyobj'] = """\
+static int
+long_double_from_pyobj(long_double* v, PyObject *obj, const char *errmess)
+{
+ double d=0;
+ if (PyArray_CheckScalar(obj)){
+ if PyArray_IsScalar(obj, LongDouble) {
+ PyArray_ScalarAsCtype(obj, v);
+ return 1;
+ }
+ else if (PyArray_Check(obj) && PyArray_TYPE(obj) == NPY_LONGDOUBLE) {
+ (*v) = *((npy_longdouble *)PyArray_DATA(obj));
+ return 1;
+ }
+ }
+ if (double_from_pyobj(&d, obj, errmess)) {
+ *v = (long_double)d;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+cfuncs['double_from_pyobj'] = """\
+static int
+double_from_pyobj(double* v, PyObject *obj, const char *errmess)
+{
+ PyObject* tmp = NULL;
+ if (PyFloat_Check(obj)) {
+ *v = PyFloat_AsDouble(obj);
+ return !(*v == -1.0 && PyErr_Occurred());
+ }
+
+ tmp = PyNumber_Float(obj);
+ if (tmp) {
+ *v = PyFloat_AsDouble(tmp);
+ Py_DECREF(tmp);
+ return !(*v == -1.0 && PyErr_Occurred());
+ }
+
+ if (PyComplex_Check(obj)) {
+ PyErr_Clear();
+ tmp = PyObject_GetAttrString(obj,\"real\");
+ }
+ else if (PyBytes_Check(obj) || PyUnicode_Check(obj)) {
+ /*pass*/;
+ }
+ else if (PySequence_Check(obj)) {
+ PyErr_Clear();
+ tmp = PySequence_GetItem(obj, 0);
+ }
+
+ if (tmp) {
+ if (double_from_pyobj(v,tmp,errmess)) {Py_DECREF(tmp); return 1;}
+ Py_DECREF(tmp);
+ }
+ {
+ PyObject* err = PyErr_Occurred();
+ if (err==NULL) err = #modulename#_error;
+ PyErr_SetString(err,errmess);
+ }
+ return 0;
+}
+"""
+
+
+needs['float_from_pyobj'] = ['double_from_pyobj']
+cfuncs['float_from_pyobj'] = """\
+static int
+float_from_pyobj(float* v, PyObject *obj, const char *errmess)
+{
+ double d=0.0;
+ if (double_from_pyobj(&d,obj,errmess)) {
+ *v = (float)d;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+needs['complex_long_double_from_pyobj'] = ['complex_long_double', 'long_double',
+ 'complex_double_from_pyobj']
+cfuncs['complex_long_double_from_pyobj'] = """\
+static int
+complex_long_double_from_pyobj(complex_long_double* v, PyObject *obj, const char *errmess)
+{
+ complex_double cd = {0.0,0.0};
+ if (PyArray_CheckScalar(obj)){
+ if PyArray_IsScalar(obj, CLongDouble) {
+ PyArray_ScalarAsCtype(obj, v);
+ return 1;
+ }
+ else if (PyArray_Check(obj) && PyArray_TYPE(obj)==NPY_CLONGDOUBLE) {
+ (*v).r = ((npy_clongdouble *)PyArray_DATA(obj))->real;
+ (*v).i = ((npy_clongdouble *)PyArray_DATA(obj))->imag;
+ return 1;
+ }
+ }
+ if (complex_double_from_pyobj(&cd,obj,errmess)) {
+ (*v).r = (long_double)cd.r;
+ (*v).i = (long_double)cd.i;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+needs['complex_double_from_pyobj'] = ['complex_double']
+cfuncs['complex_double_from_pyobj'] = """\
+static int
+complex_double_from_pyobj(complex_double* v, PyObject *obj, const char *errmess) {
+ Py_complex c;
+ if (PyComplex_Check(obj)) {
+ c = PyComplex_AsCComplex(obj);
+ (*v).r = c.real;
+ (*v).i = c.imag;
+ return 1;
+ }
+ if (PyArray_IsScalar(obj, ComplexFloating)) {
+ if (PyArray_IsScalar(obj, CFloat)) {
+ npy_cfloat new;
+ PyArray_ScalarAsCtype(obj, &new);
+ (*v).r = (double)new.real;
+ (*v).i = (double)new.imag;
+ }
+ else if (PyArray_IsScalar(obj, CLongDouble)) {
+ npy_clongdouble new;
+ PyArray_ScalarAsCtype(obj, &new);
+ (*v).r = (double)new.real;
+ (*v).i = (double)new.imag;
+ }
+ else { /* if (PyArray_IsScalar(obj, CDouble)) */
+ PyArray_ScalarAsCtype(obj, v);
+ }
+ return 1;
+ }
+ if (PyArray_CheckScalar(obj)) { /* 0-dim array or still array scalar */
+ PyArrayObject *arr;
+ if (PyArray_Check(obj)) {
+ arr = (PyArrayObject *)PyArray_Cast((PyArrayObject *)obj, NPY_CDOUBLE);
+ }
+ else {
+ arr = (PyArrayObject *)PyArray_FromScalar(obj, PyArray_DescrFromType(NPY_CDOUBLE));
+ }
+ if (arr == NULL) {
+ return 0;
+ }
+ (*v).r = ((npy_cdouble *)PyArray_DATA(arr))->real;
+ (*v).i = ((npy_cdouble *)PyArray_DATA(arr))->imag;
+ Py_DECREF(arr);
+ return 1;
+ }
+ /* Python does not provide PyNumber_Complex function :-( */
+ (*v).i = 0.0;
+ if (PyFloat_Check(obj)) {
+ (*v).r = PyFloat_AsDouble(obj);
+ return !((*v).r == -1.0 && PyErr_Occurred());
+ }
+ if (PyLong_Check(obj)) {
+ (*v).r = PyLong_AsDouble(obj);
+ return !((*v).r == -1.0 && PyErr_Occurred());
+ }
+ if (PySequence_Check(obj) && !(PyBytes_Check(obj) || PyUnicode_Check(obj))) {
+ PyObject *tmp = PySequence_GetItem(obj,0);
+ if (tmp) {
+ if (complex_double_from_pyobj(v,tmp,errmess)) {
+ Py_DECREF(tmp);
+ return 1;
+ }
+ Py_DECREF(tmp);
+ }
+ }
+ {
+ PyObject* err = PyErr_Occurred();
+ if (err==NULL)
+ err = PyExc_TypeError;
+ PyErr_SetString(err,errmess);
+ }
+ return 0;
+}
+"""
+
+
+needs['complex_float_from_pyobj'] = [
+ 'complex_float', 'complex_double_from_pyobj']
+cfuncs['complex_float_from_pyobj'] = """\
+static int
+complex_float_from_pyobj(complex_float* v,PyObject *obj,const char *errmess)
+{
+ complex_double cd={0.0,0.0};
+ if (complex_double_from_pyobj(&cd,obj,errmess)) {
+ (*v).r = (float)cd.r;
+ (*v).i = (float)cd.i;
+ return 1;
+ }
+ return 0;
+}
+"""
+
+
+cfuncs['try_pyarr_from_character'] = """\
+static int try_pyarr_from_character(PyObject* obj, character* v) {
+ PyArrayObject *arr = (PyArrayObject*)obj;
+ if (!obj) return -2;
+ if (PyArray_Check(obj)) {
+ if (F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr)) {
+ *(character *)(PyArray_DATA(arr)) = *v;
+ return 1;
+ }
+ }
+ {
+ char mess[F2PY_MESSAGE_BUFFER_SIZE];
+ PyObject* err = PyErr_Occurred();
+ if (err == NULL) {
+ err = PyExc_ValueError;
+ strcpy(mess, "try_pyarr_from_character failed"
+ " -- expected bytes array-scalar|array, got ");
+ f2py_describe(obj, mess + strlen(mess));
+ }
+ PyErr_SetString(err, mess);
+ }
+ return 0;
+}
+"""
+
+needs['try_pyarr_from_char'] = ['pyobj_from_char1', 'TRYPYARRAYTEMPLATE']
+cfuncs[
+ 'try_pyarr_from_char'] = 'static int try_pyarr_from_char(PyObject* obj,char* v) {\n TRYPYARRAYTEMPLATE(char,\'c\');\n}\n'
+needs['try_pyarr_from_signed_char'] = ['TRYPYARRAYTEMPLATE', 'unsigned_char']
+cfuncs[
+ 'try_pyarr_from_unsigned_char'] = 'static int try_pyarr_from_unsigned_char(PyObject* obj,unsigned_char* v) {\n TRYPYARRAYTEMPLATE(unsigned_char,\'b\');\n}\n'
+needs['try_pyarr_from_signed_char'] = ['TRYPYARRAYTEMPLATE', 'signed_char']
+cfuncs[
+ 'try_pyarr_from_signed_char'] = 'static int try_pyarr_from_signed_char(PyObject* obj,signed_char* v) {\n TRYPYARRAYTEMPLATE(signed_char,\'1\');\n}\n'
+needs['try_pyarr_from_short'] = ['pyobj_from_short1', 'TRYPYARRAYTEMPLATE']
+cfuncs[
+ 'try_pyarr_from_short'] = 'static int try_pyarr_from_short(PyObject* obj,short* v) {\n TRYPYARRAYTEMPLATE(short,\'s\');\n}\n'
+needs['try_pyarr_from_int'] = ['pyobj_from_int1', 'TRYPYARRAYTEMPLATE']
+cfuncs[
+ 'try_pyarr_from_int'] = 'static int try_pyarr_from_int(PyObject* obj,int* v) {\n TRYPYARRAYTEMPLATE(int,\'i\');\n}\n'
+needs['try_pyarr_from_long'] = ['pyobj_from_long1', 'TRYPYARRAYTEMPLATE']
+cfuncs[
+ 'try_pyarr_from_long'] = 'static int try_pyarr_from_long(PyObject* obj,long* v) {\n TRYPYARRAYTEMPLATE(long,\'l\');\n}\n'
+needs['try_pyarr_from_long_long'] = [
+ 'pyobj_from_long_long1', 'TRYPYARRAYTEMPLATE', 'long_long']
+cfuncs[
+ 'try_pyarr_from_long_long'] = 'static int try_pyarr_from_long_long(PyObject* obj,long_long* v) {\n TRYPYARRAYTEMPLATE(long_long,\'L\');\n}\n'
+needs['try_pyarr_from_float'] = ['pyobj_from_float1', 'TRYPYARRAYTEMPLATE']
+cfuncs[
+ 'try_pyarr_from_float'] = 'static int try_pyarr_from_float(PyObject* obj,float* v) {\n TRYPYARRAYTEMPLATE(float,\'f\');\n}\n'
+needs['try_pyarr_from_double'] = ['pyobj_from_double1', 'TRYPYARRAYTEMPLATE']
+cfuncs[
+ 'try_pyarr_from_double'] = 'static int try_pyarr_from_double(PyObject* obj,double* v) {\n TRYPYARRAYTEMPLATE(double,\'d\');\n}\n'
+needs['try_pyarr_from_complex_float'] = [
+ 'pyobj_from_complex_float1', 'TRYCOMPLEXPYARRAYTEMPLATE', 'complex_float']
+cfuncs[
+ 'try_pyarr_from_complex_float'] = 'static int try_pyarr_from_complex_float(PyObject* obj,complex_float* v) {\n TRYCOMPLEXPYARRAYTEMPLATE(float,\'F\');\n}\n'
+needs['try_pyarr_from_complex_double'] = [
+ 'pyobj_from_complex_double1', 'TRYCOMPLEXPYARRAYTEMPLATE', 'complex_double']
+cfuncs[
+ 'try_pyarr_from_complex_double'] = 'static int try_pyarr_from_complex_double(PyObject* obj,complex_double* v) {\n TRYCOMPLEXPYARRAYTEMPLATE(double,\'D\');\n}\n'
+
+
+needs['create_cb_arglist'] = ['CFUNCSMESS', 'PRINTPYOBJERR', 'MINMAX']
+# create the list of arguments to be used when calling back to python
+cfuncs['create_cb_arglist'] = """\
+static int
+create_cb_arglist(PyObject* fun, PyTupleObject* xa , const int maxnofargs,
+ const int nofoptargs, int *nofargs, PyTupleObject **args,
+ const char *errmess)
+{
+ PyObject *tmp = NULL;
+ PyObject *tmp_fun = NULL;
+ Py_ssize_t tot, opt, ext, siz, i, di = 0;
+ CFUNCSMESS(\"create_cb_arglist\\n\");
+ tot=opt=ext=siz=0;
+ /* Get the total number of arguments */
+ if (PyFunction_Check(fun)) {
+ tmp_fun = fun;
+ Py_INCREF(tmp_fun);
+ }
+ else {
+ di = 1;
+ if (PyObject_HasAttrString(fun,\"im_func\")) {
+ tmp_fun = PyObject_GetAttrString(fun,\"im_func\");
+ }
+ else if (PyObject_HasAttrString(fun,\"__call__\")) {
+ tmp = PyObject_GetAttrString(fun,\"__call__\");
+ if (PyObject_HasAttrString(tmp,\"im_func\"))
+ tmp_fun = PyObject_GetAttrString(tmp,\"im_func\");
+ else {
+ tmp_fun = fun; /* built-in function */
+ Py_INCREF(tmp_fun);
+ tot = maxnofargs;
+ if (PyCFunction_Check(fun)) {
+ /* In case the function has a co_argcount (like on PyPy) */
+ di = 0;
+ }
+ if (xa != NULL)
+ tot += PyTuple_Size((PyObject *)xa);
+ }
+ Py_XDECREF(tmp);
+ }
+ else if (PyFortran_Check(fun) || PyFortran_Check1(fun)) {
+ tot = maxnofargs;
+ if (xa != NULL)
+ tot += PyTuple_Size((PyObject *)xa);
+ tmp_fun = fun;
+ Py_INCREF(tmp_fun);
+ }
+ else if (F2PyCapsule_Check(fun)) {
+ tot = maxnofargs;
+ if (xa != NULL)
+ ext = PyTuple_Size((PyObject *)xa);
+ if(ext>0) {
+ fprintf(stderr,\"extra arguments tuple cannot be used with PyCapsule call-back\\n\");
+ goto capi_fail;
+ }
+ tmp_fun = fun;
+ Py_INCREF(tmp_fun);
+ }
+ }
+
+ if (tmp_fun == NULL) {
+ fprintf(stderr,
+ \"Call-back argument must be function|instance|instance.__call__|f2py-function \"
+ \"but got %s.\\n\",
+ ((fun == NULL) ? \"NULL\" : Py_TYPE(fun)->tp_name));
+ goto capi_fail;
+ }
+
+ if (PyObject_HasAttrString(tmp_fun,\"__code__\")) {
+ if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"__code__\"),\"co_argcount\")) {
+ PyObject *tmp_argcount = PyObject_GetAttrString(tmp,\"co_argcount\");
+ Py_DECREF(tmp);
+ if (tmp_argcount == NULL) {
+ goto capi_fail;
+ }
+ tot = PyLong_AsSsize_t(tmp_argcount) - di;
+ Py_DECREF(tmp_argcount);
+ }
+ }
+ /* Get the number of optional arguments */
+ if (PyObject_HasAttrString(tmp_fun,\"__defaults__\")) {
+ if (PyTuple_Check(tmp = PyObject_GetAttrString(tmp_fun,\"__defaults__\")))
+ opt = PyTuple_Size(tmp);
+ Py_XDECREF(tmp);
+ }
+ /* Get the number of extra arguments */
+ if (xa != NULL)
+ ext = PyTuple_Size((PyObject *)xa);
+ /* Calculate the size of call-backs argument list */
+ siz = MIN(maxnofargs+ext,tot);
+ *nofargs = MAX(0,siz-ext);
+
+#ifdef DEBUGCFUNCS
+ fprintf(stderr,
+ \"debug-capi:create_cb_arglist:maxnofargs(-nofoptargs),\"
+ \"tot,opt,ext,siz,nofargs = %d(-%d), %zd, %zd, %zd, %zd, %d\\n\",
+ maxnofargs, nofoptargs, tot, opt, ext, siz, *nofargs);
+#endif
+
+ if (siz < tot-opt) {
+ fprintf(stderr,
+ \"create_cb_arglist: Failed to build argument list \"
+ \"(siz) with enough arguments (tot-opt) required by \"
+ \"user-supplied function (siz,tot,opt=%zd, %zd, %zd).\\n\",
+ siz, tot, opt);
+ goto capi_fail;
+ }
+
+ /* Initialize argument list */
+ *args = (PyTupleObject *)PyTuple_New(siz);
+ for (i=0;i<*nofargs;i++) {
+ Py_INCREF(Py_None);
+ PyTuple_SET_ITEM((PyObject *)(*args),i,Py_None);
+ }
+ if (xa != NULL)
+ for (i=(*nofargs);i<siz;i++) {
+ tmp = PyTuple_GetItem((PyObject *)xa,i-(*nofargs));
+ Py_INCREF(tmp);
+ PyTuple_SET_ITEM(*args,i,tmp);
+ }
+ CFUNCSMESS(\"create_cb_arglist-end\\n\");
+ Py_DECREF(tmp_fun);
+ return 1;
+
+capi_fail:
+ if (PyErr_Occurred() == NULL)
+ PyErr_SetString(#modulename#_error, errmess);
+ Py_XDECREF(tmp_fun);
+ return 0;
+}
+"""
+
+
+def buildcfuncs():
+ from .capi_maps import c2capi_map
+ for k in c2capi_map.keys():
+ m = 'pyarr_from_p_%s1' % k
+ cppmacros[
+ m] = '#define %s(v) (PyArray_SimpleNewFromData(0,NULL,%s,(char *)v))' % (m, c2capi_map[k])
+ k = 'string'
+ m = 'pyarr_from_p_%s1' % k
+ # NPY_CHAR compatibility, NPY_STRING with itemsize 1
+ cppmacros[
+ m] = '#define %s(v,dims) (PyArray_New(&PyArray_Type, 1, dims, NPY_STRING, NULL, v, 1, NPY_ARRAY_CARRAY, NULL))' % (m)
+
+
+############ Auxiliary functions for sorting needs ###################
+
+def append_needs(need, flag=1):
+ # This function modifies the contents of the global `outneeds` dict.
+ if isinstance(need, list):
+ for n in need:
+ append_needs(n, flag)
+ elif isinstance(need, str):
+ if not need:
+ return
+ if need in includes0:
+ n = 'includes0'
+ elif need in includes:
+ n = 'includes'
+ elif need in typedefs:
+ n = 'typedefs'
+ elif need in typedefs_generated:
+ n = 'typedefs_generated'
+ elif need in cppmacros:
+ n = 'cppmacros'
+ elif need in cfuncs:
+ n = 'cfuncs'
+ elif need in callbacks:
+ n = 'callbacks'
+ elif need in f90modhooks:
+ n = 'f90modhooks'
+ elif need in commonhooks:
+ n = 'commonhooks'
+ else:
+ errmess('append_needs: unknown need %s\n' % (repr(need)))
+ return
+ if need in outneeds[n]:
+ return
+ if flag:
+ tmp = {}
+ if need in needs:
+ for nn in needs[need]:
+ t = append_needs(nn, 0)
+ if isinstance(t, dict):
+ for nnn in t.keys():
+ if nnn in tmp:
+ tmp[nnn] = tmp[nnn] + t[nnn]
+ else:
+ tmp[nnn] = t[nnn]
+ for nn in tmp.keys():
+ for nnn in tmp[nn]:
+ if nnn not in outneeds[nn]:
+ outneeds[nn] = [nnn] + outneeds[nn]
+ outneeds[n].append(need)
+ else:
+ tmp = {}
+ if need in needs:
+ for nn in needs[need]:
+ t = append_needs(nn, flag)
+ if isinstance(t, dict):
+ for nnn in t.keys():
+ if nnn in tmp:
+ tmp[nnn] = t[nnn] + tmp[nnn]
+ else:
+ tmp[nnn] = t[nnn]
+ if n not in tmp:
+ tmp[n] = []
+ tmp[n].append(need)
+ return tmp
+ else:
+ errmess('append_needs: expected list or string but got :%s\n' %
+ (repr(need)))
+
+
+def get_needs():
+ # This function modifies the contents of the global `outneeds` dict.
+ res = {}
+ for n in outneeds.keys():
+ out = []
+ saveout = copy.copy(outneeds[n])
+ while len(outneeds[n]) > 0:
+ if outneeds[n][0] not in needs:
+ out.append(outneeds[n][0])
+ del outneeds[n][0]
+ else:
+ flag = 0
+ for k in outneeds[n][1:]:
+ if k in needs[outneeds[n][0]]:
+ flag = 1
+ break
+ if flag:
+ outneeds[n] = outneeds[n][1:] + [outneeds[n][0]]
+ else:
+ out.append(outneeds[n][0])
+ del outneeds[n][0]
+ if saveout and (0 not in map(lambda x, y: x == y, saveout, outneeds[n])) \
+ and outneeds[n] != []:
+ print(n, saveout)
+ errmess(
+ 'get_needs: no progress in sorting needs, probably circular dependence, skipping.\n')
+ out = out + saveout
+ break
+ saveout = copy.copy(outneeds[n])
+ if out == []:
+ out = [n]
+ res[n] = out
+ return res
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/common_rules.py b/venv/lib/python3.9/site-packages/numpy/f2py/common_rules.py
new file mode 100644
index 00000000..5a488bf5
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/common_rules.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python3
+"""
+
+Build common block mechanism for f2py2e.
+
+Copyright 2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 10:57:33 $
+Pearu Peterson
+
+"""
+from . import __version__
+f2py_version = __version__.version
+
+from .auxfuncs import (
+ hasbody, hascommon, hasnote, isintent_hide, outmess
+)
+from . import capi_maps
+from . import func2subr
+from .crackfortran import rmbadname
+
+
+def findcommonblocks(block, top=1):
+ ret = []
+ if hascommon(block):
+ for key, value in block['common'].items():
+ vars_ = {v: block['vars'][v] for v in value}
+ ret.append((key, value, vars_))
+ elif hasbody(block):
+ for b in block['body']:
+ ret = ret + findcommonblocks(b, 0)
+ if top:
+ tret = []
+ names = []
+ for t in ret:
+ if t[0] not in names:
+ names.append(t[0])
+ tret.append(t)
+ return tret
+ return ret
+
+
+def buildhooks(m):
+ ret = {'commonhooks': [], 'initcommonhooks': [],
+ 'docs': ['"COMMON blocks:\\n"']}
+ fwrap = ['']
+
+ def fadd(line, s=fwrap):
+ s[0] = '%s\n %s' % (s[0], line)
+ chooks = ['']
+
+ def cadd(line, s=chooks):
+ s[0] = '%s\n%s' % (s[0], line)
+ ihooks = ['']
+
+ def iadd(line, s=ihooks):
+ s[0] = '%s\n%s' % (s[0], line)
+ doc = ['']
+
+ def dadd(line, s=doc):
+ s[0] = '%s\n%s' % (s[0], line)
+ for (name, vnames, vars) in findcommonblocks(m):
+ lower_name = name.lower()
+ hnames, inames = [], []
+ for n in vnames:
+ if isintent_hide(vars[n]):
+ hnames.append(n)
+ else:
+ inames.append(n)
+ if hnames:
+ outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n\t\t Hidden: %s\n' % (
+ name, ','.join(inames), ','.join(hnames)))
+ else:
+ outmess('\t\tConstructing COMMON block support for "%s"...\n\t\t %s\n' % (
+ name, ','.join(inames)))
+ fadd('subroutine f2pyinit%s(setupfunc)' % name)
+ fadd('external setupfunc')
+ for n in vnames:
+ fadd(func2subr.var2fixfortran(vars, n))
+ if name == '_BLNK_':
+ fadd('common %s' % (','.join(vnames)))
+ else:
+ fadd('common /%s/ %s' % (name, ','.join(vnames)))
+ fadd('call setupfunc(%s)' % (','.join(inames)))
+ fadd('end\n')
+ cadd('static FortranDataDef f2py_%s_def[] = {' % (name))
+ idims = []
+ for n in inames:
+ ct = capi_maps.getctype(vars[n])
+ elsize = capi_maps.get_elsize(vars[n])
+ at = capi_maps.c2capi_map[ct]
+ dm = capi_maps.getarrdims(n, vars[n])
+ if dm['dims']:
+ idims.append('(%s)' % (dm['dims']))
+ else:
+ idims.append('')
+ dms = dm['dims'].strip()
+ if not dms:
+ dms = '-1'
+ cadd('\t{\"%s\",%s,{{%s}},%s, %s},'
+ % (n, dm['rank'], dms, at, elsize))
+ cadd('\t{NULL}\n};')
+ inames1 = rmbadname(inames)
+ inames1_tps = ','.join(['char *' + s for s in inames1])
+ cadd('static void f2py_setup_%s(%s) {' % (name, inames1_tps))
+ cadd('\tint i_f2py=0;')
+ for n in inames1:
+ cadd('\tf2py_%s_def[i_f2py++].data = %s;' % (name, n))
+ cadd('}')
+ if '_' in lower_name:
+ F_FUNC = 'F_FUNC_US'
+ else:
+ F_FUNC = 'F_FUNC'
+ cadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void(*)(%s));'
+ % (F_FUNC, lower_name, name.upper(),
+ ','.join(['char*'] * len(inames1))))
+ cadd('static void f2py_init_%s(void) {' % name)
+ cadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
+ % (F_FUNC, lower_name, name.upper(), name))
+ cadd('}\n')
+ iadd('\ttmp = PyFortranObject_New(f2py_%s_def,f2py_init_%s);' % (name, name))
+ iadd('\tif (tmp == NULL) return NULL;')
+ iadd('\tif (F2PyDict_SetItemString(d, \"%s\", tmp) == -1) return NULL;'
+ % name)
+ iadd('\tPy_DECREF(tmp);')
+ tname = name.replace('_', '\\_')
+ dadd('\\subsection{Common block \\texttt{%s}}\n' % (tname))
+ dadd('\\begin{description}')
+ for n in inames:
+ dadd('\\item[]{{}\\verb@%s@{}}' %
+ (capi_maps.getarrdocsign(n, vars[n])))
+ if hasnote(vars[n]):
+ note = vars[n]['note']
+ if isinstance(note, list):
+ note = '\n'.join(note)
+ dadd('--- %s' % (note))
+ dadd('\\end{description}')
+ ret['docs'].append(
+ '"\t/%s/ %s\\n"' % (name, ','.join(map(lambda v, d: v + d, inames, idims))))
+ ret['commonhooks'] = chooks
+ ret['initcommonhooks'] = ihooks
+ ret['latexdoc'] = doc[0]
+ if len(ret['docs']) <= 1:
+ ret['docs'] = ''
+ return ret, fwrap[0]
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/crackfortran.py b/venv/lib/python3.9/site-packages/numpy/f2py/crackfortran.py
new file mode 100644
index 00000000..63597cef
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/crackfortran.py
@@ -0,0 +1,3545 @@
+#!/usr/bin/env python3
+"""
+crackfortran --- read fortran (77,90) code and extract declaration information.
+
+Copyright 1999-2004 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/09/27 07:13:49 $
+Pearu Peterson
+
+
+Usage of crackfortran:
+======================
+Command line keys: -quiet,-verbose,-fix,-f77,-f90,-show,-h <pyffilename>
+ -m <module name for f77 routines>,--ignore-contains
+Functions: crackfortran, crack2fortran
+The following Fortran statements/constructions are supported
+(or will be if needed):
+ block data,byte,call,character,common,complex,contains,data,
+ dimension,double complex,double precision,end,external,function,
+ implicit,integer,intent,interface,intrinsic,
+ logical,module,optional,parameter,private,public,
+ program,real,(sequence?),subroutine,type,use,virtual,
+ include,pythonmodule
+Note: 'virtual' is mapped to 'dimension'.
+Note: 'implicit integer (z) static (z)' is 'implicit static (z)' (this is minor bug).
+Note: code after 'contains' will be ignored until its scope ends.
+Note: 'common' statement is extended: dimensions are moved to variable definitions
+Note: f2py directive: <commentchar>f2py<line> is read as <line>
+Note: pythonmodule is introduced to represent Python module
+
+Usage:
+ `postlist=crackfortran(files)`
+ `postlist` contains declaration information read from the list of files `files`.
+ `crack2fortran(postlist)` returns a fortran code to be saved to pyf-file
+
+ `postlist` has the following structure:
+ *** it is a list of dictionaries containing `blocks':
+ B = {'block','body','vars','parent_block'[,'name','prefix','args','result',
+ 'implicit','externals','interfaced','common','sortvars',
+ 'commonvars','note']}
+ B['block'] = 'interface' | 'function' | 'subroutine' | 'module' |
+ 'program' | 'block data' | 'type' | 'pythonmodule' |
+ 'abstract interface'
+ B['body'] --- list containing `subblocks' with the same structure as `blocks'
+ B['parent_block'] --- dictionary of a parent block:
+ C['body'][<index>]['parent_block'] is C
+ B['vars'] --- dictionary of variable definitions
+ B['sortvars'] --- dictionary of variable definitions sorted by dependence (independent first)
+ B['name'] --- name of the block (not if B['block']=='interface')
+ B['prefix'] --- prefix string (only if B['block']=='function')
+ B['args'] --- list of argument names if B['block']== 'function' | 'subroutine'
+ B['result'] --- name of the return value (only if B['block']=='function')
+ B['implicit'] --- dictionary {'a':<variable definition>,'b':...} | None
+ B['externals'] --- list of variables being external
+ B['interfaced'] --- list of variables being external and defined
+ B['common'] --- dictionary of common blocks (list of objects)
+ B['commonvars'] --- list of variables used in common blocks (dimensions are moved to variable definitions)
+ B['from'] --- string showing the 'parents' of the current block
+ B['use'] --- dictionary of modules used in current block:
+ {<modulename>:{['only':<0|1>],['map':{<local_name1>:<use_name1>,...}]}}
+ B['note'] --- list of LaTeX comments on the block
+ B['f2pyenhancements'] --- optional dictionary
+ {'threadsafe':'','fortranname':<name>,
+ 'callstatement':<C-expr>|<multi-line block>,
+ 'callprotoargument':<C-expr-list>,
+ 'usercode':<multi-line block>|<list of multi-line blocks>,
+ 'pymethoddef:<multi-line block>'
+ }
+ B['entry'] --- dictionary {entryname:argslist,..}
+ B['varnames'] --- list of variable names given in the order of reading the
+ Fortran code, useful for derived types.
+ B['saved_interface'] --- a string of scanned routine signature, defines explicit interface
+ *** Variable definition is a dictionary
+ D = B['vars'][<variable name>] =
+ {'typespec'[,'attrspec','kindselector','charselector','=','typename']}
+ D['typespec'] = 'byte' | 'character' | 'complex' | 'double complex' |
+ 'double precision' | 'integer' | 'logical' | 'real' | 'type'
+ D['attrspec'] --- list of attributes (e.g. 'dimension(<arrayspec>)',
+ 'external','intent(in|out|inout|hide|c|callback|cache|aligned4|aligned8|aligned16)',
+ 'optional','required', etc)
+ K = D['kindselector'] = {['*','kind']} (only if D['typespec'] =
+ 'complex' | 'integer' | 'logical' | 'real' )
+ C = D['charselector'] = {['*','len','kind','f2py_len']}
+ (only if D['typespec']=='character')
+ D['='] --- initialization expression string
+ D['typename'] --- name of the type if D['typespec']=='type'
+ D['dimension'] --- list of dimension bounds
+ D['intent'] --- list of intent specifications
+ D['depend'] --- list of variable names on which current variable depends on
+ D['check'] --- list of C-expressions; if C-expr returns zero, exception is raised
+ D['note'] --- list of LaTeX comments on the variable
+ *** Meaning of kind/char selectors (few examples):
+ D['typespec>']*K['*']
+ D['typespec'](kind=K['kind'])
+ character*C['*']
+ character(len=C['len'],kind=C['kind'], f2py_len=C['f2py_len'])
+ (see also fortran type declaration statement formats below)
+
+Fortran 90 type declaration statement format (F77 is subset of F90)
+====================================================================
+(Main source: IBM XL Fortran 5.1 Language Reference Manual)
+type declaration = <typespec> [[<attrspec>]::] <entitydecl>
+<typespec> = byte |
+ character[<charselector>] |
+ complex[<kindselector>] |
+ double complex |
+ double precision |
+ integer[<kindselector>] |
+ logical[<kindselector>] |
+ real[<kindselector>] |
+ type(<typename>)
+<charselector> = * <charlen> |
+ ([len=]<len>[,[kind=]<kind>]) |
+ (kind=<kind>[,len=<len>])
+<kindselector> = * <intlen> |
+ ([kind=]<kind>)
+<attrspec> = comma separated list of attributes.
+ Only the following attributes are used in
+ building up the interface:
+ external
+ (parameter --- affects '=' key)
+ optional
+ intent
+ Other attributes are ignored.
+<intentspec> = in | out | inout
+<arrayspec> = comma separated list of dimension bounds.
+<entitydecl> = <name> [[*<charlen>][(<arrayspec>)] | [(<arrayspec>)]*<charlen>]
+ [/<init_expr>/ | =<init_expr>] [,<entitydecl>]
+
+In addition, the following attributes are used: check,depend,note
+
+TODO:
+ * Apply 'parameter' attribute (e.g. 'integer parameter :: i=2' 'real x(i)'
+ -> 'real x(2)')
+ The above may be solved by creating appropriate preprocessor program, for example.
+
+"""
+import sys
+import string
+import fileinput
+import re
+import os
+import copy
+import platform
+import codecs
+try:
+ import charset_normalizer
+except ImportError:
+ charset_normalizer = None
+
+from . import __version__
+
+# The environment provided by auxfuncs.py is needed for some calls to eval.
+# As the needed functions cannot be determined by static inspection of the
+# code, it is safest to use import * pending a major refactoring of f2py.
+from .auxfuncs import *
+from . import symbolic
+
+f2py_version = __version__.version
+
+# Global flags:
+strictf77 = 1 # Ignore `!' comments unless line[0]=='!'
+sourcecodeform = 'fix' # 'fix','free'
+quiet = 0 # Be verbose if 0 (Obsolete: not used any more)
+verbose = 1 # Be quiet if 0, extra verbose if > 1.
+tabchar = 4 * ' '
+pyffilename = ''
+f77modulename = ''
+skipemptyends = 0 # for old F77 programs without 'program' statement
+ignorecontains = 1
+dolowercase = 1
+debug = []
+
+# Global variables
+beginpattern = ''
+currentfilename = ''
+expectbegin = 1
+f90modulevars = {}
+filepositiontext = ''
+gotnextfile = 1
+groupcache = None
+groupcounter = 0
+grouplist = {groupcounter: []}
+groupname = ''
+include_paths = []
+neededmodule = -1
+onlyfuncs = []
+previous_context = None
+skipblocksuntil = -1
+skipfuncs = []
+skipfunctions = []
+usermodules = []
+
+
+def reset_global_f2py_vars():
+ global groupcounter, grouplist, neededmodule, expectbegin
+ global skipblocksuntil, usermodules, f90modulevars, gotnextfile
+ global filepositiontext, currentfilename, skipfunctions, skipfuncs
+ global onlyfuncs, include_paths, previous_context
+ global strictf77, sourcecodeform, quiet, verbose, tabchar, pyffilename
+ global f77modulename, skipemptyends, ignorecontains, dolowercase, debug
+
+ # flags
+ strictf77 = 1
+ sourcecodeform = 'fix'
+ quiet = 0
+ verbose = 1
+ tabchar = 4 * ' '
+ pyffilename = ''
+ f77modulename = ''
+ skipemptyends = 0
+ ignorecontains = 1
+ dolowercase = 1
+ debug = []
+ # variables
+ groupcounter = 0
+ grouplist = {groupcounter: []}
+ neededmodule = -1
+ expectbegin = 1
+ skipblocksuntil = -1
+ usermodules = []
+ f90modulevars = {}
+ gotnextfile = 1
+ filepositiontext = ''
+ currentfilename = ''
+ skipfunctions = []
+ skipfuncs = []
+ onlyfuncs = []
+ include_paths = []
+ previous_context = None
+
+
+def outmess(line, flag=1):
+ global filepositiontext
+
+ if not verbose:
+ return
+ if not quiet:
+ if flag:
+ sys.stdout.write(filepositiontext)
+ sys.stdout.write(line)
+
+re._MAXCACHE = 50
+defaultimplicitrules = {}
+for c in "abcdefghopqrstuvwxyz$_":
+ defaultimplicitrules[c] = {'typespec': 'real'}
+for c in "ijklmn":
+ defaultimplicitrules[c] = {'typespec': 'integer'}
+badnames = {}
+invbadnames = {}
+for n in ['int', 'double', 'float', 'char', 'short', 'long', 'void', 'case', 'while',
+ 'return', 'signed', 'unsigned', 'if', 'for', 'typedef', 'sizeof', 'union',
+ 'struct', 'static', 'register', 'new', 'break', 'do', 'goto', 'switch',
+ 'continue', 'else', 'inline', 'extern', 'delete', 'const', 'auto',
+ 'len', 'rank', 'shape', 'index', 'slen', 'size', '_i',
+ 'max', 'min',
+ 'flen', 'fshape',
+ 'string', 'complex_double', 'float_double', 'stdin', 'stderr', 'stdout',
+ 'type', 'default']:
+ badnames[n] = n + '_bn'
+ invbadnames[n + '_bn'] = n
+
+
+def rmbadname1(name):
+ if name in badnames:
+ errmess('rmbadname1: Replacing "%s" with "%s".\n' %
+ (name, badnames[name]))
+ return badnames[name]
+ return name
+
+
+def rmbadname(names):
+ return [rmbadname1(_m) for _m in names]
+
+
+def undo_rmbadname1(name):
+ if name in invbadnames:
+ errmess('undo_rmbadname1: Replacing "%s" with "%s".\n'
+ % (name, invbadnames[name]))
+ return invbadnames[name]
+ return name
+
+
+def undo_rmbadname(names):
+ return [undo_rmbadname1(_m) for _m in names]
+
+
+def getextension(name):
+ i = name.rfind('.')
+ if i == -1:
+ return ''
+ if '\\' in name[i:]:
+ return ''
+ if '/' in name[i:]:
+ return ''
+ return name[i + 1:]
+
+is_f_file = re.compile(r'.*\.(for|ftn|f77|f)\Z', re.I).match
+_has_f_header = re.compile(r'-\*-\s*fortran\s*-\*-', re.I).search
+_has_f90_header = re.compile(r'-\*-\s*f90\s*-\*-', re.I).search
+_has_fix_header = re.compile(r'-\*-\s*fix\s*-\*-', re.I).search
+_free_f90_start = re.compile(r'[^c*]\s*[^\s\d\t]', re.I).match
+
+
+def openhook(filename, mode):
+ """Ensures that filename is opened with correct encoding parameter.
+
+ This function uses charset_normalizer package, when available, for
+ determining the encoding of the file to be opened. When charset_normalizer
+ is not available, the function detects only UTF encodings, otherwise, ASCII
+ encoding is used as fallback.
+ """
+ # Reads in the entire file. Robust detection of encoding.
+ # Correctly handles comments or late stage unicode characters
+ # gh-22871
+ if charset_normalizer is not None:
+ encoding = charset_normalizer.from_path(filename).best().encoding
+ else:
+ # hint: install charset_normalizer for correct encoding handling
+ # No need to read the whole file for trying with startswith
+ nbytes = min(32, os.path.getsize(filename))
+ with open(filename, 'rb') as fhandle:
+ raw = fhandle.read(nbytes)
+ if raw.startswith(codecs.BOM_UTF8):
+ encoding = 'UTF-8-SIG'
+ elif raw.startswith((codecs.BOM_UTF32_LE, codecs.BOM_UTF32_BE)):
+ encoding = 'UTF-32'
+ elif raw.startswith((codecs.BOM_LE, codecs.BOM_BE)):
+ encoding = 'UTF-16'
+ else:
+ # Fallback, without charset_normalizer
+ encoding = 'ascii'
+ return open(filename, mode, encoding=encoding)
+
+
+def is_free_format(file):
+ """Check if file is in free format Fortran."""
+ # f90 allows both fixed and free format, assuming fixed unless
+ # signs of free format are detected.
+ result = 0
+ with openhook(file, 'r') as f:
+ line = f.readline()
+ n = 15 # the number of non-comment lines to scan for hints
+ if _has_f_header(line):
+ n = 0
+ elif _has_f90_header(line):
+ n = 0
+ result = 1
+ while n > 0 and line:
+ if line[0] != '!' and line.strip():
+ n -= 1
+ if (line[0] != '\t' and _free_f90_start(line[:5])) or line[-2:-1] == '&':
+ result = 1
+ break
+ line = f.readline()
+ return result
+
+
+# Read fortran (77,90) code
+def readfortrancode(ffile, dowithline=show, istop=1):
+ """
+ Read fortran codes from files and
+ 1) Get rid of comments, line continuations, and empty lines; lower cases.
+ 2) Call dowithline(line) on every line.
+ 3) Recursively call itself when statement \"include '<filename>'\" is met.
+ """
+ global gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77
+ global beginpattern, quiet, verbose, dolowercase, include_paths
+
+ if not istop:
+ saveglobals = gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+ beginpattern, quiet, verbose, dolowercase
+ if ffile == []:
+ return
+ localdolowercase = dolowercase
+ # cont: set to True when the content of the last line read
+ # indicates statement continuation
+ cont = False
+ finalline = ''
+ ll = ''
+ includeline = re.compile(
+ r'\s*include\s*(\'|")(?P<name>[^\'"]*)(\'|")', re.I)
+ cont1 = re.compile(r'(?P<line>.*)&\s*\Z')
+ cont2 = re.compile(r'(\s*&|)(?P<line>.*)')
+ mline_mark = re.compile(r".*?'''")
+ if istop:
+ dowithline('', -1)
+ ll, l1 = '', ''
+ spacedigits = [' '] + [str(_m) for _m in range(10)]
+ filepositiontext = ''
+ fin = fileinput.FileInput(ffile, openhook=openhook)
+ while True:
+ try:
+ l = fin.readline()
+ except UnicodeDecodeError as msg:
+ raise Exception(
+ f'readfortrancode: reading {fin.filename()}#{fin.lineno()}'
+ f' failed with\n{msg}.\nIt is likely that installing charset_normalizer'
+ ' package will help f2py determine the input file encoding'
+ ' correctly.')
+ if not l:
+ break
+ if fin.isfirstline():
+ filepositiontext = ''
+ currentfilename = fin.filename()
+ gotnextfile = 1
+ l1 = l
+ strictf77 = 0
+ sourcecodeform = 'fix'
+ ext = os.path.splitext(currentfilename)[1]
+ if is_f_file(currentfilename) and \
+ not (_has_f90_header(l) or _has_fix_header(l)):
+ strictf77 = 1
+ elif is_free_format(currentfilename) and not _has_fix_header(l):
+ sourcecodeform = 'free'
+ if strictf77:
+ beginpattern = beginpattern77
+ else:
+ beginpattern = beginpattern90
+ outmess('\tReading file %s (format:%s%s)\n'
+ % (repr(currentfilename), sourcecodeform,
+ strictf77 and ',strict' or ''))
+
+ l = l.expandtabs().replace('\xa0', ' ')
+ # Get rid of newline characters
+ while not l == '':
+ if l[-1] not in "\n\r\f":
+ break
+ l = l[:-1]
+ if not strictf77:
+ (l, rl) = split_by_unquoted(l, '!')
+ l += ' '
+ if rl[:5].lower() == '!f2py': # f2py directive
+ l, _ = split_by_unquoted(l + 4 * ' ' + rl[5:], '!')
+ if l.strip() == '': # Skip empty line
+ if sourcecodeform == 'free':
+ # In free form, a statement continues in the next line
+ # that is not a comment line [3.3.2.4^1], lines with
+ # blanks are comment lines [3.3.2.3^1]. Hence, the
+ # line continuation flag must retain its state.
+ pass
+ else:
+ # In fixed form, statement continuation is determined
+ # by a non-blank character at the 6-th position. Empty
+ # line indicates a start of a new statement
+ # [3.3.3.3^1]. Hence, the line continuation flag must
+ # be reset.
+ cont = False
+ continue
+ if sourcecodeform == 'fix':
+ if l[0] in ['*', 'c', '!', 'C', '#']:
+ if l[1:5].lower() == 'f2py': # f2py directive
+ l = ' ' + l[5:]
+ else: # Skip comment line
+ cont = False
+ continue
+ elif strictf77:
+ if len(l) > 72:
+ l = l[:72]
+ if not (l[0] in spacedigits):
+ raise Exception('readfortrancode: Found non-(space,digit) char '
+ 'in the first column.\n\tAre you sure that '
+ 'this code is in fix form?\n\tline=%s' % repr(l))
+
+ if (not cont or strictf77) and (len(l) > 5 and not l[5] == ' '):
+ # Continuation of a previous line
+ ll = ll + l[6:]
+ finalline = ''
+ origfinalline = ''
+ else:
+ if not strictf77:
+ # F90 continuation
+ r = cont1.match(l)
+ if r:
+ l = r.group('line') # Continuation follows ..
+ if cont:
+ ll = ll + cont2.match(l).group('line')
+ finalline = ''
+ origfinalline = ''
+ else:
+ # clean up line beginning from possible digits.
+ l = ' ' + l[5:]
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ ll = l
+ cont = (r is not None)
+ else:
+ # clean up line beginning from possible digits.
+ l = ' ' + l[5:]
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ ll = l
+
+ elif sourcecodeform == 'free':
+ if not cont and ext == '.pyf' and mline_mark.match(l):
+ l = l + '\n'
+ while True:
+ lc = fin.readline()
+ if not lc:
+ errmess(
+ 'Unexpected end of file when reading multiline\n')
+ break
+ l = l + lc
+ if mline_mark.match(lc):
+ break
+ l = l.rstrip()
+ r = cont1.match(l)
+ if r:
+ l = r.group('line') # Continuation follows ..
+ if cont:
+ ll = ll + cont2.match(l).group('line')
+ finalline = ''
+ origfinalline = ''
+ else:
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ ll = l
+ cont = (r is not None)
+ else:
+ raise ValueError(
+ "Flag sourcecodeform must be either 'fix' or 'free': %s" % repr(sourcecodeform))
+ filepositiontext = 'Line #%d in %s:"%s"\n\t' % (
+ fin.filelineno() - 1, currentfilename, l1)
+ m = includeline.match(origfinalline)
+ if m:
+ fn = m.group('name')
+ if os.path.isfile(fn):
+ readfortrancode(fn, dowithline=dowithline, istop=0)
+ else:
+ include_dirs = [
+ os.path.dirname(currentfilename)] + include_paths
+ foundfile = 0
+ for inc_dir in include_dirs:
+ fn1 = os.path.join(inc_dir, fn)
+ if os.path.isfile(fn1):
+ foundfile = 1
+ readfortrancode(fn1, dowithline=dowithline, istop=0)
+ break
+ if not foundfile:
+ outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n' % (
+ repr(fn), os.pathsep.join(include_dirs)))
+ else:
+ dowithline(finalline)
+ l1 = ll
+ if localdolowercase:
+ finalline = ll.lower()
+ else:
+ finalline = ll
+ origfinalline = ll
+ filepositiontext = 'Line #%d in %s:"%s"\n\t' % (
+ fin.filelineno() - 1, currentfilename, l1)
+ m = includeline.match(origfinalline)
+ if m:
+ fn = m.group('name')
+ if os.path.isfile(fn):
+ readfortrancode(fn, dowithline=dowithline, istop=0)
+ else:
+ include_dirs = [os.path.dirname(currentfilename)] + include_paths
+ foundfile = 0
+ for inc_dir in include_dirs:
+ fn1 = os.path.join(inc_dir, fn)
+ if os.path.isfile(fn1):
+ foundfile = 1
+ readfortrancode(fn1, dowithline=dowithline, istop=0)
+ break
+ if not foundfile:
+ outmess('readfortrancode: could not find include file %s in %s. Ignoring.\n' % (
+ repr(fn), os.pathsep.join(include_dirs)))
+ else:
+ dowithline(finalline)
+ filepositiontext = ''
+ fin.close()
+ if istop:
+ dowithline('', 1)
+ else:
+ gotnextfile, filepositiontext, currentfilename, sourcecodeform, strictf77,\
+ beginpattern, quiet, verbose, dolowercase = saveglobals
+
+# Crack line
+beforethisafter = r'\s*(?P<before>%s(?=\s*(\b(%s)\b)))' + \
+ r'\s*(?P<this>(\b(%s)\b))' + \
+ r'\s*(?P<after>%s)\s*\Z'
+##
+fortrantypes = r'character|logical|integer|real|complex|double\s*(precision\s*(complex|)|complex)|type(?=\s*\([\w\s,=(*)]*\))|byte'
+typespattern = re.compile(
+ beforethisafter % ('', fortrantypes, fortrantypes, '.*'), re.I), 'type'
+typespattern4implicit = re.compile(beforethisafter % (
+ '', fortrantypes + '|static|automatic|undefined', fortrantypes + '|static|automatic|undefined', '.*'), re.I)
+#
+functionpattern = re.compile(beforethisafter % (
+ r'([a-z]+[\w\s(=*+-/)]*?|)', 'function', 'function', '.*'), re.I), 'begin'
+subroutinepattern = re.compile(beforethisafter % (
+ r'[a-z\s]*?', 'subroutine', 'subroutine', '.*'), re.I), 'begin'
+# modulepattern=re.compile(beforethisafter%('[a-z\s]*?','module','module','.*'),re.I),'begin'
+#
+groupbegins77 = r'program|block\s*data'
+beginpattern77 = re.compile(
+ beforethisafter % ('', groupbegins77, groupbegins77, '.*'), re.I), 'begin'
+groupbegins90 = groupbegins77 + \
+ r'|module(?!\s*procedure)|python\s*module|(abstract|)\s*interface|' + \
+ r'type(?!\s*\()'
+beginpattern90 = re.compile(
+ beforethisafter % ('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
+groupends = (r'end|endprogram|endblockdata|endmodule|endpythonmodule|'
+ r'endinterface|endsubroutine|endfunction')
+endpattern = re.compile(
+ beforethisafter % ('', groupends, groupends, r'.*'), re.I), 'end'
+endifs = r'end\s*(if|do|where|select|while|forall|associate|block|' + \
+ r'critical|enum|team)'
+endifpattern = re.compile(
+ beforethisafter % (r'[\w]*?', endifs, endifs, r'[\w\s]*'), re.I), 'endif'
+#
+moduleprocedures = r'module\s*procedure'
+moduleprocedurepattern = re.compile(
+ beforethisafter % ('', moduleprocedures, moduleprocedures, r'.*'), re.I), \
+ 'moduleprocedure'
+implicitpattern = re.compile(
+ beforethisafter % ('', 'implicit', 'implicit', '.*'), re.I), 'implicit'
+dimensionpattern = re.compile(beforethisafter % (
+ '', 'dimension|virtual', 'dimension|virtual', '.*'), re.I), 'dimension'
+externalpattern = re.compile(
+ beforethisafter % ('', 'external', 'external', '.*'), re.I), 'external'
+optionalpattern = re.compile(
+ beforethisafter % ('', 'optional', 'optional', '.*'), re.I), 'optional'
+requiredpattern = re.compile(
+ beforethisafter % ('', 'required', 'required', '.*'), re.I), 'required'
+publicpattern = re.compile(
+ beforethisafter % ('', 'public', 'public', '.*'), re.I), 'public'
+privatepattern = re.compile(
+ beforethisafter % ('', 'private', 'private', '.*'), re.I), 'private'
+intrinsicpattern = re.compile(
+ beforethisafter % ('', 'intrinsic', 'intrinsic', '.*'), re.I), 'intrinsic'
+intentpattern = re.compile(beforethisafter % (
+ '', 'intent|depend|note|check', 'intent|depend|note|check', r'\s*\(.*?\).*'), re.I), 'intent'
+parameterpattern = re.compile(
+ beforethisafter % ('', 'parameter', 'parameter', r'\s*\(.*'), re.I), 'parameter'
+datapattern = re.compile(
+ beforethisafter % ('', 'data', 'data', '.*'), re.I), 'data'
+callpattern = re.compile(
+ beforethisafter % ('', 'call', 'call', '.*'), re.I), 'call'
+entrypattern = re.compile(
+ beforethisafter % ('', 'entry', 'entry', '.*'), re.I), 'entry'
+callfunpattern = re.compile(
+ beforethisafter % ('', 'callfun', 'callfun', '.*'), re.I), 'callfun'
+commonpattern = re.compile(
+ beforethisafter % ('', 'common', 'common', '.*'), re.I), 'common'
+usepattern = re.compile(
+ beforethisafter % ('', 'use', 'use', '.*'), re.I), 'use'
+containspattern = re.compile(
+ beforethisafter % ('', 'contains', 'contains', ''), re.I), 'contains'
+formatpattern = re.compile(
+ beforethisafter % ('', 'format', 'format', '.*'), re.I), 'format'
+# Non-fortran and f2py-specific statements
+f2pyenhancementspattern = re.compile(beforethisafter % ('', 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef',
+ 'threadsafe|fortranname|callstatement|callprotoargument|usercode|pymethoddef', '.*'), re.I | re.S), 'f2pyenhancements'
+multilinepattern = re.compile(
+ r"\s*(?P<before>''')(?P<this>.*?)(?P<after>''')\s*\Z", re.S), 'multiline'
+##
+
+def split_by_unquoted(line, characters):
+ """
+ Splits the line into (line[:i], line[i:]),
+ where i is the index of first occurrence of one of the characters
+ not within quotes, or len(line) if no such index exists
+ """
+ assert not (set('"\'') & set(characters)), "cannot split by unquoted quotes"
+ r = re.compile(
+ r"\A(?P<before>({single_quoted}|{double_quoted}|{not_quoted})*)"
+ r"(?P<after>{char}.*)\Z".format(
+ not_quoted="[^\"'{}]".format(re.escape(characters)),
+ char="[{}]".format(re.escape(characters)),
+ single_quoted=r"('([^'\\]|(\\.))*')",
+ double_quoted=r'("([^"\\]|(\\.))*")'))
+ m = r.match(line)
+ if m:
+ d = m.groupdict()
+ return (d["before"], d["after"])
+ return (line, "")
+
+def _simplifyargs(argsline):
+ a = []
+ for n in markoutercomma(argsline).split('@,@'):
+ for r in '(),':
+ n = n.replace(r, '_')
+ a.append(n)
+ return ','.join(a)
+
+crackline_re_1 = re.compile(r'\s*(?P<result>\b[a-z]+\w*\b)\s*=.*', re.I)
+
+
+def crackline(line, reset=0):
+ """
+ reset=-1 --- initialize
+ reset=0 --- crack the line
+ reset=1 --- final check if mismatch of blocks occurred
+
+ Cracked data is saved in grouplist[0].
+ """
+ global beginpattern, groupcounter, groupname, groupcache, grouplist
+ global filepositiontext, currentfilename, neededmodule, expectbegin
+ global skipblocksuntil, skipemptyends, previous_context, gotnextfile
+
+ _, has_semicolon = split_by_unquoted(line, ";")
+ if has_semicolon and not (f2pyenhancementspattern[0].match(line) or
+ multilinepattern[0].match(line)):
+ # XXX: non-zero reset values need testing
+ assert reset == 0, repr(reset)
+ # split line on unquoted semicolons
+ line, semicolon_line = split_by_unquoted(line, ";")
+ while semicolon_line:
+ crackline(line, reset)
+ line, semicolon_line = split_by_unquoted(semicolon_line[1:], ";")
+ crackline(line, reset)
+ return
+ if reset < 0:
+ groupcounter = 0
+ groupname = {groupcounter: ''}
+ groupcache = {groupcounter: {}}
+ grouplist = {groupcounter: []}
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcache[groupcounter]['block'] = ''
+ groupcache[groupcounter]['name'] = ''
+ neededmodule = -1
+ skipblocksuntil = -1
+ return
+ if reset > 0:
+ fl = 0
+ if f77modulename and neededmodule == groupcounter:
+ fl = 2
+ while groupcounter > fl:
+ outmess('crackline: groupcounter=%s groupname=%s\n' %
+ (repr(groupcounter), repr(groupname)))
+ outmess(
+ 'crackline: Mismatch of blocks encountered. Trying to fix it by assuming "end" statement.\n')
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1
+ if f77modulename and neededmodule == groupcounter:
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end interface
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end module
+ neededmodule = -1
+ return
+ if line == '':
+ return
+ flag = 0
+ for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern,
+ requiredpattern,
+ parameterpattern, datapattern, publicpattern, privatepattern,
+ intrinsicpattern,
+ endifpattern, endpattern,
+ formatpattern,
+ beginpattern, functionpattern, subroutinepattern,
+ implicitpattern, typespattern, commonpattern,
+ callpattern, usepattern, containspattern,
+ entrypattern,
+ f2pyenhancementspattern,
+ multilinepattern,
+ moduleprocedurepattern
+ ]:
+ m = pat[0].match(line)
+ if m:
+ break
+ flag = flag + 1
+ if not m:
+ re_1 = crackline_re_1
+ if 0 <= skipblocksuntil <= groupcounter:
+ return
+ if 'externals' in groupcache[groupcounter]:
+ for name in groupcache[groupcounter]['externals']:
+ if name in invbadnames:
+ name = invbadnames[name]
+ if 'interfaced' in groupcache[groupcounter] and name in groupcache[groupcounter]['interfaced']:
+ continue
+ m1 = re.match(
+ r'(?P<before>[^"]*)\b%s\b\s*@\(@(?P<args>[^@]*)@\)@.*\Z' % name, markouterparen(line), re.I)
+ if m1:
+ m2 = re_1.match(m1.group('before'))
+ a = _simplifyargs(m1.group('args'))
+ if m2:
+ line = 'callfun %s(%s) result (%s)' % (
+ name, a, m2.group('result'))
+ else:
+ line = 'callfun %s(%s)' % (name, a)
+ m = callfunpattern[0].match(line)
+ if not m:
+ outmess(
+ 'crackline: could not resolve function call for line=%s.\n' % repr(line))
+ return
+ analyzeline(m, 'callfun', line)
+ return
+ if verbose > 1 or (verbose == 1 and currentfilename.lower().endswith('.pyf')):
+ previous_context = None
+ outmess('crackline:%d: No pattern for line\n' % (groupcounter))
+ return
+ elif pat[1] == 'end':
+ if 0 <= skipblocksuntil < groupcounter:
+ groupcounter = groupcounter - 1
+ if skipblocksuntil <= groupcounter:
+ return
+ if groupcounter <= 0:
+ raise Exception('crackline: groupcounter(=%s) is nonpositive. '
+ 'Check the blocks.'
+ % (groupcounter))
+ m1 = beginpattern[0].match((line))
+ if (m1) and (not m1.group('this') == groupname[groupcounter]):
+ raise Exception('crackline: End group %s does not match with '
+ 'previous Begin group %s\n\t%s' %
+ (repr(m1.group('this')), repr(groupname[groupcounter]),
+ filepositiontext)
+ )
+ if skipblocksuntil == groupcounter:
+ skipblocksuntil = -1
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1
+ if not skipemptyends:
+ expectbegin = 1
+ elif pat[1] == 'begin':
+ if 0 <= skipblocksuntil <= groupcounter:
+ groupcounter = groupcounter + 1
+ return
+ gotnextfile = 0
+ analyzeline(m, pat[1], line)
+ expectbegin = 0
+ elif pat[1] == 'endif':
+ pass
+ elif pat[1] == 'moduleprocedure':
+ analyzeline(m, pat[1], line)
+ elif pat[1] == 'contains':
+ if ignorecontains:
+ return
+ if 0 <= skipblocksuntil <= groupcounter:
+ return
+ skipblocksuntil = groupcounter
+ else:
+ if 0 <= skipblocksuntil <= groupcounter:
+ return
+ analyzeline(m, pat[1], line)
+
+
+def markouterparen(line):
+ l = ''
+ f = 0
+ for c in line:
+ if c == '(':
+ f = f + 1
+ if f == 1:
+ l = l + '@(@'
+ continue
+ elif c == ')':
+ f = f - 1
+ if f == 0:
+ l = l + '@)@'
+ continue
+ l = l + c
+ return l
+
+
+def markoutercomma(line, comma=','):
+ l = ''
+ f = 0
+ before, after = split_by_unquoted(line, comma + '()')
+ l += before
+ while after:
+ if (after[0] == comma) and (f == 0):
+ l += '@' + comma + '@'
+ else:
+ l += after[0]
+ if after[0] == '(':
+ f += 1
+ elif after[0] == ')':
+ f -= 1
+ before, after = split_by_unquoted(after[1:], comma + '()')
+ l += before
+ assert not f, repr((f, line, l))
+ return l
+
+def unmarkouterparen(line):
+ r = line.replace('@(@', '(').replace('@)@', ')')
+ return r
+
+
+def appenddecl(decl, decl2, force=1):
+ if not decl:
+ decl = {}
+ if not decl2:
+ return decl
+ if decl is decl2:
+ return decl
+ for k in list(decl2.keys()):
+ if k == 'typespec':
+ if force or k not in decl:
+ decl[k] = decl2[k]
+ elif k == 'attrspec':
+ for l in decl2[k]:
+ decl = setattrspec(decl, l, force)
+ elif k == 'kindselector':
+ decl = setkindselector(decl, decl2[k], force)
+ elif k == 'charselector':
+ decl = setcharselector(decl, decl2[k], force)
+ elif k in ['=', 'typename']:
+ if force or k not in decl:
+ decl[k] = decl2[k]
+ elif k == 'note':
+ pass
+ elif k in ['intent', 'check', 'dimension', 'optional',
+ 'required', 'depend']:
+ errmess('appenddecl: "%s" not implemented.\n' % k)
+ else:
+ raise Exception('appenddecl: Unknown variable definition key: ' +
+ str(k))
+ return decl
+
+selectpattern = re.compile(
+ r'\s*(?P<this>(@\(@.*?@\)@|\*[\d*]+|\*\s*@\(@.*?@\)@|))(?P<after>.*)\Z', re.I)
+typedefpattern = re.compile(
+ r'(?:,(?P<attributes>[\w(),]+))?(::)?(?P<name>\b[a-z$_][\w$]*\b)'
+ r'(?:\((?P<params>[\w,]*)\))?\Z', re.I)
+nameargspattern = re.compile(
+ r'\s*(?P<name>\b[\w$]+\b)\s*(@\(@\s*(?P<args>[\w\s,]*)\s*@\)@|)\s*((result(\s*@\(@\s*(?P<result>\b[\w$]+\b)\s*@\)@|))|(bind\s*@\(@\s*(?P<bind>.*)\s*@\)@))*\s*\Z', re.I)
+operatorpattern = re.compile(
+ r'\s*(?P<scheme>(operator|assignment))'
+ r'@\(@\s*(?P<name>[^)]+)\s*@\)@\s*\Z', re.I)
+callnameargspattern = re.compile(
+ r'\s*(?P<name>\b[\w$]+\b)\s*@\(@\s*(?P<args>.*)\s*@\)@\s*\Z', re.I)
+real16pattern = re.compile(
+ r'([-+]?(?:\d+(?:\.\d*)?|\d*\.\d+))[dD]((?:[-+]?\d+)?)')
+real8pattern = re.compile(
+ r'([-+]?((?:\d+(?:\.\d*)?|\d*\.\d+))[eE]((?:[-+]?\d+)?)|(\d+\.\d*))')
+
+_intentcallbackpattern = re.compile(r'intent\s*\(.*?\bcallback\b', re.I)
+
+
+def _is_intent_callback(vdecl):
+ for a in vdecl.get('attrspec', []):
+ if _intentcallbackpattern.match(a):
+ return 1
+ return 0
+
+
+def _resolvetypedefpattern(line):
+ line = ''.join(line.split()) # removes whitespace
+ m1 = typedefpattern.match(line)
+ print(line, m1)
+ if m1:
+ attrs = m1.group('attributes')
+ attrs = [a.lower() for a in attrs.split(',')] if attrs else []
+ return m1.group('name'), attrs, m1.group('params')
+ return None, [], None
+
+
+def _resolvenameargspattern(line):
+ line = markouterparen(line)
+ m1 = nameargspattern.match(line)
+ if m1:
+ return m1.group('name'), m1.group('args'), m1.group('result'), m1.group('bind')
+ m1 = operatorpattern.match(line)
+ if m1:
+ name = m1.group('scheme') + '(' + m1.group('name') + ')'
+ return name, [], None, None
+ m1 = callnameargspattern.match(line)
+ if m1:
+ return m1.group('name'), m1.group('args'), None, None
+ return None, [], None, None
+
+
+def analyzeline(m, case, line):
+ global groupcounter, groupname, groupcache, grouplist, filepositiontext
+ global currentfilename, f77modulename, neededinterface, neededmodule
+ global expectbegin, gotnextfile, previous_context
+
+ block = m.group('this')
+ if case != 'multiline':
+ previous_context = None
+ if expectbegin and case not in ['begin', 'call', 'callfun', 'type'] \
+ and not skipemptyends and groupcounter < 1:
+ newname = os.path.basename(currentfilename).split('.')[0]
+ outmess(
+ 'analyzeline: no group yet. Creating program group with name "%s".\n' % newname)
+ gotnextfile = 0
+ groupcounter = groupcounter + 1
+ groupname[groupcounter] = 'program'
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcache[groupcounter]['block'] = 'program'
+ groupcache[groupcounter]['name'] = newname
+ groupcache[groupcounter]['from'] = 'fromsky'
+ expectbegin = 0
+ if case in ['begin', 'call', 'callfun']:
+ # Crack line => block,name,args,result
+ block = block.lower()
+ if re.match(r'block\s*data', block, re.I):
+ block = 'block data'
+ elif re.match(r'python\s*module', block, re.I):
+ block = 'python module'
+ elif re.match(r'abstract\s*interface', block, re.I):
+ block = 'abstract interface'
+ if block == 'type':
+ name, attrs, _ = _resolvetypedefpattern(m.group('after'))
+ groupcache[groupcounter]['vars'][name] = dict(attrspec = attrs)
+ args = []
+ result = None
+ else:
+ name, args, result, _ = _resolvenameargspattern(m.group('after'))
+ if name is None:
+ if block == 'block data':
+ name = '_BLOCK_DATA_'
+ else:
+ name = ''
+ if block not in ['interface', 'block data', 'abstract interface']:
+ outmess('analyzeline: No name/args pattern found for line.\n')
+
+ previous_context = (block, name, groupcounter)
+ if args:
+ args = rmbadname([x.strip()
+ for x in markoutercomma(args).split('@,@')])
+ else:
+ args = []
+ if '' in args:
+ while '' in args:
+ args.remove('')
+ outmess(
+ 'analyzeline: argument list is malformed (missing argument).\n')
+
+ # end of crack line => block,name,args,result
+ needmodule = 0
+ needinterface = 0
+
+ if case in ['call', 'callfun']:
+ needinterface = 1
+ if 'args' not in groupcache[groupcounter]:
+ return
+ if name not in groupcache[groupcounter]['args']:
+ return
+ for it in grouplist[groupcounter]:
+ if it['name'] == name:
+ return
+ if name in groupcache[groupcounter]['interfaced']:
+ return
+ block = {'call': 'subroutine', 'callfun': 'function'}[case]
+ if f77modulename and neededmodule == -1 and groupcounter <= 1:
+ neededmodule = groupcounter + 2
+ needmodule = 1
+ if block not in ['interface', 'abstract interface']:
+ needinterface = 1
+ # Create new block(s)
+ groupcounter = groupcounter + 1
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ if needmodule:
+ if verbose > 1:
+ outmess('analyzeline: Creating module block %s\n' %
+ repr(f77modulename), 0)
+ groupname[groupcounter] = 'module'
+ groupcache[groupcounter]['block'] = 'python module'
+ groupcache[groupcounter]['name'] = f77modulename
+ groupcache[groupcounter]['from'] = ''
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['interfaced'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcounter = groupcounter + 1
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ if needinterface:
+ if verbose > 1:
+ outmess('analyzeline: Creating additional interface block (groupcounter=%s).\n' % (
+ groupcounter), 0)
+ groupname[groupcounter] = 'interface'
+ groupcache[groupcounter]['block'] = 'interface'
+ groupcache[groupcounter]['name'] = 'unknown_interface'
+ groupcache[groupcounter]['from'] = '%s:%s' % (
+ groupcache[groupcounter - 1]['from'], groupcache[groupcounter - 1]['name'])
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['interfaced'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcounter = groupcounter + 1
+ groupcache[groupcounter] = {}
+ grouplist[groupcounter] = []
+ groupname[groupcounter] = block
+ groupcache[groupcounter]['block'] = block
+ if not name:
+ name = 'unknown_' + block.replace(' ', '_')
+ groupcache[groupcounter]['prefix'] = m.group('before')
+ groupcache[groupcounter]['name'] = rmbadname1(name)
+ groupcache[groupcounter]['result'] = result
+ if groupcounter == 1:
+ groupcache[groupcounter]['from'] = currentfilename
+ else:
+ if f77modulename and groupcounter == 3:
+ groupcache[groupcounter]['from'] = '%s:%s' % (
+ groupcache[groupcounter - 1]['from'], currentfilename)
+ else:
+ groupcache[groupcounter]['from'] = '%s:%s' % (
+ groupcache[groupcounter - 1]['from'], groupcache[groupcounter - 1]['name'])
+ for k in list(groupcache[groupcounter].keys()):
+ if not groupcache[groupcounter][k]:
+ del groupcache[groupcounter][k]
+
+ groupcache[groupcounter]['args'] = args
+ groupcache[groupcounter]['body'] = []
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['interfaced'] = []
+ groupcache[groupcounter]['vars'] = {}
+ groupcache[groupcounter]['entry'] = {}
+ # end of creation
+ if block == 'type':
+ groupcache[groupcounter]['varnames'] = []
+
+ if case in ['call', 'callfun']: # set parents variables
+ if name not in groupcache[groupcounter - 2]['externals']:
+ groupcache[groupcounter - 2]['externals'].append(name)
+ groupcache[groupcounter]['vars'] = copy.deepcopy(
+ groupcache[groupcounter - 2]['vars'])
+ try:
+ del groupcache[groupcounter]['vars'][name][
+ groupcache[groupcounter]['vars'][name]['attrspec'].index('external')]
+ except Exception:
+ pass
+ if block in ['function', 'subroutine']: # set global attributes
+ try:
+ groupcache[groupcounter]['vars'][name] = appenddecl(
+ groupcache[groupcounter]['vars'][name], groupcache[groupcounter - 2]['vars'][''])
+ except Exception:
+ pass
+ if case == 'callfun': # return type
+ if result and result in groupcache[groupcounter]['vars']:
+ if not name == result:
+ groupcache[groupcounter]['vars'][name] = appenddecl(
+ groupcache[groupcounter]['vars'][name], groupcache[groupcounter]['vars'][result])
+ # if groupcounter>1: # name is interfaced
+ try:
+ groupcache[groupcounter - 2]['interfaced'].append(name)
+ except Exception:
+ pass
+ if block == 'function':
+ t = typespattern[0].match(m.group('before') + ' ' + name)
+ if t:
+ typespec, selector, attr, edecl = cracktypespec0(
+ t.group('this'), t.group('after'))
+ updatevars(typespec, selector, attr, edecl)
+
+ if case in ['call', 'callfun']:
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end routine
+ grouplist[groupcounter - 1].append(groupcache[groupcounter])
+ grouplist[groupcounter - 1][-1]['body'] = grouplist[groupcounter]
+ del grouplist[groupcounter]
+ groupcounter = groupcounter - 1 # end interface
+
+ elif case == 'entry':
+ name, args, result, bind = _resolvenameargspattern(m.group('after'))
+ if name is not None:
+ if args:
+ args = rmbadname([x.strip()
+ for x in markoutercomma(args).split('@,@')])
+ else:
+ args = []
+ assert result is None, repr(result)
+ groupcache[groupcounter]['entry'][name] = args
+ previous_context = ('entry', name, groupcounter)
+ elif case == 'type':
+ typespec, selector, attr, edecl = cracktypespec0(
+ block, m.group('after'))
+ last_name = updatevars(typespec, selector, attr, edecl)
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrinsic']:
+ edecl = groupcache[groupcounter]['vars']
+ ll = m.group('after').strip()
+ i = ll.find('::')
+ if i < 0 and case == 'intent':
+ i = markouterparen(ll).find('@)@') - 2
+ ll = ll[:i + 1] + '::' + ll[i + 1:]
+ i = ll.find('::')
+ if ll[i:] == '::' and 'args' in groupcache[groupcounter]:
+ outmess('All arguments will have attribute %s%s\n' %
+ (m.group('this'), ll[:i]))
+ ll = ll + ','.join(groupcache[groupcounter]['args'])
+ if i < 0:
+ i = 0
+ pl = ''
+ else:
+ pl = ll[:i].strip()
+ ll = ll[i + 2:]
+ ch = markoutercomma(pl).split('@,@')
+ if len(ch) > 1:
+ pl = ch[0]
+ outmess('analyzeline: cannot handle multiple attributes without type specification. Ignoring %r.\n' % (
+ ','.join(ch[1:])))
+ last_name = None
+
+ for e in [x.strip() for x in markoutercomma(ll).split('@,@')]:
+ m1 = namepattern.match(e)
+ if not m1:
+ if case in ['public', 'private']:
+ k = ''
+ else:
+ print(m.groupdict())
+ outmess('analyzeline: no name pattern found in %s statement for %s. Skipping.\n' % (
+ case, repr(e)))
+ continue
+ else:
+ k = rmbadname1(m1.group('name'))
+ if case in ['public', 'private'] and \
+ (k == 'operator' or k == 'assignment'):
+ k += m1.group('after')
+ if k not in edecl:
+ edecl[k] = {}
+ if case == 'dimension':
+ ap = case + m1.group('after')
+ if case == 'intent':
+ ap = m.group('this') + pl
+ if _intentcallbackpattern.match(ap):
+ if k not in groupcache[groupcounter]['args']:
+ if groupcounter > 1:
+ if '__user__' not in groupcache[groupcounter - 2]['name']:
+ outmess(
+ 'analyzeline: missing __user__ module (could be nothing)\n')
+ # fixes ticket 1693
+ if k != groupcache[groupcounter]['name']:
+ outmess('analyzeline: appending intent(callback) %s'
+ ' to %s arguments\n' % (k, groupcache[groupcounter]['name']))
+ groupcache[groupcounter]['args'].append(k)
+ else:
+ errmess(
+ 'analyzeline: intent(callback) %s is ignored\n' % (k))
+ else:
+ errmess('analyzeline: intent(callback) %s is already'
+ ' in argument list\n' % (k))
+ if case in ['optional', 'required', 'public', 'external', 'private', 'intrinsic']:
+ ap = case
+ if 'attrspec' in edecl[k]:
+ edecl[k]['attrspec'].append(ap)
+ else:
+ edecl[k]['attrspec'] = [ap]
+ if case == 'external':
+ if groupcache[groupcounter]['block'] == 'program':
+ outmess('analyzeline: ignoring program arguments\n')
+ continue
+ if k not in groupcache[groupcounter]['args']:
+ continue
+ if 'externals' not in groupcache[groupcounter]:
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['externals'].append(k)
+ last_name = k
+ groupcache[groupcounter]['vars'] = edecl
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case == 'moduleprocedure':
+ groupcache[groupcounter]['implementedby'] = \
+ [x.strip() for x in m.group('after').split(',')]
+ elif case == 'parameter':
+ edecl = groupcache[groupcounter]['vars']
+ ll = m.group('after').strip()[1:-1]
+ last_name = None
+ for e in markoutercomma(ll).split('@,@'):
+ try:
+ k, initexpr = [x.strip() for x in e.split('=')]
+ except Exception:
+ outmess(
+ 'analyzeline: could not extract name,expr in parameter statement "%s" of "%s"\n' % (e, ll))
+ continue
+ params = get_parameters(edecl)
+ k = rmbadname1(k)
+ if k not in edecl:
+ edecl[k] = {}
+ if '=' in edecl[k] and (not edecl[k]['='] == initexpr):
+ outmess('analyzeline: Overwriting the value of parameter "%s" ("%s") with "%s".\n' % (
+ k, edecl[k]['='], initexpr))
+ t = determineexprtype(initexpr, params)
+ if t:
+ if t.get('typespec') == 'real':
+ tt = list(initexpr)
+ for m in real16pattern.finditer(initexpr):
+ tt[m.start():m.end()] = list(
+ initexpr[m.start():m.end()].lower().replace('d', 'e'))
+ initexpr = ''.join(tt)
+ elif t.get('typespec') == 'complex':
+ initexpr = initexpr[1:].lower().replace('d', 'e').\
+ replace(',', '+1j*(')
+ try:
+ v = eval(initexpr, {}, params)
+ except (SyntaxError, NameError, TypeError) as msg:
+ errmess('analyzeline: Failed to evaluate %r. Ignoring: %s\n'
+ % (initexpr, msg))
+ continue
+ edecl[k]['='] = repr(v)
+ if 'attrspec' in edecl[k]:
+ edecl[k]['attrspec'].append('parameter')
+ else:
+ edecl[k]['attrspec'] = ['parameter']
+ last_name = k
+ groupcache[groupcounter]['vars'] = edecl
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case == 'implicit':
+ if m.group('after').strip().lower() == 'none':
+ groupcache[groupcounter]['implicit'] = None
+ elif m.group('after'):
+ if 'implicit' in groupcache[groupcounter]:
+ impl = groupcache[groupcounter]['implicit']
+ else:
+ impl = {}
+ if impl is None:
+ outmess(
+ 'analyzeline: Overwriting earlier "implicit none" statement.\n')
+ impl = {}
+ for e in markoutercomma(m.group('after')).split('@,@'):
+ decl = {}
+ m1 = re.match(
+ r'\s*(?P<this>.*?)\s*(\(\s*(?P<after>[a-z-, ]+)\s*\)\s*|)\Z', e, re.I)
+ if not m1:
+ outmess(
+ 'analyzeline: could not extract info of implicit statement part "%s"\n' % (e))
+ continue
+ m2 = typespattern4implicit.match(m1.group('this'))
+ if not m2:
+ outmess(
+ 'analyzeline: could not extract types pattern of implicit statement part "%s"\n' % (e))
+ continue
+ typespec, selector, attr, edecl = cracktypespec0(
+ m2.group('this'), m2.group('after'))
+ kindselect, charselect, typename = cracktypespec(
+ typespec, selector)
+ decl['typespec'] = typespec
+ decl['kindselector'] = kindselect
+ decl['charselector'] = charselect
+ decl['typename'] = typename
+ for k in list(decl.keys()):
+ if not decl[k]:
+ del decl[k]
+ for r in markoutercomma(m1.group('after')).split('@,@'):
+ if '-' in r:
+ try:
+ begc, endc = [x.strip() for x in r.split('-')]
+ except Exception:
+ outmess(
+ 'analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement\n' % r)
+ continue
+ else:
+ begc = endc = r.strip()
+ if not len(begc) == len(endc) == 1:
+ outmess(
+ 'analyzeline: expected "<char>-<char>" instead of "%s" in range list of implicit statement (2)\n' % r)
+ continue
+ for o in range(ord(begc), ord(endc) + 1):
+ impl[chr(o)] = decl
+ groupcache[groupcounter]['implicit'] = impl
+ elif case == 'data':
+ ll = []
+ dl = ''
+ il = ''
+ f = 0
+ fc = 1
+ inp = 0
+ for c in m.group('after'):
+ if not inp:
+ if c == "'":
+ fc = not fc
+ if c == '/' and fc:
+ f = f + 1
+ continue
+ if c == '(':
+ inp = inp + 1
+ elif c == ')':
+ inp = inp - 1
+ if f == 0:
+ dl = dl + c
+ elif f == 1:
+ il = il + c
+ elif f == 2:
+ dl = dl.strip()
+ if dl.startswith(','):
+ dl = dl[1:].strip()
+ ll.append([dl, il])
+ dl = c
+ il = ''
+ f = 0
+ if f == 2:
+ dl = dl.strip()
+ if dl.startswith(','):
+ dl = dl[1:].strip()
+ ll.append([dl, il])
+ vars = {}
+ if 'vars' in groupcache[groupcounter]:
+ vars = groupcache[groupcounter]['vars']
+ last_name = None
+ for l in ll:
+ l = [x.strip() for x in l]
+ if l[0][0] == ',':
+ l[0] = l[0][1:]
+ if l[0][0] == '(':
+ outmess(
+ 'analyzeline: implied-DO list "%s" is not supported. Skipping.\n' % l[0])
+ continue
+ i = 0
+ j = 0
+ llen = len(l[1])
+ for v in rmbadname([x.strip() for x in markoutercomma(l[0]).split('@,@')]):
+ if v[0] == '(':
+ outmess(
+ 'analyzeline: implied-DO list "%s" is not supported. Skipping.\n' % v)
+ # XXX: subsequent init expressions may get wrong values.
+ # Ignoring since data statements are irrelevant for
+ # wrapping.
+ continue
+ fc = 0
+ while (i < llen) and (fc or not l[1][i] == ','):
+ if l[1][i] == "'":
+ fc = not fc
+ i = i + 1
+ i = i + 1
+ if v not in vars:
+ vars[v] = {}
+ if '=' in vars[v] and not vars[v]['='] == l[1][j:i - 1]:
+ outmess('analyzeline: changing init expression of "%s" ("%s") to "%s"\n' % (
+ v, vars[v]['='], l[1][j:i - 1]))
+ vars[v]['='] = l[1][j:i - 1]
+ j = i
+ last_name = v
+ groupcache[groupcounter]['vars'] = vars
+ if last_name is not None:
+ previous_context = ('variable', last_name, groupcounter)
+ elif case == 'common':
+ line = m.group('after').strip()
+ if not line[0] == '/':
+ line = '//' + line
+ cl = []
+ f = 0
+ bn = ''
+ ol = ''
+ for c in line:
+ if c == '/':
+ f = f + 1
+ continue
+ if f >= 3:
+ bn = bn.strip()
+ if not bn:
+ bn = '_BLNK_'
+ cl.append([bn, ol])
+ f = f - 2
+ bn = ''
+ ol = ''
+ if f % 2:
+ bn = bn + c
+ else:
+ ol = ol + c
+ bn = bn.strip()
+ if not bn:
+ bn = '_BLNK_'
+ cl.append([bn, ol])
+ commonkey = {}
+ if 'common' in groupcache[groupcounter]:
+ commonkey = groupcache[groupcounter]['common']
+ for c in cl:
+ if c[0] not in commonkey:
+ commonkey[c[0]] = []
+ for i in [x.strip() for x in markoutercomma(c[1]).split('@,@')]:
+ if i:
+ commonkey[c[0]].append(i)
+ groupcache[groupcounter]['common'] = commonkey
+ previous_context = ('common', bn, groupcounter)
+ elif case == 'use':
+ m1 = re.match(
+ r'\A\s*(?P<name>\b\w+\b)\s*((,(\s*\bonly\b\s*:|(?P<notonly>))\s*(?P<list>.*))|)\s*\Z', m.group('after'), re.I)
+ if m1:
+ mm = m1.groupdict()
+ if 'use' not in groupcache[groupcounter]:
+ groupcache[groupcounter]['use'] = {}
+ name = m1.group('name')
+ groupcache[groupcounter]['use'][name] = {}
+ isonly = 0
+ if 'list' in mm and mm['list'] is not None:
+ if 'notonly' in mm and mm['notonly'] is None:
+ isonly = 1
+ groupcache[groupcounter]['use'][name]['only'] = isonly
+ ll = [x.strip() for x in mm['list'].split(',')]
+ rl = {}
+ for l in ll:
+ if '=' in l:
+ m2 = re.match(
+ r'\A\s*(?P<local>\b\w+\b)\s*=\s*>\s*(?P<use>\b\w+\b)\s*\Z', l, re.I)
+ if m2:
+ rl[m2.group('local').strip()] = m2.group(
+ 'use').strip()
+ else:
+ outmess(
+ 'analyzeline: Not local=>use pattern found in %s\n' % repr(l))
+ else:
+ rl[l] = l
+ groupcache[groupcounter]['use'][name]['map'] = rl
+ else:
+ pass
+ else:
+ print(m.groupdict())
+ outmess('analyzeline: Could not crack the use statement.\n')
+ elif case in ['f2pyenhancements']:
+ if 'f2pyenhancements' not in groupcache[groupcounter]:
+ groupcache[groupcounter]['f2pyenhancements'] = {}
+ d = groupcache[groupcounter]['f2pyenhancements']
+ if m.group('this') == 'usercode' and 'usercode' in d:
+ if isinstance(d['usercode'], str):
+ d['usercode'] = [d['usercode']]
+ d['usercode'].append(m.group('after'))
+ else:
+ d[m.group('this')] = m.group('after')
+ elif case == 'multiline':
+ if previous_context is None:
+ if verbose:
+ outmess('analyzeline: No context for multiline block.\n')
+ return
+ gc = groupcounter
+ appendmultiline(groupcache[gc],
+ previous_context[:2],
+ m.group('this'))
+ else:
+ if verbose > 1:
+ print(m.groupdict())
+ outmess('analyzeline: No code implemented for line.\n')
+
+
+def appendmultiline(group, context_name, ml):
+ if 'f2pymultilines' not in group:
+ group['f2pymultilines'] = {}
+ d = group['f2pymultilines']
+ if context_name not in d:
+ d[context_name] = []
+ d[context_name].append(ml)
+ return
+
+
+def cracktypespec0(typespec, ll):
+ selector = None
+ attr = None
+ if re.match(r'double\s*complex', typespec, re.I):
+ typespec = 'double complex'
+ elif re.match(r'double\s*precision', typespec, re.I):
+ typespec = 'double precision'
+ else:
+ typespec = typespec.strip().lower()
+ m1 = selectpattern.match(markouterparen(ll))
+ if not m1:
+ outmess(
+ 'cracktypespec0: no kind/char_selector pattern found for line.\n')
+ return
+ d = m1.groupdict()
+ for k in list(d.keys()):
+ d[k] = unmarkouterparen(d[k])
+ if typespec in ['complex', 'integer', 'logical', 'real', 'character', 'type']:
+ selector = d['this']
+ ll = d['after']
+ i = ll.find('::')
+ if i >= 0:
+ attr = ll[:i].strip()
+ ll = ll[i + 2:]
+ return typespec, selector, attr, ll
+#####
+namepattern = re.compile(r'\s*(?P<name>\b\w+\b)\s*(?P<after>.*)\s*\Z', re.I)
+kindselector = re.compile(
+ r'\s*(\(\s*(kind\s*=)?\s*(?P<kind>.*)\s*\)|\*\s*(?P<kind2>.*?))\s*\Z', re.I)
+charselector = re.compile(
+ r'\s*(\((?P<lenkind>.*)\)|\*\s*(?P<charlen>.*))\s*\Z', re.I)
+lenkindpattern = re.compile(
+ r'\s*(kind\s*=\s*(?P<kind>.*?)\s*(@,@\s*len\s*=\s*(?P<len>.*)|)'
+ r'|(len\s*=\s*|)(?P<len2>.*?)\s*(@,@\s*(kind\s*=\s*|)(?P<kind2>.*)'
+ r'|(f2py_len\s*=\s*(?P<f2py_len>.*))|))\s*\Z', re.I)
+lenarraypattern = re.compile(
+ r'\s*(@\(@\s*(?!/)\s*(?P<array>.*?)\s*@\)@\s*\*\s*(?P<len>.*?)|(\*\s*(?P<len2>.*?)|)\s*(@\(@\s*(?!/)\s*(?P<array2>.*?)\s*@\)@|))\s*(=\s*(?P<init>.*?)|(@\(@|)/\s*(?P<init2>.*?)\s*/(@\)@|)|)\s*\Z', re.I)
+
+
+def removespaces(expr):
+ expr = expr.strip()
+ if len(expr) <= 1:
+ return expr
+ expr2 = expr[0]
+ for i in range(1, len(expr) - 1):
+ if (expr[i] == ' ' and
+ ((expr[i + 1] in "()[]{}=+-/* ") or
+ (expr[i - 1] in "()[]{}=+-/* "))):
+ continue
+ expr2 = expr2 + expr[i]
+ expr2 = expr2 + expr[-1]
+ return expr2
+
+
+def markinnerspaces(line):
+ """
+ The function replace all spaces in the input variable line which are
+ surrounded with quotation marks, with the triplet "@_@".
+
+ For instance, for the input "a 'b c'" the function returns "a 'b@_@c'"
+
+ Parameters
+ ----------
+ line : str
+
+ Returns
+ -------
+ str
+
+ """
+ fragment = ''
+ inside = False
+ current_quote = None
+ escaped = ''
+ for c in line:
+ if escaped == '\\' and c in ['\\', '\'', '"']:
+ fragment += c
+ escaped = c
+ continue
+ if not inside and c in ['\'', '"']:
+ current_quote = c
+ if c == current_quote:
+ inside = not inside
+ elif c == ' ' and inside:
+ fragment += '@_@'
+ continue
+ fragment += c
+ escaped = c # reset to non-backslash
+ return fragment
+
+
+def updatevars(typespec, selector, attrspec, entitydecl):
+ global groupcache, groupcounter
+
+ last_name = None
+ kindselect, charselect, typename = cracktypespec(typespec, selector)
+ if attrspec:
+ attrspec = [x.strip() for x in markoutercomma(attrspec).split('@,@')]
+ l = []
+ c = re.compile(r'(?P<start>[a-zA-Z]+)')
+ for a in attrspec:
+ if not a:
+ continue
+ m = c.match(a)
+ if m:
+ s = m.group('start').lower()
+ a = s + a[len(s):]
+ l.append(a)
+ attrspec = l
+ el = [x.strip() for x in markoutercomma(entitydecl).split('@,@')]
+ el1 = []
+ for e in el:
+ for e1 in [x.strip() for x in markoutercomma(removespaces(markinnerspaces(e)), comma=' ').split('@ @')]:
+ if e1:
+ el1.append(e1.replace('@_@', ' '))
+ for e in el1:
+ m = namepattern.match(e)
+ if not m:
+ outmess(
+ 'updatevars: no name pattern found for entity=%s. Skipping.\n' % (repr(e)))
+ continue
+ ename = rmbadname1(m.group('name'))
+ edecl = {}
+ if ename in groupcache[groupcounter]['vars']:
+ edecl = groupcache[groupcounter]['vars'][ename].copy()
+ not_has_typespec = 'typespec' not in edecl
+ if not_has_typespec:
+ edecl['typespec'] = typespec
+ elif typespec and (not typespec == edecl['typespec']):
+ outmess('updatevars: attempt to change the type of "%s" ("%s") to "%s". Ignoring.\n' % (
+ ename, edecl['typespec'], typespec))
+ if 'kindselector' not in edecl:
+ edecl['kindselector'] = copy.copy(kindselect)
+ elif kindselect:
+ for k in list(kindselect.keys()):
+ if k in edecl['kindselector'] and (not kindselect[k] == edecl['kindselector'][k]):
+ outmess('updatevars: attempt to change the kindselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (
+ k, ename, edecl['kindselector'][k], kindselect[k]))
+ else:
+ edecl['kindselector'][k] = copy.copy(kindselect[k])
+ if 'charselector' not in edecl and charselect:
+ if not_has_typespec:
+ edecl['charselector'] = charselect
+ else:
+ errmess('updatevars:%s: attempt to change empty charselector to %r. Ignoring.\n'
+ % (ename, charselect))
+ elif charselect:
+ for k in list(charselect.keys()):
+ if k in edecl['charselector'] and (not charselect[k] == edecl['charselector'][k]):
+ outmess('updatevars: attempt to change the charselector "%s" of "%s" ("%s") to "%s". Ignoring.\n' % (
+ k, ename, edecl['charselector'][k], charselect[k]))
+ else:
+ edecl['charselector'][k] = copy.copy(charselect[k])
+ if 'typename' not in edecl:
+ edecl['typename'] = typename
+ elif typename and (not edecl['typename'] == typename):
+ outmess('updatevars: attempt to change the typename of "%s" ("%s") to "%s". Ignoring.\n' % (
+ ename, edecl['typename'], typename))
+ if 'attrspec' not in edecl:
+ edecl['attrspec'] = copy.copy(attrspec)
+ elif attrspec:
+ for a in attrspec:
+ if a not in edecl['attrspec']:
+ edecl['attrspec'].append(a)
+ else:
+ edecl['typespec'] = copy.copy(typespec)
+ edecl['kindselector'] = copy.copy(kindselect)
+ edecl['charselector'] = copy.copy(charselect)
+ edecl['typename'] = typename
+ edecl['attrspec'] = copy.copy(attrspec)
+ if 'external' in (edecl.get('attrspec') or []) and e in groupcache[groupcounter]['args']:
+ if 'externals' not in groupcache[groupcounter]:
+ groupcache[groupcounter]['externals'] = []
+ groupcache[groupcounter]['externals'].append(e)
+ if m.group('after'):
+ m1 = lenarraypattern.match(markouterparen(m.group('after')))
+ if m1:
+ d1 = m1.groupdict()
+ for lk in ['len', 'array', 'init']:
+ if d1[lk + '2'] is not None:
+ d1[lk] = d1[lk + '2']
+ del d1[lk + '2']
+ for k in list(d1.keys()):
+ if d1[k] is not None:
+ d1[k] = unmarkouterparen(d1[k])
+ else:
+ del d1[k]
+
+ if 'len' in d1:
+ if typespec in ['complex', 'integer', 'logical', 'real']:
+ if ('kindselector' not in edecl) or (not edecl['kindselector']):
+ edecl['kindselector'] = {}
+ edecl['kindselector']['*'] = d1['len']
+ del d1['len']
+ elif typespec == 'character':
+ if ('charselector' not in edecl) or (not edecl['charselector']):
+ edecl['charselector'] = {}
+ if 'len' in edecl['charselector']:
+ del edecl['charselector']['len']
+ edecl['charselector']['*'] = d1['len']
+ del d1['len']
+
+ if 'init' in d1:
+ if '=' in edecl and (not edecl['='] == d1['init']):
+ outmess('updatevars: attempt to change the init expression of "%s" ("%s") to "%s". Ignoring.\n' % (
+ ename, edecl['='], d1['init']))
+ else:
+ edecl['='] = d1['init']
+
+ if 'len' in d1 and 'array' in d1:
+ if d1['len'] == '':
+ d1['len'] = d1['array']
+ del d1['array']
+ else:
+ d1['array'] = d1['array'] + ',' + d1['len']
+ del d1['len']
+ errmess('updatevars: "%s %s" is mapped to "%s %s(%s)"\n' % (
+ typespec, e, typespec, ename, d1['array']))
+
+ if 'array' in d1:
+ dm = 'dimension(%s)' % d1['array']
+ if 'attrspec' not in edecl or (not edecl['attrspec']):
+ edecl['attrspec'] = [dm]
+ else:
+ edecl['attrspec'].append(dm)
+ for dm1 in edecl['attrspec']:
+ if dm1[:9] == 'dimension' and dm1 != dm:
+ del edecl['attrspec'][-1]
+ errmess('updatevars:%s: attempt to change %r to %r. Ignoring.\n'
+ % (ename, dm1, dm))
+ break
+
+ else:
+ outmess('updatevars: could not crack entity declaration "%s". Ignoring.\n' % (
+ ename + m.group('after')))
+ for k in list(edecl.keys()):
+ if not edecl[k]:
+ del edecl[k]
+ groupcache[groupcounter]['vars'][ename] = edecl
+ if 'varnames' in groupcache[groupcounter]:
+ groupcache[groupcounter]['varnames'].append(ename)
+ last_name = ename
+ return last_name
+
+
+def cracktypespec(typespec, selector):
+ kindselect = None
+ charselect = None
+ typename = None
+ if selector:
+ if typespec in ['complex', 'integer', 'logical', 'real']:
+ kindselect = kindselector.match(selector)
+ if not kindselect:
+ outmess(
+ 'cracktypespec: no kindselector pattern found for %s\n' % (repr(selector)))
+ return
+ kindselect = kindselect.groupdict()
+ kindselect['*'] = kindselect['kind2']
+ del kindselect['kind2']
+ for k in list(kindselect.keys()):
+ if not kindselect[k]:
+ del kindselect[k]
+ for k, i in list(kindselect.items()):
+ kindselect[k] = rmbadname1(i)
+ elif typespec == 'character':
+ charselect = charselector.match(selector)
+ if not charselect:
+ outmess(
+ 'cracktypespec: no charselector pattern found for %s\n' % (repr(selector)))
+ return
+ charselect = charselect.groupdict()
+ charselect['*'] = charselect['charlen']
+ del charselect['charlen']
+ if charselect['lenkind']:
+ lenkind = lenkindpattern.match(
+ markoutercomma(charselect['lenkind']))
+ lenkind = lenkind.groupdict()
+ for lk in ['len', 'kind']:
+ if lenkind[lk + '2']:
+ lenkind[lk] = lenkind[lk + '2']
+ charselect[lk] = lenkind[lk]
+ del lenkind[lk + '2']
+ if lenkind['f2py_len'] is not None:
+ # used to specify the length of assumed length strings
+ charselect['f2py_len'] = lenkind['f2py_len']
+ del charselect['lenkind']
+ for k in list(charselect.keys()):
+ if not charselect[k]:
+ del charselect[k]
+ for k, i in list(charselect.items()):
+ charselect[k] = rmbadname1(i)
+ elif typespec == 'type':
+ typename = re.match(r'\s*\(\s*(?P<name>\w+)\s*\)', selector, re.I)
+ if typename:
+ typename = typename.group('name')
+ else:
+ outmess('cracktypespec: no typename found in %s\n' %
+ (repr(typespec + selector)))
+ else:
+ outmess('cracktypespec: no selector used for %s\n' %
+ (repr(selector)))
+ return kindselect, charselect, typename
+######
+
+
+def setattrspec(decl, attr, force=0):
+ if not decl:
+ decl = {}
+ if not attr:
+ return decl
+ if 'attrspec' not in decl:
+ decl['attrspec'] = [attr]
+ return decl
+ if force:
+ decl['attrspec'].append(attr)
+ if attr in decl['attrspec']:
+ return decl
+ if attr == 'static' and 'automatic' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ elif attr == 'automatic' and 'static' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ elif attr == 'public':
+ if 'private' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ elif attr == 'private':
+ if 'public' not in decl['attrspec']:
+ decl['attrspec'].append(attr)
+ else:
+ decl['attrspec'].append(attr)
+ return decl
+
+
+def setkindselector(decl, sel, force=0):
+ if not decl:
+ decl = {}
+ if not sel:
+ return decl
+ if 'kindselector' not in decl:
+ decl['kindselector'] = sel
+ return decl
+ for k in list(sel.keys()):
+ if force or k not in decl['kindselector']:
+ decl['kindselector'][k] = sel[k]
+ return decl
+
+
+def setcharselector(decl, sel, force=0):
+ if not decl:
+ decl = {}
+ if not sel:
+ return decl
+ if 'charselector' not in decl:
+ decl['charselector'] = sel
+ return decl
+
+ for k in list(sel.keys()):
+ if force or k not in decl['charselector']:
+ decl['charselector'][k] = sel[k]
+ return decl
+
+
+def getblockname(block, unknown='unknown'):
+ if 'name' in block:
+ return block['name']
+ return unknown
+
+# post processing
+
+
+def setmesstext(block):
+ global filepositiontext
+
+ try:
+ filepositiontext = 'In: %s:%s\n' % (block['from'], block['name'])
+ except Exception:
+ pass
+
+
+def get_usedict(block):
+ usedict = {}
+ if 'parent_block' in block:
+ usedict = get_usedict(block['parent_block'])
+ if 'use' in block:
+ usedict.update(block['use'])
+ return usedict
+
+
+def get_useparameters(block, param_map=None):
+ global f90modulevars
+
+ if param_map is None:
+ param_map = {}
+ usedict = get_usedict(block)
+ if not usedict:
+ return param_map
+ for usename, mapping in list(usedict.items()):
+ usename = usename.lower()
+ if usename not in f90modulevars:
+ outmess('get_useparameters: no module %s info used by %s\n' %
+ (usename, block.get('name')))
+ continue
+ mvars = f90modulevars[usename]
+ params = get_parameters(mvars)
+ if not params:
+ continue
+ # XXX: apply mapping
+ if mapping:
+ errmess('get_useparameters: mapping for %s not impl.\n' % (mapping))
+ for k, v in list(params.items()):
+ if k in param_map:
+ outmess('get_useparameters: overriding parameter %s with'
+ ' value from module %s\n' % (repr(k), repr(usename)))
+ param_map[k] = v
+
+ return param_map
+
+
+def postcrack2(block, tab='', param_map=None):
+ global f90modulevars
+
+ if not f90modulevars:
+ return block
+ if isinstance(block, list):
+ ret = [postcrack2(g, tab=tab + '\t', param_map=param_map)
+ for g in block]
+ return ret
+ setmesstext(block)
+ outmess('%sBlock: %s\n' % (tab, block['name']), 0)
+
+ if param_map is None:
+ param_map = get_useparameters(block)
+
+ if param_map is not None and 'vars' in block:
+ vars = block['vars']
+ for n in list(vars.keys()):
+ var = vars[n]
+ if 'kindselector' in var:
+ kind = var['kindselector']
+ if 'kind' in kind:
+ val = kind['kind']
+ if val in param_map:
+ kind['kind'] = param_map[val]
+ new_body = [postcrack2(b, tab=tab + '\t', param_map=param_map)
+ for b in block['body']]
+ block['body'] = new_body
+
+ return block
+
+
+def postcrack(block, args=None, tab=''):
+ """
+ TODO:
+ function return values
+ determine expression types if in argument list
+ """
+ global usermodules, onlyfunctions
+
+ if isinstance(block, list):
+ gret = []
+ uret = []
+ for g in block:
+ setmesstext(g)
+ g = postcrack(g, tab=tab + '\t')
+ # sort user routines to appear first
+ if 'name' in g and '__user__' in g['name']:
+ uret.append(g)
+ else:
+ gret.append(g)
+ return uret + gret
+ setmesstext(block)
+ if not isinstance(block, dict) and 'block' not in block:
+ raise Exception('postcrack: Expected block dictionary instead of ' +
+ str(block))
+ if 'name' in block and not block['name'] == 'unknown_interface':
+ outmess('%sBlock: %s\n' % (tab, block['name']), 0)
+ block = analyzeargs(block)
+ block = analyzecommon(block)
+ block['vars'] = analyzevars(block)
+ block['sortvars'] = sortvarnames(block['vars'])
+ if 'args' in block and block['args']:
+ args = block['args']
+ block['body'] = analyzebody(block, args, tab=tab)
+
+ userisdefined = []
+ if 'use' in block:
+ useblock = block['use']
+ for k in list(useblock.keys()):
+ if '__user__' in k:
+ userisdefined.append(k)
+ else:
+ useblock = {}
+ name = ''
+ if 'name' in block:
+ name = block['name']
+ # and not userisdefined: # Build a __user__ module
+ if 'externals' in block and block['externals']:
+ interfaced = []
+ if 'interfaced' in block:
+ interfaced = block['interfaced']
+ mvars = copy.copy(block['vars'])
+ if name:
+ mname = name + '__user__routines'
+ else:
+ mname = 'unknown__user__routines'
+ if mname in userisdefined:
+ i = 1
+ while '%s_%i' % (mname, i) in userisdefined:
+ i = i + 1
+ mname = '%s_%i' % (mname, i)
+ interface = {'block': 'interface', 'body': [],
+ 'vars': {}, 'name': name + '_user_interface'}
+ for e in block['externals']:
+ if e in interfaced:
+ edef = []
+ j = -1
+ for b in block['body']:
+ j = j + 1
+ if b['block'] == 'interface':
+ i = -1
+ for bb in b['body']:
+ i = i + 1
+ if 'name' in bb and bb['name'] == e:
+ edef = copy.copy(bb)
+ del b['body'][i]
+ break
+ if edef:
+ if not b['body']:
+ del block['body'][j]
+ del interfaced[interfaced.index(e)]
+ break
+ interface['body'].append(edef)
+ else:
+ if e in mvars and not isexternal(mvars[e]):
+ interface['vars'][e] = mvars[e]
+ if interface['vars'] or interface['body']:
+ block['interfaced'] = interfaced
+ mblock = {'block': 'python module', 'body': [
+ interface], 'vars': {}, 'name': mname, 'interfaced': block['externals']}
+ useblock[mname] = {}
+ usermodules.append(mblock)
+ if useblock:
+ block['use'] = useblock
+ return block
+
+
+def sortvarnames(vars):
+ indep = []
+ dep = []
+ for v in list(vars.keys()):
+ if 'depend' in vars[v] and vars[v]['depend']:
+ dep.append(v)
+ else:
+ indep.append(v)
+ n = len(dep)
+ i = 0
+ while dep: # XXX: How to catch dependence cycles correctly?
+ v = dep[0]
+ fl = 0
+ for w in dep[1:]:
+ if w in vars[v]['depend']:
+ fl = 1
+ break
+ if fl:
+ dep = dep[1:] + [v]
+ i = i + 1
+ if i > n:
+ errmess('sortvarnames: failed to compute dependencies because'
+ ' of cyclic dependencies between '
+ + ', '.join(dep) + '\n')
+ indep = indep + dep
+ break
+ else:
+ indep.append(v)
+ dep = dep[1:]
+ n = len(dep)
+ i = 0
+ return indep
+
+
+def analyzecommon(block):
+ if not hascommon(block):
+ return block
+ commonvars = []
+ for k in list(block['common'].keys()):
+ comvars = []
+ for e in block['common'][k]:
+ m = re.match(
+ r'\A\s*\b(?P<name>.*?)\b\s*(\((?P<dims>.*?)\)|)\s*\Z', e, re.I)
+ if m:
+ dims = []
+ if m.group('dims'):
+ dims = [x.strip()
+ for x in markoutercomma(m.group('dims')).split('@,@')]
+ n = rmbadname1(m.group('name').strip())
+ if n in block['vars']:
+ if 'attrspec' in block['vars'][n]:
+ block['vars'][n]['attrspec'].append(
+ 'dimension(%s)' % (','.join(dims)))
+ else:
+ block['vars'][n]['attrspec'] = [
+ 'dimension(%s)' % (','.join(dims))]
+ else:
+ if dims:
+ block['vars'][n] = {
+ 'attrspec': ['dimension(%s)' % (','.join(dims))]}
+ else:
+ block['vars'][n] = {}
+ if n not in commonvars:
+ commonvars.append(n)
+ else:
+ n = e
+ errmess(
+ 'analyzecommon: failed to extract "<name>[(<dims>)]" from "%s" in common /%s/.\n' % (e, k))
+ comvars.append(n)
+ block['common'][k] = comvars
+ if 'commonvars' not in block:
+ block['commonvars'] = commonvars
+ else:
+ block['commonvars'] = block['commonvars'] + commonvars
+ return block
+
+
+def analyzebody(block, args, tab=''):
+ global usermodules, skipfuncs, onlyfuncs, f90modulevars
+
+ setmesstext(block)
+ body = []
+ for b in block['body']:
+ b['parent_block'] = block
+ if b['block'] in ['function', 'subroutine']:
+ if args is not None and b['name'] not in args:
+ continue
+ else:
+ as_ = b['args']
+ if b['name'] in skipfuncs:
+ continue
+ if onlyfuncs and b['name'] not in onlyfuncs:
+ continue
+ b['saved_interface'] = crack2fortrangen(
+ b, '\n' + ' ' * 6, as_interface=True)
+
+ else:
+ as_ = args
+ b = postcrack(b, as_, tab=tab + '\t')
+ if b['block'] in ['interface', 'abstract interface'] and \
+ not b['body'] and not b.get('implementedby'):
+ if 'f2pyenhancements' not in b:
+ continue
+ if b['block'].replace(' ', '') == 'pythonmodule':
+ usermodules.append(b)
+ else:
+ if b['block'] == 'module':
+ f90modulevars[b['name']] = b['vars']
+ body.append(b)
+ return body
+
+
+def buildimplicitrules(block):
+ setmesstext(block)
+ implicitrules = defaultimplicitrules
+ attrrules = {}
+ if 'implicit' in block:
+ if block['implicit'] is None:
+ implicitrules = None
+ if verbose > 1:
+ outmess(
+ 'buildimplicitrules: no implicit rules for routine %s.\n' % repr(block['name']))
+ else:
+ for k in list(block['implicit'].keys()):
+ if block['implicit'][k].get('typespec') not in ['static', 'automatic']:
+ implicitrules[k] = block['implicit'][k]
+ else:
+ attrrules[k] = block['implicit'][k]['typespec']
+ return implicitrules, attrrules
+
+
+def myeval(e, g=None, l=None):
+ """ Like `eval` but returns only integers and floats """
+ r = eval(e, g, l)
+ if type(r) in [int, float]:
+ return r
+ raise ValueError('r=%r' % (r))
+
+getlincoef_re_1 = re.compile(r'\A\b\w+\b\Z', re.I)
+
+
+def getlincoef(e, xset): # e = a*x+b ; x in xset
+ """
+ Obtain ``a`` and ``b`` when ``e == "a*x+b"``, where ``x`` is a symbol in
+ xset.
+
+ >>> getlincoef('2*x + 1', {'x'})
+ (2, 1, 'x')
+ >>> getlincoef('3*x + x*2 + 2 + 1', {'x'})
+ (5, 3, 'x')
+ >>> getlincoef('0', {'x'})
+ (0, 0, None)
+ >>> getlincoef('0*x', {'x'})
+ (0, 0, 'x')
+ >>> getlincoef('x*x', {'x'})
+ (None, None, None)
+
+ This can be tricked by sufficiently complex expressions
+
+ >>> getlincoef('(x - 0.5)*(x - 1.5)*(x - 1)*x + 2*x + 3', {'x'})
+ (2.0, 3.0, 'x')
+ """
+ try:
+ c = int(myeval(e, {}, {}))
+ return 0, c, None
+ except Exception:
+ pass
+ if getlincoef_re_1.match(e):
+ return 1, 0, e
+ len_e = len(e)
+ for x in xset:
+ if len(x) > len_e:
+ continue
+ if re.search(r'\w\s*\([^)]*\b' + x + r'\b', e):
+ # skip function calls having x as an argument, e.g max(1, x)
+ continue
+ re_1 = re.compile(r'(?P<before>.*?)\b' + x + r'\b(?P<after>.*)', re.I)
+ m = re_1.match(e)
+ if m:
+ try:
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s' % (
+ m1.group('before'), 0, m1.group('after'))
+ m1 = re_1.match(ee)
+ b = myeval(ee, {}, {})
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s' % (
+ m1.group('before'), 1, m1.group('after'))
+ m1 = re_1.match(ee)
+ a = myeval(ee, {}, {}) - b
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s' % (
+ m1.group('before'), 0.5, m1.group('after'))
+ m1 = re_1.match(ee)
+ c = myeval(ee, {}, {})
+ # computing another point to be sure that expression is linear
+ m1 = re_1.match(e)
+ while m1:
+ ee = '%s(%s)%s' % (
+ m1.group('before'), 1.5, m1.group('after'))
+ m1 = re_1.match(ee)
+ c2 = myeval(ee, {}, {})
+ if (a * 0.5 + b == c and a * 1.5 + b == c2):
+ return a, b, x
+ except Exception:
+ pass
+ break
+ return None, None, None
+
+
+word_pattern = re.compile(r'\b[a-z][\w$]*\b', re.I)
+
+
+def _get_depend_dict(name, vars, deps):
+ if name in vars:
+ words = vars[name].get('depend', [])
+
+ if '=' in vars[name] and not isstring(vars[name]):
+ for word in word_pattern.findall(vars[name]['=']):
+ # The word_pattern may return values that are not
+ # only variables, they can be string content for instance
+ if word not in words and word in vars and word != name:
+ words.append(word)
+ for word in words[:]:
+ for w in deps.get(word, []) \
+ or _get_depend_dict(word, vars, deps):
+ if w not in words:
+ words.append(w)
+ else:
+ outmess('_get_depend_dict: no dependence info for %s\n' % (repr(name)))
+ words = []
+ deps[name] = words
+ return words
+
+
+def _calc_depend_dict(vars):
+ names = list(vars.keys())
+ depend_dict = {}
+ for n in names:
+ _get_depend_dict(n, vars, depend_dict)
+ return depend_dict
+
+
+def get_sorted_names(vars):
+ """
+ """
+ depend_dict = _calc_depend_dict(vars)
+ names = []
+ for name in list(depend_dict.keys()):
+ if not depend_dict[name]:
+ names.append(name)
+ del depend_dict[name]
+ while depend_dict:
+ for name, lst in list(depend_dict.items()):
+ new_lst = [n for n in lst if n in depend_dict]
+ if not new_lst:
+ names.append(name)
+ del depend_dict[name]
+ else:
+ depend_dict[name] = new_lst
+ return [name for name in names if name in vars]
+
+
+def _kind_func(string):
+ # XXX: return something sensible.
+ if string[0] in "'\"":
+ string = string[1:-1]
+ if real16pattern.match(string):
+ return 8
+ elif real8pattern.match(string):
+ return 4
+ return 'kind(' + string + ')'
+
+
+def _selected_int_kind_func(r):
+ # XXX: This should be processor dependent
+ m = 10 ** r
+ if m <= 2 ** 8:
+ return 1
+ if m <= 2 ** 16:
+ return 2
+ if m <= 2 ** 32:
+ return 4
+ if m <= 2 ** 63:
+ return 8
+ if m <= 2 ** 128:
+ return 16
+ return -1
+
+
+def _selected_real_kind_func(p, r=0, radix=0):
+ # XXX: This should be processor dependent
+ # This is only good for 0 <= p <= 20
+ if p < 7:
+ return 4
+ if p < 16:
+ return 8
+ machine = platform.machine().lower()
+ if machine.startswith(('aarch64', 'power', 'ppc', 'riscv', 's390x', 'sparc')):
+ if p <= 20:
+ return 16
+ else:
+ if p < 19:
+ return 10
+ elif p <= 20:
+ return 16
+ return -1
+
+
+def get_parameters(vars, global_params={}):
+ params = copy.copy(global_params)
+ g_params = copy.copy(global_params)
+ for name, func in [('kind', _kind_func),
+ ('selected_int_kind', _selected_int_kind_func),
+ ('selected_real_kind', _selected_real_kind_func), ]:
+ if name not in g_params:
+ g_params[name] = func
+ param_names = []
+ for n in get_sorted_names(vars):
+ if 'attrspec' in vars[n] and 'parameter' in vars[n]['attrspec']:
+ param_names.append(n)
+ kind_re = re.compile(r'\bkind\s*\(\s*(?P<value>.*)\s*\)', re.I)
+ selected_int_kind_re = re.compile(
+ r'\bselected_int_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
+ selected_kind_re = re.compile(
+ r'\bselected_(int|real)_kind\s*\(\s*(?P<value>.*)\s*\)', re.I)
+ for n in param_names:
+ if '=' in vars[n]:
+ v = vars[n]['=']
+ if islogical(vars[n]):
+ v = v.lower()
+ for repl in [
+ ('.false.', 'False'),
+ ('.true.', 'True'),
+ # TODO: test .eq., .neq., etc replacements.
+ ]:
+ v = v.replace(*repl)
+ v = kind_re.sub(r'kind("\1")', v)
+ v = selected_int_kind_re.sub(r'selected_int_kind(\1)', v)
+
+ # We need to act according to the data.
+ # The easy case is if the data has a kind-specifier,
+ # then we may easily remove those specifiers.
+ # However, it may be that the user uses other specifiers...(!)
+ is_replaced = False
+ if 'kindselector' in vars[n]:
+ if 'kind' in vars[n]['kindselector']:
+ orig_v_len = len(v)
+ v = v.replace('_' + vars[n]['kindselector']['kind'], '')
+ # Again, this will be true if even a single specifier
+ # has been replaced, see comment above.
+ is_replaced = len(v) < orig_v_len
+
+ if not is_replaced:
+ if not selected_kind_re.match(v):
+ v_ = v.split('_')
+ # In case there are additive parameters
+ if len(v_) > 1:
+ v = ''.join(v_[:-1]).lower().replace(v_[-1].lower(), '')
+
+ # Currently this will not work for complex numbers.
+ # There is missing code for extracting a complex number,
+ # which may be defined in either of these:
+ # a) (Re, Im)
+ # b) cmplx(Re, Im)
+ # c) dcmplx(Re, Im)
+ # d) cmplx(Re, Im, <prec>)
+
+ if isdouble(vars[n]):
+ tt = list(v)
+ for m in real16pattern.finditer(v):
+ tt[m.start():m.end()] = list(
+ v[m.start():m.end()].lower().replace('d', 'e'))
+ v = ''.join(tt)
+
+ elif iscomplex(vars[n]):
+ outmess(f'get_parameters[TODO]: '
+ f'implement evaluation of complex expression {v}\n')
+
+ # Handle _dp for gh-6624
+ # Also fixes gh-20460
+ if real16pattern.search(v):
+ v = 8
+ elif real8pattern.search(v):
+ v = 4
+ try:
+ params[n] = eval(v, g_params, params)
+
+ except Exception as msg:
+ params[n] = v
+ outmess('get_parameters: got "%s" on %s\n' % (msg, repr(v)))
+ if isstring(vars[n]) and isinstance(params[n], int):
+ params[n] = chr(params[n])
+ nl = n.lower()
+ if nl != n:
+ params[nl] = params[n]
+ else:
+ print(vars[n])
+ outmess(
+ 'get_parameters:parameter %s does not have value?!\n' % (repr(n)))
+ return params
+
+
+def _eval_length(length, params):
+ if length in ['(:)', '(*)', '*']:
+ return '(*)'
+ return _eval_scalar(length, params)
+
+_is_kind_number = re.compile(r'\d+_').match
+
+
+def _eval_scalar(value, params):
+ if _is_kind_number(value):
+ value = value.split('_')[0]
+ try:
+ # TODO: use symbolic from PR #19805
+ value = eval(value, {}, params)
+ value = (repr if isinstance(value, str) else str)(value)
+ except (NameError, SyntaxError, TypeError):
+ return value
+ except Exception as msg:
+ errmess('"%s" in evaluating %r '
+ '(available names: %s)\n'
+ % (msg, value, list(params.keys())))
+ return value
+
+
+def analyzevars(block):
+ global f90modulevars
+
+ setmesstext(block)
+ implicitrules, attrrules = buildimplicitrules(block)
+ vars = copy.copy(block['vars'])
+ if block['block'] == 'function' and block['name'] not in vars:
+ vars[block['name']] = {}
+ if '' in block['vars']:
+ del vars['']
+ if 'attrspec' in block['vars']['']:
+ gen = block['vars']['']['attrspec']
+ for n in set(vars) | set(b['name'] for b in block['body']):
+ for k in ['public', 'private']:
+ if k in gen:
+ vars[n] = setattrspec(vars.get(n, {}), k)
+ svars = []
+ args = block['args']
+ for a in args:
+ try:
+ vars[a]
+ svars.append(a)
+ except KeyError:
+ pass
+ for n in list(vars.keys()):
+ if n not in args:
+ svars.append(n)
+
+ params = get_parameters(vars, get_useparameters(block))
+
+ dep_matches = {}
+ name_match = re.compile(r'[A-Za-z][\w$]*').match
+ for v in list(vars.keys()):
+ m = name_match(v)
+ if m:
+ n = v[m.start():m.end()]
+ try:
+ dep_matches[n]
+ except KeyError:
+ dep_matches[n] = re.compile(r'.*\b%s\b' % (v), re.I).match
+ for n in svars:
+ if n[0] in list(attrrules.keys()):
+ vars[n] = setattrspec(vars[n], attrrules[n[0]])
+ if 'typespec' not in vars[n]:
+ if not('attrspec' in vars[n] and 'external' in vars[n]['attrspec']):
+ if implicitrules:
+ ln0 = n[0].lower()
+ for k in list(implicitrules[ln0].keys()):
+ if k == 'typespec' and implicitrules[ln0][k] == 'undefined':
+ continue
+ if k not in vars[n]:
+ vars[n][k] = implicitrules[ln0][k]
+ elif k == 'attrspec':
+ for l in implicitrules[ln0][k]:
+ vars[n] = setattrspec(vars[n], l)
+ elif n in block['args']:
+ outmess('analyzevars: typespec of variable %s is not defined in routine %s.\n' % (
+ repr(n), block['name']))
+ if 'charselector' in vars[n]:
+ if 'len' in vars[n]['charselector']:
+ l = vars[n]['charselector']['len']
+ try:
+ l = str(eval(l, {}, params))
+ except Exception:
+ pass
+ vars[n]['charselector']['len'] = l
+
+ if 'kindselector' in vars[n]:
+ if 'kind' in vars[n]['kindselector']:
+ l = vars[n]['kindselector']['kind']
+ try:
+ l = str(eval(l, {}, params))
+ except Exception:
+ pass
+ vars[n]['kindselector']['kind'] = l
+
+ dimension_exprs = {}
+ if 'attrspec' in vars[n]:
+ attr = vars[n]['attrspec']
+ attr.reverse()
+ vars[n]['attrspec'] = []
+ dim, intent, depend, check, note = None, None, None, None, None
+ for a in attr:
+ if a[:9] == 'dimension':
+ dim = (a[9:].strip())[1:-1]
+ elif a[:6] == 'intent':
+ intent = (a[6:].strip())[1:-1]
+ elif a[:6] == 'depend':
+ depend = (a[6:].strip())[1:-1]
+ elif a[:5] == 'check':
+ check = (a[5:].strip())[1:-1]
+ elif a[:4] == 'note':
+ note = (a[4:].strip())[1:-1]
+ else:
+ vars[n] = setattrspec(vars[n], a)
+ if intent:
+ if 'intent' not in vars[n]:
+ vars[n]['intent'] = []
+ for c in [x.strip() for x in markoutercomma(intent).split('@,@')]:
+ # Remove spaces so that 'in out' becomes 'inout'
+ tmp = c.replace(' ', '')
+ if tmp not in vars[n]['intent']:
+ vars[n]['intent'].append(tmp)
+ intent = None
+ if note:
+ note = note.replace('\\n\\n', '\n\n')
+ note = note.replace('\\n ', '\n')
+ if 'note' not in vars[n]:
+ vars[n]['note'] = [note]
+ else:
+ vars[n]['note'].append(note)
+ note = None
+ if depend is not None:
+ if 'depend' not in vars[n]:
+ vars[n]['depend'] = []
+ for c in rmbadname([x.strip() for x in markoutercomma(depend).split('@,@')]):
+ if c not in vars[n]['depend']:
+ vars[n]['depend'].append(c)
+ depend = None
+ if check is not None:
+ if 'check' not in vars[n]:
+ vars[n]['check'] = []
+ for c in [x.strip() for x in markoutercomma(check).split('@,@')]:
+ if c not in vars[n]['check']:
+ vars[n]['check'].append(c)
+ check = None
+ if dim and 'dimension' not in vars[n]:
+ vars[n]['dimension'] = []
+ for d in rmbadname([x.strip() for x in markoutercomma(dim).split('@,@')]):
+ star = ':' if d == ':' else '*'
+ # Evaluate `d` with respect to params
+ if d in params:
+ d = str(params[d])
+ for p in params:
+ re_1 = re.compile(r'(?P<before>.*?)\b' + p + r'\b(?P<after>.*)', re.I)
+ m = re_1.match(d)
+ while m:
+ d = m.group('before') + \
+ str(params[p]) + m.group('after')
+ m = re_1.match(d)
+
+ if d == star:
+ dl = [star]
+ else:
+ dl = markoutercomma(d, ':').split('@:@')
+ if len(dl) == 2 and '*' in dl: # e.g. dimension(5:*)
+ dl = ['*']
+ d = '*'
+ if len(dl) == 1 and dl[0] != star:
+ dl = ['1', dl[0]]
+ if len(dl) == 2:
+ d1, d2 = map(symbolic.Expr.parse, dl)
+ dsize = d2 - d1 + 1
+ d = dsize.tostring(language=symbolic.Language.C)
+ # find variables v that define d as a linear
+ # function, `d == a * v + b`, and store
+ # coefficients a and b for further analysis.
+ solver_and_deps = {}
+ for v in block['vars']:
+ s = symbolic.as_symbol(v)
+ if dsize.contains(s):
+ try:
+ a, b = dsize.linear_solve(s)
+
+ def solve_v(s, a=a, b=b):
+ return (s - b) / a
+
+ all_symbols = set(a.symbols())
+ all_symbols.update(b.symbols())
+ except RuntimeError as msg:
+ # d is not a linear function of v,
+ # however, if v can be determined
+ # from d using other means,
+ # implement the corresponding
+ # solve_v function here.
+ solve_v = None
+ all_symbols = set(dsize.symbols())
+ v_deps = set(
+ s.data for s in all_symbols
+ if s.data in vars)
+ solver_and_deps[v] = solve_v, list(v_deps)
+ # Note that dsize may contain symbols that are
+ # not defined in block['vars']. Here we assume
+ # these correspond to Fortran/C intrinsic
+ # functions or that are defined by other
+ # means. We'll let the compiler validate the
+ # definiteness of such symbols.
+ dimension_exprs[d] = solver_and_deps
+ vars[n]['dimension'].append(d)
+
+ if 'check' not in vars[n] and 'args' in block and n in block['args']:
+ # n is an argument that has no checks defined. Here we
+ # generate some consistency checks for n, and when n is an
+ # array, generate checks for its dimensions and construct
+ # initialization expressions.
+ n_deps = vars[n].get('depend', [])
+ n_checks = []
+ n_is_input = l_or(isintent_in, isintent_inout,
+ isintent_inplace)(vars[n])
+ if isarray(vars[n]): # n is array
+ for i, d in enumerate(vars[n]['dimension']):
+ coeffs_and_deps = dimension_exprs.get(d)
+ if coeffs_and_deps is None:
+ # d is `:` or `*` or a constant expression
+ pass
+ elif n_is_input:
+ # n is an input array argument and its shape
+ # may define variables used in dimension
+ # specifications.
+ for v, (solver, deps) in coeffs_and_deps.items():
+ def compute_deps(v, deps):
+ for v1 in coeffs_and_deps.get(v, [None, []])[1]:
+ if v1 not in deps:
+ deps.add(v1)
+ compute_deps(v1, deps)
+ all_deps = set()
+ compute_deps(v, all_deps)
+ if ((v in n_deps
+ or '=' in vars[v]
+ or 'depend' in vars[v])):
+ # Skip a variable that
+ # - n depends on
+ # - has user-defined initialization expression
+ # - has user-defined dependencies
+ continue
+ if solver is not None and v not in all_deps:
+ # v can be solved from d, hence, we
+ # make it an optional argument with
+ # initialization expression:
+ is_required = False
+ init = solver(symbolic.as_symbol(
+ f'shape({n}, {i})'))
+ init = init.tostring(
+ language=symbolic.Language.C)
+ vars[v]['='] = init
+ # n needs to be initialized before v. So,
+ # making v dependent on n and on any
+ # variables in solver or d.
+ vars[v]['depend'] = [n] + deps
+ if 'check' not in vars[v]:
+ # add check only when no
+ # user-specified checks exist
+ vars[v]['check'] = [
+ f'shape({n}, {i}) == {d}']
+ else:
+ # d is a non-linear function on v,
+ # hence, v must be a required input
+ # argument that n will depend on
+ is_required = True
+ if 'intent' not in vars[v]:
+ vars[v]['intent'] = []
+ if 'in' not in vars[v]['intent']:
+ vars[v]['intent'].append('in')
+ # v needs to be initialized before n
+ n_deps.append(v)
+ n_checks.append(
+ f'shape({n}, {i}) == {d}')
+ v_attr = vars[v].get('attrspec', [])
+ if not ('optional' in v_attr
+ or 'required' in v_attr):
+ v_attr.append(
+ 'required' if is_required else 'optional')
+ if v_attr:
+ vars[v]['attrspec'] = v_attr
+ if coeffs_and_deps is not None:
+ # extend v dependencies with ones specified in attrspec
+ for v, (solver, deps) in coeffs_and_deps.items():
+ v_deps = vars[v].get('depend', [])
+ for aa in vars[v].get('attrspec', []):
+ if aa.startswith('depend'):
+ aa = ''.join(aa.split())
+ v_deps.extend(aa[7:-1].split(','))
+ if v_deps:
+ vars[v]['depend'] = list(set(v_deps))
+ if n not in v_deps:
+ n_deps.append(v)
+ elif isstring(vars[n]):
+ if 'charselector' in vars[n]:
+ if '*' in vars[n]['charselector']:
+ length = _eval_length(vars[n]['charselector']['*'],
+ params)
+ vars[n]['charselector']['*'] = length
+ elif 'len' in vars[n]['charselector']:
+ length = _eval_length(vars[n]['charselector']['len'],
+ params)
+ del vars[n]['charselector']['len']
+ vars[n]['charselector']['*'] = length
+ if n_checks:
+ vars[n]['check'] = n_checks
+ if n_deps:
+ vars[n]['depend'] = list(set(n_deps))
+
+ if '=' in vars[n]:
+ if 'attrspec' not in vars[n]:
+ vars[n]['attrspec'] = []
+ if ('optional' not in vars[n]['attrspec']) and \
+ ('required' not in vars[n]['attrspec']):
+ vars[n]['attrspec'].append('optional')
+ if 'depend' not in vars[n]:
+ vars[n]['depend'] = []
+ for v, m in list(dep_matches.items()):
+ if m(vars[n]['=']):
+ vars[n]['depend'].append(v)
+ if not vars[n]['depend']:
+ del vars[n]['depend']
+ if isscalar(vars[n]):
+ vars[n]['='] = _eval_scalar(vars[n]['='], params)
+
+ for n in list(vars.keys()):
+ if n == block['name']: # n is block name
+ if 'note' in vars[n]:
+ block['note'] = vars[n]['note']
+ if block['block'] == 'function':
+ if 'result' in block and block['result'] in vars:
+ vars[n] = appenddecl(vars[n], vars[block['result']])
+ if 'prefix' in block:
+ pr = block['prefix']
+ pr1 = pr.replace('pure', '')
+ ispure = (not pr == pr1)
+ pr = pr1.replace('recursive', '')
+ isrec = (not pr == pr1)
+ m = typespattern[0].match(pr)
+ if m:
+ typespec, selector, attr, edecl = cracktypespec0(
+ m.group('this'), m.group('after'))
+ kindselect, charselect, typename = cracktypespec(
+ typespec, selector)
+ vars[n]['typespec'] = typespec
+ if kindselect:
+ if 'kind' in kindselect:
+ try:
+ kindselect['kind'] = eval(
+ kindselect['kind'], {}, params)
+ except Exception:
+ pass
+ vars[n]['kindselector'] = kindselect
+ if charselect:
+ vars[n]['charselector'] = charselect
+ if typename:
+ vars[n]['typename'] = typename
+ if ispure:
+ vars[n] = setattrspec(vars[n], 'pure')
+ if isrec:
+ vars[n] = setattrspec(vars[n], 'recursive')
+ else:
+ outmess(
+ 'analyzevars: prefix (%s) were not used\n' % repr(block['prefix']))
+ if not block['block'] in ['module', 'pythonmodule', 'python module', 'block data']:
+ if 'commonvars' in block:
+ neededvars = copy.copy(block['args'] + block['commonvars'])
+ else:
+ neededvars = copy.copy(block['args'])
+ for n in list(vars.keys()):
+ if l_or(isintent_callback, isintent_aux)(vars[n]):
+ neededvars.append(n)
+ if 'entry' in block:
+ neededvars.extend(list(block['entry'].keys()))
+ for k in list(block['entry'].keys()):
+ for n in block['entry'][k]:
+ if n not in neededvars:
+ neededvars.append(n)
+ if block['block'] == 'function':
+ if 'result' in block:
+ neededvars.append(block['result'])
+ else:
+ neededvars.append(block['name'])
+ if block['block'] in ['subroutine', 'function']:
+ name = block['name']
+ if name in vars and 'intent' in vars[name]:
+ block['intent'] = vars[name]['intent']
+ if block['block'] == 'type':
+ neededvars.extend(list(vars.keys()))
+ for n in list(vars.keys()):
+ if n not in neededvars:
+ del vars[n]
+ return vars
+
+analyzeargs_re_1 = re.compile(r'\A[a-z]+[\w$]*\Z', re.I)
+
+
+def expr2name(a, block, args=[]):
+ orig_a = a
+ a_is_expr = not analyzeargs_re_1.match(a)
+ if a_is_expr: # `a` is an expression
+ implicitrules, attrrules = buildimplicitrules(block)
+ at = determineexprtype(a, block['vars'], implicitrules)
+ na = 'e_'
+ for c in a:
+ c = c.lower()
+ if c not in string.ascii_lowercase + string.digits:
+ c = '_'
+ na = na + c
+ if na[-1] == '_':
+ na = na + 'e'
+ else:
+ na = na + '_e'
+ a = na
+ while a in block['vars'] or a in block['args']:
+ a = a + 'r'
+ if a in args:
+ k = 1
+ while a + str(k) in args:
+ k = k + 1
+ a = a + str(k)
+ if a_is_expr:
+ block['vars'][a] = at
+ else:
+ if a not in block['vars']:
+ if orig_a in block['vars']:
+ block['vars'][a] = block['vars'][orig_a]
+ else:
+ block['vars'][a] = {}
+ if 'externals' in block and orig_a in block['externals'] + block['interfaced']:
+ block['vars'][a] = setattrspec(block['vars'][a], 'external')
+ return a
+
+
+def analyzeargs(block):
+ setmesstext(block)
+ implicitrules, _ = buildimplicitrules(block)
+ if 'args' not in block:
+ block['args'] = []
+ args = []
+ for a in block['args']:
+ a = expr2name(a, block, args)
+ args.append(a)
+ block['args'] = args
+ if 'entry' in block:
+ for k, args1 in list(block['entry'].items()):
+ for a in args1:
+ if a not in block['vars']:
+ block['vars'][a] = {}
+
+ for b in block['body']:
+ if b['name'] in args:
+ if 'externals' not in block:
+ block['externals'] = []
+ if b['name'] not in block['externals']:
+ block['externals'].append(b['name'])
+ if 'result' in block and block['result'] not in block['vars']:
+ block['vars'][block['result']] = {}
+ return block
+
+determineexprtype_re_1 = re.compile(r'\A\(.+?,.+?\)\Z', re.I)
+determineexprtype_re_2 = re.compile(r'\A[+-]?\d+(_(?P<name>\w+)|)\Z', re.I)
+determineexprtype_re_3 = re.compile(
+ r'\A[+-]?[\d.]+[-\d+de.]*(_(?P<name>\w+)|)\Z', re.I)
+determineexprtype_re_4 = re.compile(r'\A\(.*\)\Z', re.I)
+determineexprtype_re_5 = re.compile(r'\A(?P<name>\w+)\s*\(.*?\)\s*\Z', re.I)
+
+
+def _ensure_exprdict(r):
+ if isinstance(r, int):
+ return {'typespec': 'integer'}
+ if isinstance(r, float):
+ return {'typespec': 'real'}
+ if isinstance(r, complex):
+ return {'typespec': 'complex'}
+ if isinstance(r, dict):
+ return r
+ raise AssertionError(repr(r))
+
+
+def determineexprtype(expr, vars, rules={}):
+ if expr in vars:
+ return _ensure_exprdict(vars[expr])
+ expr = expr.strip()
+ if determineexprtype_re_1.match(expr):
+ return {'typespec': 'complex'}
+ m = determineexprtype_re_2.match(expr)
+ if m:
+ if 'name' in m.groupdict() and m.group('name'):
+ outmess(
+ 'determineexprtype: selected kind types not supported (%s)\n' % repr(expr))
+ return {'typespec': 'integer'}
+ m = determineexprtype_re_3.match(expr)
+ if m:
+ if 'name' in m.groupdict() and m.group('name'):
+ outmess(
+ 'determineexprtype: selected kind types not supported (%s)\n' % repr(expr))
+ return {'typespec': 'real'}
+ for op in ['+', '-', '*', '/']:
+ for e in [x.strip() for x in markoutercomma(expr, comma=op).split('@' + op + '@')]:
+ if e in vars:
+ return _ensure_exprdict(vars[e])
+ t = {}
+ if determineexprtype_re_4.match(expr): # in parenthesis
+ t = determineexprtype(expr[1:-1], vars, rules)
+ else:
+ m = determineexprtype_re_5.match(expr)
+ if m:
+ rn = m.group('name')
+ t = determineexprtype(m.group('name'), vars, rules)
+ if t and 'attrspec' in t:
+ del t['attrspec']
+ if not t:
+ if rn[0] in rules:
+ return _ensure_exprdict(rules[rn[0]])
+ if expr[0] in '\'"':
+ return {'typespec': 'character', 'charselector': {'*': '*'}}
+ if not t:
+ outmess(
+ 'determineexprtype: could not determine expressions (%s) type.\n' % (repr(expr)))
+ return t
+
+######
+
+
+def crack2fortrangen(block, tab='\n', as_interface=False):
+ global skipfuncs, onlyfuncs
+
+ setmesstext(block)
+ ret = ''
+ if isinstance(block, list):
+ for g in block:
+ if g and g['block'] in ['function', 'subroutine']:
+ if g['name'] in skipfuncs:
+ continue
+ if onlyfuncs and g['name'] not in onlyfuncs:
+ continue
+ ret = ret + crack2fortrangen(g, tab, as_interface=as_interface)
+ return ret
+ prefix = ''
+ name = ''
+ args = ''
+ blocktype = block['block']
+ if blocktype == 'program':
+ return ''
+ argsl = []
+ if 'name' in block:
+ name = block['name']
+ if 'args' in block:
+ vars = block['vars']
+ for a in block['args']:
+ a = expr2name(a, block, argsl)
+ if not isintent_callback(vars[a]):
+ argsl.append(a)
+ if block['block'] == 'function' or argsl:
+ args = '(%s)' % ','.join(argsl)
+ f2pyenhancements = ''
+ if 'f2pyenhancements' in block:
+ for k in list(block['f2pyenhancements'].keys()):
+ f2pyenhancements = '%s%s%s %s' % (
+ f2pyenhancements, tab + tabchar, k, block['f2pyenhancements'][k])
+ intent_lst = block.get('intent', [])[:]
+ if blocktype == 'function' and 'callback' in intent_lst:
+ intent_lst.remove('callback')
+ if intent_lst:
+ f2pyenhancements = '%s%sintent(%s) %s' %\
+ (f2pyenhancements, tab + tabchar,
+ ','.join(intent_lst), name)
+ use = ''
+ if 'use' in block:
+ use = use2fortran(block['use'], tab + tabchar)
+ common = ''
+ if 'common' in block:
+ common = common2fortran(block['common'], tab + tabchar)
+ if name == 'unknown_interface':
+ name = ''
+ result = ''
+ if 'result' in block:
+ result = ' result (%s)' % block['result']
+ if block['result'] not in argsl:
+ argsl.append(block['result'])
+ body = crack2fortrangen(block['body'], tab + tabchar, as_interface=as_interface)
+ vars = vars2fortran(
+ block, block['vars'], argsl, tab + tabchar, as_interface=as_interface)
+ mess = ''
+ if 'from' in block and not as_interface:
+ mess = '! in %s' % block['from']
+ if 'entry' in block:
+ entry_stmts = ''
+ for k, i in list(block['entry'].items()):
+ entry_stmts = '%s%sentry %s(%s)' \
+ % (entry_stmts, tab + tabchar, k, ','.join(i))
+ body = body + entry_stmts
+ if blocktype == 'block data' and name == '_BLOCK_DATA_':
+ name = ''
+ ret = '%s%s%s %s%s%s %s%s%s%s%s%s%send %s %s' % (
+ tab, prefix, blocktype, name, args, result, mess, f2pyenhancements, use, vars, common, body, tab, blocktype, name)
+ return ret
+
+
+def common2fortran(common, tab=''):
+ ret = ''
+ for k in list(common.keys()):
+ if k == '_BLNK_':
+ ret = '%s%scommon %s' % (ret, tab, ','.join(common[k]))
+ else:
+ ret = '%s%scommon /%s/ %s' % (ret, tab, k, ','.join(common[k]))
+ return ret
+
+
+def use2fortran(use, tab=''):
+ ret = ''
+ for m in list(use.keys()):
+ ret = '%s%suse %s,' % (ret, tab, m)
+ if use[m] == {}:
+ if ret and ret[-1] == ',':
+ ret = ret[:-1]
+ continue
+ if 'only' in use[m] and use[m]['only']:
+ ret = '%s only:' % (ret)
+ if 'map' in use[m] and use[m]['map']:
+ c = ' '
+ for k in list(use[m]['map'].keys()):
+ if k == use[m]['map'][k]:
+ ret = '%s%s%s' % (ret, c, k)
+ c = ','
+ else:
+ ret = '%s%s%s=>%s' % (ret, c, k, use[m]['map'][k])
+ c = ','
+ if ret and ret[-1] == ',':
+ ret = ret[:-1]
+ return ret
+
+
+def true_intent_list(var):
+ lst = var['intent']
+ ret = []
+ for intent in lst:
+ try:
+ f = globals()['isintent_%s' % intent]
+ except KeyError:
+ pass
+ else:
+ if f(var):
+ ret.append(intent)
+ return ret
+
+
+def vars2fortran(block, vars, args, tab='', as_interface=False):
+ """
+ TODO:
+ public sub
+ ...
+ """
+ setmesstext(block)
+ ret = ''
+ nout = []
+ for a in args:
+ if a in block['vars']:
+ nout.append(a)
+ if 'commonvars' in block:
+ for a in block['commonvars']:
+ if a in vars:
+ if a not in nout:
+ nout.append(a)
+ else:
+ errmess(
+ 'vars2fortran: Confused?!: "%s" is not defined in vars.\n' % a)
+ if 'varnames' in block:
+ nout.extend(block['varnames'])
+ if not as_interface:
+ for a in list(vars.keys()):
+ if a not in nout:
+ nout.append(a)
+ for a in nout:
+ if 'depend' in vars[a]:
+ for d in vars[a]['depend']:
+ if d in vars and 'depend' in vars[d] and a in vars[d]['depend']:
+ errmess(
+ 'vars2fortran: Warning: cross-dependence between variables "%s" and "%s"\n' % (a, d))
+ if 'externals' in block and a in block['externals']:
+ if isintent_callback(vars[a]):
+ ret = '%s%sintent(callback) %s' % (ret, tab, a)
+ ret = '%s%sexternal %s' % (ret, tab, a)
+ if isoptional(vars[a]):
+ ret = '%s%soptional %s' % (ret, tab, a)
+ if a in vars and 'typespec' not in vars[a]:
+ continue
+ cont = 1
+ for b in block['body']:
+ if a == b['name'] and b['block'] == 'function':
+ cont = 0
+ break
+ if cont:
+ continue
+ if a not in vars:
+ show(vars)
+ outmess('vars2fortran: No definition for argument "%s".\n' % a)
+ continue
+ if a == block['name']:
+ if block['block'] != 'function' or block.get('result'):
+ # 1) skip declaring a variable that name matches with
+ # subroutine name
+ # 2) skip declaring function when its type is
+ # declared via `result` construction
+ continue
+ if 'typespec' not in vars[a]:
+ if 'attrspec' in vars[a] and 'external' in vars[a]['attrspec']:
+ if a in args:
+ ret = '%s%sexternal %s' % (ret, tab, a)
+ continue
+ show(vars[a])
+ outmess('vars2fortran: No typespec for argument "%s".\n' % a)
+ continue
+ vardef = vars[a]['typespec']
+ if vardef == 'type' and 'typename' in vars[a]:
+ vardef = '%s(%s)' % (vardef, vars[a]['typename'])
+ selector = {}
+ if 'kindselector' in vars[a]:
+ selector = vars[a]['kindselector']
+ elif 'charselector' in vars[a]:
+ selector = vars[a]['charselector']
+ if '*' in selector:
+ if selector['*'] in ['*', ':']:
+ vardef = '%s*(%s)' % (vardef, selector['*'])
+ else:
+ vardef = '%s*%s' % (vardef, selector['*'])
+ else:
+ if 'len' in selector:
+ vardef = '%s(len=%s' % (vardef, selector['len'])
+ if 'kind' in selector:
+ vardef = '%s,kind=%s)' % (vardef, selector['kind'])
+ else:
+ vardef = '%s)' % (vardef)
+ elif 'kind' in selector:
+ vardef = '%s(kind=%s)' % (vardef, selector['kind'])
+ c = ' '
+ if 'attrspec' in vars[a]:
+ attr = [l for l in vars[a]['attrspec']
+ if l not in ['external']]
+ if as_interface and 'intent(in)' in attr and 'intent(out)' in attr:
+ # In Fortran, intent(in, out) are conflicting while
+ # intent(in, out) can be specified only via
+ # `!f2py intent(out) ..`.
+ # So, for the Fortran interface, we'll drop
+ # intent(out) to resolve the conflict.
+ attr.remove('intent(out)')
+ if attr:
+ vardef = '%s, %s' % (vardef, ','.join(attr))
+ c = ','
+ if 'dimension' in vars[a]:
+ vardef = '%s%sdimension(%s)' % (
+ vardef, c, ','.join(vars[a]['dimension']))
+ c = ','
+ if 'intent' in vars[a]:
+ lst = true_intent_list(vars[a])
+ if lst:
+ vardef = '%s%sintent(%s)' % (vardef, c, ','.join(lst))
+ c = ','
+ if 'check' in vars[a]:
+ vardef = '%s%scheck(%s)' % (vardef, c, ','.join(vars[a]['check']))
+ c = ','
+ if 'depend' in vars[a]:
+ vardef = '%s%sdepend(%s)' % (
+ vardef, c, ','.join(vars[a]['depend']))
+ c = ','
+ if '=' in vars[a]:
+ v = vars[a]['=']
+ if vars[a]['typespec'] in ['complex', 'double complex']:
+ try:
+ v = eval(v)
+ v = '(%s,%s)' % (v.real, v.imag)
+ except Exception:
+ pass
+ vardef = '%s :: %s=%s' % (vardef, a, v)
+ else:
+ vardef = '%s :: %s' % (vardef, a)
+ ret = '%s%s%s' % (ret, tab, vardef)
+ return ret
+######
+
+
+# We expose post_processing_hooks as global variable so that
+# user-libraries could register their own hooks to f2py.
+post_processing_hooks = []
+
+
+def crackfortran(files):
+ global usermodules, post_processing_hooks
+
+ outmess('Reading fortran codes...\n', 0)
+ readfortrancode(files, crackline)
+ outmess('Post-processing...\n', 0)
+ usermodules = []
+ postlist = postcrack(grouplist[0])
+ outmess('Applying post-processing hooks...\n', 0)
+ for hook in post_processing_hooks:
+ outmess(f' {hook.__name__}\n', 0)
+ postlist = traverse(postlist, hook)
+ outmess('Post-processing (stage 2)...\n', 0)
+ postlist = postcrack2(postlist)
+ return usermodules + postlist
+
+
+def crack2fortran(block):
+ global f2py_version
+
+ pyf = crack2fortrangen(block) + '\n'
+ header = """! -*- f90 -*-
+! Note: the context of this file is case sensitive.
+"""
+ footer = """
+! This file was auto-generated with f2py (version:%s).
+! See:
+! https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e
+""" % (f2py_version)
+ return header + pyf + footer
+
+
+def _is_visit_pair(obj):
+ return (isinstance(obj, tuple)
+ and len(obj) == 2
+ and isinstance(obj[0], (int, str)))
+
+
+def traverse(obj, visit, parents=[], result=None, *args, **kwargs):
+ '''Traverse f2py data structure with the following visit function:
+
+ def visit(item, parents, result, *args, **kwargs):
+ """
+
+ parents is a list of key-"f2py data structure" pairs from which
+ items are taken from.
+
+ result is a f2py data structure that is filled with the
+ return value of the visit function.
+
+ item is 2-tuple (index, value) if parents[-1][1] is a list
+ item is 2-tuple (key, value) if parents[-1][1] is a dict
+
+ The return value of visit must be None, or of the same kind as
+ item, that is, if parents[-1] is a list, the return value must
+ be 2-tuple (new_index, new_value), or if parents[-1] is a
+ dict, the return value must be 2-tuple (new_key, new_value).
+
+ If new_index or new_value is None, the return value of visit
+ is ignored, that is, it will not be added to the result.
+
+ If the return value is None, the content of obj will be
+ traversed, otherwise not.
+ """
+ '''
+
+ if _is_visit_pair(obj):
+ if obj[0] == 'parent_block':
+ # avoid infinite recursion
+ return obj
+ new_result = visit(obj, parents, result, *args, **kwargs)
+ if new_result is not None:
+ assert _is_visit_pair(new_result)
+ return new_result
+ parent = obj
+ result_key, obj = obj
+ else:
+ parent = (None, obj)
+ result_key = None
+
+ if isinstance(obj, list):
+ new_result = []
+ for index, value in enumerate(obj):
+ new_index, new_item = traverse((index, value), visit,
+ parents=parents + [parent],
+ result=result, *args, **kwargs)
+ if new_index is not None:
+ new_result.append(new_item)
+ elif isinstance(obj, dict):
+ new_result = dict()
+ for key, value in obj.items():
+ new_key, new_value = traverse((key, value), visit,
+ parents=parents + [parent],
+ result=result, *args, **kwargs)
+ if new_key is not None:
+ new_result[new_key] = new_value
+ else:
+ new_result = obj
+
+ if result_key is None:
+ return new_result
+ return result_key, new_result
+
+
+def character_backward_compatibility_hook(item, parents, result,
+ *args, **kwargs):
+ """Previously, Fortran character was incorrectly treated as
+ character*1. This hook fixes the usage of the corresponding
+ variables in `check`, `dimension`, `=`, and `callstatement`
+ expressions.
+
+ The usage of `char*` in `callprotoargument` expression can be left
+ unchanged because C `character` is C typedef of `char`, although,
+ new implementations should use `character*` in the corresponding
+ expressions.
+
+ See https://github.com/numpy/numpy/pull/19388 for more information.
+
+ """
+ parent_key, parent_value = parents[-1]
+ key, value = item
+
+ def fix_usage(varname, value):
+ value = re.sub(r'[*]\s*\b' + varname + r'\b', varname, value)
+ value = re.sub(r'\b' + varname + r'\b\s*[\[]\s*0\s*[\]]',
+ varname, value)
+ return value
+
+ if parent_key in ['dimension', 'check']:
+ assert parents[-3][0] == 'vars'
+ vars_dict = parents[-3][1]
+ elif key == '=':
+ assert parents[-2][0] == 'vars'
+ vars_dict = parents[-2][1]
+ else:
+ vars_dict = None
+
+ new_value = None
+ if vars_dict is not None:
+ new_value = value
+ for varname, vd in vars_dict.items():
+ if ischaracter(vd):
+ new_value = fix_usage(varname, new_value)
+ elif key == 'callstatement':
+ vars_dict = parents[-2][1]['vars']
+ new_value = value
+ for varname, vd in vars_dict.items():
+ if ischaracter(vd):
+ # replace all occurrences of `<varname>` with
+ # `&<varname>` in argument passing
+ new_value = re.sub(
+ r'(?<![&])\b' + varname + r'\b', '&' + varname, new_value)
+
+ if new_value is not None:
+ if new_value != value:
+ # We report the replacements here so that downstream
+ # software could update their source codes
+ # accordingly. However, such updates are recommended only
+ # when BC with numpy 1.21 or older is not required.
+ outmess(f'character_bc_hook[{parent_key}.{key}]:'
+ f' replaced `{value}` -> `{new_value}`\n', 1)
+ return (key, new_value)
+
+
+post_processing_hooks.append(character_backward_compatibility_hook)
+
+
+if __name__ == "__main__":
+ files = []
+ funcs = []
+ f = 1
+ f2 = 0
+ f3 = 0
+ showblocklist = 0
+ for l in sys.argv[1:]:
+ if l == '':
+ pass
+ elif l[0] == ':':
+ f = 0
+ elif l == '-quiet':
+ quiet = 1
+ verbose = 0
+ elif l == '-verbose':
+ verbose = 2
+ quiet = 0
+ elif l == '-fix':
+ if strictf77:
+ outmess(
+ 'Use option -f90 before -fix if Fortran 90 code is in fix form.\n', 0)
+ skipemptyends = 1
+ sourcecodeform = 'fix'
+ elif l == '-skipemptyends':
+ skipemptyends = 1
+ elif l == '--ignore-contains':
+ ignorecontains = 1
+ elif l == '-f77':
+ strictf77 = 1
+ sourcecodeform = 'fix'
+ elif l == '-f90':
+ strictf77 = 0
+ sourcecodeform = 'free'
+ skipemptyends = 1
+ elif l == '-h':
+ f2 = 1
+ elif l == '-show':
+ showblocklist = 1
+ elif l == '-m':
+ f3 = 1
+ elif l[0] == '-':
+ errmess('Unknown option %s\n' % repr(l))
+ elif f2:
+ f2 = 0
+ pyffilename = l
+ elif f3:
+ f3 = 0
+ f77modulename = l
+ elif f:
+ try:
+ open(l).close()
+ files.append(l)
+ except OSError as detail:
+ errmess(f'OSError: {detail!s}\n')
+ else:
+ funcs.append(l)
+ if not strictf77 and f77modulename and not skipemptyends:
+ outmess("""\
+ Warning: You have specified module name for non Fortran 77 code that
+ should not need one (expect if you are scanning F90 code for non
+ module blocks but then you should use flag -skipemptyends and also
+ be sure that the files do not contain programs without program
+ statement).
+""", 0)
+
+ postlist = crackfortran(files)
+ if pyffilename:
+ outmess('Writing fortran code to file %s\n' % repr(pyffilename), 0)
+ pyf = crack2fortran(postlist)
+ with open(pyffilename, 'w') as f:
+ f.write(pyf)
+ if showblocklist:
+ show(postlist)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/diagnose.py b/venv/lib/python3.9/site-packages/numpy/f2py/diagnose.py
new file mode 100644
index 00000000..21ee399f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/diagnose.py
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+import os
+import sys
+import tempfile
+
+
+def run_command(cmd):
+ print('Running %r:' % (cmd))
+ os.system(cmd)
+ print('------')
+
+
+def run():
+ _path = os.getcwd()
+ os.chdir(tempfile.gettempdir())
+ print('------')
+ print('os.name=%r' % (os.name))
+ print('------')
+ print('sys.platform=%r' % (sys.platform))
+ print('------')
+ print('sys.version:')
+ print(sys.version)
+ print('------')
+ print('sys.prefix:')
+ print(sys.prefix)
+ print('------')
+ print('sys.path=%r' % (':'.join(sys.path)))
+ print('------')
+
+ try:
+ import numpy
+ has_newnumpy = 1
+ except ImportError:
+ print('Failed to import new numpy:', sys.exc_info()[1])
+ has_newnumpy = 0
+
+ try:
+ from numpy.f2py import f2py2e
+ has_f2py2e = 1
+ except ImportError:
+ print('Failed to import f2py2e:', sys.exc_info()[1])
+ has_f2py2e = 0
+
+ try:
+ import numpy.distutils
+ has_numpy_distutils = 2
+ except ImportError:
+ try:
+ import numpy_distutils
+ has_numpy_distutils = 1
+ except ImportError:
+ print('Failed to import numpy_distutils:', sys.exc_info()[1])
+ has_numpy_distutils = 0
+
+ if has_newnumpy:
+ try:
+ print('Found new numpy version %r in %s' %
+ (numpy.__version__, numpy.__file__))
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+
+ if has_f2py2e:
+ try:
+ print('Found f2py2e version %r in %s' %
+ (f2py2e.__version__.version, f2py2e.__file__))
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+
+ if has_numpy_distutils:
+ try:
+ if has_numpy_distutils == 2:
+ print('Found numpy.distutils version %r in %r' % (
+ numpy.distutils.__version__,
+ numpy.distutils.__file__))
+ else:
+ print('Found numpy_distutils version %r in %r' % (
+ numpy_distutils.numpy_distutils_version.numpy_distutils_version,
+ numpy_distutils.__file__))
+ print('------')
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+ try:
+ if has_numpy_distutils == 1:
+ print(
+ 'Importing numpy_distutils.command.build_flib ...', end=' ')
+ import numpy_distutils.command.build_flib as build_flib
+ print('ok')
+ print('------')
+ try:
+ print(
+ 'Checking availability of supported Fortran compilers:')
+ for compiler_class in build_flib.all_compilers:
+ compiler_class(verbose=1).is_available()
+ print('------')
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+ except Exception as msg:
+ print(
+ 'error:', msg, '(ignore it, build_flib is obsolute for numpy.distutils 0.2.2 and up)')
+ print('------')
+ try:
+ if has_numpy_distutils == 2:
+ print('Importing numpy.distutils.fcompiler ...', end=' ')
+ import numpy.distutils.fcompiler as fcompiler
+ else:
+ print('Importing numpy_distutils.fcompiler ...', end=' ')
+ import numpy_distutils.fcompiler as fcompiler
+ print('ok')
+ print('------')
+ try:
+ print('Checking availability of supported Fortran compilers:')
+ fcompiler.show_fcompilers()
+ print('------')
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+ try:
+ if has_numpy_distutils == 2:
+ print('Importing numpy.distutils.cpuinfo ...', end=' ')
+ from numpy.distutils.cpuinfo import cpuinfo
+ print('ok')
+ print('------')
+ else:
+ try:
+ print(
+ 'Importing numpy_distutils.command.cpuinfo ...', end=' ')
+ from numpy_distutils.command.cpuinfo import cpuinfo
+ print('ok')
+ print('------')
+ except Exception as msg:
+ print('error:', msg, '(ignore it)')
+ print('Importing numpy_distutils.cpuinfo ...', end=' ')
+ from numpy_distutils.cpuinfo import cpuinfo
+ print('ok')
+ print('------')
+ cpu = cpuinfo()
+ print('CPU information:', end=' ')
+ for name in dir(cpuinfo):
+ if name[0] == '_' and name[1] != '_' and getattr(cpu, name[1:])():
+ print(name[1:], end=' ')
+ print('------')
+ except Exception as msg:
+ print('error:', msg)
+ print('------')
+ os.chdir(_path)
+if __name__ == "__main__":
+ run()
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/f2py2e.py b/venv/lib/python3.9/site-packages/numpy/f2py/f2py2e.py
new file mode 100644
index 00000000..10508488
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/f2py2e.py
@@ -0,0 +1,704 @@
+#!/usr/bin/env python3
+"""
+
+f2py2e - Fortran to Python C/API generator. 2nd Edition.
+ See __usage__ below.
+
+Copyright 1999--2011 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@cens.ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/05/06 08:31:19 $
+Pearu Peterson
+
+"""
+import sys
+import os
+import pprint
+import re
+from pathlib import Path
+
+from . import crackfortran
+from . import rules
+from . import cb_rules
+from . import auxfuncs
+from . import cfuncs
+from . import f90mod_rules
+from . import __version__
+from . import capi_maps
+
+f2py_version = __version__.version
+numpy_version = __version__.version
+errmess = sys.stderr.write
+# outmess=sys.stdout.write
+show = pprint.pprint
+outmess = auxfuncs.outmess
+
+__usage__ =\
+f"""Usage:
+
+1) To construct extension module sources:
+
+ f2py [<options>] <fortran files> [[[only:]||[skip:]] \\
+ <fortran functions> ] \\
+ [: <fortran files> ...]
+
+2) To compile fortran files and build extension modules:
+
+ f2py -c [<options>, <build_flib options>, <extra options>] <fortran files>
+
+3) To generate signature files:
+
+ f2py -h <filename.pyf> ...< same options as in (1) >
+
+Description: This program generates a Python C/API file (<modulename>module.c)
+ that contains wrappers for given fortran functions so that they
+ can be called from Python. With the -c option the corresponding
+ extension modules are built.
+
+Options:
+
+ --2d-numpy Use numpy.f2py tool with NumPy support. [DEFAULT]
+ --2d-numeric Use f2py2e tool with Numeric support.
+ --2d-numarray Use f2py2e tool with Numarray support.
+ --g3-numpy Use 3rd generation f2py from the separate f2py package.
+ [NOT AVAILABLE YET]
+
+ -h <filename> Write signatures of the fortran routines to file <filename>
+ and exit. You can then edit <filename> and use it instead
+ of <fortran files>. If <filename>==stdout then the
+ signatures are printed to stdout.
+ <fortran functions> Names of fortran routines for which Python C/API
+ functions will be generated. Default is all that are found
+ in <fortran files>.
+ <fortran files> Paths to fortran/signature files that will be scanned for
+ <fortran functions> in order to determine their signatures.
+ skip: Ignore fortran functions that follow until `:'.
+ only: Use only fortran functions that follow until `:'.
+ : Get back to <fortran files> mode.
+
+ -m <modulename> Name of the module; f2py generates a Python/C API
+ file <modulename>module.c or extension module <modulename>.
+ Default is 'untitled'.
+
+ '-include<header>' Writes additional headers in the C wrapper, can be passed
+ multiple times, generates #include <header> each time.
+
+ --[no-]lower Do [not] lower the cases in <fortran files>. By default,
+ --lower is assumed with -h key, and --no-lower without -h key.
+
+ --build-dir <dirname> All f2py generated files are created in <dirname>.
+ Default is tempfile.mkdtemp().
+
+ --overwrite-signature Overwrite existing signature file.
+
+ --[no-]latex-doc Create (or not) <modulename>module.tex.
+ Default is --no-latex-doc.
+ --short-latex Create 'incomplete' LaTeX document (without commands
+ \\documentclass, \\tableofcontents, and \\begin{{document}},
+ \\end{{document}}).
+
+ --[no-]rest-doc Create (or not) <modulename>module.rst.
+ Default is --no-rest-doc.
+
+ --debug-capi Create C/API code that reports the state of the wrappers
+ during runtime. Useful for debugging.
+
+ --[no-]wrap-functions Create Fortran subroutine wrappers to Fortran 77
+ functions. --wrap-functions is default because it ensures
+ maximum portability/compiler independence.
+
+ --include-paths <path1>:<path2>:... Search include files from the given
+ directories.
+
+ --help-link [..] List system resources found by system_info.py. See also
+ --link-<resource> switch below. [..] is optional list
+ of resources names. E.g. try 'f2py --help-link lapack_opt'.
+
+ --f2cmap <filename> Load Fortran-to-Python KIND specification from the given
+ file. Default: .f2py_f2cmap in current directory.
+
+ --quiet Run quietly.
+ --verbose Run with extra verbosity.
+ --skip-empty-wrappers Only generate wrapper files when needed.
+ -v Print f2py version ID and exit.
+
+
+numpy.distutils options (only effective with -c):
+
+ --fcompiler= Specify Fortran compiler type by vendor
+ --compiler= Specify C compiler type (as defined by distutils)
+
+ --help-fcompiler List available Fortran compilers and exit
+ --f77exec= Specify the path to F77 compiler
+ --f90exec= Specify the path to F90 compiler
+ --f77flags= Specify F77 compiler flags
+ --f90flags= Specify F90 compiler flags
+ --opt= Specify optimization flags
+ --arch= Specify architecture specific optimization flags
+ --noopt Compile without optimization
+ --noarch Compile without arch-dependent optimization
+ --debug Compile with debugging information
+
+Extra options (only effective with -c):
+
+ --link-<resource> Link extension module with <resource> as defined
+ by numpy.distutils/system_info.py. E.g. to link
+ with optimized LAPACK libraries (vecLib on MacOSX,
+ ATLAS elsewhere), use --link-lapack_opt.
+ See also --help-link switch.
+
+ -L/path/to/lib/ -l<libname>
+ -D<define> -U<name>
+ -I/path/to/include/
+ <filename>.o <filename>.so <filename>.a
+
+ Using the following macros may be required with non-gcc Fortran
+ compilers:
+ -DPREPEND_FORTRAN -DNO_APPEND_FORTRAN -DUPPERCASE_FORTRAN
+ -DUNDERSCORE_G77
+
+ When using -DF2PY_REPORT_ATEXIT, a performance report of F2PY
+ interface is printed out at exit (platforms: Linux).
+
+ When using -DF2PY_REPORT_ON_ARRAY_COPY=<int>, a message is
+ sent to stderr whenever F2PY interface makes a copy of an
+ array. Integer <int> sets the threshold for array sizes when
+ a message should be shown.
+
+Version: {f2py_version}
+numpy Version: {numpy_version}
+Requires: Python 3.5 or higher.
+License: NumPy license (see LICENSE.txt in the NumPy source code)
+Copyright 1999 - 2011 Pearu Peterson all rights reserved.
+https://web.archive.org/web/20140822061353/http://cens.ioc.ee/projects/f2py2e"""
+
+
+def scaninputline(inputline):
+ files, skipfuncs, onlyfuncs, debug = [], [], [], []
+ f, f2, f3, f5, f6, f7, f8, f9, f10 = 1, 0, 0, 0, 0, 0, 0, 0, 0
+ verbose = 1
+ emptygen = True
+ dolc = -1
+ dolatexdoc = 0
+ dorestdoc = 0
+ wrapfuncs = 1
+ buildpath = '.'
+ include_paths = []
+ signsfile, modulename = None, None
+ options = {'buildpath': buildpath,
+ 'coutput': None,
+ 'f2py_wrapper_output': None}
+ for l in inputline:
+ if l == '':
+ pass
+ elif l == 'only:':
+ f = 0
+ elif l == 'skip:':
+ f = -1
+ elif l == ':':
+ f = 1
+ elif l[:8] == '--debug-':
+ debug.append(l[8:])
+ elif l == '--lower':
+ dolc = 1
+ elif l == '--build-dir':
+ f6 = 1
+ elif l == '--no-lower':
+ dolc = 0
+ elif l == '--quiet':
+ verbose = 0
+ elif l == '--verbose':
+ verbose += 1
+ elif l == '--latex-doc':
+ dolatexdoc = 1
+ elif l == '--no-latex-doc':
+ dolatexdoc = 0
+ elif l == '--rest-doc':
+ dorestdoc = 1
+ elif l == '--no-rest-doc':
+ dorestdoc = 0
+ elif l == '--wrap-functions':
+ wrapfuncs = 1
+ elif l == '--no-wrap-functions':
+ wrapfuncs = 0
+ elif l == '--short-latex':
+ options['shortlatex'] = 1
+ elif l == '--coutput':
+ f8 = 1
+ elif l == '--f2py-wrapper-output':
+ f9 = 1
+ elif l == '--f2cmap':
+ f10 = 1
+ elif l == '--overwrite-signature':
+ options['h-overwrite'] = 1
+ elif l == '-h':
+ f2 = 1
+ elif l == '-m':
+ f3 = 1
+ elif l[:2] == '-v':
+ print(f2py_version)
+ sys.exit()
+ elif l == '--show-compilers':
+ f5 = 1
+ elif l[:8] == '-include':
+ cfuncs.outneeds['userincludes'].append(l[9:-1])
+ cfuncs.userincludes[l[9:-1]] = '#include ' + l[8:]
+ elif l[:15] in '--include_paths':
+ outmess(
+ 'f2py option --include_paths is deprecated, use --include-paths instead.\n')
+ f7 = 1
+ elif l[:15] in '--include-paths':
+ f7 = 1
+ elif l == '--skip-empty-wrappers':
+ emptygen = False
+ elif l[0] == '-':
+ errmess('Unknown option %s\n' % repr(l))
+ sys.exit()
+ elif f2:
+ f2 = 0
+ signsfile = l
+ elif f3:
+ f3 = 0
+ modulename = l
+ elif f6:
+ f6 = 0
+ buildpath = l
+ elif f7:
+ f7 = 0
+ include_paths.extend(l.split(os.pathsep))
+ elif f8:
+ f8 = 0
+ options["coutput"] = l
+ elif f9:
+ f9 = 0
+ options["f2py_wrapper_output"] = l
+ elif f10:
+ f10 = 0
+ options["f2cmap_file"] = l
+ elif f == 1:
+ try:
+ with open(l):
+ pass
+ files.append(l)
+ except OSError as detail:
+ errmess(f'OSError: {detail!s}. Skipping file "{l!s}".\n')
+ elif f == -1:
+ skipfuncs.append(l)
+ elif f == 0:
+ onlyfuncs.append(l)
+ if not f5 and not files and not modulename:
+ print(__usage__)
+ sys.exit()
+ if not os.path.isdir(buildpath):
+ if not verbose:
+ outmess('Creating build directory %s\n' % (buildpath))
+ os.mkdir(buildpath)
+ if signsfile:
+ signsfile = os.path.join(buildpath, signsfile)
+ if signsfile and os.path.isfile(signsfile) and 'h-overwrite' not in options:
+ errmess(
+ 'Signature file "%s" exists!!! Use --overwrite-signature to overwrite.\n' % (signsfile))
+ sys.exit()
+
+ options['emptygen'] = emptygen
+ options['debug'] = debug
+ options['verbose'] = verbose
+ if dolc == -1 and not signsfile:
+ options['do-lower'] = 0
+ else:
+ options['do-lower'] = dolc
+ if modulename:
+ options['module'] = modulename
+ if signsfile:
+ options['signsfile'] = signsfile
+ if onlyfuncs:
+ options['onlyfuncs'] = onlyfuncs
+ if skipfuncs:
+ options['skipfuncs'] = skipfuncs
+ options['dolatexdoc'] = dolatexdoc
+ options['dorestdoc'] = dorestdoc
+ options['wrapfuncs'] = wrapfuncs
+ options['buildpath'] = buildpath
+ options['include_paths'] = include_paths
+ options.setdefault('f2cmap_file', None)
+ return files, options
+
+
+def callcrackfortran(files, options):
+ rules.options = options
+ crackfortran.debug = options['debug']
+ crackfortran.verbose = options['verbose']
+ if 'module' in options:
+ crackfortran.f77modulename = options['module']
+ if 'skipfuncs' in options:
+ crackfortran.skipfuncs = options['skipfuncs']
+ if 'onlyfuncs' in options:
+ crackfortran.onlyfuncs = options['onlyfuncs']
+ crackfortran.include_paths[:] = options['include_paths']
+ crackfortran.dolowercase = options['do-lower']
+ postlist = crackfortran.crackfortran(files)
+ if 'signsfile' in options:
+ outmess('Saving signatures to file "%s"\n' % (options['signsfile']))
+ pyf = crackfortran.crack2fortran(postlist)
+ if options['signsfile'][-6:] == 'stdout':
+ sys.stdout.write(pyf)
+ else:
+ with open(options['signsfile'], 'w') as f:
+ f.write(pyf)
+ if options["coutput"] is None:
+ for mod in postlist:
+ mod["coutput"] = "%smodule.c" % mod["name"]
+ else:
+ for mod in postlist:
+ mod["coutput"] = options["coutput"]
+ if options["f2py_wrapper_output"] is None:
+ for mod in postlist:
+ mod["f2py_wrapper_output"] = "%s-f2pywrappers.f" % mod["name"]
+ else:
+ for mod in postlist:
+ mod["f2py_wrapper_output"] = options["f2py_wrapper_output"]
+ return postlist
+
+
+def buildmodules(lst):
+ cfuncs.buildcfuncs()
+ outmess('Building modules...\n')
+ modules, mnames, isusedby = [], [], {}
+ for item in lst:
+ if '__user__' in item['name']:
+ cb_rules.buildcallbacks(item)
+ else:
+ if 'use' in item:
+ for u in item['use'].keys():
+ if u not in isusedby:
+ isusedby[u] = []
+ isusedby[u].append(item['name'])
+ modules.append(item)
+ mnames.append(item['name'])
+ ret = {}
+ for module, name in zip(modules, mnames):
+ if name in isusedby:
+ outmess('\tSkipping module "%s" which is used by %s.\n' % (
+ name, ','.join('"%s"' % s for s in isusedby[name])))
+ else:
+ um = []
+ if 'use' in module:
+ for u in module['use'].keys():
+ if u in isusedby and u in mnames:
+ um.append(modules[mnames.index(u)])
+ else:
+ outmess(
+ f'\tModule "{name}" uses nonexisting "{u}" '
+ 'which will be ignored.\n')
+ ret[name] = {}
+ dict_append(ret[name], rules.buildmodule(module, um))
+ return ret
+
+
+def dict_append(d_out, d_in):
+ for (k, v) in d_in.items():
+ if k not in d_out:
+ d_out[k] = []
+ if isinstance(v, list):
+ d_out[k] = d_out[k] + v
+ else:
+ d_out[k].append(v)
+
+
+def run_main(comline_list):
+ """
+ Equivalent to running::
+
+ f2py <args>
+
+ where ``<args>=string.join(<list>,' ')``, but in Python. Unless
+ ``-h`` is used, this function returns a dictionary containing
+ information on generated modules and their dependencies on source
+ files.
+
+ You cannot build extension modules with this function, that is,
+ using ``-c`` is not allowed. Use the ``compile`` command instead.
+
+ Examples
+ --------
+ The command ``f2py -m scalar scalar.f`` can be executed from Python as
+ follows.
+
+ .. literalinclude:: ../../source/f2py/code/results/run_main_session.dat
+ :language: python
+
+ """
+ crackfortran.reset_global_f2py_vars()
+ f2pydir = os.path.dirname(os.path.abspath(cfuncs.__file__))
+ fobjhsrc = os.path.join(f2pydir, 'src', 'fortranobject.h')
+ fobjcsrc = os.path.join(f2pydir, 'src', 'fortranobject.c')
+ files, options = scaninputline(comline_list)
+ auxfuncs.options = options
+ capi_maps.load_f2cmap_file(options['f2cmap_file'])
+ postlist = callcrackfortran(files, options)
+ isusedby = {}
+ for plist in postlist:
+ if 'use' in plist:
+ for u in plist['use'].keys():
+ if u not in isusedby:
+ isusedby[u] = []
+ isusedby[u].append(plist['name'])
+ for plist in postlist:
+ if plist['block'] == 'python module' and '__user__' in plist['name']:
+ if plist['name'] in isusedby:
+ # if not quiet:
+ outmess(
+ f'Skipping Makefile build for module "{plist["name"]}" '
+ 'which is used by {}\n'.format(
+ ','.join(f'"{s}"' for s in isusedby[plist['name']])))
+ if 'signsfile' in options:
+ if options['verbose'] > 1:
+ outmess(
+ 'Stopping. Edit the signature file and then run f2py on the signature file: ')
+ outmess('%s %s\n' %
+ (os.path.basename(sys.argv[0]), options['signsfile']))
+ return
+ for plist in postlist:
+ if plist['block'] != 'python module':
+ if 'python module' not in options:
+ errmess(
+ 'Tip: If your original code is Fortran source then you must use -m option.\n')
+ raise TypeError('All blocks must be python module blocks but got %s' % (
+ repr(plist['block'])))
+ auxfuncs.debugoptions = options['debug']
+ f90mod_rules.options = options
+ auxfuncs.wrapfuncs = options['wrapfuncs']
+
+ ret = buildmodules(postlist)
+
+ for mn in ret.keys():
+ dict_append(ret[mn], {'csrc': fobjcsrc, 'h': fobjhsrc})
+ return ret
+
+
+def filter_files(prefix, suffix, files, remove_prefix=None):
+ """
+ Filter files by prefix and suffix.
+ """
+ filtered, rest = [], []
+ match = re.compile(prefix + r'.*' + suffix + r'\Z').match
+ if remove_prefix:
+ ind = len(prefix)
+ else:
+ ind = 0
+ for file in [x.strip() for x in files]:
+ if match(file):
+ filtered.append(file[ind:])
+ else:
+ rest.append(file)
+ return filtered, rest
+
+
+def get_prefix(module):
+ p = os.path.dirname(os.path.dirname(module.__file__))
+ return p
+
+
+def run_compile():
+ """
+ Do it all in one call!
+ """
+ import tempfile
+
+ i = sys.argv.index('-c')
+ del sys.argv[i]
+
+ remove_build_dir = 0
+ try:
+ i = sys.argv.index('--build-dir')
+ except ValueError:
+ i = None
+ if i is not None:
+ build_dir = sys.argv[i + 1]
+ del sys.argv[i + 1]
+ del sys.argv[i]
+ else:
+ remove_build_dir = 1
+ build_dir = tempfile.mkdtemp()
+
+ _reg1 = re.compile(r'--link-')
+ sysinfo_flags = [_m for _m in sys.argv[1:] if _reg1.match(_m)]
+ sys.argv = [_m for _m in sys.argv if _m not in sysinfo_flags]
+ if sysinfo_flags:
+ sysinfo_flags = [f[7:] for f in sysinfo_flags]
+
+ _reg2 = re.compile(
+ r'--((no-|)(wrap-functions|lower)|debug-capi|quiet|skip-empty-wrappers)|-include')
+ f2py_flags = [_m for _m in sys.argv[1:] if _reg2.match(_m)]
+ sys.argv = [_m for _m in sys.argv if _m not in f2py_flags]
+ f2py_flags2 = []
+ fl = 0
+ for a in sys.argv[1:]:
+ if a in ['only:', 'skip:']:
+ fl = 1
+ elif a == ':':
+ fl = 0
+ if fl or a == ':':
+ f2py_flags2.append(a)
+ if f2py_flags2 and f2py_flags2[-1] != ':':
+ f2py_flags2.append(':')
+ f2py_flags.extend(f2py_flags2)
+
+ sys.argv = [_m for _m in sys.argv if _m not in f2py_flags2]
+ _reg3 = re.compile(
+ r'--((f(90)?compiler(-exec|)|compiler)=|help-compiler)')
+ flib_flags = [_m for _m in sys.argv[1:] if _reg3.match(_m)]
+ sys.argv = [_m for _m in sys.argv if _m not in flib_flags]
+ _reg4 = re.compile(
+ r'--((f(77|90)(flags|exec)|opt|arch)=|(debug|noopt|noarch|help-fcompiler))')
+ fc_flags = [_m for _m in sys.argv[1:] if _reg4.match(_m)]
+ sys.argv = [_m for _m in sys.argv if _m not in fc_flags]
+
+ del_list = []
+ for s in flib_flags:
+ v = '--fcompiler='
+ if s[:len(v)] == v:
+ from numpy.distutils import fcompiler
+ fcompiler.load_all_fcompiler_classes()
+ allowed_keys = list(fcompiler.fcompiler_class.keys())
+ nv = ov = s[len(v):].lower()
+ if ov not in allowed_keys:
+ vmap = {} # XXX
+ try:
+ nv = vmap[ov]
+ except KeyError:
+ if ov not in vmap.values():
+ print('Unknown vendor: "%s"' % (s[len(v):]))
+ nv = ov
+ i = flib_flags.index(s)
+ flib_flags[i] = '--fcompiler=' + nv
+ continue
+ for s in del_list:
+ i = flib_flags.index(s)
+ del flib_flags[i]
+ assert len(flib_flags) <= 2, repr(flib_flags)
+
+ _reg5 = re.compile(r'--(verbose)')
+ setup_flags = [_m for _m in sys.argv[1:] if _reg5.match(_m)]
+ sys.argv = [_m for _m in sys.argv if _m not in setup_flags]
+
+ if '--quiet' in f2py_flags:
+ setup_flags.append('--quiet')
+
+ modulename = 'untitled'
+ sources = sys.argv[1:]
+
+ for optname in ['--include_paths', '--include-paths', '--f2cmap']:
+ if optname in sys.argv:
+ i = sys.argv.index(optname)
+ f2py_flags.extend(sys.argv[i:i + 2])
+ del sys.argv[i + 1], sys.argv[i]
+ sources = sys.argv[1:]
+
+ if '-m' in sys.argv:
+ i = sys.argv.index('-m')
+ modulename = sys.argv[i + 1]
+ del sys.argv[i + 1], sys.argv[i]
+ sources = sys.argv[1:]
+ else:
+ from numpy.distutils.command.build_src import get_f2py_modulename
+ pyf_files, sources = filter_files('', '[.]pyf([.]src|)', sources)
+ sources = pyf_files + sources
+ for f in pyf_files:
+ modulename = get_f2py_modulename(f)
+ if modulename:
+ break
+
+ extra_objects, sources = filter_files('', '[.](o|a|so|dylib)', sources)
+ include_dirs, sources = filter_files('-I', '', sources, remove_prefix=1)
+ library_dirs, sources = filter_files('-L', '', sources, remove_prefix=1)
+ libraries, sources = filter_files('-l', '', sources, remove_prefix=1)
+ undef_macros, sources = filter_files('-U', '', sources, remove_prefix=1)
+ define_macros, sources = filter_files('-D', '', sources, remove_prefix=1)
+ for i in range(len(define_macros)):
+ name_value = define_macros[i].split('=', 1)
+ if len(name_value) == 1:
+ name_value.append(None)
+ if len(name_value) == 2:
+ define_macros[i] = tuple(name_value)
+ else:
+ print('Invalid use of -D:', name_value)
+
+ from numpy.distutils.system_info import get_info
+
+ num_info = {}
+ if num_info:
+ include_dirs.extend(num_info.get('include_dirs', []))
+
+ from numpy.distutils.core import setup, Extension
+ ext_args = {'name': modulename, 'sources': sources,
+ 'include_dirs': include_dirs,
+ 'library_dirs': library_dirs,
+ 'libraries': libraries,
+ 'define_macros': define_macros,
+ 'undef_macros': undef_macros,
+ 'extra_objects': extra_objects,
+ 'f2py_options': f2py_flags,
+ }
+
+ if sysinfo_flags:
+ from numpy.distutils.misc_util import dict_append
+ for n in sysinfo_flags:
+ i = get_info(n)
+ if not i:
+ outmess('No %s resources found in system'
+ ' (try `f2py --help-link`)\n' % (repr(n)))
+ dict_append(ext_args, **i)
+
+ ext = Extension(**ext_args)
+ sys.argv = [sys.argv[0]] + setup_flags
+ sys.argv.extend(['build',
+ '--build-temp', build_dir,
+ '--build-base', build_dir,
+ '--build-platlib', '.',
+ # disable CCompilerOpt
+ '--disable-optimization'])
+ if fc_flags:
+ sys.argv.extend(['config_fc'] + fc_flags)
+ if flib_flags:
+ sys.argv.extend(['build_ext'] + flib_flags)
+
+ setup(ext_modules=[ext])
+
+ if remove_build_dir and os.path.exists(build_dir):
+ import shutil
+ outmess('Removing build directory %s\n' % (build_dir))
+ shutil.rmtree(build_dir)
+
+
+def main():
+ if '--help-link' in sys.argv[1:]:
+ sys.argv.remove('--help-link')
+ from numpy.distutils.system_info import show_all
+ show_all()
+ return
+
+ # Probably outdated options that were not working before 1.16
+ if '--g3-numpy' in sys.argv[1:]:
+ sys.stderr.write("G3 f2py support is not implemented, yet.\\n")
+ sys.exit(1)
+ elif '--2e-numeric' in sys.argv[1:]:
+ sys.argv.remove('--2e-numeric')
+ elif '--2e-numarray' in sys.argv[1:]:
+ # Note that this errors becaust the -DNUMARRAY argument is
+ # not recognized. Just here for back compatibility and the
+ # error message.
+ sys.argv.append("-DNUMARRAY")
+ sys.argv.remove('--2e-numarray')
+ elif '--2e-numpy' in sys.argv[1:]:
+ sys.argv.remove('--2e-numpy')
+ else:
+ pass
+
+ if '-c' in sys.argv[1:]:
+ run_compile()
+ else:
+ run_main(sys.argv[1:])
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/f90mod_rules.py b/venv/lib/python3.9/site-packages/numpy/f2py/f90mod_rules.py
new file mode 100644
index 00000000..a3bb6a21
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/f90mod_rules.py
@@ -0,0 +1,264 @@
+#!/usr/bin/env python3
+"""
+
+Build F90 module support for f2py2e.
+
+Copyright 2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/02/03 19:30:23 $
+Pearu Peterson
+
+"""
+__version__ = "$Revision: 1.27 $"[10:-1]
+
+f2py_version = 'See `f2py -v`'
+
+import numpy as np
+
+from . import capi_maps
+from . import func2subr
+from .crackfortran import undo_rmbadname, undo_rmbadname1
+
+# The environment provided by auxfuncs.py is needed for some calls to eval.
+# As the needed functions cannot be determined by static inspection of the
+# code, it is safest to use import * pending a major refactoring of f2py.
+from .auxfuncs import *
+
+options = {}
+
+
+def findf90modules(m):
+ if ismodule(m):
+ return [m]
+ if not hasbody(m):
+ return []
+ ret = []
+ for b in m['body']:
+ if ismodule(b):
+ ret.append(b)
+ else:
+ ret = ret + findf90modules(b)
+ return ret
+
+fgetdims1 = """\
+ external f2pysetdata
+ logical ns
+ integer r,i
+ integer(%d) s(*)
+ ns = .FALSE.
+ if (allocated(d)) then
+ do i=1,r
+ if ((size(d,i).ne.s(i)).and.(s(i).ge.0)) then
+ ns = .TRUE.
+ end if
+ end do
+ if (ns) then
+ deallocate(d)
+ end if
+ end if
+ if ((.not.allocated(d)).and.(s(1).ge.1)) then""" % np.intp().itemsize
+
+fgetdims2 = """\
+ end if
+ if (allocated(d)) then
+ do i=1,r
+ s(i) = size(d,i)
+ end do
+ end if
+ flag = 1
+ call f2pysetdata(d,allocated(d))"""
+
+fgetdims2_sa = """\
+ end if
+ if (allocated(d)) then
+ do i=1,r
+ s(i) = size(d,i)
+ end do
+ !s(r) must be equal to len(d(1))
+ end if
+ flag = 2
+ call f2pysetdata(d,allocated(d))"""
+
+
+def buildhooks(pymod):
+ from . import rules
+ ret = {'f90modhooks': [], 'initf90modhooks': [], 'body': [],
+ 'need': ['F_FUNC', 'arrayobject.h'],
+ 'separatorsfor': {'includes0': '\n', 'includes': '\n'},
+ 'docs': ['"Fortran 90/95 modules:\\n"'],
+ 'latexdoc': []}
+ fhooks = ['']
+
+ def fadd(line, s=fhooks):
+ s[0] = '%s\n %s' % (s[0], line)
+ doc = ['']
+
+ def dadd(line, s=doc):
+ s[0] = '%s\n%s' % (s[0], line)
+ for m in findf90modules(pymod):
+ sargs, fargs, efargs, modobjs, notvars, onlyvars = [], [], [], [], [
+ m['name']], []
+ sargsp = []
+ ifargs = []
+ mfargs = []
+ if hasbody(m):
+ for b in m['body']:
+ notvars.append(b['name'])
+ for n in m['vars'].keys():
+ var = m['vars'][n]
+ if (n not in notvars) and (not l_or(isintent_hide, isprivate)(var)):
+ onlyvars.append(n)
+ mfargs.append(n)
+ outmess('\t\tConstructing F90 module support for "%s"...\n' %
+ (m['name']))
+ if onlyvars:
+ outmess('\t\t Variables: %s\n' % (' '.join(onlyvars)))
+ chooks = ['']
+
+ def cadd(line, s=chooks):
+ s[0] = '%s\n%s' % (s[0], line)
+ ihooks = ['']
+
+ def iadd(line, s=ihooks):
+ s[0] = '%s\n%s' % (s[0], line)
+
+ vrd = capi_maps.modsign2map(m)
+ cadd('static FortranDataDef f2py_%s_def[] = {' % (m['name']))
+ dadd('\\subsection{Fortran 90/95 module \\texttt{%s}}\n' % (m['name']))
+ if hasnote(m):
+ note = m['note']
+ if isinstance(note, list):
+ note = '\n'.join(note)
+ dadd(note)
+ if onlyvars:
+ dadd('\\begin{description}')
+ for n in onlyvars:
+ var = m['vars'][n]
+ modobjs.append(n)
+ ct = capi_maps.getctype(var)
+ at = capi_maps.c2capi_map[ct]
+ dm = capi_maps.getarrdims(n, var)
+ dms = dm['dims'].replace('*', '-1').strip()
+ dms = dms.replace(':', '-1').strip()
+ if not dms:
+ dms = '-1'
+ use_fgetdims2 = fgetdims2
+ cadd('\t{"%s",%s,{{%s}},%s, %s},' %
+ (undo_rmbadname1(n), dm['rank'], dms, at,
+ capi_maps.get_elsize(var)))
+ dadd('\\item[]{{}\\verb@%s@{}}' %
+ (capi_maps.getarrdocsign(n, var)))
+ if hasnote(var):
+ note = var['note']
+ if isinstance(note, list):
+ note = '\n'.join(note)
+ dadd('--- %s' % (note))
+ if isallocatable(var):
+ fargs.append('f2py_%s_getdims_%s' % (m['name'], n))
+ efargs.append(fargs[-1])
+ sargs.append(
+ 'void (*%s)(int*,int*,void(*)(char*,int*),int*)' % (n))
+ sargsp.append('void (*)(int*,int*,void(*)(char*,int*),int*)')
+ iadd('\tf2py_%s_def[i_f2py++].func = %s;' % (m['name'], n))
+ fadd('subroutine %s(r,s,f2pysetdata,flag)' % (fargs[-1]))
+ fadd('use %s, only: d => %s\n' %
+ (m['name'], undo_rmbadname1(n)))
+ fadd('integer flag\n')
+ fhooks[0] = fhooks[0] + fgetdims1
+ dms = range(1, int(dm['rank']) + 1)
+ fadd(' allocate(d(%s))\n' %
+ (','.join(['s(%s)' % i for i in dms])))
+ fhooks[0] = fhooks[0] + use_fgetdims2
+ fadd('end subroutine %s' % (fargs[-1]))
+ else:
+ fargs.append(n)
+ sargs.append('char *%s' % (n))
+ sargsp.append('char*')
+ iadd('\tf2py_%s_def[i_f2py++].data = %s;' % (m['name'], n))
+ if onlyvars:
+ dadd('\\end{description}')
+ if hasbody(m):
+ for b in m['body']:
+ if not isroutine(b):
+ outmess("f90mod_rules.buildhooks:"
+ f" skipping {b['block']} {b['name']}\n")
+ continue
+ modobjs.append('%s()' % (b['name']))
+ b['modulename'] = m['name']
+ api, wrap = rules.buildapi(b)
+ if isfunction(b):
+ fhooks[0] = fhooks[0] + wrap
+ fargs.append('f2pywrap_%s_%s' % (m['name'], b['name']))
+ ifargs.append(func2subr.createfuncwrapper(b, signature=1))
+ else:
+ if wrap:
+ fhooks[0] = fhooks[0] + wrap
+ fargs.append('f2pywrap_%s_%s' % (m['name'], b['name']))
+ ifargs.append(
+ func2subr.createsubrwrapper(b, signature=1))
+ else:
+ fargs.append(b['name'])
+ mfargs.append(fargs[-1])
+ api['externroutines'] = []
+ ar = applyrules(api, vrd)
+ ar['docs'] = []
+ ar['docshort'] = []
+ ret = dictappend(ret, ar)
+ cadd(('\t{"%s",-1,{{-1}},0,0,NULL,(void *)'
+ 'f2py_rout_#modulename#_%s_%s,'
+ 'doc_f2py_rout_#modulename#_%s_%s},')
+ % (b['name'], m['name'], b['name'], m['name'], b['name']))
+ sargs.append('char *%s' % (b['name']))
+ sargsp.append('char *')
+ iadd('\tf2py_%s_def[i_f2py++].data = %s;' %
+ (m['name'], b['name']))
+ cadd('\t{NULL}\n};\n')
+ iadd('}')
+ ihooks[0] = 'static void f2py_setup_%s(%s) {\n\tint i_f2py=0;%s' % (
+ m['name'], ','.join(sargs), ihooks[0])
+ if '_' in m['name']:
+ F_FUNC = 'F_FUNC_US'
+ else:
+ F_FUNC = 'F_FUNC'
+ iadd('extern void %s(f2pyinit%s,F2PYINIT%s)(void (*)(%s));'
+ % (F_FUNC, m['name'], m['name'].upper(), ','.join(sargsp)))
+ iadd('static void f2py_init_%s(void) {' % (m['name']))
+ iadd('\t%s(f2pyinit%s,F2PYINIT%s)(f2py_setup_%s);'
+ % (F_FUNC, m['name'], m['name'].upper(), m['name']))
+ iadd('}\n')
+ ret['f90modhooks'] = ret['f90modhooks'] + chooks + ihooks
+ ret['initf90modhooks'] = ['\tPyDict_SetItemString(d, "%s", PyFortranObject_New(f2py_%s_def,f2py_init_%s));' % (
+ m['name'], m['name'], m['name'])] + ret['initf90modhooks']
+ fadd('')
+ fadd('subroutine f2pyinit%s(f2pysetupfunc)' % (m['name']))
+ if mfargs:
+ for a in undo_rmbadname(mfargs):
+ fadd('use %s, only : %s' % (m['name'], a))
+ if ifargs:
+ fadd(' '.join(['interface'] + ifargs))
+ fadd('end interface')
+ fadd('external f2pysetupfunc')
+ if efargs:
+ for a in undo_rmbadname(efargs):
+ fadd('external %s' % (a))
+ fadd('call f2pysetupfunc(%s)' % (','.join(undo_rmbadname(fargs))))
+ fadd('end subroutine f2pyinit%s\n' % (m['name']))
+
+ dadd('\n'.join(ret['latexdoc']).replace(
+ r'\subsection{', r'\subsubsection{'))
+
+ ret['latexdoc'] = []
+ ret['docs'].append('"\t%s --- %s"' % (m['name'],
+ ','.join(undo_rmbadname(modobjs))))
+
+ ret['routine_defs'] = ''
+ ret['doc'] = []
+ ret['docshort'] = []
+ ret['latexdoc'] = doc[0]
+ if len(ret['docs']) <= 1:
+ ret['docs'] = ''
+ return ret, fhooks[0]
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/func2subr.py b/venv/lib/python3.9/site-packages/numpy/f2py/func2subr.py
new file mode 100644
index 00000000..2a05f065
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/func2subr.py
@@ -0,0 +1,303 @@
+#!/usr/bin/env python3
+"""
+
+Rules for building C/API module with f2py2e.
+
+Copyright 1999,2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2004/11/26 11:13:06 $
+Pearu Peterson
+
+"""
+import copy
+
+from .auxfuncs import (
+ getfortranname, isexternal, isfunction, isfunction_wrap, isintent_in,
+ isintent_out, islogicalfunction, ismoduleroutine, isscalar,
+ issubroutine, issubroutine_wrap, outmess, show
+)
+
+
+def var2fixfortran(vars, a, fa=None, f90mode=None):
+ if fa is None:
+ fa = a
+ if a not in vars:
+ show(vars)
+ outmess('var2fixfortran: No definition for argument "%s".\n' % a)
+ return ''
+ if 'typespec' not in vars[a]:
+ show(vars[a])
+ outmess('var2fixfortran: No typespec for argument "%s".\n' % a)
+ return ''
+ vardef = vars[a]['typespec']
+ if vardef == 'type' and 'typename' in vars[a]:
+ vardef = '%s(%s)' % (vardef, vars[a]['typename'])
+ selector = {}
+ lk = ''
+ if 'kindselector' in vars[a]:
+ selector = vars[a]['kindselector']
+ lk = 'kind'
+ elif 'charselector' in vars[a]:
+ selector = vars[a]['charselector']
+ lk = 'len'
+ if '*' in selector:
+ if f90mode:
+ if selector['*'] in ['*', ':', '(*)']:
+ vardef = '%s(len=*)' % (vardef)
+ else:
+ vardef = '%s(%s=%s)' % (vardef, lk, selector['*'])
+ else:
+ if selector['*'] in ['*', ':']:
+ vardef = '%s*(%s)' % (vardef, selector['*'])
+ else:
+ vardef = '%s*%s' % (vardef, selector['*'])
+ else:
+ if 'len' in selector:
+ vardef = '%s(len=%s' % (vardef, selector['len'])
+ if 'kind' in selector:
+ vardef = '%s,kind=%s)' % (vardef, selector['kind'])
+ else:
+ vardef = '%s)' % (vardef)
+ elif 'kind' in selector:
+ vardef = '%s(kind=%s)' % (vardef, selector['kind'])
+
+ vardef = '%s %s' % (vardef, fa)
+ if 'dimension' in vars[a]:
+ vardef = '%s(%s)' % (vardef, ','.join(vars[a]['dimension']))
+ return vardef
+
+
+def createfuncwrapper(rout, signature=0):
+ assert isfunction(rout)
+
+ extra_args = []
+ vars = rout['vars']
+ for a in rout['args']:
+ v = rout['vars'][a]
+ for i, d in enumerate(v.get('dimension', [])):
+ if d == ':':
+ dn = 'f2py_%s_d%s' % (a, i)
+ dv = dict(typespec='integer', intent=['hide'])
+ dv['='] = 'shape(%s, %s)' % (a, i)
+ extra_args.append(dn)
+ vars[dn] = dv
+ v['dimension'][i] = dn
+ rout['args'].extend(extra_args)
+ need_interface = bool(extra_args)
+
+ ret = ['']
+
+ def add(line, ret=ret):
+ ret[0] = '%s\n %s' % (ret[0], line)
+ name = rout['name']
+ fortranname = getfortranname(rout)
+ f90mode = ismoduleroutine(rout)
+ newname = '%sf2pywrap' % (name)
+
+ if newname not in vars:
+ vars[newname] = vars[name]
+ args = [newname] + rout['args'][1:]
+ else:
+ args = [newname] + rout['args']
+
+ l_tmpl = var2fixfortran(vars, name, '@@@NAME@@@', f90mode)
+ if l_tmpl[:13] == 'character*(*)':
+ if f90mode:
+ l_tmpl = 'character(len=10)' + l_tmpl[13:]
+ else:
+ l_tmpl = 'character*10' + l_tmpl[13:]
+ charselect = vars[name]['charselector']
+ if charselect.get('*', '') == '(*)':
+ charselect['*'] = '10'
+
+ l1 = l_tmpl.replace('@@@NAME@@@', newname)
+ rl = None
+
+ sargs = ', '.join(args)
+ if f90mode:
+ add('subroutine f2pywrap_%s_%s (%s)' %
+ (rout['modulename'], name, sargs))
+ if not signature:
+ add('use %s, only : %s' % (rout['modulename'], fortranname))
+ else:
+ add('subroutine f2pywrap%s (%s)' % (name, sargs))
+ if not need_interface:
+ add('external %s' % (fortranname))
+ rl = l_tmpl.replace('@@@NAME@@@', '') + ' ' + fortranname
+
+ if need_interface:
+ for line in rout['saved_interface'].split('\n'):
+ if line.lstrip().startswith('use ') and '__user__' not in line:
+ add(line)
+
+ args = args[1:]
+ dumped_args = []
+ for a in args:
+ if isexternal(vars[a]):
+ add('external %s' % (a))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args:
+ continue
+ if isscalar(vars[a]):
+ add(var2fixfortran(vars, a, f90mode=f90mode))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args:
+ continue
+ if isintent_in(vars[a]):
+ add(var2fixfortran(vars, a, f90mode=f90mode))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args:
+ continue
+ add(var2fixfortran(vars, a, f90mode=f90mode))
+
+ add(l1)
+ if rl is not None:
+ add(rl)
+
+ if need_interface:
+ if f90mode:
+ # f90 module already defines needed interface
+ pass
+ else:
+ add('interface')
+ add(rout['saved_interface'].lstrip())
+ add('end interface')
+
+ sargs = ', '.join([a for a in args if a not in extra_args])
+
+ if not signature:
+ if islogicalfunction(rout):
+ add('%s = .not.(.not.%s(%s))' % (newname, fortranname, sargs))
+ else:
+ add('%s = %s(%s)' % (newname, fortranname, sargs))
+ if f90mode:
+ add('end subroutine f2pywrap_%s_%s' % (rout['modulename'], name))
+ else:
+ add('end')
+ return ret[0]
+
+
+def createsubrwrapper(rout, signature=0):
+ assert issubroutine(rout)
+
+ extra_args = []
+ vars = rout['vars']
+ for a in rout['args']:
+ v = rout['vars'][a]
+ for i, d in enumerate(v.get('dimension', [])):
+ if d == ':':
+ dn = 'f2py_%s_d%s' % (a, i)
+ dv = dict(typespec='integer', intent=['hide'])
+ dv['='] = 'shape(%s, %s)' % (a, i)
+ extra_args.append(dn)
+ vars[dn] = dv
+ v['dimension'][i] = dn
+ rout['args'].extend(extra_args)
+ need_interface = bool(extra_args)
+
+ ret = ['']
+
+ def add(line, ret=ret):
+ ret[0] = '%s\n %s' % (ret[0], line)
+ name = rout['name']
+ fortranname = getfortranname(rout)
+ f90mode = ismoduleroutine(rout)
+
+ args = rout['args']
+
+ sargs = ', '.join(args)
+ if f90mode:
+ add('subroutine f2pywrap_%s_%s (%s)' %
+ (rout['modulename'], name, sargs))
+ if not signature:
+ add('use %s, only : %s' % (rout['modulename'], fortranname))
+ else:
+ add('subroutine f2pywrap%s (%s)' % (name, sargs))
+ if not need_interface:
+ add('external %s' % (fortranname))
+
+ if need_interface:
+ for line in rout['saved_interface'].split('\n'):
+ if line.lstrip().startswith('use ') and '__user__' not in line:
+ add(line)
+
+ dumped_args = []
+ for a in args:
+ if isexternal(vars[a]):
+ add('external %s' % (a))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args:
+ continue
+ if isscalar(vars[a]):
+ add(var2fixfortran(vars, a, f90mode=f90mode))
+ dumped_args.append(a)
+ for a in args:
+ if a in dumped_args:
+ continue
+ add(var2fixfortran(vars, a, f90mode=f90mode))
+
+ if need_interface:
+ if f90mode:
+ # f90 module already defines needed interface
+ pass
+ else:
+ add('interface')
+ for line in rout['saved_interface'].split('\n'):
+ if line.lstrip().startswith('use ') and '__user__' in line:
+ continue
+ add(line)
+ add('end interface')
+
+ sargs = ', '.join([a for a in args if a not in extra_args])
+
+ if not signature:
+ add('call %s(%s)' % (fortranname, sargs))
+ if f90mode:
+ add('end subroutine f2pywrap_%s_%s' % (rout['modulename'], name))
+ else:
+ add('end')
+ return ret[0]
+
+
+def assubr(rout):
+ if isfunction_wrap(rout):
+ fortranname = getfortranname(rout)
+ name = rout['name']
+ outmess('\t\tCreating wrapper for Fortran function "%s"("%s")...\n' % (
+ name, fortranname))
+ rout = copy.copy(rout)
+ fname = name
+ rname = fname
+ if 'result' in rout:
+ rname = rout['result']
+ rout['vars'][fname] = rout['vars'][rname]
+ fvar = rout['vars'][fname]
+ if not isintent_out(fvar):
+ if 'intent' not in fvar:
+ fvar['intent'] = []
+ fvar['intent'].append('out')
+ flag = 1
+ for i in fvar['intent']:
+ if i.startswith('out='):
+ flag = 0
+ break
+ if flag:
+ fvar['intent'].append('out=%s' % (rname))
+ rout['args'][:] = [fname] + rout['args']
+ return rout, createfuncwrapper(rout)
+ if issubroutine_wrap(rout):
+ fortranname = getfortranname(rout)
+ name = rout['name']
+ outmess('\t\tCreating wrapper for Fortran subroutine "%s"("%s")...\n'
+ % (name, fortranname))
+ rout = copy.copy(rout)
+ return rout, createsubrwrapper(rout)
+ return rout, ''
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/rules.py b/venv/lib/python3.9/site-packages/numpy/f2py/rules.py
new file mode 100644
index 00000000..1bac8710
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/rules.py
@@ -0,0 +1,1571 @@
+#!/usr/bin/env python3
+"""
+
+Rules for building C/API module with f2py2e.
+
+Here is a skeleton of a new wrapper function (13Dec2001):
+
+wrapper_function(args)
+ declarations
+ get_python_arguments, say, `a' and `b'
+
+ get_a_from_python
+ if (successful) {
+
+ get_b_from_python
+ if (successful) {
+
+ callfortran
+ if (successful) {
+
+ put_a_to_python
+ if (successful) {
+
+ put_b_to_python
+ if (successful) {
+
+ buildvalue = ...
+
+ }
+
+ }
+
+ }
+
+ }
+ cleanup_b
+
+ }
+ cleanup_a
+
+ return buildvalue
+
+Copyright 1999,2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2005/08/30 08:58:42 $
+Pearu Peterson
+
+"""
+import os, sys
+import time
+import copy
+from pathlib import Path
+
+# __version__.version is now the same as the NumPy version
+from . import __version__
+
+from .auxfuncs import (
+ applyrules, debugcapi, dictappend, errmess, gentitle, getargs2,
+ hascallstatement, hasexternals, hasinitvalue, hasnote,
+ hasresultnote, isarray, isarrayofstrings, ischaracter,
+ ischaracterarray, ischaracter_or_characterarray, iscomplex,
+ iscomplexarray, iscomplexfunction, iscomplexfunction_warn,
+ isdummyroutine, isexternal, isfunction, isfunction_wrap, isint1,
+ isint1array, isintent_aux, isintent_c, isintent_callback,
+ isintent_copy, isintent_hide, isintent_inout, isintent_nothide,
+ isintent_out, isintent_overwrite, islogical, islong_complex,
+ islong_double, islong_doublefunction, islong_long,
+ islong_longfunction, ismoduleroutine, isoptional, isrequired,
+ isscalar, issigned_long_longarray, isstring, isstringarray,
+ isstringfunction, issubroutine, isattr_value,
+ issubroutine_wrap, isthreadsafe, isunsigned, isunsigned_char,
+ isunsigned_chararray, isunsigned_long_long,
+ isunsigned_long_longarray, isunsigned_short, isunsigned_shortarray,
+ l_and, l_not, l_or, outmess, replace, stripcomma, requiresf90wrapper
+)
+
+from . import capi_maps
+from . import cfuncs
+from . import common_rules
+from . import use_rules
+from . import f90mod_rules
+from . import func2subr
+
+f2py_version = __version__.version
+numpy_version = __version__.version
+
+options = {}
+sepdict = {}
+# for k in ['need_cfuncs']: sepdict[k]=','
+for k in ['decl',
+ 'frompyobj',
+ 'cleanupfrompyobj',
+ 'topyarr', 'method',
+ 'pyobjfrom', 'closepyobjfrom',
+ 'freemem',
+ 'userincludes',
+ 'includes0', 'includes', 'typedefs', 'typedefs_generated',
+ 'cppmacros', 'cfuncs', 'callbacks',
+ 'latexdoc',
+ 'restdoc',
+ 'routine_defs', 'externroutines',
+ 'initf2pywraphooks',
+ 'commonhooks', 'initcommonhooks',
+ 'f90modhooks', 'initf90modhooks']:
+ sepdict[k] = '\n'
+
+#################### Rules for C/API module #################
+
+generationtime = int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))
+module_rules = {
+ 'modulebody': """\
+/* File: #modulename#module.c
+ * This file is auto-generated with f2py (version:#f2py_version#).
+ * f2py is a Fortran to Python Interface Generator (FPIG), Second Edition,
+ * written by Pearu Peterson <pearu@cens.ioc.ee>.
+ * Generation date: """ + time.asctime(time.gmtime(generationtime)) + """
+ * Do not edit this file directly unless you know what you are doing!!!
+ */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#ifndef PY_SSIZE_T_CLEAN
+#define PY_SSIZE_T_CLEAN
+#endif /* PY_SSIZE_T_CLEAN */
+
+/* Unconditionally included */
+#include <Python.h>
+#include <numpy/npy_os.h>
+
+""" + gentitle("See f2py2e/cfuncs.py: includes") + """
+#includes#
+#includes0#
+
+""" + gentitle("See f2py2e/rules.py: mod_rules['modulebody']") + """
+static PyObject *#modulename#_error;
+static PyObject *#modulename#_module;
+
+""" + gentitle("See f2py2e/cfuncs.py: typedefs") + """
+#typedefs#
+
+""" + gentitle("See f2py2e/cfuncs.py: typedefs_generated") + """
+#typedefs_generated#
+
+""" + gentitle("See f2py2e/cfuncs.py: cppmacros") + """
+#cppmacros#
+
+""" + gentitle("See f2py2e/cfuncs.py: cfuncs") + """
+#cfuncs#
+
+""" + gentitle("See f2py2e/cfuncs.py: userincludes") + """
+#userincludes#
+
+""" + gentitle("See f2py2e/capi_rules.py: usercode") + """
+#usercode#
+
+/* See f2py2e/rules.py */
+#externroutines#
+
+""" + gentitle("See f2py2e/capi_rules.py: usercode1") + """
+#usercode1#
+
+""" + gentitle("See f2py2e/cb_rules.py: buildcallback") + """
+#callbacks#
+
+""" + gentitle("See f2py2e/rules.py: buildapi") + """
+#body#
+
+""" + gentitle("See f2py2e/f90mod_rules.py: buildhooks") + """
+#f90modhooks#
+
+""" + gentitle("See f2py2e/rules.py: module_rules['modulebody']") + """
+
+""" + gentitle("See f2py2e/common_rules.py: buildhooks") + """
+#commonhooks#
+
+""" + gentitle("See f2py2e/rules.py") + """
+
+static FortranDataDef f2py_routine_defs[] = {
+#routine_defs#
+ {NULL}
+};
+
+static PyMethodDef f2py_module_methods[] = {
+#pymethoddef#
+ {NULL,NULL}
+};
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "#modulename#",
+ NULL,
+ -1,
+ f2py_module_methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC PyInit_#modulename#(void) {
+ int i;
+ PyObject *m,*d, *s, *tmp;
+ m = #modulename#_module = PyModule_Create(&moduledef);
+ Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
+ import_array();
+ if (PyErr_Occurred())
+ {PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return m;}
+ d = PyModule_GetDict(m);
+ s = PyUnicode_FromString(\"#f2py_version#\");
+ PyDict_SetItemString(d, \"__version__\", s);
+ Py_DECREF(s);
+ s = PyUnicode_FromString(
+ \"This module '#modulename#' is auto-generated with f2py (version:#f2py_version#).\\nFunctions:\\n\"\n#docs#\".\");
+ PyDict_SetItemString(d, \"__doc__\", s);
+ Py_DECREF(s);
+ s = PyUnicode_FromString(\"""" + numpy_version + """\");
+ PyDict_SetItemString(d, \"__f2py_numpy_version__\", s);
+ Py_DECREF(s);
+ #modulename#_error = PyErr_NewException (\"#modulename#.error\", NULL, NULL);
+ /*
+ * Store the error object inside the dict, so that it could get deallocated.
+ * (in practice, this is a module, so it likely will not and cannot.)
+ */
+ PyDict_SetItemString(d, \"_#modulename#_error\", #modulename#_error);
+ Py_DECREF(#modulename#_error);
+ for(i=0;f2py_routine_defs[i].name!=NULL;i++) {
+ tmp = PyFortranObject_NewAsAttr(&f2py_routine_defs[i]);
+ PyDict_SetItemString(d, f2py_routine_defs[i].name, tmp);
+ Py_DECREF(tmp);
+ }
+#initf2pywraphooks#
+#initf90modhooks#
+#initcommonhooks#
+#interface_usercode#
+
+#ifdef F2PY_REPORT_ATEXIT
+ if (! PyErr_Occurred())
+ on_exit(f2py_report_on_exit,(void*)\"#modulename#\");
+#endif
+ return m;
+}
+#ifdef __cplusplus
+}
+#endif
+""",
+ 'separatorsfor': {'latexdoc': '\n\n',
+ 'restdoc': '\n\n'},
+ 'latexdoc': ['\\section{Module \\texttt{#texmodulename#}}\n',
+ '#modnote#\n',
+ '#latexdoc#'],
+ 'restdoc': ['Module #modulename#\n' + '=' * 80,
+ '\n#restdoc#']
+}
+
+defmod_rules = [
+ {'body': '/*eof body*/',
+ 'method': '/*eof method*/',
+ 'externroutines': '/*eof externroutines*/',
+ 'routine_defs': '/*eof routine_defs*/',
+ 'initf90modhooks': '/*eof initf90modhooks*/',
+ 'initf2pywraphooks': '/*eof initf2pywraphooks*/',
+ 'initcommonhooks': '/*eof initcommonhooks*/',
+ 'latexdoc': '',
+ 'restdoc': '',
+ 'modnote': {hasnote: '#note#', l_not(hasnote): ''},
+ }
+]
+
+routine_rules = {
+ 'separatorsfor': sepdict,
+ 'body': """
+#begintitle#
+static char doc_#apiname#[] = \"\\\n#docreturn##name#(#docsignatureshort#)\\n\\nWrapper for ``#name#``.\\\n\\n#docstrsigns#\";
+/* #declfortranroutine# */
+static PyObject *#apiname#(const PyObject *capi_self,
+ PyObject *capi_args,
+ PyObject *capi_keywds,
+ #functype# (*f2py_func)(#callprotoargument#)) {
+ PyObject * volatile capi_buildvalue = NULL;
+ volatile int f2py_success = 1;
+#decl#
+ static char *capi_kwlist[] = {#kwlist##kwlistopt##kwlistxa#NULL};
+#usercode#
+#routdebugenter#
+#ifdef F2PY_REPORT_ATEXIT
+f2py_start_clock();
+#endif
+ if (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\
+ \"#argformat#|#keyformat##xaformat#:#pyname#\",\\
+ capi_kwlist#args_capi##keys_capi##keys_xa#))\n return NULL;
+#frompyobj#
+/*end of frompyobj*/
+#ifdef F2PY_REPORT_ATEXIT
+f2py_start_call_clock();
+#endif
+#callfortranroutine#
+if (PyErr_Occurred())
+ f2py_success = 0;
+#ifdef F2PY_REPORT_ATEXIT
+f2py_stop_call_clock();
+#endif
+/*end of callfortranroutine*/
+ if (f2py_success) {
+#pyobjfrom#
+/*end of pyobjfrom*/
+ CFUNCSMESS(\"Building return value.\\n\");
+ capi_buildvalue = Py_BuildValue(\"#returnformat#\"#return#);
+/*closepyobjfrom*/
+#closepyobjfrom#
+ } /*if (f2py_success) after callfortranroutine*/
+/*cleanupfrompyobj*/
+#cleanupfrompyobj#
+ if (capi_buildvalue == NULL) {
+#routdebugfailure#
+ } else {
+#routdebugleave#
+ }
+ CFUNCSMESS(\"Freeing memory.\\n\");
+#freemem#
+#ifdef F2PY_REPORT_ATEXIT
+f2py_stop_clock();
+#endif
+ return capi_buildvalue;
+}
+#endtitle#
+""",
+ 'routine_defs': '#routine_def#',
+ 'initf2pywraphooks': '#initf2pywraphook#',
+ 'externroutines': '#declfortranroutine#',
+ 'doc': '#docreturn##name#(#docsignature#)',
+ 'docshort': '#docreturn##name#(#docsignatureshort#)',
+ 'docs': '" #docreturn##name#(#docsignature#)\\n"\n',
+ 'need': ['arrayobject.h', 'CFUNCSMESS', 'MINMAX'],
+ 'cppmacros': {debugcapi: '#define DEBUGCFUNCS'},
+ 'latexdoc': ['\\subsection{Wrapper function \\texttt{#texname#}}\n',
+ """
+\\noindent{{}\\verb@#docreturn##name#@{}}\\texttt{(#latexdocsignatureshort#)}
+#routnote#
+
+#latexdocstrsigns#
+"""],
+ 'restdoc': ['Wrapped function ``#name#``\n' + '-' * 80,
+
+ ]
+}
+
+################## Rules for C/API function ##############
+
+rout_rules = [
+ { # Init
+ 'separatorsfor': {'callfortranroutine': '\n', 'routdebugenter': '\n', 'decl': '\n',
+ 'routdebugleave': '\n', 'routdebugfailure': '\n',
+ 'setjmpbuf': ' || ',
+ 'docstrreq': '\n', 'docstropt': '\n', 'docstrout': '\n',
+ 'docstrcbs': '\n', 'docstrsigns': '\\n"\n"',
+ 'latexdocstrsigns': '\n',
+ 'latexdocstrreq': '\n', 'latexdocstropt': '\n',
+ 'latexdocstrout': '\n', 'latexdocstrcbs': '\n',
+ },
+ 'kwlist': '', 'kwlistopt': '', 'callfortran': '', 'callfortranappend': '',
+ 'docsign': '', 'docsignopt': '', 'decl': '/*decl*/',
+ 'freemem': '/*freemem*/',
+ 'docsignshort': '', 'docsignoptshort': '',
+ 'docstrsigns': '', 'latexdocstrsigns': '',
+ 'docstrreq': '\\nParameters\\n----------',
+ 'docstropt': '\\nOther Parameters\\n----------------',
+ 'docstrout': '\\nReturns\\n-------',
+ 'docstrcbs': '\\nNotes\\n-----\\nCall-back functions::\\n',
+ 'latexdocstrreq': '\\noindent Required arguments:',
+ 'latexdocstropt': '\\noindent Optional arguments:',
+ 'latexdocstrout': '\\noindent Return objects:',
+ 'latexdocstrcbs': '\\noindent Call-back functions:',
+ 'args_capi': '', 'keys_capi': '', 'functype': '',
+ 'frompyobj': '/*frompyobj*/',
+ # this list will be reversed
+ 'cleanupfrompyobj': ['/*end of cleanupfrompyobj*/'],
+ 'pyobjfrom': '/*pyobjfrom*/',
+ # this list will be reversed
+ 'closepyobjfrom': ['/*end of closepyobjfrom*/'],
+ 'topyarr': '/*topyarr*/', 'routdebugleave': '/*routdebugleave*/',
+ 'routdebugenter': '/*routdebugenter*/',
+ 'routdebugfailure': '/*routdebugfailure*/',
+ 'callfortranroutine': '/*callfortranroutine*/',
+ 'argformat': '', 'keyformat': '', 'need_cfuncs': '',
+ 'docreturn': '', 'return': '', 'returnformat': '', 'rformat': '',
+ 'kwlistxa': '', 'keys_xa': '', 'xaformat': '', 'docsignxa': '', 'docsignxashort': '',
+ 'initf2pywraphook': '',
+ 'routnote': {hasnote: '--- #note#', l_not(hasnote): ''},
+ }, {
+ 'apiname': 'f2py_rout_#modulename#_#name#',
+ 'pyname': '#modulename#.#name#',
+ 'decl': '',
+ '_check': l_not(ismoduleroutine)
+ }, {
+ 'apiname': 'f2py_rout_#modulename#_#f90modulename#_#name#',
+ 'pyname': '#modulename#.#f90modulename#.#name#',
+ 'decl': '',
+ '_check': ismoduleroutine
+ }, { # Subroutine
+ 'functype': 'void',
+ 'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+ l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern void #fortranname#(#callprotoargument#);',
+ ismoduleroutine: '',
+ isdummyroutine: ''
+ },
+ 'routine_def': {
+ l_not(l_or(ismoduleroutine, isintent_c, isdummyroutine)):
+ ' {\"#name#\",-1,{{-1}},0,0,(char *)'
+ ' #F_FUNC#(#fortranname#,#FORTRANNAME#),'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)):
+ ' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine), isdummyroutine):
+ ' {\"#name#\",-1,{{-1}},0,0,NULL,'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'need': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'F_FUNC'},
+ 'callfortranroutine': [
+ {debugcapi: [
+ """ fprintf(stderr,\"debug-capi:Fortran subroutine `#fortranname#(#callfortran#)\'\\n\");"""]},
+ {hasexternals: """\
+ if (#setjmpbuf#) {
+ f2py_success = 0;
+ } else {"""},
+ {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
+ {hascallstatement: ''' #callstatement#;
+ /*(*f2py_func)(#callfortran#);*/'''},
+ {l_not(l_or(hascallstatement, isdummyroutine))
+ : ' (*f2py_func)(#callfortran#);'},
+ {isthreadsafe: ' Py_END_ALLOW_THREADS'},
+ {hasexternals: """ }"""}
+ ],
+ '_check': l_and(issubroutine, l_not(issubroutine_wrap)),
+ }, { # Wrapped function
+ 'functype': 'void',
+ 'declfortranroutine': {l_not(l_or(ismoduleroutine, isdummyroutine)): 'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);',
+ isdummyroutine: '',
+ },
+
+ 'routine_def': {
+ l_not(l_or(ismoduleroutine, isdummyroutine)):
+ ' {\"#name#\",-1,{{-1}},0,0,(char *)'
+ ' #F_WRAPPEDFUNC#(#name_lower#,#NAME#),'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ isdummyroutine:
+ ' {\"#name#\",-1,{{-1}},0,0,NULL,'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'initf2pywraphook': {l_not(l_or(ismoduleroutine, isdummyroutine)): '''
+ {
+ extern #ctype# #F_FUNC#(#name_lower#,#NAME#)(void);
+ PyObject* o = PyDict_GetItemString(d,"#name#");
+ tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL);
+ PyObject_SetAttrString(o,"_cpointer", tmp);
+ Py_DECREF(tmp);
+ s = PyUnicode_FromString("#name#");
+ PyObject_SetAttrString(o,"__name__", s);
+ Py_DECREF(s);
+ }
+ '''},
+ 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']},
+ 'callfortranroutine': [
+ {debugcapi: [
+ """ fprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]},
+ {hasexternals: """\
+ if (#setjmpbuf#) {
+ f2py_success = 0;
+ } else {"""},
+ {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
+ {l_not(l_or(hascallstatement, isdummyroutine))
+ : ' (*f2py_func)(#callfortran#);'},
+ {hascallstatement:
+ ' #callstatement#;\n /*(*f2py_func)(#callfortran#);*/'},
+ {isthreadsafe: ' Py_END_ALLOW_THREADS'},
+ {hasexternals: ' }'}
+ ],
+ '_check': isfunction_wrap,
+ }, { # Wrapped subroutine
+ 'functype': 'void',
+ 'declfortranroutine': {l_not(l_or(ismoduleroutine, isdummyroutine)): 'extern void #F_WRAPPEDFUNC#(#name_lower#,#NAME#)(#callprotoargument#);',
+ isdummyroutine: '',
+ },
+
+ 'routine_def': {
+ l_not(l_or(ismoduleroutine, isdummyroutine)):
+ ' {\"#name#\",-1,{{-1}},0,0,(char *)'
+ ' #F_WRAPPEDFUNC#(#name_lower#,#NAME#),'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ isdummyroutine:
+ ' {\"#name#\",-1,{{-1}},0,0,NULL,'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'initf2pywraphook': {l_not(l_or(ismoduleroutine, isdummyroutine)): '''
+ {
+ extern void #F_FUNC#(#name_lower#,#NAME#)(void);
+ PyObject* o = PyDict_GetItemString(d,"#name#");
+ tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL);
+ PyObject_SetAttrString(o,"_cpointer", tmp);
+ Py_DECREF(tmp);
+ s = PyUnicode_FromString("#name#");
+ PyObject_SetAttrString(o,"__name__", s);
+ Py_DECREF(s);
+ }
+ '''},
+ 'need': {l_not(l_or(ismoduleroutine, isdummyroutine)): ['F_WRAPPEDFUNC', 'F_FUNC']},
+ 'callfortranroutine': [
+ {debugcapi: [
+ """ fprintf(stderr,\"debug-capi:Fortran subroutine `f2pywrap#name_lower#(#callfortran#)\'\\n\");"""]},
+ {hasexternals: """\
+ if (#setjmpbuf#) {
+ f2py_success = 0;
+ } else {"""},
+ {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
+ {l_not(l_or(hascallstatement, isdummyroutine))
+ : ' (*f2py_func)(#callfortran#);'},
+ {hascallstatement:
+ ' #callstatement#;\n /*(*f2py_func)(#callfortran#);*/'},
+ {isthreadsafe: ' Py_END_ALLOW_THREADS'},
+ {hasexternals: ' }'}
+ ],
+ '_check': issubroutine_wrap,
+ }, { # Function
+ 'functype': '#ctype#',
+ 'docreturn': {l_not(isintent_hide): '#rname#,'},
+ 'docstrout': '#pydocsignout#',
+ 'latexdocstrout': ['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {hasresultnote: '--- #resultnote#'}],
+ 'callfortranroutine': [{l_and(debugcapi, isstringfunction): """\
+#ifdef USESCOMPAQFORTRAN
+ fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callcompaqfortran#)\\n\");
+#else
+ fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\");
+#endif
+"""},
+ {l_and(debugcapi, l_not(isstringfunction)): """\
+ fprintf(stderr,\"debug-capi:Fortran function #ctype# #fortranname#(#callfortran#)\\n\");
+"""}
+ ],
+ '_check': l_and(isfunction, l_not(isfunction_wrap))
+ }, { # Scalar function
+ 'declfortranroutine': {l_and(l_not(l_or(ismoduleroutine, isintent_c)), l_not(isdummyroutine)): 'extern #ctype# #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+ l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)): 'extern #ctype# #fortranname#(#callprotoargument#);',
+ isdummyroutine: ''
+ },
+ 'routine_def': {
+ l_and(l_not(l_or(ismoduleroutine, isintent_c)),
+ l_not(isdummyroutine)):
+ (' {\"#name#\",-1,{{-1}},0,0,(char *)'
+ ' #F_FUNC#(#fortranname#,#FORTRANNAME#),'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},'),
+ l_and(l_not(ismoduleroutine), isintent_c, l_not(isdummyroutine)):
+ (' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,'
+ ' (f2py_init_func)#apiname#,doc_#apiname#},'),
+ isdummyroutine:
+ ' {\"#name#\",-1,{{-1}},0,0,NULL,'
+ '(f2py_init_func)#apiname#,doc_#apiname#},',
+ },
+ 'decl': [{iscomplexfunction_warn: ' #ctype# #name#_return_value={0,0};',
+ l_not(iscomplexfunction): ' #ctype# #name#_return_value=0;'},
+ {iscomplexfunction:
+ ' PyObject *#name#_return_value_capi = Py_None;'}
+ ],
+ 'callfortranroutine': [
+ {hasexternals: """\
+ if (#setjmpbuf#) {
+ f2py_success = 0;
+ } else {"""},
+ {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
+ {hascallstatement: ''' #callstatement#;
+/* #name#_return_value = (*f2py_func)(#callfortran#);*/
+'''},
+ {l_not(l_or(hascallstatement, isdummyroutine))
+ : ' #name#_return_value = (*f2py_func)(#callfortran#);'},
+ {isthreadsafe: ' Py_END_ALLOW_THREADS'},
+ {hasexternals: ' }'},
+ {l_and(debugcapi, iscomplexfunction)
+ : ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value.r,#name#_return_value.i);'},
+ {l_and(debugcapi, l_not(iscomplexfunction)): ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value);'}],
+ 'pyobjfrom': {iscomplexfunction: ' #name#_return_value_capi = pyobj_from_#ctype#1(#name#_return_value);'},
+ 'need': [{l_not(isdummyroutine): 'F_FUNC'},
+ {iscomplexfunction: 'pyobj_from_#ctype#1'},
+ {islong_longfunction: 'long_long'},
+ {islong_doublefunction: 'long_double'}],
+ 'returnformat': {l_not(isintent_hide): '#rformat#'},
+ 'return': {iscomplexfunction: ',#name#_return_value_capi',
+ l_not(l_or(iscomplexfunction, isintent_hide)): ',#name#_return_value'},
+ '_check': l_and(isfunction, l_not(isstringfunction), l_not(isfunction_wrap))
+ }, { # String function # in use for --no-wrap
+ 'declfortranroutine': 'extern void #F_FUNC#(#fortranname#,#FORTRANNAME#)(#callprotoargument#);',
+ 'routine_def': {l_not(l_or(ismoduleroutine, isintent_c)):
+ ' {\"#name#\",-1,{{-1}},0,0,(char *)#F_FUNC#(#fortranname#,#FORTRANNAME#),(f2py_init_func)#apiname#,doc_#apiname#},',
+ l_and(l_not(ismoduleroutine), isintent_c):
+ ' {\"#name#\",-1,{{-1}},0,0,(char *)#fortranname#,(f2py_init_func)#apiname#,doc_#apiname#},'
+ },
+ 'decl': [' #ctype# #name#_return_value = NULL;',
+ ' int #name#_return_value_len = 0;'],
+ 'callfortran':'#name#_return_value,#name#_return_value_len,',
+ 'callfortranroutine':[' #name#_return_value_len = #rlength#;',
+ ' if ((#name#_return_value = (string)malloc('
+ + '#name#_return_value_len+1) == NULL) {',
+ ' PyErr_SetString(PyExc_MemoryError, \"out of memory\");',
+ ' f2py_success = 0;',
+ ' } else {',
+ " (#name#_return_value)[#name#_return_value_len] = '\\0';",
+ ' }',
+ ' if (f2py_success) {',
+ {hasexternals: """\
+ if (#setjmpbuf#) {
+ f2py_success = 0;
+ } else {"""},
+ {isthreadsafe: ' Py_BEGIN_ALLOW_THREADS'},
+ """\
+#ifdef USESCOMPAQFORTRAN
+ (*f2py_func)(#callcompaqfortran#);
+#else
+ (*f2py_func)(#callfortran#);
+#endif
+""",
+ {isthreadsafe: ' Py_END_ALLOW_THREADS'},
+ {hasexternals: ' }'},
+ {debugcapi:
+ ' fprintf(stderr,"#routdebugshowvalue#\\n",#name#_return_value_len,#name#_return_value);'},
+ ' } /* if (f2py_success) after (string)malloc */',
+ ],
+ 'returnformat': '#rformat#',
+ 'return': ',#name#_return_value',
+ 'freemem': ' STRINGFREE(#name#_return_value);',
+ 'need': ['F_FUNC', '#ctype#', 'STRINGFREE'],
+ '_check':l_and(isstringfunction, l_not(isfunction_wrap)) # ???obsolete
+ },
+ { # Debugging
+ 'routdebugenter': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#(#docsignature#)\\n");',
+ 'routdebugleave': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: successful.\\n");',
+ 'routdebugfailure': ' fprintf(stderr,"debug-capi:Python C/API function #modulename#.#name#: failure.\\n");',
+ '_check': debugcapi
+ }
+]
+
+################ Rules for arguments ##################
+
+typedef_need_dict = {islong_long: 'long_long',
+ islong_double: 'long_double',
+ islong_complex: 'complex_long_double',
+ isunsigned_char: 'unsigned_char',
+ isunsigned_short: 'unsigned_short',
+ isunsigned: 'unsigned',
+ isunsigned_long_long: 'unsigned_long_long',
+ isunsigned_chararray: 'unsigned_char',
+ isunsigned_shortarray: 'unsigned_short',
+ isunsigned_long_longarray: 'unsigned_long_long',
+ issigned_long_longarray: 'long_long',
+ isint1: 'signed_char',
+ ischaracter_or_characterarray: 'character',
+ }
+
+aux_rules = [
+ {
+ 'separatorsfor': sepdict
+ },
+ { # Common
+ 'frompyobj': [' /* Processing auxiliary variable #varname# */',
+ {debugcapi: ' fprintf(stderr,"#vardebuginfo#\\n");'}, ],
+ 'cleanupfrompyobj': ' /* End of cleaning variable #varname# */',
+ 'need': typedef_need_dict,
+ },
+ # Scalars (not complex)
+ { # Common
+ 'decl': ' #ctype# #varname# = 0;',
+ 'need': {hasinitvalue: 'math.h'},
+ 'frompyobj': {hasinitvalue: ' #varname# = #init#;'},
+ '_check': l_and(isscalar, l_not(iscomplex)),
+ },
+ {
+ 'return': ',#varname#',
+ 'docstrout': '#pydocsignout#',
+ 'docreturn': '#outvarname#,',
+ 'returnformat': '#varrformat#',
+ '_check': l_and(isscalar, l_not(iscomplex), isintent_out),
+ },
+ # Complex scalars
+ { # Common
+ 'decl': ' #ctype# #varname#;',
+ 'frompyobj': {hasinitvalue: ' #varname#.r = #init.r#, #varname#.i = #init.i#;'},
+ '_check': iscomplex
+ },
+ # String
+ { # Common
+ 'decl': [' #ctype# #varname# = NULL;',
+ ' int slen(#varname#);',
+ ],
+ 'need':['len..'],
+ '_check':isstring
+ },
+ # Array
+ { # Common
+ 'decl': [' #ctype# *#varname# = NULL;',
+ ' npy_intp #varname#_Dims[#rank#] = {#rank*[-1]#};',
+ ' const int #varname#_Rank = #rank#;',
+ ],
+ 'need':['len..', {hasinitvalue: 'forcomb'}, {hasinitvalue: 'CFUNCSMESS'}],
+ '_check': isarray
+ },
+ # Scalararray
+ { # Common
+ '_check': l_and(isarray, l_not(iscomplexarray))
+ }, { # Not hidden
+ '_check': l_and(isarray, l_not(iscomplexarray), isintent_nothide)
+ },
+ # Integer*1 array
+ {'need': '#ctype#',
+ '_check': isint1array,
+ '_depend': ''
+ },
+ # Integer*-1 array
+ {'need': '#ctype#',
+ '_check': l_or(isunsigned_chararray, isunsigned_char),
+ '_depend': ''
+ },
+ # Integer*-2 array
+ {'need': '#ctype#',
+ '_check': isunsigned_shortarray,
+ '_depend': ''
+ },
+ # Integer*-8 array
+ {'need': '#ctype#',
+ '_check': isunsigned_long_longarray,
+ '_depend': ''
+ },
+ # Complexarray
+ {'need': '#ctype#',
+ '_check': iscomplexarray,
+ '_depend': ''
+ },
+ # Stringarray
+ {
+ 'callfortranappend': {isarrayofstrings: 'flen(#varname#),'},
+ 'need': 'string',
+ '_check': isstringarray
+ }
+]
+
+arg_rules = [
+ {
+ 'separatorsfor': sepdict
+ },
+ { # Common
+ 'frompyobj': [' /* Processing variable #varname# */',
+ {debugcapi: ' fprintf(stderr,"#vardebuginfo#\\n");'}, ],
+ 'cleanupfrompyobj': ' /* End of cleaning variable #varname# */',
+ '_depend': '',
+ 'need': typedef_need_dict,
+ },
+ # Doc signatures
+ {
+ 'docstropt': {l_and(isoptional, isintent_nothide): '#pydocsign#'},
+ 'docstrreq': {l_and(isrequired, isintent_nothide): '#pydocsign#'},
+ 'docstrout': {isintent_out: '#pydocsignout#'},
+ 'latexdocstropt': {l_and(isoptional, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote: '--- #note#'}]},
+ 'latexdocstrreq': {l_and(isrequired, isintent_nothide): ['\\item[]{{}\\verb@#pydocsign#@{}}',
+ {hasnote: '--- #note#'}]},
+ 'latexdocstrout': {isintent_out: ['\\item[]{{}\\verb@#pydocsignout#@{}}',
+ {l_and(hasnote, isintent_hide): '--- #note#',
+ l_and(hasnote, isintent_nothide): '--- See above.'}]},
+ 'depend': ''
+ },
+ # Required/Optional arguments
+ {
+ 'kwlist': '"#varname#",',
+ 'docsign': '#varname#,',
+ '_check': l_and(isintent_nothide, l_not(isoptional))
+ },
+ {
+ 'kwlistopt': '"#varname#",',
+ 'docsignopt': '#varname#=#showinit#,',
+ 'docsignoptshort': '#varname#,',
+ '_check': l_and(isintent_nothide, isoptional)
+ },
+ # Docstring/BuildValue
+ {
+ 'docreturn': '#outvarname#,',
+ 'returnformat': '#varrformat#',
+ '_check': isintent_out
+ },
+ # Externals (call-back functions)
+ { # Common
+ 'docsignxa': {isintent_nothide: '#varname#_extra_args=(),'},
+ 'docsignxashort': {isintent_nothide: '#varname#_extra_args,'},
+ 'docstropt': {isintent_nothide: '#varname#_extra_args : input tuple, optional\\n Default: ()'},
+ 'docstrcbs': '#cbdocstr#',
+ 'latexdocstrcbs': '\\item[] #cblatexdocstr#',
+ 'latexdocstropt': {isintent_nothide: '\\item[]{{}\\verb@#varname#_extra_args := () input tuple@{}} --- Extra arguments for call-back function {{}\\verb@#varname#@{}}.'},
+ 'decl': [' #cbname#_t #varname#_cb = { Py_None, NULL, 0 };',
+ ' #cbname#_t *#varname#_cb_ptr = &#varname#_cb;',
+ ' PyTupleObject *#varname#_xa_capi = NULL;',
+ {l_not(isintent_callback):
+ ' #cbname#_typedef #varname#_cptr;'}
+ ],
+ 'kwlistxa': {isintent_nothide: '"#varname#_extra_args",'},
+ 'argformat': {isrequired: 'O'},
+ 'keyformat': {isoptional: 'O'},
+ 'xaformat': {isintent_nothide: 'O!'},
+ 'args_capi': {isrequired: ',&#varname#_cb.capi'},
+ 'keys_capi': {isoptional: ',&#varname#_cb.capi'},
+ 'keys_xa': ',&PyTuple_Type,&#varname#_xa_capi',
+ 'setjmpbuf': '(setjmp(#varname#_cb.jmpbuf))',
+ 'callfortran': {l_not(isintent_callback): '#varname#_cptr,'},
+ 'need': ['#cbname#', 'setjmp.h'],
+ '_check':isexternal
+ },
+ {
+ 'frompyobj': [{l_not(isintent_callback): """\
+if(F2PyCapsule_Check(#varname#_cb.capi)) {
+ #varname#_cptr = F2PyCapsule_AsVoidPtr(#varname#_cb.capi);
+} else {
+ #varname#_cptr = #cbname#;
+}
+"""}, {isintent_callback: """\
+if (#varname#_cb.capi==Py_None) {
+ #varname#_cb.capi = PyObject_GetAttrString(#modulename#_module,\"#varname#\");
+ if (#varname#_cb.capi) {
+ if (#varname#_xa_capi==NULL) {
+ if (PyObject_HasAttrString(#modulename#_module,\"#varname#_extra_args\")) {
+ PyObject* capi_tmp = PyObject_GetAttrString(#modulename#_module,\"#varname#_extra_args\");
+ if (capi_tmp) {
+ #varname#_xa_capi = (PyTupleObject *)PySequence_Tuple(capi_tmp);
+ Py_DECREF(capi_tmp);
+ }
+ else {
+ #varname#_xa_capi = (PyTupleObject *)Py_BuildValue(\"()\");
+ }
+ if (#varname#_xa_capi==NULL) {
+ PyErr_SetString(#modulename#_error,\"Failed to convert #modulename#.#varname#_extra_args to tuple.\\n\");
+ return NULL;
+ }
+ }
+ }
+ }
+ if (#varname#_cb.capi==NULL) {
+ PyErr_SetString(#modulename#_error,\"Callback #varname# not defined (as an argument or module #modulename# attribute).\\n\");
+ return NULL;
+ }
+}
+"""},
+ """\
+ if (create_cb_arglist(#varname#_cb.capi,#varname#_xa_capi,#maxnofargs#,#nofoptargs#,&#varname#_cb.nofargs,&#varname#_cb.args_capi,\"failed in processing argument list for call-back #varname#.\")) {
+""",
+ {debugcapi: ["""\
+ fprintf(stderr,\"debug-capi:Assuming %d arguments; at most #maxnofargs#(-#nofoptargs#) is expected.\\n\",#varname#_cb.nofargs);
+ CFUNCSMESSPY(\"for #varname#=\",#varname#_cb.capi);""",
+ {l_not(isintent_callback): """ fprintf(stderr,\"#vardebugshowvalue# (call-back in C).\\n\",#cbname#);"""}]},
+ """\
+ CFUNCSMESS(\"Saving callback variables for `#varname#`.\\n\");
+ #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);""",
+ ],
+ 'cleanupfrompyobj':
+ """\
+ CFUNCSMESS(\"Restoring callback variables for `#varname#`.\\n\");
+ #varname#_cb_ptr = swap_active_#cbname#(#varname#_cb_ptr);
+ Py_DECREF(#varname#_cb.args_capi);
+ }""",
+ 'need': ['SWAP', 'create_cb_arglist'],
+ '_check':isexternal,
+ '_depend':''
+ },
+ # Scalars (not complex)
+ { # Common
+ 'decl': ' #ctype# #varname# = 0;',
+ 'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
+ 'callfortran': {l_or(isintent_c, isattr_value): '#varname#,', l_not(l_or(isintent_c, isattr_value)): '&#varname#,'},
+ 'return': {isintent_out: ',#varname#'},
+ '_check': l_and(isscalar, l_not(iscomplex))
+ }, {
+ 'need': {hasinitvalue: 'math.h'},
+ '_check': l_and(isscalar, l_not(iscomplex)),
+ }, { # Not hidden
+ 'decl': ' PyObject *#varname#_capi = Py_None;',
+ 'argformat': {isrequired: 'O'},
+ 'keyformat': {isoptional: 'O'},
+ 'args_capi': {isrequired: ',&#varname#_capi'},
+ 'keys_capi': {isoptional: ',&#varname#_capi'},
+ 'pyobjfrom': {isintent_inout: """\
+ f2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#);
+ if (f2py_success) {"""},
+ 'closepyobjfrom': {isintent_inout: " } /*if (f2py_success) of #varname# pyobjfrom*/"},
+ 'need': {isintent_inout: 'try_pyarr_from_#ctype#'},
+ '_check': l_and(isscalar, l_not(iscomplex), l_not(isstring),
+ isintent_nothide)
+ }, {
+ 'frompyobj': [
+ # hasinitvalue...
+ # if pyobj is None:
+ # varname = init
+ # else
+ # from_pyobj(varname)
+ #
+ # isoptional and noinitvalue...
+ # if pyobj is not None:
+ # from_pyobj(varname)
+ # else:
+ # varname is uninitialized
+ #
+ # ...
+ # from_pyobj(varname)
+ #
+ {hasinitvalue: ' if (#varname#_capi == Py_None) #varname# = #init#; else',
+ '_depend': ''},
+ {l_and(isoptional, l_not(hasinitvalue)): ' if (#varname#_capi != Py_None)',
+ '_depend': ''},
+ {l_not(islogical): '''\
+ f2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");
+ if (f2py_success) {'''},
+ {islogical: '''\
+ #varname# = (#ctype#)PyObject_IsTrue(#varname#_capi);
+ f2py_success = 1;
+ if (f2py_success) {'''},
+ ],
+ 'cleanupfrompyobj': ' } /*if (f2py_success) of #varname#*/',
+ 'need': {l_not(islogical): '#ctype#_from_pyobj'},
+ '_check': l_and(isscalar, l_not(iscomplex), isintent_nothide),
+ '_depend': ''
+ }, { # Hidden
+ 'frompyobj': {hasinitvalue: ' #varname# = #init#;'},
+ 'need': typedef_need_dict,
+ '_check': l_and(isscalar, l_not(iscomplex), isintent_hide),
+ '_depend': ''
+ }, { # Common
+ 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#);'},
+ '_check': l_and(isscalar, l_not(iscomplex)),
+ '_depend': ''
+ },
+ # Complex scalars
+ { # Common
+ 'decl': ' #ctype# #varname#;',
+ 'callfortran': {isintent_c: '#varname#,', l_not(isintent_c): '&#varname#,'},
+ 'pyobjfrom': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'},
+ 'return': {isintent_out: ',#varname#_capi'},
+ '_check': iscomplex
+ }, { # Not hidden
+ 'decl': ' PyObject *#varname#_capi = Py_None;',
+ 'argformat': {isrequired: 'O'},
+ 'keyformat': {isoptional: 'O'},
+ 'args_capi': {isrequired: ',&#varname#_capi'},
+ 'keys_capi': {isoptional: ',&#varname#_capi'},
+ 'need': {isintent_inout: 'try_pyarr_from_#ctype#'},
+ 'pyobjfrom': {isintent_inout: """\
+ f2py_success = try_pyarr_from_#ctype#(#varname#_capi,&#varname#);
+ if (f2py_success) {"""},
+ 'closepyobjfrom': {isintent_inout: " } /*if (f2py_success) of #varname# pyobjfrom*/"},
+ '_check': l_and(iscomplex, isintent_nothide)
+ }, {
+ 'frompyobj': [{hasinitvalue: ' if (#varname#_capi==Py_None) {#varname#.r = #init.r#, #varname#.i = #init.i#;} else'},
+ {l_and(isoptional, l_not(hasinitvalue))
+ : ' if (#varname#_capi != Py_None)'},
+ ' f2py_success = #ctype#_from_pyobj(&#varname#,#varname#_capi,"#pyname#() #nth# (#varname#) can\'t be converted to #ctype#");'
+ '\n if (f2py_success) {'],
+ 'cleanupfrompyobj': ' } /*if (f2py_success) of #varname# frompyobj*/',
+ 'need': ['#ctype#_from_pyobj'],
+ '_check': l_and(iscomplex, isintent_nothide),
+ '_depend': ''
+ }, { # Hidden
+ 'decl': {isintent_out: ' PyObject *#varname#_capi = Py_None;'},
+ '_check': l_and(iscomplex, isintent_hide)
+ }, {
+ 'frompyobj': {hasinitvalue: ' #varname#.r = #init.r#, #varname#.i = #init.i#;'},
+ '_check': l_and(iscomplex, isintent_hide),
+ '_depend': ''
+ }, { # Common
+ 'pyobjfrom': {isintent_out: ' #varname#_capi = pyobj_from_#ctype#1(#varname#);'},
+ 'need': ['pyobj_from_#ctype#1'],
+ '_check': iscomplex
+ }, {
+ 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",#varname#.r,#varname#.i);'},
+ '_check': iscomplex,
+ '_depend': ''
+ },
+ # String
+ { # Common
+ 'decl': [' #ctype# #varname# = NULL;',
+ ' int slen(#varname#);',
+ ' PyObject *#varname#_capi = Py_None;'],
+ 'callfortran':'#varname#,',
+ 'callfortranappend':'slen(#varname#),',
+ 'pyobjfrom':[
+ {debugcapi:
+ ' fprintf(stderr,'
+ '"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'},
+ # The trailing null value for Fortran is blank.
+ {l_and(isintent_out, l_not(isintent_c)):
+ " STRINGPADN(#varname#, slen(#varname#), ' ', '\\0');"},
+ ],
+ 'return': {isintent_out: ',#varname#'},
+ 'need': ['len..',
+ {l_and(isintent_out, l_not(isintent_c)): 'STRINGPADN'}],
+ '_check': isstring
+ }, { # Common
+ 'frompyobj': [
+ """\
+ slen(#varname#) = #elsize#;
+ f2py_success = #ctype#_from_pyobj(&#varname#,&slen(#varname#),#init#,"""
+"""#varname#_capi,\"#ctype#_from_pyobj failed in converting #nth#"""
+"""`#varname#\' of #pyname# to C #ctype#\");
+ if (f2py_success) {""",
+ # The trailing null value for Fortran is blank.
+ {l_not(isintent_c):
+ " STRINGPADN(#varname#, slen(#varname#), '\\0', ' ');"},
+ ],
+ 'cleanupfrompyobj': """\
+ STRINGFREE(#varname#);
+ } /*if (f2py_success) of #varname#*/""",
+ 'need': ['#ctype#_from_pyobj', 'len..', 'STRINGFREE',
+ {l_not(isintent_c): 'STRINGPADN'}],
+ '_check':isstring,
+ '_depend':''
+ }, { # Not hidden
+ 'argformat': {isrequired: 'O'},
+ 'keyformat': {isoptional: 'O'},
+ 'args_capi': {isrequired: ',&#varname#_capi'},
+ 'keys_capi': {isoptional: ',&#varname#_capi'},
+ 'pyobjfrom': [
+ {l_and(isintent_inout, l_not(isintent_c)):
+ " STRINGPADN(#varname#, slen(#varname#), ' ', '\\0');"},
+ {isintent_inout: '''\
+ f2py_success = try_pyarr_from_#ctype#(#varname#_capi, #varname#,
+ slen(#varname#));
+ if (f2py_success) {'''}],
+ 'closepyobjfrom': {isintent_inout: ' } /*if (f2py_success) of #varname# pyobjfrom*/'},
+ 'need': {isintent_inout: 'try_pyarr_from_#ctype#',
+ l_and(isintent_inout, l_not(isintent_c)): 'STRINGPADN'},
+ '_check': l_and(isstring, isintent_nothide)
+ }, { # Hidden
+ '_check': l_and(isstring, isintent_hide)
+ }, {
+ 'frompyobj': {debugcapi: ' fprintf(stderr,"#vardebugshowvalue#\\n",slen(#varname#),#varname#);'},
+ '_check': isstring,
+ '_depend': ''
+ },
+ # Array
+ { # Common
+ 'decl': [' #ctype# *#varname# = NULL;',
+ ' npy_intp #varname#_Dims[#rank#] = {#rank*[-1]#};',
+ ' const int #varname#_Rank = #rank#;',
+ ' PyArrayObject *capi_#varname#_as_array = NULL;',
+ ' int capi_#varname#_intent = 0;',
+ {isstringarray: ' int slen(#varname#) = 0;'},
+ ],
+ 'callfortran':'#varname#,',
+ 'callfortranappend': {isstringarray: 'slen(#varname#),'},
+ 'return': {isintent_out: ',capi_#varname#_as_array'},
+ 'need': 'len..',
+ '_check': isarray
+ }, { # intent(overwrite) array
+ 'decl': ' int capi_overwrite_#varname# = 1;',
+ 'kwlistxa': '"overwrite_#varname#",',
+ 'xaformat': 'i',
+ 'keys_xa': ',&capi_overwrite_#varname#',
+ 'docsignxa': 'overwrite_#varname#=1,',
+ 'docsignxashort': 'overwrite_#varname#,',
+ 'docstropt': 'overwrite_#varname# : input int, optional\\n Default: 1',
+ '_check': l_and(isarray, isintent_overwrite),
+ }, {
+ 'frompyobj': ' capi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);',
+ '_check': l_and(isarray, isintent_overwrite),
+ '_depend': '',
+ },
+ { # intent(copy) array
+ 'decl': ' int capi_overwrite_#varname# = 0;',
+ 'kwlistxa': '"overwrite_#varname#",',
+ 'xaformat': 'i',
+ 'keys_xa': ',&capi_overwrite_#varname#',
+ 'docsignxa': 'overwrite_#varname#=0,',
+ 'docsignxashort': 'overwrite_#varname#,',
+ 'docstropt': 'overwrite_#varname# : input int, optional\\n Default: 0',
+ '_check': l_and(isarray, isintent_copy),
+ }, {
+ 'frompyobj': ' capi_#varname#_intent |= (capi_overwrite_#varname#?0:F2PY_INTENT_COPY);',
+ '_check': l_and(isarray, isintent_copy),
+ '_depend': '',
+ }, {
+ 'need': [{hasinitvalue: 'forcomb'}, {hasinitvalue: 'CFUNCSMESS'}],
+ '_check': isarray,
+ '_depend': ''
+ }, { # Not hidden
+ 'decl': ' PyObject *#varname#_capi = Py_None;',
+ 'argformat': {isrequired: 'O'},
+ 'keyformat': {isoptional: 'O'},
+ 'args_capi': {isrequired: ',&#varname#_capi'},
+ 'keys_capi': {isoptional: ',&#varname#_capi'},
+ '_check': l_and(isarray, isintent_nothide)
+ }, {
+ 'frompyobj': [
+ ' #setdims#;',
+ ' capi_#varname#_intent |= #intent#;',
+ (' const char * capi_errmess = "#modulename#.#pyname#:'
+ ' failed to create array from the #nth# `#varname#`";'),
+ {isintent_hide:
+ ' capi_#varname#_as_array = ndarray_from_pyobj('
+ ' #atype#,#elsize#,#varname#_Dims,#varname#_Rank,'
+ ' capi_#varname#_intent,Py_None,capi_errmess);'},
+ {isintent_nothide:
+ ' capi_#varname#_as_array = ndarray_from_pyobj('
+ ' #atype#,#elsize#,#varname#_Dims,#varname#_Rank,'
+ ' capi_#varname#_intent,#varname#_capi,capi_errmess);'},
+ """\
+ if (capi_#varname#_as_array == NULL) {
+ PyObject* capi_err = PyErr_Occurred();
+ if (capi_err == NULL) {
+ capi_err = #modulename#_error;
+ PyErr_SetString(capi_err, capi_errmess);
+ }
+ } else {
+ #varname# = (#ctype# *)(PyArray_DATA(capi_#varname#_as_array));
+""",
+ {isstringarray:
+ ' slen(#varname#) = f2py_itemsize(#varname#);'},
+ {hasinitvalue: [
+ {isintent_nothide:
+ ' if (#varname#_capi == Py_None) {'},
+ {isintent_hide: ' {'},
+ {iscomplexarray: ' #ctype# capi_c;'},
+ """\
+ int *_i,capi_i=0;
+ CFUNCSMESS(\"#name#: Initializing #varname#=#init#\\n\");
+ if (initforcomb(PyArray_DIMS(capi_#varname#_as_array),
+ PyArray_NDIM(capi_#varname#_as_array),1)) {
+ while ((_i = nextforcomb()))
+ #varname#[capi_i++] = #init#; /* fortran way */
+ } else {
+ PyObject *exc, *val, *tb;
+ PyErr_Fetch(&exc, &val, &tb);
+ PyErr_SetString(exc ? exc : #modulename#_error,
+ \"Initialization of #nth# #varname# failed (initforcomb).\");
+ npy_PyErr_ChainExceptionsCause(exc, val, tb);
+ f2py_success = 0;
+ }
+ }
+ if (f2py_success) {"""]},
+ ],
+ 'cleanupfrompyobj': [ # note that this list will be reversed
+ ' } '
+ '/* if (capi_#varname#_as_array == NULL) ... else of #varname# */',
+ {l_not(l_or(isintent_out, isintent_hide)): """\
+ if((PyObject *)capi_#varname#_as_array!=#varname#_capi) {
+ Py_XDECREF(capi_#varname#_as_array); }"""},
+ {l_and(isintent_hide, l_not(isintent_out))
+ : """ Py_XDECREF(capi_#varname#_as_array);"""},
+ {hasinitvalue: ' } /*if (f2py_success) of #varname# init*/'},
+ ],
+ '_check': isarray,
+ '_depend': ''
+ },
+ # Scalararray
+ { # Common
+ '_check': l_and(isarray, l_not(iscomplexarray))
+ }, { # Not hidden
+ '_check': l_and(isarray, l_not(iscomplexarray), isintent_nothide)
+ },
+ # Integer*1 array
+ {'need': '#ctype#',
+ '_check': isint1array,
+ '_depend': ''
+ },
+ # Integer*-1 array
+ {'need': '#ctype#',
+ '_check': isunsigned_chararray,
+ '_depend': ''
+ },
+ # Integer*-2 array
+ {'need': '#ctype#',
+ '_check': isunsigned_shortarray,
+ '_depend': ''
+ },
+ # Integer*-8 array
+ {'need': '#ctype#',
+ '_check': isunsigned_long_longarray,
+ '_depend': ''
+ },
+ # Complexarray
+ {'need': '#ctype#',
+ '_check': iscomplexarray,
+ '_depend': ''
+ },
+ # Character
+ {
+ 'need': 'string',
+ '_check': ischaracter,
+ },
+ # Character array
+ {
+ 'need': 'string',
+ '_check': ischaracterarray,
+ },
+ # Stringarray
+ {
+ 'callfortranappend': {isarrayofstrings: 'flen(#varname#),'},
+ 'need': 'string',
+ '_check': isstringarray
+ }
+]
+
+################# Rules for checking ###############
+
+check_rules = [
+ {
+ 'frompyobj': {debugcapi: ' fprintf(stderr,\"debug-capi:Checking `#check#\'\\n\");'},
+ 'need': 'len..'
+ }, {
+ 'frompyobj': ' CHECKSCALAR(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {',
+ 'cleanupfrompyobj': ' } /*CHECKSCALAR(#check#)*/',
+ 'need': 'CHECKSCALAR',
+ '_check': l_and(isscalar, l_not(iscomplex)),
+ '_break': ''
+ }, {
+ 'frompyobj': ' CHECKSTRING(#check#,\"#check#\",\"#nth# #varname#\",\"#varshowvalue#\",#varname#) {',
+ 'cleanupfrompyobj': ' } /*CHECKSTRING(#check#)*/',
+ 'need': 'CHECKSTRING',
+ '_check': isstring,
+ '_break': ''
+ }, {
+ 'need': 'CHECKARRAY',
+ 'frompyobj': ' CHECKARRAY(#check#,\"#check#\",\"#nth# #varname#\") {',
+ 'cleanupfrompyobj': ' } /*CHECKARRAY(#check#)*/',
+ '_check': isarray,
+ '_break': ''
+ }, {
+ 'need': 'CHECKGENERIC',
+ 'frompyobj': ' CHECKGENERIC(#check#,\"#check#\",\"#nth# #varname#\") {',
+ 'cleanupfrompyobj': ' } /*CHECKGENERIC(#check#)*/',
+ }
+]
+
+########## Applying the rules. No need to modify what follows #############
+
+#################### Build C/API module #######################
+
+
+def buildmodule(m, um):
+ """
+ Return
+ """
+ outmess(' Building module "%s"...\n' % (m['name']))
+ ret = {}
+ mod_rules = defmod_rules[:]
+ vrd = capi_maps.modsign2map(m)
+ rd = dictappend({'f2py_version': f2py_version}, vrd)
+ funcwrappers = []
+ funcwrappers2 = [] # F90 codes
+ for n in m['interfaced']:
+ nb = None
+ for bi in m['body']:
+ if bi['block'] not in ['interface', 'abstract interface']:
+ errmess('buildmodule: Expected interface block. Skipping.\n')
+ continue
+ for b in bi['body']:
+ if b['name'] == n:
+ nb = b
+ break
+
+ if not nb:
+ print(
+ 'buildmodule: Could not find the body of interfaced routine "%s". Skipping.\n' % (n), file=sys.stderr)
+ continue
+ nb_list = [nb]
+ if 'entry' in nb:
+ for k, a in nb['entry'].items():
+ nb1 = copy.deepcopy(nb)
+ del nb1['entry']
+ nb1['name'] = k
+ nb1['args'] = a
+ nb_list.append(nb1)
+ for nb in nb_list:
+ # requiresf90wrapper must be called before buildapi as it
+ # rewrites assumed shape arrays as automatic arrays.
+ isf90 = requiresf90wrapper(nb)
+ # options is in scope here
+ if options['emptygen']:
+ b_path = options['buildpath']
+ m_name = vrd['modulename']
+ outmess(' Generating possibly empty wrappers"\n')
+ Path(f"{b_path}/{vrd['coutput']}").touch()
+ if isf90:
+ # f77 + f90 wrappers
+ outmess(f' Maybe empty "{m_name}-f2pywrappers2.f90"\n')
+ Path(f'{b_path}/{m_name}-f2pywrappers2.f90').touch()
+ outmess(f' Maybe empty "{m_name}-f2pywrappers.f"\n')
+ Path(f'{b_path}/{m_name}-f2pywrappers.f').touch()
+ else:
+ # only f77 wrappers
+ outmess(f' Maybe empty "{m_name}-f2pywrappers.f"\n')
+ Path(f'{b_path}/{m_name}-f2pywrappers.f').touch()
+ api, wrap = buildapi(nb)
+ if wrap:
+ if isf90:
+ funcwrappers2.append(wrap)
+ else:
+ funcwrappers.append(wrap)
+ ar = applyrules(api, vrd)
+ rd = dictappend(rd, ar)
+
+ # Construct COMMON block support
+ cr, wrap = common_rules.buildhooks(m)
+ if wrap:
+ funcwrappers.append(wrap)
+ ar = applyrules(cr, vrd)
+ rd = dictappend(rd, ar)
+
+ # Construct F90 module support
+ mr, wrap = f90mod_rules.buildhooks(m)
+ if wrap:
+ funcwrappers2.append(wrap)
+ ar = applyrules(mr, vrd)
+ rd = dictappend(rd, ar)
+
+ for u in um:
+ ar = use_rules.buildusevars(u, m['use'][u['name']])
+ rd = dictappend(rd, ar)
+
+ needs = cfuncs.get_needs()
+ # Add mapped definitions
+ needs['typedefs'] += [cvar for cvar in capi_maps.f2cmap_mapped #
+ if cvar in typedef_need_dict.values()]
+ code = {}
+ for n in needs.keys():
+ code[n] = []
+ for k in needs[n]:
+ c = ''
+ if k in cfuncs.includes0:
+ c = cfuncs.includes0[k]
+ elif k in cfuncs.includes:
+ c = cfuncs.includes[k]
+ elif k in cfuncs.userincludes:
+ c = cfuncs.userincludes[k]
+ elif k in cfuncs.typedefs:
+ c = cfuncs.typedefs[k]
+ elif k in cfuncs.typedefs_generated:
+ c = cfuncs.typedefs_generated[k]
+ elif k in cfuncs.cppmacros:
+ c = cfuncs.cppmacros[k]
+ elif k in cfuncs.cfuncs:
+ c = cfuncs.cfuncs[k]
+ elif k in cfuncs.callbacks:
+ c = cfuncs.callbacks[k]
+ elif k in cfuncs.f90modhooks:
+ c = cfuncs.f90modhooks[k]
+ elif k in cfuncs.commonhooks:
+ c = cfuncs.commonhooks[k]
+ else:
+ errmess('buildmodule: unknown need %s.\n' % (repr(k)))
+ continue
+ code[n].append(c)
+ mod_rules.append(code)
+ for r in mod_rules:
+ if ('_check' in r and r['_check'](m)) or ('_check' not in r):
+ ar = applyrules(r, vrd, m)
+ rd = dictappend(rd, ar)
+ ar = applyrules(module_rules, rd)
+
+ fn = os.path.join(options['buildpath'], vrd['coutput'])
+ ret['csrc'] = fn
+ with open(fn, 'w') as f:
+ f.write(ar['modulebody'].replace('\t', 2 * ' '))
+ outmess(' Wrote C/API module "%s" to file "%s"\n' % (m['name'], fn))
+
+ if options['dorestdoc']:
+ fn = os.path.join(
+ options['buildpath'], vrd['modulename'] + 'module.rest')
+ with open(fn, 'w') as f:
+ f.write('.. -*- rest -*-\n')
+ f.write('\n'.join(ar['restdoc']))
+ outmess(' ReST Documentation is saved to file "%s/%smodule.rest"\n' %
+ (options['buildpath'], vrd['modulename']))
+ if options['dolatexdoc']:
+ fn = os.path.join(
+ options['buildpath'], vrd['modulename'] + 'module.tex')
+ ret['ltx'] = fn
+ with open(fn, 'w') as f:
+ f.write(
+ '%% This file is auto-generated with f2py (version:%s)\n' % (f2py_version))
+ if 'shortlatex' not in options:
+ f.write(
+ '\\documentclass{article}\n\\usepackage{a4wide}\n\\begin{document}\n\\tableofcontents\n\n')
+ f.write('\n'.join(ar['latexdoc']))
+ if 'shortlatex' not in options:
+ f.write('\\end{document}')
+ outmess(' Documentation is saved to file "%s/%smodule.tex"\n' %
+ (options['buildpath'], vrd['modulename']))
+ if funcwrappers:
+ wn = os.path.join(options['buildpath'], vrd['f2py_wrapper_output'])
+ ret['fsrc'] = wn
+ with open(wn, 'w') as f:
+ f.write('C -*- fortran -*-\n')
+ f.write(
+ 'C This file is autogenerated with f2py (version:%s)\n' % (f2py_version))
+ f.write(
+ 'C It contains Fortran 77 wrappers to fortran functions.\n')
+ lines = []
+ for l in ('\n\n'.join(funcwrappers) + '\n').split('\n'):
+ if 0 <= l.find('!') < 66:
+ # don't split comment lines
+ lines.append(l + '\n')
+ elif l and l[0] == ' ':
+ while len(l) >= 66:
+ lines.append(l[:66] + '\n &')
+ l = l[66:]
+ lines.append(l + '\n')
+ else:
+ lines.append(l + '\n')
+ lines = ''.join(lines).replace('\n &\n', '\n')
+ f.write(lines)
+ outmess(' Fortran 77 wrappers are saved to "%s"\n' % (wn))
+ if funcwrappers2:
+ wn = os.path.join(
+ options['buildpath'], '%s-f2pywrappers2.f90' % (vrd['modulename']))
+ ret['fsrc'] = wn
+ with open(wn, 'w') as f:
+ f.write('! -*- f90 -*-\n')
+ f.write(
+ '! This file is autogenerated with f2py (version:%s)\n' % (f2py_version))
+ f.write(
+ '! It contains Fortran 90 wrappers to fortran functions.\n')
+ lines = []
+ for l in ('\n\n'.join(funcwrappers2) + '\n').split('\n'):
+ if 0 <= l.find('!') < 72:
+ # don't split comment lines
+ lines.append(l + '\n')
+ elif len(l) > 72 and l[0] == ' ':
+ lines.append(l[:72] + '&\n &')
+ l = l[72:]
+ while len(l) > 66:
+ lines.append(l[:66] + '&\n &')
+ l = l[66:]
+ lines.append(l + '\n')
+ else:
+ lines.append(l + '\n')
+ lines = ''.join(lines).replace('\n &\n', '\n')
+ f.write(lines)
+ outmess(' Fortran 90 wrappers are saved to "%s"\n' % (wn))
+ return ret
+
+################## Build C/API function #############
+
+stnd = {1: 'st', 2: 'nd', 3: 'rd', 4: 'th', 5: 'th',
+ 6: 'th', 7: 'th', 8: 'th', 9: 'th', 0: 'th'}
+
+
+def buildapi(rout):
+ rout, wrap = func2subr.assubr(rout)
+ args, depargs = getargs2(rout)
+ capi_maps.depargs = depargs
+ var = rout['vars']
+
+ if ismoduleroutine(rout):
+ outmess(' Constructing wrapper function "%s.%s"...\n' %
+ (rout['modulename'], rout['name']))
+ else:
+ outmess(' Constructing wrapper function "%s"...\n' % (rout['name']))
+ # Routine
+ vrd = capi_maps.routsign2map(rout)
+ rd = dictappend({}, vrd)
+ for r in rout_rules:
+ if ('_check' in r and r['_check'](rout)) or ('_check' not in r):
+ ar = applyrules(r, vrd, rout)
+ rd = dictappend(rd, ar)
+
+ # Args
+ nth, nthk = 0, 0
+ savevrd = {}
+ for a in args:
+ vrd = capi_maps.sign2map(a, var[a])
+ if isintent_aux(var[a]):
+ _rules = aux_rules
+ else:
+ _rules = arg_rules
+ if not isintent_hide(var[a]):
+ if not isoptional(var[a]):
+ nth = nth + 1
+ vrd['nth'] = repr(nth) + stnd[nth % 10] + ' argument'
+ else:
+ nthk = nthk + 1
+ vrd['nth'] = repr(nthk) + stnd[nthk % 10] + ' keyword'
+ else:
+ vrd['nth'] = 'hidden'
+ savevrd[a] = vrd
+ for r in _rules:
+ if '_depend' in r:
+ continue
+ if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
+ ar = applyrules(r, vrd, var[a])
+ rd = dictappend(rd, ar)
+ if '_break' in r:
+ break
+ for a in depargs:
+ if isintent_aux(var[a]):
+ _rules = aux_rules
+ else:
+ _rules = arg_rules
+ vrd = savevrd[a]
+ for r in _rules:
+ if '_depend' not in r:
+ continue
+ if ('_check' in r and r['_check'](var[a])) or ('_check' not in r):
+ ar = applyrules(r, vrd, var[a])
+ rd = dictappend(rd, ar)
+ if '_break' in r:
+ break
+ if 'check' in var[a]:
+ for c in var[a]['check']:
+ vrd['check'] = c
+ ar = applyrules(check_rules, vrd, var[a])
+ rd = dictappend(rd, ar)
+ if isinstance(rd['cleanupfrompyobj'], list):
+ rd['cleanupfrompyobj'].reverse()
+ if isinstance(rd['closepyobjfrom'], list):
+ rd['closepyobjfrom'].reverse()
+ rd['docsignature'] = stripcomma(replace('#docsign##docsignopt##docsignxa#',
+ {'docsign': rd['docsign'],
+ 'docsignopt': rd['docsignopt'],
+ 'docsignxa': rd['docsignxa']}))
+ optargs = stripcomma(replace('#docsignopt##docsignxa#',
+ {'docsignxa': rd['docsignxashort'],
+ 'docsignopt': rd['docsignoptshort']}
+ ))
+ if optargs == '':
+ rd['docsignatureshort'] = stripcomma(
+ replace('#docsign#', {'docsign': rd['docsign']}))
+ else:
+ rd['docsignatureshort'] = replace('#docsign#[#docsignopt#]',
+ {'docsign': rd['docsign'],
+ 'docsignopt': optargs,
+ })
+ rd['latexdocsignatureshort'] = rd['docsignatureshort'].replace('_', '\\_')
+ rd['latexdocsignatureshort'] = rd[
+ 'latexdocsignatureshort'].replace(',', ', ')
+ cfs = stripcomma(replace('#callfortran##callfortranappend#', {
+ 'callfortran': rd['callfortran'], 'callfortranappend': rd['callfortranappend']}))
+ if len(rd['callfortranappend']) > 1:
+ rd['callcompaqfortran'] = stripcomma(replace('#callfortran# 0,#callfortranappend#', {
+ 'callfortran': rd['callfortran'], 'callfortranappend': rd['callfortranappend']}))
+ else:
+ rd['callcompaqfortran'] = cfs
+ rd['callfortran'] = cfs
+ if isinstance(rd['docreturn'], list):
+ rd['docreturn'] = stripcomma(
+ replace('#docreturn#', {'docreturn': rd['docreturn']})) + ' = '
+ rd['docstrsigns'] = []
+ rd['latexdocstrsigns'] = []
+ for k in ['docstrreq', 'docstropt', 'docstrout', 'docstrcbs']:
+ if k in rd and isinstance(rd[k], list):
+ rd['docstrsigns'] = rd['docstrsigns'] + rd[k]
+ k = 'latex' + k
+ if k in rd and isinstance(rd[k], list):
+ rd['latexdocstrsigns'] = rd['latexdocstrsigns'] + rd[k][0:1] +\
+ ['\\begin{description}'] + rd[k][1:] +\
+ ['\\end{description}']
+
+ ar = applyrules(routine_rules, rd)
+ if ismoduleroutine(rout):
+ outmess(' %s\n' % (ar['docshort']))
+ else:
+ outmess(' %s\n' % (ar['docshort']))
+ return ar, wrap
+
+
+#################### EOF rules.py #######################
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/setup.py b/venv/lib/python3.9/site-packages/numpy/f2py/setup.py
new file mode 100644
index 00000000..499609f9
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/setup.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+"""
+setup.py for installing F2PY
+
+Usage:
+ pip install .
+
+Copyright 2001-2005 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@cens.ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Revision: 1.32 $
+$Date: 2005/01/30 17:22:14 $
+Pearu Peterson
+
+"""
+from numpy.distutils.core import setup
+from numpy.distutils.misc_util import Configuration
+
+
+from __version__ import version
+
+
+def configuration(parent_package='', top_path=None):
+ config = Configuration('f2py', parent_package, top_path)
+ config.add_subpackage('tests')
+ config.add_data_dir('tests/src')
+ config.add_data_files(
+ 'src/fortranobject.c',
+ 'src/fortranobject.h')
+ config.add_data_files('*.pyi')
+ return config
+
+
+if __name__ == "__main__":
+
+ config = configuration(top_path='')
+ config = config.todict()
+
+ config['classifiers'] = [
+ 'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'Intended Audience :: Science/Research',
+ 'License :: OSI Approved :: NumPy License',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Programming Language :: C',
+ 'Programming Language :: Fortran',
+ 'Programming Language :: Python',
+ 'Topic :: Scientific/Engineering',
+ 'Topic :: Software Development :: Code Generators',
+ ]
+ setup(version=version,
+ description="F2PY - Fortran to Python Interface Generator",
+ author="Pearu Peterson",
+ author_email="pearu@cens.ioc.ee",
+ maintainer="Pearu Peterson",
+ maintainer_email="pearu@cens.ioc.ee",
+ license="BSD",
+ platforms="Unix, Windows (mingw|cygwin), Mac OSX",
+ long_description="""\
+The Fortran to Python Interface Generator, or F2PY for short, is a
+command line tool (f2py) for generating Python C/API modules for
+wrapping Fortran 77/90/95 subroutines, accessing common blocks from
+Python, and calling Python functions from Fortran (call-backs).
+Interfacing subroutines/data from Fortran 90/95 modules is supported.""",
+ url="https://numpy.org/doc/stable/f2py/",
+ keywords=['Fortran', 'f2py'],
+ **config)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.c b/venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.c
new file mode 100644
index 00000000..add6e8b6
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.c
@@ -0,0 +1,1422 @@
+#define FORTRANOBJECT_C
+#include "fortranobject.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ This file implements: FortranObject, array_from_pyobj, copy_ND_array
+
+ Author: Pearu Peterson <pearu@cens.ioc.ee>
+ $Revision: 1.52 $
+ $Date: 2005/07/11 07:44:20 $
+*/
+
+int
+F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj)
+{
+ if (obj == NULL) {
+ fprintf(stderr, "Error loading %s\n", name);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ return -1;
+ }
+ return PyDict_SetItemString(dict, name, obj);
+}
+
+/*
+ * Python-only fallback for thread-local callback pointers
+ */
+void *
+F2PySwapThreadLocalCallbackPtr(char *key, void *ptr)
+{
+ PyObject *local_dict, *value;
+ void *prev;
+
+ local_dict = PyThreadState_GetDict();
+ if (local_dict == NULL) {
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyThreadState_GetDict "
+ "failed");
+ }
+
+ value = PyDict_GetItemString(local_dict, key);
+ if (value != NULL) {
+ prev = PyLong_AsVoidPtr(value);
+ if (PyErr_Occurred()) {
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
+ }
+ }
+ else {
+ prev = NULL;
+ }
+
+ value = PyLong_FromVoidPtr((void *)ptr);
+ if (value == NULL) {
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyLong_FromVoidPtr failed");
+ }
+
+ if (PyDict_SetItemString(local_dict, key, value) != 0) {
+ Py_FatalError(
+ "F2PySwapThreadLocalCallbackPtr: PyDict_SetItemString failed");
+ }
+
+ Py_DECREF(value);
+
+ return prev;
+}
+
+void *
+F2PyGetThreadLocalCallbackPtr(char *key)
+{
+ PyObject *local_dict, *value;
+ void *prev;
+
+ local_dict = PyThreadState_GetDict();
+ if (local_dict == NULL) {
+ Py_FatalError(
+ "F2PyGetThreadLocalCallbackPtr: PyThreadState_GetDict failed");
+ }
+
+ value = PyDict_GetItemString(local_dict, key);
+ if (value != NULL) {
+ prev = PyLong_AsVoidPtr(value);
+ if (PyErr_Occurred()) {
+ Py_FatalError(
+ "F2PyGetThreadLocalCallbackPtr: PyLong_AsVoidPtr failed");
+ }
+ }
+ else {
+ prev = NULL;
+ }
+
+ return prev;
+}
+
+static PyArray_Descr *
+get_descr_from_type_and_elsize(const int type_num, const int elsize) {
+ PyArray_Descr * descr = PyArray_DescrFromType(type_num);
+ if (type_num == NPY_STRING) {
+ // PyArray_DescrFromType returns descr with elsize = 0.
+ PyArray_DESCR_REPLACE(descr);
+ if (descr == NULL) {
+ return NULL;
+ }
+ descr->elsize = elsize;
+ }
+ return descr;
+}
+
+/************************* FortranObject *******************************/
+
+typedef PyObject *(*fortranfunc)(PyObject *, PyObject *, PyObject *, void *);
+
+PyObject *
+PyFortranObject_New(FortranDataDef *defs, f2py_void_func init)
+{
+ int i;
+ PyFortranObject *fp = NULL;
+ PyObject *v = NULL;
+ if (init != NULL) { /* Initialize F90 module objects */
+ (*(init))();
+ }
+ fp = PyObject_New(PyFortranObject, &PyFortran_Type);
+ if (fp == NULL) {
+ return NULL;
+ }
+ if ((fp->dict = PyDict_New()) == NULL) {
+ Py_DECREF(fp);
+ return NULL;
+ }
+ fp->len = 0;
+ while (defs[fp->len].name != NULL) {
+ fp->len++;
+ }
+ if (fp->len == 0) {
+ goto fail;
+ }
+ fp->defs = defs;
+ for (i = 0; i < fp->len; i++) {
+ if (fp->defs[i].rank == -1) { /* Is Fortran routine */
+ v = PyFortranObject_NewAsAttr(&(fp->defs[i]));
+ if (v == NULL) {
+ goto fail;
+ }
+ PyDict_SetItemString(fp->dict, fp->defs[i].name, v);
+ Py_XDECREF(v);
+ }
+ else if ((fp->defs[i].data) !=
+ NULL) { /* Is Fortran variable or array (not allocatable) */
+ PyArray_Descr *
+ descr = get_descr_from_type_and_elsize(fp->defs[i].type,
+ fp->defs[i].elsize);
+ if (descr == NULL) {
+ goto fail;
+ }
+ v = PyArray_NewFromDescr(&PyArray_Type, descr, fp->defs[i].rank,
+ fp->defs[i].dims.d, NULL, fp->defs[i].data,
+ NPY_ARRAY_FARRAY, NULL);
+ if (v == NULL) {
+ Py_DECREF(descr);
+ goto fail;
+ }
+ PyDict_SetItemString(fp->dict, fp->defs[i].name, v);
+ Py_XDECREF(v);
+ }
+ }
+ return (PyObject *)fp;
+fail:
+ Py_XDECREF(fp);
+ return NULL;
+}
+
+PyObject *
+PyFortranObject_NewAsAttr(FortranDataDef *defs)
+{ /* used for calling F90 module routines */
+ PyFortranObject *fp = NULL;
+ fp = PyObject_New(PyFortranObject, &PyFortran_Type);
+ if (fp == NULL)
+ return NULL;
+ if ((fp->dict = PyDict_New()) == NULL) {
+ PyObject_Del(fp);
+ return NULL;
+ }
+ fp->len = 1;
+ fp->defs = defs;
+ if (defs->rank == -1) {
+ PyDict_SetItemString(fp->dict, "__name__", PyUnicode_FromFormat("function %s", defs->name));
+ } else if (defs->rank == 0) {
+ PyDict_SetItemString(fp->dict, "__name__", PyUnicode_FromFormat("scalar %s", defs->name));
+ } else {
+ PyDict_SetItemString(fp->dict, "__name__", PyUnicode_FromFormat("array %s", defs->name));
+ }
+ return (PyObject *)fp;
+}
+
+/* Fortran methods */
+
+static void
+fortran_dealloc(PyFortranObject *fp)
+{
+ Py_XDECREF(fp->dict);
+ PyObject_Del(fp);
+}
+
+/* Returns number of bytes consumed from buf, or -1 on error. */
+static Py_ssize_t
+format_def(char *buf, Py_ssize_t size, FortranDataDef def)
+{
+ char *p = buf;
+ int i;
+ npy_intp n;
+
+ n = PyOS_snprintf(p, size, "array(%" NPY_INTP_FMT, def.dims.d[0]);
+ if (n < 0 || n >= size) {
+ return -1;
+ }
+ p += n;
+ size -= n;
+
+ for (i = 1; i < def.rank; i++) {
+ n = PyOS_snprintf(p, size, ",%" NPY_INTP_FMT, def.dims.d[i]);
+ if (n < 0 || n >= size) {
+ return -1;
+ }
+ p += n;
+ size -= n;
+ }
+
+ if (size <= 0) {
+ return -1;
+ }
+
+ *p++ = ')';
+ size--;
+
+ if (def.data == NULL) {
+ static const char notalloc[] = ", not allocated";
+ if ((size_t)size < sizeof(notalloc)) {
+ return -1;
+ }
+ memcpy(p, notalloc, sizeof(notalloc));
+ p += sizeof(notalloc);
+ size -= sizeof(notalloc);
+ }
+
+ return p - buf;
+}
+
+static PyObject *
+fortran_doc(FortranDataDef def)
+{
+ char *buf, *p;
+ PyObject *s = NULL;
+ Py_ssize_t n, origsize, size = 100;
+
+ if (def.doc != NULL) {
+ size += strlen(def.doc);
+ }
+ origsize = size;
+ buf = p = (char *)PyMem_Malloc(size);
+ if (buf == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ if (def.rank == -1) {
+ if (def.doc) {
+ n = strlen(def.doc);
+ if (n > size) {
+ goto fail;
+ }
+ memcpy(p, def.doc, n);
+ p += n;
+ size -= n;
+ }
+ else {
+ n = PyOS_snprintf(p, size, "%s - no docs available", def.name);
+ if (n < 0 || n >= size) {
+ goto fail;
+ }
+ p += n;
+ size -= n;
+ }
+ }
+ else {
+ PyArray_Descr *d = PyArray_DescrFromType(def.type);
+ n = PyOS_snprintf(p, size, "%s : '%c'-", def.name, d->type);
+ Py_DECREF(d);
+ if (n < 0 || n >= size) {
+ goto fail;
+ }
+ p += n;
+ size -= n;
+
+ if (def.data == NULL) {
+ n = format_def(p, size, def);
+ if (n < 0) {
+ goto fail;
+ }
+ p += n;
+ size -= n;
+ }
+ else if (def.rank > 0) {
+ n = format_def(p, size, def);
+ if (n < 0) {
+ goto fail;
+ }
+ p += n;
+ size -= n;
+ }
+ else {
+ n = strlen("scalar");
+ if (size < n) {
+ goto fail;
+ }
+ memcpy(p, "scalar", n);
+ p += n;
+ size -= n;
+ }
+ }
+ if (size <= 1) {
+ goto fail;
+ }
+ *p++ = '\n';
+ size--;
+
+ /* p now points one beyond the last character of the string in buf */
+ s = PyUnicode_FromStringAndSize(buf, p - buf);
+
+ PyMem_Free(buf);
+ return s;
+
+fail:
+ fprintf(stderr,
+ "fortranobject.c: fortran_doc: len(p)=%zd>%zd=size:"
+ " too long docstring required, increase size\n",
+ p - buf, origsize);
+ PyMem_Free(buf);
+ return NULL;
+}
+
+static FortranDataDef *save_def; /* save pointer of an allocatable array */
+static void
+set_data(char *d, npy_intp *f)
+{ /* callback from Fortran */
+ if (*f) /* In fortran f=allocated(d) */
+ save_def->data = d;
+ else
+ save_def->data = NULL;
+ /* printf("set_data: d=%p,f=%d\n",d,*f); */
+}
+
+static PyObject *
+fortran_getattr(PyFortranObject *fp, char *name)
+{
+ int i, j, k, flag;
+ if (fp->dict != NULL) {
+ PyObject *v = _PyDict_GetItemStringWithError(fp->dict, name);
+ if (v == NULL && PyErr_Occurred()) {
+ return NULL;
+ }
+ else if (v != NULL) {
+ Py_INCREF(v);
+ return v;
+ }
+ }
+ for (i = 0, j = 1; i < fp->len && (j = strcmp(name, fp->defs[i].name));
+ i++)
+ ;
+ if (j == 0)
+ if (fp->defs[i].rank != -1) { /* F90 allocatable array */
+ if (fp->defs[i].func == NULL)
+ return NULL;
+ for (k = 0; k < fp->defs[i].rank; ++k) fp->defs[i].dims.d[k] = -1;
+ save_def = &fp->defs[i];
+ (*(fp->defs[i].func))(&fp->defs[i].rank, fp->defs[i].dims.d,
+ set_data, &flag);
+ if (flag == 2)
+ k = fp->defs[i].rank + 1;
+ else
+ k = fp->defs[i].rank;
+ if (fp->defs[i].data != NULL) { /* array is allocated */
+ PyObject *v = PyArray_New(
+ &PyArray_Type, k, fp->defs[i].dims.d, fp->defs[i].type,
+ NULL, fp->defs[i].data, 0, NPY_ARRAY_FARRAY, NULL);
+ if (v == NULL)
+ return NULL;
+ /* Py_INCREF(v); */
+ return v;
+ }
+ else { /* array is not allocated */
+ Py_RETURN_NONE;
+ }
+ }
+ if (strcmp(name, "__dict__") == 0) {
+ Py_INCREF(fp->dict);
+ return fp->dict;
+ }
+ if (strcmp(name, "__doc__") == 0) {
+ PyObject *s = PyUnicode_FromString(""), *s2, *s3;
+ for (i = 0; i < fp->len; i++) {
+ s2 = fortran_doc(fp->defs[i]);
+ s3 = PyUnicode_Concat(s, s2);
+ Py_DECREF(s2);
+ Py_DECREF(s);
+ s = s3;
+ }
+ if (PyDict_SetItemString(fp->dict, name, s))
+ return NULL;
+ return s;
+ }
+ if ((strcmp(name, "_cpointer") == 0) && (fp->len == 1)) {
+ PyObject *cobj =
+ F2PyCapsule_FromVoidPtr((void *)(fp->defs[0].data), NULL);
+ if (PyDict_SetItemString(fp->dict, name, cobj))
+ return NULL;
+ return cobj;
+ }
+ PyObject *str, *ret;
+ str = PyUnicode_FromString(name);
+ ret = PyObject_GenericGetAttr((PyObject *)fp, str);
+ Py_DECREF(str);
+ return ret;
+}
+
+static int
+fortran_setattr(PyFortranObject *fp, char *name, PyObject *v)
+{
+ int i, j, flag;
+ PyArrayObject *arr = NULL;
+ for (i = 0, j = 1; i < fp->len && (j = strcmp(name, fp->defs[i].name));
+ i++)
+ ;
+ if (j == 0) {
+ if (fp->defs[i].rank == -1) {
+ PyErr_SetString(PyExc_AttributeError,
+ "over-writing fortran routine");
+ return -1;
+ }
+ if (fp->defs[i].func != NULL) { /* is allocatable array */
+ npy_intp dims[F2PY_MAX_DIMS];
+ int k;
+ save_def = &fp->defs[i];
+ if (v != Py_None) { /* set new value (reallocate if needed --
+ see f2py generated code for more
+ details ) */
+ for (k = 0; k < fp->defs[i].rank; k++) dims[k] = -1;
+ if ((arr = array_from_pyobj(fp->defs[i].type, dims,
+ fp->defs[i].rank, F2PY_INTENT_IN,
+ v)) == NULL)
+ return -1;
+ (*(fp->defs[i].func))(&fp->defs[i].rank, PyArray_DIMS(arr),
+ set_data, &flag);
+ }
+ else { /* deallocate */
+ for (k = 0; k < fp->defs[i].rank; k++) dims[k] = 0;
+ (*(fp->defs[i].func))(&fp->defs[i].rank, dims, set_data,
+ &flag);
+ for (k = 0; k < fp->defs[i].rank; k++) dims[k] = -1;
+ }
+ memcpy(fp->defs[i].dims.d, dims,
+ fp->defs[i].rank * sizeof(npy_intp));
+ }
+ else { /* not allocatable array */
+ if ((arr = array_from_pyobj(fp->defs[i].type, fp->defs[i].dims.d,
+ fp->defs[i].rank, F2PY_INTENT_IN,
+ v)) == NULL)
+ return -1;
+ }
+ if (fp->defs[i].data !=
+ NULL) { /* copy Python object to Fortran array */
+ npy_intp s = PyArray_MultiplyList(fp->defs[i].dims.d,
+ PyArray_NDIM(arr));
+ if (s == -1)
+ s = PyArray_MultiplyList(PyArray_DIMS(arr), PyArray_NDIM(arr));
+ if (s < 0 || (memcpy(fp->defs[i].data, PyArray_DATA(arr),
+ s * PyArray_ITEMSIZE(arr))) == NULL) {
+ if ((PyObject *)arr != v) {
+ Py_DECREF(arr);
+ }
+ return -1;
+ }
+ if ((PyObject *)arr != v) {
+ Py_DECREF(arr);
+ }
+ }
+ else
+ return (fp->defs[i].func == NULL ? -1 : 0);
+ return 0; /* successful */
+ }
+ if (fp->dict == NULL) {
+ fp->dict = PyDict_New();
+ if (fp->dict == NULL)
+ return -1;
+ }
+ if (v == NULL) {
+ int rv = PyDict_DelItemString(fp->dict, name);
+ if (rv < 0)
+ PyErr_SetString(PyExc_AttributeError,
+ "delete non-existing fortran attribute");
+ return rv;
+ }
+ else
+ return PyDict_SetItemString(fp->dict, name, v);
+}
+
+static PyObject *
+fortran_call(PyFortranObject *fp, PyObject *arg, PyObject *kw)
+{
+ int i = 0;
+ /* printf("fortran call
+ name=%s,func=%p,data=%p,%p\n",fp->defs[i].name,
+ fp->defs[i].func,fp->defs[i].data,&fp->defs[i].data); */
+ if (fp->defs[i].rank == -1) { /* is Fortran routine */
+ if (fp->defs[i].func == NULL) {
+ PyErr_Format(PyExc_RuntimeError, "no function to call");
+ return NULL;
+ }
+ else if (fp->defs[i].data == NULL)
+ /* dummy routine */
+ return (*((fortranfunc)(fp->defs[i].func)))((PyObject *)fp, arg,
+ kw, NULL);
+ else
+ return (*((fortranfunc)(fp->defs[i].func)))(
+ (PyObject *)fp, arg, kw, (void *)fp->defs[i].data);
+ }
+ PyErr_Format(PyExc_TypeError, "this fortran object is not callable");
+ return NULL;
+}
+
+static PyObject *
+fortran_repr(PyFortranObject *fp)
+{
+ PyObject *name = NULL, *repr = NULL;
+ name = PyObject_GetAttrString((PyObject *)fp, "__name__");
+ PyErr_Clear();
+ if (name != NULL && PyUnicode_Check(name)) {
+ repr = PyUnicode_FromFormat("<fortran %U>", name);
+ }
+ else {
+ repr = PyUnicode_FromString("<fortran object>");
+ }
+ Py_XDECREF(name);
+ return repr;
+}
+
+PyTypeObject PyFortran_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "fortran",
+ .tp_basicsize = sizeof(PyFortranObject),
+ .tp_dealloc = (destructor)fortran_dealloc,
+ .tp_getattr = (getattrfunc)fortran_getattr,
+ .tp_setattr = (setattrfunc)fortran_setattr,
+ .tp_repr = (reprfunc)fortran_repr,
+ .tp_call = (ternaryfunc)fortran_call,
+};
+
+/************************* f2py_report_atexit *******************************/
+
+#ifdef F2PY_REPORT_ATEXIT
+static int passed_time = 0;
+static int passed_counter = 0;
+static int passed_call_time = 0;
+static struct timeb start_time;
+static struct timeb stop_time;
+static struct timeb start_call_time;
+static struct timeb stop_call_time;
+static int cb_passed_time = 0;
+static int cb_passed_counter = 0;
+static int cb_passed_call_time = 0;
+static struct timeb cb_start_time;
+static struct timeb cb_stop_time;
+static struct timeb cb_start_call_time;
+static struct timeb cb_stop_call_time;
+
+extern void
+f2py_start_clock(void)
+{
+ ftime(&start_time);
+}
+extern void
+f2py_start_call_clock(void)
+{
+ f2py_stop_clock();
+ ftime(&start_call_time);
+}
+extern void
+f2py_stop_clock(void)
+{
+ ftime(&stop_time);
+ passed_time += 1000 * (stop_time.time - start_time.time);
+ passed_time += stop_time.millitm - start_time.millitm;
+}
+extern void
+f2py_stop_call_clock(void)
+{
+ ftime(&stop_call_time);
+ passed_call_time += 1000 * (stop_call_time.time - start_call_time.time);
+ passed_call_time += stop_call_time.millitm - start_call_time.millitm;
+ passed_counter += 1;
+ f2py_start_clock();
+}
+
+extern void
+f2py_cb_start_clock(void)
+{
+ ftime(&cb_start_time);
+}
+extern void
+f2py_cb_start_call_clock(void)
+{
+ f2py_cb_stop_clock();
+ ftime(&cb_start_call_time);
+}
+extern void
+f2py_cb_stop_clock(void)
+{
+ ftime(&cb_stop_time);
+ cb_passed_time += 1000 * (cb_stop_time.time - cb_start_time.time);
+ cb_passed_time += cb_stop_time.millitm - cb_start_time.millitm;
+}
+extern void
+f2py_cb_stop_call_clock(void)
+{
+ ftime(&cb_stop_call_time);
+ cb_passed_call_time +=
+ 1000 * (cb_stop_call_time.time - cb_start_call_time.time);
+ cb_passed_call_time +=
+ cb_stop_call_time.millitm - cb_start_call_time.millitm;
+ cb_passed_counter += 1;
+ f2py_cb_start_clock();
+}
+
+static int f2py_report_on_exit_been_here = 0;
+extern void
+f2py_report_on_exit(int exit_flag, void *name)
+{
+ if (f2py_report_on_exit_been_here) {
+ fprintf(stderr, " %s\n", (char *)name);
+ return;
+ }
+ f2py_report_on_exit_been_here = 1;
+ fprintf(stderr, " /-----------------------\\\n");
+ fprintf(stderr, " < F2PY performance report >\n");
+ fprintf(stderr, " \\-----------------------/\n");
+ fprintf(stderr, "Overall time spent in ...\n");
+ fprintf(stderr, "(a) wrapped (Fortran/C) functions : %8d msec\n",
+ passed_call_time);
+ fprintf(stderr, "(b) f2py interface, %6d calls : %8d msec\n",
+ passed_counter, passed_time);
+ fprintf(stderr, "(c) call-back (Python) functions : %8d msec\n",
+ cb_passed_call_time);
+ fprintf(stderr, "(d) f2py call-back interface, %6d calls : %8d msec\n",
+ cb_passed_counter, cb_passed_time);
+
+ fprintf(stderr,
+ "(e) wrapped (Fortran/C) functions (actual) : %8d msec\n\n",
+ passed_call_time - cb_passed_call_time - cb_passed_time);
+ fprintf(stderr,
+ "Use -DF2PY_REPORT_ATEXIT_DISABLE to disable this message.\n");
+ fprintf(stderr, "Exit status: %d\n", exit_flag);
+ fprintf(stderr, "Modules : %s\n", (char *)name);
+}
+#endif
+
+/********************** report on array copy ****************************/
+
+#ifdef F2PY_REPORT_ON_ARRAY_COPY
+static void
+f2py_report_on_array_copy(PyArrayObject *arr)
+{
+ const npy_intp arr_size = PyArray_Size((PyObject *)arr);
+ if (arr_size > F2PY_REPORT_ON_ARRAY_COPY) {
+ fprintf(stderr,
+ "copied an array: size=%ld, elsize=%" NPY_INTP_FMT "\n",
+ arr_size, (npy_intp)PyArray_ITEMSIZE(arr));
+ }
+}
+static void
+f2py_report_on_array_copy_fromany(void)
+{
+ fprintf(stderr, "created an array from object\n");
+}
+
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR \
+ f2py_report_on_array_copy((PyArrayObject *)arr)
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY f2py_report_on_array_copy_fromany()
+#else
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMARR
+#define F2PY_REPORT_ON_ARRAY_COPY_FROMANY
+#endif
+
+/************************* array_from_obj *******************************/
+
+/*
+ * File: array_from_pyobj.c
+ *
+ * Description:
+ * ------------
+ * Provides array_from_pyobj function that returns a contiguous array
+ * object with the given dimensions and required storage order, either
+ * in row-major (C) or column-major (Fortran) order. The function
+ * array_from_pyobj is very flexible about its Python object argument
+ * that can be any number, list, tuple, or array.
+ *
+ * array_from_pyobj is used in f2py generated Python extension
+ * modules.
+ *
+ * Author: Pearu Peterson <pearu@cens.ioc.ee>
+ * Created: 13-16 January 2002
+ * $Id: fortranobject.c,v 1.52 2005/07/11 07:44:20 pearu Exp $
+ */
+
+static int check_and_fix_dimensions(const PyArrayObject* arr,
+ const int rank,
+ npy_intp *dims,
+ const char *errmess);
+
+static int
+find_first_negative_dimension(const int rank, const npy_intp *dims)
+{
+ for (int i = 0; i < rank; ++i) {
+ if (dims[i] < 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+#ifdef DEBUG_COPY_ND_ARRAY
+void
+dump_dims(int rank, npy_intp const *dims)
+{
+ int i;
+ printf("[");
+ for (i = 0; i < rank; ++i) {
+ printf("%3" NPY_INTP_FMT, dims[i]);
+ }
+ printf("]\n");
+}
+void
+dump_attrs(const PyArrayObject *obj)
+{
+ const PyArrayObject_fields *arr = (const PyArrayObject_fields *)obj;
+ int rank = PyArray_NDIM(arr);
+ npy_intp size = PyArray_Size((PyObject *)arr);
+ printf("\trank = %d, flags = %d, size = %" NPY_INTP_FMT "\n", rank,
+ arr->flags, size);
+ printf("\tstrides = ");
+ dump_dims(rank, arr->strides);
+ printf("\tdimensions = ");
+ dump_dims(rank, arr->dimensions);
+}
+#endif
+
+#define SWAPTYPE(a, b, t) \
+ { \
+ t c; \
+ c = (a); \
+ (a) = (b); \
+ (b) = c; \
+ }
+
+static int
+swap_arrays(PyArrayObject *obj1, PyArrayObject *obj2)
+{
+ PyArrayObject_fields *arr1 = (PyArrayObject_fields *)obj1,
+ *arr2 = (PyArrayObject_fields *)obj2;
+ SWAPTYPE(arr1->data, arr2->data, char *);
+ SWAPTYPE(arr1->nd, arr2->nd, int);
+ SWAPTYPE(arr1->dimensions, arr2->dimensions, npy_intp *);
+ SWAPTYPE(arr1->strides, arr2->strides, npy_intp *);
+ SWAPTYPE(arr1->base, arr2->base, PyObject *);
+ SWAPTYPE(arr1->descr, arr2->descr, PyArray_Descr *);
+ SWAPTYPE(arr1->flags, arr2->flags, int);
+ /* SWAPTYPE(arr1->weakreflist,arr2->weakreflist,PyObject*); */
+ return 0;
+}
+
+#define ARRAY_ISCOMPATIBLE(arr,type_num) \
+ ((PyArray_ISINTEGER(arr) && PyTypeNum_ISINTEGER(type_num)) || \
+ (PyArray_ISFLOAT(arr) && PyTypeNum_ISFLOAT(type_num)) || \
+ (PyArray_ISCOMPLEX(arr) && PyTypeNum_ISCOMPLEX(type_num)) || \
+ (PyArray_ISBOOL(arr) && PyTypeNum_ISBOOL(type_num)) || \
+ (PyArray_ISSTRING(arr) && PyTypeNum_ISSTRING(type_num)))
+
+static int
+get_elsize(PyObject *obj) {
+ /*
+ get_elsize determines array itemsize from a Python object. Returns
+ elsize if successful, -1 otherwise.
+
+ Supported types of the input are: numpy.ndarray, bytes, str, tuple,
+ list.
+ */
+
+ if (PyArray_Check(obj)) {
+ return PyArray_DESCR((PyArrayObject *)obj)->elsize;
+ } else if (PyBytes_Check(obj)) {
+ return PyBytes_GET_SIZE(obj);
+ } else if (PyUnicode_Check(obj)) {
+ return PyUnicode_GET_LENGTH(obj);
+ } else if (PySequence_Check(obj)) {
+ PyObject* fast = PySequence_Fast(obj, "f2py:fortranobject.c:get_elsize");
+ if (fast != NULL) {
+ Py_ssize_t i, n = PySequence_Fast_GET_SIZE(fast);
+ int sz, elsize = 0;
+ for (i=0; i<n; i++) {
+ sz = get_elsize(PySequence_Fast_GET_ITEM(fast, i) /* borrowed */);
+ if (sz > elsize) {
+ elsize = sz;
+ }
+ }
+ Py_DECREF(fast);
+ return elsize;
+ }
+ }
+ return -1;
+}
+
+extern PyArrayObject *
+ndarray_from_pyobj(const int type_num,
+ const int elsize_,
+ npy_intp *dims,
+ const int rank,
+ const int intent,
+ PyObject *obj,
+ const char *errmess) {
+ /*
+ * Return an array with given element type and shape from a Python
+ * object while taking into account the usage intent of the array.
+ *
+ * - element type is defined by type_num and elsize
+ * - shape is defined by dims and rank
+ *
+ * ndarray_from_pyobj is used to convert Python object arguments
+ * to numpy ndarrays with given type and shape that data is passed
+ * to interfaced Fortran or C functions.
+ *
+ * errmess (if not NULL), contains a prefix of an error message
+ * for an exception to be triggered within this function.
+ *
+ * Negative elsize value means that elsize is to be determined
+ * from the Python object in runtime.
+ *
+ * Note on strings
+ * ---------------
+ *
+ * String type (type_num == NPY_STRING) does not have fixed
+ * element size and, by default, the type object sets it to
+ * 0. Therefore, for string types, one has to use elsize
+ * argument. For other types, elsize value is ignored.
+ *
+ * NumPy defines the type of a fixed-width string as
+ * dtype('S<width>'). In addition, there is also dtype('c'), that
+ * appears as dtype('S1') (these have the same type_num value),
+ * but is actually different (.char attribute is either 'S' or
+ * 'c', respecitely).
+ *
+ * In Fortran, character arrays and strings are different
+ * concepts. The relation between Fortran types, NumPy dtypes,
+ * and type_num-elsize pairs, is defined as follows:
+ *
+ * character*5 foo | dtype('S5') | elsize=5, shape=()
+ * character(5) foo | dtype('S1') | elsize=1, shape=(5)
+ * character*5 foo(n) | dtype('S5') | elsize=5, shape=(n,)
+ * character(5) foo(n) | dtype('S1') | elsize=1, shape=(5, n)
+ * character*(*) foo | dtype('S') | elsize=-1, shape=()
+ *
+ * Note about reference counting
+ * -----------------------------
+ *
+ * If the caller returns the array to Python, it must be done with
+ * Py_BuildValue("N",arr). Otherwise, if obj!=arr then the caller
+ * must call Py_DECREF(arr).
+ *
+ * Note on intent(cache,out,..)
+ * ----------------------------
+ * Don't expect correct data when returning intent(cache) array.
+ *
+ */
+ char mess[F2PY_MESSAGE_BUFFER_SIZE];
+ PyArrayObject *arr = NULL;
+ int elsize = (elsize_ < 0 ? get_elsize(obj) : elsize_);
+ if (elsize < 0) {
+ if (errmess != NULL) {
+ strcpy(mess, errmess);
+ }
+ sprintf(mess + strlen(mess),
+ " -- failed to determine element size from %s",
+ Py_TYPE(obj)->tp_name);
+ PyErr_SetString(PyExc_SystemError, mess);
+ return NULL;
+ }
+ PyArray_Descr * descr = get_descr_from_type_and_elsize(type_num, elsize); // new reference
+ if (descr == NULL) {
+ return NULL;
+ }
+ elsize = descr->elsize;
+ if ((intent & F2PY_INTENT_HIDE)
+ || ((intent & F2PY_INTENT_CACHE) && (obj == Py_None))
+ || ((intent & F2PY_OPTIONAL) && (obj == Py_None))
+ ) {
+ /* intent(cache), optional, intent(hide) */
+ int ineg = find_first_negative_dimension(rank, dims);
+ if (ineg >= 0) {
+ int i;
+ strcpy(mess, "failed to create intent(cache|hide)|optional array"
+ "-- must have defined dimensions but got (");
+ for(i = 0; i < rank; ++i)
+ sprintf(mess + strlen(mess), "%" NPY_INTP_FMT ",", dims[i]);
+ strcat(mess, ")");
+ PyErr_SetString(PyExc_ValueError, mess);
+ Py_DECREF(descr);
+ return NULL;
+ }
+ arr = (PyArrayObject *) \
+ PyArray_NewFromDescr(&PyArray_Type, descr, rank, dims,
+ NULL, NULL, !(intent & F2PY_INTENT_C), NULL);
+ if (arr == NULL) {
+ Py_DECREF(descr);
+ return NULL;
+ }
+ if (PyArray_ITEMSIZE(arr) != elsize) {
+ strcpy(mess, "failed to create intent(cache|hide)|optional array");
+ sprintf(mess+strlen(mess)," -- expected elsize=%d got %" NPY_INTP_FMT, elsize, (npy_intp)PyArray_ITEMSIZE(arr));
+ PyErr_SetString(PyExc_ValueError,mess);
+ Py_DECREF(arr);
+ return NULL;
+ }
+ if (!(intent & F2PY_INTENT_CACHE)) {
+ PyArray_FILLWBYTE(arr, 0);
+ }
+ return arr;
+ }
+
+ if (PyArray_Check(obj)) {
+ arr = (PyArrayObject *)obj;
+ if (intent & F2PY_INTENT_CACHE) {
+ /* intent(cache) */
+ if (PyArray_ISONESEGMENT(arr)
+ && PyArray_ITEMSIZE(arr) >= elsize) {
+ if (check_and_fix_dimensions(arr, rank, dims, errmess)) {
+ Py_DECREF(descr);
+ return NULL;
+ }
+ if (intent & F2PY_INTENT_OUT)
+ Py_INCREF(arr);
+ Py_DECREF(descr);
+ return arr;
+ }
+ strcpy(mess, "failed to initialize intent(cache) array");
+ if (!PyArray_ISONESEGMENT(arr))
+ strcat(mess, " -- input must be in one segment");
+ if (PyArray_ITEMSIZE(arr) < elsize)
+ sprintf(mess + strlen(mess),
+ " -- expected at least elsize=%d but got "
+ "%" NPY_INTP_FMT,
+ elsize, (npy_intp)PyArray_ITEMSIZE(arr));
+ PyErr_SetString(PyExc_ValueError, mess);
+ Py_DECREF(descr);
+ return NULL;
+ }
+
+ /* here we have always intent(in) or intent(inout) or intent(inplace)
+ */
+
+ if (check_and_fix_dimensions(arr, rank, dims, errmess)) {
+ Py_DECREF(descr);
+ return NULL;
+ }
+ /*
+ printf("intent alignment=%d\n", F2PY_GET_ALIGNMENT(intent));
+ printf("alignment check=%d\n", F2PY_CHECK_ALIGNMENT(arr, intent));
+ int i;
+ for (i=1;i<=16;i++)
+ printf("i=%d isaligned=%d\n", i, ARRAY_ISALIGNED(arr, i));
+ */
+ if ((! (intent & F2PY_INTENT_COPY)) &&
+ PyArray_ITEMSIZE(arr) == elsize &&
+ ARRAY_ISCOMPATIBLE(arr,type_num) &&
+ F2PY_CHECK_ALIGNMENT(arr, intent)) {
+ if ((intent & F2PY_INTENT_INOUT || intent & F2PY_INTENT_INPLACE)
+ ? ((intent & F2PY_INTENT_C) ? PyArray_ISCARRAY(arr) : PyArray_ISFARRAY(arr))
+ : ((intent & F2PY_INTENT_C) ? PyArray_ISCARRAY_RO(arr) : PyArray_ISFARRAY_RO(arr))) {
+ if ((intent & F2PY_INTENT_OUT)) {
+ Py_INCREF(arr);
+ }
+ /* Returning input array */
+ Py_DECREF(descr);
+ return arr;
+ }
+ }
+ if (intent & F2PY_INTENT_INOUT) {
+ strcpy(mess, "failed to initialize intent(inout) array");
+ /* Must use PyArray_IS*ARRAY because intent(inout) requires
+ * writable input */
+ if ((intent & F2PY_INTENT_C) && !PyArray_ISCARRAY(arr))
+ strcat(mess, " -- input not contiguous");
+ if (!(intent & F2PY_INTENT_C) && !PyArray_ISFARRAY(arr))
+ strcat(mess, " -- input not fortran contiguous");
+ if (PyArray_ITEMSIZE(arr) != elsize)
+ sprintf(mess + strlen(mess),
+ " -- expected elsize=%d but got %" NPY_INTP_FMT,
+ elsize,
+ (npy_intp)PyArray_ITEMSIZE(arr)
+ );
+ if (!(ARRAY_ISCOMPATIBLE(arr, type_num))) {
+ sprintf(mess + strlen(mess),
+ " -- input '%c' not compatible to '%c'",
+ PyArray_DESCR(arr)->type, descr->type);
+ }
+ if (!(F2PY_CHECK_ALIGNMENT(arr, intent)))
+ sprintf(mess + strlen(mess), " -- input not %d-aligned",
+ F2PY_GET_ALIGNMENT(intent));
+ PyErr_SetString(PyExc_ValueError, mess);
+ Py_DECREF(descr);
+ return NULL;
+ }
+
+ /* here we have always intent(in) or intent(inplace) */
+
+ {
+ PyArrayObject * retarr = (PyArrayObject *) \
+ PyArray_NewFromDescr(&PyArray_Type, descr, PyArray_NDIM(arr), PyArray_DIMS(arr),
+ NULL, NULL, !(intent & F2PY_INTENT_C), NULL);
+ if (retarr==NULL) {
+ Py_DECREF(descr);
+ return NULL;
+ }
+ F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
+ if (PyArray_CopyInto(retarr, arr)) {
+ Py_DECREF(retarr);
+ return NULL;
+ }
+ if (intent & F2PY_INTENT_INPLACE) {
+ if (swap_arrays(arr,retarr)) {
+ Py_DECREF(retarr);
+ return NULL; /* XXX: set exception */
+ }
+ Py_XDECREF(retarr);
+ if (intent & F2PY_INTENT_OUT)
+ Py_INCREF(arr);
+ } else {
+ arr = retarr;
+ }
+ }
+ return arr;
+ }
+
+ if ((intent & F2PY_INTENT_INOUT) || (intent & F2PY_INTENT_INPLACE) ||
+ (intent & F2PY_INTENT_CACHE)) {
+ PyErr_Format(PyExc_TypeError,
+ "failed to initialize intent(inout|inplace|cache) "
+ "array, input '%s' object is not an array",
+ Py_TYPE(obj)->tp_name);
+ Py_DECREF(descr);
+ return NULL;
+ }
+
+ {
+ F2PY_REPORT_ON_ARRAY_COPY_FROMANY;
+ arr = (PyArrayObject *)PyArray_FromAny(
+ obj, descr, 0, 0,
+ ((intent & F2PY_INTENT_C) ? NPY_ARRAY_CARRAY
+ : NPY_ARRAY_FARRAY) |
+ NPY_ARRAY_FORCECAST,
+ NULL);
+ // Warning: in the case of NPY_STRING, PyArray_FromAny may
+ // reset descr->elsize, e.g. dtype('S0') becomes dtype('S1').
+ if (arr == NULL) {
+ Py_DECREF(descr);
+ return NULL;
+ }
+ if (type_num != NPY_STRING && PyArray_ITEMSIZE(arr) != elsize) {
+ // This is internal sanity tests: elsize has been set to
+ // descr->elsize in the beginning of this function.
+ strcpy(mess, "failed to initialize intent(in) array");
+ sprintf(mess + strlen(mess),
+ " -- expected elsize=%d got %" NPY_INTP_FMT, elsize,
+ (npy_intp)PyArray_ITEMSIZE(arr));
+ PyErr_SetString(PyExc_ValueError, mess);
+ Py_DECREF(arr);
+ return NULL;
+ }
+ if (check_and_fix_dimensions(arr, rank, dims, errmess)) {
+ Py_DECREF(arr);
+ return NULL;
+ }
+ return arr;
+ }
+}
+
+extern PyArrayObject *
+array_from_pyobj(const int type_num,
+ npy_intp *dims,
+ const int rank,
+ const int intent,
+ PyObject *obj) {
+ /*
+ Same as ndarray_from_pyobj but with elsize determined from type,
+ if possible. Provided for backward compatibility.
+ */
+ PyArray_Descr* descr = PyArray_DescrFromType(type_num);
+ int elsize = descr->elsize;
+ Py_DECREF(descr);
+ return ndarray_from_pyobj(type_num, elsize, dims, rank, intent, obj, NULL);
+}
+
+/*****************************************/
+/* Helper functions for array_from_pyobj */
+/*****************************************/
+
+static int
+check_and_fix_dimensions(const PyArrayObject* arr, const int rank,
+ npy_intp *dims, const char *errmess)
+{
+ /*
+ * This function fills in blanks (that are -1's) in dims list using
+ * the dimensions from arr. It also checks that non-blank dims will
+ * match with the corresponding values in arr dimensions.
+ *
+ * Returns 0 if the function is successful.
+ *
+ * If an error condition is detected, an exception is set and 1 is
+ * returned.
+ */
+ char mess[F2PY_MESSAGE_BUFFER_SIZE];
+ const npy_intp arr_size =
+ (PyArray_NDIM(arr)) ? PyArray_Size((PyObject *)arr) : 1;
+#ifdef DEBUG_COPY_ND_ARRAY
+ dump_attrs(arr);
+ printf("check_and_fix_dimensions:init: dims=");
+ dump_dims(rank, dims);
+#endif
+ if (rank > PyArray_NDIM(arr)) { /* [1,2] -> [[1],[2]]; 1 -> [[1]] */
+ npy_intp new_size = 1;
+ int free_axe = -1;
+ int i;
+ npy_intp d;
+ /* Fill dims where -1 or 0; check dimensions; calc new_size; */
+ for (i = 0; i < PyArray_NDIM(arr); ++i) {
+ d = PyArray_DIM(arr, i);
+ if (dims[i] >= 0) {
+ if (d > 1 && dims[i] != d) {
+ PyErr_Format(
+ PyExc_ValueError,
+ "%d-th dimension must be fixed to %" NPY_INTP_FMT
+ " but got %" NPY_INTP_FMT "\n",
+ i, dims[i], d);
+ return 1;
+ }
+ if (!dims[i])
+ dims[i] = 1;
+ }
+ else {
+ dims[i] = d ? d : 1;
+ }
+ new_size *= dims[i];
+ }
+ for (i = PyArray_NDIM(arr); i < rank; ++i)
+ if (dims[i] > 1) {
+ PyErr_Format(PyExc_ValueError,
+ "%d-th dimension must be %" NPY_INTP_FMT
+ " but got 0 (not defined).\n",
+ i, dims[i]);
+ return 1;
+ }
+ else if (free_axe < 0)
+ free_axe = i;
+ else
+ dims[i] = 1;
+ if (free_axe >= 0) {
+ dims[free_axe] = arr_size / new_size;
+ new_size *= dims[free_axe];
+ }
+ if (new_size != arr_size) {
+ PyErr_Format(PyExc_ValueError,
+ "unexpected array size: new_size=%" NPY_INTP_FMT
+ ", got array with arr_size=%" NPY_INTP_FMT
+ " (maybe too many free indices)\n",
+ new_size, arr_size);
+ return 1;
+ }
+ }
+ else if (rank == PyArray_NDIM(arr)) {
+ npy_intp new_size = 1;
+ int i;
+ npy_intp d;
+ for (i = 0; i < rank; ++i) {
+ d = PyArray_DIM(arr, i);
+ if (dims[i] >= 0) {
+ if (d > 1 && d != dims[i]) {
+ if (errmess != NULL) {
+ strcpy(mess, errmess);
+ }
+ sprintf(mess + strlen(mess),
+ " -- %d-th dimension must be fixed to %"
+ NPY_INTP_FMT " but got %" NPY_INTP_FMT,
+ i, dims[i], d);
+ PyErr_SetString(PyExc_ValueError, mess);
+ return 1;
+ }
+ if (!dims[i])
+ dims[i] = 1;
+ }
+ else
+ dims[i] = d;
+ new_size *= dims[i];
+ }
+ if (new_size != arr_size) {
+ PyErr_Format(PyExc_ValueError,
+ "unexpected array size: new_size=%" NPY_INTP_FMT
+ ", got array with arr_size=%" NPY_INTP_FMT "\n",
+ new_size, arr_size);
+ return 1;
+ }
+ }
+ else { /* [[1,2]] -> [[1],[2]] */
+ int i, j;
+ npy_intp d;
+ int effrank;
+ npy_intp size;
+ for (i = 0, effrank = 0; i < PyArray_NDIM(arr); ++i)
+ if (PyArray_DIM(arr, i) > 1)
+ ++effrank;
+ if (dims[rank - 1] >= 0)
+ if (effrank > rank) {
+ PyErr_Format(PyExc_ValueError,
+ "too many axes: %d (effrank=%d), "
+ "expected rank=%d\n",
+ PyArray_NDIM(arr), effrank, rank);
+ return 1;
+ }
+
+ for (i = 0, j = 0; i < rank; ++i) {
+ while (j < PyArray_NDIM(arr) && PyArray_DIM(arr, j) < 2) ++j;
+ if (j >= PyArray_NDIM(arr))
+ d = 1;
+ else
+ d = PyArray_DIM(arr, j++);
+ if (dims[i] >= 0) {
+ if (d > 1 && d != dims[i]) {
+ if (errmess != NULL) {
+ strcpy(mess, errmess);
+ }
+ sprintf(mess + strlen(mess),
+ " -- %d-th dimension must be fixed to %"
+ NPY_INTP_FMT " but got %" NPY_INTP_FMT
+ " (real index=%d)\n",
+ i, dims[i], d, j-1);
+ PyErr_SetString(PyExc_ValueError, mess);
+ return 1;
+ }
+ if (!dims[i])
+ dims[i] = 1;
+ }
+ else
+ dims[i] = d;
+ }
+
+ for (i = rank; i < PyArray_NDIM(arr);
+ ++i) { /* [[1,2],[3,4]] -> [1,2,3,4] */
+ while (j < PyArray_NDIM(arr) && PyArray_DIM(arr, j) < 2) ++j;
+ if (j >= PyArray_NDIM(arr))
+ d = 1;
+ else
+ d = PyArray_DIM(arr, j++);
+ dims[rank - 1] *= d;
+ }
+ for (i = 0, size = 1; i < rank; ++i) size *= dims[i];
+ if (size != arr_size) {
+ char msg[200];
+ int len;
+ snprintf(msg, sizeof(msg),
+ "unexpected array size: size=%" NPY_INTP_FMT
+ ", arr_size=%" NPY_INTP_FMT
+ ", rank=%d, effrank=%d, arr.nd=%d, dims=[",
+ size, arr_size, rank, effrank, PyArray_NDIM(arr));
+ for (i = 0; i < rank; ++i) {
+ len = strlen(msg);
+ snprintf(msg + len, sizeof(msg) - len, " %" NPY_INTP_FMT,
+ dims[i]);
+ }
+ len = strlen(msg);
+ snprintf(msg + len, sizeof(msg) - len, " ], arr.dims=[");
+ for (i = 0; i < PyArray_NDIM(arr); ++i) {
+ len = strlen(msg);
+ snprintf(msg + len, sizeof(msg) - len, " %" NPY_INTP_FMT,
+ PyArray_DIM(arr, i));
+ }
+ len = strlen(msg);
+ snprintf(msg + len, sizeof(msg) - len, " ]\n");
+ PyErr_SetString(PyExc_ValueError, msg);
+ return 1;
+ }
+ }
+#ifdef DEBUG_COPY_ND_ARRAY
+ printf("check_and_fix_dimensions:end: dims=");
+ dump_dims(rank, dims);
+#endif
+ return 0;
+}
+
+/* End of file: array_from_pyobj.c */
+
+/************************* copy_ND_array *******************************/
+
+extern int
+copy_ND_array(const PyArrayObject *arr, PyArrayObject *out)
+{
+ F2PY_REPORT_ON_ARRAY_COPY_FROMARR;
+ return PyArray_CopyInto(out, (PyArrayObject *)arr);
+}
+
+/********************* Various utility functions ***********************/
+
+extern int
+f2py_describe(PyObject *obj, char *buf) {
+ /*
+ Write the description of a Python object to buf. The caller must
+ provide buffer with size sufficient to write the description.
+
+ Return 1 on success.
+ */
+ char localbuf[F2PY_MESSAGE_BUFFER_SIZE];
+ if (PyBytes_Check(obj)) {
+ sprintf(localbuf, "%d-%s", (npy_int)PyBytes_GET_SIZE(obj), Py_TYPE(obj)->tp_name);
+ } else if (PyUnicode_Check(obj)) {
+ sprintf(localbuf, "%d-%s", (npy_int)PyUnicode_GET_LENGTH(obj), Py_TYPE(obj)->tp_name);
+ } else if (PyArray_CheckScalar(obj)) {
+ PyArrayObject* arr = (PyArrayObject*)obj;
+ sprintf(localbuf, "%c%" NPY_INTP_FMT "-%s-scalar", PyArray_DESCR(arr)->kind, PyArray_ITEMSIZE(arr), Py_TYPE(obj)->tp_name);
+ } else if (PyArray_Check(obj)) {
+ int i;
+ PyArrayObject* arr = (PyArrayObject*)obj;
+ strcpy(localbuf, "(");
+ for (i=0; i<PyArray_NDIM(arr); i++) {
+ if (i) {
+ strcat(localbuf, " ");
+ }
+ sprintf(localbuf + strlen(localbuf), "%" NPY_INTP_FMT ",", PyArray_DIM(arr, i));
+ }
+ sprintf(localbuf + strlen(localbuf), ")-%c%" NPY_INTP_FMT "-%s", PyArray_DESCR(arr)->kind, PyArray_ITEMSIZE(arr), Py_TYPE(obj)->tp_name);
+ } else if (PySequence_Check(obj)) {
+ sprintf(localbuf, "%d-%s", (npy_int)PySequence_Length(obj), Py_TYPE(obj)->tp_name);
+ } else {
+ sprintf(localbuf, "%s instance", Py_TYPE(obj)->tp_name);
+ }
+ // TODO: detect the size of buf and make sure that size(buf) >= size(localbuf).
+ strcpy(buf, localbuf);
+ return 1;
+}
+
+extern npy_intp
+f2py_size_impl(PyArrayObject* var, ...)
+{
+ npy_intp sz = 0;
+ npy_intp dim;
+ npy_intp rank;
+ va_list argp;
+ va_start(argp, var);
+ dim = va_arg(argp, npy_int);
+ if (dim==-1)
+ {
+ sz = PyArray_SIZE(var);
+ }
+ else
+ {
+ rank = PyArray_NDIM(var);
+ if (dim>=1 && dim<=rank)
+ sz = PyArray_DIM(var, dim-1);
+ else
+ fprintf(stderr, "f2py_size: 2nd argument value=%" NPY_INTP_FMT
+ " fails to satisfy 1<=value<=%" NPY_INTP_FMT
+ ". Result will be 0.\n", dim, rank);
+ }
+ va_end(argp);
+ return sz;
+}
+
+/*********************************************/
+/* Compatibility functions for Python >= 3.0 */
+/*********************************************/
+
+PyObject *
+F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
+{
+ PyObject *ret = PyCapsule_New(ptr, NULL, dtor);
+ if (ret == NULL) {
+ PyErr_Clear();
+ }
+ return ret;
+}
+
+void *
+F2PyCapsule_AsVoidPtr(PyObject *obj)
+{
+ void *ret = PyCapsule_GetPointer(obj, NULL);
+ if (ret == NULL) {
+ PyErr_Clear();
+ }
+ return ret;
+}
+
+int
+F2PyCapsule_Check(PyObject *ptr)
+{
+ return PyCapsule_CheckExact(ptr);
+}
+
+#ifdef __cplusplus
+}
+#endif
+/************************* EOF fortranobject.c *******************************/
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.h b/venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.h
new file mode 100644
index 00000000..abd699c2
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/src/fortranobject.h
@@ -0,0 +1,173 @@
+#ifndef Py_FORTRANOBJECT_H
+#define Py_FORTRANOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+
+#ifndef NPY_NO_DEPRECATED_API
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+#endif
+#ifdef FORTRANOBJECT_C
+#define NO_IMPORT_ARRAY
+#endif
+#define PY_ARRAY_UNIQUE_SYMBOL _npy_f2py_ARRAY_API
+#include "numpy/arrayobject.h"
+#include "numpy/npy_3kcompat.h"
+
+#ifdef F2PY_REPORT_ATEXIT
+#include <sys/timeb.h>
+// clang-format off
+extern void f2py_start_clock(void);
+extern void f2py_stop_clock(void);
+extern void f2py_start_call_clock(void);
+extern void f2py_stop_call_clock(void);
+extern void f2py_cb_start_clock(void);
+extern void f2py_cb_stop_clock(void);
+extern void f2py_cb_start_call_clock(void);
+extern void f2py_cb_stop_call_clock(void);
+extern void f2py_report_on_exit(int, void *);
+// clang-format on
+#endif
+
+#ifdef DMALLOC
+#include "dmalloc.h"
+#endif
+
+/* Fortran object interface */
+
+/*
+123456789-123456789-123456789-123456789-123456789-123456789-123456789-12
+
+PyFortranObject represents various Fortran objects:
+Fortran (module) routines, COMMON blocks, module data.
+
+Author: Pearu Peterson <pearu@cens.ioc.ee>
+*/
+
+#define F2PY_MAX_DIMS 40
+#define F2PY_MESSAGE_BUFFER_SIZE 300 // Increase on "stack smashing detected"
+
+typedef void (*f2py_set_data_func)(char *, npy_intp *);
+typedef void (*f2py_void_func)(void);
+typedef void (*f2py_init_func)(int *, npy_intp *, f2py_set_data_func, int *);
+
+/*typedef void* (*f2py_c_func)(void*,...);*/
+
+typedef void *(*f2pycfunc)(void);
+
+typedef struct {
+ char *name; /* attribute (array||routine) name */
+ int rank; /* array rank, 0 for scalar, max is F2PY_MAX_DIMS,
+ || rank=-1 for Fortran routine */
+ struct {
+ npy_intp d[F2PY_MAX_DIMS];
+ } dims; /* dimensions of the array, || not used */
+ int type; /* PyArray_<type> || not used */
+ int elsize; /* Element size || not used */
+ char *data; /* pointer to array || Fortran routine */
+ f2py_init_func func; /* initialization function for
+ allocatable arrays:
+ func(&rank,dims,set_ptr_func,name,len(name))
+ || C/API wrapper for Fortran routine */
+ char *doc; /* documentation string; only recommended
+ for routines. */
+} FortranDataDef;
+
+typedef struct {
+ PyObject_HEAD
+ int len; /* Number of attributes */
+ FortranDataDef *defs; /* An array of FortranDataDef's */
+ PyObject *dict; /* Fortran object attribute dictionary */
+} PyFortranObject;
+
+#define PyFortran_Check(op) (Py_TYPE(op) == &PyFortran_Type)
+#define PyFortran_Check1(op) (0 == strcmp(Py_TYPE(op)->tp_name, "fortran"))
+
+extern PyTypeObject PyFortran_Type;
+extern int
+F2PyDict_SetItemString(PyObject *dict, char *name, PyObject *obj);
+extern PyObject *
+PyFortranObject_New(FortranDataDef *defs, f2py_void_func init);
+extern PyObject *
+PyFortranObject_NewAsAttr(FortranDataDef *defs);
+
+PyObject *
+F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *));
+void *
+F2PyCapsule_AsVoidPtr(PyObject *obj);
+int
+F2PyCapsule_Check(PyObject *ptr);
+
+extern void *
+F2PySwapThreadLocalCallbackPtr(char *key, void *ptr);
+extern void *
+F2PyGetThreadLocalCallbackPtr(char *key);
+
+#define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & NPY_ARRAY_C_CONTIGUOUS)
+#define F2PY_INTENT_IN 1
+#define F2PY_INTENT_INOUT 2
+#define F2PY_INTENT_OUT 4
+#define F2PY_INTENT_HIDE 8
+#define F2PY_INTENT_CACHE 16
+#define F2PY_INTENT_COPY 32
+#define F2PY_INTENT_C 64
+#define F2PY_OPTIONAL 128
+#define F2PY_INTENT_INPLACE 256
+#define F2PY_INTENT_ALIGNED4 512
+#define F2PY_INTENT_ALIGNED8 1024
+#define F2PY_INTENT_ALIGNED16 2048
+
+#define ARRAY_ISALIGNED(ARR, SIZE) ((size_t)(PyArray_DATA(ARR)) % (SIZE) == 0)
+#define F2PY_ALIGN4(intent) (intent & F2PY_INTENT_ALIGNED4)
+#define F2PY_ALIGN8(intent) (intent & F2PY_INTENT_ALIGNED8)
+#define F2PY_ALIGN16(intent) (intent & F2PY_INTENT_ALIGNED16)
+
+#define F2PY_GET_ALIGNMENT(intent) \
+ (F2PY_ALIGN4(intent) \
+ ? 4 \
+ : (F2PY_ALIGN8(intent) ? 8 : (F2PY_ALIGN16(intent) ? 16 : 1)))
+#define F2PY_CHECK_ALIGNMENT(arr, intent) \
+ ARRAY_ISALIGNED(arr, F2PY_GET_ALIGNMENT(intent))
+#define F2PY_ARRAY_IS_CHARACTER_COMPATIBLE(arr) ((PyArray_DESCR(arr)->type_num == NPY_STRING && PyArray_DESCR(arr)->elsize >= 1) \
+ || PyArray_DESCR(arr)->type_num == NPY_UINT8)
+#define F2PY_IS_UNICODE_ARRAY(arr) (PyArray_DESCR(arr)->type_num == NPY_UNICODE)
+
+extern PyArrayObject *
+ndarray_from_pyobj(const int type_num, const int elsize_, npy_intp *dims,
+ const int rank, const int intent, PyObject *obj,
+ const char *errmess);
+
+extern PyArrayObject *
+array_from_pyobj(const int type_num, npy_intp *dims, const int rank,
+ const int intent, PyObject *obj);
+extern int
+copy_ND_array(const PyArrayObject *in, PyArrayObject *out);
+
+#ifdef DEBUG_COPY_ND_ARRAY
+extern void
+dump_attrs(const PyArrayObject *arr);
+#endif
+
+ extern int f2py_describe(PyObject *obj, char *buf);
+
+ /* Utility CPP macros and functions that can be used in signature file
+ expressions. See signature-file.rst for documentation.
+ */
+
+#define f2py_itemsize(var) (PyArray_DESCR((capi_ ## var ## _as_array))->elsize)
+#define f2py_size(var, ...) f2py_size_impl((PyArrayObject *)(capi_ ## var ## _as_array), ## __VA_ARGS__, -1)
+#define f2py_rank(var) var ## _Rank
+#define f2py_shape(var,dim) var ## _Dims[dim]
+#define f2py_len(var) f2py_shape(var,0)
+#define f2py_fshape(var,dim) f2py_shape(var,rank(var)-dim-1)
+#define f2py_flen(var) f2py_fshape(var,0)
+#define f2py_slen(var) capi_ ## var ## _len
+
+ extern npy_intp f2py_size_impl(PyArrayObject* var, ...);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_FORTRANOBJECT_H */
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/symbolic.py b/venv/lib/python3.9/site-packages/numpy/f2py/symbolic.py
new file mode 100644
index 00000000..c2ab0f14
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/symbolic.py
@@ -0,0 +1,1510 @@
+"""Fortran/C symbolic expressions
+
+References:
+- J3/21-007: Draft Fortran 202x. https://j3-fortran.org/doc/year/21/21-007.pdf
+"""
+
+# To analyze Fortran expressions to solve dimensions specifications,
+# for instances, we implement a minimal symbolic engine for parsing
+# expressions into a tree of expression instances. As a first
+# instance, we care only about arithmetic expressions involving
+# integers and operations like addition (+), subtraction (-),
+# multiplication (*), division (Fortran / is Python //, Fortran // is
+# concatenate), and exponentiation (**). In addition, .pyf files may
+# contain C expressions that support here is implemented as well.
+#
+# TODO: support logical constants (Op.BOOLEAN)
+# TODO: support logical operators (.AND., ...)
+# TODO: support defined operators (.MYOP., ...)
+#
+__all__ = ['Expr']
+
+
+import re
+import warnings
+from enum import Enum
+from math import gcd
+
+
+class Language(Enum):
+ """
+ Used as Expr.tostring language argument.
+ """
+ Python = 0
+ Fortran = 1
+ C = 2
+
+
+class Op(Enum):
+ """
+ Used as Expr op attribute.
+ """
+ INTEGER = 10
+ REAL = 12
+ COMPLEX = 15
+ STRING = 20
+ ARRAY = 30
+ SYMBOL = 40
+ TERNARY = 100
+ APPLY = 200
+ INDEXING = 210
+ CONCAT = 220
+ RELATIONAL = 300
+ TERMS = 1000
+ FACTORS = 2000
+ REF = 3000
+ DEREF = 3001
+
+
+class RelOp(Enum):
+ """
+ Used in Op.RELATIONAL expression to specify the function part.
+ """
+ EQ = 1
+ NE = 2
+ LT = 3
+ LE = 4
+ GT = 5
+ GE = 6
+
+ @classmethod
+ def fromstring(cls, s, language=Language.C):
+ if language is Language.Fortran:
+ return {'.eq.': RelOp.EQ, '.ne.': RelOp.NE,
+ '.lt.': RelOp.LT, '.le.': RelOp.LE,
+ '.gt.': RelOp.GT, '.ge.': RelOp.GE}[s.lower()]
+ return {'==': RelOp.EQ, '!=': RelOp.NE, '<': RelOp.LT,
+ '<=': RelOp.LE, '>': RelOp.GT, '>=': RelOp.GE}[s]
+
+ def tostring(self, language=Language.C):
+ if language is Language.Fortran:
+ return {RelOp.EQ: '.eq.', RelOp.NE: '.ne.',
+ RelOp.LT: '.lt.', RelOp.LE: '.le.',
+ RelOp.GT: '.gt.', RelOp.GE: '.ge.'}[self]
+ return {RelOp.EQ: '==', RelOp.NE: '!=',
+ RelOp.LT: '<', RelOp.LE: '<=',
+ RelOp.GT: '>', RelOp.GE: '>='}[self]
+
+
+class ArithOp(Enum):
+ """
+ Used in Op.APPLY expression to specify the function part.
+ """
+ POS = 1
+ NEG = 2
+ ADD = 3
+ SUB = 4
+ MUL = 5
+ DIV = 6
+ POW = 7
+
+
+class OpError(Exception):
+ pass
+
+
+class Precedence(Enum):
+ """
+ Used as Expr.tostring precedence argument.
+ """
+ ATOM = 0
+ POWER = 1
+ UNARY = 2
+ PRODUCT = 3
+ SUM = 4
+ LT = 6
+ EQ = 7
+ LAND = 11
+ LOR = 12
+ TERNARY = 13
+ ASSIGN = 14
+ TUPLE = 15
+ NONE = 100
+
+
+integer_types = (int,)
+number_types = (int, float)
+
+
+def _pairs_add(d, k, v):
+ # Internal utility method for updating terms and factors data.
+ c = d.get(k)
+ if c is None:
+ d[k] = v
+ else:
+ c = c + v
+ if c:
+ d[k] = c
+ else:
+ del d[k]
+
+
+class ExprWarning(UserWarning):
+ pass
+
+
+def ewarn(message):
+ warnings.warn(message, ExprWarning, stacklevel=2)
+
+
+class Expr:
+ """Represents a Fortran expression as a op-data pair.
+
+ Expr instances are hashable and sortable.
+ """
+
+ @staticmethod
+ def parse(s, language=Language.C):
+ """Parse a Fortran expression to a Expr.
+ """
+ return fromstring(s, language=language)
+
+ def __init__(self, op, data):
+ assert isinstance(op, Op)
+
+ # sanity checks
+ if op is Op.INTEGER:
+ # data is a 2-tuple of numeric object and a kind value
+ # (default is 4)
+ assert isinstance(data, tuple) and len(data) == 2
+ assert isinstance(data[0], int)
+ assert isinstance(data[1], (int, str)), data
+ elif op is Op.REAL:
+ # data is a 2-tuple of numeric object and a kind value
+ # (default is 4)
+ assert isinstance(data, tuple) and len(data) == 2
+ assert isinstance(data[0], float)
+ assert isinstance(data[1], (int, str)), data
+ elif op is Op.COMPLEX:
+ # data is a 2-tuple of constant expressions
+ assert isinstance(data, tuple) and len(data) == 2
+ elif op is Op.STRING:
+ # data is a 2-tuple of quoted string and a kind value
+ # (default is 1)
+ assert isinstance(data, tuple) and len(data) == 2
+ assert (isinstance(data[0], str)
+ and data[0][::len(data[0])-1] in ('""', "''", '@@'))
+ assert isinstance(data[1], (int, str)), data
+ elif op is Op.SYMBOL:
+ # data is any hashable object
+ assert hash(data) is not None
+ elif op in (Op.ARRAY, Op.CONCAT):
+ # data is a tuple of expressions
+ assert isinstance(data, tuple)
+ assert all(isinstance(item, Expr) for item in data), data
+ elif op in (Op.TERMS, Op.FACTORS):
+ # data is {<term|base>:<coeff|exponent>} where dict values
+ # are nonzero Python integers
+ assert isinstance(data, dict)
+ elif op is Op.APPLY:
+ # data is (<function>, <operands>, <kwoperands>) where
+ # operands are Expr instances
+ assert isinstance(data, tuple) and len(data) == 3
+ # function is any hashable object
+ assert hash(data[0]) is not None
+ assert isinstance(data[1], tuple)
+ assert isinstance(data[2], dict)
+ elif op is Op.INDEXING:
+ # data is (<object>, <indices>)
+ assert isinstance(data, tuple) and len(data) == 2
+ # function is any hashable object
+ assert hash(data[0]) is not None
+ elif op is Op.TERNARY:
+ # data is (<cond>, <expr1>, <expr2>)
+ assert isinstance(data, tuple) and len(data) == 3
+ elif op in (Op.REF, Op.DEREF):
+ # data is Expr instance
+ assert isinstance(data, Expr)
+ elif op is Op.RELATIONAL:
+ # data is (<relop>, <left>, <right>)
+ assert isinstance(data, tuple) and len(data) == 3
+ else:
+ raise NotImplementedError(
+ f'unknown op or missing sanity check: {op}')
+
+ self.op = op
+ self.data = data
+
+ def __eq__(self, other):
+ return (isinstance(other, Expr)
+ and self.op is other.op
+ and self.data == other.data)
+
+ def __hash__(self):
+ if self.op in (Op.TERMS, Op.FACTORS):
+ data = tuple(sorted(self.data.items()))
+ elif self.op is Op.APPLY:
+ data = self.data[:2] + tuple(sorted(self.data[2].items()))
+ else:
+ data = self.data
+ return hash((self.op, data))
+
+ def __lt__(self, other):
+ if isinstance(other, Expr):
+ if self.op is not other.op:
+ return self.op.value < other.op.value
+ if self.op in (Op.TERMS, Op.FACTORS):
+ return (tuple(sorted(self.data.items()))
+ < tuple(sorted(other.data.items())))
+ if self.op is Op.APPLY:
+ if self.data[:2] != other.data[:2]:
+ return self.data[:2] < other.data[:2]
+ return tuple(sorted(self.data[2].items())) < tuple(
+ sorted(other.data[2].items()))
+ return self.data < other.data
+ return NotImplemented
+
+ def __le__(self, other): return self == other or self < other
+
+ def __gt__(self, other): return not (self <= other)
+
+ def __ge__(self, other): return not (self < other)
+
+ def __repr__(self):
+ return f'{type(self).__name__}({self.op}, {self.data!r})'
+
+ def __str__(self):
+ return self.tostring()
+
+ def tostring(self, parent_precedence=Precedence.NONE,
+ language=Language.Fortran):
+ """Return a string representation of Expr.
+ """
+ if self.op in (Op.INTEGER, Op.REAL):
+ precedence = (Precedence.SUM if self.data[0] < 0
+ else Precedence.ATOM)
+ r = str(self.data[0]) + (f'_{self.data[1]}'
+ if self.data[1] != 4 else '')
+ elif self.op is Op.COMPLEX:
+ r = ', '.join(item.tostring(Precedence.TUPLE, language=language)
+ for item in self.data)
+ r = '(' + r + ')'
+ precedence = Precedence.ATOM
+ elif self.op is Op.SYMBOL:
+ precedence = Precedence.ATOM
+ r = str(self.data)
+ elif self.op is Op.STRING:
+ r = self.data[0]
+ if self.data[1] != 1:
+ r = self.data[1] + '_' + r
+ precedence = Precedence.ATOM
+ elif self.op is Op.ARRAY:
+ r = ', '.join(item.tostring(Precedence.TUPLE, language=language)
+ for item in self.data)
+ r = '[' + r + ']'
+ precedence = Precedence.ATOM
+ elif self.op is Op.TERMS:
+ terms = []
+ for term, coeff in sorted(self.data.items()):
+ if coeff < 0:
+ op = ' - '
+ coeff = -coeff
+ else:
+ op = ' + '
+ if coeff == 1:
+ term = term.tostring(Precedence.SUM, language=language)
+ else:
+ if term == as_number(1):
+ term = str(coeff)
+ else:
+ term = f'{coeff} * ' + term.tostring(
+ Precedence.PRODUCT, language=language)
+ if terms:
+ terms.append(op)
+ elif op == ' - ':
+ terms.append('-')
+ terms.append(term)
+ r = ''.join(terms) or '0'
+ precedence = Precedence.SUM if terms else Precedence.ATOM
+ elif self.op is Op.FACTORS:
+ factors = []
+ tail = []
+ for base, exp in sorted(self.data.items()):
+ op = ' * '
+ if exp == 1:
+ factor = base.tostring(Precedence.PRODUCT,
+ language=language)
+ elif language is Language.C:
+ if exp in range(2, 10):
+ factor = base.tostring(Precedence.PRODUCT,
+ language=language)
+ factor = ' * '.join([factor] * exp)
+ elif exp in range(-10, 0):
+ factor = base.tostring(Precedence.PRODUCT,
+ language=language)
+ tail += [factor] * -exp
+ continue
+ else:
+ factor = base.tostring(Precedence.TUPLE,
+ language=language)
+ factor = f'pow({factor}, {exp})'
+ else:
+ factor = base.tostring(Precedence.POWER,
+ language=language) + f' ** {exp}'
+ if factors:
+ factors.append(op)
+ factors.append(factor)
+ if tail:
+ if not factors:
+ factors += ['1']
+ factors += ['/', '(', ' * '.join(tail), ')']
+ r = ''.join(factors) or '1'
+ precedence = Precedence.PRODUCT if factors else Precedence.ATOM
+ elif self.op is Op.APPLY:
+ name, args, kwargs = self.data
+ if name is ArithOp.DIV and language is Language.C:
+ numer, denom = [arg.tostring(Precedence.PRODUCT,
+ language=language)
+ for arg in args]
+ r = f'{numer} / {denom}'
+ precedence = Precedence.PRODUCT
+ else:
+ args = [arg.tostring(Precedence.TUPLE, language=language)
+ for arg in args]
+ args += [k + '=' + v.tostring(Precedence.NONE)
+ for k, v in kwargs.items()]
+ r = f'{name}({", ".join(args)})'
+ precedence = Precedence.ATOM
+ elif self.op is Op.INDEXING:
+ name = self.data[0]
+ args = [arg.tostring(Precedence.TUPLE, language=language)
+ for arg in self.data[1:]]
+ r = f'{name}[{", ".join(args)}]'
+ precedence = Precedence.ATOM
+ elif self.op is Op.CONCAT:
+ args = [arg.tostring(Precedence.PRODUCT, language=language)
+ for arg in self.data]
+ r = " // ".join(args)
+ precedence = Precedence.PRODUCT
+ elif self.op is Op.TERNARY:
+ cond, expr1, expr2 = [a.tostring(Precedence.TUPLE,
+ language=language)
+ for a in self.data]
+ if language is Language.C:
+ r = f'({cond}?{expr1}:{expr2})'
+ elif language is Language.Python:
+ r = f'({expr1} if {cond} else {expr2})'
+ elif language is Language.Fortran:
+ r = f'merge({expr1}, {expr2}, {cond})'
+ else:
+ raise NotImplementedError(
+ f'tostring for {self.op} and {language}')
+ precedence = Precedence.ATOM
+ elif self.op is Op.REF:
+ r = '&' + self.data.tostring(Precedence.UNARY, language=language)
+ precedence = Precedence.UNARY
+ elif self.op is Op.DEREF:
+ r = '*' + self.data.tostring(Precedence.UNARY, language=language)
+ precedence = Precedence.UNARY
+ elif self.op is Op.RELATIONAL:
+ rop, left, right = self.data
+ precedence = (Precedence.EQ if rop in (RelOp.EQ, RelOp.NE)
+ else Precedence.LT)
+ left = left.tostring(precedence, language=language)
+ right = right.tostring(precedence, language=language)
+ rop = rop.tostring(language=language)
+ r = f'{left} {rop} {right}'
+ else:
+ raise NotImplementedError(f'tostring for op {self.op}')
+ if parent_precedence.value < precedence.value:
+ # If parent precedence is higher than operand precedence,
+ # operand will be enclosed in parenthesis.
+ return '(' + r + ')'
+ return r
+
+ def __pos__(self):
+ return self
+
+ def __neg__(self):
+ return self * -1
+
+ def __add__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ if self.op is other.op:
+ if self.op in (Op.INTEGER, Op.REAL):
+ return as_number(
+ self.data[0] + other.data[0],
+ max(self.data[1], other.data[1]))
+ if self.op is Op.COMPLEX:
+ r1, i1 = self.data
+ r2, i2 = other.data
+ return as_complex(r1 + r2, i1 + i2)
+ if self.op is Op.TERMS:
+ r = Expr(self.op, dict(self.data))
+ for k, v in other.data.items():
+ _pairs_add(r.data, k, v)
+ return normalize(r)
+ if self.op is Op.COMPLEX and other.op in (Op.INTEGER, Op.REAL):
+ return self + as_complex(other)
+ elif self.op in (Op.INTEGER, Op.REAL) and other.op is Op.COMPLEX:
+ return as_complex(self) + other
+ elif self.op is Op.REAL and other.op is Op.INTEGER:
+ return self + as_real(other, kind=self.data[1])
+ elif self.op is Op.INTEGER and other.op is Op.REAL:
+ return as_real(self, kind=other.data[1]) + other
+ return as_terms(self) + as_terms(other)
+ return NotImplemented
+
+ def __radd__(self, other):
+ if isinstance(other, number_types):
+ return as_number(other) + self
+ return NotImplemented
+
+ def __sub__(self, other):
+ return self + (-other)
+
+ def __rsub__(self, other):
+ if isinstance(other, number_types):
+ return as_number(other) - self
+ return NotImplemented
+
+ def __mul__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ if self.op is other.op:
+ if self.op in (Op.INTEGER, Op.REAL):
+ return as_number(self.data[0] * other.data[0],
+ max(self.data[1], other.data[1]))
+ elif self.op is Op.COMPLEX:
+ r1, i1 = self.data
+ r2, i2 = other.data
+ return as_complex(r1 * r2 - i1 * i2, r1 * i2 + r2 * i1)
+
+ if self.op is Op.FACTORS:
+ r = Expr(self.op, dict(self.data))
+ for k, v in other.data.items():
+ _pairs_add(r.data, k, v)
+ return normalize(r)
+ elif self.op is Op.TERMS:
+ r = Expr(self.op, {})
+ for t1, c1 in self.data.items():
+ for t2, c2 in other.data.items():
+ _pairs_add(r.data, t1 * t2, c1 * c2)
+ return normalize(r)
+
+ if self.op is Op.COMPLEX and other.op in (Op.INTEGER, Op.REAL):
+ return self * as_complex(other)
+ elif other.op is Op.COMPLEX and self.op in (Op.INTEGER, Op.REAL):
+ return as_complex(self) * other
+ elif self.op is Op.REAL and other.op is Op.INTEGER:
+ return self * as_real(other, kind=self.data[1])
+ elif self.op is Op.INTEGER and other.op is Op.REAL:
+ return as_real(self, kind=other.data[1]) * other
+
+ if self.op is Op.TERMS:
+ return self * as_terms(other)
+ elif other.op is Op.TERMS:
+ return as_terms(self) * other
+
+ return as_factors(self) * as_factors(other)
+ return NotImplemented
+
+ def __rmul__(self, other):
+ if isinstance(other, number_types):
+ return as_number(other) * self
+ return NotImplemented
+
+ def __pow__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ if other.op is Op.INTEGER:
+ exponent = other.data[0]
+ # TODO: other kind not used
+ if exponent == 0:
+ return as_number(1)
+ if exponent == 1:
+ return self
+ if exponent > 0:
+ if self.op is Op.FACTORS:
+ r = Expr(self.op, {})
+ for k, v in self.data.items():
+ r.data[k] = v * exponent
+ return normalize(r)
+ return self * (self ** (exponent - 1))
+ elif exponent != -1:
+ return (self ** (-exponent)) ** -1
+ return Expr(Op.FACTORS, {self: exponent})
+ return as_apply(ArithOp.POW, self, other)
+ return NotImplemented
+
+ def __truediv__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ # Fortran / is different from Python /:
+ # - `/` is a truncate operation for integer operands
+ return normalize(as_apply(ArithOp.DIV, self, other))
+ return NotImplemented
+
+ def __rtruediv__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ return other / self
+ return NotImplemented
+
+ def __floordiv__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ # Fortran // is different from Python //:
+ # - `//` is a concatenate operation for string operands
+ return normalize(Expr(Op.CONCAT, (self, other)))
+ return NotImplemented
+
+ def __rfloordiv__(self, other):
+ other = as_expr(other)
+ if isinstance(other, Expr):
+ return other // self
+ return NotImplemented
+
+ def __call__(self, *args, **kwargs):
+ # In Fortran, parenthesis () are use for both function call as
+ # well as indexing operations.
+ #
+ # TODO: implement a method for deciding when __call__ should
+ # return an INDEXING expression.
+ return as_apply(self, *map(as_expr, args),
+ **dict((k, as_expr(v)) for k, v in kwargs.items()))
+
+ def __getitem__(self, index):
+ # Provided to support C indexing operations that .pyf files
+ # may contain.
+ index = as_expr(index)
+ if not isinstance(index, tuple):
+ index = index,
+ if len(index) > 1:
+ ewarn(f'C-index should be a single expression but got `{index}`')
+ return Expr(Op.INDEXING, (self,) + index)
+
+ def substitute(self, symbols_map):
+ """Recursively substitute symbols with values in symbols map.
+
+ Symbols map is a dictionary of symbol-expression pairs.
+ """
+ if self.op is Op.SYMBOL:
+ value = symbols_map.get(self)
+ if value is None:
+ return self
+ m = re.match(r'\A(@__f2py_PARENTHESIS_(\w+)_\d+@)\Z', self.data)
+ if m:
+ # complement to fromstring method
+ items, paren = m.groups()
+ if paren in ['ROUNDDIV', 'SQUARE']:
+ return as_array(value)
+ assert paren == 'ROUND', (paren, value)
+ return value
+ if self.op in (Op.INTEGER, Op.REAL, Op.STRING):
+ return self
+ if self.op in (Op.ARRAY, Op.COMPLEX):
+ return Expr(self.op, tuple(item.substitute(symbols_map)
+ for item in self.data))
+ if self.op is Op.CONCAT:
+ return normalize(Expr(self.op, tuple(item.substitute(symbols_map)
+ for item in self.data)))
+ if self.op is Op.TERMS:
+ r = None
+ for term, coeff in self.data.items():
+ if r is None:
+ r = term.substitute(symbols_map) * coeff
+ else:
+ r += term.substitute(symbols_map) * coeff
+ if r is None:
+ ewarn('substitute: empty TERMS expression interpreted as'
+ ' int-literal 0')
+ return as_number(0)
+ return r
+ if self.op is Op.FACTORS:
+ r = None
+ for base, exponent in self.data.items():
+ if r is None:
+ r = base.substitute(symbols_map) ** exponent
+ else:
+ r *= base.substitute(symbols_map) ** exponent
+ if r is None:
+ ewarn('substitute: empty FACTORS expression interpreted'
+ ' as int-literal 1')
+ return as_number(1)
+ return r
+ if self.op is Op.APPLY:
+ target, args, kwargs = self.data
+ if isinstance(target, Expr):
+ target = target.substitute(symbols_map)
+ args = tuple(a.substitute(symbols_map) for a in args)
+ kwargs = dict((k, v.substitute(symbols_map))
+ for k, v in kwargs.items())
+ return normalize(Expr(self.op, (target, args, kwargs)))
+ if self.op is Op.INDEXING:
+ func = self.data[0]
+ if isinstance(func, Expr):
+ func = func.substitute(symbols_map)
+ args = tuple(a.substitute(symbols_map) for a in self.data[1:])
+ return normalize(Expr(self.op, (func,) + args))
+ if self.op is Op.TERNARY:
+ operands = tuple(a.substitute(symbols_map) for a in self.data)
+ return normalize(Expr(self.op, operands))
+ if self.op in (Op.REF, Op.DEREF):
+ return normalize(Expr(self.op, self.data.substitute(symbols_map)))
+ if self.op is Op.RELATIONAL:
+ rop, left, right = self.data
+ left = left.substitute(symbols_map)
+ right = right.substitute(symbols_map)
+ return normalize(Expr(self.op, (rop, left, right)))
+ raise NotImplementedError(f'substitute method for {self.op}: {self!r}')
+
+ def traverse(self, visit, *args, **kwargs):
+ """Traverse expression tree with visit function.
+
+ The visit function is applied to an expression with given args
+ and kwargs.
+
+ Traverse call returns an expression returned by visit when not
+ None, otherwise return a new normalized expression with
+ traverse-visit sub-expressions.
+ """
+ result = visit(self, *args, **kwargs)
+ if result is not None:
+ return result
+
+ if self.op in (Op.INTEGER, Op.REAL, Op.STRING, Op.SYMBOL):
+ return self
+ elif self.op in (Op.COMPLEX, Op.ARRAY, Op.CONCAT, Op.TERNARY):
+ return normalize(Expr(self.op, tuple(
+ item.traverse(visit, *args, **kwargs)
+ for item in self.data)))
+ elif self.op in (Op.TERMS, Op.FACTORS):
+ data = {}
+ for k, v in self.data.items():
+ k = k.traverse(visit, *args, **kwargs)
+ v = (v.traverse(visit, *args, **kwargs)
+ if isinstance(v, Expr) else v)
+ if k in data:
+ v = data[k] + v
+ data[k] = v
+ return normalize(Expr(self.op, data))
+ elif self.op is Op.APPLY:
+ obj = self.data[0]
+ func = (obj.traverse(visit, *args, **kwargs)
+ if isinstance(obj, Expr) else obj)
+ operands = tuple(operand.traverse(visit, *args, **kwargs)
+ for operand in self.data[1])
+ kwoperands = dict((k, v.traverse(visit, *args, **kwargs))
+ for k, v in self.data[2].items())
+ return normalize(Expr(self.op, (func, operands, kwoperands)))
+ elif self.op is Op.INDEXING:
+ obj = self.data[0]
+ obj = (obj.traverse(visit, *args, **kwargs)
+ if isinstance(obj, Expr) else obj)
+ indices = tuple(index.traverse(visit, *args, **kwargs)
+ for index in self.data[1:])
+ return normalize(Expr(self.op, (obj,) + indices))
+ elif self.op in (Op.REF, Op.DEREF):
+ return normalize(Expr(self.op,
+ self.data.traverse(visit, *args, **kwargs)))
+ elif self.op is Op.RELATIONAL:
+ rop, left, right = self.data
+ left = left.traverse(visit, *args, **kwargs)
+ right = right.traverse(visit, *args, **kwargs)
+ return normalize(Expr(self.op, (rop, left, right)))
+ raise NotImplementedError(f'traverse method for {self.op}')
+
+ def contains(self, other):
+ """Check if self contains other.
+ """
+ found = []
+
+ def visit(expr, found=found):
+ if found:
+ return expr
+ elif expr == other:
+ found.append(1)
+ return expr
+
+ self.traverse(visit)
+
+ return len(found) != 0
+
+ def symbols(self):
+ """Return a set of symbols contained in self.
+ """
+ found = set()
+
+ def visit(expr, found=found):
+ if expr.op is Op.SYMBOL:
+ found.add(expr)
+
+ self.traverse(visit)
+
+ return found
+
+ def polynomial_atoms(self):
+ """Return a set of expressions used as atoms in polynomial self.
+ """
+ found = set()
+
+ def visit(expr, found=found):
+ if expr.op is Op.FACTORS:
+ for b in expr.data:
+ b.traverse(visit)
+ return expr
+ if expr.op in (Op.TERMS, Op.COMPLEX):
+ return
+ if expr.op is Op.APPLY and isinstance(expr.data[0], ArithOp):
+ if expr.data[0] is ArithOp.POW:
+ expr.data[1][0].traverse(visit)
+ return expr
+ return
+ if expr.op in (Op.INTEGER, Op.REAL):
+ return expr
+
+ found.add(expr)
+
+ if expr.op in (Op.INDEXING, Op.APPLY):
+ return expr
+
+ self.traverse(visit)
+
+ return found
+
+ def linear_solve(self, symbol):
+ """Return a, b such that a * symbol + b == self.
+
+ If self is not linear with respect to symbol, raise RuntimeError.
+ """
+ b = self.substitute({symbol: as_number(0)})
+ ax = self - b
+ a = ax.substitute({symbol: as_number(1)})
+
+ zero, _ = as_numer_denom(a * symbol - ax)
+
+ if zero != as_number(0):
+ raise RuntimeError(f'not a {symbol}-linear equation:'
+ f' {a} * {symbol} + {b} == {self}')
+ return a, b
+
+
+def normalize(obj):
+ """Normalize Expr and apply basic evaluation methods.
+ """
+ if not isinstance(obj, Expr):
+ return obj
+
+ if obj.op is Op.TERMS:
+ d = {}
+ for t, c in obj.data.items():
+ if c == 0:
+ continue
+ if t.op is Op.COMPLEX and c != 1:
+ t = t * c
+ c = 1
+ if t.op is Op.TERMS:
+ for t1, c1 in t.data.items():
+ _pairs_add(d, t1, c1 * c)
+ else:
+ _pairs_add(d, t, c)
+ if len(d) == 0:
+ # TODO: deterimine correct kind
+ return as_number(0)
+ elif len(d) == 1:
+ (t, c), = d.items()
+ if c == 1:
+ return t
+ return Expr(Op.TERMS, d)
+
+ if obj.op is Op.FACTORS:
+ coeff = 1
+ d = {}
+ for b, e in obj.data.items():
+ if e == 0:
+ continue
+ if b.op is Op.TERMS and isinstance(e, integer_types) and e > 1:
+ # expand integer powers of sums
+ b = b * (b ** (e - 1))
+ e = 1
+
+ if b.op in (Op.INTEGER, Op.REAL):
+ if e == 1:
+ coeff *= b.data[0]
+ elif e > 0:
+ coeff *= b.data[0] ** e
+ else:
+ _pairs_add(d, b, e)
+ elif b.op is Op.FACTORS:
+ if e > 0 and isinstance(e, integer_types):
+ for b1, e1 in b.data.items():
+ _pairs_add(d, b1, e1 * e)
+ else:
+ _pairs_add(d, b, e)
+ else:
+ _pairs_add(d, b, e)
+ if len(d) == 0 or coeff == 0:
+ # TODO: deterimine correct kind
+ assert isinstance(coeff, number_types)
+ return as_number(coeff)
+ elif len(d) == 1:
+ (b, e), = d.items()
+ if e == 1:
+ t = b
+ else:
+ t = Expr(Op.FACTORS, d)
+ if coeff == 1:
+ return t
+ return Expr(Op.TERMS, {t: coeff})
+ elif coeff == 1:
+ return Expr(Op.FACTORS, d)
+ else:
+ return Expr(Op.TERMS, {Expr(Op.FACTORS, d): coeff})
+
+ if obj.op is Op.APPLY and obj.data[0] is ArithOp.DIV:
+ dividend, divisor = obj.data[1]
+ t1, c1 = as_term_coeff(dividend)
+ t2, c2 = as_term_coeff(divisor)
+ if isinstance(c1, integer_types) and isinstance(c2, integer_types):
+ g = gcd(c1, c2)
+ c1, c2 = c1//g, c2//g
+ else:
+ c1, c2 = c1/c2, 1
+
+ if t1.op is Op.APPLY and t1.data[0] is ArithOp.DIV:
+ numer = t1.data[1][0] * c1
+ denom = t1.data[1][1] * t2 * c2
+ return as_apply(ArithOp.DIV, numer, denom)
+
+ if t2.op is Op.APPLY and t2.data[0] is ArithOp.DIV:
+ numer = t2.data[1][1] * t1 * c1
+ denom = t2.data[1][0] * c2
+ return as_apply(ArithOp.DIV, numer, denom)
+
+ d = dict(as_factors(t1).data)
+ for b, e in as_factors(t2).data.items():
+ _pairs_add(d, b, -e)
+ numer, denom = {}, {}
+ for b, e in d.items():
+ if e > 0:
+ numer[b] = e
+ else:
+ denom[b] = -e
+ numer = normalize(Expr(Op.FACTORS, numer)) * c1
+ denom = normalize(Expr(Op.FACTORS, denom)) * c2
+
+ if denom.op in (Op.INTEGER, Op.REAL) and denom.data[0] == 1:
+ # TODO: denom kind not used
+ return numer
+ return as_apply(ArithOp.DIV, numer, denom)
+
+ if obj.op is Op.CONCAT:
+ lst = [obj.data[0]]
+ for s in obj.data[1:]:
+ last = lst[-1]
+ if (
+ last.op is Op.STRING
+ and s.op is Op.STRING
+ and last.data[0][0] in '"\''
+ and s.data[0][0] == last.data[0][-1]
+ ):
+ new_last = as_string(last.data[0][:-1] + s.data[0][1:],
+ max(last.data[1], s.data[1]))
+ lst[-1] = new_last
+ else:
+ lst.append(s)
+ if len(lst) == 1:
+ return lst[0]
+ return Expr(Op.CONCAT, tuple(lst))
+
+ if obj.op is Op.TERNARY:
+ cond, expr1, expr2 = map(normalize, obj.data)
+ if cond.op is Op.INTEGER:
+ return expr1 if cond.data[0] else expr2
+ return Expr(Op.TERNARY, (cond, expr1, expr2))
+
+ return obj
+
+
+def as_expr(obj):
+ """Convert non-Expr objects to Expr objects.
+ """
+ if isinstance(obj, complex):
+ return as_complex(obj.real, obj.imag)
+ if isinstance(obj, number_types):
+ return as_number(obj)
+ if isinstance(obj, str):
+ # STRING expression holds string with boundary quotes, hence
+ # applying repr:
+ return as_string(repr(obj))
+ if isinstance(obj, tuple):
+ return tuple(map(as_expr, obj))
+ return obj
+
+
+def as_symbol(obj):
+ """Return object as SYMBOL expression (variable or unparsed expression).
+ """
+ return Expr(Op.SYMBOL, obj)
+
+
+def as_number(obj, kind=4):
+ """Return object as INTEGER or REAL constant.
+ """
+ if isinstance(obj, int):
+ return Expr(Op.INTEGER, (obj, kind))
+ if isinstance(obj, float):
+ return Expr(Op.REAL, (obj, kind))
+ if isinstance(obj, Expr):
+ if obj.op in (Op.INTEGER, Op.REAL):
+ return obj
+ raise OpError(f'cannot convert {obj} to INTEGER or REAL constant')
+
+
+def as_integer(obj, kind=4):
+ """Return object as INTEGER constant.
+ """
+ if isinstance(obj, int):
+ return Expr(Op.INTEGER, (obj, kind))
+ if isinstance(obj, Expr):
+ if obj.op is Op.INTEGER:
+ return obj
+ raise OpError(f'cannot convert {obj} to INTEGER constant')
+
+
+def as_real(obj, kind=4):
+ """Return object as REAL constant.
+ """
+ if isinstance(obj, int):
+ return Expr(Op.REAL, (float(obj), kind))
+ if isinstance(obj, float):
+ return Expr(Op.REAL, (obj, kind))
+ if isinstance(obj, Expr):
+ if obj.op is Op.REAL:
+ return obj
+ elif obj.op is Op.INTEGER:
+ return Expr(Op.REAL, (float(obj.data[0]), kind))
+ raise OpError(f'cannot convert {obj} to REAL constant')
+
+
+def as_string(obj, kind=1):
+ """Return object as STRING expression (string literal constant).
+ """
+ return Expr(Op.STRING, (obj, kind))
+
+
+def as_array(obj):
+ """Return object as ARRAY expression (array constant).
+ """
+ if isinstance(obj, Expr):
+ obj = obj,
+ return Expr(Op.ARRAY, obj)
+
+
+def as_complex(real, imag=0):
+ """Return object as COMPLEX expression (complex literal constant).
+ """
+ return Expr(Op.COMPLEX, (as_expr(real), as_expr(imag)))
+
+
+def as_apply(func, *args, **kwargs):
+ """Return object as APPLY expression (function call, constructor, etc.)
+ """
+ return Expr(Op.APPLY,
+ (func, tuple(map(as_expr, args)),
+ dict((k, as_expr(v)) for k, v in kwargs.items())))
+
+
+def as_ternary(cond, expr1, expr2):
+ """Return object as TERNARY expression (cond?expr1:expr2).
+ """
+ return Expr(Op.TERNARY, (cond, expr1, expr2))
+
+
+def as_ref(expr):
+ """Return object as referencing expression.
+ """
+ return Expr(Op.REF, expr)
+
+
+def as_deref(expr):
+ """Return object as dereferencing expression.
+ """
+ return Expr(Op.DEREF, expr)
+
+
+def as_eq(left, right):
+ return Expr(Op.RELATIONAL, (RelOp.EQ, left, right))
+
+
+def as_ne(left, right):
+ return Expr(Op.RELATIONAL, (RelOp.NE, left, right))
+
+
+def as_lt(left, right):
+ return Expr(Op.RELATIONAL, (RelOp.LT, left, right))
+
+
+def as_le(left, right):
+ return Expr(Op.RELATIONAL, (RelOp.LE, left, right))
+
+
+def as_gt(left, right):
+ return Expr(Op.RELATIONAL, (RelOp.GT, left, right))
+
+
+def as_ge(left, right):
+ return Expr(Op.RELATIONAL, (RelOp.GE, left, right))
+
+
+def as_terms(obj):
+ """Return expression as TERMS expression.
+ """
+ if isinstance(obj, Expr):
+ obj = normalize(obj)
+ if obj.op is Op.TERMS:
+ return obj
+ if obj.op is Op.INTEGER:
+ return Expr(Op.TERMS, {as_integer(1, obj.data[1]): obj.data[0]})
+ if obj.op is Op.REAL:
+ return Expr(Op.TERMS, {as_real(1, obj.data[1]): obj.data[0]})
+ return Expr(Op.TERMS, {obj: 1})
+ raise OpError(f'cannot convert {type(obj)} to terms Expr')
+
+
+def as_factors(obj):
+ """Return expression as FACTORS expression.
+ """
+ if isinstance(obj, Expr):
+ obj = normalize(obj)
+ if obj.op is Op.FACTORS:
+ return obj
+ if obj.op is Op.TERMS:
+ if len(obj.data) == 1:
+ (term, coeff), = obj.data.items()
+ if coeff == 1:
+ return Expr(Op.FACTORS, {term: 1})
+ return Expr(Op.FACTORS, {term: 1, Expr.number(coeff): 1})
+ if ((obj.op is Op.APPLY
+ and obj.data[0] is ArithOp.DIV
+ and not obj.data[2])):
+ return Expr(Op.FACTORS, {obj.data[1][0]: 1, obj.data[1][1]: -1})
+ return Expr(Op.FACTORS, {obj: 1})
+ raise OpError(f'cannot convert {type(obj)} to terms Expr')
+
+
+def as_term_coeff(obj):
+ """Return expression as term-coefficient pair.
+ """
+ if isinstance(obj, Expr):
+ obj = normalize(obj)
+ if obj.op is Op.INTEGER:
+ return as_integer(1, obj.data[1]), obj.data[0]
+ if obj.op is Op.REAL:
+ return as_real(1, obj.data[1]), obj.data[0]
+ if obj.op is Op.TERMS:
+ if len(obj.data) == 1:
+ (term, coeff), = obj.data.items()
+ return term, coeff
+ # TODO: find common divisor of coefficients
+ if obj.op is Op.APPLY and obj.data[0] is ArithOp.DIV:
+ t, c = as_term_coeff(obj.data[1][0])
+ return as_apply(ArithOp.DIV, t, obj.data[1][1]), c
+ return obj, 1
+ raise OpError(f'cannot convert {type(obj)} to term and coeff')
+
+
+def as_numer_denom(obj):
+ """Return expression as numer-denom pair.
+ """
+ if isinstance(obj, Expr):
+ obj = normalize(obj)
+ if obj.op in (Op.INTEGER, Op.REAL, Op.COMPLEX, Op.SYMBOL,
+ Op.INDEXING, Op.TERNARY):
+ return obj, as_number(1)
+ elif obj.op is Op.APPLY:
+ if obj.data[0] is ArithOp.DIV and not obj.data[2]:
+ numers, denoms = map(as_numer_denom, obj.data[1])
+ return numers[0] * denoms[1], numers[1] * denoms[0]
+ return obj, as_number(1)
+ elif obj.op is Op.TERMS:
+ numers, denoms = [], []
+ for term, coeff in obj.data.items():
+ n, d = as_numer_denom(term)
+ n = n * coeff
+ numers.append(n)
+ denoms.append(d)
+ numer, denom = as_number(0), as_number(1)
+ for i in range(len(numers)):
+ n = numers[i]
+ for j in range(len(numers)):
+ if i != j:
+ n *= denoms[j]
+ numer += n
+ denom *= denoms[i]
+ if denom.op in (Op.INTEGER, Op.REAL) and denom.data[0] < 0:
+ numer, denom = -numer, -denom
+ return numer, denom
+ elif obj.op is Op.FACTORS:
+ numer, denom = as_number(1), as_number(1)
+ for b, e in obj.data.items():
+ bnumer, bdenom = as_numer_denom(b)
+ if e > 0:
+ numer *= bnumer ** e
+ denom *= bdenom ** e
+ elif e < 0:
+ numer *= bdenom ** (-e)
+ denom *= bnumer ** (-e)
+ return numer, denom
+ raise OpError(f'cannot convert {type(obj)} to numer and denom')
+
+
+def _counter():
+ # Used internally to generate unique dummy symbols
+ counter = 0
+ while True:
+ counter += 1
+ yield counter
+
+
+COUNTER = _counter()
+
+
+def eliminate_quotes(s):
+ """Replace quoted substrings of input string.
+
+ Return a new string and a mapping of replacements.
+ """
+ d = {}
+
+ def repl(m):
+ kind, value = m.groups()[:2]
+ if kind:
+ # remove trailing underscore
+ kind = kind[:-1]
+ p = {"'": "SINGLE", '"': "DOUBLE"}[value[0]]
+ k = f'{kind}@__f2py_QUOTES_{p}_{COUNTER.__next__()}@'
+ d[k] = value
+ return k
+
+ new_s = re.sub(r'({kind}_|)({single_quoted}|{double_quoted})'.format(
+ kind=r'\w[\w\d_]*',
+ single_quoted=r"('([^'\\]|(\\.))*')",
+ double_quoted=r'("([^"\\]|(\\.))*")'),
+ repl, s)
+
+ assert '"' not in new_s
+ assert "'" not in new_s
+
+ return new_s, d
+
+
+def insert_quotes(s, d):
+ """Inverse of eliminate_quotes.
+ """
+ for k, v in d.items():
+ kind = k[:k.find('@')]
+ if kind:
+ kind += '_'
+ s = s.replace(k, kind + v)
+ return s
+
+
+def replace_parenthesis(s):
+ """Replace substrings of input that are enclosed in parenthesis.
+
+ Return a new string and a mapping of replacements.
+ """
+ # Find a parenthesis pair that appears first.
+
+ # Fortran deliminator are `(`, `)`, `[`, `]`, `(/', '/)`, `/`.
+ # We don't handle `/` deliminator because it is not a part of an
+ # expression.
+ left, right = None, None
+ mn_i = len(s)
+ for left_, right_ in (('(/', '/)'),
+ '()',
+ '{}', # to support C literal structs
+ '[]'):
+ i = s.find(left_)
+ if i == -1:
+ continue
+ if i < mn_i:
+ mn_i = i
+ left, right = left_, right_
+
+ if left is None:
+ return s, {}
+
+ i = mn_i
+ j = s.find(right, i)
+
+ while s.count(left, i + 1, j) != s.count(right, i + 1, j):
+ j = s.find(right, j + 1)
+ if j == -1:
+ raise ValueError(f'Mismatch of {left+right} parenthesis in {s!r}')
+
+ p = {'(': 'ROUND', '[': 'SQUARE', '{': 'CURLY', '(/': 'ROUNDDIV'}[left]
+
+ k = f'@__f2py_PARENTHESIS_{p}_{COUNTER.__next__()}@'
+ v = s[i+len(left):j]
+ r, d = replace_parenthesis(s[j+len(right):])
+ d[k] = v
+ return s[:i] + k + r, d
+
+
+def _get_parenthesis_kind(s):
+ assert s.startswith('@__f2py_PARENTHESIS_'), s
+ return s.split('_')[4]
+
+
+def unreplace_parenthesis(s, d):
+ """Inverse of replace_parenthesis.
+ """
+ for k, v in d.items():
+ p = _get_parenthesis_kind(k)
+ left = dict(ROUND='(', SQUARE='[', CURLY='{', ROUNDDIV='(/')[p]
+ right = dict(ROUND=')', SQUARE=']', CURLY='}', ROUNDDIV='/)')[p]
+ s = s.replace(k, left + v + right)
+ return s
+
+
+def fromstring(s, language=Language.C):
+ """Create an expression from a string.
+
+ This is a "lazy" parser, that is, only arithmetic operations are
+ resolved, non-arithmetic operations are treated as symbols.
+ """
+ r = _FromStringWorker(language=language).parse(s)
+ if isinstance(r, Expr):
+ return r
+ raise ValueError(f'failed to parse `{s}` to Expr instance: got `{r}`')
+
+
+class _Pair:
+ # Internal class to represent a pair of expressions
+
+ def __init__(self, left, right):
+ self.left = left
+ self.right = right
+
+ def substitute(self, symbols_map):
+ left, right = self.left, self.right
+ if isinstance(left, Expr):
+ left = left.substitute(symbols_map)
+ if isinstance(right, Expr):
+ right = right.substitute(symbols_map)
+ return _Pair(left, right)
+
+ def __repr__(self):
+ return f'{type(self).__name__}({self.left}, {self.right})'
+
+
+class _FromStringWorker:
+
+ def __init__(self, language=Language.C):
+ self.original = None
+ self.quotes_map = None
+ self.language = language
+
+ def finalize_string(self, s):
+ return insert_quotes(s, self.quotes_map)
+
+ def parse(self, inp):
+ self.original = inp
+ unquoted, self.quotes_map = eliminate_quotes(inp)
+ return self.process(unquoted)
+
+ def process(self, s, context='expr'):
+ """Parse string within the given context.
+
+ The context may define the result in case of ambiguous
+ expressions. For instance, consider expressions `f(x, y)` and
+ `(x, y) + (a, b)` where `f` is a function and pair `(x, y)`
+ denotes complex number. Specifying context as "args" or
+ "expr", the subexpression `(x, y)` will be parse to an
+ argument list or to a complex number, respectively.
+ """
+ if isinstance(s, (list, tuple)):
+ return type(s)(self.process(s_, context) for s_ in s)
+
+ assert isinstance(s, str), (type(s), s)
+
+ # replace subexpressions in parenthesis with f2py @-names
+ r, raw_symbols_map = replace_parenthesis(s)
+ r = r.strip()
+
+ def restore(r):
+ # restores subexpressions marked with f2py @-names
+ if isinstance(r, (list, tuple)):
+ return type(r)(map(restore, r))
+ return unreplace_parenthesis(r, raw_symbols_map)
+
+ # comma-separated tuple
+ if ',' in r:
+ operands = restore(r.split(','))
+ if context == 'args':
+ return tuple(self.process(operands))
+ if context == 'expr':
+ if len(operands) == 2:
+ # complex number literal
+ return as_complex(*self.process(operands))
+ raise NotImplementedError(
+ f'parsing comma-separated list (context={context}): {r}')
+
+ # ternary operation
+ m = re.match(r'\A([^?]+)[?]([^:]+)[:](.+)\Z', r)
+ if m:
+ assert context == 'expr', context
+ oper, expr1, expr2 = restore(m.groups())
+ oper = self.process(oper)
+ expr1 = self.process(expr1)
+ expr2 = self.process(expr2)
+ return as_ternary(oper, expr1, expr2)
+
+ # relational expression
+ if self.language is Language.Fortran:
+ m = re.match(
+ r'\A(.+)\s*[.](eq|ne|lt|le|gt|ge)[.]\s*(.+)\Z', r, re.I)
+ else:
+ m = re.match(
+ r'\A(.+)\s*([=][=]|[!][=]|[<][=]|[<]|[>][=]|[>])\s*(.+)\Z', r)
+ if m:
+ left, rop, right = m.groups()
+ if self.language is Language.Fortran:
+ rop = '.' + rop + '.'
+ left, right = self.process(restore((left, right)))
+ rop = RelOp.fromstring(rop, language=self.language)
+ return Expr(Op.RELATIONAL, (rop, left, right))
+
+ # keyword argument
+ m = re.match(r'\A(\w[\w\d_]*)\s*[=](.*)\Z', r)
+ if m:
+ keyname, value = m.groups()
+ value = restore(value)
+ return _Pair(keyname, self.process(value))
+
+ # addition/subtraction operations
+ operands = re.split(r'((?<!\d[edED])[+-])', r)
+ if len(operands) > 1:
+ result = self.process(restore(operands[0] or '0'))
+ for op, operand in zip(operands[1::2], operands[2::2]):
+ operand = self.process(restore(operand))
+ op = op.strip()
+ if op == '+':
+ result += operand
+ else:
+ assert op == '-'
+ result -= operand
+ return result
+
+ # string concatenate operation
+ if self.language is Language.Fortran and '//' in r:
+ operands = restore(r.split('//'))
+ return Expr(Op.CONCAT,
+ tuple(self.process(operands)))
+
+ # multiplication/division operations
+ operands = re.split(r'(?<=[@\w\d_])\s*([*]|/)',
+ (r if self.language is Language.C
+ else r.replace('**', '@__f2py_DOUBLE_STAR@')))
+ if len(operands) > 1:
+ operands = restore(operands)
+ if self.language is not Language.C:
+ operands = [operand.replace('@__f2py_DOUBLE_STAR@', '**')
+ for operand in operands]
+ # Expression is an arithmetic product
+ result = self.process(operands[0])
+ for op, operand in zip(operands[1::2], operands[2::2]):
+ operand = self.process(operand)
+ op = op.strip()
+ if op == '*':
+ result *= operand
+ else:
+ assert op == '/'
+ result /= operand
+ return result
+
+ # referencing/dereferencing
+ if r.startswith('*') or r.startswith('&'):
+ op = {'*': Op.DEREF, '&': Op.REF}[r[0]]
+ operand = self.process(restore(r[1:]))
+ return Expr(op, operand)
+
+ # exponentiation operations
+ if self.language is not Language.C and '**' in r:
+ operands = list(reversed(restore(r.split('**'))))
+ result = self.process(operands[0])
+ for operand in operands[1:]:
+ operand = self.process(operand)
+ result = operand ** result
+ return result
+
+ # int-literal-constant
+ m = re.match(r'\A({digit_string})({kind}|)\Z'.format(
+ digit_string=r'\d+',
+ kind=r'_(\d+|\w[\w\d_]*)'), r)
+ if m:
+ value, _, kind = m.groups()
+ if kind and kind.isdigit():
+ kind = int(kind)
+ return as_integer(int(value), kind or 4)
+
+ # real-literal-constant
+ m = re.match(r'\A({significant}({exponent}|)|\d+{exponent})({kind}|)\Z'
+ .format(
+ significant=r'[.]\d+|\d+[.]\d*',
+ exponent=r'[edED][+-]?\d+',
+ kind=r'_(\d+|\w[\w\d_]*)'), r)
+ if m:
+ value, _, _, kind = m.groups()
+ if kind and kind.isdigit():
+ kind = int(kind)
+ value = value.lower()
+ if 'd' in value:
+ return as_real(float(value.replace('d', 'e')), kind or 8)
+ return as_real(float(value), kind or 4)
+
+ # string-literal-constant with kind parameter specification
+ if r in self.quotes_map:
+ kind = r[:r.find('@')]
+ return as_string(self.quotes_map[r], kind or 1)
+
+ # array constructor or literal complex constant or
+ # parenthesized expression
+ if r in raw_symbols_map:
+ paren = _get_parenthesis_kind(r)
+ items = self.process(restore(raw_symbols_map[r]),
+ 'expr' if paren == 'ROUND' else 'args')
+ if paren == 'ROUND':
+ if isinstance(items, Expr):
+ return items
+ if paren in ['ROUNDDIV', 'SQUARE']:
+ # Expression is a array constructor
+ if isinstance(items, Expr):
+ items = (items,)
+ return as_array(items)
+
+ # function call/indexing
+ m = re.match(r'\A(.+)\s*(@__f2py_PARENTHESIS_(ROUND|SQUARE)_\d+@)\Z',
+ r)
+ if m:
+ target, args, paren = m.groups()
+ target = self.process(restore(target))
+ args = self.process(restore(args)[1:-1], 'args')
+ if not isinstance(args, tuple):
+ args = args,
+ if paren == 'ROUND':
+ kwargs = dict((a.left, a.right) for a in args
+ if isinstance(a, _Pair))
+ args = tuple(a for a in args if not isinstance(a, _Pair))
+ # Warning: this could also be Fortran indexing operation..
+ return as_apply(target, *args, **kwargs)
+ else:
+ # Expression is a C/Python indexing operation
+ # (e.g. used in .pyf files)
+ assert paren == 'SQUARE'
+ return target[args]
+
+ # Fortran standard conforming identifier
+ m = re.match(r'\A\w[\w\d_]*\Z', r)
+ if m:
+ return as_symbol(r)
+
+ # fall-back to symbol
+ r = self.finalize_string(restore(r))
+ ewarn(
+ f'fromstring: treating {r!r} as symbol (original={self.original})')
+ return as_symbol(r)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/__init__.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/__init__.py
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90
new file mode 100644
index 00000000..76d16aae
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/foo.f90
@@ -0,0 +1,34 @@
+module ops_module
+
+ abstract interface
+ subroutine op(x, y, z)
+ integer, intent(in) :: x, y
+ integer, intent(out) :: z
+ end subroutine
+ end interface
+
+contains
+
+ subroutine foo(x, y, r1, r2)
+ integer, intent(in) :: x, y
+ integer, intent(out) :: r1, r2
+ procedure (op) add1, add2
+ procedure (op), pointer::p
+ p=>add1
+ call p(x, y, r1)
+ p=>add2
+ call p(x, y, r2)
+ end subroutine
+end module
+
+subroutine add1(x, y, z)
+ integer, intent(in) :: x, y
+ integer, intent(out) :: z
+ z = x + y
+end subroutine
+
+subroutine add2(x, y, z)
+ integer, intent(in) :: x, y
+ integer, intent(out) :: z
+ z = x + 2 * y
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90
new file mode 100644
index 00000000..36791e46
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/abstract_interface/gh18403_mod.f90
@@ -0,0 +1,6 @@
+module test
+ abstract interface
+ subroutine foo()
+ end subroutine
+ end interface
+end module test
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
new file mode 100644
index 00000000..9a8b4a75
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
@@ -0,0 +1,230 @@
+/*
+ * This file was auto-generated with f2py (version:2_1330) and hand edited by
+ * Pearu for testing purposes. Do not edit this file unless you know what you
+ * are doing!!!
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************** See f2py2e/cfuncs.py: includes ***********************/
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+#include "fortranobject.h"
+#include <math.h>
+
+static PyObject *wrap_error;
+static PyObject *wrap_module;
+
+/************************************ call ************************************/
+static char doc_f2py_rout_wrap_call[] = "\
+Function signature:\n\
+ arr = call(type_num,dims,intent,obj)\n\
+Required arguments:\n"
+" type_num : input int\n"
+" dims : input int-sequence\n"
+" intent : input int\n"
+" obj : input python object\n"
+"Return objects:\n"
+" arr : array";
+static PyObject *f2py_rout_wrap_call(PyObject *capi_self,
+ PyObject *capi_args) {
+ PyObject * volatile capi_buildvalue = NULL;
+ int type_num = 0;
+ int elsize = 0;
+ npy_intp *dims = NULL;
+ PyObject *dims_capi = Py_None;
+ int rank = 0;
+ int intent = 0;
+ PyArrayObject *capi_arr_tmp = NULL;
+ PyObject *arr_capi = Py_None;
+ int i;
+
+ if (!PyArg_ParseTuple(capi_args,"iiOiO|:wrap.call",\
+ &type_num,&elsize,&dims_capi,&intent,&arr_capi))
+ return NULL;
+ rank = PySequence_Length(dims_capi);
+ dims = malloc(rank*sizeof(npy_intp));
+ for (i=0;i<rank;++i) {
+ PyObject *tmp;
+ tmp = PySequence_GetItem(dims_capi, i);
+ if (tmp == NULL) {
+ goto fail;
+ }
+ dims[i] = (npy_intp)PyLong_AsLong(tmp);
+ Py_DECREF(tmp);
+ if (dims[i] == -1 && PyErr_Occurred()) {
+ goto fail;
+ }
+ }
+ capi_arr_tmp = ndarray_from_pyobj(type_num,elsize,dims,rank,intent|F2PY_INTENT_OUT,arr_capi,"wrap.call failed");
+ if (capi_arr_tmp == NULL) {
+ free(dims);
+ return NULL;
+ }
+ capi_buildvalue = Py_BuildValue("N",capi_arr_tmp);
+ free(dims);
+ return capi_buildvalue;
+
+fail:
+ free(dims);
+ return NULL;
+}
+
+static char doc_f2py_rout_wrap_attrs[] = "\
+Function signature:\n\
+ arr = array_attrs(arr)\n\
+Required arguments:\n"
+" arr : input array object\n"
+"Return objects:\n"
+" data : data address in hex\n"
+" nd : int\n"
+" dimensions : tuple\n"
+" strides : tuple\n"
+" base : python object\n"
+" (kind,type,type_num,elsize,alignment) : 4-tuple\n"
+" flags : int\n"
+" itemsize : int\n"
+;
+static PyObject *f2py_rout_wrap_attrs(PyObject *capi_self,
+ PyObject *capi_args) {
+ PyObject *arr_capi = Py_None;
+ PyArrayObject *arr = NULL;
+ PyObject *dimensions = NULL;
+ PyObject *strides = NULL;
+ char s[100];
+ int i;
+ memset(s,0,100);
+ if (!PyArg_ParseTuple(capi_args,"O!|:wrap.attrs",
+ &PyArray_Type,&arr_capi))
+ return NULL;
+ arr = (PyArrayObject *)arr_capi;
+ sprintf(s,"%p",PyArray_DATA(arr));
+ dimensions = PyTuple_New(PyArray_NDIM(arr));
+ strides = PyTuple_New(PyArray_NDIM(arr));
+ for (i=0;i<PyArray_NDIM(arr);++i) {
+ PyTuple_SetItem(dimensions,i,PyLong_FromLong(PyArray_DIM(arr,i)));
+ PyTuple_SetItem(strides,i,PyLong_FromLong(PyArray_STRIDE(arr,i)));
+ }
+ return Py_BuildValue("siNNO(cciii)ii",s,PyArray_NDIM(arr),
+ dimensions,strides,
+ (PyArray_BASE(arr)==NULL?Py_None:PyArray_BASE(arr)),
+ PyArray_DESCR(arr)->kind,
+ PyArray_DESCR(arr)->type,
+ PyArray_TYPE(arr),
+ PyArray_ITEMSIZE(arr),
+ PyArray_DESCR(arr)->alignment,
+ PyArray_FLAGS(arr),
+ PyArray_ITEMSIZE(arr));
+}
+
+static PyMethodDef f2py_module_methods[] = {
+
+ {"call",f2py_rout_wrap_call,METH_VARARGS,doc_f2py_rout_wrap_call},
+ {"array_attrs",f2py_rout_wrap_attrs,METH_VARARGS,doc_f2py_rout_wrap_attrs},
+ {NULL,NULL}
+};
+
+static struct PyModuleDef moduledef = {
+ PyModuleDef_HEAD_INIT,
+ "test_array_from_pyobj_ext",
+ NULL,
+ -1,
+ f2py_module_methods,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
+ PyObject *m,*d, *s;
+ m = wrap_module = PyModule_Create(&moduledef);
+ Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
+ import_array();
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module wrap (failed to import numpy)");
+ d = PyModule_GetDict(m);
+ s = PyUnicode_FromString("This module 'wrap' is auto-generated with f2py (version:2_1330).\nFunctions:\n"
+ " arr = call(type_num,dims,intent,obj)\n"
+ ".");
+ PyDict_SetItemString(d, "__doc__", s);
+ wrap_error = PyErr_NewException ("wrap.error", NULL, NULL);
+ Py_DECREF(s);
+
+#define ADDCONST(NAME, CONST) \
+ s = PyLong_FromLong(CONST); \
+ PyDict_SetItemString(d, NAME, s); \
+ Py_DECREF(s)
+
+ ADDCONST("F2PY_INTENT_IN", F2PY_INTENT_IN);
+ ADDCONST("F2PY_INTENT_INOUT", F2PY_INTENT_INOUT);
+ ADDCONST("F2PY_INTENT_OUT", F2PY_INTENT_OUT);
+ ADDCONST("F2PY_INTENT_HIDE", F2PY_INTENT_HIDE);
+ ADDCONST("F2PY_INTENT_CACHE", F2PY_INTENT_CACHE);
+ ADDCONST("F2PY_INTENT_COPY", F2PY_INTENT_COPY);
+ ADDCONST("F2PY_INTENT_C", F2PY_INTENT_C);
+ ADDCONST("F2PY_OPTIONAL", F2PY_OPTIONAL);
+ ADDCONST("F2PY_INTENT_INPLACE", F2PY_INTENT_INPLACE);
+ ADDCONST("NPY_BOOL", NPY_BOOL);
+ ADDCONST("NPY_BYTE", NPY_BYTE);
+ ADDCONST("NPY_UBYTE", NPY_UBYTE);
+ ADDCONST("NPY_SHORT", NPY_SHORT);
+ ADDCONST("NPY_USHORT", NPY_USHORT);
+ ADDCONST("NPY_INT", NPY_INT);
+ ADDCONST("NPY_UINT", NPY_UINT);
+ ADDCONST("NPY_INTP", NPY_INTP);
+ ADDCONST("NPY_UINTP", NPY_UINTP);
+ ADDCONST("NPY_LONG", NPY_LONG);
+ ADDCONST("NPY_ULONG", NPY_ULONG);
+ ADDCONST("NPY_LONGLONG", NPY_LONGLONG);
+ ADDCONST("NPY_ULONGLONG", NPY_ULONGLONG);
+ ADDCONST("NPY_FLOAT", NPY_FLOAT);
+ ADDCONST("NPY_DOUBLE", NPY_DOUBLE);
+ ADDCONST("NPY_LONGDOUBLE", NPY_LONGDOUBLE);
+ ADDCONST("NPY_CFLOAT", NPY_CFLOAT);
+ ADDCONST("NPY_CDOUBLE", NPY_CDOUBLE);
+ ADDCONST("NPY_CLONGDOUBLE", NPY_CLONGDOUBLE);
+ ADDCONST("NPY_OBJECT", NPY_OBJECT);
+ ADDCONST("NPY_STRING", NPY_STRING);
+ ADDCONST("NPY_UNICODE", NPY_UNICODE);
+ ADDCONST("NPY_VOID", NPY_VOID);
+ ADDCONST("NPY_NTYPES", NPY_NTYPES);
+ ADDCONST("NPY_NOTYPE", NPY_NOTYPE);
+ ADDCONST("NPY_USERDEF", NPY_USERDEF);
+
+ ADDCONST("CONTIGUOUS", NPY_ARRAY_C_CONTIGUOUS);
+ ADDCONST("FORTRAN", NPY_ARRAY_F_CONTIGUOUS);
+ ADDCONST("OWNDATA", NPY_ARRAY_OWNDATA);
+ ADDCONST("FORCECAST", NPY_ARRAY_FORCECAST);
+ ADDCONST("ENSURECOPY", NPY_ARRAY_ENSURECOPY);
+ ADDCONST("ENSUREARRAY", NPY_ARRAY_ENSUREARRAY);
+ ADDCONST("ALIGNED", NPY_ARRAY_ALIGNED);
+ ADDCONST("WRITEABLE", NPY_ARRAY_WRITEABLE);
+ ADDCONST("WRITEBACKIFCOPY", NPY_ARRAY_WRITEBACKIFCOPY);
+
+ ADDCONST("BEHAVED", NPY_ARRAY_BEHAVED);
+ ADDCONST("BEHAVED_NS", NPY_ARRAY_BEHAVED_NS);
+ ADDCONST("CARRAY", NPY_ARRAY_CARRAY);
+ ADDCONST("FARRAY", NPY_ARRAY_FARRAY);
+ ADDCONST("CARRAY_RO", NPY_ARRAY_CARRAY_RO);
+ ADDCONST("FARRAY_RO", NPY_ARRAY_FARRAY_RO);
+ ADDCONST("DEFAULT", NPY_ARRAY_DEFAULT);
+ ADDCONST("UPDATE_ALL", NPY_ARRAY_UPDATE_ALL);
+
+#undef ADDCONST(
+
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module wrap");
+
+#ifdef F2PY_REPORT_ATEXIT
+ on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call");
+#endif
+
+ return m;
+}
+#ifdef __cplusplus
+}
+#endif
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap
new file mode 100644
index 00000000..2665f89b
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/.f2py_f2cmap
@@ -0,0 +1 @@
+dict(real=dict(rk="double"))
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90
new file mode 100644
index 00000000..b301710f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_free.f90
@@ -0,0 +1,34 @@
+
+subroutine sum(x, res)
+ implicit none
+ real, intent(in) :: x(:)
+ real, intent(out) :: res
+
+ integer :: i
+
+ !print *, "sum: size(x) = ", size(x)
+
+ res = 0.0
+
+ do i = 1, size(x)
+ res = res + x(i)
+ enddo
+
+end subroutine sum
+
+function fsum(x) result (res)
+ implicit none
+ real, intent(in) :: x(:)
+ real :: res
+
+ integer :: i
+
+ !print *, "fsum: size(x) = ", size(x)
+
+ res = 0.0
+
+ do i = 1, size(x)
+ res = res + x(i)
+ enddo
+
+end function fsum
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90
new file mode 100644
index 00000000..cbe6317e
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_mod.f90
@@ -0,0 +1,41 @@
+
+module mod
+
+contains
+
+subroutine sum(x, res)
+ implicit none
+ real, intent(in) :: x(:)
+ real, intent(out) :: res
+
+ integer :: i
+
+ !print *, "sum: size(x) = ", size(x)
+
+ res = 0.0
+
+ do i = 1, size(x)
+ res = res + x(i)
+ enddo
+
+end subroutine sum
+
+function fsum(x) result (res)
+ implicit none
+ real, intent(in) :: x(:)
+ real :: res
+
+ integer :: i
+
+ !print *, "fsum: size(x) = ", size(x)
+
+ res = 0.0
+
+ do i = 1, size(x)
+ res = res + x(i)
+ enddo
+
+end function fsum
+
+
+end module mod
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90
new file mode 100644
index 00000000..337465ac
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/foo_use.f90
@@ -0,0 +1,19 @@
+subroutine sum_with_use(x, res)
+ use precision
+
+ implicit none
+
+ real(kind=rk), intent(in) :: x(:)
+ real(kind=rk), intent(out) :: res
+
+ integer :: i
+
+ !print *, "size(x) = ", size(x)
+
+ res = 0.0
+
+ do i = 1, size(x)
+ res = res + x(i)
+ enddo
+
+ end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90
new file mode 100644
index 00000000..ed6c70cb
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/assumed_shape/precision.f90
@@ -0,0 +1,4 @@
+module precision
+ integer, parameter :: rk = selected_real_kind(8)
+ integer, parameter :: ik = selected_real_kind(4)
+end module
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/block_docstring/foo.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/block_docstring/foo.f
new file mode 100644
index 00000000..c8315f12
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/block_docstring/foo.f
@@ -0,0 +1,6 @@
+ SUBROUTINE FOO()
+ INTEGER BAR(2, 3)
+
+ COMMON /BLOCK/ BAR
+ RETURN
+ END
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/foo.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/foo.f
new file mode 100644
index 00000000..ba397bb3
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/foo.f
@@ -0,0 +1,62 @@
+ subroutine t(fun,a)
+ integer a
+cf2py intent(out) a
+ external fun
+ call fun(a)
+ end
+
+ subroutine func(a)
+cf2py intent(in,out) a
+ integer a
+ a = a + 11
+ end
+
+ subroutine func0(a)
+cf2py intent(out) a
+ integer a
+ a = 11
+ end
+
+ subroutine t2(a)
+cf2py intent(callback) fun
+ integer a
+cf2py intent(out) a
+ external fun
+ call fun(a)
+ end
+
+ subroutine string_callback(callback, a)
+ external callback
+ double precision callback
+ double precision a
+ character*1 r
+cf2py intent(out) a
+ r = 'r'
+ a = callback(r)
+ end
+
+ subroutine string_callback_array(callback, cu, lencu, a)
+ external callback
+ integer callback
+ integer lencu
+ character*8 cu(lencu)
+ integer a
+cf2py intent(out) a
+
+ a = callback(cu, lencu)
+ end
+
+ subroutine hidden_callback(a, r)
+ external global_f
+cf2py intent(callback, hide) global_f
+ integer a, r, global_f
+cf2py intent(out) r
+ r = global_f(a)
+ end
+
+ subroutine hidden_callback2(a, r)
+ external global_f
+ integer a, r, global_f
+cf2py intent(out) r
+ r = global_f(a)
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh17797.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh17797.f90
new file mode 100644
index 00000000..49853afd
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh17797.f90
@@ -0,0 +1,7 @@
+function gh17797(f, y) result(r)
+ external f
+ integer(8) :: r, f
+ integer(8), dimension(:) :: y
+ r = f(0)
+ r = r + sum(y)
+end function gh17797
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh18335.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh18335.f90
new file mode 100644
index 00000000..92b6d754
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/callback/gh18335.f90
@@ -0,0 +1,17 @@
+ ! When gh18335_workaround is defined as an extension,
+ ! the issue cannot be reproduced.
+ !subroutine gh18335_workaround(f, y)
+ ! implicit none
+ ! external f
+ ! integer(kind=1) :: y(1)
+ ! call f(y)
+ !end subroutine gh18335_workaround
+
+ function gh18335(f) result (r)
+ implicit none
+ external f
+ integer(kind=1) :: y(1), r
+ y(1) = 123
+ call f(y)
+ r = y(1)
+ end function gh18335
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hi77.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hi77.f
new file mode 100644
index 00000000..8b916ebe
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hi77.f
@@ -0,0 +1,3 @@
+ SUBROUTINE HI
+ PRINT*, "HELLO WORLD"
+ END SUBROUTINE
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hiworld.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hiworld.f90
new file mode 100644
index 00000000..981f8775
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/cli/hiworld.f90
@@ -0,0 +1,3 @@
+function hi()
+ print*, "Hello World"
+end function
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/common/block.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/common/block.f
new file mode 100644
index 00000000..7ea7968f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/common/block.f
@@ -0,0 +1,11 @@
+ SUBROUTINE INITCB
+ DOUBLE PRECISION LONG
+ CHARACTER STRING
+ INTEGER OK
+
+ COMMON /BLOCK/ LONG, STRING, OK
+ LONG = 1.0
+ STRING = '2'
+ OK = 3
+ RETURN
+ END
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90
new file mode 100644
index 00000000..e2cbd445
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/accesstype.f90
@@ -0,0 +1,13 @@
+module foo
+ public
+ type, private, bind(c) :: a
+ integer :: i
+ end type a
+ type, bind(c) :: b_
+ integer :: j
+ end type b_
+ public :: b_
+ type :: c
+ integer :: k
+ end type c
+end module foo
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90
new file mode 100644
index 00000000..e327b25c
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/foo_deps.f90
@@ -0,0 +1,6 @@
+module foo
+ type bar
+ character(len = 4) :: text
+ end type bar
+ type(bar), parameter :: abar = bar('abar')
+end module foo
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f
new file mode 100644
index 00000000..1bb2e674
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh15035.f
@@ -0,0 +1,16 @@
+ subroutine subb(k)
+ real(8), intent(inout) :: k(:)
+ k=k+1
+ endsubroutine
+
+ subroutine subc(w,k)
+ real(8), intent(in) :: w(:)
+ real(8), intent(out) :: k(size(w))
+ k=w+1
+ endsubroutine
+
+ function t0(value)
+ character value
+ character t0
+ t0 = value
+ endfunction
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f
new file mode 100644
index 00000000..99595384
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh17859.f
@@ -0,0 +1,12 @@
+ integer(8) function external_as_statement(fcn)
+ implicit none
+ external fcn
+ integer(8) :: fcn
+ external_as_statement = fcn(0)
+ end
+
+ integer(8) function external_as_attribute(fcn)
+ implicit none
+ integer(8), external :: fcn
+ external_as_attribute = fcn(0)
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90
new file mode 100644
index 00000000..31ea9327
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/gh2848.f90
@@ -0,0 +1,13 @@
+ subroutine gh2848( &
+ ! first 2 parameters
+ par1, par2,&
+ ! last 2 parameters
+ par3, par4)
+
+ integer, intent(in) :: par1, par2
+ integer, intent(out) :: par3, par4
+
+ par3 = par1
+ par4 = par2
+
+ end subroutine gh2848
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90
new file mode 100644
index 00000000..1d060a3d
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/operators.f90
@@ -0,0 +1,49 @@
+module foo
+ type bar
+ character(len = 32) :: item
+ end type bar
+ interface operator(.item.)
+ module procedure item_int, item_real
+ end interface operator(.item.)
+ interface operator(==)
+ module procedure items_are_equal
+ end interface operator(==)
+ interface assignment(=)
+ module procedure get_int, get_real
+ end interface assignment(=)
+contains
+ function item_int(val) result(elem)
+ integer, intent(in) :: val
+ type(bar) :: elem
+
+ write(elem%item, "(I32)") val
+ end function item_int
+
+ function item_real(val) result(elem)
+ real, intent(in) :: val
+ type(bar) :: elem
+
+ write(elem%item, "(1PE32.12)") val
+ end function item_real
+
+ function items_are_equal(val1, val2) result(equal)
+ type(bar), intent(in) :: val1, val2
+ logical :: equal
+
+ equal = (val1%item == val2%item)
+ end function items_are_equal
+
+ subroutine get_real(rval, item)
+ real, intent(out) :: rval
+ type(bar), intent(in) :: item
+
+ read(item%item, *) rval
+ end subroutine get_real
+
+ subroutine get_int(rval, item)
+ integer, intent(out) :: rval
+ type(bar), intent(in) :: item
+
+ read(item%item, *) rval
+ end subroutine get_int
+end module foo
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90
new file mode 100644
index 00000000..2674c214
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/privatemod.f90
@@ -0,0 +1,11 @@
+module foo
+ private
+ integer :: a
+ public :: setA
+ integer :: b
+contains
+ subroutine setA(v)
+ integer, intent(in) :: v
+ a = v
+ end subroutine setA
+end module foo
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90
new file mode 100644
index 00000000..1db76e3f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/publicmod.f90
@@ -0,0 +1,10 @@
+module foo
+ public
+ integer, private :: a
+ public :: setA
+contains
+ subroutine setA(v)
+ integer, intent(in) :: v
+ a = v
+ end subroutine setA
+end module foo
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90
new file mode 100644
index 00000000..46bef7cb
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/pubprivmod.f90
@@ -0,0 +1,10 @@
+module foo
+ public
+ integer, private :: a
+ integer :: b
+contains
+ subroutine setA(v)
+ integer, intent(in) :: v
+ a = v
+ end subroutine setA
+end module foo
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90
new file mode 100644
index 00000000..13515ce9
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/crackfortran/unicode_comment.f90
@@ -0,0 +1,4 @@
+subroutine foo(x)
+ real(8), intent(in) :: x
+ ! Écrit à l'écran la valeur de x
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap
new file mode 100644
index 00000000..a4425f88
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/.f2py_f2cmap
@@ -0,0 +1 @@
+dict(real=dict(real32='float', real64='double'), integer=dict(int64='long_long'))
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90
new file mode 100644
index 00000000..3f0e12c7
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/f2cmap/isoFortranEnvMap.f90
@@ -0,0 +1,9 @@
+ subroutine func1(n, x, res)
+ use, intrinsic :: iso_fortran_env, only: int64, real64
+ implicit none
+ integer(int64), intent(in) :: n
+ real(real64), intent(in) :: x(n)
+ real(real64), intent(out) :: res
+Cf2py intent(hide) :: n
+ res = sum(x)
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/kind/foo.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/kind/foo.f90
new file mode 100644
index 00000000..d3d15cfb
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/kind/foo.f90
@@ -0,0 +1,20 @@
+
+
+subroutine selectedrealkind(p, r, res)
+ implicit none
+
+ integer, intent(in) :: p, r
+ !f2py integer :: r=0
+ integer, intent(out) :: res
+ res = selected_real_kind(p, r)
+
+end subroutine
+
+subroutine selectedintkind(p, res)
+ implicit none
+
+ integer, intent(in) :: p
+ integer, intent(out) :: res
+ res = selected_int_kind(p)
+
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo.f
new file mode 100644
index 00000000..c3474257
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo.f
@@ -0,0 +1,5 @@
+ subroutine bar11(a)
+cf2py intent(out) a
+ integer a
+ a = 11
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90
new file mode 100644
index 00000000..7543a6ac
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_fixed.f90
@@ -0,0 +1,8 @@
+ module foo_fixed
+ contains
+ subroutine bar12(a)
+!f2py intent(out) a
+ integer a
+ a = 12
+ end subroutine bar12
+ end module foo_fixed
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90
new file mode 100644
index 00000000..c1b641f1
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/mixed/foo_free.f90
@@ -0,0 +1,8 @@
+module foo_free
+contains
+ subroutine bar13(a)
+ !f2py intent(out) a
+ integer a
+ a = 13
+ end subroutine bar13
+end module foo_free
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/mod.mod b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/mod.mod
new file mode 100644
index 00000000..8670a97e
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/mod.mod
Binary files differ
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f90
new file mode 100644
index 00000000..4505e0cb
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/module_data/module_data_docstring.f90
@@ -0,0 +1,12 @@
+module mod
+ integer :: i
+ integer :: x(4)
+ real, dimension(2,3) :: a
+ real, allocatable, dimension(:,:) :: b
+contains
+ subroutine foo
+ integer :: k
+ k = 1
+ a(1,2) = a(1,2)+3
+ end subroutine foo
+end module mod
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90
new file mode 100644
index 00000000..bf1fa928
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/negative_bounds/issue_20853.f90
@@ -0,0 +1,7 @@
+subroutine foo(is_, ie_, arr, tout)
+ implicit none
+ integer :: is_,ie_
+ real, intent(in) :: arr(is_:ie_)
+ real, intent(out) :: tout(is_:ie_)
+ tout = arr
+end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90
new file mode 100644
index 00000000..ac90cedc
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_both.f90
@@ -0,0 +1,57 @@
+! Check that parameters are correct intercepted.
+! Constants with comma separations are commonly
+! used, for instance Pi = 3._dp
+subroutine foo(x)
+ implicit none
+ integer, parameter :: sp = selected_real_kind(6)
+ integer, parameter :: dp = selected_real_kind(15)
+ integer, parameter :: ii = selected_int_kind(9)
+ integer, parameter :: il = selected_int_kind(18)
+ real(dp), intent(inout) :: x
+ dimension x(3)
+ real(sp), parameter :: three_s = 3._sp
+ real(dp), parameter :: three_d = 3._dp
+ integer(ii), parameter :: three_i = 3_ii
+ integer(il), parameter :: three_l = 3_il
+ x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
+ x(2) = x(2) * three_s
+ x(3) = x(3) * three_l
+ return
+end subroutine
+
+
+subroutine foo_no(x)
+ implicit none
+ integer, parameter :: sp = selected_real_kind(6)
+ integer, parameter :: dp = selected_real_kind(15)
+ integer, parameter :: ii = selected_int_kind(9)
+ integer, parameter :: il = selected_int_kind(18)
+ real(dp), intent(inout) :: x
+ dimension x(3)
+ real(sp), parameter :: three_s = 3.
+ real(dp), parameter :: three_d = 3.
+ integer(ii), parameter :: three_i = 3
+ integer(il), parameter :: three_l = 3
+ x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
+ x(2) = x(2) * three_s
+ x(3) = x(3) * three_l
+ return
+end subroutine
+
+subroutine foo_sum(x)
+ implicit none
+ integer, parameter :: sp = selected_real_kind(6)
+ integer, parameter :: dp = selected_real_kind(15)
+ integer, parameter :: ii = selected_int_kind(9)
+ integer, parameter :: il = selected_int_kind(18)
+ real(dp), intent(inout) :: x
+ dimension x(3)
+ real(sp), parameter :: three_s = 2._sp + 1._sp
+ real(dp), parameter :: three_d = 1._dp + 2._dp
+ integer(ii), parameter :: three_i = 2_ii + 1_ii
+ integer(il), parameter :: three_l = 1_il + 2_il
+ x(1) = x(1) + x(2) * three_s * three_i + x(3) * three_d * three_l
+ x(2) = x(2) * three_s
+ x(3) = x(3) * three_l
+ return
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90
new file mode 100644
index 00000000..e51f5e9b
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_compound.f90
@@ -0,0 +1,15 @@
+! Check that parameters are correct intercepted.
+! Constants with comma separations are commonly
+! used, for instance Pi = 3._dp
+subroutine foo_compound_int(x)
+ implicit none
+ integer, parameter :: ii = selected_int_kind(9)
+ integer(ii), intent(inout) :: x
+ dimension x(3)
+ integer(ii), parameter :: three = 3_ii
+ integer(ii), parameter :: two = 2_ii
+ integer(ii), parameter :: six = three * 1_ii * two
+
+ x(1) = x(1) + x(2) + x(3) * six
+ return
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90
new file mode 100644
index 00000000..aaa83d2e
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_integer.f90
@@ -0,0 +1,22 @@
+! Check that parameters are correct intercepted.
+! Constants with comma separations are commonly
+! used, for instance Pi = 3._dp
+subroutine foo_int(x)
+ implicit none
+ integer, parameter :: ii = selected_int_kind(9)
+ integer(ii), intent(inout) :: x
+ dimension x(3)
+ integer(ii), parameter :: three = 3_ii
+ x(1) = x(1) + x(2) + x(3) * three
+ return
+end subroutine
+
+subroutine foo_long(x)
+ implicit none
+ integer, parameter :: ii = selected_int_kind(18)
+ integer(ii), intent(inout) :: x
+ dimension x(3)
+ integer(ii), parameter :: three = 3_ii
+ x(1) = x(1) + x(2) + x(3) * three
+ return
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90
new file mode 100644
index 00000000..62c9a5b9
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_non_compound.f90
@@ -0,0 +1,23 @@
+! Check that parameters are correct intercepted.
+! Specifically that types of constants without
+! compound kind specs are correctly inferred
+! adapted Gibbs iteration code from pymc
+! for this test case
+subroutine foo_non_compound_int(x)
+ implicit none
+ integer, parameter :: ii = selected_int_kind(9)
+
+ integer(ii) maxiterates
+ parameter (maxiterates=2)
+
+ integer(ii) maxseries
+ parameter (maxseries=2)
+
+ integer(ii) wasize
+ parameter (wasize=maxiterates*maxseries)
+ integer(ii), intent(inout) :: x
+ dimension x(wasize)
+
+ x(1) = x(1) + x(2) + x(3) + x(4) * wasize
+ return
+end subroutine
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90
new file mode 100644
index 00000000..02ac9dd9
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/parameter/constant_real.f90
@@ -0,0 +1,23 @@
+! Check that parameters are correct intercepted.
+! Constants with comma separations are commonly
+! used, for instance Pi = 3._dp
+subroutine foo_single(x)
+ implicit none
+ integer, parameter :: rp = selected_real_kind(6)
+ real(rp), intent(inout) :: x
+ dimension x(3)
+ real(rp), parameter :: three = 3._rp
+ x(1) = x(1) + x(2) + x(3) * three
+ return
+end subroutine
+
+subroutine foo_double(x)
+ implicit none
+ integer, parameter :: rp = selected_real_kind(15)
+ real(rp), intent(inout) :: x
+ dimension x(3)
+ real(rp), parameter :: three = 3._rp
+ x(1) = x(1) + x(2) + x(3) * three
+ return
+end subroutine
+
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/quoted_character/foo.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/quoted_character/foo.f
new file mode 100644
index 00000000..9dc1cfa4
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/quoted_character/foo.f
@@ -0,0 +1,14 @@
+ SUBROUTINE FOO(OUT1, OUT2, OUT3, OUT4, OUT5, OUT6)
+ CHARACTER SINGLE, DOUBLE, SEMICOL, EXCLA, OPENPAR, CLOSEPAR
+ PARAMETER (SINGLE="'", DOUBLE='"', SEMICOL=';', EXCLA="!",
+ 1 OPENPAR="(", CLOSEPAR=")")
+ CHARACTER OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
+Cf2py intent(out) OUT1, OUT2, OUT3, OUT4, OUT5, OUT6
+ OUT1 = SINGLE
+ OUT2 = DOUBLE
+ OUT3 = SEMICOL
+ OUT4 = EXCLA
+ OUT5 = OPENPAR
+ OUT6 = CLOSEPAR
+ RETURN
+ END
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/regression/inout.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/regression/inout.f90
new file mode 100644
index 00000000..80cdad90
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/regression/inout.f90
@@ -0,0 +1,9 @@
+! Check that intent(in out) translates as intent(inout).
+! The separation seems to be a common usage.
+ subroutine foo(x)
+ implicit none
+ real(4), intent(in out) :: x
+ dimension x(3)
+ x(1) = x(1) + x(2) + x(3)
+ return
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo77.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo77.f
new file mode 100644
index 00000000..facae101
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo77.f
@@ -0,0 +1,45 @@
+ function t0(value)
+ character value
+ character t0
+ t0 = value
+ end
+ function t1(value)
+ character*1 value
+ character*1 t1
+ t1 = value
+ end
+ function t5(value)
+ character*5 value
+ character*5 t5
+ t5 = value
+ end
+ function ts(value)
+ character*(*) value
+ character*(*) ts
+ ts = value
+ end
+
+ subroutine s0(t0,value)
+ character value
+ character t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s1(t1,value)
+ character*1 value
+ character*1 t1
+cf2py intent(out) t1
+ t1 = value
+ end
+ subroutine s5(t5,value)
+ character*5 value
+ character*5 t5
+cf2py intent(out) t5
+ t5 = value
+ end
+ subroutine ss(ts,value)
+ character*(*) value
+ character*10 ts
+cf2py intent(out) ts
+ ts = value
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo90.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo90.f90
new file mode 100644
index 00000000..36182bcf
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_character/foo90.f90
@@ -0,0 +1,48 @@
+module f90_return_char
+ contains
+ function t0(value)
+ character :: value
+ character :: t0
+ t0 = value
+ end function t0
+ function t1(value)
+ character(len=1) :: value
+ character(len=1) :: t1
+ t1 = value
+ end function t1
+ function t5(value)
+ character(len=5) :: value
+ character(len=5) :: t5
+ t5 = value
+ end function t5
+ function ts(value)
+ character(len=*) :: value
+ character(len=10) :: ts
+ ts = value
+ end function ts
+
+ subroutine s0(t0,value)
+ character :: value
+ character :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s1(t1,value)
+ character(len=1) :: value
+ character(len=1) :: t1
+!f2py intent(out) t1
+ t1 = value
+ end subroutine s1
+ subroutine s5(t5,value)
+ character(len=5) :: value
+ character(len=5) :: t5
+!f2py intent(out) t5
+ t5 = value
+ end subroutine s5
+ subroutine ss(ts,value)
+ character(len=*) :: value
+ character(len=10) :: ts
+!f2py intent(out) ts
+ ts = value
+ end subroutine ss
+end module f90_return_char
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo77.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo77.f
new file mode 100644
index 00000000..37a1ec84
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo77.f
@@ -0,0 +1,45 @@
+ function t0(value)
+ complex value
+ complex t0
+ t0 = value
+ end
+ function t8(value)
+ complex*8 value
+ complex*8 t8
+ t8 = value
+ end
+ function t16(value)
+ complex*16 value
+ complex*16 t16
+ t16 = value
+ end
+ function td(value)
+ double complex value
+ double complex td
+ td = value
+ end
+
+ subroutine s0(t0,value)
+ complex value
+ complex t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s8(t8,value)
+ complex*8 value
+ complex*8 t8
+cf2py intent(out) t8
+ t8 = value
+ end
+ subroutine s16(t16,value)
+ complex*16 value
+ complex*16 t16
+cf2py intent(out) t16
+ t16 = value
+ end
+ subroutine sd(td,value)
+ double complex value
+ double complex td
+cf2py intent(out) td
+ td = value
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90
new file mode 100644
index 00000000..adc27b47
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_complex/foo90.f90
@@ -0,0 +1,48 @@
+module f90_return_complex
+ contains
+ function t0(value)
+ complex :: value
+ complex :: t0
+ t0 = value
+ end function t0
+ function t8(value)
+ complex(kind=4) :: value
+ complex(kind=4) :: t8
+ t8 = value
+ end function t8
+ function t16(value)
+ complex(kind=8) :: value
+ complex(kind=8) :: t16
+ t16 = value
+ end function t16
+ function td(value)
+ double complex :: value
+ double complex :: td
+ td = value
+ end function td
+
+ subroutine s0(t0,value)
+ complex :: value
+ complex :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s8(t8,value)
+ complex(kind=4) :: value
+ complex(kind=4) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+ subroutine s16(t16,value)
+ complex(kind=8) :: value
+ complex(kind=8) :: t16
+!f2py intent(out) t16
+ t16 = value
+ end subroutine s16
+ subroutine sd(td,value)
+ double complex :: value
+ double complex :: td
+!f2py intent(out) td
+ td = value
+ end subroutine sd
+end module f90_return_complex
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo77.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo77.f
new file mode 100644
index 00000000..1ab895b9
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo77.f
@@ -0,0 +1,56 @@
+ function t0(value)
+ integer value
+ integer t0
+ t0 = value
+ end
+ function t1(value)
+ integer*1 value
+ integer*1 t1
+ t1 = value
+ end
+ function t2(value)
+ integer*2 value
+ integer*2 t2
+ t2 = value
+ end
+ function t4(value)
+ integer*4 value
+ integer*4 t4
+ t4 = value
+ end
+ function t8(value)
+ integer*8 value
+ integer*8 t8
+ t8 = value
+ end
+
+ subroutine s0(t0,value)
+ integer value
+ integer t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s1(t1,value)
+ integer*1 value
+ integer*1 t1
+cf2py intent(out) t1
+ t1 = value
+ end
+ subroutine s2(t2,value)
+ integer*2 value
+ integer*2 t2
+cf2py intent(out) t2
+ t2 = value
+ end
+ subroutine s4(t4,value)
+ integer*4 value
+ integer*4 t4
+cf2py intent(out) t4
+ t4 = value
+ end
+ subroutine s8(t8,value)
+ integer*8 value
+ integer*8 t8
+cf2py intent(out) t8
+ t8 = value
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90
new file mode 100644
index 00000000..ba9249aa
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_integer/foo90.f90
@@ -0,0 +1,59 @@
+module f90_return_integer
+ contains
+ function t0(value)
+ integer :: value
+ integer :: t0
+ t0 = value
+ end function t0
+ function t1(value)
+ integer(kind=1) :: value
+ integer(kind=1) :: t1
+ t1 = value
+ end function t1
+ function t2(value)
+ integer(kind=2) :: value
+ integer(kind=2) :: t2
+ t2 = value
+ end function t2
+ function t4(value)
+ integer(kind=4) :: value
+ integer(kind=4) :: t4
+ t4 = value
+ end function t4
+ function t8(value)
+ integer(kind=8) :: value
+ integer(kind=8) :: t8
+ t8 = value
+ end function t8
+
+ subroutine s0(t0,value)
+ integer :: value
+ integer :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s1(t1,value)
+ integer(kind=1) :: value
+ integer(kind=1) :: t1
+!f2py intent(out) t1
+ t1 = value
+ end subroutine s1
+ subroutine s2(t2,value)
+ integer(kind=2) :: value
+ integer(kind=2) :: t2
+!f2py intent(out) t2
+ t2 = value
+ end subroutine s2
+ subroutine s4(t4,value)
+ integer(kind=4) :: value
+ integer(kind=4) :: t4
+!f2py intent(out) t4
+ t4 = value
+ end subroutine s4
+ subroutine s8(t8,value)
+ integer(kind=8) :: value
+ integer(kind=8) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+end module f90_return_integer
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo77.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo77.f
new file mode 100644
index 00000000..ef530145
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo77.f
@@ -0,0 +1,56 @@
+ function t0(value)
+ logical value
+ logical t0
+ t0 = value
+ end
+ function t1(value)
+ logical*1 value
+ logical*1 t1
+ t1 = value
+ end
+ function t2(value)
+ logical*2 value
+ logical*2 t2
+ t2 = value
+ end
+ function t4(value)
+ logical*4 value
+ logical*4 t4
+ t4 = value
+ end
+c function t8(value)
+c logical*8 value
+c logical*8 t8
+c t8 = value
+c end
+
+ subroutine s0(t0,value)
+ logical value
+ logical t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s1(t1,value)
+ logical*1 value
+ logical*1 t1
+cf2py intent(out) t1
+ t1 = value
+ end
+ subroutine s2(t2,value)
+ logical*2 value
+ logical*2 t2
+cf2py intent(out) t2
+ t2 = value
+ end
+ subroutine s4(t4,value)
+ logical*4 value
+ logical*4 t4
+cf2py intent(out) t4
+ t4 = value
+ end
+c subroutine s8(t8,value)
+c logical*8 value
+c logical*8 t8
+cf2py intent(out) t8
+c t8 = value
+c end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90
new file mode 100644
index 00000000..a4526468
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_logical/foo90.f90
@@ -0,0 +1,59 @@
+module f90_return_logical
+ contains
+ function t0(value)
+ logical :: value
+ logical :: t0
+ t0 = value
+ end function t0
+ function t1(value)
+ logical(kind=1) :: value
+ logical(kind=1) :: t1
+ t1 = value
+ end function t1
+ function t2(value)
+ logical(kind=2) :: value
+ logical(kind=2) :: t2
+ t2 = value
+ end function t2
+ function t4(value)
+ logical(kind=4) :: value
+ logical(kind=4) :: t4
+ t4 = value
+ end function t4
+ function t8(value)
+ logical(kind=8) :: value
+ logical(kind=8) :: t8
+ t8 = value
+ end function t8
+
+ subroutine s0(t0,value)
+ logical :: value
+ logical :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s1(t1,value)
+ logical(kind=1) :: value
+ logical(kind=1) :: t1
+!f2py intent(out) t1
+ t1 = value
+ end subroutine s1
+ subroutine s2(t2,value)
+ logical(kind=2) :: value
+ logical(kind=2) :: t2
+!f2py intent(out) t2
+ t2 = value
+ end subroutine s2
+ subroutine s4(t4,value)
+ logical(kind=4) :: value
+ logical(kind=4) :: t4
+!f2py intent(out) t4
+ t4 = value
+ end subroutine s4
+ subroutine s8(t8,value)
+ logical(kind=8) :: value
+ logical(kind=8) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+end module f90_return_logical
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo77.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo77.f
new file mode 100644
index 00000000..bf43dbf1
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo77.f
@@ -0,0 +1,45 @@
+ function t0(value)
+ real value
+ real t0
+ t0 = value
+ end
+ function t4(value)
+ real*4 value
+ real*4 t4
+ t4 = value
+ end
+ function t8(value)
+ real*8 value
+ real*8 t8
+ t8 = value
+ end
+ function td(value)
+ double precision value
+ double precision td
+ td = value
+ end
+
+ subroutine s0(t0,value)
+ real value
+ real t0
+cf2py intent(out) t0
+ t0 = value
+ end
+ subroutine s4(t4,value)
+ real*4 value
+ real*4 t4
+cf2py intent(out) t4
+ t4 = value
+ end
+ subroutine s8(t8,value)
+ real*8 value
+ real*8 t8
+cf2py intent(out) t8
+ t8 = value
+ end
+ subroutine sd(td,value)
+ double precision value
+ double precision td
+cf2py intent(out) td
+ td = value
+ end
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo90.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo90.f90
new file mode 100644
index 00000000..df971998
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/return_real/foo90.f90
@@ -0,0 +1,48 @@
+module f90_return_real
+ contains
+ function t0(value)
+ real :: value
+ real :: t0
+ t0 = value
+ end function t0
+ function t4(value)
+ real(kind=4) :: value
+ real(kind=4) :: t4
+ t4 = value
+ end function t4
+ function t8(value)
+ real(kind=8) :: value
+ real(kind=8) :: t8
+ t8 = value
+ end function t8
+ function td(value)
+ double precision :: value
+ double precision :: td
+ td = value
+ end function td
+
+ subroutine s0(t0,value)
+ real :: value
+ real :: t0
+!f2py intent(out) t0
+ t0 = value
+ end subroutine s0
+ subroutine s4(t4,value)
+ real(kind=4) :: value
+ real(kind=4) :: t4
+!f2py intent(out) t4
+ t4 = value
+ end subroutine s4
+ subroutine s8(t8,value)
+ real(kind=8) :: value
+ real(kind=8) :: t8
+!f2py intent(out) t8
+ t8 = value
+ end subroutine s8
+ subroutine sd(td,value)
+ double precision :: value
+ double precision :: td
+!f2py intent(out) td
+ td = value
+ end subroutine sd
+end module f90_return_real
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/size/foo.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/size/foo.f90
new file mode 100644
index 00000000..5b66f8c4
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/size/foo.f90
@@ -0,0 +1,44 @@
+
+subroutine foo(a, n, m, b)
+ implicit none
+
+ real, intent(in) :: a(n, m)
+ integer, intent(in) :: n, m
+ real, intent(out) :: b(size(a, 1))
+
+ integer :: i
+
+ do i = 1, size(b)
+ b(i) = sum(a(i,:))
+ enddo
+end subroutine
+
+subroutine trans(x,y)
+ implicit none
+ real, intent(in), dimension(:,:) :: x
+ real, intent(out), dimension( size(x,2), size(x,1) ) :: y
+ integer :: N, M, i, j
+ N = size(x,1)
+ M = size(x,2)
+ DO i=1,N
+ do j=1,M
+ y(j,i) = x(i,j)
+ END DO
+ END DO
+end subroutine trans
+
+subroutine flatten(x,y)
+ implicit none
+ real, intent(in), dimension(:,:) :: x
+ real, intent(out), dimension( size(x) ) :: y
+ integer :: N, M, i, j, k
+ N = size(x,1)
+ M = size(x,2)
+ k = 1
+ DO i=1,N
+ do j=1,M
+ y(k) = x(i,j)
+ k = k + 1
+ END DO
+ END DO
+end subroutine flatten
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/char.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/char.f90
new file mode 100644
index 00000000..bb7985ce
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/char.f90
@@ -0,0 +1,29 @@
+MODULE char_test
+
+CONTAINS
+
+SUBROUTINE change_strings(strings, n_strs, out_strings)
+ IMPLICIT NONE
+
+ ! Inputs
+ INTEGER, INTENT(IN) :: n_strs
+ CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
+ CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: out_strings
+
+!f2py INTEGER, INTENT(IN) :: n_strs
+!f2py CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings
+!f2py CHARACTER, INTENT(OUT), DIMENSION(2,n_strs) :: strings
+
+ ! Misc.
+ INTEGER*4 :: j
+
+
+ DO j=1, n_strs
+ out_strings(1,j) = strings(1,j)
+ out_strings(2,j) = 'A'
+ END DO
+
+END SUBROUTINE change_strings
+
+END MODULE char_test
+
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/fixed_string.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/fixed_string.f90
new file mode 100644
index 00000000..7fd15854
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/fixed_string.f90
@@ -0,0 +1,34 @@
+function sint(s) result(i)
+ implicit none
+ character(len=*) :: s
+ integer :: j, i
+ i = 0
+ do j=len(s), 1, -1
+ if (.not.((i.eq.0).and.(s(j:j).eq.' '))) then
+ i = i + ichar(s(j:j)) * 10 ** (j - 1)
+ endif
+ end do
+ return
+ end function sint
+
+ function test_in_bytes4(a) result (i)
+ implicit none
+ integer :: sint
+ character(len=4) :: a
+ integer :: i
+ i = sint(a)
+ a(1:1) = 'A'
+ return
+ end function test_in_bytes4
+
+ function test_inout_bytes4(a) result (i)
+ implicit none
+ integer :: sint
+ character(len=4), intent(inout) :: a
+ integer :: i
+ if (a(1:1).ne.' ') then
+ a(1:1) = 'E'
+ endif
+ i = sint(a)
+ return
+ end function test_inout_bytes4
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/scalar_string.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/scalar_string.f90
new file mode 100644
index 00000000..f8f07617
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/scalar_string.f90
@@ -0,0 +1,9 @@
+MODULE string_test
+
+ character(len=8) :: string
+ character string77 * 8
+
+ character(len=12), dimension(5,7) :: strarr
+ character strarr77(5,7) * 12
+
+END MODULE string_test
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/string.f b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/string.f
new file mode 100644
index 00000000..5210ca4d
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/string/string.f
@@ -0,0 +1,12 @@
+C FILE: STRING.F
+ SUBROUTINE FOO(A,B,C,D)
+ CHARACTER*5 A, B
+ CHARACTER*(*) C,D
+Cf2py intent(in) a,c
+Cf2py intent(inout) b,d
+ A(1:1) = 'A'
+ B(1:1) = 'B'
+ C(1:1) = 'C'
+ D(1:1) = 'D'
+ END
+C END OF FILE STRING.F
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90 b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90
new file mode 100644
index 00000000..7d9dc0fd
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/src/value_attrspec/gh21665.f90
@@ -0,0 +1,9 @@
+module fortfuncs
+ implicit none
+contains
+ subroutine square(x,y)
+ integer, intent(in), value :: x
+ integer, intent(out) :: y
+ y = x*x
+ end subroutine square
+end module fortfuncs
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_abstract_interface.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_abstract_interface.py
new file mode 100644
index 00000000..42902913
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_abstract_interface.py
@@ -0,0 +1,25 @@
+from pathlib import Path
+import pytest
+import textwrap
+from . import util
+from numpy.f2py import crackfortran
+from numpy.testing import IS_WASM
+
+
+@pytest.mark.skipif(IS_WASM, reason="Cannot start subprocess")
+class TestAbstractInterface(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "abstract_interface", "foo.f90")]
+
+ skip = ["add1", "add2"]
+
+ def test_abstract_interface(self):
+ assert self.module.ops_module.foo(3, 5) == (8, 13)
+
+ def test_parse_abstract_interface(self):
+ # Test gh18403
+ fpath = util.getpath("tests", "src", "abstract_interface",
+ "gh18403_mod.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ assert len(mod[0]["body"]) == 1
+ assert mod[0]["body"][0]["block"] == "abstract interface"
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_array_from_pyobj.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_array_from_pyobj.py
new file mode 100644
index 00000000..2b8c8def
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_array_from_pyobj.py
@@ -0,0 +1,686 @@
+import os
+import sys
+import copy
+import platform
+import pytest
+
+import numpy as np
+
+from numpy.testing import assert_, assert_equal
+from numpy.core.multiarray import typeinfo as _typeinfo
+from . import util
+
+wrap = None
+
+# Extend core typeinfo with CHARACTER to test dtype('c')
+_ti = _typeinfo['STRING']
+typeinfo = dict(
+ CHARACTER=type(_ti)(('c', _ti.num, 8, _ti.alignment, _ti.type)),
+ **_typeinfo)
+
+
+def setup_module():
+ """
+ Build the required testing extension module
+
+ """
+ global wrap
+
+ # Check compiler availability first
+ if not util.has_c_compiler():
+ pytest.skip("No C compiler available")
+
+ if wrap is None:
+ config_code = """
+ config.add_extension('test_array_from_pyobj_ext',
+ sources=['wrapmodule.c', 'fortranobject.c'],
+ define_macros=[])
+ """
+ d = os.path.dirname(__file__)
+ src = [
+ util.getpath("tests", "src", "array_from_pyobj", "wrapmodule.c"),
+ util.getpath("src", "fortranobject.c"),
+ util.getpath("src", "fortranobject.h"),
+ ]
+ wrap = util.build_module_distutils(src, config_code,
+ "test_array_from_pyobj_ext")
+
+
+def flags_info(arr):
+ flags = wrap.array_attrs(arr)[6]
+ return flags2names(flags)
+
+
+def flags2names(flags):
+ info = []
+ for flagname in [
+ "CONTIGUOUS",
+ "FORTRAN",
+ "OWNDATA",
+ "ENSURECOPY",
+ "ENSUREARRAY",
+ "ALIGNED",
+ "NOTSWAPPED",
+ "WRITEABLE",
+ "WRITEBACKIFCOPY",
+ "UPDATEIFCOPY",
+ "BEHAVED",
+ "BEHAVED_RO",
+ "CARRAY",
+ "FARRAY",
+ ]:
+ if abs(flags) & getattr(wrap, flagname, 0):
+ info.append(flagname)
+ return info
+
+
+class Intent:
+ def __init__(self, intent_list=[]):
+ self.intent_list = intent_list[:]
+ flags = 0
+ for i in intent_list:
+ if i == "optional":
+ flags |= wrap.F2PY_OPTIONAL
+ else:
+ flags |= getattr(wrap, "F2PY_INTENT_" + i.upper())
+ self.flags = flags
+
+ def __getattr__(self, name):
+ name = name.lower()
+ if name == "in_":
+ name = "in"
+ return self.__class__(self.intent_list + [name])
+
+ def __str__(self):
+ return "intent(%s)" % (",".join(self.intent_list))
+
+ def __repr__(self):
+ return "Intent(%r)" % (self.intent_list)
+
+ def is_intent(self, *names):
+ for name in names:
+ if name not in self.intent_list:
+ return False
+ return True
+
+ def is_intent_exact(self, *names):
+ return len(self.intent_list) == len(names) and self.is_intent(*names)
+
+
+intent = Intent()
+
+_type_names = [
+ "BOOL",
+ "BYTE",
+ "UBYTE",
+ "SHORT",
+ "USHORT",
+ "INT",
+ "UINT",
+ "LONG",
+ "ULONG",
+ "LONGLONG",
+ "ULONGLONG",
+ "FLOAT",
+ "DOUBLE",
+ "CFLOAT",
+ "STRING1",
+ "STRING5",
+ "CHARACTER",
+]
+
+_cast_dict = {"BOOL": ["BOOL"]}
+_cast_dict["BYTE"] = _cast_dict["BOOL"] + ["BYTE"]
+_cast_dict["UBYTE"] = _cast_dict["BOOL"] + ["UBYTE"]
+_cast_dict["BYTE"] = ["BYTE"]
+_cast_dict["UBYTE"] = ["UBYTE"]
+_cast_dict["SHORT"] = _cast_dict["BYTE"] + ["UBYTE", "SHORT"]
+_cast_dict["USHORT"] = _cast_dict["UBYTE"] + ["BYTE", "USHORT"]
+_cast_dict["INT"] = _cast_dict["SHORT"] + ["USHORT", "INT"]
+_cast_dict["UINT"] = _cast_dict["USHORT"] + ["SHORT", "UINT"]
+
+_cast_dict["LONG"] = _cast_dict["INT"] + ["LONG"]
+_cast_dict["ULONG"] = _cast_dict["UINT"] + ["ULONG"]
+
+_cast_dict["LONGLONG"] = _cast_dict["LONG"] + ["LONGLONG"]
+_cast_dict["ULONGLONG"] = _cast_dict["ULONG"] + ["ULONGLONG"]
+
+_cast_dict["FLOAT"] = _cast_dict["SHORT"] + ["USHORT", "FLOAT"]
+_cast_dict["DOUBLE"] = _cast_dict["INT"] + ["UINT", "FLOAT", "DOUBLE"]
+
+_cast_dict["CFLOAT"] = _cast_dict["FLOAT"] + ["CFLOAT"]
+
+_cast_dict['STRING1'] = ['STRING1']
+_cast_dict['STRING5'] = ['STRING5']
+_cast_dict['CHARACTER'] = ['CHARACTER']
+
+# 32 bit system malloc typically does not provide the alignment required by
+# 16 byte long double types this means the inout intent cannot be satisfied
+# and several tests fail as the alignment flag can be randomly true or fals
+# when numpy gains an aligned allocator the tests could be enabled again
+#
+# Furthermore, on macOS ARM64, LONGDOUBLE is an alias for DOUBLE.
+if ((np.intp().dtype.itemsize != 4 or np.clongdouble().dtype.alignment <= 8)
+ and sys.platform != "win32"
+ and (platform.system(), platform.processor()) != ("Darwin", "arm")):
+ _type_names.extend(["LONGDOUBLE", "CDOUBLE", "CLONGDOUBLE"])
+ _cast_dict["LONGDOUBLE"] = _cast_dict["LONG"] + [
+ "ULONG",
+ "FLOAT",
+ "DOUBLE",
+ "LONGDOUBLE",
+ ]
+ _cast_dict["CLONGDOUBLE"] = _cast_dict["LONGDOUBLE"] + [
+ "CFLOAT",
+ "CDOUBLE",
+ "CLONGDOUBLE",
+ ]
+ _cast_dict["CDOUBLE"] = _cast_dict["DOUBLE"] + ["CFLOAT", "CDOUBLE"]
+
+
+class Type:
+ _type_cache = {}
+
+ def __new__(cls, name):
+ if isinstance(name, np.dtype):
+ dtype0 = name
+ name = None
+ for n, i in typeinfo.items():
+ if not isinstance(i, type) and dtype0.type is i.type:
+ name = n
+ break
+ obj = cls._type_cache.get(name.upper(), None)
+ if obj is not None:
+ return obj
+ obj = object.__new__(cls)
+ obj._init(name)
+ cls._type_cache[name.upper()] = obj
+ return obj
+
+ def _init(self, name):
+ self.NAME = name.upper()
+
+ if self.NAME == 'CHARACTER':
+ info = typeinfo[self.NAME]
+ self.type_num = getattr(wrap, 'NPY_STRING')
+ self.elsize = 1
+ self.dtype = np.dtype('c')
+ elif self.NAME.startswith('STRING'):
+ info = typeinfo[self.NAME[:6]]
+ self.type_num = getattr(wrap, 'NPY_STRING')
+ self.elsize = int(self.NAME[6:] or 0)
+ self.dtype = np.dtype(f'S{self.elsize}')
+ else:
+ info = typeinfo[self.NAME]
+ self.type_num = getattr(wrap, 'NPY_' + self.NAME)
+ self.elsize = info.bits // 8
+ self.dtype = np.dtype(info.type)
+
+ assert self.type_num == info.num
+ self.type = info.type
+ self.dtypechar = info.char
+
+ def __repr__(self):
+ return (f"Type({self.NAME})|type_num={self.type_num},"
+ f" dtype={self.dtype},"
+ f" type={self.type}, elsize={self.elsize},"
+ f" dtypechar={self.dtypechar}")
+
+ def cast_types(self):
+ return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
+
+ def all_types(self):
+ return [self.__class__(_m) for _m in _type_names]
+
+ def smaller_types(self):
+ bits = typeinfo[self.NAME].alignment
+ types = []
+ for name in _type_names:
+ if typeinfo[name].alignment < bits:
+ types.append(Type(name))
+ return types
+
+ def equal_types(self):
+ bits = typeinfo[self.NAME].alignment
+ types = []
+ for name in _type_names:
+ if name == self.NAME:
+ continue
+ if typeinfo[name].alignment == bits:
+ types.append(Type(name))
+ return types
+
+ def larger_types(self):
+ bits = typeinfo[self.NAME].alignment
+ types = []
+ for name in _type_names:
+ if typeinfo[name].alignment > bits:
+ types.append(Type(name))
+ return types
+
+
+class Array:
+
+ def __repr__(self):
+ return (f'Array({self.type}, {self.dims}, {self.intent},'
+ f' {self.obj})|arr={self.arr}')
+
+ def __init__(self, typ, dims, intent, obj):
+ self.type = typ
+ self.dims = dims
+ self.intent = intent
+ self.obj_copy = copy.deepcopy(obj)
+ self.obj = obj
+
+ # arr.dtypechar may be different from typ.dtypechar
+ self.arr = wrap.call(typ.type_num,
+ typ.elsize,
+ dims, intent.flags, obj)
+
+ assert isinstance(self.arr, np.ndarray)
+
+ self.arr_attr = wrap.array_attrs(self.arr)
+
+ if len(dims) > 1:
+ if self.intent.is_intent("c"):
+ assert (intent.flags & wrap.F2PY_INTENT_C)
+ assert not self.arr.flags["FORTRAN"]
+ assert self.arr.flags["CONTIGUOUS"]
+ assert (not self.arr_attr[6] & wrap.FORTRAN)
+ else:
+ assert (not intent.flags & wrap.F2PY_INTENT_C)
+ assert self.arr.flags["FORTRAN"]
+ assert not self.arr.flags["CONTIGUOUS"]
+ assert (self.arr_attr[6] & wrap.FORTRAN)
+
+ if obj is None:
+ self.pyarr = None
+ self.pyarr_attr = None
+ return
+
+ if intent.is_intent("cache"):
+ assert isinstance(obj, np.ndarray), repr(type(obj))
+ self.pyarr = np.array(obj).reshape(*dims).copy()
+ else:
+ self.pyarr = np.array(
+ np.array(obj, dtype=typ.dtypechar).reshape(*dims),
+ order=self.intent.is_intent("c") and "C" or "F",
+ )
+ assert self.pyarr.dtype == typ
+ self.pyarr.setflags(write=self.arr.flags["WRITEABLE"])
+ assert self.pyarr.flags["OWNDATA"], (obj, intent)
+ self.pyarr_attr = wrap.array_attrs(self.pyarr)
+
+ if len(dims) > 1:
+ if self.intent.is_intent("c"):
+ assert not self.pyarr.flags["FORTRAN"]
+ assert self.pyarr.flags["CONTIGUOUS"]
+ assert (not self.pyarr_attr[6] & wrap.FORTRAN)
+ else:
+ assert self.pyarr.flags["FORTRAN"]
+ assert not self.pyarr.flags["CONTIGUOUS"]
+ assert (self.pyarr_attr[6] & wrap.FORTRAN)
+
+ assert self.arr_attr[1] == self.pyarr_attr[1] # nd
+ assert self.arr_attr[2] == self.pyarr_attr[2] # dimensions
+ if self.arr_attr[1] <= 1:
+ assert self.arr_attr[3] == self.pyarr_attr[3], repr((
+ self.arr_attr[3],
+ self.pyarr_attr[3],
+ self.arr.tobytes(),
+ self.pyarr.tobytes(),
+ )) # strides
+ assert self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:], repr((
+ self.arr_attr[5], self.pyarr_attr[5]
+ )) # descr
+ assert self.arr_attr[6] == self.pyarr_attr[6], repr((
+ self.arr_attr[6],
+ self.pyarr_attr[6],
+ flags2names(0 * self.arr_attr[6] - self.pyarr_attr[6]),
+ flags2names(self.arr_attr[6]),
+ intent,
+ )) # flags
+
+ if intent.is_intent("cache"):
+ assert self.arr_attr[5][3] >= self.type.elsize
+ else:
+ assert self.arr_attr[5][3] == self.type.elsize
+ assert (self.arr_equal(self.pyarr, self.arr))
+
+ if isinstance(self.obj, np.ndarray):
+ if typ.elsize == Type(obj.dtype).elsize:
+ if not intent.is_intent("copy") and self.arr_attr[1] <= 1:
+ assert self.has_shared_memory()
+
+ def arr_equal(self, arr1, arr2):
+ if arr1.shape != arr2.shape:
+ return False
+ return (arr1 == arr2).all()
+
+ def __str__(self):
+ return str(self.arr)
+
+ def has_shared_memory(self):
+ """Check that created array shares data with input array."""
+ if self.obj is self.arr:
+ return True
+ if not isinstance(self.obj, np.ndarray):
+ return False
+ obj_attr = wrap.array_attrs(self.obj)
+ return obj_attr[0] == self.arr_attr[0]
+
+
+class TestIntent:
+ def test_in_out(self):
+ assert str(intent.in_.out) == "intent(in,out)"
+ assert intent.in_.c.is_intent("c")
+ assert not intent.in_.c.is_intent_exact("c")
+ assert intent.in_.c.is_intent_exact("c", "in")
+ assert intent.in_.c.is_intent_exact("in", "c")
+ assert not intent.in_.is_intent("c")
+
+
+class TestSharedMemory:
+
+ @pytest.fixture(autouse=True, scope="class", params=_type_names)
+ def setup_type(self, request):
+ request.cls.type = Type(request.param)
+ request.cls.array = lambda self, dims, intent, obj: Array(
+ Type(request.param), dims, intent, obj)
+
+ @property
+ def num2seq(self):
+ if self.type.NAME.startswith('STRING'):
+ elsize = self.type.elsize
+ return ['1' * elsize, '2' * elsize]
+ return [1, 2]
+
+ @property
+ def num23seq(self):
+ if self.type.NAME.startswith('STRING'):
+ elsize = self.type.elsize
+ return [['1' * elsize, '2' * elsize, '3' * elsize],
+ ['4' * elsize, '5' * elsize, '6' * elsize]]
+ return [[1, 2, 3], [4, 5, 6]]
+
+ def test_in_from_2seq(self):
+ a = self.array([2], intent.in_, self.num2seq)
+ assert not a.has_shared_memory()
+
+ def test_in_from_2casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num2seq, dtype=t.dtype)
+ a = self.array([len(self.num2seq)], intent.in_, obj)
+ if t.elsize == self.type.elsize:
+ assert a.has_shared_memory(), repr((self.type.dtype, t.dtype))
+ else:
+ assert not a.has_shared_memory()
+
+ @pytest.mark.parametrize("write", ["w", "ro"])
+ @pytest.mark.parametrize("order", ["C", "F"])
+ @pytest.mark.parametrize("inp", ["2seq", "23seq"])
+ def test_in_nocopy(self, write, order, inp):
+ """Test if intent(in) array can be passed without copies"""
+ seq = getattr(self, "num" + inp)
+ obj = np.array(seq, dtype=self.type.dtype, order=order)
+ obj.setflags(write=(write == 'w'))
+ a = self.array(obj.shape,
+ ((order == 'C' and intent.in_.c) or intent.in_), obj)
+ assert a.has_shared_memory()
+
+ def test_inout_2seq(self):
+ obj = np.array(self.num2seq, dtype=self.type.dtype)
+ a = self.array([len(self.num2seq)], intent.inout, obj)
+ assert a.has_shared_memory()
+
+ try:
+ a = self.array([2], intent.in_.inout, self.num2seq)
+ except TypeError as msg:
+ if not str(msg).startswith(
+ "failed to initialize intent(inout|inplace|cache) array"):
+ raise
+ else:
+ raise SystemError("intent(inout) should have failed on sequence")
+
+ def test_f_inout_23seq(self):
+ obj = np.array(self.num23seq, dtype=self.type.dtype, order="F")
+ shape = (len(self.num23seq), len(self.num23seq[0]))
+ a = self.array(shape, intent.in_.inout, obj)
+ assert a.has_shared_memory()
+
+ obj = np.array(self.num23seq, dtype=self.type.dtype, order="C")
+ shape = (len(self.num23seq), len(self.num23seq[0]))
+ try:
+ a = self.array(shape, intent.in_.inout, obj)
+ except ValueError as msg:
+ if not str(msg).startswith(
+ "failed to initialize intent(inout) array"):
+ raise
+ else:
+ raise SystemError(
+ "intent(inout) should have failed on improper array")
+
+ def test_c_inout_23seq(self):
+ obj = np.array(self.num23seq, dtype=self.type.dtype)
+ shape = (len(self.num23seq), len(self.num23seq[0]))
+ a = self.array(shape, intent.in_.c.inout, obj)
+ assert a.has_shared_memory()
+
+ def test_in_copy_from_2casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num2seq, dtype=t.dtype)
+ a = self.array([len(self.num2seq)], intent.in_.copy, obj)
+ assert not a.has_shared_memory()
+
+ def test_c_in_from_23seq(self):
+ a = self.array(
+ [len(self.num23seq), len(self.num23seq[0])], intent.in_,
+ self.num23seq)
+ assert not a.has_shared_memory()
+
+ def test_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num23seq, dtype=t.dtype)
+ a = self.array(
+ [len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
+ assert not a.has_shared_memory()
+
+ def test_f_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num23seq, dtype=t.dtype, order="F")
+ a = self.array(
+ [len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
+ if t.elsize == self.type.elsize:
+ assert a.has_shared_memory()
+ else:
+ assert not a.has_shared_memory()
+
+ def test_c_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num23seq, dtype=t.dtype)
+ a = self.array(
+ [len(self.num23seq), len(self.num23seq[0])], intent.in_.c, obj)
+ if t.elsize == self.type.elsize:
+ assert a.has_shared_memory()
+ else:
+ assert not a.has_shared_memory()
+
+ def test_f_copy_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num23seq, dtype=t.dtype, order="F")
+ a = self.array(
+ [len(self.num23seq), len(self.num23seq[0])], intent.in_.copy,
+ obj)
+ assert not a.has_shared_memory()
+
+ def test_c_copy_in_from_23casttype(self):
+ for t in self.type.cast_types():
+ obj = np.array(self.num23seq, dtype=t.dtype)
+ a = self.array(
+ [len(self.num23seq), len(self.num23seq[0])], intent.in_.c.copy,
+ obj)
+ assert not a.has_shared_memory()
+
+ def test_in_cache_from_2casttype(self):
+ for t in self.type.all_types():
+ if t.elsize != self.type.elsize:
+ continue
+ obj = np.array(self.num2seq, dtype=t.dtype)
+ shape = (len(self.num2seq), )
+ a = self.array(shape, intent.in_.c.cache, obj)
+ assert a.has_shared_memory()
+
+ a = self.array(shape, intent.in_.cache, obj)
+ assert a.has_shared_memory()
+
+ obj = np.array(self.num2seq, dtype=t.dtype, order="F")
+ a = self.array(shape, intent.in_.c.cache, obj)
+ assert a.has_shared_memory()
+
+ a = self.array(shape, intent.in_.cache, obj)
+ assert a.has_shared_memory(), repr(t.dtype)
+
+ try:
+ a = self.array(shape, intent.in_.cache, obj[::-1])
+ except ValueError as msg:
+ if not str(msg).startswith(
+ "failed to initialize intent(cache) array"):
+ raise
+ else:
+ raise SystemError(
+ "intent(cache) should have failed on multisegmented array")
+
+ def test_in_cache_from_2casttype_failure(self):
+ for t in self.type.all_types():
+ if t.NAME == 'STRING':
+ # string elsize is 0, so skipping the test
+ continue
+ if t.elsize >= self.type.elsize:
+ continue
+ obj = np.array(self.num2seq, dtype=t.dtype)
+ shape = (len(self.num2seq), )
+ try:
+ self.array(shape, intent.in_.cache, obj) # Should succeed
+ except ValueError as msg:
+ if not str(msg).startswith(
+ "failed to initialize intent(cache) array"):
+ raise
+ else:
+ raise SystemError(
+ "intent(cache) should have failed on smaller array")
+
+ def test_cache_hidden(self):
+ shape = (2, )
+ a = self.array(shape, intent.cache.hide, None)
+ assert a.arr.shape == shape
+
+ shape = (2, 3)
+ a = self.array(shape, intent.cache.hide, None)
+ assert a.arr.shape == shape
+
+ shape = (-1, 3)
+ try:
+ a = self.array(shape, intent.cache.hide, None)
+ except ValueError as msg:
+ if not str(msg).startswith(
+ "failed to create intent(cache|hide)|optional array"):
+ raise
+ else:
+ raise SystemError(
+ "intent(cache) should have failed on undefined dimensions")
+
+ def test_hidden(self):
+ shape = (2, )
+ a = self.array(shape, intent.hide, None)
+ assert a.arr.shape == shape
+ assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
+
+ shape = (2, 3)
+ a = self.array(shape, intent.hide, None)
+ assert a.arr.shape == shape
+ assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
+ assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
+
+ shape = (2, 3)
+ a = self.array(shape, intent.c.hide, None)
+ assert a.arr.shape == shape
+ assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
+ assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
+
+ shape = (-1, 3)
+ try:
+ a = self.array(shape, intent.hide, None)
+ except ValueError as msg:
+ if not str(msg).startswith(
+ "failed to create intent(cache|hide)|optional array"):
+ raise
+ else:
+ raise SystemError(
+ "intent(hide) should have failed on undefined dimensions")
+
+ def test_optional_none(self):
+ shape = (2, )
+ a = self.array(shape, intent.optional, None)
+ assert a.arr.shape == shape
+ assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
+
+ shape = (2, 3)
+ a = self.array(shape, intent.optional, None)
+ assert a.arr.shape == shape
+ assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
+ assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
+
+ shape = (2, 3)
+ a = self.array(shape, intent.c.optional, None)
+ assert a.arr.shape == shape
+ assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
+ assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
+
+ def test_optional_from_2seq(self):
+ obj = self.num2seq
+ shape = (len(obj), )
+ a = self.array(shape, intent.optional, obj)
+ assert a.arr.shape == shape
+ assert not a.has_shared_memory()
+
+ def test_optional_from_23seq(self):
+ obj = self.num23seq
+ shape = (len(obj), len(obj[0]))
+ a = self.array(shape, intent.optional, obj)
+ assert a.arr.shape == shape
+ assert not a.has_shared_memory()
+
+ a = self.array(shape, intent.optional.c, obj)
+ assert a.arr.shape == shape
+ assert not a.has_shared_memory()
+
+ def test_inplace(self):
+ obj = np.array(self.num23seq, dtype=self.type.dtype)
+ assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
+ shape = obj.shape
+ a = self.array(shape, intent.inplace, obj)
+ assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
+ a.arr[1][2] = 54
+ assert obj[1][2] == a.arr[1][2] == np.array(54, dtype=self.type.dtype)
+ assert a.arr is obj
+ assert obj.flags["FORTRAN"] # obj attributes are changed inplace!
+ assert not obj.flags["CONTIGUOUS"]
+
+ def test_inplace_from_casttype(self):
+ for t in self.type.cast_types():
+ if t is self.type:
+ continue
+ obj = np.array(self.num23seq, dtype=t.dtype)
+ assert obj.dtype.type == t.type
+ assert obj.dtype.type is not self.type.type
+ assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
+ shape = obj.shape
+ a = self.array(shape, intent.inplace, obj)
+ assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
+ a.arr[1][2] = 54
+ assert obj[1][2] == a.arr[1][2] == np.array(54,
+ dtype=self.type.dtype)
+ assert a.arr is obj
+ assert obj.flags["FORTRAN"] # obj attributes changed inplace!
+ assert not obj.flags["CONTIGUOUS"]
+ assert obj.dtype.type is self.type.type # obj changed inplace!
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_assumed_shape.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_assumed_shape.py
new file mode 100644
index 00000000..d4664cf8
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_assumed_shape.py
@@ -0,0 +1,49 @@
+import os
+import pytest
+import tempfile
+
+from . import util
+
+
+class TestAssumedShapeSumExample(util.F2PyTest):
+ sources = [
+ util.getpath("tests", "src", "assumed_shape", "foo_free.f90"),
+ util.getpath("tests", "src", "assumed_shape", "foo_use.f90"),
+ util.getpath("tests", "src", "assumed_shape", "precision.f90"),
+ util.getpath("tests", "src", "assumed_shape", "foo_mod.f90"),
+ util.getpath("tests", "src", "assumed_shape", ".f2py_f2cmap"),
+ ]
+
+ @pytest.mark.slow
+ def test_all(self):
+ r = self.module.fsum([1, 2])
+ assert r == 3
+ r = self.module.sum([1, 2])
+ assert r == 3
+ r = self.module.sum_with_use([1, 2])
+ assert r == 3
+
+ r = self.module.mod.sum([1, 2])
+ assert r == 3
+ r = self.module.mod.fsum([1, 2])
+ assert r == 3
+
+
+class TestF2cmapOption(TestAssumedShapeSumExample):
+ def setup_method(self):
+ # Use a custom file name for .f2py_f2cmap
+ self.sources = list(self.sources)
+ f2cmap_src = self.sources.pop(-1)
+
+ self.f2cmap_file = tempfile.NamedTemporaryFile(delete=False)
+ with open(f2cmap_src, "rb") as f:
+ self.f2cmap_file.write(f.read())
+ self.f2cmap_file.close()
+
+ self.sources.append(self.f2cmap_file.name)
+ self.options = ["--f2cmap", self.f2cmap_file.name]
+
+ super().setup_method()
+
+ def teardown_method(self):
+ os.unlink(self.f2cmap_file.name)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_block_docstring.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_block_docstring.py
new file mode 100644
index 00000000..e0eacc03
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_block_docstring.py
@@ -0,0 +1,17 @@
+import sys
+import pytest
+from . import util
+
+from numpy.testing import IS_PYPY
+
+
+class TestBlockDocString(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "block_docstring", "foo.f")]
+
+ @pytest.mark.skipif(sys.platform == "win32",
+ reason="Fails with MinGW64 Gfortran (Issue #9673)")
+ @pytest.mark.xfail(IS_PYPY,
+ reason="PyPy cannot modify tp_doc after PyType_Ready")
+ def test_block_docstring(self):
+ expected = "bar : 'i'-array(2,3)\n"
+ assert self.module.block.__doc__ == expected
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_callback.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_callback.py
new file mode 100644
index 00000000..018cea4f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_callback.py
@@ -0,0 +1,230 @@
+import math
+import textwrap
+import sys
+import pytest
+import threading
+import traceback
+import time
+
+import numpy as np
+from numpy.testing import IS_PYPY
+from . import util
+
+
+class TestF77Callback(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "callback", "foo.f")]
+
+ @pytest.mark.parametrize("name", "t,t2".split(","))
+ def test_all(self, name):
+ self.check_function(name)
+
+ @pytest.mark.xfail(IS_PYPY,
+ reason="PyPy cannot modify tp_doc after PyType_Ready")
+ def test_docstring(self):
+ expected = textwrap.dedent("""\
+ a = t(fun,[fun_extra_args])
+
+ Wrapper for ``t``.
+
+ Parameters
+ ----------
+ fun : call-back function
+
+ Other Parameters
+ ----------------
+ fun_extra_args : input tuple, optional
+ Default: ()
+
+ Returns
+ -------
+ a : int
+
+ Notes
+ -----
+ Call-back functions::
+
+ def fun(): return a
+ Return objects:
+ a : int
+ """)
+ assert self.module.t.__doc__ == expected
+
+ def check_function(self, name):
+ t = getattr(self.module, name)
+ r = t(lambda: 4)
+ assert r == 4
+ r = t(lambda a: 5, fun_extra_args=(6, ))
+ assert r == 5
+ r = t(lambda a: a, fun_extra_args=(6, ))
+ assert r == 6
+ r = t(lambda a: 5 + a, fun_extra_args=(7, ))
+ assert r == 12
+ r = t(lambda a: math.degrees(a), fun_extra_args=(math.pi, ))
+ assert r == 180
+ r = t(math.degrees, fun_extra_args=(math.pi, ))
+ assert r == 180
+
+ r = t(self.module.func, fun_extra_args=(6, ))
+ assert r == 17
+ r = t(self.module.func0)
+ assert r == 11
+ r = t(self.module.func0._cpointer)
+ assert r == 11
+
+ class A:
+ def __call__(self):
+ return 7
+
+ def mth(self):
+ return 9
+
+ a = A()
+ r = t(a)
+ assert r == 7
+ r = t(a.mth)
+ assert r == 9
+
+ @pytest.mark.skipif(sys.platform == 'win32',
+ reason='Fails with MinGW64 Gfortran (Issue #9673)')
+ def test_string_callback(self):
+ def callback(code):
+ if code == "r":
+ return 0
+ else:
+ return 1
+
+ f = getattr(self.module, "string_callback")
+ r = f(callback)
+ assert r == 0
+
+ @pytest.mark.skipif(sys.platform == 'win32',
+ reason='Fails with MinGW64 Gfortran (Issue #9673)')
+ def test_string_callback_array(self):
+ # See gh-10027
+ cu1 = np.zeros((1, ), "S8")
+ cu2 = np.zeros((1, 8), "c")
+ cu3 = np.array([""], "S8")
+
+ def callback(cu, lencu):
+ if cu.shape != (lencu,):
+ return 1
+ if cu.dtype != "S8":
+ return 2
+ if not np.all(cu == b""):
+ return 3
+ return 0
+
+ f = getattr(self.module, "string_callback_array")
+ for cu in [cu1, cu2, cu3]:
+ res = f(callback, cu, cu.size)
+ assert res == 0
+
+ def test_threadsafety(self):
+ # Segfaults if the callback handling is not threadsafe
+
+ errors = []
+
+ def cb():
+ # Sleep here to make it more likely for another thread
+ # to call their callback at the same time.
+ time.sleep(1e-3)
+
+ # Check reentrancy
+ r = self.module.t(lambda: 123)
+ assert r == 123
+
+ return 42
+
+ def runner(name):
+ try:
+ for j in range(50):
+ r = self.module.t(cb)
+ assert r == 42
+ self.check_function(name)
+ except Exception:
+ errors.append(traceback.format_exc())
+
+ threads = [
+ threading.Thread(target=runner, args=(arg, ))
+ for arg in ("t", "t2") for n in range(20)
+ ]
+
+ for t in threads:
+ t.start()
+
+ for t in threads:
+ t.join()
+
+ errors = "\n\n".join(errors)
+ if errors:
+ raise AssertionError(errors)
+
+ def test_hidden_callback(self):
+ try:
+ self.module.hidden_callback(2)
+ except Exception as msg:
+ assert str(msg).startswith("Callback global_f not defined")
+
+ try:
+ self.module.hidden_callback2(2)
+ except Exception as msg:
+ assert str(msg).startswith("cb: Callback global_f not defined")
+
+ self.module.global_f = lambda x: x + 1
+ r = self.module.hidden_callback(2)
+ assert r == 3
+
+ self.module.global_f = lambda x: x + 2
+ r = self.module.hidden_callback(2)
+ assert r == 4
+
+ del self.module.global_f
+ try:
+ self.module.hidden_callback(2)
+ except Exception as msg:
+ assert str(msg).startswith("Callback global_f not defined")
+
+ self.module.global_f = lambda x=0: x + 3
+ r = self.module.hidden_callback(2)
+ assert r == 5
+
+ # reproducer of gh18341
+ r = self.module.hidden_callback2(2)
+ assert r == 3
+
+
+class TestF77CallbackPythonTLS(TestF77Callback):
+ """
+ Callback tests using Python thread-local storage instead of
+ compiler-provided
+ """
+
+ options = ["-DF2PY_USE_PYTHON_TLS"]
+
+
+class TestF90Callback(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "callback", "gh17797.f90")]
+
+ def test_gh17797(self):
+ def incr(x):
+ return x + 123
+
+ y = np.array([1, 2, 3], dtype=np.int64)
+ r = self.module.gh17797(incr, y)
+ assert r == 123 + 1 + 2 + 3
+
+
+class TestGH18335(util.F2PyTest):
+ """The reproduction of the reported issue requires specific input that
+ extensions may break the issue conditions, so the reproducer is
+ implemented as a separate test class. Do not extend this test with
+ other tests!
+ """
+ sources = [util.getpath("tests", "src", "callback", "gh18335.f90")]
+
+ def test_gh18335(self):
+ def foo(x):
+ x[0] += 1
+
+ r = self.module.gh18335(foo)
+ assert r == 123 + 1
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_character.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_character.py
new file mode 100644
index 00000000..79998b46
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_character.py
@@ -0,0 +1,592 @@
+import pytest
+import textwrap
+from numpy.testing import assert_array_equal, assert_equal, assert_raises
+import numpy as np
+from numpy.f2py.tests import util
+
+
+class TestCharacterString(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
+ suffix = '.f90'
+ fprefix = 'test_character_string'
+ length_list = ['1', '3', 'star']
+
+ code = ''
+ for length in length_list:
+ fsuffix = length
+ clength = dict(star='(*)').get(length, length)
+
+ code += textwrap.dedent(f"""
+
+ subroutine {fprefix}_input_{fsuffix}(c, o, n)
+ character*{clength}, intent(in) :: c
+ integer n
+ !f2py integer, depend(c), intent(hide) :: n = slen(c)
+ integer*1, dimension(n) :: o
+ !f2py intent(out) o
+ o = transfer(c, o)
+ end subroutine {fprefix}_input_{fsuffix}
+
+ subroutine {fprefix}_output_{fsuffix}(c, o, n)
+ character*{clength}, intent(out) :: c
+ integer n
+ integer*1, dimension(n), intent(in) :: o
+ !f2py integer, depend(o), intent(hide) :: n = len(o)
+ c = transfer(o, c)
+ end subroutine {fprefix}_output_{fsuffix}
+
+ subroutine {fprefix}_array_input_{fsuffix}(c, o, m, n)
+ integer m, i, n
+ character*{clength}, intent(in), dimension(m) :: c
+ !f2py integer, depend(c), intent(hide) :: m = len(c)
+ !f2py integer, depend(c), intent(hide) :: n = f2py_itemsize(c)
+ integer*1, dimension(m, n), intent(out) :: o
+ do i=1,m
+ o(i, :) = transfer(c(i), o(i, :))
+ end do
+ end subroutine {fprefix}_array_input_{fsuffix}
+
+ subroutine {fprefix}_array_output_{fsuffix}(c, o, m, n)
+ character*{clength}, intent(out), dimension(m) :: c
+ integer n
+ integer*1, dimension(m, n), intent(in) :: o
+ !f2py character(f2py_len=n) :: c
+ !f2py integer, depend(o), intent(hide) :: m = len(o)
+ !f2py integer, depend(o), intent(hide) :: n = shape(o, 1)
+ do i=1,m
+ c(i) = transfer(o(i, :), c(i))
+ end do
+ end subroutine {fprefix}_array_output_{fsuffix}
+
+ subroutine {fprefix}_2d_array_input_{fsuffix}(c, o, m1, m2, n)
+ integer m1, m2, i, j, n
+ character*{clength}, intent(in), dimension(m1, m2) :: c
+ !f2py integer, depend(c), intent(hide) :: m1 = len(c)
+ !f2py integer, depend(c), intent(hide) :: m2 = shape(c, 1)
+ !f2py integer, depend(c), intent(hide) :: n = f2py_itemsize(c)
+ integer*1, dimension(m1, m2, n), intent(out) :: o
+ do i=1,m1
+ do j=1,m2
+ o(i, j, :) = transfer(c(i, j), o(i, j, :))
+ end do
+ end do
+ end subroutine {fprefix}_2d_array_input_{fsuffix}
+ """)
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_input(self, length):
+ fsuffix = {'(*)': 'star'}.get(length, length)
+ f = getattr(self.module, self.fprefix + '_input_' + fsuffix)
+
+ a = {'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length]
+
+ assert_array_equal(f(a), np.array(list(map(ord, a)), dtype='u1'))
+
+ @pytest.mark.parametrize("length", length_list[:-1])
+ def test_output(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_output_' + fsuffix)
+
+ a = {'1': 'a', '3': 'abc'}[length]
+
+ assert_array_equal(f(np.array(list(map(ord, a)), dtype='u1')),
+ a.encode())
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_array_input(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_array_input_' + fsuffix)
+
+ a = np.array([{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
+ {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length],
+ ], dtype='S')
+
+ expected = np.array([[c for c in s] for s in a], dtype='u1')
+ assert_array_equal(f(a), expected)
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_array_output(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_array_output_' + fsuffix)
+
+ expected = np.array(
+ [{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
+ {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length]], dtype='S')
+
+ a = np.array([[c for c in s] for s in expected], dtype='u1')
+ assert_array_equal(f(a), expected)
+
+ @pytest.mark.parametrize("length", length_list)
+ def test_2d_array_input(self, length):
+ fsuffix = length
+ f = getattr(self.module, self.fprefix + '_2d_array_input_' + fsuffix)
+
+ a = np.array([[{'1': 'a', '3': 'abc', 'star': 'abcde' * 3}[length],
+ {'1': 'A', '3': 'ABC', 'star': 'ABCDE' * 3}[length]],
+ [{'1': 'f', '3': 'fgh', 'star': 'fghij' * 3}[length],
+ {'1': 'F', '3': 'FGH', 'star': 'FGHIJ' * 3}[length]]],
+ dtype='S')
+ expected = np.array([[[c for c in item] for item in row] for row in a],
+ dtype='u1', order='F')
+ assert_array_equal(f(a), expected)
+
+
+class TestCharacter(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
+ suffix = '.f90'
+ fprefix = 'test_character'
+
+ code = textwrap.dedent(f"""
+ subroutine {fprefix}_input(c, o)
+ character, intent(in) :: c
+ integer*1 o
+ !f2py intent(out) o
+ o = transfer(c, o)
+ end subroutine {fprefix}_input
+
+ subroutine {fprefix}_output(c, o)
+ character :: c
+ integer*1, intent(in) :: o
+ !f2py intent(out) c
+ c = transfer(o, c)
+ end subroutine {fprefix}_output
+
+ subroutine {fprefix}_input_output(c, o)
+ character, intent(in) :: c
+ character o
+ !f2py intent(out) o
+ o = c
+ end subroutine {fprefix}_input_output
+
+ subroutine {fprefix}_inout(c, n)
+ character :: c, n
+ !f2py intent(in) n
+ !f2py intent(inout) c
+ c = n
+ end subroutine {fprefix}_inout
+
+ function {fprefix}_return(o) result (c)
+ character :: c
+ character, intent(in) :: o
+ c = transfer(o, c)
+ end function {fprefix}_return
+
+ subroutine {fprefix}_array_input(c, o)
+ character, intent(in) :: c(3)
+ integer*1 o(3)
+ !f2py intent(out) o
+ integer i
+ do i=1,3
+ o(i) = transfer(c(i), o(i))
+ end do
+ end subroutine {fprefix}_array_input
+
+ subroutine {fprefix}_2d_array_input(c, o)
+ character, intent(in) :: c(2, 3)
+ integer*1 o(2, 3)
+ !f2py intent(out) o
+ integer i, j
+ do i=1,2
+ do j=1,3
+ o(i, j) = transfer(c(i, j), o(i, j))
+ end do
+ end do
+ end subroutine {fprefix}_2d_array_input
+
+ subroutine {fprefix}_array_output(c, o)
+ character :: c(3)
+ integer*1, intent(in) :: o(3)
+ !f2py intent(out) c
+ do i=1,3
+ c(i) = transfer(o(i), c(i))
+ end do
+ end subroutine {fprefix}_array_output
+
+ subroutine {fprefix}_array_inout(c, n)
+ character :: c(3), n(3)
+ !f2py intent(in) n(3)
+ !f2py intent(inout) c(3)
+ do i=1,3
+ c(i) = n(i)
+ end do
+ end subroutine {fprefix}_array_inout
+
+ subroutine {fprefix}_2d_array_inout(c, n)
+ character :: c(2, 3), n(2, 3)
+ !f2py intent(in) n(2, 3)
+ !f2py intent(inout) c(2. 3)
+ integer i, j
+ do i=1,2
+ do j=1,3
+ c(i, j) = n(i, j)
+ end do
+ end do
+ end subroutine {fprefix}_2d_array_inout
+
+ function {fprefix}_array_return(o) result (c)
+ character, dimension(3) :: c
+ character, intent(in) :: o(3)
+ do i=1,3
+ c(i) = o(i)
+ end do
+ end function {fprefix}_array_return
+
+ function {fprefix}_optional(o) result (c)
+ character, intent(in) :: o
+ !f2py character o = "a"
+ character :: c
+ c = o
+ end function {fprefix}_optional
+ """)
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_input(self, dtype):
+ f = getattr(self.module, self.fprefix + '_input')
+
+ assert_equal(f(np.array('a', dtype=dtype)), ord('a'))
+ assert_equal(f(np.array(b'a', dtype=dtype)), ord('a'))
+ assert_equal(f(np.array(['a'], dtype=dtype)), ord('a'))
+ assert_equal(f(np.array('abc', dtype=dtype)), ord('a'))
+ assert_equal(f(np.array([['a']], dtype=dtype)), ord('a'))
+
+ def test_input_varia(self):
+ f = getattr(self.module, self.fprefix + '_input')
+
+ assert_equal(f('a'), ord('a'))
+ assert_equal(f(b'a'), ord(b'a'))
+ assert_equal(f(''), 0)
+ assert_equal(f(b''), 0)
+ assert_equal(f(b'\0'), 0)
+ assert_equal(f('ab'), ord('a'))
+ assert_equal(f(b'ab'), ord('a'))
+ assert_equal(f(['a']), ord('a'))
+
+ assert_equal(f(np.array(b'a')), ord('a'))
+ assert_equal(f(np.array([b'a'])), ord('a'))
+ a = np.array('a')
+ assert_equal(f(a), ord('a'))
+ a = np.array(['a'])
+ assert_equal(f(a), ord('a'))
+
+ try:
+ f([])
+ except IndexError as msg:
+ if not str(msg).endswith(' got 0-list'):
+ raise
+ else:
+ raise SystemError(f'{f.__name__} should have failed on empty list')
+
+ try:
+ f(97)
+ except TypeError as msg:
+ if not str(msg).endswith(' got int instance'):
+ raise
+ else:
+ raise SystemError(f'{f.__name__} should have failed on int value')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1', 'U1'])
+ def test_array_input(self, dtype):
+ f = getattr(self.module, self.fprefix + '_array_input')
+
+ assert_array_equal(f(np.array(['a', 'b', 'c'], dtype=dtype)),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+ assert_array_equal(f(np.array([b'a', b'b', b'c'], dtype=dtype)),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+
+ def test_array_input_varia(self):
+ f = getattr(self.module, self.fprefix + '_array_input')
+ assert_array_equal(f(['a', 'b', 'c']),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+ assert_array_equal(f([b'a', b'b', b'c']),
+ np.array(list(map(ord, 'abc')), dtype='i1'))
+
+ try:
+ f(['a', 'b', 'c', 'd'])
+ except ValueError as msg:
+ if not str(msg).endswith(
+ 'th dimension must be fixed to 3 but got 4'):
+ raise
+ else:
+ raise SystemError(
+ f'{f.__name__} should have failed on wrong input')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1', 'U1'])
+ def test_2d_array_input(self, dtype):
+ f = getattr(self.module, self.fprefix + '_2d_array_input')
+
+ a = np.array([['a', 'b', 'c'],
+ ['d', 'e', 'f']], dtype=dtype, order='F')
+ expected = a.view(np.uint32 if dtype == 'U1' else np.uint8)
+ assert_array_equal(f(a), expected)
+
+ def test_output(self):
+ f = getattr(self.module, self.fprefix + '_output')
+
+ assert_equal(f(ord(b'a')), b'a')
+ assert_equal(f(0), b'\0')
+
+ def test_array_output(self):
+ f = getattr(self.module, self.fprefix + '_array_output')
+
+ assert_array_equal(f(list(map(ord, 'abc'))),
+ np.array(list('abc'), dtype='S1'))
+
+ def test_input_output(self):
+ f = getattr(self.module, self.fprefix + '_input_output')
+
+ assert_equal(f(b'a'), b'a')
+ assert_equal(f('a'), b'a')
+ assert_equal(f(''), b'\0')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_inout(self, dtype):
+ f = getattr(self.module, self.fprefix + '_inout')
+
+ a = np.array(list('abc'), dtype=dtype)
+ f(a, 'A')
+ assert_array_equal(a, np.array(list('Abc'), dtype=a.dtype))
+ f(a[1:], 'B')
+ assert_array_equal(a, np.array(list('ABc'), dtype=a.dtype))
+
+ a = np.array(['abc'], dtype=dtype)
+ f(a, 'A')
+ assert_array_equal(a, np.array(['Abc'], dtype=a.dtype))
+
+ def test_inout_varia(self):
+ f = getattr(self.module, self.fprefix + '_inout')
+ a = np.array('abc', dtype='S3')
+ f(a, 'A')
+ assert_array_equal(a, np.array('Abc', dtype=a.dtype))
+
+ a = np.array(['abc'], dtype='S3')
+ f(a, 'A')
+ assert_array_equal(a, np.array(['Abc'], dtype=a.dtype))
+
+ try:
+ f('abc', 'A')
+ except ValueError as msg:
+ if not str(msg).endswith(' got 3-str'):
+ raise
+ else:
+ raise SystemError(f'{f.__name__} should have failed on str value')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_array_inout(self, dtype):
+ f = getattr(self.module, self.fprefix + '_array_inout')
+ n = np.array(['A', 'B', 'C'], dtype=dtype, order='F')
+
+ a = np.array(['a', 'b', 'c'], dtype=dtype, order='F')
+ f(a, n)
+ assert_array_equal(a, n)
+
+ a = np.array(['a', 'b', 'c', 'd'], dtype=dtype)
+ f(a[1:], n)
+ assert_array_equal(a, np.array(['a', 'A', 'B', 'C'], dtype=dtype))
+
+ a = np.array([['a', 'b', 'c']], dtype=dtype, order='F')
+ f(a, n)
+ assert_array_equal(a, np.array([['A', 'B', 'C']], dtype=dtype))
+
+ a = np.array(['a', 'b', 'c', 'd'], dtype=dtype, order='F')
+ try:
+ f(a, n)
+ except ValueError as msg:
+ if not str(msg).endswith(
+ 'th dimension must be fixed to 3 but got 4'):
+ raise
+ else:
+ raise SystemError(
+ f'{f.__name__} should have failed on wrong input')
+
+ @pytest.mark.parametrize("dtype", ['c', 'S1'])
+ def test_2d_array_inout(self, dtype):
+ f = getattr(self.module, self.fprefix + '_2d_array_inout')
+ n = np.array([['A', 'B', 'C'],
+ ['D', 'E', 'F']],
+ dtype=dtype, order='F')
+ a = np.array([['a', 'b', 'c'],
+ ['d', 'e', 'f']],
+ dtype=dtype, order='F')
+ f(a, n)
+ assert_array_equal(a, n)
+
+ def test_return(self):
+ f = getattr(self.module, self.fprefix + '_return')
+
+ assert_equal(f('a'), b'a')
+
+ @pytest.mark.skip('fortran function returning array segfaults')
+ def test_array_return(self):
+ f = getattr(self.module, self.fprefix + '_array_return')
+
+ a = np.array(list('abc'), dtype='S1')
+ assert_array_equal(f(a), a)
+
+ def test_optional(self):
+ f = getattr(self.module, self.fprefix + '_optional')
+
+ assert_equal(f(), b"a")
+ assert_equal(f(b'B'), b"B")
+
+
+class TestMiscCharacter(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/test-build-f2py']
+ suffix = '.f90'
+ fprefix = 'test_misc_character'
+
+ code = textwrap.dedent(f"""
+ subroutine {fprefix}_gh18684(x, y, m)
+ character(len=5), dimension(m), intent(in) :: x
+ character*5, dimension(m), intent(out) :: y
+ integer i, m
+ !f2py integer, intent(hide), depend(x) :: m = f2py_len(x)
+ do i=1,m
+ y(i) = x(i)
+ end do
+ end subroutine {fprefix}_gh18684
+
+ subroutine {fprefix}_gh6308(x, i)
+ integer i
+ !f2py check(i>=0 && i<12) i
+ character*5 name, x
+ common name(12)
+ name(i + 1) = x
+ end subroutine {fprefix}_gh6308
+
+ subroutine {fprefix}_gh4519(x)
+ character(len=*), intent(in) :: x(:)
+ !f2py intent(out) x
+ integer :: i
+ do i=1, size(x)
+ print*, "x(",i,")=", x(i)
+ end do
+ end subroutine {fprefix}_gh4519
+
+ pure function {fprefix}_gh3425(x) result (y)
+ character(len=*), intent(in) :: x
+ character(len=len(x)) :: y
+ integer :: i
+ do i = 1, len(x)
+ j = iachar(x(i:i))
+ if (j>=iachar("a") .and. j<=iachar("z") ) then
+ y(i:i) = achar(j-32)
+ else
+ y(i:i) = x(i:i)
+ endif
+ end do
+ end function {fprefix}_gh3425
+
+ subroutine {fprefix}_character_bc_new(x, y, z)
+ character, intent(in) :: x
+ character, intent(out) :: y
+ !f2py character, depend(x) :: y = x
+ !f2py character, dimension((x=='a'?1:2)), depend(x), intent(out) :: z
+ character, dimension(*) :: z
+ !f2py character, optional, check(x == 'a' || x == 'b') :: x = 'a'
+ !f2py callstatement (*f2py_func)(&x, &y, z)
+ !f2py callprotoargument character*, character*, character*
+ if (y.eq.x) then
+ y = x
+ else
+ y = 'e'
+ endif
+ z(1) = 'c'
+ end subroutine {fprefix}_character_bc_new
+
+ subroutine {fprefix}_character_bc_old(x, y, z)
+ character, intent(in) :: x
+ character, intent(out) :: y
+ !f2py character, depend(x) :: y = x[0]
+ !f2py character, dimension((*x=='a'?1:2)), depend(x), intent(out) :: z
+ character, dimension(*) :: z
+ !f2py character, optional, check(*x == 'a' || x[0] == 'b') :: x = 'a'
+ !f2py callstatement (*f2py_func)(x, y, z)
+ !f2py callprotoargument char*, char*, char*
+ if (y.eq.x) then
+ y = x
+ else
+ y = 'e'
+ endif
+ z(1) = 'c'
+ end subroutine {fprefix}_character_bc_old
+ """)
+
+ def test_gh18684(self):
+ # Test character(len=5) and character*5 usages
+ f = getattr(self.module, self.fprefix + '_gh18684')
+ x = np.array(["abcde", "fghij"], dtype='S5')
+ y = f(x)
+
+ assert_array_equal(x, y)
+
+ def test_gh6308(self):
+ # Test character string array in a common block
+ f = getattr(self.module, self.fprefix + '_gh6308')
+
+ assert_equal(self.module._BLNK_.name.dtype, np.dtype('S5'))
+ assert_equal(len(self.module._BLNK_.name), 12)
+ f("abcde", 0)
+ assert_equal(self.module._BLNK_.name[0], b"abcde")
+ f("12345", 5)
+ assert_equal(self.module._BLNK_.name[5], b"12345")
+
+ def test_gh4519(self):
+ # Test array of assumed length strings
+ f = getattr(self.module, self.fprefix + '_gh4519')
+
+ for x, expected in [
+ ('a', dict(shape=(), dtype=np.dtype('S1'))),
+ ('text', dict(shape=(), dtype=np.dtype('S4'))),
+ (np.array(['1', '2', '3'], dtype='S1'),
+ dict(shape=(3,), dtype=np.dtype('S1'))),
+ (['1', '2', '34'],
+ dict(shape=(3,), dtype=np.dtype('S2'))),
+ (['', ''], dict(shape=(2,), dtype=np.dtype('S1')))]:
+ r = f(x)
+ for k, v in expected.items():
+ assert_equal(getattr(r, k), v)
+
+ def test_gh3425(self):
+ # Test returning a copy of assumed length string
+ f = getattr(self.module, self.fprefix + '_gh3425')
+ # f is equivalent to bytes.upper
+
+ assert_equal(f('abC'), b'ABC')
+ assert_equal(f(''), b'')
+ assert_equal(f('abC12d'), b'ABC12D')
+
+ @pytest.mark.parametrize("state", ['new', 'old'])
+ def test_character_bc(self, state):
+ f = getattr(self.module, self.fprefix + '_character_bc_' + state)
+
+ c, a = f()
+ assert_equal(c, b'a')
+ assert_equal(len(a), 1)
+
+ c, a = f(b'b')
+ assert_equal(c, b'b')
+ assert_equal(len(a), 2)
+
+ assert_raises(Exception, lambda: f(b'c'))
+
+
+class TestStringScalarArr(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "scalar_string.f90")]
+
+ @pytest.mark.slow
+ def test_char(self):
+ for out in (self.module.string_test.string,
+ self.module.string_test.string77):
+ expected = ()
+ assert out.shape == expected
+ expected = '|S8'
+ assert out.dtype == expected
+
+ @pytest.mark.slow
+ def test_char_arr(self):
+ for out in (self.module.string_test.strarr,
+ self.module.string_test.strarr77):
+ expected = (5,7)
+ assert out.shape == expected
+ expected = '|S12'
+ assert out.dtype == expected
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_common.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_common.py
new file mode 100644
index 00000000..8a4b221e
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_common.py
@@ -0,0 +1,18 @@
+import os
+import sys
+import pytest
+
+import numpy as np
+from . import util
+
+
+class TestCommonBlock(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "common", "block.f")]
+
+ @pytest.mark.skipif(sys.platform == "win32",
+ reason="Fails with MinGW64 Gfortran (Issue #9673)")
+ def test_common_block(self):
+ self.module.initcb()
+ assert self.module.block.long_bn == np.array(1.0, dtype=np.float64)
+ assert self.module.block.string_bn == np.array("2", dtype="|S1")
+ assert self.module.block.ok == np.array(3, dtype=np.int32)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_compile_function.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_compile_function.py
new file mode 100644
index 00000000..3c16f319
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_compile_function.py
@@ -0,0 +1,117 @@
+"""See https://github.com/numpy/numpy/pull/11937.
+
+"""
+import sys
+import os
+import uuid
+from importlib import import_module
+import pytest
+
+import numpy.f2py
+
+from . import util
+
+
+def setup_module():
+ if not util.has_c_compiler():
+ pytest.skip("Needs C compiler")
+ if not util.has_f77_compiler():
+ pytest.skip("Needs FORTRAN 77 compiler")
+
+
+# extra_args can be a list (since gh-11937) or string.
+# also test absence of extra_args
+@pytest.mark.parametrize("extra_args",
+ [["--noopt", "--debug"], "--noopt --debug", ""])
+@pytest.mark.leaks_references(reason="Imported module seems never deleted.")
+def test_f2py_init_compile(extra_args):
+ # flush through the f2py __init__ compile() function code path as a
+ # crude test for input handling following migration from
+ # exec_command() to subprocess.check_output() in gh-11937
+
+ # the Fortran 77 syntax requires 6 spaces before any commands, but
+ # more space may be added/
+ fsource = """
+ integer function foo()
+ foo = 10 + 5
+ return
+ end
+ """
+ # use various helper functions in util.py to enable robust build /
+ # compile and reimport cycle in test suite
+ moddir = util.get_module_dir()
+ modname = util.get_temp_module_name()
+
+ cwd = os.getcwd()
+ target = os.path.join(moddir, str(uuid.uuid4()) + ".f")
+ # try running compile() with and without a source_fn provided so
+ # that the code path where a temporary file for writing Fortran
+ # source is created is also explored
+ for source_fn in [target, None]:
+ # mimic the path changing behavior used by build_module() in
+ # util.py, but don't actually use build_module() because it has
+ # its own invocation of subprocess that circumvents the
+ # f2py.compile code block under test
+ with util.switchdir(moddir):
+ ret_val = numpy.f2py.compile(fsource,
+ modulename=modname,
+ extra_args=extra_args,
+ source_fn=source_fn)
+
+ # check for compile success return value
+ assert ret_val == 0
+
+ # we are not currently able to import the Python-Fortran
+ # interface module on Windows / Appveyor, even though we do get
+ # successful compilation on that platform with Python 3.x
+ if sys.platform != "win32":
+ # check for sensible result of Fortran function; that means
+ # we can import the module name in Python and retrieve the
+ # result of the sum operation
+ return_check = import_module(modname)
+ calc_result = return_check.foo()
+ assert calc_result == 15
+ # Removal from sys.modules, is not as such necessary. Even with
+ # removal, the module (dict) stays alive.
+ del sys.modules[modname]
+
+
+def test_f2py_init_compile_failure():
+ # verify an appropriate integer status value returned by
+ # f2py.compile() when invalid Fortran is provided
+ ret_val = numpy.f2py.compile(b"invalid")
+ assert ret_val == 1
+
+
+def test_f2py_init_compile_bad_cmd():
+ # verify that usage of invalid command in f2py.compile() returns
+ # status value of 127 for historic consistency with exec_command()
+ # error handling
+
+ # patch the sys Python exe path temporarily to induce an OSError
+ # downstream NOTE: how bad of an idea is this patching?
+ try:
+ temp = sys.executable
+ sys.executable = "does not exist"
+
+ # the OSError should take precedence over invalid Fortran
+ ret_val = numpy.f2py.compile(b"invalid")
+ assert ret_val == 127
+ finally:
+ sys.executable = temp
+
+
+@pytest.mark.parametrize(
+ "fsource",
+ [
+ "program test_f2py\nend program test_f2py",
+ b"program test_f2py\nend program test_f2py",
+ ],
+)
+def test_compile_from_strings(tmpdir, fsource):
+ # Make sure we can compile str and bytes gh-12796
+ with util.switchdir(tmpdir):
+ ret_val = numpy.f2py.compile(fsource,
+ modulename="test_compile_from_strings",
+ extension=".f90")
+ assert ret_val == 0
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_crackfortran.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_crackfortran.py
new file mode 100644
index 00000000..73ac4e27
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_crackfortran.py
@@ -0,0 +1,278 @@
+import importlib
+import codecs
+import unicodedata
+import pytest
+import numpy as np
+from numpy.f2py.crackfortran import markinnerspaces
+from . import util
+from numpy.f2py import crackfortran
+import textwrap
+
+
+class TestNoSpace(util.F2PyTest):
+ # issue gh-15035: add handling for endsubroutine, endfunction with no space
+ # between "end" and the block name
+ sources = [util.getpath("tests", "src", "crackfortran", "gh15035.f")]
+
+ def test_module(self):
+ k = np.array([1, 2, 3], dtype=np.float64)
+ w = np.array([1, 2, 3], dtype=np.float64)
+ self.module.subb(k)
+ assert np.allclose(k, w + 1)
+ self.module.subc([w, k])
+ assert np.allclose(k, w + 1)
+ assert self.module.t0("23") == b"2"
+
+
+class TestPublicPrivate:
+ def test_defaultPrivate(self):
+ fpath = util.getpath("tests", "src", "crackfortran", "privatemod.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ mod = mod[0]
+ assert "private" in mod["vars"]["a"]["attrspec"]
+ assert "public" not in mod["vars"]["a"]["attrspec"]
+ assert "private" in mod["vars"]["b"]["attrspec"]
+ assert "public" not in mod["vars"]["b"]["attrspec"]
+ assert "private" not in mod["vars"]["seta"]["attrspec"]
+ assert "public" in mod["vars"]["seta"]["attrspec"]
+
+ def test_defaultPublic(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "publicmod.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ mod = mod[0]
+ assert "private" in mod["vars"]["a"]["attrspec"]
+ assert "public" not in mod["vars"]["a"]["attrspec"]
+ assert "private" not in mod["vars"]["seta"]["attrspec"]
+ assert "public" in mod["vars"]["seta"]["attrspec"]
+
+ def test_access_type(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "accesstype.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ tt = mod[0]['vars']
+ assert set(tt['a']['attrspec']) == {'private', 'bind(c)'}
+ assert set(tt['b_']['attrspec']) == {'public', 'bind(c)'}
+ assert set(tt['c']['attrspec']) == {'public'}
+
+
+class TestModuleProcedure():
+ def test_moduleOperators(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "operators.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ mod = mod[0]
+ assert "body" in mod and len(mod["body"]) == 9
+ assert mod["body"][1]["name"] == "operator(.item.)"
+ assert "implementedby" in mod["body"][1]
+ assert mod["body"][1]["implementedby"] == \
+ ["item_int", "item_real"]
+ assert mod["body"][2]["name"] == "operator(==)"
+ assert "implementedby" in mod["body"][2]
+ assert mod["body"][2]["implementedby"] == ["items_are_equal"]
+ assert mod["body"][3]["name"] == "assignment(=)"
+ assert "implementedby" in mod["body"][3]
+ assert mod["body"][3]["implementedby"] == \
+ ["get_int", "get_real"]
+
+ def test_notPublicPrivate(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "pubprivmod.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ mod = mod[0]
+ assert mod['vars']['a']['attrspec'] == ['private', ]
+ assert mod['vars']['b']['attrspec'] == ['public', ]
+ assert mod['vars']['seta']['attrspec'] == ['public', ]
+
+
+class TestExternal(util.F2PyTest):
+ # issue gh-17859: add external attribute support
+ sources = [util.getpath("tests", "src", "crackfortran", "gh17859.f")]
+
+ def test_external_as_statement(self):
+ def incr(x):
+ return x + 123
+
+ r = self.module.external_as_statement(incr)
+ assert r == 123
+
+ def test_external_as_attribute(self):
+ def incr(x):
+ return x + 123
+
+ r = self.module.external_as_attribute(incr)
+ assert r == 123
+
+
+class TestCrackFortran(util.F2PyTest):
+ # gh-2848: commented lines between parameters in subroutine parameter lists
+ sources = [util.getpath("tests", "src", "crackfortran", "gh2848.f90")]
+
+ def test_gh2848(self):
+ r = self.module.gh2848(1, 2)
+ assert r == (1, 2)
+
+
+class TestMarkinnerspaces:
+ # gh-14118: markinnerspaces does not handle multiple quotations
+
+ def test_do_not_touch_normal_spaces(self):
+ test_list = ["a ", " a", "a b c", "'abcdefghij'"]
+ for i in test_list:
+ assert markinnerspaces(i) == i
+
+ def test_one_relevant_space(self):
+ assert markinnerspaces("a 'b c' \\' \\'") == "a 'b@_@c' \\' \\'"
+ assert markinnerspaces(r'a "b c" \" \"') == r'a "b@_@c" \" \"'
+
+ def test_ignore_inner_quotes(self):
+ assert markinnerspaces("a 'b c\" \" d' e") == "a 'b@_@c\"@_@\"@_@d' e"
+ assert markinnerspaces("a \"b c' ' d\" e") == "a \"b@_@c'@_@'@_@d\" e"
+
+ def test_multiple_relevant_spaces(self):
+ assert markinnerspaces("a 'b c' 'd e'") == "a 'b@_@c' 'd@_@e'"
+ assert markinnerspaces(r'a "b c" "d e"') == r'a "b@_@c" "d@_@e"'
+
+class TestDimSpec(util.F2PyTest):
+ """This test suite tests various expressions that are used as dimension
+ specifications.
+
+ There exists two usage cases where analyzing dimensions
+ specifications are important.
+
+ In the first case, the size of output arrays must be defined based
+ on the inputs to a Fortran function. Because Fortran supports
+ arbitrary bases for indexing, for instance, `arr(lower:upper)`,
+ f2py has to evaluate an expression `upper - lower + 1` where
+ `lower` and `upper` are arbitrary expressions of input parameters.
+ The evaluation is performed in C, so f2py has to translate Fortran
+ expressions to valid C expressions (an alternative approach is
+ that a developer specifies the corresponding C expressions in a
+ .pyf file).
+
+ In the second case, when user provides an input array with a given
+ size but some hidden parameters used in dimensions specifications
+ need to be determined based on the input array size. This is a
+ harder problem because f2py has to solve the inverse problem: find
+ a parameter `p` such that `upper(p) - lower(p) + 1` equals to the
+ size of input array. In the case when this equation cannot be
+ solved (e.g. because the input array size is wrong), raise an
+ error before calling the Fortran function (that otherwise would
+ likely crash Python process when the size of input arrays is
+ wrong). f2py currently supports this case only when the equation
+ is linear with respect to unknown parameter.
+
+ """
+
+ suffix = ".f90"
+
+ code_template = textwrap.dedent("""
+ function get_arr_size_{count}(a, n) result (length)
+ integer, intent(in) :: n
+ integer, dimension({dimspec}), intent(out) :: a
+ integer length
+ length = size(a)
+ end function
+
+ subroutine get_inv_arr_size_{count}(a, n)
+ integer :: n
+ ! the value of n is computed in f2py wrapper
+ !f2py intent(out) n
+ integer, dimension({dimspec}), intent(in) :: a
+ if (a({first}).gt.0) then
+ print*, "a=", a
+ endif
+ end subroutine
+ """)
+
+ linear_dimspecs = [
+ "n", "2*n", "2:n", "n/2", "5 - n/2", "3*n:20", "n*(n+1):n*(n+5)",
+ "2*n, n"
+ ]
+ nonlinear_dimspecs = ["2*n:3*n*n+2*n"]
+ all_dimspecs = linear_dimspecs + nonlinear_dimspecs
+
+ code = ""
+ for count, dimspec in enumerate(all_dimspecs):
+ lst = [(d.split(":")[0] if ":" in d else "1") for d in dimspec.split(',')]
+ code += code_template.format(
+ count=count,
+ dimspec=dimspec,
+ first=", ".join(lst),
+ )
+
+ @pytest.mark.parametrize("dimspec", all_dimspecs)
+ def test_array_size(self, dimspec):
+
+ count = self.all_dimspecs.index(dimspec)
+ get_arr_size = getattr(self.module, f"get_arr_size_{count}")
+
+ for n in [1, 2, 3, 4, 5]:
+ sz, a = get_arr_size(n)
+ assert a.size == sz
+
+ @pytest.mark.parametrize("dimspec", all_dimspecs)
+ def test_inv_array_size(self, dimspec):
+
+ count = self.all_dimspecs.index(dimspec)
+ get_arr_size = getattr(self.module, f"get_arr_size_{count}")
+ get_inv_arr_size = getattr(self.module, f"get_inv_arr_size_{count}")
+
+ for n in [1, 2, 3, 4, 5]:
+ sz, a = get_arr_size(n)
+ if dimspec in self.nonlinear_dimspecs:
+ # one must specify n as input, the call we'll ensure
+ # that a and n are compatible:
+ n1 = get_inv_arr_size(a, n)
+ else:
+ # in case of linear dependence, n can be determined
+ # from the shape of a:
+ n1 = get_inv_arr_size(a)
+ # n1 may be different from n (for instance, when `a` size
+ # is a function of some `n` fraction) but it must produce
+ # the same sized array
+ sz1, _ = get_arr_size(n1)
+ assert sz == sz1, (n, n1, sz, sz1)
+
+
+class TestModuleDeclaration:
+ def test_dependencies(self, tmp_path):
+ fpath = util.getpath("tests", "src", "crackfortran", "foo_deps.f90")
+ mod = crackfortran.crackfortran([str(fpath)])
+ assert len(mod) == 1
+ assert mod[0]["vars"]["abar"]["="] == "bar('abar')"
+
+class TestEval(util.F2PyTest):
+ def test_eval_scalar(self):
+ eval_scalar = crackfortran._eval_scalar
+
+ assert eval_scalar('123', {}) == '123'
+ assert eval_scalar('12 + 3', {}) == '15'
+ assert eval_scalar('a + b', dict(a=1, b=2)) == '3'
+ assert eval_scalar('"123"', {}) == "'123'"
+
+
+class TestFortranReader(util.F2PyTest):
+ @pytest.mark.parametrize("encoding",
+ ['ascii', 'utf-8', 'utf-16', 'utf-32'])
+ def test_input_encoding(self, tmp_path, encoding):
+ # gh-635
+ f_path = tmp_path / f"input_with_{encoding}_encoding.f90"
+ with f_path.open('w', encoding=encoding) as ff:
+ ff.write("""
+ subroutine foo()
+ end subroutine foo
+ """)
+ mod = crackfortran.crackfortran([str(f_path)])
+ assert mod[0]['name'] == 'foo'
+
+class TestUnicodeComment(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "crackfortran", "unicode_comment.f90")]
+
+ @pytest.mark.skipif(
+ (importlib.util.find_spec("charset_normalizer") is None),
+ reason="test requires charset_normalizer which is not installed",
+ )
+ def test_encoding_comment(self):
+ self.module.foo(3)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_docs.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_docs.py
new file mode 100644
index 00000000..6631dd82
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_docs.py
@@ -0,0 +1,55 @@
+import os
+import pytest
+import numpy as np
+from numpy.testing import assert_array_equal, assert_equal
+from . import util
+
+
+def get_docdir():
+ # assuming that documentation tests are run from a source
+ # directory
+ return os.path.abspath(os.path.join(
+ os.path.dirname(__file__),
+ '..', '..', '..',
+ 'doc', 'source', 'f2py', 'code'))
+
+
+pytestmark = pytest.mark.skipif(
+ not os.path.isdir(get_docdir()),
+ reason=('Could not find f2py documentation sources'
+ f' ({get_docdir()} does not exists)'))
+
+
+def _path(*a):
+ return os.path.join(*((get_docdir(),) + a))
+
+
+class TestDocAdvanced(util.F2PyTest):
+ # options = ['--debug-capi', '--build-dir', '/tmp/build-f2py']
+ sources = [_path('asterisk1.f90'), _path('asterisk2.f90'),
+ _path('ftype.f')]
+
+ def test_asterisk1(self):
+ foo = getattr(self.module, 'foo1')
+ assert_equal(foo(), b'123456789A12')
+
+ def test_asterisk2(self):
+ foo = getattr(self.module, 'foo2')
+ assert_equal(foo(2), b'12')
+ assert_equal(foo(12), b'123456789A12')
+ assert_equal(foo(24), b'123456789A123456789B')
+
+ def test_ftype(self):
+ ftype = self.module
+ ftype.foo()
+ assert_equal(ftype.data.a, 0)
+ ftype.data.a = 3
+ ftype.data.x = [1, 2, 3]
+ assert_equal(ftype.data.a, 3)
+ assert_array_equal(ftype.data.x,
+ np.array([1, 2, 3], dtype=np.float32))
+ ftype.data.x[1] = 45
+ assert_array_equal(ftype.data.x,
+ np.array([1, 45, 3], dtype=np.float32))
+
+ # TODO: implement test methods for other example Fortran codes
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2cmap.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2cmap.py
new file mode 100644
index 00000000..d2967e4f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2cmap.py
@@ -0,0 +1,15 @@
+from . import util
+import numpy as np
+
+class TestF2Cmap(util.F2PyTest):
+ sources = [
+ util.getpath("tests", "src", "f2cmap", "isoFortranEnvMap.f90"),
+ util.getpath("tests", "src", "f2cmap", ".f2py_f2cmap")
+ ]
+
+ # gh-15095
+ def test_long_long_map(self):
+ inp = np.ones(3)
+ out = self.module.func1(inp)
+ exp_out = 3
+ assert out == exp_out
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2py2e.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2py2e.py
new file mode 100644
index 00000000..2c10f046
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_f2py2e.py
@@ -0,0 +1,769 @@
+import textwrap, re, sys, subprocess, shlex
+from pathlib import Path
+from collections import namedtuple
+
+import pytest
+
+from . import util
+from numpy.f2py.f2py2e import main as f2pycli
+
+#########################
+# CLI utils and classes #
+#########################
+
+PPaths = namedtuple("PPaths", "finp, f90inp, pyf, wrap77, wrap90, cmodf")
+
+
+def get_io_paths(fname_inp, mname="untitled"):
+ """Takes in a temporary file for testing and returns the expected output and input paths
+
+ Here expected output is essentially one of any of the possible generated
+ files.
+
+ ..note::
+
+ Since this does not actually run f2py, none of these are guaranteed to
+ exist, and module names are typically incorrect
+
+ Parameters
+ ----------
+ fname_inp : str
+ The input filename
+ mname : str, optional
+ The name of the module, untitled by default
+
+ Returns
+ -------
+ genp : NamedTuple PPaths
+ The possible paths which are generated, not all of which exist
+ """
+ bpath = Path(fname_inp)
+ return PPaths(
+ finp=bpath.with_suffix(".f"),
+ f90inp=bpath.with_suffix(".f90"),
+ pyf=bpath.with_suffix(".pyf"),
+ wrap77=bpath.with_name(f"{mname}-f2pywrappers.f"),
+ wrap90=bpath.with_name(f"{mname}-f2pywrappers2.f90"),
+ cmodf=bpath.with_name(f"{mname}module.c"),
+ )
+
+
+##############
+# CLI Fixtures and Tests #
+#############
+
+
+@pytest.fixture(scope="session")
+def hello_world_f90(tmpdir_factory):
+ """Generates a single f90 file for testing"""
+ fdat = util.getpath("tests", "src", "cli", "hiworld.f90").read_text()
+ fn = tmpdir_factory.getbasetemp() / "hello.f90"
+ fn.write_text(fdat, encoding="ascii")
+ return fn
+
+
+@pytest.fixture(scope="session")
+def hello_world_f77(tmpdir_factory):
+ """Generates a single f77 file for testing"""
+ fdat = util.getpath("tests", "src", "cli", "hi77.f").read_text()
+ fn = tmpdir_factory.getbasetemp() / "hello.f"
+ fn.write_text(fdat, encoding="ascii")
+ return fn
+
+
+@pytest.fixture(scope="session")
+def retreal_f77(tmpdir_factory):
+ """Generates a single f77 file for testing"""
+ fdat = util.getpath("tests", "src", "return_real", "foo77.f").read_text()
+ fn = tmpdir_factory.getbasetemp() / "foo.f"
+ fn.write_text(fdat, encoding="ascii")
+ return fn
+
+@pytest.fixture(scope="session")
+def f2cmap_f90(tmpdir_factory):
+ """Generates a single f90 file for testing"""
+ fdat = util.getpath("tests", "src", "f2cmap", "isoFortranEnvMap.f90").read_text()
+ f2cmap = util.getpath("tests", "src", "f2cmap", ".f2py_f2cmap").read_text()
+ fn = tmpdir_factory.getbasetemp() / "f2cmap.f90"
+ fmap = tmpdir_factory.getbasetemp() / "mapfile"
+ fn.write_text(fdat, encoding="ascii")
+ fmap.write_text(f2cmap, encoding="ascii")
+ return fn
+
+
+def test_gen_pyf(capfd, hello_world_f90, monkeypatch):
+ """Ensures that a signature file is generated via the CLI
+ CLI :: -h
+ """
+ ipath = Path(hello_world_f90)
+ opath = Path(hello_world_f90).stem + ".pyf"
+ monkeypatch.setattr(sys, "argv", f'f2py -h {opath} {ipath}'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli() # Generate wrappers
+ out, _ = capfd.readouterr()
+ assert "Saving signatures to file" in out
+ assert Path(f'{opath}').exists()
+
+
+def test_gen_pyf_stdout(capfd, hello_world_f90, monkeypatch):
+ """Ensures that a signature file can be dumped to stdout
+ CLI :: -h
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -h stdout {ipath}'.split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Saving signatures to file" in out
+ assert "function hi() ! in " in out
+
+
+def test_gen_pyf_no_overwrite(capfd, hello_world_f90, monkeypatch):
+ """Ensures that the CLI refuses to overwrite signature files
+ CLI :: -h without --overwrite-signature
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -h faker.pyf {ipath}'.split())
+
+ with util.switchdir(ipath.parent):
+ Path("faker.pyf").write_text("Fake news", encoding="ascii")
+ with pytest.raises(SystemExit):
+ f2pycli() # Refuse to overwrite
+ _, err = capfd.readouterr()
+ assert "Use --overwrite-signature to overwrite" in err
+
+
+@pytest.mark.xfail
+def test_f2py_skip(capfd, retreal_f77, monkeypatch):
+ """Tests that functions can be skipped
+ CLI :: skip:
+ """
+ foutl = get_io_paths(retreal_f77, mname="test")
+ ipath = foutl.finp
+ toskip = "t0 t4 t8 sd s8 s4"
+ remaining = "td s0"
+ monkeypatch.setattr(
+ sys, "argv",
+ f'f2py {ipath} -m test skip: {toskip}'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, err = capfd.readouterr()
+ for skey in toskip.split():
+ assert (
+ f'buildmodule: Could not found the body of interfaced routine "{skey}". Skipping.'
+ in err)
+ for rkey in remaining.split():
+ assert f'Constructing wrapper function "{rkey}"' in out
+
+
+def test_f2py_only(capfd, retreal_f77, monkeypatch):
+ """Test that functions can be kept by only:
+ CLI :: only:
+ """
+ foutl = get_io_paths(retreal_f77, mname="test")
+ ipath = foutl.finp
+ toskip = "t0 t4 t8 sd s8 s4"
+ tokeep = "td s0"
+ monkeypatch.setattr(
+ sys, "argv",
+ f'f2py {ipath} -m test only: {tokeep}'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, err = capfd.readouterr()
+ for skey in toskip.split():
+ assert (
+ f'buildmodule: Could not find the body of interfaced routine "{skey}". Skipping.'
+ in err)
+ for rkey in tokeep.split():
+ assert f'Constructing wrapper function "{rkey}"' in out
+
+
+def test_file_processing_switch(capfd, hello_world_f90, retreal_f77,
+ monkeypatch):
+ """Tests that it is possible to return to file processing mode
+ CLI :: :
+ BUG: numpy-gh #20520
+ """
+ foutl = get_io_paths(retreal_f77, mname="test")
+ ipath = foutl.finp
+ toskip = "t0 t4 t8 sd s8 s4"
+ ipath2 = Path(hello_world_f90)
+ tokeep = "td s0 hi" # hi is in ipath2
+ mname = "blah"
+ monkeypatch.setattr(
+ sys,
+ "argv",
+ f'f2py {ipath} -m {mname} only: {tokeep} : {ipath2}'.split(
+ ),
+ )
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, err = capfd.readouterr()
+ for skey in toskip.split():
+ assert (
+ f'buildmodule: Could not find the body of interfaced routine "{skey}". Skipping.'
+ in err)
+ for rkey in tokeep.split():
+ assert f'Constructing wrapper function "{rkey}"' in out
+
+
+def test_mod_gen_f77(capfd, hello_world_f90, monkeypatch):
+ """Checks the generation of files based on a module name
+ CLI :: -m
+ """
+ MNAME = "hi"
+ foutl = get_io_paths(hello_world_f90, mname=MNAME)
+ ipath = foutl.f90inp
+ monkeypatch.setattr(sys, "argv", f'f2py {ipath} -m {MNAME}'.split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+
+ # Always generate C module
+ assert Path.exists(foutl.cmodf)
+ # File contains a function, check for F77 wrappers
+ assert Path.exists(foutl.wrap77)
+
+
+def test_lower_cmod(capfd, hello_world_f77, monkeypatch):
+ """Lowers cases by flag or when -h is present
+
+ CLI :: --[no-]lower
+ """
+ foutl = get_io_paths(hello_world_f77, mname="test")
+ ipath = foutl.finp
+ capshi = re.compile(r"HI\(\)")
+ capslo = re.compile(r"hi\(\)")
+ # Case I: --lower is passed
+ monkeypatch.setattr(sys, "argv", f'f2py {ipath} -m test --lower'.split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert capslo.search(out) is not None
+ assert capshi.search(out) is None
+ # Case II: --no-lower is passed
+ monkeypatch.setattr(sys, "argv",
+ f'f2py {ipath} -m test --no-lower'.split())
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert capslo.search(out) is None
+ assert capshi.search(out) is not None
+
+
+def test_lower_sig(capfd, hello_world_f77, monkeypatch):
+ """Lowers cases in signature files by flag or when -h is present
+
+ CLI :: --[no-]lower -h
+ """
+ foutl = get_io_paths(hello_world_f77, mname="test")
+ ipath = foutl.finp
+ # Signature files
+ capshi = re.compile(r"Block: HI")
+ capslo = re.compile(r"Block: hi")
+ # Case I: --lower is implied by -h
+ # TODO: Clean up to prevent passing --overwrite-signature
+ monkeypatch.setattr(
+ sys,
+ "argv",
+ f'f2py {ipath} -h {foutl.pyf} -m test --overwrite-signature'.split(),
+ )
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert capslo.search(out) is not None
+ assert capshi.search(out) is None
+
+ # Case II: --no-lower overrides -h
+ monkeypatch.setattr(
+ sys,
+ "argv",
+ f'f2py {ipath} -h {foutl.pyf} -m test --overwrite-signature --no-lower'
+ .split(),
+ )
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert capslo.search(out) is None
+ assert capshi.search(out) is not None
+
+
+def test_build_dir(capfd, hello_world_f90, monkeypatch):
+ """Ensures that the build directory can be specified
+
+ CLI :: --build-dir
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ odir = "tttmp"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --build-dir {odir}'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert f"Wrote C/API module \"{mname}\"" in out
+
+
+def test_overwrite(capfd, hello_world_f90, monkeypatch):
+ """Ensures that the build directory can be specified
+
+ CLI :: --overwrite-signature
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(
+ sys, "argv",
+ f'f2py -h faker.pyf {ipath} --overwrite-signature'.split())
+
+ with util.switchdir(ipath.parent):
+ Path("faker.pyf").write_text("Fake news", encoding="ascii")
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Saving signatures to file" in out
+
+
+def test_latexdoc(capfd, hello_world_f90, monkeypatch):
+ """Ensures that TeX documentation is written out
+
+ CLI :: --latex-doc
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --latex-doc'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Documentation is saved to file" in out
+ with Path(f"{mname}module.tex").open() as otex:
+ assert "\\documentclass" in otex.read()
+
+
+def test_nolatexdoc(capfd, hello_world_f90, monkeypatch):
+ """Ensures that TeX documentation is written out
+
+ CLI :: --no-latex-doc
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --no-latex-doc'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Documentation is saved to file" not in out
+
+
+def test_shortlatex(capfd, hello_world_f90, monkeypatch):
+ """Ensures that truncated documentation is written out
+
+ TODO: Test to ensure this has no effect without --latex-doc
+ CLI :: --latex-doc --short-latex
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(
+ sys,
+ "argv",
+ f'f2py -m {mname} {ipath} --latex-doc --short-latex'.split(),
+ )
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Documentation is saved to file" in out
+ with Path(f"./{mname}module.tex").open() as otex:
+ assert "\\documentclass" not in otex.read()
+
+
+def test_restdoc(capfd, hello_world_f90, monkeypatch):
+ """Ensures that RsT documentation is written out
+
+ CLI :: --rest-doc
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --rest-doc'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "ReST Documentation is saved to file" in out
+ with Path(f"./{mname}module.rest").open() as orst:
+ assert r".. -*- rest -*-" in orst.read()
+
+
+def test_norestexdoc(capfd, hello_world_f90, monkeypatch):
+ """Ensures that TeX documentation is written out
+
+ CLI :: --no-rest-doc
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --no-rest-doc'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "ReST Documentation is saved to file" not in out
+
+
+def test_debugcapi(capfd, hello_world_f90, monkeypatch):
+ """Ensures that debugging wrappers are written
+
+ CLI :: --debug-capi
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --debug-capi'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ with Path(f"./{mname}module.c").open() as ocmod:
+ assert r"#define DEBUGCFUNCS" in ocmod.read()
+
+
+@pytest.mark.xfail(reason="Consistently fails on CI.")
+def test_debugcapi_bld(hello_world_f90, monkeypatch):
+ """Ensures that debugging wrappers work
+
+ CLI :: --debug-capi -c
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} -c --debug-capi'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ cmd_run = shlex.split("python3 -c \"import blah; blah.hi()\"")
+ rout = subprocess.run(cmd_run, capture_output=True, encoding='UTF-8')
+ eout = ' Hello World\n'
+ eerr = textwrap.dedent("""\
+debug-capi:Python C/API function blah.hi()
+debug-capi:float hi=:output,hidden,scalar
+debug-capi:hi=0
+debug-capi:Fortran subroutine `f2pywraphi(&hi)'
+debug-capi:hi=0
+debug-capi:Building return value.
+debug-capi:Python C/API function blah.hi: successful.
+debug-capi:Freeing memory.
+ """)
+ assert rout.stdout == eout
+ assert rout.stderr == eerr
+
+
+def test_wrapfunc_def(capfd, hello_world_f90, monkeypatch):
+ """Ensures that fortran subroutine wrappers for F77 are included by default
+
+ CLI :: --[no]-wrap-functions
+ """
+ # Implied
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv", f'f2py -m {mname} {ipath}'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert r"Fortran 77 wrappers are saved to" in out
+
+ # Explicit
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --wrap-functions'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert r"Fortran 77 wrappers are saved to" in out
+
+
+def test_nowrapfunc(capfd, hello_world_f90, monkeypatch):
+ """Ensures that fortran subroutine wrappers for F77 can be disabled
+
+ CLI :: --no-wrap-functions
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(sys, "argv",
+ f'f2py -m {mname} {ipath} --no-wrap-functions'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert r"Fortran 77 wrappers are saved to" not in out
+
+
+def test_inclheader(capfd, hello_world_f90, monkeypatch):
+ """Add to the include directories
+
+ CLI :: -include
+ TODO: Document this in the help string
+ """
+ ipath = Path(hello_world_f90)
+ mname = "blah"
+ monkeypatch.setattr(
+ sys,
+ "argv",
+ f'f2py -m {mname} {ipath} -include<stdbool.h> -include<stdio.h> '.
+ split(),
+ )
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ with Path(f"./{mname}module.c").open() as ocmod:
+ ocmr = ocmod.read()
+ assert "#include <stdbool.h>" in ocmr
+ assert "#include <stdio.h>" in ocmr
+
+
+def test_inclpath():
+ """Add to the include directories
+
+ CLI :: --include-paths
+ """
+ # TODO: populate
+ pass
+
+
+def test_hlink():
+ """Add to the include directories
+
+ CLI :: --help-link
+ """
+ # TODO: populate
+ pass
+
+
+def test_f2cmap(capfd, f2cmap_f90, monkeypatch):
+ """Check that Fortran-to-Python KIND specs can be passed
+
+ CLI :: --f2cmap
+ """
+ ipath = Path(f2cmap_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} --f2cmap mapfile'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "Reading f2cmap from 'mapfile' ..." in out
+ assert "Mapping \"real(kind=real32)\" to \"float\"" in out
+ assert "Mapping \"real(kind=real64)\" to \"double\"" in out
+ assert "Mapping \"integer(kind=int64)\" to \"long_long\"" in out
+ assert "Successfully applied user defined f2cmap changes" in out
+
+
+def test_quiet(capfd, hello_world_f90, monkeypatch):
+ """Reduce verbosity
+
+ CLI :: --quiet
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} --quiet'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert len(out) == 0
+
+
+def test_verbose(capfd, hello_world_f90, monkeypatch):
+ """Increase verbosity
+
+ CLI :: --verbose
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} --verbose'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ assert "analyzeline" in out
+
+
+def test_version(capfd, monkeypatch):
+ """Ensure version
+
+ CLI :: -v
+ """
+ monkeypatch.setattr(sys, "argv", 'f2py -v'.split())
+ # TODO: f2py2e should not call sys.exit() after printing the version
+ with pytest.raises(SystemExit):
+ f2pycli()
+ out, _ = capfd.readouterr()
+ import numpy as np
+ assert np.__version__ == out.strip()
+
+
+@pytest.mark.xfail(reason="Consistently fails on CI.")
+def test_npdistop(hello_world_f90, monkeypatch):
+ """
+ CLI :: -c
+ """
+ ipath = Path(hello_world_f90)
+ monkeypatch.setattr(sys, "argv", f'f2py -m blah {ipath} -c'.split())
+
+ with util.switchdir(ipath.parent):
+ f2pycli()
+ cmd_run = shlex.split("python -c \"import blah; blah.hi()\"")
+ rout = subprocess.run(cmd_run, capture_output=True, encoding='UTF-8')
+ eout = ' Hello World\n'
+ assert rout.stdout == eout
+
+
+# Numpy distutils flags
+# TODO: These should be tested separately
+
+
+def test_npd_fcompiler():
+ """
+ CLI :: -c --fcompiler
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_compiler():
+ """
+ CLI :: -c --compiler
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_help_fcompiler():
+ """
+ CLI :: -c --help-fcompiler
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_f77exec():
+ """
+ CLI :: -c --f77exec
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_f90exec():
+ """
+ CLI :: -c --f90exec
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_f77flags():
+ """
+ CLI :: -c --f77flags
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_f90flags():
+ """
+ CLI :: -c --f90flags
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_opt():
+ """
+ CLI :: -c --opt
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_arch():
+ """
+ CLI :: -c --arch
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_noopt():
+ """
+ CLI :: -c --noopt
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_noarch():
+ """
+ CLI :: -c --noarch
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_debug():
+ """
+ CLI :: -c --debug
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_link_auto():
+ """
+ CLI :: -c --link-<resource>
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_lib():
+ """
+ CLI :: -c -L/path/to/lib/ -l<libname>
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_define():
+ """
+ CLI :: -D<define>
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_undefine():
+ """
+ CLI :: -U<name>
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_incl():
+ """
+ CLI :: -I/path/to/include/
+ """
+ # TODO: populate
+ pass
+
+
+def test_npd_linker():
+ """
+ CLI :: <filename>.o <filename>.so <filename>.a
+ """
+ # TODO: populate
+ pass
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_kind.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_kind.py
new file mode 100644
index 00000000..f0cb61fb
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_kind.py
@@ -0,0 +1,26 @@
+import os
+import pytest
+
+from numpy.f2py.crackfortran import (
+ _selected_int_kind_func as selected_int_kind,
+ _selected_real_kind_func as selected_real_kind,
+)
+from . import util
+
+
+class TestKind(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "kind", "foo.f90")]
+
+ def test_all(self):
+ selectedrealkind = self.module.selectedrealkind
+ selectedintkind = self.module.selectedintkind
+
+ for i in range(40):
+ assert selectedintkind(i) == selected_int_kind(
+ i
+ ), f"selectedintkind({i}): expected {selected_int_kind(i)!r} but got {selectedintkind(i)!r}"
+
+ for i in range(20):
+ assert selectedrealkind(i) == selected_real_kind(
+ i
+ ), f"selectedrealkind({i}): expected {selected_real_kind(i)!r} but got {selectedrealkind(i)!r}"
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_mixed.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_mixed.py
new file mode 100644
index 00000000..80653b7d
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_mixed.py
@@ -0,0 +1,33 @@
+import os
+import textwrap
+import pytest
+
+from numpy.testing import IS_PYPY
+from . import util
+
+
+class TestMixed(util.F2PyTest):
+ sources = [
+ util.getpath("tests", "src", "mixed", "foo.f"),
+ util.getpath("tests", "src", "mixed", "foo_fixed.f90"),
+ util.getpath("tests", "src", "mixed", "foo_free.f90"),
+ ]
+
+ def test_all(self):
+ assert self.module.bar11() == 11
+ assert self.module.foo_fixed.bar12() == 12
+ assert self.module.foo_free.bar13() == 13
+
+ @pytest.mark.xfail(IS_PYPY,
+ reason="PyPy cannot modify tp_doc after PyType_Ready")
+ def test_docstring(self):
+ expected = textwrap.dedent("""\
+ a = bar11()
+
+ Wrapper for ``bar11``.
+
+ Returns
+ -------
+ a : int
+ """)
+ assert self.module.bar11.__doc__ == expected
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_module_doc.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_module_doc.py
new file mode 100644
index 00000000..28822d40
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_module_doc.py
@@ -0,0 +1,27 @@
+import os
+import sys
+import pytest
+import textwrap
+
+from . import util
+from numpy.testing import IS_PYPY
+
+
+class TestModuleDocString(util.F2PyTest):
+ sources = [
+ util.getpath("tests", "src", "module_data",
+ "module_data_docstring.f90")
+ ]
+
+ @pytest.mark.skipif(sys.platform == "win32",
+ reason="Fails with MinGW64 Gfortran (Issue #9673)")
+ @pytest.mark.xfail(IS_PYPY,
+ reason="PyPy cannot modify tp_doc after PyType_Ready")
+ def test_module_docstring(self):
+ assert self.module.mod.__doc__ == textwrap.dedent("""\
+ i : 'i'-scalar
+ x : 'i'-array(4)
+ a : 'f'-array(2,3)
+ b : 'f'-array(-1,-1), not allocated\x00
+ foo()\n
+ Wrapper for ``foo``.\n\n""")
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_parameter.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_parameter.py
new file mode 100644
index 00000000..2f620eaa
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_parameter.py
@@ -0,0 +1,112 @@
+import os
+import pytest
+
+import numpy as np
+
+from . import util
+
+
+class TestParameters(util.F2PyTest):
+ # Check that intent(in out) translates as intent(inout)
+ sources = [
+ util.getpath("tests", "src", "parameter", "constant_real.f90"),
+ util.getpath("tests", "src", "parameter", "constant_integer.f90"),
+ util.getpath("tests", "src", "parameter", "constant_both.f90"),
+ util.getpath("tests", "src", "parameter", "constant_compound.f90"),
+ util.getpath("tests", "src", "parameter", "constant_non_compound.f90"),
+ ]
+
+ @pytest.mark.slow
+ def test_constant_real_single(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.float32)[::2]
+ pytest.raises(ValueError, self.module.foo_single, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.float32)
+ self.module.foo_single(x)
+ assert np.allclose(x, [0 + 1 + 2 * 3, 1, 2])
+
+ @pytest.mark.slow
+ def test_constant_real_double(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.float64)[::2]
+ pytest.raises(ValueError, self.module.foo_double, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.float64)
+ self.module.foo_double(x)
+ assert np.allclose(x, [0 + 1 + 2 * 3, 1, 2])
+
+ @pytest.mark.slow
+ def test_constant_compound_int(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.int32)[::2]
+ pytest.raises(ValueError, self.module.foo_compound_int, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.int32)
+ self.module.foo_compound_int(x)
+ assert np.allclose(x, [0 + 1 + 2 * 6, 1, 2])
+
+ @pytest.mark.slow
+ def test_constant_non_compound_int(self):
+ # check values
+ x = np.arange(4, dtype=np.int32)
+ self.module.foo_non_compound_int(x)
+ assert np.allclose(x, [0 + 1 + 2 + 3 * 4, 1, 2, 3])
+
+ @pytest.mark.slow
+ def test_constant_integer_int(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.int32)[::2]
+ pytest.raises(ValueError, self.module.foo_int, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.int32)
+ self.module.foo_int(x)
+ assert np.allclose(x, [0 + 1 + 2 * 3, 1, 2])
+
+ @pytest.mark.slow
+ def test_constant_integer_long(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.int64)[::2]
+ pytest.raises(ValueError, self.module.foo_long, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.int64)
+ self.module.foo_long(x)
+ assert np.allclose(x, [0 + 1 + 2 * 3, 1, 2])
+
+ @pytest.mark.slow
+ def test_constant_both(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.float64)[::2]
+ pytest.raises(ValueError, self.module.foo, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.float64)
+ self.module.foo(x)
+ assert np.allclose(x, [0 + 1 * 3 * 3 + 2 * 3 * 3, 1 * 3, 2 * 3])
+
+ @pytest.mark.slow
+ def test_constant_no(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.float64)[::2]
+ pytest.raises(ValueError, self.module.foo_no, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.float64)
+ self.module.foo_no(x)
+ assert np.allclose(x, [0 + 1 * 3 * 3 + 2 * 3 * 3, 1 * 3, 2 * 3])
+
+ @pytest.mark.slow
+ def test_constant_sum(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.float64)[::2]
+ pytest.raises(ValueError, self.module.foo_sum, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.float64)
+ self.module.foo_sum(x)
+ assert np.allclose(x, [0 + 1 * 3 * 3 + 2 * 3 * 3, 1 * 3, 2 * 3])
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_quoted_character.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_quoted_character.py
new file mode 100644
index 00000000..82671cd8
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_quoted_character.py
@@ -0,0 +1,16 @@
+"""See https://github.com/numpy/numpy/pull/10676.
+
+"""
+import sys
+import pytest
+
+from . import util
+
+
+class TestQuotedCharacter(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "quoted_character", "foo.f")]
+
+ @pytest.mark.skipif(sys.platform == "win32",
+ reason="Fails with MinGW64 Gfortran (Issue #9673)")
+ def test_quoted_character(self):
+ assert self.module.foo() == (b"'", b'"', b";", b"!", b"(", b")")
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_regression.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_regression.py
new file mode 100644
index 00000000..044f952f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_regression.py
@@ -0,0 +1,66 @@
+import os
+import pytest
+
+import numpy as np
+
+from . import util
+
+
+class TestIntentInOut(util.F2PyTest):
+ # Check that intent(in out) translates as intent(inout)
+ sources = [util.getpath("tests", "src", "regression", "inout.f90")]
+
+ @pytest.mark.slow
+ def test_inout(self):
+ # non-contiguous should raise error
+ x = np.arange(6, dtype=np.float32)[::2]
+ pytest.raises(ValueError, self.module.foo, x)
+
+ # check values with contiguous array
+ x = np.arange(3, dtype=np.float32)
+ self.module.foo(x)
+ assert np.allclose(x, [3, 1, 2])
+
+
+class TestNegativeBounds(util.F2PyTest):
+ # Check that negative bounds work correctly
+ sources = [util.getpath("tests", "src", "negative_bounds", "issue_20853.f90")]
+
+ @pytest.mark.slow
+ def test_negbound(self):
+ xvec = np.arange(12)
+ xlow = -6
+ xhigh = 4
+ # Calculate the upper bound,
+ # Keeping the 1 index in mind
+ def ubound(xl, xh):
+ return xh - xl + 1
+ rval = self.module.foo(is_=xlow, ie_=xhigh,
+ arr=xvec[:ubound(xlow, xhigh)])
+ expval = np.arange(11, dtype = np.float32)
+ assert np.allclose(rval, expval)
+
+
+class TestNumpyVersionAttribute(util.F2PyTest):
+ # Check that th attribute __f2py_numpy_version__ is present
+ # in the compiled module and that has the value np.__version__.
+ sources = [util.getpath("tests", "src", "regression", "inout.f90")]
+
+ @pytest.mark.slow
+ def test_numpy_version_attribute(self):
+
+ # Check that self.module has an attribute named "__f2py_numpy_version__"
+ assert hasattr(self.module, "__f2py_numpy_version__")
+
+ # Check that the attribute __f2py_numpy_version__ is a string
+ assert isinstance(self.module.__f2py_numpy_version__, str)
+
+ # Check that __f2py_numpy_version__ has the value numpy.__version__
+ assert np.__version__ == self.module.__f2py_numpy_version__
+
+
+def test_include_path():
+ incdir = np.f2py.get_include()
+ fnames_in_dir = os.listdir(incdir)
+ for fname in ("fortranobject.c", "fortranobject.h"):
+ assert fname in fnames_in_dir
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_character.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_character.py
new file mode 100644
index 00000000..36c1f10f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_character.py
@@ -0,0 +1,45 @@
+import pytest
+
+from numpy import array
+from . import util
+import platform
+
+IS_S390X = platform.machine() == "s390x"
+
+
+class TestReturnCharacter(util.F2PyTest):
+ def check_function(self, t, tname):
+ if tname in ["t0", "t1", "s0", "s1"]:
+ assert t("23") == b"2"
+ r = t("ab")
+ assert r == b"a"
+ r = t(array("ab"))
+ assert r == b"a"
+ r = t(array(77, "u1"))
+ assert r == b"M"
+ elif tname in ["ts", "ss"]:
+ assert t(23) == b"23"
+ assert t("123456789abcdef") == b"123456789a"
+ elif tname in ["t5", "s5"]:
+ assert t(23) == b"23"
+ assert t("ab") == b"ab"
+ assert t("123456789abcdef") == b"12345"
+ else:
+ raise NotImplementedError
+
+
+class TestFReturnCharacter(TestReturnCharacter):
+ sources = [
+ util.getpath("tests", "src", "return_character", "foo77.f"),
+ util.getpath("tests", "src", "return_character", "foo90.f90"),
+ ]
+
+ @pytest.mark.xfail(IS_S390X, reason="callback returns ' '")
+ @pytest.mark.parametrize("name", "t0,t1,t5,s0,s1,s5,ss".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+ @pytest.mark.xfail(IS_S390X, reason="callback returns ' '")
+ @pytest.mark.parametrize("name", "t0,t1,t5,ts,s0,s1,s5,ss".split(","))
+ def test_all_f90(self, name):
+ self.check_function(getattr(self.module.f90_return_char, name), name)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_complex.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_complex.py
new file mode 100644
index 00000000..9df79632
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_complex.py
@@ -0,0 +1,65 @@
+import pytest
+
+from numpy import array
+from . import util
+
+
+class TestReturnComplex(util.F2PyTest):
+ def check_function(self, t, tname):
+ if tname in ["t0", "t8", "s0", "s8"]:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234j) - 234.0j) <= err
+ assert abs(t(234.6) - 234.6) <= err
+ assert abs(t(234) - 234.0) <= err
+ assert abs(t(234.6 + 3j) - (234.6 + 3j)) <= err
+ # assert abs(t('234')-234.)<=err
+ # assert abs(t('234.6')-234.6)<=err
+ assert abs(t(-234) + 234.0) <= err
+ assert abs(t([234]) - 234.0) <= err
+ assert abs(t((234, )) - 234.0) <= err
+ assert abs(t(array(234)) - 234.0) <= err
+ assert abs(t(array(23 + 4j, "F")) - (23 + 4j)) <= err
+ assert abs(t(array([234])) - 234.0) <= err
+ assert abs(t(array([[234]])) - 234.0) <= err
+ assert abs(t(array([234]).astype("b")) + 22.0) <= err
+ assert abs(t(array([234], "h")) - 234.0) <= err
+ assert abs(t(array([234], "i")) - 234.0) <= err
+ assert abs(t(array([234], "l")) - 234.0) <= err
+ assert abs(t(array([234], "q")) - 234.0) <= err
+ assert abs(t(array([234], "f")) - 234.0) <= err
+ assert abs(t(array([234], "d")) - 234.0) <= err
+ assert abs(t(array([234 + 3j], "F")) - (234 + 3j)) <= err
+ assert abs(t(array([234], "D")) - 234.0) <= err
+
+ # pytest.raises(TypeError, t, array([234], 'a1'))
+ pytest.raises(TypeError, t, "abc")
+
+ pytest.raises(IndexError, t, [])
+ pytest.raises(IndexError, t, ())
+
+ pytest.raises(TypeError, t, t)
+ pytest.raises(TypeError, t, {})
+
+ try:
+ r = t(10**400)
+ assert repr(r) in ["(inf+0j)", "(Infinity+0j)"]
+ except OverflowError:
+ pass
+
+
+class TestFReturnComplex(TestReturnComplex):
+ sources = [
+ util.getpath("tests", "src", "return_complex", "foo77.f"),
+ util.getpath("tests", "src", "return_complex", "foo90.f90"),
+ ]
+
+ @pytest.mark.parametrize("name", "t0,t8,t16,td,s0,s8,s16,sd".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+ @pytest.mark.parametrize("name", "t0,t8,t16,td,s0,s8,s16,sd".split(","))
+ def test_all_f90(self, name):
+ self.check_function(getattr(self.module.f90_return_complex, name),
+ name)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_integer.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_integer.py
new file mode 100644
index 00000000..a43c677f
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_integer.py
@@ -0,0 +1,55 @@
+import pytest
+
+from numpy import array
+from . import util
+
+
+class TestReturnInteger(util.F2PyTest):
+ def check_function(self, t, tname):
+ assert t(123) == 123
+ assert t(123.6) == 123
+ assert t("123") == 123
+ assert t(-123) == -123
+ assert t([123]) == 123
+ assert t((123, )) == 123
+ assert t(array(123)) == 123
+ assert t(array([123])) == 123
+ assert t(array([[123]])) == 123
+ assert t(array([123], "b")) == 123
+ assert t(array([123], "h")) == 123
+ assert t(array([123], "i")) == 123
+ assert t(array([123], "l")) == 123
+ assert t(array([123], "B")) == 123
+ assert t(array([123], "f")) == 123
+ assert t(array([123], "d")) == 123
+
+ # pytest.raises(ValueError, t, array([123],'S3'))
+ pytest.raises(ValueError, t, "abc")
+
+ pytest.raises(IndexError, t, [])
+ pytest.raises(IndexError, t, ())
+
+ pytest.raises(Exception, t, t)
+ pytest.raises(Exception, t, {})
+
+ if tname in ["t8", "s8"]:
+ pytest.raises(OverflowError, t, 100000000000000000000000)
+ pytest.raises(OverflowError, t, 10000000011111111111111.23)
+
+
+class TestFReturnInteger(TestReturnInteger):
+ sources = [
+ util.getpath("tests", "src", "return_integer", "foo77.f"),
+ util.getpath("tests", "src", "return_integer", "foo90.f90"),
+ ]
+
+ @pytest.mark.parametrize("name",
+ "t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+ @pytest.mark.parametrize("name",
+ "t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","))
+ def test_all_f90(self, name):
+ self.check_function(getattr(self.module.f90_return_integer, name),
+ name)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_logical.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_logical.py
new file mode 100644
index 00000000..92fb902a
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_logical.py
@@ -0,0 +1,64 @@
+import pytest
+
+from numpy import array
+from . import util
+
+
+class TestReturnLogical(util.F2PyTest):
+ def check_function(self, t):
+ assert t(True) == 1
+ assert t(False) == 0
+ assert t(0) == 0
+ assert t(None) == 0
+ assert t(0.0) == 0
+ assert t(0j) == 0
+ assert t(1j) == 1
+ assert t(234) == 1
+ assert t(234.6) == 1
+ assert t(234.6 + 3j) == 1
+ assert t("234") == 1
+ assert t("aaa") == 1
+ assert t("") == 0
+ assert t([]) == 0
+ assert t(()) == 0
+ assert t({}) == 0
+ assert t(t) == 1
+ assert t(-234) == 1
+ assert t(10**100) == 1
+ assert t([234]) == 1
+ assert t((234, )) == 1
+ assert t(array(234)) == 1
+ assert t(array([234])) == 1
+ assert t(array([[234]])) == 1
+ assert t(array([127], "b")) == 1
+ assert t(array([234], "h")) == 1
+ assert t(array([234], "i")) == 1
+ assert t(array([234], "l")) == 1
+ assert t(array([234], "f")) == 1
+ assert t(array([234], "d")) == 1
+ assert t(array([234 + 3j], "F")) == 1
+ assert t(array([234], "D")) == 1
+ assert t(array(0)) == 0
+ assert t(array([0])) == 0
+ assert t(array([[0]])) == 0
+ assert t(array([0j])) == 0
+ assert t(array([1])) == 1
+ pytest.raises(ValueError, t, array([0, 0]))
+
+
+class TestFReturnLogical(TestReturnLogical):
+ sources = [
+ util.getpath("tests", "src", "return_logical", "foo77.f"),
+ util.getpath("tests", "src", "return_logical", "foo90.f90"),
+ ]
+
+ @pytest.mark.slow
+ @pytest.mark.parametrize("name", "t0,t1,t2,t4,s0,s1,s2,s4".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name))
+
+ @pytest.mark.slow
+ @pytest.mark.parametrize("name",
+ "t0,t1,t2,t4,t8,s0,s1,s2,s4,s8".split(","))
+ def test_all_f90(self, name):
+ self.check_function(getattr(self.module.f90_return_logical, name))
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_real.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_real.py
new file mode 100644
index 00000000..9e76c151
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_return_real.py
@@ -0,0 +1,109 @@
+import platform
+import pytest
+import numpy as np
+
+from numpy import array
+from . import util
+
+
+class TestReturnReal(util.F2PyTest):
+ def check_function(self, t, tname):
+ if tname in ["t0", "t4", "s0", "s4"]:
+ err = 1e-5
+ else:
+ err = 0.0
+ assert abs(t(234) - 234.0) <= err
+ assert abs(t(234.6) - 234.6) <= err
+ assert abs(t("234") - 234) <= err
+ assert abs(t("234.6") - 234.6) <= err
+ assert abs(t(-234) + 234) <= err
+ assert abs(t([234]) - 234) <= err
+ assert abs(t((234, )) - 234.0) <= err
+ assert abs(t(array(234)) - 234.0) <= err
+ assert abs(t(array([234])) - 234.0) <= err
+ assert abs(t(array([[234]])) - 234.0) <= err
+ assert abs(t(array([234]).astype("b")) + 22) <= err
+ assert abs(t(array([234], "h")) - 234.0) <= err
+ assert abs(t(array([234], "i")) - 234.0) <= err
+ assert abs(t(array([234], "l")) - 234.0) <= err
+ assert abs(t(array([234], "B")) - 234.0) <= err
+ assert abs(t(array([234], "f")) - 234.0) <= err
+ assert abs(t(array([234], "d")) - 234.0) <= err
+ if tname in ["t0", "t4", "s0", "s4"]:
+ assert t(1e200) == t(1e300) # inf
+
+ # pytest.raises(ValueError, t, array([234], 'S1'))
+ pytest.raises(ValueError, t, "abc")
+
+ pytest.raises(IndexError, t, [])
+ pytest.raises(IndexError, t, ())
+
+ pytest.raises(Exception, t, t)
+ pytest.raises(Exception, t, {})
+
+ try:
+ r = t(10**400)
+ assert repr(r) in ["inf", "Infinity"]
+ except OverflowError:
+ pass
+
+
+@pytest.mark.skipif(
+ platform.system() == "Darwin",
+ reason="Prone to error when run with numpy/f2py/tests on mac os, "
+ "but not when run in isolation",
+)
+@pytest.mark.skipif(
+ np.dtype(np.intp).itemsize < 8,
+ reason="32-bit builds are buggy"
+)
+class TestCReturnReal(TestReturnReal):
+ suffix = ".pyf"
+ module_name = "c_ext_return_real"
+ code = """
+python module c_ext_return_real
+usercode \'\'\'
+float t4(float value) { return value; }
+void s4(float *t4, float value) { *t4 = value; }
+double t8(double value) { return value; }
+void s8(double *t8, double value) { *t8 = value; }
+\'\'\'
+interface
+ function t4(value)
+ real*4 intent(c) :: t4,value
+ end
+ function t8(value)
+ real*8 intent(c) :: t8,value
+ end
+ subroutine s4(t4,value)
+ intent(c) s4
+ real*4 intent(out) :: t4
+ real*4 intent(c) :: value
+ end
+ subroutine s8(t8,value)
+ intent(c) s8
+ real*8 intent(out) :: t8
+ real*8 intent(c) :: value
+ end
+end interface
+end python module c_ext_return_real
+ """
+
+ @pytest.mark.parametrize("name", "t4,t8,s4,s8".split(","))
+ def test_all(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+
+class TestFReturnReal(TestReturnReal):
+ sources = [
+ util.getpath("tests", "src", "return_real", "foo77.f"),
+ util.getpath("tests", "src", "return_real", "foo90.f90"),
+ ]
+
+ @pytest.mark.parametrize("name", "t0,t4,t8,td,s0,s4,s8,sd".split(","))
+ def test_all_f77(self, name):
+ self.check_function(getattr(self.module, name), name)
+
+ @pytest.mark.parametrize("name", "t0,t4,t8,td,s0,s4,s8,sd".split(","))
+ def test_all_f90(self, name):
+ self.check_function(getattr(self.module.f90_return_real, name), name)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_semicolon_split.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_semicolon_split.py
new file mode 100644
index 00000000..6d499046
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_semicolon_split.py
@@ -0,0 +1,74 @@
+import platform
+import pytest
+import numpy as np
+
+from . import util
+
+
+@pytest.mark.skipif(
+ platform.system() == "Darwin",
+ reason="Prone to error when run with numpy/f2py/tests on mac os, "
+ "but not when run in isolation",
+)
+@pytest.mark.skipif(
+ np.dtype(np.intp).itemsize < 8,
+ reason="32-bit builds are buggy"
+)
+class TestMultiline(util.F2PyTest):
+ suffix = ".pyf"
+ module_name = "multiline"
+ code = f"""
+python module {module_name}
+ usercode '''
+void foo(int* x) {{
+ char dummy = ';';
+ *x = 42;
+}}
+'''
+ interface
+ subroutine foo(x)
+ intent(c) foo
+ integer intent(out) :: x
+ end subroutine foo
+ end interface
+end python module {module_name}
+ """
+
+ def test_multiline(self):
+ assert self.module.foo() == 42
+
+
+@pytest.mark.skipif(
+ platform.system() == "Darwin",
+ reason="Prone to error when run with numpy/f2py/tests on mac os, "
+ "but not when run in isolation",
+)
+@pytest.mark.skipif(
+ np.dtype(np.intp).itemsize < 8,
+ reason="32-bit builds are buggy"
+)
+class TestCallstatement(util.F2PyTest):
+ suffix = ".pyf"
+ module_name = "callstatement"
+ code = f"""
+python module {module_name}
+ usercode '''
+void foo(int* x) {{
+}}
+'''
+ interface
+ subroutine foo(x)
+ intent(c) foo
+ integer intent(out) :: x
+ callprotoargument int*
+ callstatement {{ &
+ ; &
+ x = 42; &
+ }}
+ end subroutine foo
+ end interface
+end python module {module_name}
+ """
+
+ def test_callstatement(self):
+ assert self.module.foo() == 42
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_size.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_size.py
new file mode 100644
index 00000000..bd2c349d
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_size.py
@@ -0,0 +1,45 @@
+import os
+import pytest
+import numpy as np
+
+from . import util
+
+
+class TestSizeSumExample(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "size", "foo.f90")]
+
+ @pytest.mark.slow
+ def test_all(self):
+ r = self.module.foo([[]])
+ assert r == [0]
+
+ r = self.module.foo([[1, 2]])
+ assert r == [3]
+
+ r = self.module.foo([[1, 2], [3, 4]])
+ assert np.allclose(r, [3, 7])
+
+ r = self.module.foo([[1, 2], [3, 4], [5, 6]])
+ assert np.allclose(r, [3, 7, 11])
+
+ @pytest.mark.slow
+ def test_transpose(self):
+ r = self.module.trans([[]])
+ assert np.allclose(r.T, np.array([[]]))
+
+ r = self.module.trans([[1, 2]])
+ assert np.allclose(r, [[1.], [2.]])
+
+ r = self.module.trans([[1, 2, 3], [4, 5, 6]])
+ assert np.allclose(r, [[1, 4], [2, 5], [3, 6]])
+
+ @pytest.mark.slow
+ def test_flatten(self):
+ r = self.module.flatten([[]])
+ assert np.allclose(r, [])
+
+ r = self.module.flatten([[1, 2]])
+ assert np.allclose(r, [1, 2])
+
+ r = self.module.flatten([[1, 2, 3], [4, 5, 6]])
+ assert np.allclose(r, [1, 2, 3, 4, 5, 6])
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_string.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_string.py
new file mode 100644
index 00000000..9e937188
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_string.py
@@ -0,0 +1,100 @@
+import os
+import pytest
+import textwrap
+import numpy as np
+from . import util
+
+
+class TestString(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "char.f90")]
+
+ @pytest.mark.slow
+ def test_char(self):
+ strings = np.array(["ab", "cd", "ef"], dtype="c").T
+ inp, out = self.module.char_test.change_strings(
+ strings, strings.shape[1])
+ assert inp == pytest.approx(strings)
+ expected = strings.copy()
+ expected[1, :] = "AAA"
+ assert out == pytest.approx(expected)
+
+
+class TestDocStringArguments(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "string.f")]
+
+ def test_example(self):
+ a = np.array(b"123\0\0")
+ b = np.array(b"123\0\0")
+ c = np.array(b"123")
+ d = np.array(b"123")
+
+ self.module.foo(a, b, c, d)
+
+ assert a.tobytes() == b"123\0\0"
+ assert b.tobytes() == b"B23\0\0"
+ assert c.tobytes() == b"123"
+ assert d.tobytes() == b"D23"
+
+
+class TestFixedString(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "string", "fixed_string.f90")]
+
+ @staticmethod
+ def _sint(s, start=0, end=None):
+ """Return the content of a string buffer as integer value.
+
+ For example:
+ _sint('1234') -> 4321
+ _sint('123A') -> 17321
+ """
+ if isinstance(s, np.ndarray):
+ s = s.tobytes()
+ elif isinstance(s, str):
+ s = s.encode()
+ assert isinstance(s, bytes)
+ if end is None:
+ end = len(s)
+ i = 0
+ for j in range(start, min(end, len(s))):
+ i += s[j] * 10**j
+ return i
+
+ def _get_input(self, intent="in"):
+ if intent in ["in"]:
+ yield ""
+ yield "1"
+ yield "1234"
+ yield "12345"
+ yield b""
+ yield b"\0"
+ yield b"1"
+ yield b"\01"
+ yield b"1\0"
+ yield b"1234"
+ yield b"12345"
+ yield np.ndarray((), np.bytes_, buffer=b"") # array(b'', dtype='|S0')
+ yield np.array(b"") # array(b'', dtype='|S1')
+ yield np.array(b"\0")
+ yield np.array(b"1")
+ yield np.array(b"1\0")
+ yield np.array(b"\01")
+ yield np.array(b"1234")
+ yield np.array(b"123\0")
+ yield np.array(b"12345")
+
+ def test_intent_in(self):
+ for s in self._get_input():
+ r = self.module.test_in_bytes4(s)
+ # also checks that s is not changed inplace
+ expected = self._sint(s, end=4)
+ assert r == expected, s
+
+ def test_intent_inout(self):
+ for s in self._get_input(intent="inout"):
+ rest = self._sint(s, start=4)
+ r = self.module.test_inout_bytes4(s)
+ expected = self._sint(s, end=4)
+ assert r == expected
+
+ # check that the rest of input string is preserved
+ assert rest == self._sint(s, start=4)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_symbolic.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_symbolic.py
new file mode 100644
index 00000000..84527831
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_symbolic.py
@@ -0,0 +1,494 @@
+import pytest
+
+from numpy.f2py.symbolic import (
+ Expr,
+ Op,
+ ArithOp,
+ Language,
+ as_symbol,
+ as_number,
+ as_string,
+ as_array,
+ as_complex,
+ as_terms,
+ as_factors,
+ eliminate_quotes,
+ insert_quotes,
+ fromstring,
+ as_expr,
+ as_apply,
+ as_numer_denom,
+ as_ternary,
+ as_ref,
+ as_deref,
+ normalize,
+ as_eq,
+ as_ne,
+ as_lt,
+ as_gt,
+ as_le,
+ as_ge,
+)
+from . import util
+
+
+class TestSymbolic(util.F2PyTest):
+ def test_eliminate_quotes(self):
+ def worker(s):
+ r, d = eliminate_quotes(s)
+ s1 = insert_quotes(r, d)
+ assert s1 == s
+
+ for kind in ["", "mykind_"]:
+ worker(kind + '"1234" // "ABCD"')
+ worker(kind + '"1234" // ' + kind + '"ABCD"')
+ worker(kind + "\"1234\" // 'ABCD'")
+ worker(kind + '"1234" // ' + kind + "'ABCD'")
+ worker(kind + '"1\\"2\'AB\'34"')
+ worker("a = " + kind + "'1\\'2\"AB\"34'")
+
+ def test_sanity(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+
+ assert x.op == Op.SYMBOL
+ assert repr(x) == "Expr(Op.SYMBOL, 'x')"
+ assert x == x
+ assert x != y
+ assert hash(x) is not None
+
+ n = as_number(123)
+ m = as_number(456)
+ assert n.op == Op.INTEGER
+ assert repr(n) == "Expr(Op.INTEGER, (123, 4))"
+ assert n == n
+ assert n != m
+ assert hash(n) is not None
+
+ fn = as_number(12.3)
+ fm = as_number(45.6)
+ assert fn.op == Op.REAL
+ assert repr(fn) == "Expr(Op.REAL, (12.3, 4))"
+ assert fn == fn
+ assert fn != fm
+ assert hash(fn) is not None
+
+ c = as_complex(1, 2)
+ c2 = as_complex(3, 4)
+ assert c.op == Op.COMPLEX
+ assert repr(c) == ("Expr(Op.COMPLEX, (Expr(Op.INTEGER, (1, 4)),"
+ " Expr(Op.INTEGER, (2, 4))))")
+ assert c == c
+ assert c != c2
+ assert hash(c) is not None
+
+ s = as_string("'123'")
+ s2 = as_string('"ABC"')
+ assert s.op == Op.STRING
+ assert repr(s) == "Expr(Op.STRING, (\"'123'\", 1))", repr(s)
+ assert s == s
+ assert s != s2
+
+ a = as_array((n, m))
+ b = as_array((n, ))
+ assert a.op == Op.ARRAY
+ assert repr(a) == ("Expr(Op.ARRAY, (Expr(Op.INTEGER, (123, 4)),"
+ " Expr(Op.INTEGER, (456, 4))))")
+ assert a == a
+ assert a != b
+
+ t = as_terms(x)
+ u = as_terms(y)
+ assert t.op == Op.TERMS
+ assert repr(t) == "Expr(Op.TERMS, {Expr(Op.SYMBOL, 'x'): 1})"
+ assert t == t
+ assert t != u
+ assert hash(t) is not None
+
+ v = as_factors(x)
+ w = as_factors(y)
+ assert v.op == Op.FACTORS
+ assert repr(v) == "Expr(Op.FACTORS, {Expr(Op.SYMBOL, 'x'): 1})"
+ assert v == v
+ assert w != v
+ assert hash(v) is not None
+
+ t = as_ternary(x, y, z)
+ u = as_ternary(x, z, y)
+ assert t.op == Op.TERNARY
+ assert t == t
+ assert t != u
+ assert hash(t) is not None
+
+ e = as_eq(x, y)
+ f = as_lt(x, y)
+ assert e.op == Op.RELATIONAL
+ assert e == e
+ assert e != f
+ assert hash(e) is not None
+
+ def test_tostring_fortran(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ n = as_number(123)
+ m = as_number(456)
+ a = as_array((n, m))
+ c = as_complex(n, m)
+
+ assert str(x) == "x"
+ assert str(n) == "123"
+ assert str(a) == "[123, 456]"
+ assert str(c) == "(123, 456)"
+
+ assert str(Expr(Op.TERMS, {x: 1})) == "x"
+ assert str(Expr(Op.TERMS, {x: 2})) == "2 * x"
+ assert str(Expr(Op.TERMS, {x: -1})) == "-x"
+ assert str(Expr(Op.TERMS, {x: -2})) == "-2 * x"
+ assert str(Expr(Op.TERMS, {x: 1, y: 1})) == "x + y"
+ assert str(Expr(Op.TERMS, {x: -1, y: -1})) == "-x - y"
+ assert str(Expr(Op.TERMS, {x: 2, y: 3})) == "2 * x + 3 * y"
+ assert str(Expr(Op.TERMS, {x: -2, y: 3})) == "-2 * x + 3 * y"
+ assert str(Expr(Op.TERMS, {x: 2, y: -3})) == "2 * x - 3 * y"
+
+ assert str(Expr(Op.FACTORS, {x: 1})) == "x"
+ assert str(Expr(Op.FACTORS, {x: 2})) == "x ** 2"
+ assert str(Expr(Op.FACTORS, {x: -1})) == "x ** -1"
+ assert str(Expr(Op.FACTORS, {x: -2})) == "x ** -2"
+ assert str(Expr(Op.FACTORS, {x: 1, y: 1})) == "x * y"
+ assert str(Expr(Op.FACTORS, {x: 2, y: 3})) == "x ** 2 * y ** 3"
+
+ v = Expr(Op.FACTORS, {x: 2, Expr(Op.TERMS, {x: 1, y: 1}): 3})
+ assert str(v) == "x ** 2 * (x + y) ** 3", str(v)
+ v = Expr(Op.FACTORS, {x: 2, Expr(Op.FACTORS, {x: 1, y: 1}): 3})
+ assert str(v) == "x ** 2 * (x * y) ** 3", str(v)
+
+ assert str(Expr(Op.APPLY, ("f", (), {}))) == "f()"
+ assert str(Expr(Op.APPLY, ("f", (x, ), {}))) == "f(x)"
+ assert str(Expr(Op.APPLY, ("f", (x, y), {}))) == "f(x, y)"
+ assert str(Expr(Op.INDEXING, ("f", x))) == "f[x]"
+
+ assert str(as_ternary(x, y, z)) == "merge(y, z, x)"
+ assert str(as_eq(x, y)) == "x .eq. y"
+ assert str(as_ne(x, y)) == "x .ne. y"
+ assert str(as_lt(x, y)) == "x .lt. y"
+ assert str(as_le(x, y)) == "x .le. y"
+ assert str(as_gt(x, y)) == "x .gt. y"
+ assert str(as_ge(x, y)) == "x .ge. y"
+
+ def test_tostring_c(self):
+ language = Language.C
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ n = as_number(123)
+
+ assert Expr(Op.FACTORS, {x: 2}).tostring(language=language) == "x * x"
+ assert (Expr(Op.FACTORS, {
+ x + y: 2
+ }).tostring(language=language) == "(x + y) * (x + y)")
+ assert Expr(Op.FACTORS, {
+ x: 12
+ }).tostring(language=language) == "pow(x, 12)"
+
+ assert as_apply(ArithOp.DIV, x,
+ y).tostring(language=language) == "x / y"
+ assert (as_apply(ArithOp.DIV, x,
+ x + y).tostring(language=language) == "x / (x + y)")
+ assert (as_apply(ArithOp.DIV, x - y, x +
+ y).tostring(language=language) == "(x - y) / (x + y)")
+ assert (x + (x - y) / (x + y) +
+ n).tostring(language=language) == "123 + x + (x - y) / (x + y)"
+
+ assert as_ternary(x, y, z).tostring(language=language) == "(x?y:z)"
+ assert as_eq(x, y).tostring(language=language) == "x == y"
+ assert as_ne(x, y).tostring(language=language) == "x != y"
+ assert as_lt(x, y).tostring(language=language) == "x < y"
+ assert as_le(x, y).tostring(language=language) == "x <= y"
+ assert as_gt(x, y).tostring(language=language) == "x > y"
+ assert as_ge(x, y).tostring(language=language) == "x >= y"
+
+ def test_operations(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+
+ assert x + x == Expr(Op.TERMS, {x: 2})
+ assert x - x == Expr(Op.INTEGER, (0, 4))
+ assert x + y == Expr(Op.TERMS, {x: 1, y: 1})
+ assert x - y == Expr(Op.TERMS, {x: 1, y: -1})
+ assert x * x == Expr(Op.FACTORS, {x: 2})
+ assert x * y == Expr(Op.FACTORS, {x: 1, y: 1})
+
+ assert +x == x
+ assert -x == Expr(Op.TERMS, {x: -1}), repr(-x)
+ assert 2 * x == Expr(Op.TERMS, {x: 2})
+ assert 2 + x == Expr(Op.TERMS, {x: 1, as_number(1): 2})
+ assert 2 * x + 3 * y == Expr(Op.TERMS, {x: 2, y: 3})
+ assert (x + y) * 2 == Expr(Op.TERMS, {x: 2, y: 2})
+
+ assert x**2 == Expr(Op.FACTORS, {x: 2})
+ assert (x + y)**2 == Expr(
+ Op.TERMS,
+ {
+ Expr(Op.FACTORS, {x: 2}): 1,
+ Expr(Op.FACTORS, {y: 2}): 1,
+ Expr(Op.FACTORS, {
+ x: 1,
+ y: 1
+ }): 2,
+ },
+ )
+ assert (x + y) * x == x**2 + x * y
+ assert (x + y)**2 == x**2 + 2 * x * y + y**2
+ assert (x + y)**2 + (x - y)**2 == 2 * x**2 + 2 * y**2
+ assert (x + y) * z == x * z + y * z
+ assert z * (x + y) == x * z + y * z
+
+ assert (x / 2) == as_apply(ArithOp.DIV, x, as_number(2))
+ assert (2 * x / 2) == x
+ assert (3 * x / 2) == as_apply(ArithOp.DIV, 3 * x, as_number(2))
+ assert (4 * x / 2) == 2 * x
+ assert (5 * x / 2) == as_apply(ArithOp.DIV, 5 * x, as_number(2))
+ assert (6 * x / 2) == 3 * x
+ assert ((3 * 5) * x / 6) == as_apply(ArithOp.DIV, 5 * x, as_number(2))
+ assert (30 * x**2 * y**4 / (24 * x**3 * y**3)) == as_apply(
+ ArithOp.DIV, 5 * y, 4 * x)
+ assert ((15 * x / 6) / 5) == as_apply(ArithOp.DIV, x,
+ as_number(2)), (15 * x / 6) / 5
+ assert (x / (5 / x)) == as_apply(ArithOp.DIV, x**2, as_number(5))
+
+ assert (x / 2.0) == Expr(Op.TERMS, {x: 0.5})
+
+ s = as_string('"ABC"')
+ t = as_string('"123"')
+
+ assert s // t == Expr(Op.STRING, ('"ABC123"', 1))
+ assert s // x == Expr(Op.CONCAT, (s, x))
+ assert x // s == Expr(Op.CONCAT, (x, s))
+
+ c = as_complex(1.0, 2.0)
+ assert -c == as_complex(-1.0, -2.0)
+ assert c + c == as_expr((1 + 2j) * 2)
+ assert c * c == as_expr((1 + 2j)**2)
+
+ def test_substitute(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ a = as_array((x, y))
+
+ assert x.substitute({x: y}) == y
+ assert (x + y).substitute({x: z}) == y + z
+ assert (x * y).substitute({x: z}) == y * z
+ assert (x**4).substitute({x: z}) == z**4
+ assert (x / y).substitute({x: z}) == z / y
+ assert x.substitute({x: y + z}) == y + z
+ assert a.substitute({x: y + z}) == as_array((y + z, y))
+
+ assert as_ternary(x, y,
+ z).substitute({x: y + z}) == as_ternary(y + z, y, z)
+ assert as_eq(x, y).substitute({x: y + z}) == as_eq(y + z, y)
+
+ def test_fromstring(self):
+
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ f = as_symbol("f")
+ s = as_string('"ABC"')
+ t = as_string('"123"')
+ a = as_array((x, y))
+
+ assert fromstring("x") == x
+ assert fromstring("+ x") == x
+ assert fromstring("- x") == -x
+ assert fromstring("x + y") == x + y
+ assert fromstring("x + 1") == x + 1
+ assert fromstring("x * y") == x * y
+ assert fromstring("x * 2") == x * 2
+ assert fromstring("x / y") == x / y
+ assert fromstring("x ** 2", language=Language.Python) == x**2
+ assert fromstring("x ** 2 ** 3", language=Language.Python) == x**2**3
+ assert fromstring("(x + y) * z") == (x + y) * z
+
+ assert fromstring("f(x)") == f(x)
+ assert fromstring("f(x,y)") == f(x, y)
+ assert fromstring("f[x]") == f[x]
+ assert fromstring("f[x][y]") == f[x][y]
+
+ assert fromstring('"ABC"') == s
+ assert (normalize(
+ fromstring('"ABC" // "123" ',
+ language=Language.Fortran)) == s // t)
+ assert fromstring('f("ABC")') == f(s)
+ assert fromstring('MYSTRKIND_"ABC"') == as_string('"ABC"', "MYSTRKIND")
+
+ assert fromstring("(/x, y/)") == a, fromstring("(/x, y/)")
+ assert fromstring("f((/x, y/))") == f(a)
+ assert fromstring("(/(x+y)*z/)") == as_array(((x + y) * z, ))
+
+ assert fromstring("123") == as_number(123)
+ assert fromstring("123_2") == as_number(123, 2)
+ assert fromstring("123_myintkind") == as_number(123, "myintkind")
+
+ assert fromstring("123.0") == as_number(123.0, 4)
+ assert fromstring("123.0_4") == as_number(123.0, 4)
+ assert fromstring("123.0_8") == as_number(123.0, 8)
+ assert fromstring("123.0e0") == as_number(123.0, 4)
+ assert fromstring("123.0d0") == as_number(123.0, 8)
+ assert fromstring("123d0") == as_number(123.0, 8)
+ assert fromstring("123e-0") == as_number(123.0, 4)
+ assert fromstring("123d+0") == as_number(123.0, 8)
+ assert fromstring("123.0_myrealkind") == as_number(123.0, "myrealkind")
+ assert fromstring("3E4") == as_number(30000.0, 4)
+
+ assert fromstring("(1, 2)") == as_complex(1, 2)
+ assert fromstring("(1e2, PI)") == as_complex(as_number(100.0),
+ as_symbol("PI"))
+
+ assert fromstring("[1, 2]") == as_array((as_number(1), as_number(2)))
+
+ assert fromstring("POINT(x, y=1)") == as_apply(as_symbol("POINT"),
+ x,
+ y=as_number(1))
+ assert fromstring(
+ 'PERSON(name="John", age=50, shape=(/34, 23/))') == as_apply(
+ as_symbol("PERSON"),
+ name=as_string('"John"'),
+ age=as_number(50),
+ shape=as_array((as_number(34), as_number(23))),
+ )
+
+ assert fromstring("x?y:z") == as_ternary(x, y, z)
+
+ assert fromstring("*x") == as_deref(x)
+ assert fromstring("**x") == as_deref(as_deref(x))
+ assert fromstring("&x") == as_ref(x)
+ assert fromstring("(*x) * (*y)") == as_deref(x) * as_deref(y)
+ assert fromstring("(*x) * *y") == as_deref(x) * as_deref(y)
+ assert fromstring("*x * *y") == as_deref(x) * as_deref(y)
+ assert fromstring("*x**y") == as_deref(x) * as_deref(y)
+
+ assert fromstring("x == y") == as_eq(x, y)
+ assert fromstring("x != y") == as_ne(x, y)
+ assert fromstring("x < y") == as_lt(x, y)
+ assert fromstring("x > y") == as_gt(x, y)
+ assert fromstring("x <= y") == as_le(x, y)
+ assert fromstring("x >= y") == as_ge(x, y)
+
+ assert fromstring("x .eq. y", language=Language.Fortran) == as_eq(x, y)
+ assert fromstring("x .ne. y", language=Language.Fortran) == as_ne(x, y)
+ assert fromstring("x .lt. y", language=Language.Fortran) == as_lt(x, y)
+ assert fromstring("x .gt. y", language=Language.Fortran) == as_gt(x, y)
+ assert fromstring("x .le. y", language=Language.Fortran) == as_le(x, y)
+ assert fromstring("x .ge. y", language=Language.Fortran) == as_ge(x, y)
+
+ def test_traverse(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+ f = as_symbol("f")
+
+ # Use traverse to substitute a symbol
+ def replace_visit(s, r=z):
+ if s == x:
+ return r
+
+ assert x.traverse(replace_visit) == z
+ assert y.traverse(replace_visit) == y
+ assert z.traverse(replace_visit) == z
+ assert (f(y)).traverse(replace_visit) == f(y)
+ assert (f(x)).traverse(replace_visit) == f(z)
+ assert (f[y]).traverse(replace_visit) == f[y]
+ assert (f[z]).traverse(replace_visit) == f[z]
+ assert (x + y + z).traverse(replace_visit) == (2 * z + y)
+ assert (x +
+ f(y, x - z)).traverse(replace_visit) == (z +
+ f(y, as_number(0)))
+ assert as_eq(x, y).traverse(replace_visit) == as_eq(z, y)
+
+ # Use traverse to collect symbols, method 1
+ function_symbols = set()
+ symbols = set()
+
+ def collect_symbols(s):
+ if s.op is Op.APPLY:
+ oper = s.data[0]
+ function_symbols.add(oper)
+ if oper in symbols:
+ symbols.remove(oper)
+ elif s.op is Op.SYMBOL and s not in function_symbols:
+ symbols.add(s)
+
+ (x + f(y, x - z)).traverse(collect_symbols)
+ assert function_symbols == {f}
+ assert symbols == {x, y, z}
+
+ # Use traverse to collect symbols, method 2
+ def collect_symbols2(expr, symbols):
+ if expr.op is Op.SYMBOL:
+ symbols.add(expr)
+
+ symbols = set()
+ (x + f(y, x - z)).traverse(collect_symbols2, symbols)
+ assert symbols == {x, y, z, f}
+
+ # Use traverse to partially collect symbols
+ def collect_symbols3(expr, symbols):
+ if expr.op is Op.APPLY:
+ # skip traversing function calls
+ return expr
+ if expr.op is Op.SYMBOL:
+ symbols.add(expr)
+
+ symbols = set()
+ (x + f(y, x - z)).traverse(collect_symbols3, symbols)
+ assert symbols == {x}
+
+ def test_linear_solve(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ z = as_symbol("z")
+
+ assert x.linear_solve(x) == (as_number(1), as_number(0))
+ assert (x + 1).linear_solve(x) == (as_number(1), as_number(1))
+ assert (2 * x).linear_solve(x) == (as_number(2), as_number(0))
+ assert (2 * x + 3).linear_solve(x) == (as_number(2), as_number(3))
+ assert as_number(3).linear_solve(x) == (as_number(0), as_number(3))
+ assert y.linear_solve(x) == (as_number(0), y)
+ assert (y * z).linear_solve(x) == (as_number(0), y * z)
+
+ assert (x + y).linear_solve(x) == (as_number(1), y)
+ assert (z * x + y).linear_solve(x) == (z, y)
+ assert ((z + y) * x + y).linear_solve(x) == (z + y, y)
+ assert (z * y * x + y).linear_solve(x) == (z * y, y)
+
+ pytest.raises(RuntimeError, lambda: (x * x).linear_solve(x))
+
+ def test_as_numer_denom(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ n = as_number(123)
+
+ assert as_numer_denom(x) == (x, as_number(1))
+ assert as_numer_denom(x / n) == (x, n)
+ assert as_numer_denom(n / x) == (n, x)
+ assert as_numer_denom(x / y) == (x, y)
+ assert as_numer_denom(x * y) == (x * y, as_number(1))
+ assert as_numer_denom(n + x / y) == (x + n * y, y)
+ assert as_numer_denom(n + x / (y - x / n)) == (y * n**2, y * n - x)
+
+ def test_polynomial_atoms(self):
+ x = as_symbol("x")
+ y = as_symbol("y")
+ n = as_number(123)
+
+ assert x.polynomial_atoms() == {x}
+ assert n.polynomial_atoms() == set()
+ assert (y[x]).polynomial_atoms() == {y[x]}
+ assert (y(x)).polynomial_atoms() == {y(x)}
+ assert (y(x) + x).polynomial_atoms() == {y(x), x}
+ assert (y(x) * x[y]).polynomial_atoms() == {y(x), x[y]}
+ assert (y(x)**x).polynomial_atoms() == {y(x)}
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_value_attrspec.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_value_attrspec.py
new file mode 100644
index 00000000..83aaf6c9
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/test_value_attrspec.py
@@ -0,0 +1,14 @@
+import os
+import pytest
+
+from . import util
+
+class TestValueAttr(util.F2PyTest):
+ sources = [util.getpath("tests", "src", "value_attrspec", "gh21665.f90")]
+
+ # gh-21665
+ def test_long_long_map(self):
+ inp = 2
+ out = self.module.fortfuncs.square(inp)
+ exp_out = 4
+ assert out == exp_out
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/tests/util.py b/venv/lib/python3.9/site-packages/numpy/f2py/tests/util.py
new file mode 100644
index 00000000..1534c4e7
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/tests/util.py
@@ -0,0 +1,419 @@
+"""
+Utility functions for
+
+- building and importing modules on test time, using a temporary location
+- detecting if compilers are present
+- determining paths to tests
+
+"""
+import os
+import sys
+import subprocess
+import tempfile
+import shutil
+import atexit
+import textwrap
+import re
+import pytest
+import contextlib
+import numpy
+
+from pathlib import Path
+from numpy.compat import asbytes, asstr
+from numpy.testing import temppath, IS_WASM
+from importlib import import_module
+
+#
+# Maintaining a temporary module directory
+#
+
+_module_dir = None
+_module_num = 5403
+
+
+def _cleanup():
+ global _module_dir
+ if _module_dir is not None:
+ try:
+ sys.path.remove(_module_dir)
+ except ValueError:
+ pass
+ try:
+ shutil.rmtree(_module_dir)
+ except OSError:
+ pass
+ _module_dir = None
+
+
+def get_module_dir():
+ global _module_dir
+ if _module_dir is None:
+ _module_dir = tempfile.mkdtemp()
+ atexit.register(_cleanup)
+ if _module_dir not in sys.path:
+ sys.path.insert(0, _module_dir)
+ return _module_dir
+
+
+def get_temp_module_name():
+ # Assume single-threaded, and the module dir usable only by this thread
+ global _module_num
+ get_module_dir()
+ name = "_test_ext_module_%d" % _module_num
+ _module_num += 1
+ if name in sys.modules:
+ # this should not be possible, but check anyway
+ raise RuntimeError("Temporary module name already in use.")
+ return name
+
+
+def _memoize(func):
+ memo = {}
+
+ def wrapper(*a, **kw):
+ key = repr((a, kw))
+ if key not in memo:
+ try:
+ memo[key] = func(*a, **kw)
+ except Exception as e:
+ memo[key] = e
+ raise
+ ret = memo[key]
+ if isinstance(ret, Exception):
+ raise ret
+ return ret
+
+ wrapper.__name__ = func.__name__
+ return wrapper
+
+
+#
+# Building modules
+#
+
+
+@_memoize
+def build_module(source_files, options=[], skip=[], only=[], module_name=None):
+ """
+ Compile and import a f2py module, built from the given files.
+
+ """
+
+ code = f"import sys; sys.path = {sys.path!r}; import numpy.f2py; numpy.f2py.main()"
+
+ d = get_module_dir()
+
+ # Copy files
+ dst_sources = []
+ f2py_sources = []
+ for fn in source_files:
+ if not os.path.isfile(fn):
+ raise RuntimeError("%s is not a file" % fn)
+ dst = os.path.join(d, os.path.basename(fn))
+ shutil.copyfile(fn, dst)
+ dst_sources.append(dst)
+
+ base, ext = os.path.splitext(dst)
+ if ext in (".f90", ".f", ".c", ".pyf"):
+ f2py_sources.append(dst)
+
+ assert f2py_sources
+
+ # Prepare options
+ if module_name is None:
+ module_name = get_temp_module_name()
+ f2py_opts = ["-c", "-m", module_name] + options + f2py_sources
+ if skip:
+ f2py_opts += ["skip:"] + skip
+ if only:
+ f2py_opts += ["only:"] + only
+
+ # Build
+ cwd = os.getcwd()
+ try:
+ os.chdir(d)
+ cmd = [sys.executable, "-c", code] + f2py_opts
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ out, err = p.communicate()
+ if p.returncode != 0:
+ raise RuntimeError("Running f2py failed: %s\n%s" %
+ (cmd[4:], asstr(out)))
+ finally:
+ os.chdir(cwd)
+
+ # Partial cleanup
+ for fn in dst_sources:
+ os.unlink(fn)
+
+ # Import
+ return import_module(module_name)
+
+
+@_memoize
+def build_code(source_code,
+ options=[],
+ skip=[],
+ only=[],
+ suffix=None,
+ module_name=None):
+ """
+ Compile and import Fortran code using f2py.
+
+ """
+ if suffix is None:
+ suffix = ".f"
+ with temppath(suffix=suffix) as path:
+ with open(path, "w") as f:
+ f.write(source_code)
+ return build_module([path],
+ options=options,
+ skip=skip,
+ only=only,
+ module_name=module_name)
+
+
+#
+# Check if compilers are available at all...
+#
+
+_compiler_status = None
+
+
+def _get_compiler_status():
+ global _compiler_status
+ if _compiler_status is not None:
+ return _compiler_status
+
+ _compiler_status = (False, False, False)
+ if IS_WASM:
+ # Can't run compiler from inside WASM.
+ return _compiler_status
+
+ # XXX: this is really ugly. But I don't know how to invoke Distutils
+ # in a safer way...
+ code = textwrap.dedent(f"""\
+ import os
+ import sys
+ sys.path = {repr(sys.path)}
+
+ def configuration(parent_name='',top_path=None):
+ global config
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('', parent_name, top_path)
+ return config
+
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+
+ config_cmd = config.get_config_cmd()
+ have_c = config_cmd.try_compile('void foo() {{}}')
+ print('COMPILERS:%%d,%%d,%%d' %% (have_c,
+ config.have_f77c(),
+ config.have_f90c()))
+ sys.exit(99)
+ """)
+ code = code % dict(syspath=repr(sys.path))
+
+ tmpdir = tempfile.mkdtemp()
+ try:
+ script = os.path.join(tmpdir, "setup.py")
+
+ with open(script, "w") as f:
+ f.write(code)
+
+ cmd = [sys.executable, "setup.py", "config"]
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ cwd=tmpdir)
+ out, err = p.communicate()
+ finally:
+ shutil.rmtree(tmpdir)
+
+ m = re.search(br"COMPILERS:(\d+),(\d+),(\d+)", out)
+ if m:
+ _compiler_status = (
+ bool(int(m.group(1))),
+ bool(int(m.group(2))),
+ bool(int(m.group(3))),
+ )
+ # Finished
+ return _compiler_status
+
+
+def has_c_compiler():
+ return _get_compiler_status()[0]
+
+
+def has_f77_compiler():
+ return _get_compiler_status()[1]
+
+
+def has_f90_compiler():
+ return _get_compiler_status()[2]
+
+
+#
+# Building with distutils
+#
+
+
+@_memoize
+def build_module_distutils(source_files, config_code, module_name, **kw):
+ """
+ Build a module via distutils and import it.
+
+ """
+ d = get_module_dir()
+
+ # Copy files
+ dst_sources = []
+ for fn in source_files:
+ if not os.path.isfile(fn):
+ raise RuntimeError("%s is not a file" % fn)
+ dst = os.path.join(d, os.path.basename(fn))
+ shutil.copyfile(fn, dst)
+ dst_sources.append(dst)
+
+ # Build script
+ config_code = textwrap.dedent(config_code).replace("\n", "\n ")
+
+ code = fr"""
+import os
+import sys
+sys.path = {repr(sys.path)}
+
+def configuration(parent_name='',top_path=None):
+ from numpy.distutils.misc_util import Configuration
+ config = Configuration('', parent_name, top_path)
+ {config_code}
+ return config
+
+if __name__ == "__main__":
+ from numpy.distutils.core import setup
+ setup(configuration=configuration)
+ """
+ script = os.path.join(d, get_temp_module_name() + ".py")
+ dst_sources.append(script)
+ with open(script, "wb") as f:
+ f.write(asbytes(code))
+
+ # Build
+ cwd = os.getcwd()
+ try:
+ os.chdir(d)
+ cmd = [sys.executable, script, "build_ext", "-i"]
+ p = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ out, err = p.communicate()
+ if p.returncode != 0:
+ raise RuntimeError("Running distutils build failed: %s\n%s" %
+ (cmd[4:], asstr(out)))
+ finally:
+ os.chdir(cwd)
+
+ # Partial cleanup
+ for fn in dst_sources:
+ os.unlink(fn)
+
+ # Import
+ __import__(module_name)
+ return sys.modules[module_name]
+
+
+#
+# Unittest convenience
+#
+
+
+class F2PyTest:
+ code = None
+ sources = None
+ options = []
+ skip = []
+ only = []
+ suffix = ".f"
+ module = None
+
+ @property
+ def module_name(self):
+ cls = type(self)
+ return f'_{cls.__module__.rsplit(".",1)[-1]}_{cls.__name__}_ext_module'
+
+ def setup_method(self):
+ if sys.platform == "win32":
+ pytest.skip("Fails with MinGW64 Gfortran (Issue #9673)")
+
+ if self.module is not None:
+ return
+
+ # Check compiler availability first
+ if not has_c_compiler():
+ pytest.skip("No C compiler available")
+
+ codes = []
+ if self.sources:
+ codes.extend(self.sources)
+ if self.code is not None:
+ codes.append(self.suffix)
+
+ needs_f77 = False
+ needs_f90 = False
+ needs_pyf = False
+ for fn in codes:
+ if str(fn).endswith(".f"):
+ needs_f77 = True
+ elif str(fn).endswith(".f90"):
+ needs_f90 = True
+ elif str(fn).endswith(".pyf"):
+ needs_pyf = True
+ if needs_f77 and not has_f77_compiler():
+ pytest.skip("No Fortran 77 compiler available")
+ if needs_f90 and not has_f90_compiler():
+ pytest.skip("No Fortran 90 compiler available")
+ if needs_pyf and not (has_f90_compiler() or has_f77_compiler()):
+ pytest.skip("No Fortran compiler available")
+
+ # Build the module
+ if self.code is not None:
+ self.module = build_code(
+ self.code,
+ options=self.options,
+ skip=self.skip,
+ only=self.only,
+ suffix=self.suffix,
+ module_name=self.module_name,
+ )
+
+ if self.sources is not None:
+ self.module = build_module(
+ self.sources,
+ options=self.options,
+ skip=self.skip,
+ only=self.only,
+ module_name=self.module_name,
+ )
+
+
+#
+# Helper functions
+#
+
+
+def getpath(*a):
+ # Package root
+ d = Path(numpy.f2py.__file__).parent.resolve()
+ return d.joinpath(*a)
+
+
+@contextlib.contextmanager
+def switchdir(path):
+ curpath = Path.cwd()
+ os.chdir(path)
+ try:
+ yield
+ finally:
+ os.chdir(curpath)
diff --git a/venv/lib/python3.9/site-packages/numpy/f2py/use_rules.py b/venv/lib/python3.9/site-packages/numpy/f2py/use_rules.py
new file mode 100644
index 00000000..f1b71e83
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/numpy/f2py/use_rules.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python3
+"""
+
+Build 'use others module data' mechanism for f2py2e.
+
+Unfinished.
+
+Copyright 2000 Pearu Peterson all rights reserved,
+Pearu Peterson <pearu@ioc.ee>
+Permission to use, modify, and distribute this software is given under the
+terms of the NumPy License.
+
+NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+$Date: 2000/09/10 12:35:43 $
+Pearu Peterson
+
+"""
+__version__ = "$Revision: 1.3 $"[10:-1]
+
+f2py_version = 'See `f2py -v`'
+
+
+from .auxfuncs import (
+ applyrules, dictappend, gentitle, hasnote, outmess
+)
+
+
+usemodule_rules = {
+ 'body': """
+#begintitle#
+static char doc_#apiname#[] = \"\\\nVariable wrapper signature:\\n\\
+\t #name# = get_#name#()\\n\\
+Arguments:\\n\\
+#docstr#\";
+extern F_MODFUNC(#usemodulename#,#USEMODULENAME#,#realname#,#REALNAME#);
+static PyObject *#apiname#(PyObject *capi_self, PyObject *capi_args) {
+/*#decl#*/
+\tif (!PyArg_ParseTuple(capi_args, \"\")) goto capi_fail;
+printf(\"c: %d\\n\",F_MODFUNC(#usemodulename#,#USEMODULENAME#,#realname#,#REALNAME#));
+\treturn Py_BuildValue(\"\");
+capi_fail:
+\treturn NULL;
+}
+""",
+ 'method': '\t{\"get_#name#\",#apiname#,METH_VARARGS|METH_KEYWORDS,doc_#apiname#},',
+ 'need': ['F_MODFUNC']
+}
+
+################
+
+
+def buildusevars(m, r):
+ ret = {}
+ outmess(
+ '\t\tBuilding use variable hooks for module "%s" (feature only for F90/F95)...\n' % (m['name']))
+ varsmap = {}
+ revmap = {}
+ if 'map' in r:
+ for k in r['map'].keys():
+ if r['map'][k] in revmap:
+ outmess('\t\t\tVariable "%s<=%s" is already mapped by "%s". Skipping.\n' % (
+ r['map'][k], k, revmap[r['map'][k]]))
+ else:
+ revmap[r['map'][k]] = k
+ if 'only' in r and r['only']:
+ for v in r['map'].keys():
+ if r['map'][v] in m['vars']:
+
+ if revmap[r['map'][v]] == v:
+ varsmap[v] = r['map'][v]
+ else:
+ outmess('\t\t\tIgnoring map "%s=>%s". See above.\n' %
+ (v, r['map'][v]))
+ else:
+ outmess(
+ '\t\t\tNo definition for variable "%s=>%s". Skipping.\n' % (v, r['map'][v]))
+ else:
+ for v in m['vars'].keys():
+ if v in revmap:
+ varsmap[v] = revmap[v]
+ else:
+ varsmap[v] = v
+ for v in varsmap.keys():
+ ret = dictappend(ret, buildusevar(v, varsmap[v], m['vars'], m['name']))
+ return ret
+
+
+def buildusevar(name, realname, vars, usemodulename):
+ outmess('\t\t\tConstructing wrapper function for variable "%s=>%s"...\n' % (
+ name, realname))
+ ret = {}
+ vrd = {'name': name,
+ 'realname': realname,
+ 'REALNAME': realname.upper(),
+ 'usemodulename': usemodulename,
+ 'USEMODULENAME': usemodulename.upper(),
+ 'texname': name.replace('_', '\\_'),
+ 'begintitle': gentitle('%s=>%s' % (name, realname)),
+ 'endtitle': gentitle('end of %s=>%s' % (name, realname)),
+ 'apiname': '#modulename#_use_%s_from_%s' % (realname, usemodulename)
+ }
+ nummap = {0: 'Ro', 1: 'Ri', 2: 'Rii', 3: 'Riii', 4: 'Riv',
+ 5: 'Rv', 6: 'Rvi', 7: 'Rvii', 8: 'Rviii', 9: 'Rix'}
+ vrd['texnamename'] = name
+ for i in nummap.keys():
+ vrd['texnamename'] = vrd['texnamename'].replace(repr(i), nummap[i])
+ if hasnote(vars[realname]):
+ vrd['note'] = vars[realname]['note']
+ rd = dictappend({}, vrd)
+
+ print(name, realname, vars[realname])
+ ret = applyrules(usemodule_rules, rd)
+ return ret