diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml new file mode 100644 index 000000000..cfe884258 --- /dev/null +++ b/.github/workflows/typecheck.yml @@ -0,0 +1,29 @@ +name: Typecheck + +on: + pull_request: + push: + branches: + - main + - development + + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-python@v5 + with: + python-version: "3.10" + + - name: Install package and test dependencies + run: | + python -m pip install .[complete] + python -m pip install -r requirements-dev.txt + + - uses: jakebailey/pyright-action@v2 diff --git a/doc/source/conf.py b/doc/source/conf.py index 0303f72ca..d51c371ee 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -32,13 +32,17 @@ # ones. extensions = [ "sphinx.ext.autodoc", + # IMPORTANT: napoleon must be loaded before sphinx_autodoc_typehints + # https://github.com/tox-dev/sphinx-autodoc-typehints/issues/15 + "sphinx.ext.napoleon", + "sphinx_autodoc_typehints", "sphinx.ext.autosectionlabel", "numpydoc", # "sphinx.ext.autosummary", "myst_nb", "contributors", # custom extension, from pandas "sphinxcontrib.bibtex", - "sphinx_panels", + "sphinx_design", # "sphinx.ext.imgconverter", # this extension should help the latex svg warning, but results in an error instead ] myst_enable_extensions = [ @@ -79,6 +83,31 @@ nb_execution_mode = "off" suppress_warnings = ["myst.header"] # suppress non-consecutive header warning + +# -- Options for Napoleon docstring parsing ---------------------------------- +napoleon_google_docstring = False +napoleon_numpy_docstring = True +napoleon_use_admonition_for_examples = True +napoleon_use_admonition_for_notes = True + + +# -- Options for autodoc ----------------------------------------------------- + +# Show the typehints in the description of each object instead of the signature. +autodoc_typehints = "description" + + +# -- Options for autodoc typehints-------------------------------------------- + +# Replace Union annotations with union operator "|" +always_use_bars_union = True +# always_document_param_types = True + +# Show the default value for a parameter after its type +typehints_defaults = "comma" +typehints_use_return = True + + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for diff --git a/doc/source/index.rst b/doc/source/index.rst index e73818942..1630006c7 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -31,86 +31,109 @@ ICESat-2 datasets to enable scientific discovery. To further enhance data discovery, we have developed the QUEST module to facilitate querying of ICESat-2 data and complimentary Argo oceanographic data, with additional dataset support expected in the future. -.. panels:: - :card: + intro-card text-center - :column: col-lg-4 col-md-4 col-sm-6 col-xs-12 p-2 - :img-top-cls: pl-2 pr-2 pt-2 pb-2 +.. grid:: 1 2 2 3 + :gutter: 3 + :class-container: sd-text-center - --- - :img-top: https://cdn-icons-png.flaticon.com/128/2498/2498074.png + .. grid-item-card:: + :img-top: https://cdn-icons-png.flaticon.com/128/2498/2498074.png + :class-img-top: sd-p-2 + :class-card: sd-shadow-md - **Getting Started** - ^^^^^^^^^^^^^^^^^^^ + **Getting Started** + ^^^^^^^^^^^^^^^^^^^ - New to ICESat-2 or icepyx? - Learn how to install icepyx and use it to jumpstart your project today. - Check out our gallery of examples, too! + New to ICESat-2 or icepyx? + Learn how to install icepyx and use it to jumpstart your project today. + Check out our gallery of examples, too! - .. link-button:: install_ref - :type: ref - :text: Installation Instructions - :classes: stretched-link btn-outline-primary btn-block + .. button-ref:: install_ref + :ref-type: ref + :color: primary + :outline: + :expand: - --- - :img-top: https://cdn-icons-png.flaticon.com/128/3730/3730041.png + Installation Instructions - **User Guide** - ^^^^^^^^^^^^^^ + .. grid-item-card:: + :img-top: https://cdn-icons-png.flaticon.com/128/3730/3730041.png + :class-img-top: sd-p-2 + :class-card: sd-shadow-md - The user guide provides in-depth information on the tools and functionality - available for obtaining and interacting with ICESat-2 data products. + **User Guide** + ^^^^^^^^^^^^^^ - .. link-button:: api_doc_ref - :type: ref - :text: Software Docs - :classes: stretched-link btn-outline-primary btn-block + The user guide provides in-depth information on the tools and functionality + available for obtaining and interacting with ICESat-2 data products. - --- - :img-top: https://cdn-icons-png.flaticon.com/512/4230/4230997.png + .. button-ref:: api_doc_ref + :ref-type: ref + :color: primary + :outline: + :expand: - **Development Guide** - ^^^^^^^^^^^^^^^^^^^^^ + Software Docs - Have an idea or an ancillary dataset to contribute to icepyx? Go here for information on best practices - for developing and contributing to icepyx. + .. grid-item-card:: + :img-top: https://cdn-icons-png.flaticon.com/512/4230/4230997.png + :class-img-top: sd-p-2 + :class-card: sd-shadow-md - .. link-button:: dev_guide_label - :type: ref - :text: Development Guide - :classes: stretched-link btn-outline-primary btn-block + **Development Guide** + ^^^^^^^^^^^^^^^^^^^^^ - --- - :img-top: https://cdn-icons-png.flaticon.com/128/1283/1283342.png + Have an idea or an ancillary dataset to contribute to icepyx? Go here for information on best practices + for developing and contributing to icepyx. - **Get in Touch** - ^^^^^^^^^^^^^^^^ + .. button-ref:: dev_guide_label + :ref-type: ref + :color: primary + :outline: + :expand: - icepyx is more than just software! - We're a community of data producers, managers, and users - who collaborate openly and share code and skills - for every step along the entire data pipeline. Find resources for - your questions here! + Development Guide - .. link-button:: contact_ref_label - :type: ref - :text: Get Involved! - :classes: stretched-link btn-outline-primary btn-block + .. grid-item-card:: + :img-top: https://cdn-icons-png.flaticon.com/128/1283/1283342.png + :class-img-top: sd-p-2 + :class-card: sd-shadow-md - --- - :img-top: https://icesat-2.gsfc.nasa.gov/sites/default/files/MissionLogo_0.png - :img-top-cls: pl-2 pr-2 pt-4 pb-4 + **Get in Touch** + ^^^^^^^^^^^^^^^^ - **ICESat-2 Resources** - ^^^^^^^^^^^^^^^^^^^^^^ + icepyx is more than just software! + We're a community of data producers, managers, and users + who collaborate openly and share code and skills + for every step along the entire data pipeline. Find resources for + your questions here! - Curious about other tools for working with ICESat-2 data? - Want to share your resource? - Check out the amazing work already in progress! + .. button-ref:: contact_ref_label + :ref-type: ref + :color: primary + :outline: + :expand: - .. link-button:: resource_ref_label - :type: ref - :text: ICESat-2 Resource Guide - :classes: stretched-link btn-outline-primary btn-block + Get Involved! + + .. grid-item-card:: + :img-top: https://icesat-2.gsfc.nasa.gov/sites/default/files/MissionLogo_0.png + :class-img-top: sd-p-2 + :class-card: sd-shadow-md + + **ICESat-2 Resources** + ^^^^^^^^^^^^^^^^^^^^^^ + + Curious about other tools for working with ICESat-2 data? + Want to share your resource? + Check out the amazing work already in progress! + + .. button-ref:: resource_ref_label + :ref-type: ref + :color: primary + :outline: + :expand: + + ICESat-2 Resource Guide .. toctree:: diff --git a/doc/source/user_guide/documentation/icepyx.rst b/doc/source/user_guide/documentation/icepyx.rst index eec823e10..bb71b63e0 100644 --- a/doc/source/user_guide/documentation/icepyx.rst +++ b/doc/source/user_guide/documentation/icepyx.rst @@ -19,3 +19,4 @@ Diagrams are updated automatically after a pull request (PR) is approved and bef read variables components + types diff --git a/doc/source/user_guide/documentation/types.rst b/doc/source/user_guide/documentation/types.rst new file mode 100644 index 000000000..991a80431 --- /dev/null +++ b/doc/source/user_guide/documentation/types.rst @@ -0,0 +1,11 @@ +Types +===== + +.. automodule:: icepyx.core.types + :members: + :undoc-members: + :exclude-members: CMRParamsBase,CMRParamsWithBbox,CMRParamsWithPolygon + +.. COMMENT. `exclude-members` specified above is required because those models + contain symbols ('[', ']') in some keys, which sphinx doesn't like. + See: https://github.com/sphinx-doc/sphinx/issues/11039 diff --git a/icepyx/core/APIformatting.py b/icepyx/core/APIformatting.py index 4b1966910..1c225d2ef 100644 --- a/icepyx/core/APIformatting.py +++ b/icepyx/core/APIformatting.py @@ -1,6 +1,13 @@ -# Generate and format information for submitting to API (CMR and NSIDC) +"""Generate and format information for submitting to API (CMR and NSIDC).""" import datetime as dt +from typing import Any, Generic, Literal, TypeVar, Union, overload + +from icepyx.core.types import ( + CMRParams, + EGIParamsSubset, + EGIRequiredParams, +) # ---------------------------------------------------------------------- # parameter-specific formatting for display @@ -183,12 +190,56 @@ def to_string(params): return "&".join(param_list) +ParameterType = Literal["CMR", "required", "subset"] +# DevGoal: When Python 3.12 is minimum supported version, migrate to PEP695 style +T = TypeVar("T", bound=ParameterType) + + +class _FmtedKeysDescriptor: + """Enable the Parameters class' fmted_keys property to be typechecked correctly. + + See: https://github.com/microsoft/pyright/issues/3071#issuecomment-1043978070 + """ + + @overload + def __get__( + self, + instance: 'Parameters[Literal["CMR"]]', + owner: Any, + ) -> CMRParams: ... + + @overload + def __get__( + self, + instance: 'Parameters[Literal["required"]]', + owner: Any, + ) -> EGIRequiredParams: ... + + @overload + def __get__( + self, + instance: 'Parameters[Literal["subset"]]', + owner: Any, + ) -> EGIParamsSubset: ... + + def __get__( + self, + instance: "Parameters", + owner: Any, + ) -> Union[CMRParams, EGIRequiredParams, EGIParamsSubset]: + """ + Returns the dictionary of formatted keys associated with the + parameter object. + """ + return instance._fmted_keys + + # ---------------------------------------------------------------------- # DevNote: Currently, this class is not tested!! # DevGoal: this could be expanded, similar to the variables class, to provide users with valid options if need be # DevGoal: currently this does not do much by way of checking/formatting of other subsetting options (reprojection or formats) # it would be great to incorporate that so that people can't just feed any keywords in... -class Parameters: +class Parameters(Generic[T]): """ Build and update the parameter lists needed to submit a data order @@ -206,7 +257,14 @@ class Parameters: on the type of query. Must be one of ['search','download'] """ - def __init__(self, partype, values=None, reqtype=None): + fmted_keys = _FmtedKeysDescriptor() + + def __init__( + self, + partype: T, + values=None, + reqtype=None, + ): assert partype in [ "CMR", "required", @@ -242,15 +300,7 @@ def poss_keys(self): # return self._wanted - @property - def fmted_keys(self): - """ - Returns the dictionary of formatted keys associated with the - parameter object. - """ - return self._fmted_keys - - def _get_possible_keys(self): + def _get_possible_keys(self) -> dict[str, list[str]]: """ Use the parameter type to get a list of possible parameter keys. """ @@ -347,7 +397,7 @@ def check_values(self): else: return False - def build_params(self, **kwargs): + def build_params(self, **kwargs) -> None: """ Build the parameter dictionary of formatted key:value pairs for submission to NSIDC in the data request. @@ -443,3 +493,8 @@ def build_params(self, **kwargs): k = "Boundingshape" self._fmted_keys.update({k: kwargs["spatial_extent"]}) + + +CMRParameters = Parameters[Literal["CMR"]] +RequiredParameters = Parameters[Literal["required"]] +SubsetParameters = Parameters[Literal["subset"]] diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 9f12fbecf..71b4393e5 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -54,7 +54,7 @@ def __init__(self, auth=None): self._s3login_credentials = None self._s3_initial_ts = None # timer for 1h expiration on s3 credentials - def __str__(self): + def __str__(self) -> str: if self.session: repr_string = "EarthdataAuth obj with session initialized" else: diff --git a/icepyx/core/granules.py b/icepyx/core/granules.py index b29a147e1..080d8b19c 100644 --- a/icepyx/core/granules.py +++ b/icepyx/core/granules.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime import io import json @@ -10,10 +12,16 @@ import numpy as np import requests +from requests.compat import unquote import icepyx.core.APIformatting as apifmt from icepyx.core.auth import EarthdataAuthMixin import icepyx.core.exceptions +from icepyx.core.types import ( + CMRParams, + EGIRequiredParamsDownload, + EGIRequiredParamsSearch, +) from icepyx.core.urls import DOWNLOAD_BASE_URL, GRANULE_SEARCH_BASE_URL, ORDER_BASE_URL @@ -170,24 +178,32 @@ def __init__( # ---------------------------------------------------------------------- # Methods - def get_avail(self, CMRparams, reqparams, cloud=False): + def get_avail( + self, + CMRparams: CMRParams, + reqparams: EGIRequiredParamsSearch, + cloud: bool = False, + ): """ Get a list of available granules for the query object's parameters. Generates the `avail` attribute of the granules object. Parameters ---------- - CMRparams : dictionary + CMRparams : Dictionary of properly formatted CMR search parameters. - reqparams : dictionary + reqparams : Dictionary of properly formatted parameters required for searching, ordering, or downloading from NSIDC. - cloud : deprecated, boolean, default False + cloud : CMR metadata is always collected for the cloud system. + .. deprecated:: 1.2 + This parameter is ignored. + Notes ----- - This function is used by query.Query.avail_granules(), which automatically + This function is used by ``query.Query.avail_granules()``, which automatically feeds in the required parameters. See Also @@ -261,13 +277,13 @@ def get_avail(self, CMRparams, reqparams, cloud=False): # DevGoal: add kwargs to allow subsetting and more control over request options. def place_order( self, - CMRparams, - reqparams, + CMRparams: CMRParams, + reqparams: EGIRequiredParamsDownload, subsetparams, verbose, subset=True, geom_filepath=None, - ): # , **kwargs): + ): """ Place an order for the available granules for the query object. Adds the list of zipped files (orders) to the granules data object (which is @@ -276,11 +292,11 @@ def place_order( Parameters ---------- - CMRparams : dictionary + CMRparams : Dictionary of properly formatted CMR search parameters. - reqparams : dictionary + reqparams : Dictionary of properly formatted parameters required for searching, ordering, - or downloading from NSIDC. + or downloading from NSIDC (via their EGI system). subsetparams : dictionary Dictionary of properly formatted subsetting parameters. An empty dictionary is passed as input here when subsetting is set to False in query methods. @@ -359,7 +375,7 @@ def place_order( request.raise_for_status() esir_root = ET.fromstring(request.content) if verbose is True: - print("Order request URL: ", requests.utils.unquote(request.url)) + print("Order request URL: ", unquote(request.url)) print( "Order request response XML content: ", request.content.decode("utf-8"), @@ -402,6 +418,7 @@ def place_order( loop_root = ET.fromstring(loop_response.content) # Continue loop while request is still processing + loop_root = None while status == "pending" or status == "processing": print( "Your order status is still ", @@ -425,6 +442,13 @@ def place_order( if status == "pending" or status == "processing": continue + if not isinstance(loop_root, ET.Element): + # The typechecker determined that loop_root could be unbound at this + # point. We know for sure this shouldn't be possible, though, because + # the while loop should run once. + # See: https://github.com/microsoft/pyright/discussions/2033 + raise RuntimeError("Programmer error!") + # Order can either complete, complete_with_errors, or fail: # Provide complete_with_errors error message: if status == "complete_with_errors" or status == "failed": diff --git a/icepyx/core/query.py b/icepyx/core/query.py index d547a959f..71df8723e 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -1,7 +1,9 @@ import pprint +from typing import Optional, Union, cast import geopandas as gpd import matplotlib.pyplot as plt +from typing_extensions import Never import icepyx.core.APIformatting as apifmt from icepyx.core.auth import EarthdataAuthMixin @@ -11,6 +13,12 @@ import icepyx.core.is2ref as is2ref import icepyx.core.spatial as spat import icepyx.core.temporal as tp +from icepyx.core.types import ( + CMRParams, + EGIParamsSubset, + EGIRequiredParams, + EGIRequiredParamsDownload, +) import icepyx.core.validate_inputs as val from icepyx.core.variables import Variables as Variables from icepyx.core.visualization import Visualize @@ -393,6 +401,10 @@ class Query(GenQuery, EarthdataAuthMixin): GenQuery """ + _CMRparams: apifmt.CMRParameters + _reqparams: apifmt.RequiredParameters + _subsetparams: Optional[apifmt.SubsetParameters] + # ---------------------------------------------------------------------- # Constructors @@ -532,7 +544,7 @@ def tracks(self): return sorted(set(self._tracks)) @property - def CMRparams(self): + def CMRparams(self) -> CMRParams: """ Display the CMR key:value pairs that will be submitted. It generates the dictionary if it does not already exist. @@ -573,7 +585,7 @@ def CMRparams(self): return self._CMRparams.fmted_keys @property - def reqparams(self): + def reqparams(self) -> EGIRequiredParams: """ Display the required key:value pairs that will be submitted. It generates the dictionary if it does not already exist. @@ -599,7 +611,7 @@ def reqparams(self): # @property # DevQuestion: if I make this a property, I get a "dict" object is not callable # when I try to give input kwargs... what approach should I be taking? - def subsetparams(self, **kwargs): + def subsetparams(self, **kwargs) -> Union[EGIParamsSubset, dict[Never, Never]]: """ Display the subsetting key:value pairs that will be submitted. It generates the dictionary if it does not already exist @@ -1001,7 +1013,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): if "email" in self._reqparams.fmted_keys or email is False: self._reqparams.build_params(**self._reqparams.fmted_keys) elif email is True: - user_profile = self.auth.get_user_profile() + user_profile = self.auth.get_user_profile() # pyright: ignore[reportAttributeAccessIssue] self._reqparams.build_params( **self._reqparams.fmted_keys, email=user_profile["email_address"] ) @@ -1032,7 +1044,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): tempCMRparams["readable_granule_name[]"] = gran self._granules.place_order( tempCMRparams, - self.reqparams, + cast(EGIRequiredParamsDownload, self.reqparams), self.subsetparams(**kwargs), verbose, subset, @@ -1042,7 +1054,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): else: self._granules.place_order( self.CMRparams, - self.reqparams, + cast(EGIRequiredParamsDownload, self.reqparams), self.subsetparams(**kwargs), verbose, subset, @@ -1135,14 +1147,14 @@ def visualize_spatial_extent( import geoviews as gv from shapely.geometry import Polygon # noqa: F401 - gv.extension("bokeh") + gv.extension("bokeh") # pyright: ignore[reportCallIssue] bbox_poly = gv.Path(gdf["geometry"]).opts(color="red", line_color="red") tile = gv.tile_sources.EsriImagery.opts(width=500, height=500) - return tile * bbox_poly + return tile * bbox_poly # pyright: ignore[reportOperatorIssue] except ImportError: - world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) + world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres")) # pyright: ignore[reportAttributeAccessIssue] f, ax = plt.subplots(1, figsize=(12, 6)) world.plot(ax=ax, facecolor="lightgray", edgecolor="gray") gdf.plot(ax=ax, color="#FF8C00", alpha=0.7) diff --git a/icepyx/core/types.py b/icepyx/core/types.py new file mode 100644 index 000000000..e85f8696f --- /dev/null +++ b/icepyx/core/types.py @@ -0,0 +1,111 @@ +from __future__ import annotations + +from typing import Literal, TypedDict, Union + +from typing_extensions import NotRequired + +ICESat2ProductShortName = Literal[ + "ATL01", + "ATL02", + "ATL03", + "ATL04", + "ATL06", + "ATL07", + "ATL07QL", + "ATL08", + "ATL09", + "ATL09QL", + "ATL10", + "ATL11", + "ATL12", + "ATL13", + "ATL14", + "ATL15", + "ATL16", + "ATL17", + "ATL19", + "ATL20", + "ATL21", + "ATL23", +] + +CMRParamsBase = TypedDict( + "CMRParamsBase", + { + "temporal": NotRequired[str], + "options[readable_granule_name][pattern]": NotRequired[str], + "options[spatial][or]": NotRequired[str], + "readable_granule_name[]": NotRequired[str], + }, +) + + +class CMRParamsWithBbox(CMRParamsBase): + bounding_box: str + + +class CMRParamsWithPolygon(CMRParamsBase): + polygon: str + + +CMRParams = Union[CMRParamsWithBbox, CMRParamsWithPolygon] + + +class EGIRequiredParamsBase(TypedDict): + """Common parameters for searching, ordering, or downloading from EGI. + + See: https://wiki.earthdata.nasa.gov/display/SDPSDOCS/EGI+Programmatic+Access+Documentation + + EGI shares parameters with CMR, so this data is used in conjunction with CMRParams + to build EGI requests. + + TODO: Validate more strongly (with Pydantic and its annotated types? + https://docs.pydantic.dev/latest/concepts/types/#composing-types-via-annotated): + + * version is 3 digits + * 0 < page_size <= 2000 + """ + + short_name: ICESat2ProductShortName # alias: "product" + version: str + page_size: int # default 2000 + page_num: int # default 0 + + +class EGIRequiredParamsSearch(EGIRequiredParamsBase): + """Parameters for interacting with EGI.""" + + +class EGIRequiredParamsDownload(EGIRequiredParamsBase): + """Parameters for ordering from EGI. + + TODO: Validate more strongly (with Pydantic?): page_num >=0. + """ + + request_mode: Literal["sync", "async", "stream"] # default "async" + include_meta: Literal["Y", "N"] # default "Y" + client_string: Literal["icepyx"] # default "icepyx" + # token, email + + +class EGIParamsSubsetBase(TypedDict): + """Parameters for subsetting with EGI.""" + + time: NotRequired[str] + format: NotRequired[str] + projection: NotRequired[str] + projection_parameters: NotRequired[str] + Coverage: NotRequired[str] + + +class EGIParamsSubsetBbox(EGIParamsSubsetBase): + bbox: NotRequired[str] + + +class EGIParamsSubsetBoundingShape(EGIParamsSubsetBase): + Boundingshape: NotRequired[str] + + +EGIParamsSubset = Union[EGIParamsSubsetBbox, EGIParamsSubsetBoundingShape] + +EGIRequiredParams = Union[EGIRequiredParamsSearch, EGIRequiredParamsDownload] diff --git a/icepyx/core/visualization.py b/icepyx/core/visualization.py index 0ddb9fd40..0f983b5e1 100644 --- a/icepyx/core/visualization.py +++ b/icepyx/core/visualization.py @@ -466,7 +466,7 @@ def parallel_request_OA(self) -> da.array: OA_data_da = da.concatenate(requested_OA_data, axis=0) return OA_data_da - def viz_elevation(self) -> (hv.DynamicMap, hv.Layout): + def viz_elevation(self) -> tuple[hv.DynamicMap, hv.Layout]: """ Visualize elevation requested from OpenAltimetry API using datashader based on cycles https://holoviz.org/tutorial/Large_Data.html diff --git a/pyproject.toml b/pyproject.toml index f44ea450a..564f53976 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,3 +124,27 @@ ignore = [ [tool.ruff.lint.isort] force-sort-within-sections = true + + +[tool.pyright] +pythonVersion = "3.9" +# DevGoal: "strict" +typeCheckingMode = "standard" +include = [ + "icepyx", +] +exclude = [ + "**/__pycache__", + "icepyx/tests", +] +# DevGoal: Remove all ignores +ignore = [ + "icepyx/quest/*", + "icepyx/core/APIformatting.py", + "icepyx/core/auth.py", + "icepyx/core/is2ref.py", + "icepyx/core/read.py", + "icepyx/core/spatial.py", + "icepyx/core/variables.py", + "icepyx/core/visualization.py", +] diff --git a/requirements-dev.txt b/requirements-dev.txt index 66106dab8..238785444 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,10 @@ +pandas-stubs pre-commit pypistats +pyright pytest>=4.6 pytest-cov responses +types-docutils +types-requests +types-tqdm diff --git a/requirements-docs.txt b/requirements-docs.txt index 51dc9ff5a..554b4d2b8 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -6,6 +6,7 @@ numpydoc pybtex pygithub sphinx>=4.3 -sphinx-panels +sphinx-autodoc-typehints>=2.0 +sphinx-design sphinx_rtd_theme>=1.0 sphinxcontrib-bibtex