Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion argopy/data_fetchers/argovis_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def __init__(
}

def __repr__(self):
summary = ["<datafetcher.argovis>"]
summary = ["<datafetcher.product.argovis>"]
summary.append(self._repr_data_source)
summary.append(self._repr_access_point)
summary.append(self._repr_server)
Expand Down
26 changes: 18 additions & 8 deletions argopy/fetchers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#!/bin/env python
# -*coding: UTF-8 -*-
"""

High level helper methods to load Argo data from any source
Expand All @@ -11,14 +9,15 @@

import os
import warnings
from typing import Optional

import netCDF4
from argopy import pandas as pd # Lazily import large module
from argopy import xarray as xr # Lazily import large module
import numpy as np
import logging

from argopy.options import OPTIONS, VALIDATE, PARALLEL_SETUP
from argopy.options import OPTIONS, VALIDATE, PARALLEL_SETUP, PRODUCT_LIST
from argopy.errors import (
InvalidFetcherAccessPoint,
InvalidFetcher,
Expand Down Expand Up @@ -74,9 +73,11 @@ class ArgoDataFetcher:
mode: str, optional
User mode. Eg: ``standard`` or ``expert``. Set to OPTIONS['mode'] by default if empty.
src: str, optional
Source of the data to use. Eg: ``erddap``. Set to OPTIONS['src'] by default if empty.
Argo data source to use. Eg: ``erddap``. Set to OPTIONS['src'] by default if empty.
ds: str, optional
Name of the dataset to load. Eg: ``phy``. Set to OPTIONS['ds'] by default if empty.
product: str, optional
Name of a third-party product to use as data source. Eg: ``argovis``. This parameter takes precedence over ``src``.
**fetcher_kwargs: optional
Additional arguments passed on data source fetcher creation of each access points.

Expand All @@ -89,10 +90,9 @@ class ArgoDataFetcher:

"""

def __init__(self, mode: str = "", src: str = "", ds: str = "", **fetcher_kwargs):
def __init__(self, mode: str = "", src: str = "", ds: str = "", product: Optional[str]= None, **fetcher_kwargs):
"""Create a fetcher instance


Returns
-------
:class:`argopy.fetchers.ArgoDataFetcher`
Expand All @@ -104,6 +104,12 @@ def __init__(self, mode: str = "", src: str = "", ds: str = "", **fetcher_kwargs
self._src = OPTIONS["src"] if src == "" else VALIDATE("src", src)
self.fetcher_kwargs = {**fetcher_kwargs}

if product is not None:
# Third-party products must update this section to be included:
if product.lower() not in PRODUCT_LIST.datafetcher:
raise InvalidFetcher(f"The '{product}' product has no implementation. Available products are: {PRODUCT_LIST.datafetcher}.")
self._src = product

if self._dataset_id == "bgc":
self._dataset_id = "bgc-s"

Expand Down Expand Up @@ -195,7 +201,7 @@ def __init__(self, mode: str = "", src: str = "", ds: str = "", **fetcher_kwargs
self._mode == "expert" or self._mode == "research"
):
raise OptionValueError(
"The 'argovis' data source fetching is only available in 'standard' user mode"
"The 'argovis' product is only available in 'standard' user mode"
)
if self._src == "gdac" and "bgc" in self._dataset_id:
warnings.warn(
Expand Down Expand Up @@ -260,8 +266,12 @@ def __repr__(self):
if self.fetcher:
summary = [self.fetcher.__repr__()]
else:
if self._src not in PRODUCT_LIST.datafetcher:
obj = f"datafetcher.{self._src}"
else:
obj = f"datafetcher.product.{self._src}"
summary = [
"<datafetcher.%s> 'No access point initialised'" % self._src,
f"<{obj}> 'No access point initialised'",
"Available access points: %s" % ", ".join(self.Fetchers.keys()),
]

Expand Down
33 changes: 28 additions & 5 deletions argopy/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import logging
import fsspec
import importlib

from dataclasses import dataclass

try:
import distributed
Expand Down Expand Up @@ -77,10 +77,24 @@
DEFAULT = OPTIONS.copy()

# Define the list of possible values
DATA_SOURCE_LIST = frozenset(["erddap", "argovis", "gdac"])
DATA_SOURCE_LIST = frozenset(["erddap", "gdac", "argovis"])
_DATASET_LIST = frozenset(["phy", "bgc", "ref", "bgc-s", "bgc-b"])
_USER_LEVEL_LIST = frozenset(["standard", "expert", "research"])

@dataclass(frozen=True)
class PRODUCT_LIST:
"""A place to define the list of valid third-party products

Notes
-----
This is a read-only dataclass
"""
datafetcher : tuple[str] = tuple(["argovis"]) # To be used with the 'product' argument
"""List of valid values for the ``product`` argument of the :class:`argopy.DataFetcher` class"""

argofloat: tuple[str] = tuple([]) # To be
"""List of valid values for the :meth:`argopy.ArgoFloat.open_product` method"""


# Define how to validate options:
def _positive_integer(value):
Expand Down Expand Up @@ -120,9 +134,18 @@ def validate_parallel_method(method):
else:
return False

def validate_data_source(src):
if src == 'argovis':
warnings.warn(
f"'argovis' as a 'src' option is no longer accepted and will raise an error soon. To fetch data from the Argovis server, please update your code to use the new DataFetcher 'product' argument dedicated to third-party providers like Argovis -- Deprecated since version 1.5",
category=FutureWarning,
stacklevel=2,
)
return src in DATA_SOURCE_LIST


_VALIDATORS = {
DATA_SOURCE: DATA_SOURCE_LIST.__contains__,
DATA_SOURCE: validate_data_source,
GDAC: validate_gdac,
ERDDAP: validate_erddap,
ARGOVIS: lambda x: isinstance(x, str),
Expand Down Expand Up @@ -175,7 +198,7 @@ class set_options:
Define the Dataset to work with: ``phy``, ``bgc`` or ``ref``

src: str, default: ``erddap``
Source of fetched data: ``erddap``, ``gdac``, ``argovis``
Source of fetched data: ``erddap``, ``gdac``

mode: str, default: ``standard``
User mode: ``standard``, ``expert`` or ``research``
Expand Down Expand Up @@ -208,7 +231,7 @@ class set_options:
Password to use when a simple authentication is required

argovis_api_key: str, default: ``guest``
The API key to use when fetching data from the `argovis` data source
The API key to use when fetching data from the `argovis` product

You can get a free key at https://argovis-keygen.colorado.edu

Expand Down
2 changes: 1 addition & 1 deletion argopy/reference/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"""

# Deprecated:
from .reference_tables import ArgoNVSReferenceTables
from .reference_tables import NVScollection, ArgoNVSReferenceTables

# New APIs:
from .concept import ArgoReferenceValue
Expand Down
5 changes: 5 additions & 0 deletions argopy/stores/float/products/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
Place in this submodule all third-party product machinery to be used by the :meth:`argopy.ArgoFloat.open_product` method.

When adding a new product, don't forget to update :class:`argopy.options.PRODUCT_LIST`.
"""
27 changes: 26 additions & 1 deletion argopy/stores/float/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import numpy as np
from concurrent.futures import ThreadPoolExecutor, as_completed

from argopy.options import OPTIONS
from argopy.options import OPTIONS, PRODUCT_LIST
from argopy.errors import InvalidOption, DataNotFound
from argopy.plot import dashboard
from argopy.stores import ArgoIndex
Expand Down Expand Up @@ -1135,3 +1135,28 @@ def __getitem__(self, args) -> int | str | list[int | str]:
return results

raise NotImplementedError

def open_product(
self, name: str = "", **kwargs
) -> xr.Dataset | Any:
"""Open and decode a third-party product for a given float

Parameters
----------
name: str
Name of the third-party product to open.
\**kwargs
All the other arguments are passed to the product facade.

Returns
-------
:class:`xarray.Dataset` | Any
"""

# Third-party access modules must be located in: argopy.stores.float.products
# and the facade called from here.

if name not in PRODUCT_LIST.argofloat:
raise NotImplementedError(
"Product '%s' not found. Available third-party product for this float are: %s"
% (name, PRODUCT_LIST.argofloat))
6 changes: 3 additions & 3 deletions argopy/tests/test_fetchers_data_argovis.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ def assert_all(this_fetcher, cacheable):

@requires_argovis
class Test_Backend:
""" Test ERDDAP data fetching backend """
src = 'argovis'
""" Test data fetching backend """
product = 'argovis'

#############
# UTILITIES #
Expand All @@ -130,7 +130,7 @@ def setup_class(self):

def _setup_fetcher(self, this_request, cached=False, parallel=False):
"""Helper method to set up options for a fetcher creation"""
defaults_args = {"src": self.src,
defaults_args = {"product": self.product,
"cache": cached,
"cachedir": self.cachedir,
"parallel": parallel,
Expand Down
2 changes: 1 addition & 1 deletion cli/citests_httpdata_manager
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ class Lister:
[this_URI.commit(self.dfile(uri, "js")) for uri in encode(facade.uri)]

for ds in requests_seq:
fetcher = DataFetcher(src="argovis", ds=ds)
fetcher = DataFetcher(product="argovis", ds=ds)
for access_point in requests_seq[ds]:
[
add_to_URI(fetcher.profile(*cfg))
Expand Down
7 changes: 7 additions & 0 deletions docs/api-hidden.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
argopy.data_fetchers.CTDRefDataFetcher

argopy.options.set_options
argopy.options.PRODUCT_LIST

argopy.tutorial.open_dataset

Expand Down Expand Up @@ -145,6 +146,7 @@
argopy.related.TopoFetcher.cachepath
argopy.related.TopoFetcher.uri

argopy.reference.NVScollection
argopy.reference.ArgoNVSReferenceTables
argopy.reference.ArgoNVSReferenceTables.search
argopy.reference.ArgoNVSReferenceTables.valid_ref
Expand Down Expand Up @@ -404,6 +406,7 @@
argopy.ArgoFloat.dac
argopy.ArgoFloat.path
argopy.ArgoFloat.metadata
argopy.ArgoFloat.open_product

argopy.stores.ArgoFloat.plot
argopy.stores.ArgoFloat.plot.trajectory
Expand All @@ -414,6 +417,10 @@
argopy.ArgoFloat.plot.scatter
argopy.ArgoFloat.plot.map

argopy.stores.float.extensions.ArgoFloatAnyConfigParametersProto
argopy.stores.float.extensions.ArgoFloatConfigParametersProto
argopy.stores.float.extensions.ArgoFloatLaunchConfigParametersProto

argopy.stores.ArgoFloat.config
argopy.stores.ArgoFloat.config.n_params
argopy.stores.ArgoFloat.config.parameters
Expand Down
Loading
Loading