diff --git a/.github/workflows/testMaps.yml b/.github/workflows/testMaps.yml index f783dc134..37139204c 100644 --- a/.github/workflows/testMaps.yml +++ b/.github/workflows/testMaps.yml @@ -13,40 +13,28 @@ jobs: # set operating systems to test os: [ubuntu-latest] # set python versions to test - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10", "3.11"] name: test_Maps ${{ matrix.os }} ${{ matrix.python-version }} steps: # checkout repository - uses: actions/checkout@v3 # install miniconda environment - - uses: conda-incubator/setup-miniconda@v2 + + - uses: mamba-org/setup-micromamba@v1 with: environment-file: tests/test_env.yml - - # use mamba to speed up installation - #mamba-version: "*" - #channels: conda-forge - #channel-priority: true - - miniforge-variant: Mambaforge - miniforge-version: latest - - activate-environment: eomaps - - show-channel-urls: true - use-only-tar-bz2: true - - python-version: ${{ matrix.python-version }} - - auto-activate-base: false - auto-update-conda: true - # run pytest - - name: test Maps - # do this to ensure proper activation of conda environment + init-shell: >- + bash + cache-environment: true + post-cleanup: 'all' + create-args: >- + python=${{ matrix.python-version }} + - name: Test Maps shell: bash -l {0} run: | - python -m pytest --cov=eomaps --cov-report=xml + pip install -e .[all] + python -m pytest -v --cov=eomaps --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: diff --git a/docs/api_data_visualization.rst b/docs/api_data_visualization.rst index 82cfe62ae..7823c98b6 100644 --- a/docs/api_data_visualization.rst +++ b/docs/api_data_visualization.rst @@ -849,7 +849,7 @@ Once a dataset has been plotted, a colorbar with a colored histogram on top can | cbB.tick_params(labelcolor="darkblue", labelsize=9) | | | | | | m.subplots_adjust(bottom=0.1) | | - | mA.show() | | + | m.show_layer(mA.layer) | | +-----------------------------------------------------------------+------------------------------------------+ .. autosummary:: diff --git a/docs/installation.rst b/docs/installation.rst index e51ade5bc..16fdcc550 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -8,6 +8,7 @@ :local: :depth: 1 + Recommended way (via ``conda`` and ``mamba``) --------------------------------------------- @@ -17,27 +18,35 @@ EOmaps is available via the ``conda-forge`` channel and can be installed via: conda install -c conda-forge eomaps -This should make sure all required dependencies are correctly installed. + +This will install all required and optional dependencies. + .. admonition:: Greatly speed up the installation! - Since the dependencies of EOmaps can be demanding to solve for the classic ``conda`` solver, it is **highly recommended** - that you use `mamba `_ to install EOmaps! + Since the dependencies of EOmaps can be demanding to solve for ``conda``, it is **highly recommended** + that you use `mamba `_ to install EOmaps! - To install ``mamba``, simply use: + ``mamba`` is a reimplementation of the conda package manager in C++, capable of solving environments a lot faster. - .. code-block:: console + The best way to get started is to use `miniforge `_. - conda install -c conda-forge mamba + However, you can also install ``mamba`` into an existing ``conda`` environment with: - Once ``mamba`` is installed, you just need to replace the term ``conda`` with ``mamba`` and you're good to go! + .. code-block:: console + + conda install -c conda-forge mamba - .. code-block:: console - mamba install -c conda-forge eomaps + Once ``mamba`` is installed, you just need to replace the term ``conda`` with ``mamba`` and you're good to go! - Alternatively you can also configure ``conda`` to use the ``libmamba`` solver by default. - (More info here: `A Faster Solver for Conda: Libmamba `_ ) + .. code-block:: console + + mamba install -c conda-forge eomaps + + + Alternatively you can also configure ``conda`` to use the ``libmamba`` solver by default. + (More info here: `A Faster Solver for Conda: Libmamba `_ ) A quick tutorial on how to **get started from scratch** is available here: :ref:`quickstart_guide` @@ -45,18 +54,45 @@ A quick tutorial on how to **get started from scratch** is available here: :ref: More details on how to **configure your favorite IDE** to work with EOmaps can be found in the FAQ section :ref:`configuring_the_editor`. + + Alternative way (via ``pip``) ----------------------------- -EOmaps is also available on ``pip`` and can be installed via + +EOmaps is also available on ``pip``. + +To install EOmaps with a **minimal set of dependencies**, use: .. code-block:: console pip install eomaps -However, it is **not guaranteed that all dependencies are correctly resolved** and some manual -tweaking of the environment might be required to ensure that all packages work as expected. -Especially dependencies on C/C++ libraries such as ``geos`` or ``pyproj`` have to be configured -carefully to set up everying correctly. If you are not sure what you're doing, use ``conda + mamba``! +Optional dependencies +~~~~~~~~~~~~~~~~~~~~~ + +Some features (:ref:`webmap_layers`, :ref:`companion_widget`, etc.) require additional dependencies. +To use them you have to install the required dependency-groups: + +To get all features of EOmaps, you can use one of: + +.. code-block:: console + + pip install eomaps[all] # ALL optional dependencies + pip install eomaps[all_nogui] # All optional dependencies (except ``Qt`` GUI framework) + + +In addition, you can use the following dependency-groups to activate only selected features: + +.. code-block:: console + + pip install eomaps[wms] # dependencies required for WebMap services + pip install eomaps[gui] # dependencies for ``Qt`` GUI framework and the CompanionWidget + pip install eomaps[io] # add support for ``pandas``, ``xarray``, ``geopandas`` and ``rioxarray`` + pip install eomaps[shade] # add capabilities to visualize extremely large datasets (via ``datashader``) + pip install eomaps[classify] # add support for ``mapclassify`` to classify datasets + + +(It is also possible to combine dependency-groups, e.g.: ``pip install eomaps[wms, gui]``) -A list of all required dependencies can be found in :ref:`setup_a_dev_env` +A list of all associated packages can be found in :ref:`setup_a_dev_env` or in the ``pyproject.toml`` file. diff --git a/eomaps/__init__.py b/eomaps/__init__.py index 959c260aa..bc2a416c9 100644 --- a/eomaps/__init__.py +++ b/eomaps/__init__.py @@ -1,3 +1,4 @@ +import importlib.metadata from .helpers import register_modules as _register_modules # address numpy runtime warning concerning binary incompatibility when @@ -6,8 +7,8 @@ from .eomaps import Maps from .mapsgrid import MapsGrid -from ._version import __version__ +__version__ = importlib.metadata.version("eomaps") __author__ = "Raphael Quast" # Follow conventions used by cartopy to setup cache directory diff --git a/eomaps/_version.py b/eomaps/_version.py deleted file mode 100644 index 40d114c5b..000000000 --- a/eomaps/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "7.3.3" diff --git a/eomaps/eomaps.py b/eomaps/eomaps.py index d9b3cbedd..98ca1b986 100644 --- a/eomaps/eomaps.py +++ b/eomaps/eomaps.py @@ -13,6 +13,7 @@ import gc from textwrap import fill from contextlib import contextmanager, ExitStack +import importlib.metadata import numpy as np @@ -71,7 +72,7 @@ from ._data_manager import DataManager -from ._version import __version__ +__version__ = importlib.metadata.version("eomaps") def _handle_backends(): diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..8607913ba --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,71 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.packages.find] +include = ["eomaps"] + +[project] +name = "eomaps" +version = "8.0" +description = "A library to create interactive maps of geographical datasets." +requires-python = ">=3.8" + +authors = [ + { name="Raphael Quast", email="raphael.quast@geo.tuwien.ac.at" }, +] + +keywords = ["Visualization", "Plotting", "Maps", "Geographical Data"] + +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", + "Operating System :: OS Independent", +] + +dependencies = [ + "numpy", + "scipy", + "matplotlib>=3.4", + "cartopy>=0.20.0", + "descartes", + "pyproj", + "packaging", + "click" +] + +[project.optional-dependencies] + +all = ["eomaps[io, classify, wms, shade, gui]"] + +all_nogui = ["eomaps[io, classify, wms, shade]"] + +io = [ + "pandas", + "geopandas", + "xarray", + "netcdf4", + "rioxarray" +] + +classify = ["mapclassify"] + +wms = [ + "owslib", + "requests", + "cairosvg", +] + +shade = ["datashader"] + +gui = [ + "PyQt5", + "qtpy" + ] + +[project.scripts] +eomaps = "eomaps.scripts.open:cli" + +[project.urls] +Documentation = "https://eomaps.readthedocs.io/" +Repository = "https://github.com/raphaelquast/eomaps" diff --git a/setup.py b/setup.py deleted file mode 100644 index a1cbf5775..000000000 --- a/setup.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: UTF-8 -*- - -""" -This file is part of EOmaps. -For COPYING and LICENSE details, please refer to the LICENSE file -""" -from setuptools import setup, find_packages -from pathlib import Path -import re - -# add the README as long-description -this_directory = Path(__file__).parent -try: - long_description = (this_directory / "README.md").read_text() -except Exception: - long_description = "A library to create interactive maps of geographical datasets." - -# get version-number from _version.py -try: - with open(this_directory / "eomaps" / "_version.py") as file: - (version,) = re.findall('__version__ = "(.*)"', file.read()) -except Exception: - version = "undefined" - -setup( - name="EOmaps", - version=version, - description="A library to create interactive maps of geographical datasets.", - packages=find_packages(), - package_dir={"eomaps": "eomaps"}, - package_data={"eomaps": ["logo.png", "NE_features.json", "qtcompanion/icons/*"]}, - # include_package_data=True, - author="Raphael Quast", - author_email="raphael.quast@geo.tuwien.ac.at", - maintainer="Raphael Quast", - maintainer_email="raphael.quast@geo.tuwien.ac.at", - license="GNU General Public License v3 or later (GPLv3+)", - url="https://github.com/raphaelquast/maps", - long_description=long_description, - long_description_content_type="text/markdown", - install_requires=[ - "numpy", - "scipy", - "pandas", - "matplotlib>=3.4", - "cartopy>=0.20.0", - "descartes", - "mapclassify", - "pyproj", - "pyepsg", - "geopandas", - "owslib", - "requests", - "xmltodict", - "cairosvg", - "packaging", - "click", - "qtpy", - ], - entry_points={"console_scripts": ["eomaps = eomaps.scripts.open:cli"]}, - keywords=["visualization", "plotting", "maps", "geographical data"], - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering :: Visualization", - "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", - # Pick your license as you wish (should match "license" above) - # ~ 'License :: OSI Approved :: MIT License', - "Programming Language :: Python :: 3.7", - ], - license_files=("LICENSE",), -) diff --git a/tests/test_doc_codeblocks.py b/tests/test_doc_codeblocks.py index 45027d320..22dd683fe 100644 --- a/tests/test_doc_codeblocks.py +++ b/tests/test_doc_codeblocks.py @@ -58,7 +58,7 @@ def __new__(mcs, name, bases, tests): source_code = node.astext() name = node.attributes["names"][0] - test_name = f"test_{i}" + test_name = f"test_{p.stem}_{i}" tests[test_name] = gen_test(i, name, source_code) os.chdir(cwd) diff --git a/tests/test_doc_notebooks.py b/tests/test_doc_notebooks.py index 71e9ca604..072ab2a1f 100644 --- a/tests/test_doc_notebooks.py +++ b/tests/test_doc_notebooks.py @@ -31,7 +31,8 @@ def test_doc_notebook(self, notebook): nb = nbformat.read(f, as_version=4) # parse all code-cells from notebook code_cells = [i["source"] for i in nb["cells"] if i["cell_type"] == "code"] - code = "" + # make sure plt.ion() is called before each test! + code = "import matplotlib.pyplot as plt\n" "plt.ion()\n" "\n" for c in code_cells: for l in c.split("\n"):