diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2f65bb72..bc0c6247 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -4,7 +4,7 @@ # token stolen if the Action is compromised. See the comments and links here: # https://github.com/pypa/gh-action-pypi-publish/issues/27 # -name: docs +name: documentation # Only build PRs, the main branch, and releases. Pushes to branches will only # be built when a PR is opened. This avoids duplicated buids in PRs comming @@ -21,10 +21,7 @@ on: # Use bash by default in all jobs defaults: run: - # The -l {0} is necessary for conda environments to be activated - # But this breaks on MacOS if using actions/setup-python: - # https://github.com/actions/setup-python/issues/132 - shell: bash -l {0} + shell: bash jobs: ############################################################################# @@ -32,11 +29,7 @@ jobs: build: runs-on: ubuntu-latest env: - REQUIREMENTS: requirements.txt - REQUIREMENTS_DEV: requirements-dev.txt - REQUIREMENTS_OPTIONAL: requirements-optional.txt - DEPENDENCIES: optional - INSTALL_EXTRA: + REQUIREMENTS: env/requirements-docs.txt PYTHON: 3.9 steps: @@ -70,6 +63,23 @@ jobs: with: python-version: ${{ env.PYTHON }} + - name: Collect requirements - run-time + run: python tools/export_requirements.py > requirements-full.txt + + - name: Collect requirements - other + run: | + echo "Capturing dependencies from:" + for requirement in $REQUIREMENTS + do + echo " $requirement" + cat $requirement >> requirements-full.txt + done + + - name: List requirements + run: | + echo "Collected dependencies:" + cat requirements-full.txt + - name: Get the pip cache folder id: pip-cache run: | @@ -79,45 +89,17 @@ jobs: uses: actions/cache@v2 with: path: ${{ steps.pip-cache.outputs.dir }} - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} - restore-keys: | - ${{ runner.os }}-pip- + key: ${{ runner.os }}-pip-${{ hashFiles('requirements-full.txt') }} - name: Install requirements run: | - requirements_file=requirements-full.txt - if [ ! -z "$REQUIREMENTS" ]; then - echo "Capturing dependencies from $REQUIREMENTS" - cat $REQUIREMENTS >> $requirements_file - fi - if [ ! -z "$REQUIREMENTS_DEV" ]; then - echo "Capturing dependencies from $REQUIREMENTS_DEV" - cat $REQUIREMENTS_DEV >> $requirements_file - fi - if [ "$DEPENDENCIES" == "optional" ]; then - echo "Capturing optional dependencies from $REQUIREMENTS_OPTIONAL" - cat $REQUIREMENTS_OPTIONAL >> $requirements_file - fi - if [ ! -z "$INSTALL_EXTRA" ]; then - echo "Capturing extra dependencies: $INSTALL_EXTRA" - echo "# Extra" >> $requirements_file - # Use xargs to print one argument per line - echo $INSTALL_EXTRA | xargs -n 1 >> $requirements_file - fi - if [ -f $requirements_file ]; then - echo "Collected dependencies:" - cat $requirements_file - echo "" - # Install wheel before anything else so pip can use wheels for - # other packages. - python -m pip install setuptools wheel - python -m pip install --requirement $requirements_file - else - echo "No requirements defined." - fi + # Install the build requirements before anything else so pip can use + # wheels for other packages. + python -m pip install --requirement env/requirements-build.txt + python -m pip install --requirement requirements-full.txt - name: List installed packages - run: pip freeze + run: python -m pip freeze - name: Build source and wheel distributions run: | @@ -127,7 +109,7 @@ jobs: ls -lh dist/ - name: Install the package - run: pip install --no-deps dist/*.whl + run: python -m pip install dist/*.whl - name: Build the documentation run: make -C doc clean all diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 79e816b3..f07db933 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -6,8 +6,8 @@ # name: pypi -# Only run for pushes to the main branch and releases. on: + pull_request: push: branches: - main @@ -21,13 +21,11 @@ defaults: shell: bash jobs: + ############################################################################# - # Publish built wheels and source archives to PyPI and test PyPI - publish: + # Build and check wheels and source distrubutions + build: runs-on: ubuntu-latest - # Only publish from the origin repository, not forks - if: github.repository_owner == 'fatiando' - steps: # Checks-out your repository under $GITHUB_WORKSPACE - name: Checkout @@ -52,7 +50,9 @@ jobs: python-version: "3.9" - name: Install requirements - run: python -m pip install setuptools setuptools_scm twine wheel + run: | + python -m pip install -r env/requirements-build.txt + python -m pip install twine - name: List installed packages run: python -m pip freeze @@ -63,7 +63,7 @@ jobs: # Change setuptools-scm local_scheme to "no-local-version" so the # local part of the version isn't included, making the version string # compatible with Test PyPI. - sed --in-place "s/node-and-date/no-local-version/g" setup.py + sed --in-place "s/node-and-date/no-local-version/g" pyproject.toml - name: Build source and wheel distributions run: | @@ -75,8 +75,41 @@ jobs: - name: Check the archives run: twine check dist/* + # Store the archives as a build artifact so we can deploy them later + - name: Upload archives as artifacts + # Only if not a pull request + if: success() && github.event_name != 'pull_request' + uses: actions/upload-artifact@v2 + with: + name: pypi-${{ github.sha }} + path: dist + + ############################################################################# + # Publish built wheels and source archives to PyPI and test PyPI + publish: + runs-on: ubuntu-latest + needs: build + # Only publish from the origin repository, not forks + if: github.repository_owner == 'fatiando' && github.event_name != 'pull_request' + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + # The GitHub token is preserved by default but this job doesn't need + # to be able to push to GitHub. + persist-credentials: false + + # Fetch the built archives from the "build" job + - name: Download built archives artifact + uses: actions/download-artifact@v2 + with: + name: pypi-${{ github.sha }} + path: dist + - name: Publish to Test PyPI - if: success() + # Only publish to TestPyPI when a PR is merged (pushed to main) + if: success() && github.event_name == 'push' uses: pypa/gh-action-pypi-publish@bce3b74dbf8cc32833ffba9d15f83425c1a736e0 with: user: __token__ diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 8b7a5b1a..c4c549a7 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -4,7 +4,7 @@ # token stolen if the Action is compromised. See the comments and links here: # https://github.com/pypa/gh-action-pypi-publish/issues/27 # -name: code-style +name: checks # Only build PRs and the main branch. Pushes to branches will only be built # when a PR is opened. @@ -16,9 +16,7 @@ on: ############################################################################### jobs: - - black: - name: black [format] + format: runs-on: ubuntu-latest steps: - name: Checkout @@ -29,19 +27,18 @@ jobs: - name: Setup Python uses: actions/setup-python@v2 with: - python-version: '3.9' + python-version: "3.10" - name: Install requirements - run: pip install black + run: python -m pip install -r env/requirements-style.txt - name: List installed packages - run: pip freeze + run: python -m pip freeze - name: Check code format - run: make black-check + run: make black-check license-check - flake8: - name: flake8 [style] + style: runs-on: ubuntu-latest steps: - name: Checkout @@ -52,59 +49,13 @@ jobs: - name: Setup Python uses: actions/setup-python@v2 with: - python-version: '3.9' + python-version: "3.10" - name: Install requirements - run: pip install flake8 + run: python -m pip install -r env/requirements-style.txt - name: List installed packages - run: pip freeze + run: python -m pip freeze - name: Check code style - run: make flake8 - - pylint: - name: pylint [style] - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - - name: Install requirements - run: pip install pylint==2.4.* - - - name: List installed packages - run: pip freeze - - - name: Linting (pylint) - run: make lint - - license: - name: license [style] - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - persist-credentials: false - - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - - name: Install requirements - run: pip install pathspec - - - name: List installed packages - run: pip freeze - - - name: Check license notice on all source files - run: make license-check + run: make flake8 lint diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7b0c575c..cd64f86e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,27 +28,30 @@ jobs: ############################################################################# # Run tests and upload to codecov test: - name: ${{ matrix.os }} py${{ matrix.python }} ${{ matrix.dependencies }} + name: ${{ matrix.os }} python=${{ matrix.python }} dependencies=${{ matrix.dependencies }} runs-on: ${{ matrix.os }}-latest strategy: # Otherwise, the workflow would stop if a single job fails. We want to # run all of them to catch failures in different combinations. fail-fast: false matrix: - os: [ubuntu, macos, windows] - python: ["3.6", "3.10"] - # If "optional", will install non-required dependencies in the build - # environment. Otherwise, only required dependencies are installed. - dependencies: ["", optional] + os: + - ubuntu + - macos + - windows + python: + - "3.6" + - "3.10" + dependencies: + - latest + - optional + - oldest env: - REQUIREMENTS: requirements.txt - REQUIREMENTS_DEV: requirements-dev.txt - REQUIREMENTS_OPTIONAL: requirements-optional.txt - INSTALL_EXTRA: - DEPENDENCIES: ${{ matrix.dependencies }} + REQUIREMENTS: env/requirements-test.txt # Used to tag codecov submissions OS: ${{ matrix.os }} PYTHON: ${{ matrix.python }} + DEPENDENCIES: ${{ matrix.dependencies }} steps: # Cancel any previous run of the test job @@ -81,6 +84,31 @@ jobs: with: python-version: ${{ matrix.python }} + - name: Collect requirements - run-time + run: python tools/export_requirements.py > requirements-full.txt + + - name: Collect requirements - optional + if: matrix.dependencies == 'optional' || matrix.dependencies == 'oldest' + run: cat env/requirements-optional.txt >> requirements-full.txt + + - name: Collect requirements - convert to oldest supported + if: matrix.dependencies == 'oldest' + run: python tools/oldest_requirements.py requirements-full.txt + + - name: Collect requirements - other + run: | + echo "Capturing dependencies from:" + for requirement in $REQUIREMENTS + do + echo " $requirement" + cat $requirement >> requirements-full.txt + done + + - name: List requirements + run: | + echo "Collected dependencies:" + cat requirements-full.txt + - name: Get the pip cache folder id: pip-cache run: | @@ -90,45 +118,14 @@ jobs: uses: actions/cache@v2 with: path: ${{ steps.pip-cache.outputs.dir }} - key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }} - restore-keys: | - ${{ runner.os }}-pip- + key: ${{ runner.os }}-pip-${{ hashFiles('requirements-full.txt') }} - name: Install requirements run: | - requirements_file=requirements-full.txt - if [ ! -z "$REQUIREMENTS" ]; then - echo "Capturing dependencies from $REQUIREMENTS" - cat $REQUIREMENTS >> $requirements_file - fi - if [ ! -z "$REQUIREMENTS_DEV" ]; then - echo "Capturing dependencies from $REQUIREMENTS_DEV" - cat $REQUIREMENTS_DEV >> $requirements_file - fi - if [ "$DEPENDENCIES" == "optional" ]; then - echo "Capturing optional dependencies from $REQUIREMENTS_OPTIONAL" - cat $REQUIREMENTS_OPTIONAL >> $requirements_file - fi - if [ ! -z "$INSTALL_EXTRA" ]; then - echo "Capturing extra dependencies: $INSTALL_EXTRA" - echo "# Extra" >> $requirements_file - # Use xargs to print one argument per line - echo $INSTALL_EXTRA | xargs -n 1 >> $requirements_file - fi - if [ -f $requirements_file ]; then - echo "Collected dependencies:" - cat $requirements_file - echo "" - # Install wheel before anything else so pip can use wheels for - # other packages. - python -m pip install setuptools wheel - python -m pip install --requirement $requirements_file - else - echo "No requirements defined." - fi - - - name: List installed packages - run: pip freeze + # Install the build requirements before anything else so pip can use + # wheels for other packages. + python -m pip install --requirement env/requirements-build.txt + python -m pip install --requirement requirements-full.txt - name: Build source and wheel distributions run: | @@ -138,7 +135,10 @@ jobs: ls -lh dist/ - name: Install the package - run: pip install --no-deps dist/*.whl + run: python -m pip install --no-deps dist/*.whl + + - name: List installed packages + run: python -m pip freeze - name: Run the tests run: make test diff --git a/MANIFEST.in b/MANIFEST.in index 3eed9ae7..c9ec456b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,11 +3,12 @@ prune .github prune data prune doc +prune env prune paper exclude .*.yml exclude .*rc -exclude requirements*.txt exclude Makefile exclude .gitignore exclude .gitattributes exclude environment.yml +exclude license_notice.py diff --git a/Makefile b/Makefile index f2e7187f..9b42e628 100644 --- a/Makefile +++ b/Makefile @@ -3,16 +3,15 @@ PROJECT=pooch TESTDIR=tmp-test-dir-with-unique-name PYTEST_ARGS=--cov-config=../.coveragerc --cov-report=term-missing --cov=$(PROJECT) --doctest-modules -v --pyargs LINT_FILES=setup.py $(PROJECT) -BLACK_FILES=setup.py doc/conf.py $(PROJECT) license_notice.py -FLAKE8_FILES=setup.py doc/conf.py $(PROJECT) license_notice.py +CHECK_STYLE=setup.py doc/conf.py $(PROJECT) tools help: @echo "Commands:" @echo "" @echo " install install in editable mode" @echo " test run the test suite (including doctests) and report coverage" - @echo " format run black to automatically format the code" - @echo " check run code style and quality checks (black and flake8)" + @echo " format automatically format the code" + @echo " check run code style and quality checks" @echo " lint run pylint for a deeper (and slower) quality check" @echo " clean clean up build and generated files" @echo "" @@ -27,22 +26,24 @@ test: cp $(TESTDIR)/.coverage* . rm -r $(TESTDIR) -format: license - black $(BLACK_FILES) +format: license black -check: black-check flake8 license-check +check: black-check license-check flake8 + +black: + black $(CHECK_STYLE) black-check: - black --check $(BLACK_FILES) + black --check $(CHECK_STYLE) license: - python license_notice.py + python tools/license_notice.py license-check: - python license_notice.py --check + python tools/license_notice.py --check flake8: - flake8 $(FLAKE8_FILES) + flake8 $(CHECK_STYLE) lint: pylint --jobs=0 $(LINT_FILES) diff --git a/doc/compatibility.rst b/doc/compatibility.rst index 6e1b4a22..71d184fe 100644 --- a/doc/compatibility.rst +++ b/doc/compatibility.rst @@ -1,10 +1,10 @@ .. _compatibility: -Compatibility notes -=================== +Version compatibility +===================== -Pooch version compatibility ---------------------------- +Pooch backwards incompatible changes +------------------------------------ We try to retain backwards compatibility whenever possible. Major breaking changes to the Pooch API will be marked by a major release and deprecation @@ -28,12 +28,31 @@ If there are any backwards incompatible changes, they will be listed below: to update to capturing logs instead.** The vast majority of users are unaffected. +.. _dependency-versions: + +Supported dependency versions +----------------------------- + +Pooch follows the recommendations in +`NEP29 `__ for setting +the minimum required version of our dependencies. +In short, we support **all minor releases of our dependencies from the previous +24 months** before a Pooch release with a minimum of 2 minor releases. + +We follow this guidance conservatively and won't require newer versions if the +older ones are still working without causing problems. +Whenever support for a version is dropped, we will include a note in the +:ref:`changes`. + +.. note:: + + This was introduced in Pooch v1.6.0. .. _python-versions: -Python version compatibility ----------------------------- +Supported Python versions +------------------------- If you require support for older Python versions, please pin Pooch to the following releases to ensure compatibility: diff --git a/doc/hashes.rst b/doc/hashes.rst index 995df8fa..ba30f2d0 100644 --- a/doc/hashes.rst +++ b/doc/hashes.rst @@ -98,6 +98,9 @@ the files once, unless they are deleted from the cache. If this script is run over a period of time, your cache directory will increase in size, as the files are stored in daily subdirectories. + +.. _hashes-other: + Other supported hashes ---------------------- diff --git a/doc/install.rst b/doc/install.rst index b560bb73..370b63a3 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -3,30 +3,15 @@ Installing ========== -Which Python? -------------- - -You'll need **Python >= 3.6** (see :ref:`python-versions` if you -require support for older versions). - -We recommend using the -`Anaconda `__ -or `Miniconda `__ -Python distributions to ensure you have all dependencies installed and the -``conda`` package manager available. -Installing Anaconda does not require administrative rights to your computer and -doesn't interfere with any other Python installations in your system. - -.. note:: +There are different ways to install Pooch: - The commands below should be executed in a terminal. On Windows, use the - "Anaconda Prompt" app or ``cmd.exe`` if you're not using Anaconda. +.. tabbed:: pip + Using the `pip `__ package manager: -Installing ----------- + .. code:: bash -There are different ways to install Pooch: + python -m pip install pooch .. tabbed:: conda @@ -37,23 +22,25 @@ There are different ways to install Pooch: conda install pooch --channel conda-forge -.. tabbed:: pip +.. tabbed:: Development version - Using the `pip `__ package manager: + Using ``pip`` to install the latest **unreleased** version from GitHub + (**not recommended** in most situations): .. code:: bash - python -m pip install pooch - - -.. tabbed:: Development version + python -m pip install --upgrade git+https://github.com/fatiando/pooch - Using ``pip`` to install the latest **unreleased** version from GitHub: +.. note:: - .. code:: bash + The commands above should be executed in a terminal. On Windows, use the + ``cmd.exe`` or the "Anaconda Prompt" app if you're using Anaconda. - python -m pip install --upgrade git+https://github.com/fatiando/pooch +Which Python? +------------- +You'll need **Python >= 3.6**. See :ref:`python-versions` if you +require support for older versions. .. _dependencies: @@ -66,9 +53,9 @@ manually. Required: -* `requests `__ -* `packaging `__ * `appdirs `__ +* `packaging `__ +* `requests `__ Optional: @@ -76,3 +63,5 @@ Optional: progress bar. See :ref:`progressbars`. * `paramiko `__: For SFTP downloads. See :class:`pooch.SFTPDownloader`. +* `xxhash `__: For the faster xxHash + algorithms. See :ref:`hashes-other`. diff --git a/env/requirements-build.txt b/env/requirements-build.txt new file mode 100644 index 00000000..12218e83 --- /dev/null +++ b/env/requirements-build.txt @@ -0,0 +1,4 @@ +# Requirements for building +setuptools_scm>=6.2 +setuptools>=45 +wheel diff --git a/env/requirements-docs.txt b/env/requirements-docs.txt new file mode 100644 index 00000000..7a23ae28 --- /dev/null +++ b/env/requirements-docs.txt @@ -0,0 +1,4 @@ +# Documentation requirements +sphinx==3.5.* +sphinx-book-theme==0.0.41 +sphinx-panels==0.5.* diff --git a/env/requirements-optional.txt b/env/requirements-optional.txt new file mode 100644 index 00000000..792588e0 --- /dev/null +++ b/env/requirements-optional.txt @@ -0,0 +1,4 @@ +# Optional dependencies +tqdm>=4.41.0,<5.0.0 +paramiko>=2.7.0 +xxhash>=1.4.3 diff --git a/env/requirements-style.txt b/env/requirements-style.txt new file mode 100644 index 00000000..21ef9c09 --- /dev/null +++ b/env/requirements-style.txt @@ -0,0 +1,5 @@ +# Style checks +black +flake8 +pylint==2.4.* +pathspec diff --git a/env/requirements-test.txt b/env/requirements-test.txt new file mode 100644 index 00000000..3476db60 --- /dev/null +++ b/env/requirements-test.txt @@ -0,0 +1,5 @@ +# Testing requirements +pytest +pytest-cov +pytest-localftpserver +coverage diff --git a/pooch/tests/test_downloaders.py b/pooch/tests/test_downloaders.py index 1bac43a9..01afe56b 100644 --- a/pooch/tests/test_downloaders.py +++ b/pooch/tests/test_downloaders.py @@ -54,7 +54,6 @@ [ BASEURL + "tiny-data.txt", # HTTPDownloader FIGSHAREURL, # DOIDownloader - "sftp://test.rebex.net/pub/example/pocketftp.png", # SFTPDownloader ], ) def test_progressbar_kwarg_passed(url): @@ -63,6 +62,14 @@ def test_progressbar_kwarg_passed(url): assert downloader.progressbar is True +@pytest.mark.skipif(paramiko is None, reason="requires paramiko") +def test_progressbar_kwarg_passed_sftp(): + """The progressbar keyword argument must pass through choose_downloader""" + url = "sftp://test.rebex.net/pub/example/pocketftp.png" + downloader = choose_downloader(url, progressbar=True) + assert downloader.progressbar is True + + def test_unsupported_protocol(): "Should raise ValueError when protocol is not supported" with pytest.raises(ValueError): diff --git a/pooch/tests/test_hashes.py b/pooch/tests/test_hashes.py index 1b553f90..9932b986 100644 --- a/pooch/tests/test_hashes.py +++ b/pooch/tests/test_hashes.py @@ -14,6 +14,14 @@ import pytest +try: + import xxhash + + XXHASH_MAJOR_VERSION = int(xxhash.VERSION.split(".")[0]) +except ImportError: + xxhash = None + XXHASH_MAJOR_VERSION = 0 + from ..core import Pooch from ..hashes import ( make_registry, @@ -36,11 +44,12 @@ "md5": "70e2afd3fd7e336ae478b1e740a5f08e", } TINY_DATA_HASHES_XXH = { + "xxh64": "f843815fe57948fa", + "xxh32": "98d6f1a2", + # Require xxHash > 2.0 "xxh128": "0267d220db258fffb0c567c0ecd1b689", "xxh3_128": "0267d220db258fffb0c567c0ecd1b689", - "xxh64": "f843815fe57948fa", "xxh3_64": "811e3f2a12aec53f", - "xxh32": "98d6f1a2", } TINY_DATA_HASHES = TINY_DATA_HASHES_HASHLIB.copy() TINY_DATA_HASHES.update(TINY_DATA_HASHES_XXH) @@ -113,7 +122,10 @@ def test_file_hash_invalid_algorithm(): def test_file_hash(alg, expected_hash): "Test the hash calculation using hashlib and xxhash" if alg.startswith("xxh"): - pytest.importorskip("xxhash") + if xxhash is None: + pytest.skip("requires xxhash") + if alg not in ["xxh64", "xxh32"] and XXHASH_MAJOR_VERSION < 2: + pytest.skip("requires xxhash > 2.0") fname = os.path.join(DATA_DIR, "tiny-data.txt") check_tiny_data(fname) returned_hash = file_hash(fname, alg) @@ -128,7 +140,10 @@ def test_file_hash(alg, expected_hash): def test_hash_matches(alg, expected_hash): "Make sure the hash checking function works" if alg.startswith("xxh"): - pytest.importorskip("xxhash") + if xxhash is None: + pytest.skip("requires xxhash") + if alg not in ["xxh64", "xxh32"] and XXHASH_MAJOR_VERSION < 2: + pytest.skip("requires xxhash > 2.0") fname = os.path.join(DATA_DIR, "tiny-data.txt") check_tiny_data(fname) # Check if the check passes diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..5e2ca61f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +# Specify that we use setuptools and setuptools_scm (to generate the version +# string). Actual configuration is in setup.py and setup.cfg. +[build-system] +requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +version_scheme = "post-release" +local_scheme = "node-and-date" +write_to = "pooch/_version.py" + +[tool.pytest.ini_options] +markers = [ + "network: test requires network access", +] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 5a1a202e..00000000 --- a/pytest.ini +++ /dev/null @@ -1,3 +0,0 @@ -[pytest] -markers = - network: test requires network access diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 1704cfe3..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,9 +0,0 @@ -# Development requirements -setuptools_scm -pytest -pytest-cov -pytest-localftpserver -coverage -sphinx==3.5.* -sphinx-book-theme==0.0.41 -sphinx-panels==0.5.* diff --git a/requirements-optional.txt b/requirements-optional.txt deleted file mode 100644 index e089c14e..00000000 --- a/requirements-optional.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Optional dependencies -tqdm -paramiko -xxhash diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index fae3aa26..00000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -requests -packaging -appdirs diff --git a/setup.cfg b/setup.cfg index 64b434fc..59983d25 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,54 @@ +[metadata] +name = pooch +fullname = Pooch +description = "Pooch manages your Python library's sample data files: it automatically downloads and stores them in a local directory, with support for versioning and corruption checks." +long_description = file: README.rst +long_description_content_type = text/x-rst +author = The Pooch Developers +author_email = fatiandoaterra@protonmail.com +maintainer = "Leonardo Uieda" +maintainer_email = leouieda@gmail.com +license = BSD 3-Clause License +license_file = LICENSE.txt +platform = any +keywords = data, download, caching, http +classifiers = + Development Status :: 5 - Production/Stable + Intended Audience :: Science/Research + Intended Audience :: Developers + Intended Audience :: Education + License :: OSI Approved :: BSD License + Natural Language :: English + Operating System :: OS Independent + Topic :: Scientific/Engineering + Topic :: Software Development :: Libraries + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 +url = https://github.com/fatiando/pooch +project_urls = + Documentation = https://www.fatiando.org/pooch + Release Notes = https://github.com/fatiando/pooch/releases + Bug Tracker = https://github.com/fatiando/pooch/issues + Source Code = https://github.com/fatiando/pooch + +[options] +zip_safe = True +include_package_data = True +packages = find: +python_requires = >=3.6 +setup_requires = +install_requires = + appdirs>=1.3.0 + packaging>=20.0 + requests>=2.19.0 + +[options.package_data] +pooch.tests = data/*, data/store/*, data/store/subdir/* + [flake8] ignore = E203, E266, E501, W503, F401, E741 max-line-length = 88 diff --git a/setup.py b/setup.py index 927ee4e0..f245bc65 100644 --- a/setup.py +++ b/setup.py @@ -5,88 +5,12 @@ # This code is part of the Fatiando a Terra project (https://www.fatiando.org) # """ -Build and install the project. - -Uses setuptools_scm to manage version numbers using git tags. +Setup script for the Python package. +Metadata and build configuration are defined in setup.cfg +Uses setuptools-scm to manage version numbers using git tags. """ -import os -from setuptools import setup, find_packages - - -NAME = "pooch" -FULLNAME = "Pooch" -AUTHOR = "Leonardo Uieda" -AUTHOR_EMAIL = "leouieda@gmail.com" -MAINTAINER = AUTHOR -MAINTAINER_EMAIL = AUTHOR_EMAIL -LICENSE = "BSD License" -URL = "https://github.com/fatiando/pooch" -DESCRIPTION = ( - "Pooch manages your Python library's sample data files: " - "it automatically downloads and stores them in a local directory, " - "with support for versioning and corruption checks." -) -KEYWORDS = "" -with open("README.rst") as f: - LONG_DESCRIPTION = "".join(f.readlines()) +from setuptools import setup -CLASSIFIERS = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Science/Research", - "Intended Audience :: Developers", - "Intended Audience :: Education", - "Topic :: Scientific/Engineering", - "Topic :: Software Development :: Libraries", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3 :: Only", - f"License :: OSI Approved :: {LICENSE}", -] -PLATFORMS = "Any" -PACKAGES = find_packages(exclude=["doc"]) -SCRIPTS = [] -PACKAGE_DATA = { - "pooch.tests": [ - os.path.join("data", "*"), - os.path.join("data", "store", "*"), - os.path.join("data", "store", "subdir", "*"), - ] -} -INSTALL_REQUIRES = ["requests", "packaging", "appdirs"] -PYTHON_REQUIRES = ">=3.6" -SETUP_REQUIRES = ["setuptools_scm"] -# Configuration for setuptools-scm -USE_SCM_VERSION = { - "relative_to": __file__, - "version_scheme": "post-release", - "local_scheme": "node-and-date", - "write_to": f"{NAME}/_version.py", -} if __name__ == "__main__": - setup( - name=NAME, - fullname=FULLNAME, - description=DESCRIPTION, - long_description=LONG_DESCRIPTION, - use_scm_version=USE_SCM_VERSION, - author=AUTHOR, - author_email=AUTHOR_EMAIL, - maintainer=MAINTAINER, - maintainer_email=MAINTAINER_EMAIL, - license=LICENSE, - url=URL, - platforms=PLATFORMS, - scripts=SCRIPTS, - packages=PACKAGES, - package_data=PACKAGE_DATA, - classifiers=CLASSIFIERS, - keywords=KEYWORDS, - install_requires=INSTALL_REQUIRES, - python_requires=PYTHON_REQUIRES, - setup_requires=SETUP_REQUIRES, - ) + setup() diff --git a/tools/export_requirements.py b/tools/export_requirements.py new file mode 100644 index 00000000..378498ca --- /dev/null +++ b/tools/export_requirements.py @@ -0,0 +1,19 @@ +# Copyright (c) 2018 The Pooch Developers. +# Distributed under the terms of the BSD 3-Clause License. +# SPDX-License-Identifier: BSD-3-Clause +# +# This code is part of the Fatiando a Terra project (https://www.fatiando.org) +# +""" +Export the run-time requirements from setup.cfg to a requirement.txt format. +Modified from https://github.com/Unidata/MetPy +""" +import configparser + +# Read the setup.cfg +config = configparser.ConfigParser() +config.read("setup.cfg") + +print("# Run-time dependencies") +for package in config["options"]["install_requires"].strip().split("\n"): + print(package.strip()) diff --git a/license_notice.py b/tools/license_notice.py similarity index 100% rename from license_notice.py rename to tools/license_notice.py diff --git a/tools/oldest_requirements.py b/tools/oldest_requirements.py new file mode 100644 index 00000000..92db06e8 --- /dev/null +++ b/tools/oldest_requirements.py @@ -0,0 +1,27 @@ +# Copyright (c) 2018 The Pooch Developers. +# Distributed under the terms of the BSD 3-Clause License. +# SPDX-License-Identifier: BSD-3-Clause +# +# This code is part of the Fatiando a Terra project (https://www.fatiando.org) +# +""" +Convert the requirements in the given file to their oldest version by +replacing >= with == in place. +""" +import sys + + +requirements_file = sys.argv[1] + + +def to_oldest(package): + "Convert the specification to pin to the oldest version" + oldest = package.split(",")[0].replace(">=", "==") + return f"{oldest.strip()}\n" + + +with open(requirements_file) as input_file: + requirements = [to_oldest(line) for line in input_file] + +with open(requirements_file, "wt") as output_file: + output_file.writelines(requirements)