diff --git a/.github/workflows/buildwheel.yml b/.github/workflows/buildwheel.yml index 05630625..8b01fea5 100644 --- a/.github/workflows/buildwheel.yml +++ b/.github/workflows/buildwheel.yml @@ -68,7 +68,6 @@ jobs: python-version: ['3.9', '3.10', '3.11'] steps: - - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -77,26 +76,26 @@ jobs: name: artifact path: wheelhouse - run: pip install --find-links wheelhouse python_flint - - run: python test/test.py - - doctest_wheels: - needs: build_wheels - name: Doctests for ${{ matrix.python-version }} wheel on ${{ matrix.os }} - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-20.04, windows-2019, macos-12] - python-version: ['3.9', '3.10', '3.11'] + - run: python -m flint.test --verbose + test_pip_linux_vcs: + name: Install from git checkout on Ubuntu + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: ${{ matrix.python-version }} - - uses: actions/download-artifact@v3 + python-version: 3.11 + - run: bin/pip_install_ubuntu.sh . # Install from checkout + - run: python -m flint.test --verbose + + test_pip_linux_pypi: + name: Install from PyPI sdist on Ubuntu + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 with: - name: artifact - path: wheelhouse - - run: pip install --find-links wheelhouse python_flint - - run: python test/dtest.py + python-version: 3.11 + - run: bin/pip_install_ubuntu.sh python-flint # Install from PyPI sdist + - run: python -m flint.test --verbose diff --git a/.travis.yml b/.travis.yml index 13feb74f..6ddc8b57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,4 +28,4 @@ install: - pip install . script: - - python test/test.py + - python -m flint.test diff --git a/README.md b/README.md index 1fe3c28e..d75966cb 100644 --- a/README.md +++ b/README.md @@ -18,25 +18,43 @@ Author: Fredrik Johansson Installation ------------ -First install both FLINT (version 2.5 or later) and Arb (version 2.15 or later). -See: +On Windows (x86-64) or OSX (x86-64 or arm64) there are prebuilt wheels for +python-flint 0.4.1 that can be installed from PyPI using pip + + pip install python-flint + +There is currently a problem with the Linux wheels and so for now Linux wheels +are not available on PyPI. Instead for Linux first install both FLINT 2.9.0 and +Arb 2.23. Note that as of python-flint 0.4.1 only these *exact* versions of +FLINT and Arb will work. While some Linux distributions may provide FLINT and +Arb it is unlikely that they will provide the exact versions required (e.g. +for Ubuntu only Ubuntu 23.04 provides these versions at the time of writing). + +See here for instructions on building FLINT and Arb: * http://flintlib.org/ * http://arblib.org/ -The latest release of Python-FLINT can then be installed using: +The latest release of Python-FLINT can then be built and installed using: - pip install python-flint + pip install 'cython>=3' numpy wheel + pip install --no-build-isolation python-flint -Python-FLINT can also be installed git checkout or a source archive +Python-FLINT can also be installed from a git checkout or a source archive as follows: - pip install . + pip install 'cython>=3' numpy wheel + pip install --no-build-isolation . + +A script that builds and installs FLINT, Arb and Python-FLINT that is tested on +Ubuntu can be found in the git repo here: + +* https://github.com/fredrik-johansson/python-flint/blob/master/bin/pip_install_ubuntu.sh See the documentation for further notes on building and installing Python-FLINT: - https://fredrikj.net/python-flint/setup.html +* https://fredrikj.net/python-flint/setup.html Examples ------------------------------------- @@ -95,7 +113,6 @@ To do * Conversions to and from external types (numpy, sage, sympy, mpmath, gmpy) * Improved printing and string input/output * IPython hooks (TeX pretty-printing etc.) -* Windows support License ------------ diff --git a/bin/build_mingw64_wheel.sh b/bin/build_mingw64_wheel.sh index bd8eae80..3ce1787d 100755 --- a/bin/build_mingw64_wheel.sh +++ b/bin/build_mingw64_wheel.sh @@ -44,7 +44,7 @@ fi PYTHON=$PYTHONDIR/python VER="${PYTHONVER//./}" -WHEELNAME=python_flint-0.4.0-cp$VER-cp$VER-win_amd64.whl +WHEELNAME=python_flint-0.4.1-cp$VER-cp$VER-win_amd64.whl $PYTHON -c 'print("hello world")' @@ -90,7 +90,7 @@ wheel pack python_flint-* cd .. # Make the wheel relocatable -delvewheel repair dist/python_flint-0.4.0-cp$VER-cp$VER-win_amd64.whl \ +delvewheel repair dist/python_flint-0.4.1-cp$VER-cp$VER-win_amd64.whl \ --add-path .local/bin:.local/lib/ # Make a virtual enironment to test the wheel diff --git a/bin/cibw.sh b/bin/cibw.sh index 1e20ce34..2f84d5f6 100755 --- a/bin/cibw.sh +++ b/bin/cibw.sh @@ -29,7 +29,7 @@ export CIBW_BEFORE_BUILD_WINDOWS='C:\\msys64\\usr\\bin\\bash bin/cibw_before_bui export CIBW_REPAIR_WHEEL_COMMAND_WINDOWS='bin\cibw_repair_wheel_command_windows.bat {dest_dir} {wheel}' # export CIBW_TEST_COMMAND="python -c 'import flint; print(str(flint.fmpz(2)))'" -export CIBW_TEST_COMMAND="python {project}/test/test.py && python {project}/test/dtest.py" +export CIBW_TEST_COMMAND="python -m flint.test" # cibuildwheel --platform linux # cibuildwheel --platform windows diff --git a/bin/coverage.sh b/bin/coverage.sh index aec78737..eeb30f96 100755 --- a/bin/coverage.sh +++ b/bin/coverage.sh @@ -33,8 +33,7 @@ export PYTHON_FLINT_COVERAGE=true python setup.py build_ext --inplace -pytest --cov flint test/test.py -coverage run --append test/dtest.py +coverage run -m flint.test $@ #coverage report -m coverage html diff --git a/bin/pip_install_ubuntu.sh b/bin/pip_install_ubuntu.sh new file mode 100755 index 00000000..ecc8ebf7 --- /dev/null +++ b/bin/pip_install_ubuntu.sh @@ -0,0 +1,87 @@ +#!/bin/bash + +set -o errexit + +# This script should work to install python-flint on Ubuntu from a VCS checkout +# +# $ git checkout https://github.com/fredrik-johansson/python-flint.git +# $ bin/pip_install_ubuntu.sh . +# +# To install an sdist from PyPI, use +# +# $ bin/pip_install_ubuntu.sh python-flint +# + +# Install runtime and build dependencies + +# The commented commands below would attempt to build python-flint against a +# system installation of Flint and Arb in Ubuntu. +# +# Ubuntu 23.04 has Flint 2.9.0 and Arb 2.23.0, so this script might work there +# (for python-flint 0.4.1). That is untested though (23.04 not available in CI). +# +# With Ubuntu 22.04, this will build but then crashes when running the tests. +# most likely this is because the versions of flint and flint-arb are too old. +# At the time of writing in Ubuntu 22.04 there is Flint 2.8.4 and Arb 2.22. The +# main CI tests and wheels for python-flint 0.4.1 are built with Flint 2.9.0 +# and Arb 2.23.0. +# +# Link against libflint-arb instead of libarb on Ubuntu +# export PYTHON_FLINT_LIBFLINT_ARB=1 +# sudo apt-get update +# sudo apt-get install libflint-dev libflint-arb-dev + + +# Build Flint and Arb manually +# +# First install their dependencies and build dependencies +sudo apt-get update +sudo apt-get install libgmp-dev libmpfr-dev xz-utils + +# Only these *EXACT* versions will work. +FLINTVER=2.9.0 +ARBVER=2.23.0 + +# This will default to installing in /usr/local. If you want to install in a +# non-standard location then configure flint with +# ./configure --disable-static --prefix=$PREFIX +# and arb with +# ./configure --disable-static --prefix=$PREFIX --with-flint=$PREFIX +# If $PREFIX is no in default search paths, then at build time set +# export C_INCLUDE_PATH=$PREFIX/include +# and at runtime set +# export LD_LIBRARY_PATH=$PREFIX/lib + +curl -O -L https://www.flintlib.org/flint-$FLINTVER.tar.gz +tar xf flint-$FLINTVER.tar.gz +cd flint-$FLINTVER + ./configure --disable-static + make -j + sudo make install +cd .. + +curl -O -L https://github.com/fredrik-johansson/arb/archive/refs/tags/$ARBVER.tar.gz +mv $ARBVER.tar.gz arb-$ARBVER.tar.gz +tar xf arb-$ARBVER.tar.gz +cd arb-$ARBVER + ./configure --disable-static + make -j + sudo make install +cd .. + +ls -l /usr/local/lib +sudo ldconfig /usr/local/lib + +# Python build requirements. Ideally these would be in pyprojec.toml, but +# first need to migrate from setup.py to pyproject.toml. +pip install 'cython>=3' numpy wheel + +# Install from checkout (or sdist). +echo ----------------------------------------------------------- +echo +echo Running: +echo $ pip install --no-build-isolation $1 +echo +echo ----------------------------------------------------------- + +pip install --no-build-isolation $1 diff --git a/doc/source/conf.py b/doc/source/conf.py index c2ae42cc..98ff53aa 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -51,9 +51,9 @@ # built documents. # # The short X.Y version. -version = '0.4.0' +version = '0.4.1' # The full version, including alpha/beta/rc tags. -release = '0.4.0' +release = '0.4.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/source/setup.rst b/doc/source/setup.rst index e4389152..8865850b 100644 --- a/doc/source/setup.rst +++ b/doc/source/setup.rst @@ -42,8 +42,7 @@ Then run:: Run the test suite:: - python test/test.py - python test/dtest.py + python -m flint.test Build the documentation:: @@ -86,8 +85,7 @@ you can then build Python-FLINT in place with:: and run the test suite with:: - python test/test.py - python test/dtest.py + python -m flint.test This way of building Python-FLINT depends on the ``bin/activate`` script to locate the shared libraries at runtime. The script will also set ``PYTHONPATH`` diff --git a/setup.py b/setup.py index 0ad57646..5888fc1a 100644 --- a/setup.py +++ b/setup.py @@ -34,7 +34,13 @@ # For the MSVC toolchain link with mpir instead of gmp libraries = ["arb", "flint", "mpir", "mpfr", "pthreads"] else: - libraries = ["arb", "flint"] + # On Ubuntu libarb.so is called libflint-arb.so + if os.getenv('PYTHON_FLINT_LIBFLINT_ARB'): + arb = 'flint-arb' + else: + arb = 'arb' + + libraries = [arb, "flint"] (opt,) = get_config_vars('OPT') os.environ['OPT'] = " ".join(flag for flag in opt.split() if flag != '-Wstrict-prototypes') @@ -75,10 +81,12 @@ cmdclass={'build_ext': build_ext}, ext_modules=cythonize(ext_modules, compiler_directives=compiler_directives), #ext_modules=cythonize(ext_modules, compiler_directives=compiler_directives, annotate=True), - packages=['flint'], + packages=['flint', 'flint.test'], package_dir={'': 'src'}, description='Bindings for FLINT and Arb', - version='0.4.0', + long_description=open('README.md').read(), + long_description_content_type='text/markdown', + version='0.4.1', url='https://github.com/python-flint/python-flint', author='Fredrik Johansson', author_email='fredrik.johansson@gmail.com', diff --git a/src/flint/__init__.py b/src/flint/__init__.py index 42d566bf..cec8c1bf 100644 --- a/src/flint/__init__.py +++ b/src/flint/__init__.py @@ -1,3 +1,3 @@ from ._flint import * -__version__ = '0.4.0' +__version__ = '0.4.1' diff --git a/src/flint/test/__init__.py b/src/flint/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/flint/test/__main__.py b/src/flint/test/__main__.py new file mode 100644 index 00000000..a90ec10f --- /dev/null +++ b/src/flint/test/__main__.py @@ -0,0 +1,129 @@ +# +# Run the python-flint test-suite as +# +# python -m flint.test +# + +import sys +import doctest +import traceback +import argparse + +import flint +from flint.test.test import all_tests + + +def run_tests(verbose=None): + """Run all tests + + This is usually called by + + $ python -m flint.flint + """ + # Show the limited output by default + if verbose is None: + verbose = True + + total = 0 + failed = 0 + + for test in all_tests: + + if verbose: + print(f'{test.__name__}...', end='', flush=True) + + try: + test() + except Exception as e: + print(f'Error in {test.__name__}') + if verbose: + traceback.print_exc() + failed += 1 + else: + if verbose: + print('OK') + + total += 1 + + return failed, total + + +def run_doctests(verbose=None): + """Run the python-flint doctests""" + # Here verbose=True shows a lot of output. + failed, total = doctest.testmod(flint._flint, verbose=verbose) + return failed, total + + +def run_all_tests(tests=True, doctests=True, verbose=None): + + success = True + + if tests: + print("Running tests...") + t_failed, t_total = run_tests(verbose=verbose) + + if doctests: + print("Running doctests...") + d_failed, d_total = run_doctests(verbose=verbose) + + if tests: + if t_failed: + print(f'flint.test: {t_failed} of {t_total} tests failed') + success = False + else: + print(f'flint.test: all {t_total} tests passed!') + + if doctests: + if d_failed: + print(f'flint.test: {d_failed} of {d_total} doctests failed') + success = False + else: + print(f'flint.test: all {d_total} doctests passed!') + + return success + + +def main(*args): + """Run the python-flint test-suite""" + + parser = argparse.ArgumentParser(description="Run the python-flint test-suite") + parser.add_argument("--quiet", "-q", action="store_true", help="less verbose output") + parser.add_argument("--verbose", "-v", action="store_true", help="more verbose output") + parser.add_argument("--tests", "-t", action="store_true", help="run tests") + parser.add_argument("--doctests", "-d", action="store_true", help="run doctests") + args = parser.parse_args(args) + + if not args.tests and not args.doctests: + # Default is run all tests: + tests = True + doctests = True + else: + # Either --tests or --doctests was specified + tests = args.tests + doctests = args.doctests + + # Default is show output from tests but keep the doctests quiet. + if args.verbose: + verbose = True + elif args.quiet: + verbose = False + else: + verbose = None + + success = run_all_tests(tests=tests, doctests=doctests, verbose=verbose) + + if not success: + print("----------------------------------------") + print("!!!FAILED!!!: Something is wrong with your installation of python-flint!") + print("----------------------------------------") + return 1 + else: + print("----------------------------------------") + print("OK: Your installation of python-flint seems to be working just fine!") + print("----------------------------------------") + return 0 + + +if __name__ == "__main__": + sys.exit(main(*sys.argv[1:])) diff --git a/test/test.py b/src/flint/test/test.py similarity index 97% rename from test/test.py rename to src/flint/test/test.py index 55cbfe7f..69c62ecc 100644 --- a/test/test.py +++ b/src/flint/test/test.py @@ -30,7 +30,7 @@ def raises(f, exception): def test_pyflint(): - assert flint.__version__ == "0.4.0" + assert flint.__version__ == "0.4.1" ctx = flint.ctx assert str(ctx) == repr(ctx) == _default_ctx_string @@ -1558,22 +1558,23 @@ def test_pickling(): obj2 = pickle.loads(s) assert obj == obj2 -if __name__ == "__main__": - sys.stdout.write("test_pyflint..."); test_pyflint(); print("OK") - sys.stdout.write("test_fmpz..."); test_fmpz(); print("OK") - sys.stdout.write("test_fmpz_factor..."); test_fmpz_factor(); print("OK") - sys.stdout.write("test_fmpz_functions..."); test_fmpz_functions(); print("OK") - sys.stdout.write("test_fmpz_poly..."); test_fmpz_poly(); print("OK") - sys.stdout.write("test_fmpz_poly_factor..."); test_fmpz_poly_factor(); print("OK") - sys.stdout.write("test_fmpz_poly_functions..."); test_fmpz_poly_functions(); print("OK") - sys.stdout.write("test_fmpz_mat..."); test_fmpz_mat(); print("OK") - sys.stdout.write("test_fmpz_series..."); test_fmpz_series(); print("OK") - sys.stdout.write("test_fmpq..."); test_fmpq(); print("OK") - sys.stdout.write("test_fmpq_poly..."); test_fmpq_poly(); print("OK") - sys.stdout.write("test_fmpq_mat..."); test_fmpq_mat(); print("OK") - sys.stdout.write("test_fmpq_series..."); test_fmpq_series(); print("OK") - sys.stdout.write("test_nmod..."); test_nmod(); print("OK") - sys.stdout.write("test_nmod_poly..."); test_nmod_poly(); print("OK") - sys.stdout.write("test_nmod_mat..."); test_nmod_mat(); print("OK") - sys.stdout.write("test_arb.."); test_arb(); print("OK") - print("OK") + +all_tests = [ + test_pyflint, + test_fmpz, + test_fmpz_factor, + test_fmpz_functions, + test_fmpz_poly, + test_fmpz_poly_factor, + test_fmpz_poly_functions, + test_fmpz_mat, + test_fmpz_series, + test_fmpq, + test_fmpq_poly, + test_fmpq_mat, + test_fmpq_series, + test_nmod, + test_nmod_poly, + test_nmod_mat, + test_arb, +] diff --git a/test/dtest.py b/test/dtest.py deleted file mode 100644 index 754a8b90..00000000 --- a/test/dtest.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys -import doctest -import flint - -sys.stdout.write("doctests..."); -fail, total = doctest.testmod(flint._flint); -if fail == 0: - print("OK") -else: - raise AssertionError("%i of %i doctests failed" % (fail, total))