diff --git a/.azure/pipelines.yml b/.azure/pipelines.yml index 631ab1ade4..b9e20329e7 100644 --- a/.azure/pipelines.yml +++ b/.azure/pipelines.yml @@ -34,7 +34,7 @@ stages: steps: - template: templates/install.yml parameters: - python_version: 3.10 + python_version: 3 conda_packages: 'hunspell' - bash: | @@ -62,7 +62,7 @@ stages: steps: - template: templates/install.yml parameters: - python_version: 3.10 + python_version: 3 conda_packages: 'numpy' - bash: | @@ -85,7 +85,7 @@ stages: steps: - template: templates/install.yml parameters: - python_version: 3.10 + python_version: 3 conda_packages: 'numpy' - bash: | @@ -106,74 +106,74 @@ stages: matrix: linux-py3k-petsc: image: ubuntu-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: petsc MPIRUN: linux-py3k-petsc-parallel: image: ubuntu-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: petsc MPIRUN: 'mpirun -np 2' linux-py3k-scipy: image: ubuntu-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: scipy MPIRUN: - linux-py37-trilinos: + linux-py3k-trilinos: image: ubuntu-latest - python_version: 3.7 - conda_packages: 'gmsh pytrilinos' + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py pytrilinos mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: trilinos MPIRUN: - linux-py37-trilinos-parallel: + linux-py3k-trilinos-parallel: image: ubuntu-latest - python_version: 3.7 - conda_packages: 'gmsh pytrilinos' + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py pytrilinos mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: trilinos MPIRUN: 'mpirun -np 2' macos-py27-pysparse: image: macos-latest python_version: 2.7 - conda_packages: '"traitsui<7.0.0" "gmsh<4.0"' + conda_packages: 'numpy scipy matplotlib-base future packaging pysparse mayavi "traitsui<7.0.0" "gmsh<4.0"' FIPY_SOLVERS: pysparse MPIRUN: macos-py3k-petsc: image: macos-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: petsc MPIRUN: macos-py3k-petsc-parallel: image: macos-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: petsc MPIRUN: 'mpirun -np 2' macos-py3k-scipy: image: macos-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: scipy MPIRUN: - macos-py37-trilinos: + macos-py3k-trilinos: image: macos-latest - python_version: 3.7 - conda_packages: 'gmsh pytrilinos' + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py pytrilinos mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: trilinos MPIRUN: - macos-py37-trilinos-parallel: + macos-py3k-trilinos-parallel: image: macos-latest - python_version: 3.7 - conda_packages: 'gmsh pytrilinos' + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py pytrilinos mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: trilinos MPIRUN: 'mpirun -np 2' windows-py3k-scipy: image: windows-latest - python_version: 3.10 - conda_packages: gmsh + python_version: 3 + conda_packages: 'numpy scipy matplotlib-base future packaging mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: scipy MPIRUN: @@ -214,8 +214,8 @@ stages: steps: - template: templates/install.yml parameters: - python_version: 3.10 - conda_packages: 'sphinx future matplotlib pandas imagemagick' + python_version: 3 + conda_packages: 'numpy scipy matplotlib future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2" sphinx pandas imagemagick' - bash: | source activate myEnvironment @@ -233,6 +233,10 @@ stages: sudo apt-get --yes install texlive-extra-utils displayName: Install LaTeX + - bash: | + conda env export --name myEnvironment + displayName: Environment + - bash: | source activate myEnvironment export ETS_TOOLKIT=null @@ -260,13 +264,13 @@ stages: unix: image: ubuntu-latest python_version: 3.10 - conda_packages: gmsh + conda_packages: 'numpy scipy matplotlib-base future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: petsc MPIRUN: windows: image: windows-latest python_version: 3.10 - conda_packages: gmsh + conda_packages: 'numpy scipy matplotlib-base future packaging mayavi "gmsh <4.0|>=4.5.2"' FIPY_SOLVERS: scipy MPIRUN: @@ -291,6 +295,10 @@ stages: displayName: Build wheel condition: startsWith(variables.image, 'ubuntu') + - bash: | + conda env export --name myEnvironment + displayName: Environment + - bash: | source activate myEnvironment python setup.py release --unix diff --git a/.azure/templates/install.yml b/.azure/templates/install.yml index ca5ca1c96d..7b85780efe 100644 --- a/.azure/templates/install.yml +++ b/.azure/templates/install.yml @@ -44,12 +44,10 @@ steps: - bash: | if [[ ${{ parameters.python_version }} == "2.7" ]]; then # mamba doesn't work in Py2.7; do mamba installs from base - mamba install --quiet --name myEnvironment --channel conda-forge --only-deps python=${{ parameters.python_version }} fipy mamba install --quiet --name myEnvironment --channel conda-forge python=${{ parameters.python_version }} ${{ parameters.conda_packages }} else # do mamba installs from environment on Py3k source activate myEnvironment - mamba install --quiet --channel conda-forge --only-deps python=${{ parameters.python_version }} fipy mamba install --quiet --channel conda-forge python=${{ parameters.python_version }} ${{ parameters.conda_packages }} fi displayName: Install Anaconda packages diff --git a/INSTALLATION.rst b/INSTALLATION.rst index 9f7fb6da2b..731130af9c 100644 --- a/INSTALLATION.rst +++ b/INSTALLATION.rst @@ -78,6 +78,17 @@ Recommended Method :term:`Gmsh` is an optional package because some versions are incompatible with :term:`FiPy`, so it must be requested explicitly. + .. note:: + + The `fipy conda-forge`_ package is a convenience. You may choose to + install packages explicitly, e.g.,:: + + $ conda create --name --channel conda-forge python=3 numpy scipy matplotlib-base future packaging mpich mpi4py petsc4py mayavi "gmsh <4.0|>=4.5.2" + + or + + $ conda create --name --channel conda-forge python=2.7 numpy scipy matplotlib-base future packaging pysparse mayavi "traitsui<7.0.0" "gmsh<4.0" + .. attention:: Windows x86_64 is fully supported, but this does not work on @@ -150,7 +161,8 @@ Recommended Method .. _Windows: http://www.microsoft.com/windows/ .. |CondaForge| image:: https://anaconda.org/conda-forge/fipy/badges/installer/conda.svg .. _CondaForge: https://anaconda.org/conda-forge/fipy -.. _mamba: https://github.com/mamba-org/mamba +.. _mamba: https://mamba.readthedocs.io/ +.. _fipy conda-forge: https://anaconda.org/conda-forge/fipy -------------- diff --git a/documentation/_themes/nist/basic_layout.html b/documentation/_themes/nist/basic_layout.html index e689da3c6f..0b090ff729 100644 --- a/documentation/_themes/nist/basic_layout.html +++ b/documentation/_themes/nist/basic_layout.html @@ -94,7 +94,7 @@

{{ _('Navigation') }}

{%- endmacro %} {%- macro css() %} - + {%- for css in css_files %} {%- if css|attr("filename") %} diff --git a/fipy/matrices/trilinosMatrix.py b/fipy/matrices/trilinosMatrix.py index e13ab61e03..6c7dd3e9cd 100644 --- a/fipy/matrices/trilinosMatrix.py +++ b/fipy/matrices/trilinosMatrix.py @@ -477,7 +477,10 @@ def exportMmf(self, filename): def numpyArray(self): import tempfile import os - from scipy.io import mmio + try: + from scipy.io import mmread + except ImportError: + from scipy.io.mmio import mmread from fipy.tools import parallelComm if parallelComm.procID == 0: @@ -490,7 +493,7 @@ def numpyArray(self): self.exportMmf(mtxName) parallelComm.Barrier() - mtx = mmio.mmread(mtxName) + mtx = mmread(mtxName) parallelComm.Barrier() if parallelComm.procID == 0: diff --git a/fipy/solvers/trilinos/__init__.py b/fipy/solvers/trilinos/__init__.py index c5920201a8..9ebd700622 100644 --- a/fipy/solvers/trilinos/__init__.py +++ b/fipy/solvers/trilinos/__init__.py @@ -34,15 +34,18 @@ def _dealWithTrilinosImportPathologies(): from PyTrilinos import Epetra - import platform - if platform.dist()[0] == 'debian': - import PyTrilinos - if '10.0.4' in PyTrilinos.version(): - # The package mpi4py is a required package if you are using - # Trilinos on a Debian platform with Trilinos version 10.0.4 due to - # a Trilinos bug (see ). - - from mpi4py import MPI + try: + import platform + if platform.dist()[0] == 'debian': + import PyTrilinos + if '10.0.4' in PyTrilinos.version(): + # The package mpi4py is a required package if you are using + # Trilinos on a Debian platform with Trilinos version 10.0.4 due to + # a Trilinos bug (see ). + + from mpi4py import MPI + except: + pass _dealWithTrilinosImportPathologies() diff --git a/fipy/tests/test.py b/fipy/tests/test.py index 7fb9626033..ec678beeda 100644 --- a/fipy/tests/test.py +++ b/fipy/tests/test.py @@ -40,6 +40,13 @@ def runTests(self): message="`np\.int` is a deprecated alias for the builtin `int`.*", module="skfmm\.pfmm") + # Don't raise errors in scikits.umfpack + # due to deprecation of pkg_resources.declare_namespace + # raised in Python 3.7, but not newer + # (combination of PyTrilinos and Gmsh(?) forces this old configuration) + warnings.filterwarnings(action="default", category=DeprecationWarning, + message="Deprecated call to `pkg_resources\.declare_namespace\('scikits'\)`.*") + super(DeprecationErroringTestProgram, self).runTests() class test(_test): diff --git a/fipy/variables/operatorVariable.py b/fipy/variables/operatorVariable.py index 6d1727d1ec..89860b1213 100644 --- a/fipy/variables/operatorVariable.py +++ b/fipy/variables/operatorVariable.py @@ -84,13 +84,12 @@ def _getRepresentation(self, style="__repr__", argDict={}, id=id, freshen=False) for i in range(len(self.var))])) try: - instructions = dis.get_instructions(self.op.__code__) - parseInstructions = self._py3kInstructions + representation = self._py3kInstructions(op=self.op, style=style, argDict=argDict, id=id, freshen=freshen) except AttributeError: instructions = [ord(byte) for byte in self.op.__code__.co_code] - parseInstructions = self._py2kInstructions + representation = self._py2kInstructions(instructions, style=style, argDict=argDict, id=id, freshen=freshen) - return parseInstructions(instructions, style=style, argDict=argDict, id=id, freshen=freshen) + return representation def __var(self, i, style, argDict, id, freshen): v = self.var[i] @@ -139,6 +138,12 @@ def __var(self, i, style, argDict, id, freshen): 62: "<<", 63: ">>", 64: "&", 65: "^", 66: "|", 106: "==" } + # introduced in Python 3.11 + _binary_op = { + 0: "+", 1: "&", 2: "//", 3: "<<", 4: "@", 5: "*", 6: "%", 7: "|", + 8: "**", 9: ">>", 10: "-", 11: "/", 12: "^" + } + def _py2kInstructions(self, bytecodes, style, argDict, id, freshen): def _popIndex(): return bytecodes.pop(0) + bytecodes.pop(0) * 256 @@ -193,11 +198,14 @@ def _popIndex(): repr(allbytecodes), repr(stack))) - def _py3kInstructions(self, instructions, style, argDict, id, freshen): + def _py3kInstructions(self, op, style, argDict, id, freshen): stack = [] - + kws = [] + instructions = dis.get_instructions(op.__code__) + for ins in instructions: if ins.opname == 'UNARY_CONVERT': + # Removed in Python 3 stack.append("`" + stack.pop() + "`") elif ins.opname == 'BINARY_SUBSCR': stack.append(stack.pop(-2) + "[" + stack.pop() + "]") @@ -210,18 +218,22 @@ def _py3kInstructions(self, instructions, style, argDict, id, freshen): elif ins.opname == 'LOAD_CONST': stack.append(ins.argval) elif ins.opname in ['LOAD_ATTR', 'LOAD_METHOD']: + # LOAD_METHOD new in Python 3.7 stack.append(stack.pop() + "." + ins.argval) elif ins.opname == 'COMPARE_OP': stack.append(stack.pop(-2) + " " + dis.cmp_op[ins.arg] + " " + stack.pop()) elif ins.opname == 'LOAD_GLOBAL': + # Changed in Python 3.11 stack.append(ins.argval) elif ins.opname == 'LOAD_FAST': stack.append(self.__var(ins.arg, style=style, argDict=argDict, id=id, freshen=freshen)) elif ins.opname in ['CALL_FUNCTION', 'CALL_METHOD']: + # Removed in Python 3.11 # args are last ins.arg items on stack args, stack = stack[-ins.arg:], stack[:-ins.arg] stack.append(stack.pop() + "(" + ", ".join(args) + ")") elif ins.opname == 'CALL_FUNCTION_KW': + # Removed in Python 3.11 kws = list(stack.pop()) # args are last ins.arg items on stack args, stack = stack[-ins.arg:], stack[:-ins.arg] @@ -230,7 +242,52 @@ def _py3kInstructions(self, instructions, style, argDict, id, freshen): kwargs.append(kws.pop() + "=" + args.pop()) stack.append(stack.pop() + "(" + ", ".join(args + kwargs) + ")") elif ins.opname == 'LOAD_DEREF': - stack.append(ins.argval) + # Changed in Python 3.11 + stack.append(op.__closure__[ins.arg-1].cell_contents) + elif ins.opname == 'RESUME': + # New in Python 3.11 + pass + elif ins.opname == 'BINARY_OP': + # New in Python 3.11 + stack.append(stack.pop(-2) + " " + self._binary_op[ins.argval] + " " + stack.pop()) + elif ins.opname == 'PRECALL': + # New in Python 3.11 + pass + elif ins.opname == 'CALL': + # New in Python 3.11 + kwargs = [kw + "=" + str(stack.pop()) for kw in kws] + positionals = [stack.pop() for _ in range(ins.argval - len(kws))] + callable = stack.pop() + if len(stack) > 0: + call_self = callable + callable = stack.pop() + stack.append(callable + "(" + ", ".join(positionals + kwargs) + ")") + kws = [] + elif ins.opname == 'COPY_FREE_VARS': + # New in Python 3.11 + pass + elif ins.opname == 'KW_NAMES': + # New in Python 3.11 + kws = op.__code__.co_consts[ins.arg] + elif ins.opname == 'BUILD_TUPLE': + tpl = tuple(stack.pop() for _ in range(ins.argval)) + stack.append(tpl) + elif ins.opname == 'BUILD_MAP': + # Changed in Python 3.5 + d = {stack.pop(): stack.pop() for _ in range(ins.argval)} + stack.append(d) + elif ins.opname == 'DICT_MERGE': + # New in Python 3.9 + updates = [stack.pop() for _ in range(ins.argval)] + d = stack.pop() + for u in updates: + d.update(u) + stack.append(d) + elif ins.opname == 'CALL_FUNCTION_EX': + # New in Python 3.6 + kwargs = [k + "=" + str(v) for k, v in stack.pop().items()] + args = [str(v) for v in stack.pop()] + stack.append(stack.pop() + "(" + ", ".join(args + kwargs) + ")") elif ins.opcode in self._unop: stack.append(self._unop[ins.opcode] + '(' + stack.pop() + ')') elif ins.opcode in self._binop: