diff --git a/.github/workflows/osx.yml b/.github/workflows/osx.yml deleted file mode 100644 index b170e795e..000000000 --- a/.github/workflows/osx.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Mathics (OSX) - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - env: - NO_CYTHON: 1 - runs-on: macos-latest - strategy: - matrix: - os: [macOS] - python-version: [3.6, 3.7, 3.8, 3.9] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - brew install llvm@11 - python -m pip install --upgrade pip - LLVM_CONFIG=/usr/local/Cellar/llvm@11/11.1.0/bin/llvm-config pip install llvmlite - # Can remove after next Mathics-Scanner release - # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full] - - name: Install Mathics with full dependencies - run: | - make develop-full - - name: Test Mathics - run: | - make -j3 check diff --git a/.github/workflows/ubuntu-cython.yml b/.github/workflows/ubuntu-cython.yml deleted file mode 100644 index 19a990dcb..000000000 --- a/.github/workflows/ubuntu-cython.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Mathics (ubuntu full with Cython) - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - runs-on: ubuntu-20.04 - strategy: - matrix: - python-version: [3.9] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get update -qq && sudo apt-get install -qq liblapack-dev llvm-dev - python -m pip install --upgrade pip - # Can remove after next Mathics-Scanner release - # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full] - - name: Install Mathics with full dependencies - run: | - make develop-full-cython - - name: Test Mathics - run: | - make -j3 check diff --git a/.github/workflows/ubuntu-pyston.yml b/.github/workflows/ubuntu-pyston.yml new file mode 100644 index 000000000..62bab8ed5 --- /dev/null +++ b/.github/workflows/ubuntu-pyston.yml @@ -0,0 +1,35 @@ +name: Mathics (ubuntu full with Pyston) + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-22.04 + strategy: + matrix: + pyston-version: [2.3.4] + steps: + - uses: actions/checkout@v3 + - name: Set up Pyston ${{ matrix.pyston-version }} + run: | + wget https://github.com/pyston/pyston/releases/download/pyston_2.3.4/pyston_2.3.4_20.04_amd64.deb + sudo apt-get install tk8.6-blt2.5 libffi7 + sudo dpkg -i pyston_2.3.4_20.04_amd64.deb + - name: Install dependencies + run: | + sudo apt-get update -qq && sudo apt-get install -qq liblapack-dev llvm-11 llvm-11-dev + # sudo /usr/lib/llvm-11/bin/llvm-config --version + sudo pyston -m pip install --upgrade pip + sudo LLVM_CONFIG=/usr/lib/llvm-11/bin/llvm-config pyston -m pip install llvmlite + - name: Install Mathics with minimal dependencies + run: | + make develop + - name: Test Mathics + run: | + # py.test seems to use always the default python interpreter of the system. Any idea about how to + # change this behaviour? + make -j3 PYTHON=pyston doctest diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml deleted file mode 100644 index 7a8b7796c..000000000 --- a/.github/workflows/ubuntu.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Mathics (ubuntu) - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - env: - NO_CYTHON: 1 - runs-on: ubuntu-20.04 - strategy: - matrix: - python-version: [3.6, 3.7, 3.8, 3.9] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get update -qq && sudo apt-get install -qq liblapack-dev llvm-dev - python -m pip install --upgrade pip - # Can remove after next Mathics-Scanner release - # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full] - - name: Install Mathics with full dependencies - run: | - make develop-full - - name: Test Mathics - run: | - make -j3 check diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100755 index e91bc7127..000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Mathics (Windows) - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - env: - NO_CYTHON: 1 - runs-on: windows-latest - strategy: - matrix: - os: [windows] - python-version: [3.7, 3.8] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install wheel - choco install llvm - set LLVM_DIR="C:\Program Files\LLVM" - # Can remove after next Mathics-Scanner release - # python -m pip install -e git+https://github.com/Mathics3/mathics-scanner#egg=Mathics-Scanner[full] - pip install -e . - - name: Install Mathics - run: | - python setup.py install - - name: Test Mathics - run: | - pip install -e .[dev,full] - set PYTEST_WORKERS="-n3" - make check diff --git a/mathics/algorithm/integrators.py b/mathics/algorithm/integrators.py index 2466c4bee..dbb6818bb 100644 --- a/mathics/algorithm/integrators.py +++ b/mathics/algorithm/integrators.py @@ -229,3 +229,5 @@ def apply_D_to_Integral(func, domain, var, evaluation, options, head): } integrator_methods["Simpson"] = integrator_methods["Internal"] integrator_methods["Automatic"] = integrator_methods["Internal"] + +integrator_messages = {} diff --git a/mathics/builtin/numbers/calculus.py b/mathics/builtin/numbers/calculus.py index 6e7d953b0..8b9715974 100644 --- a/mathics/builtin/numbers/calculus.py +++ b/mathics/builtin/numbers/calculus.py @@ -1285,18 +1285,9 @@ class _BaseFinder(Builtin): This class is the basis class for FindRoot, FindMinimum and FindMaximum. """ - options = { - "MaxIterations": "100", - "Method": "Automatic", - "AccuracyGoal": "Automatic", - "PrecisionGoal": "Automatic", - "StepMonitor": "None", - "EvaluationMonitor": "None", - "Jacobian": "Automatic", - } - attributes = hold_all | protected - + requires = ["scipy"] + methods = {} messages = { "snum": "Value `1` is not a number.", "nnum": "The function value is not a number at `1` = `2`.", @@ -1313,7 +1304,15 @@ class _BaseFinder(Builtin): ), } - methods = {} + options = { + "MaxIterations": "100", + "Method": "Automatic", + "AccuracyGoal": "Automatic", + "PrecisionGoal": "Automatic", + "StepMonitor": "None", + "EvaluationMonitor": "None", + "Jacobian": "Automatic", + } def apply(self, f, x, x0, evaluation, options): "%(name)s[f_, {x_, x0_}, OptionsPattern[]]" @@ -2048,6 +2047,7 @@ class NIntegrate(Builtin): """ + requires = ["scipy"] summary_text = "numerical integration in one or several variables" messages = { "bdmtd": "The Method option should be a built-in method name.", @@ -2077,6 +2077,7 @@ class NIntegrate(Builtin): "Automatic": (None, False), } try: + # builtin integrators from mathics.algorithm.integrators import ( integrator_methods, integrator_messages, @@ -2088,6 +2089,7 @@ class NIntegrate(Builtin): pass try: + # scipy integrators from mathics.builtin.scipy_utils.integrators import ( scipy_nintegrate_methods, scipy_nintegrate_messages, @@ -2096,11 +2098,9 @@ class NIntegrate(Builtin): methods.update(scipy_nintegrate_methods) messages.update(scipy_nintegrate_messages) except Exception as e: - print(e) - print("scipy integrators was not loaded.") pass - methods.update( + messages.update( { "bdmtd": "The Method option should be a " + "built-in method name in {`" diff --git a/mathics/builtin/optiondoc.py b/mathics/builtin/optiondoc.py index c49ccde1d..27f665222 100644 --- a/mathics/builtin/optiondoc.py +++ b/mathics/builtin/optiondoc.py @@ -176,10 +176,14 @@ class MaxRecursion(Builtin):
is an option for functions like NIntegrate and Plot that specifies how many recursive subdivisions can be made. - >> NIntegrate[Exp[-10^8 x^2], {x, -1, 1}, MaxRecursion -> 10] - = 1.97519×10^-207 + >> NIntegrate[Exp[-10^8 x^2], {x, -1, 1}, Method->"Internal", MaxRecursion -> 3] + = 0.0777778 + >> NIntegrate[Exp[-10^8 x^2], {x, -1, 1}, Method->"Internal", MaxRecursion -> 6] + = 0.00972222 """ + # This test does not pass if scipy is not available... + summary_text = "maximum number of recursive subdivisions" diff --git a/mathics/doc/common_doc.py b/mathics/doc/common_doc.py index b6ad88e52..dbf071825 100644 --- a/mathics/doc/common_doc.py +++ b/mathics/doc/common_doc.py @@ -138,6 +138,28 @@ test_result_map = {} +# TODO: Use this when checking requires for modules. +requires_lib_cache = {} + + +def check_requires_list(requires: list) -> bool: + global requires_cache + + for package in requires: + lib_is_installed = requires_lib_cache.get(package, None) + if lib_is_installed is None: + lib_is_installed = True + try: + importlib.import_module(package) + except ImportError: + lib_is_installed = False + requires_lib_cache[package] = lib_is_installed + + if not lib_is_installed: + return False + return True + + def get_results_by_test(test_expr: str, full_test_key: list, doc_data: dict) -> list: """ Sometimes test numbering is off, either due to bugs or changes since the @@ -665,6 +687,8 @@ def get_tests(self): # iterated below. Probably some other code is faulty and # when fixed the below loop and collection into doctest_list[] # will be removed. + if not docsubsection.installed: + continue doctest_list = [] index = 1 for doctests in docsubsection.items: @@ -906,13 +930,8 @@ def add_section( object to the chapter, a DocChapter object. "section_object" is either a Python module or a Class object instance. """ - installed = True - for package in getattr(section_object, "requires", []): - try: - importlib.import_module(package) - except ImportError: - installed = False - break + installed = check_requires_list(getattr(section_object, "requires", [])) + # FIXME add an additional mechanism in the module # to allow a docstring and indicate it is not to go in the # user manual @@ -949,17 +968,12 @@ def add_subsection( operator=None, in_guide=False, ): - installed = True - for package in getattr(instance, "requires", []): - try: - importlib.import_module(package) - except ImportError: - installed = False - break + installed = check_requires_list(getattr(instance, "requires", [])) # FIXME add an additional mechanism in the module # to allow a docstring and indicate it is not to go in the # user manual + if not instance.__doc__: return subsection = DocSubsection( @@ -1058,6 +1072,8 @@ def __init__(self, module=None): and var.__module__[: len(self.pymathicsmodule.__name__)] == self.pymathicsmodule.__name__ ): # nopep8 + if not check_requires_list(var): + continue instance = var(expression=False) if isinstance(instance, Builtin): self.symbols[instance.get_name()] = instance @@ -1105,13 +1121,7 @@ def __init__(self, module=None): chapter = DocChapter(builtin_part, title, XMLDoc(text)) for name in self.symbols: instance = self.symbols[name] - installed = True - for package in getattr(instance, "requires", []): - try: - importlib.import_module(package) - except ImportError: - installed = False - break + installed = check_requires_list(getattr(instance, "requires", [])) section = DocSection( chapter, strip_system_prefix(name), @@ -1329,8 +1339,12 @@ def get_tests(self): # A guide section's subsection are Sections without the Guide. # it is *their* subsections where we generally find tests. for section in self.subsections: + if not section.installed: + continue for subsection in section.subsections: # FIXME we are omitting the section title here... + if not subsection.installed: + continue for doctests in subsection.items: yield doctests.get_tests()