diff --git a/conda_environment_test.yaml b/conda_environment_test.yaml index f09f406e..227a8992 100644 --- a/conda_environment_test.yaml +++ b/conda_environment_test.yaml @@ -7,6 +7,7 @@ dependencies: - netcdf4==1.6.5 - syrupy==4.6.1 - compliance-checker==5.1.1 + - numpydoc==1.8.0 - pip: - pytest-order==1.2.1 - freezegun==1.5.1 diff --git a/copernicusmarine/command_line_interface/group_describe.py b/copernicusmarine/command_line_interface/group_describe.py index 4ec4e773..7290c128 100644 --- a/copernicusmarine/command_line_interface/group_describe.py +++ b/copernicusmarine/command_line_interface/group_describe.py @@ -6,6 +6,7 @@ log_exception_and_exit, ) from copernicusmarine.command_line_interface.utils import tqdm_disable_option +from copernicusmarine.core_functions import documentation_utils from copernicusmarine.core_functions.click_custom_class import ( CustomClickOptionsCommand, ) @@ -24,13 +25,9 @@ def cli_describe() -> None: "describe", cls=CustomClickOptionsCommand, short_help="Print Copernicus Marine catalogue as JSON.", - help=""" - Print Copernicus Marine catalogue as JSON. - - The default display contains information on the products, and more data can be displayed using the ``--include-`` flags. - - The ``--contains`` option allows the user to specify one or several strings to filter through the catalogue display. The search is performed recursively on all attributes of the catalog, and the tokens only need to be contained in one of the attributes (i.e., not an exact match). - """, # noqa + help=documentation_utils.DESCRIBE["DESCRIBE_DESCRIPTION_HELP"] + + " \n\nReturns\n " + + documentation_utils.DESCRIBE["DESCRIBE_RESPONSE_HELP"], # noqa epilog=""" Examples: @@ -40,7 +37,7 @@ def cli_describe() -> None: .. code-block:: bash - copernicusmarine describe -c METOFFICE-GLO-SST-L4-NRT-OBS-SST-V2 + copernicusmarine describe -c METOFFICE-GLO-SST-L4-NRT-OBS-SST-V2 \n """, # noqa ) @click.option( @@ -48,29 +45,28 @@ def cli_describe() -> None: type=bool, is_flag=True, default=False, - help="Include product description in output.", + help=documentation_utils.DESCRIBE["INCLUDE_DESCRIPTION_HELP"], ) @click.option( "--include-datasets", type=bool, is_flag=True, default=False, - help="Include product dataset details in output.", + help=documentation_utils.DESCRIBE["INCLUDE_DATASETS_HELP"], ) @click.option( "--include-keywords", type=bool, is_flag=True, default=False, - help="Include product keyword details in output.", + help=documentation_utils.DESCRIBE["INCLUDE_KEYWORDS_HELP"], ) @click.option( "--include-versions", type=bool, is_flag=True, default=False, - help="Include dataset versions in output. " - "By default, shows only the default version.", + help=documentation_utils.DESCRIBE["INCLUDE_VERSIONS_HELP"], ) @click.option( "-a", @@ -78,34 +74,27 @@ def cli_describe() -> None: type=bool, is_flag=True, default=False, - help="Include all the possible data in output: " - "description, datasets, keywords, and versions.", + help=documentation_utils.DESCRIBE["INCLUDE_ALL_HELP"], ) @click.option( "--contains", "-c", type=str, multiple=True, - help="Filter catalogue output. Returns products with attributes " - "matching a string token.", + help=documentation_utils.DESCRIBE["CONTAINS_HELP"], ) @click.option( "--max-concurrent-requests", type=int, default=15, - help="Maximum number of concurrent requests. " - "Default 15. The describe command uses a thread " - "pool executor to manage concurrent requests.", + help=documentation_utils.DESCRIBE["MAX_CONCURRENT_REQUESTS_HELP"], ) @tqdm_disable_option @click.option( "--log-level", type=click.Choice(["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL", "QUIET"]), default="INFO", - help=( - "Set the details printed to console by the command " - "(based on standard logging library)." - ), + help=documentation_utils.DESCRIBE["LOG_LEVEL_HELP"], ) @click.option( "--staging", diff --git a/copernicusmarine/command_line_interface/group_get.py b/copernicusmarine/command_line_interface/group_get.py index dce20769..06d58cf4 100644 --- a/copernicusmarine/command_line_interface/group_get.py +++ b/copernicusmarine/command_line_interface/group_get.py @@ -14,6 +14,7 @@ force_dataset_version_option, tqdm_disable_option, ) +from copernicusmarine.core_functions import documentation_utils from copernicusmarine.core_functions.click_custom_class import ( CustomClickOptionsCommand, ) @@ -21,11 +22,6 @@ create_get_template, get_function, ) -from copernicusmarine.core_functions.utils import ( - OVERWRITE_LONG_OPTION, - OVERWRITE_OPTION_HELP_TEXT, - OVERWRITE_SHORT_OPTION, -) logger = logging.getLogger("copernicusmarine") blank_logger = logging.getLogger("copernicusmarine_blank_logger") @@ -40,17 +36,15 @@ def cli_get() -> None: "get", cls=CustomClickOptionsCommand, short_help="Download originally produced data files.", - help=""" - Download originally produced data files. - - The ``--dataset-id`` is required (can be found via the "describe" command). The function fetches the files recursively if a folder path is passed as a URL. When provided a dataset ID, all the files in the corresponding folder will be downloaded if none of the ``--filter`` or ``--regex`` options is specified. - """, # noqa + help=documentation_utils.GET["GET_DESCRIPTION_HELP"] + + " See :ref:`describe `. \n\nReturns\n " + + documentation_utils.GET["GET_RESPONSE_HELP"], epilog=""" Example to download all the files from a given dataset: .. code-block:: bash - copernicusmarine get -i cmems_mod_nws_bgc-pft_myint_7km-3D-diato_P1M-m + copernicusmarine get -i cmems_mod_nws_bgc-pft_myint_7km-3D-diato_P1M-m \n """, # noqa ) @click.option( @@ -58,7 +52,7 @@ def cli_get() -> None: "-i", type=str, default=None, - help="The datasetID.", + help=documentation_utils.GET["DATASET_ID_HELP"], ) @force_dataset_version_option @force_dataset_part_option @@ -66,123 +60,97 @@ def cli_get() -> None: "--username", type=str, default=None, - help="If not set, search for environment variable" - + " COPERNICUSMARINE_SERVICE_USERNAME" - + ", or else look for configuration files, or else ask for user input.", + help=documentation_utils.GET["USERNAME_HELP"], ) @click.option( "--password", type=str, default=None, - help="If not set, search for environment variable" - + " COPERNICUSMARINE_SERVICE_PASSWORD" - + ", or else look for configuration files, or else ask for user input.", + help=documentation_utils.GET["PASSWORD_HELP"], ) @click.option( "--no-directories", "-nd", cls=MutuallyExclusiveOption, is_flag=True, - help="Option to not recreate folder hierarchy in ouput directory.", + help=documentation_utils.GET["NO_DIRECTORIES_HELP"], default=False, mutually_exclusive=["sync"], ) @click.option( "--show-outputnames", is_flag=True, - help="Option to display the names of the" - + " output files before download.", + help=documentation_utils.GET["SHOW_OUTPUTNAMES_HELP"], default=False, ) @click.option( "--output-directory", "-o", type=click.Path(path_type=pathlib.Path), - help="The destination directory for the downloaded files." - + " Default is the current directory.", + help=documentation_utils.GET["OUTPUT_DIRECTORY_HELP"], ) @click.option( "--credentials-file", type=click.Path(path_type=pathlib.Path), - help=( - "Path to a credentials file if not in its default directory. " - "Accepts .copernicusmarine-credentials / .netrc or _netrc / " - "motuclient-python.ini files." - ), + help=documentation_utils.GET["CREDENTIALS_FILE_HELP"], ) @click.option( "--force-download", is_flag=True, default=False, - help="Flag to skip confirmation before download.", + help=documentation_utils.GET["FORCE_DOWNLOAD_HELP"], ) @click.option( - OVERWRITE_LONG_OPTION, - OVERWRITE_SHORT_OPTION, + documentation_utils.GET["OVERWRITE_LONG_OPTION"], + documentation_utils.GET["OVERWRITE_SHORT_OPTION"], is_flag=True, default=False, - help=OVERWRITE_OPTION_HELP_TEXT, + help=documentation_utils.GET["OVERWRITE_OUTPUT_DATA_HELP"], ) @click.option( "--create-template", type=bool, is_flag=True, default=False, - help="Option to create a file get_template.json in your current directory " - "containing CLI arguments. If specified, no other action will be performed.", + help=documentation_utils.GET["CREATE_TEMPLATE_HELP"], ) @click.option( "--request-file", type=click.Path(exists=True, path_type=pathlib.Path), - help="Option to pass a file containing CLI arguments. " - "The file MUST follow the structure of dataclass 'GetRequest'." - " For more information please refer to the README.", + help=documentation_utils.GET["REQUEST_FILE_HELP"], ) @click.option( "--filter", "--filter-with-globbing-pattern", type=str, default=None, - help="A pattern that must match the absolute paths of " - "the files to download.", + help=documentation_utils.GET["FILTER_HELP"], ) @click.option( "--regex", "--filter-with-regular-expression", type=str, default=None, - help="The regular expression that must match the absolute paths of " - "the files to download.", + help=documentation_utils.GET["REGEX_HELP"], ) @click.option( "--file-list", type=pathlib.Path, default=None, - help="Path to a .txt file containing a list of file paths," - " line by line, that will be downloaded directly." - " These files must be from the specified dataset using the --dataset-id." - " If no files can be found, the Toolbox will list all" - " files on the remote server and attempt to find a match.", + help=documentation_utils.GET["FILE_LIST_HELP"], ) @click.option( "--create-file-list", type=str, default=None, - help="Option to only create a file containing " - "the names of the targeted files instead of downloading them. " - "It writes the file in the directory specified with the " - "--output-directory option (default to current directory). " - "The file name specified should end with '.txt' or '.csv' " - "If specified, no other action will be performed. " - "Please find more information in the README.", + help=documentation_utils.GET["CREATE_FILE_LIST_HELP"], ) @click.option( "--sync", cls=MutuallyExclusiveOption, is_flag=True, default=False, - help="Option to synchronize the local directory with " - "the remote directory. See the documentation for more details.", + help=documentation_utils.GET["SYNC_HELP"], mutually_exclusive=["no-directories"], ) @click.option( @@ -190,8 +158,7 @@ def cli_get() -> None: cls=MutuallyExclusiveOption, is_flag=True, default=False, - help="Option to delete local files that are not present on " - "the remote server while applying sync.", + help=documentation_utils.GET["SYNC_DELETE_HELP"], mutually_exclusive=["no-directories"], ) @click.option( @@ -199,32 +166,27 @@ def cli_get() -> None: type=bool, is_flag=True, default=False, - help="Option to get the index files of an INSITU dataset. Temporary option.", + help=documentation_utils.GET["INDEX_PARTS_HELP"], ) @click.option( "--dry-run", type=bool, is_flag=True, default=False, - help="Runs query without downloading data.", + help=documentation_utils.GET["DRY_RUN_HELP"], ) @click.option( "--max-concurrent-requests", type=int, default=15, - help="Maximum number of concurrent requests. " - "Default 15. The get command uses a thread " - "pool executor to manage concurrent requests.", + help=documentation_utils.GET["MAX_CONCURRENT_REQUESTS_HELP"], ) @tqdm_disable_option @click.option( "--log-level", type=click.Choice(["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL", "QUIET"]), default="INFO", - help=( - "Set the details printed to console by the command " - "(based on standard logging library)." - ), + help=documentation_utils.GET["LOG_LEVEL_HELP"], ) @click.option( "--staging", diff --git a/copernicusmarine/command_line_interface/group_login.py b/copernicusmarine/command_line_interface/group_login.py index d7c2c0f4..8df8c1d8 100644 --- a/copernicusmarine/command_line_interface/group_login.py +++ b/copernicusmarine/command_line_interface/group_login.py @@ -7,6 +7,7 @@ from copernicusmarine.command_line_interface.exception_handler import ( log_exception_and_exit, ) +from copernicusmarine.core_functions import documentation_utils from copernicusmarine.core_functions.click_custom_class import ( CustomClickOptionsCommand, ) @@ -27,11 +28,9 @@ def cli_login() -> None: "login", cls=CustomClickOptionsCommand, short_help="Create a configuration file with your Copernicus Marine credentials.", - help=""" - Create a configuration file with your Copernicus Marine credentials. - - Create a configuration file under the ``$HOME/.copernicusmarine`` directory (overwritable with the ``--credentials-file`` option). - """, # noqa + help=documentation_utils.LOGIN["LOGIN_DESCRIPTION_HELP"] + + " \n\nReturns\n " + + documentation_utils.LOGIN["LOGIN_RESPONSE_HELP"], # noqa epilog=""" Examples: @@ -59,50 +58,37 @@ def cli_login() -> None: @click.option( "--username", hide_input=False, - help="If not set, search for environment variable" - + " COPERNICUSMARINE_SERVICE_USERNAME" - + ", or else ask for user input.", + help=documentation_utils.LOGIN["USERNAME_HELP"], ) @click.option( "--password", hide_input=True, - help="If not set, search for environment variable" - + " COPERNICUSMARINE_SERVICE_PASSWORD" - + ", or else ask for user input.", + help=documentation_utils.LOGIN["PASSWORD_HELP"], ) @click.option( "--configuration-file-directory", type=click.Path(path_type=pathlib.Path), default=DEFAULT_CLIENT_BASE_DIRECTORY, - help="Path to the directory where the configuration file is stored.", + help=documentation_utils.LOGIN["CONFIGURATION_FILE_DIRECTORY_HELP"], ) @click.option( "--overwrite-configuration-file", "-overwrite", is_flag=True, default=False, - help="Flag to skip confirmation before overwriting configuration file.", + help=documentation_utils.LOGIN["OVERWRITE_CONFIGURATION_FILE_HELP"], ) @click.option( "--check-credentials-valid", is_flag=True, default=False, - help="Flag to check if the credentials are valid. " - "No other action will be performed. " - "The validity will be check in this order: " - "1. Check if the credentials are valid with the provided username and password." - "2. Check if the credentials are valid in the configuration file." - "3. Check if the credentials are valid in the environment variables." - "When any is found not valid, will return False immediately.", + help=documentation_utils.LOGIN["CHECK_CREDENTIALS_VALID_HELP"], ) @click.option( "--log-level", type=click.Choice(["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL", "QUIET"]), default="INFO", - help=( - "Set the details printed to console by the command " - "(based on standard logging library)." - ), + help=documentation_utils.LOGIN["LOG_LEVEL_HELP"], ) @log_exception_and_exit def login( diff --git a/copernicusmarine/command_line_interface/group_subset.py b/copernicusmarine/command_line_interface/group_subset.py index 962bea5c..a06b6146 100644 --- a/copernicusmarine/command_line_interface/group_subset.py +++ b/copernicusmarine/command_line_interface/group_subset.py @@ -13,6 +13,7 @@ force_dataset_version_option, tqdm_disable_option, ) +from copernicusmarine.core_functions import documentation_utils from copernicusmarine.core_functions.click_custom_class import ( CustomClickOptionsCommand, ) @@ -27,17 +28,11 @@ FileFormat, VerticalDimensionOutput, ) -from copernicusmarine.core_functions.services_utils import CommandType from copernicusmarine.core_functions.subset import ( create_subset_template, subset_function, ) -from copernicusmarine.core_functions.utils import ( - OVERWRITE_LONG_OPTION, - OVERWRITE_OPTION_HELP_TEXT, - OVERWRITE_SHORT_OPTION, - datetime_parser, -) +from copernicusmarine.core_functions.utils import datetime_parser logger = logging.getLogger("copernicusmarine") blank_logger = logging.getLogger("copernicusmarine_blank_logger") @@ -52,11 +47,10 @@ def cli_subset() -> None: "subset", cls=CustomClickOptionsCommand, short_help="Download subsets of datasets as NetCDF files or Zarr stores.", - help=""" - Download subsets of datasets as NetCDF files or Zarr stores. - - The ``--dataset-id`` is required (can be found via the "describe" command). The argument values passed individually through the CLI take precedence over the values from the ``--motu-api-request`` option, which takes precedence over the ones from the ``--request-file`` option. - """, # noqa + help=documentation_utils.SUBSET["SUBSET_DESCRIPTION_HELP"] + + "See :ref:`describe `." + + " \n\nReturns\n " + + documentation_utils.SUBSET["SUBSET_RESPONSE_HELP"], epilog=""" Examples: @@ -68,7 +62,7 @@ def cli_subset() -> None: .. code-block:: bash - copernicusmarine subset -i cmems_mod_ibi_phy_my_0.083deg-3D_P1D-m -v thetao -v so -t 2021-01-01 -T 2021-01-03 -x 0.0 -X 0.1 -y 28.0 -Y 28.1 -z 1 -Z 2 + copernicusmarine subset -i cmems_mod_ibi_phy_my_0.083deg-3D_P1D-m -v thetao -v so -t 2021-01-01 -T 2021-01-03 -x 0.0 -X 0.1 -y 28.0 -Y 28.1 -z 1 -Z 2 \n """, # noqa ) @click.option( @@ -76,7 +70,7 @@ def cli_subset() -> None: "-i", type=str, default=None, - help="The datasetID.", + help=documentation_utils.SUBSET["DATASET_ID_HELP"], ) @force_dataset_version_option @force_dataset_part_option @@ -84,212 +78,159 @@ def cli_subset() -> None: "--username", type=str, default=None, - help="If not set, search for environment variable" - + " COPERNICUSMARINE_SERVICE_USERNAME" - + ", or else look for configuration files, or else ask for user input.", + help=documentation_utils.SUBSET["USERNAME_HELP"], ) @click.option( "--password", type=str, default=None, - help="If not set, search for environment variable" - + " COPERNICUSMARINE_SERVICE_PASSWORD" - + ", or else look for configuration files, or else ask for user input.", + help=documentation_utils.SUBSET["PASSWORD_HELP"], ) @click.option( "--variable", "-v", "variables", type=str, - help="Specify dataset variable. Can be used multiple times.", + help=documentation_utils.SUBSET["VARIABLES_HELP"], multiple=True, ) @click.option( "--minimum-longitude", "-x", type=float, - help=( - "Minimum longitude for the subset. " - "The value will be reduced to the interval [-180; 360[." - ), + help=documentation_utils.SUBSET["MINIMUM_LONGITUDE_HELP"], ) @click.option( "--maximum-longitude", "-X", type=float, - help=( - "Maximum longitude for the subset. " - "The value will be reduced to the interval [-180; 360[." - ), + help=documentation_utils.SUBSET["MAXIMUM_LONGITUDE_HELP"], ) @click.option( "--minimum-latitude", "-y", type=click.FloatRange(min=-90, max=90), - help="Minimum latitude for the subset." - " Requires a float within this range:", + help=documentation_utils.SUBSET["MINIMUM_LATITUDE_HELP"], ) @click.option( "--maximum-latitude", "-Y", type=click.FloatRange(min=-90, max=90), - help="Maximum latitude for the subset." - " Requires a float within this range:", + help=documentation_utils.SUBSET["MAXIMUM_LATITUDE_HELP"], ) @click.option( "--minimum-depth", "-z", type=click.FloatRange(min=0), - help="Minimum depth for the subset. Requires a float within this range:", + help=documentation_utils.SUBSET["MINIMUM_DEPTH_HELP"], ) @click.option( "--maximum-depth", "-Z", type=click.FloatRange(min=0), - help="Maximum depth for the subset. Requires a float within this range:", + help=documentation_utils.SUBSET["MAXIMUM_DEPTH_HELP"], ) @click.option( "--vertical-dimension-output", "-V", type=click.Choice(DEFAULT_VERTICAL_DIMENSION_OUTPUTS), default=DEFAULT_VERTICAL_DIMENSION_OUTPUT, - help=( - "Consolidate the vertical dimension (the z-axis) as requested:" - " `depth` with descending positive values." - " `elevation` with ascending positive values." - " Default is `depth`." - ), + help=documentation_utils.SUBSET["VERTICAL_DIMENSION_OUTPUT_HELP"], ) @click.option( "--start-datetime", "-t", type=str, - help="The start datetime of the temporal subset. " - "Caution: encapsulate date " - + 'with " " to ensure valid expression for format "%Y-%m-%d %H:%M:%S". ' - + "Supports common format parsed by pendulum. " - + "See https://pendulum.eustace.io/docs/#parsing", + help=documentation_utils.SUBSET["START_DATETIME_HELP"] + + "Caution: encapsulate date with “ “ to ensure valid " + "expression for format “%Y-%m-%d %H:%M:%S”.", ) @click.option( "--end-datetime", "-T", type=str, - help="The end datetime of the temporal subset. Caution: encapsulate date " - + 'with " " to ensure valid expression for format "%Y-%m-%d %H:%M:%S". ' - + "Supports common format parsed by pendulum. " - + "See https://pendulum.eustace.io/docs/#parsing", + help=documentation_utils.SUBSET["END_DATETIME_HELP"] + + "Caution: encapsulate date with “ “ to ensure valid " + "expression for format “%Y-%m-%d %H:%M:%S”.", ) @click.option( "--coordinates-selection-method", type=click.Choice(DEFAULT_COORDINATES_SELECTION_METHODS), default=DEFAULT_COORDINATES_SELECTION_METHOD, - help=( - "The method in which the coordinates will be retrieved." - " If 'inside', the retrieved selection will be inside the requested" - " interval." - " If 'strict-inside', the retrieved selection will be inside the requested" - " interval and an error will raise if there doesn't exist the values." - " If 'nearest', the returned interval extremes will be the closest to what" - " has been asked for. A warning will be displayed if outside of bounds." - " If 'outisde', the extremes will be taken to contain all the requested" - " interval. A warning will also be displayed if the subset is " - "outside of the dataset bounds." - ), + help=documentation_utils.SUBSET["COORDINATES_SELECTION_METHOD_HELP"], ) @click.option( "--output-directory", "-o", type=click.Path(path_type=pathlib.Path), - help="The destination folder for the downloaded files." - + " Default is the current directory.", + help=documentation_utils.SUBSET["OUTPUT_DIRECTORY_HELP"], ) @click.option( "--credentials-file", type=click.Path(path_type=pathlib.Path), - help=( - "Path to a credentials file if not in its default directory. " - "Accepts .copernicusmarine-credentials / .netrc or _netrc / " - "motuclient-python.ini files." - ), + help=documentation_utils.SUBSET["CREDENTIALS_FILE_HELP"], ) @click.option( "--output-filename", "-f", type=str, - help=( - "Concatenate the downloaded data in the given file name " - "(under the output directory)." - ), + help=documentation_utils.SUBSET["OUTPUT_FILENAME_HELP"], ) @click.option( "--file-format", type=click.Choice(DEFAULT_FILE_FORMATS), default=DEFAULT_FILE_FORMAT, - help=("Format of the downloaded dataset. Default to NetCDF (.nc)."), + help=documentation_utils.SUBSET["FILE_FORMAT_HELP"], ) @click.option( "--force-download", is_flag=True, default=False, - help="Flag to skip confirmation before download.", + help=documentation_utils.SUBSET["FORCE_DOWNLOAD_HELP"], ) @click.option( - OVERWRITE_LONG_OPTION, - OVERWRITE_SHORT_OPTION, + documentation_utils.SUBSET["OVERWRITE_LONG_OPTION"], + documentation_utils.SUBSET["OVERWRITE_SHORT_OPTION"], is_flag=True, default=False, - help=OVERWRITE_OPTION_HELP_TEXT, + help=documentation_utils.SUBSET["OVERWRITE_OUTPUT_DATA_HELP"], ) @click.option( "--service", "-s", type=str, - help=( - "Force download through one of the available services " - f"using the service name among {CommandType.SUBSET.service_names()} " - f"or its short name among {CommandType.SUBSET.service_short_names()}." - ), + help=documentation_utils.SUBSET["SERVICE_HELP"], ) @click.option( "--create-template", type=bool, is_flag=True, default=False, - help="Option to create a file subset_template.json in your current directory " - "containing CLI arguments. If specified, no other action will be performed.", + help=documentation_utils.SUBSET["CREATE_TEMPLATE_HELP"], ) @click.option( "--request-file", type=click.Path(exists=True, path_type=pathlib.Path), - help="Option to pass a file containing CLI arguments. " - "The file MUST follow the structure of dataclass 'SubsetRequest'." - " For more information please refer to the README.", + help=documentation_utils.SUBSET["REQUEST_FILE_HELP"], ) @click.option( "--motu-api-request", type=str, - help=( - "Option to pass a complete MOTU API request as a string. " - 'Caution, user has to replace double quotes " with single ' - "quotes ' in the request." - ), + help=documentation_utils.SUBSET["MOTU_API_REQUEST_HELP"], ) @click.option( "--dry-run", type=bool, is_flag=True, default=False, - help="Runs query without downloading data.", + help=documentation_utils.SUBSET["DRY_RUN_HELP"], ) @tqdm_disable_option @click.option( "--log-level", type=click.Choice(["DEBUG", "INFO", "WARN", "ERROR", "CRITICAL", "QUIET"]), default="INFO", - help=( - "Set the details printed to console by the command " - "(based on standard logging library)." - ), + help=documentation_utils.SUBSET["LOG_LEVEL_HELP"], ) @click.option( "--staging", @@ -304,18 +245,15 @@ def cli_subset() -> None: is_flag=False, flag_value=1, default=0, - help=( - "Specify a compression level to apply on the NetCDF output file. " - "A value of 0 means no compression, and 9 is the highest level of " - "compression available" - ), + help=documentation_utils.SUBSET["NETCDF_COMPRESSION_LEVEL_HELP"] + + " If used as a flag, the assigned value will be 1.", ) @click.option( "--netcdf3-compatible", type=bool, default=False, is_flag=True, - help=("Enable downloading the dataset in a netCDF 3 compatible format."), + help=documentation_utils.SUBSET["NETCDF3_COMPATIBLE_HELP"], ) @log_exception_and_exit def subset( diff --git a/copernicusmarine/command_line_interface/utils.py b/copernicusmarine/command_line_interface/utils.py index dc0d60da..7d1a3d1c 100644 --- a/copernicusmarine/command_line_interface/utils.py +++ b/copernicusmarine/command_line_interface/utils.py @@ -2,6 +2,8 @@ from click import Context, Option, UsageError from click.core import ParameterSource +from copernicusmarine.core_functions import documentation_utils + class MutuallyExclusiveOption(Option): def __init__(self, *args, **kwargs): @@ -55,19 +57,19 @@ def assert_cli_args_are_not_set_except_create_template( "--disable-progress-bar", is_flag=True, default=False, - help="Flag to hide progress bar.", + help=documentation_utils.SUBSET["DISABLE_PROGRESS_BAR_HELP"], ) force_dataset_version_option = click.option( "--dataset-version", type=str, default=None, - help="Force the selection of a specific dataset version.", + help=documentation_utils.SUBSET["DATASET_VERSION_HELP"], ) force_dataset_part_option = click.option( "--dataset-part", type=str, default=None, - help="Force the selection of a specific dataset part.", + help=documentation_utils.SUBSET["DATASET_PART_HELP"], ) diff --git a/copernicusmarine/core_functions/documentation_utils.py b/copernicusmarine/core_functions/documentation_utils.py new file mode 100644 index 00000000..798b2f5e --- /dev/null +++ b/copernicusmarine/core_functions/documentation_utils.py @@ -0,0 +1,246 @@ +from copernicusmarine.core_functions.services_utils import CommandType + +SHARED: dict[str, str] = { + "OVERWRITE_SHORT_OPTION": "--overwrite", + "OVERWRITE_LONG_OPTION": "--overwrite-output-data", + "OVERWRITE_OUTPUT_DATA_HELP": ( + "If specified and if the file already exists on destination, then it will be " + "overwritten instead of creating new one with unique index." + ), + "USERNAME_HELP": ( + "The username for authentication." + ), # a little hardcoding in Python API + "PASSWORD_HELP": ( + "The password for authentication." + ), # a little hardcoding in Python API + "LOG_LEVEL_HELP": ( + "Set the details printed to console by the command " + "(based on standard logging library)." + ), + "CREATE_TEMPLATE_HELP": ( + "Option to create a file _template.json in your current directory " + "containing the arguments. If specified, no other action will be performed." + ), + "CREDENTIALS_FILE_HELP": ( + "Path to a credentials file if not in its default directory" + " (``$HOME/.copernicusmarine``). Accepts " + ".copernicusmarine-credentials / .netrc or _netrc / motuclient-python.ini " + "files." + ), + "DATASET_VERSION_HELP": "Force the selection of a specific dataset version.", + "DATASET_PART_HELP": "Force the selection of a specific dataset part.", + "DATASET_ID_HELP": ( + "The datasetID, required either as an argument or in the request_file option." + ), + "DISABLE_PROGRESS_BAR_HELP": "Flag to hide progress bar.", + "FORCE_DOWNLOAD_HELP": "Flag to skip confirmation before download.", + "DRY_RUN_HELP": "If True, runs query without downloading data.", + "OUTPUT_DIRECTORY_HELP": ( + "The destination folder for the downloaded files. Default is the current " + "directory." + ), + "REQUEST_FILE_HELP": ( + "Option to pass a file containing the arguments. For more information " + "please refer to the documentation or use option ``--create-template`` " + "from the command line interface for an example template." + ), +} + +LOGIN: dict[str, str] = { + "LOGIN_DESCRIPTION_HELP": ( + "Create a configuration file with your Copernicus Marine credentials" + " under the ``$HOME/.copernicusmarine`` directory" + " (overwritable with the ``overwrite_configuration_file`` option)." + ), + "LOGIN_RESPONSE_HELP": ( + "Exit code\n 0 exit code if the login was successfully " + "completed, 1 otherwise." + ), + "CONFIGURATION_FILE_DIRECTORY_HELP": ( + "Path to the directory where the configuration file is stored." + ), + "OVERWRITE_CONFIGURATION_FILE_HELP": ( + "Flag to skip confirmation before overwriting configuration file." + ), + "CHECK_CREDENTIALS_VALID_HELP": ( + "Flag to check if the credentials are valid. " + "No other action will be performed. " + "The validity will be check in this order: " + "1. Check if the credentials are valid" + " with the provided username and password. " + "2. Check if the credentials are valid in the environment variables. " + "3. Check if the credentials are valid in the configuration file. " + "When any is found (valid or not valid), will return immediately." + ), +} + +DESCRIBE: dict[str, str] = { + "DESCRIBE_DESCRIPTION_HELP": ( + "Retrieve and parse the metadata information " + "from the Copernicus Marine catalogue." + ), + "DESCRIBE_RESPONSE_HELP": ( + "JSON\n A dictionary containing the retrieved metadata information." + ), + "MAX_CONCURRENT_REQUESTS_HELP": ( + "Maximum number of concurrent requests (>=1). Default 15. The command uses " + "a thread pool executor to manage concurrent requests." + ), + "INCLUDE_DESCRIPTION_HELP": "Include product description in output.", + "INCLUDE_DATASETS_HELP": "Include product dataset details in output.", + "INCLUDE_KEYWORDS_HELP": "Include product keyword details in output.", + "INCLUDE_VERSIONS_HELP": ( + "Include dataset versions in output. By default, shows only the default " + "version." + ), + "INCLUDE_ALL_HELP": ( + "Include all the possible data in output: description, datasets, keywords, " + "and versions." + ), + "CONTAINS_HELP": ( + "Filter catalogue output. Returns products with attributes matching a string " + "token." + ), +} + +SUBSET: dict[str, str] = { + "SUBSET_DESCRIPTION_HELP": ( + "Extracts a subset of data from a specified dataset using given parameters." + "\n\nThe datasetID is required and can be found via the ``describe`` " + "command. " # has some hardcoding in CLI and python API + ), + "SUBSET_RESPONSE_HELP": ( + "JSON \n A description of the downloaded data and its destination." + ), + "SERVICE_HELP": ( + f"Force download through one of the available services using the service name " + f"among {CommandType.SUBSET.service_names()} or " + f"its short name among {CommandType.SUBSET.service_names()}." + ), + "VARIABLES_HELP": "Specify dataset variable. Can be used multiple times.", + "MINIMUM_LONGITUDE_HELP": ( + "Minimum longitude for the subset. The value will be transposed " + "to the interval [-180; 360[." + ), + "MAXIMUM_LONGITUDE_HELP": ( + "Maximum longitude for the subset. The value will be transposed" + " to the interval [-180; 360[." + ), + "MINIMUM_LATITUDE_HELP": ( + "Minimum latitude for the subset. Requires a float from -90 " + "degrees to +90." + ), + "MAXIMUM_LATITUDE_HELP": ( + "Maximum latitude for the subset. Requires a float from -90 degrees " + "to +90." + ), + "MINIMUM_DEPTH_HELP": ( + "Minimum depth for the subset. Requires a positive float (or 0)." + ), + "MAXIMUM_DEPTH_HELP": ( + "Maximum depth for the subset. Requires a positive float (or 0)." + ), + "VERTICAL_DIMENSION_OUTPUT_HELP": ( + "Consolidate the vertical dimension (the z-axis) as requested: depth with " + "descending positive values, elevation with ascending positive values. " + "Default is depth." + ), + "START_DATETIME_HELP": ( + "The start datetime of the temporal subset. Supports common " + "format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing)." + ), # hardocded in cli: Caution: encapsulate date with “ “ to ensure valid + # expression for format “%Y-%m-%d %H:%M:%S”. + "END_DATETIME_HELP": ( + "The end datetime of the temporal subset. Supports common " + "format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing)." + ), # hardocded in cli: Caution: encapsulate date with “ “ + # to ensure valid expression for format “%Y-%m-%d %H:%M:%S”. + "COORDINATES_SELECTION_METHOD_HELP": ( + "If ``inside``, the " + "selection retrieved will be inside the requested range. If ``strict-" + "inside``, the selection retrieved will be inside the requested range, " + "and an error will be raised if the values don't exist. " + "If ``nearest``, the extremes closest to the requested values will " + "be returned. If ``outside``," + " the extremes will be taken to contain all the requested interval." + " The methods ``inside``, ``nearest`` and ``outside`` will display" + " a warning if the request is out of bounds." + ), + "OUTPUT_FILENAME_HELP": ( + "Save the downloaded data with the given file name (under the output " + "directory)." + ), + "FILE_FORMAT_HELP": "Format of the downloaded dataset. Default to NetCDF '.nc'.", + "MOTU_API_REQUEST_HELP": ( + "Option to pass a complete MOTU API request as a string. Caution, user has to " + "replace double quotes “ with single quotes ' in the request." + ), + "NETCDF_COMPRESSION_LEVEL_HELP": ( + "Specify a compression level to apply on the NetCDF output file. A value of 0 " + "means no compression, and 9 is the highest level of compression available." + ), # some hardcoding in CLI to add the flag value + "NETCDF3_COMPATIBLE_HELP": ( + "Enable downloading the dataset in a netCDF3 compatible format." + ), +} + +GET: dict[str, str] = { + "GET_DESCRIPTION_HELP": ( + "Download originally produced data files.\n\n" + "The datasetID is required (either as an " + "argument or in a request file) and can be found via the ``describe``" + " command." + ), # has some hardcoding in CLI + "MAX_CONCURRENT_REQUESTS_HELP": ( + "Maximum number of concurrent requests. Default 15. The command uses a thread " + "pool executor to manage concurrent requests. If set to 0, no parallel" + " executions are used." + ), + "GET_RESPONSE_HELP": ( + "JSON \n A list of files that were downloaded and some metadata." + ), + "SHOW_OUTPUTNAMES_HELP": ( + "Option to display the names of the output files before download." + ), + "FILTER_HELP": ( + "A pattern that must match the absolute paths of the files to download." + ), + "REGEX_HELP": ( + "The regular expression that must match the absolute paths of the files to " + "download." + ), + "FILE_LIST_HELP": ( + "Path to a '.txt' file containing a " + "list of file paths, line by line, that will " + "be downloaded directly. These files must be from the same dataset as the one s" + "pecified dataset with the datasetID option. If no files can be found, the " + "Toolbox will list all files on the remote server and attempt to find a match." + ), + "CREATE_FILE_LIST_HELP": ( + "Option to only create a file containing the names of the targeted files " + "instead of downloading them. It writes the file to the specified output" + " directory (default to current directory). The file " + "name specified should end with '.txt' or '.csv'. If specified, no other " + "action will be performed." + ), + "SYNC_HELP": ( + "Option to synchronize the local directory with the remote directory. See the " + "documentation for more details." + ), + "SYNC_DELETE_HELP": ( + "Option to delete local files that are not present on the remote server while " + "applying sync." + ), + "INDEX_PARTS_HELP": ( + "Option to get the index files of an INSITU dataset." + ), + "NO_DIRECTORIES_HELP": ( + "If True, downloaded files will not be organized into directories." + ), +} + + +SUBSET.update(SHARED) +GET.update(SHARED) +LOGIN.update(SHARED) +DESCRIBE.update(SHARED) diff --git a/copernicusmarine/core_functions/exceptions.py b/copernicusmarine/core_functions/exceptions.py index 5affdb8f..58e396da 100644 --- a/copernicusmarine/core_functions/exceptions.py +++ b/copernicusmarine/core_functions/exceptions.py @@ -33,7 +33,7 @@ class CoordinatesOutOfDatasetBounds(Exception): Exception raised when the coordinates are out of the dataset bounds. Please make sure the coordinates are within the dataset bounds. If you are using the - strict mode, the coordinates must be within the dataset bounds. + strict-inside mode, the coordinates must be within the dataset bounds. """ def __init__(self, message: str): diff --git a/copernicusmarine/core_functions/get.py b/copernicusmarine/core_functions/get.py index 86b86e02..aa1b4405 100644 --- a/copernicusmarine/core_functions/get.py +++ b/copernicusmarine/core_functions/get.py @@ -108,7 +108,7 @@ def get_function( if create_file_list is not None: assert create_file_list.endswith(".txt") or create_file_list.endswith( ".csv" - ), "Download file list must be a .txt or .csv file. " + ), "Download file list must be a '.txt' or '.csv' file. " f"Got '{create_file_list}' instead." if file_list_path: direct_download_files = get_direct_download_files(file_list_path) @@ -211,7 +211,7 @@ def get_direct_download_files( if not os.path.exists(file_list_path): raise FileNotFoundError( f"File {file_list_path} does not exist." - " Please provide a valid path to a .txt file." + " Please provide a valid path to a '.txt' file." ) with open(file_list_path) as f: direct_download_files = [line.strip() for line in f.readlines()] diff --git a/copernicusmarine/core_functions/models.py b/copernicusmarine/core_functions/models.py index 2ae33679..3671083b 100644 --- a/copernicusmarine/core_functions/models.py +++ b/copernicusmarine/core_functions/models.py @@ -91,4 +91,4 @@ class ResponseSubset(BaseModel): #: get the final result in MB. data_needed: Optional[float] #: The bounds of the subsetted dataset. - coodinates_extent: DatasetCoordinatesExtent + coordinates_extent: DatasetCoordinatesExtent diff --git a/copernicusmarine/core_functions/utils.py b/copernicusmarine/core_functions/utils.py index 767c3b9d..3e08e290 100644 --- a/copernicusmarine/core_functions/utils.py +++ b/copernicusmarine/core_functions/utils.py @@ -31,12 +31,6 @@ logger = logging.getLogger("copernicusmarine") -OVERWRITE_SHORT_OPTION = "--overwrite" -OVERWRITE_LONG_OPTION = "--overwrite-output-data" -OVERWRITE_OPTION_HELP_TEXT = ( - "If specified and if the file already exists on destination, then it will be " - "overwritten instead of creating new one with unique index." -) FORCE_DOWNLOAD_CLI_PROMPT_MESSAGE = "Do you want to proceed with download?" diff --git a/copernicusmarine/download_functions/download_arco_series.py b/copernicusmarine/download_functions/download_arco_series.py index 066f4bae..703b4301 100644 --- a/copernicusmarine/download_functions/download_arco_series.py +++ b/copernicusmarine/download_functions/download_arco_series.py @@ -134,7 +134,7 @@ def download_dataset( output=output_path, size=final_result_size_estimation, data_needed=data_needed_approximation, - coodinates_extent=get_dataset_coordinates_extent(dataset), + coordinates_extent=get_dataset_coordinates_extent(dataset), ) if dry_run: diff --git a/copernicusmarine/download_functions/utils.py b/copernicusmarine/download_functions/utils.py index 2fe87099..986f6cb1 100644 --- a/copernicusmarine/download_functions/utils.py +++ b/copernicusmarine/download_functions/utils.py @@ -229,9 +229,9 @@ def get_message_formatted_dataset_size_estimation( f"\nEstimated size of the data that needs " f"to be downloaded to obtain the result:" f" {estimation_data_downloaded:.0f} MB" - "\nThis a very rough estimation and usually" - " its higher than the actual size of the" - " data that needs to be downloaded." + "\nThis is a very rough estimate that is" + " generally higher than the actual size of the" + " data that needs to be downloaded." ) diff --git a/copernicusmarine/python_interface/describe.py b/copernicusmarine/python_interface/describe.py index 03a5a83c..e367ff98 100644 --- a/copernicusmarine/python_interface/describe.py +++ b/copernicusmarine/python_interface/describe.py @@ -25,35 +25,32 @@ def describe( staging: bool = False, ) -> dict[str, Any]: """ - Retrieve metadata information from the Copernicus Marine catalogue. - - This function fetches metadata information from the Copernicus Marine catalogue - based on specified parameters and options. + Retrieve and parse the metadata information from the Copernicus Marine catalogue. Parameters ---------- include_description : bool, optional - Whether to include description for each product. Defaults to False. + Include product description in output. include_datasets : bool, optional - Whether to include dataset information. Defaults to False. + Include product dataset details in output. include_keywords : bool, optional - Whether to include keywords for each product. Defaults to False. + Include product keyword details in output. include_versions : bool, optional - Whether to include all versions of each dataset. Defaults to False. + Include dataset versions in output. By default, shows only the default version. include_all : bool, optional - Whether to include all metadata information. Defaults to False. + Include all the possible data in output: description, datasets, keywords, and versions. contains : list[str], optional - List of strings to filter items containing these values. Defaults to []. + Filter catalogue output. Returns products with attributes matching a string token. max_concurrent_requests : int, optional - Maximum number of concurrent requests. Defaults to 15. The describe command - uses a thread pool executor to manage concurrent requests. + Maximum number of concurrent requests (>=1). Default 15. The command uses a thread pool executor to manage concurrent requests. disable_progress_bar : bool, optional - Whether to disable the progress bar. Defaults to False. + Flag to hide progress bar. Returns ------- dict[str, Any] A dictionary containing the retrieved metadata information. + """ # noqa if not isinstance(contains, list): diff --git a/copernicusmarine/python_interface/get.py b/copernicusmarine/python_interface/get.py index 9646560f..0dc67109 100644 --- a/copernicusmarine/python_interface/get.py +++ b/copernicusmarine/python_interface/get.py @@ -40,57 +40,54 @@ def get( staging: bool = False, ) -> ResponseGet: """ - Fetches data from the Copernicus Marine server based on the provided parameters. + Download originally produced data files. + + The datasetID is required (either as an argument or in a request file) and can be found via the ``describe`` command. Parameters ---------- dataset_id : str, optional - The unique identifier of the dataset. + The datasetID, required either as an argument or in the request_file option. dataset_version : str, optional - Force the use of a specific dataset version. + Force the selection of a specific dataset version. dataset_part : str, optional - Force the use of a specific dataset part. + Force the selection of a specific dataset part. username : str, optional - The username for authentication. See also :func:`~copernicusmarine.login`. + The username for authentication. password : str, optional - The password for authentication. See also :func:`~copernicusmarine.login`. + The password for authentication. output_directory : Union[pathlib.Path, str], optional - The directory where downloaded files will be saved. + The destination folder for the downloaded files. Default is the current directory. credentials_file : Union[pathlib.Path, str], optional - Path to a file containing authentication credentials. + Path to a credentials file if not in its default directory (``$HOME/.copernicusmarine``). Accepts .copernicusmarine-credentials / .netrc or _netrc / motuclient-python.ini files. force_download : bool, optional - Skip confirmation before download. + Flag to skip confirmation before download. overwrite_output_data : bool, optional - If True, overwrite existing output files. + If specified and if the file already exists on destination, then it will be overwritten instead of creating new one with unique index. request_file : Union[pathlib.Path, str], optional - Path to a file containing request parameters. For more information, please refer to the README. + Option to pass a file containing the arguments. For more information please refer to the documentation or use option ``--create-template`` from the command line interface for an example template. no_directories : bool, optional If True, downloaded files will not be organized into directories. show_outputnames : bool, optional - If True, display the names of the downloaded files. + Option to display the names of the output files before download. filter : str, optional - Apply a filter to the downloaded data. + A pattern that must match the absolute paths of the files to download. regex : str, optional - Apply a regular expression filter to the downloaded data. + The regular expression that must match the absolute paths of the files to download. file_list : Union[pathlib.Path, str], optional - Path to a .txt file containing a list of file paths, line by line, that will be downloaded directly. - These files must be from the specified dataset using the --dataset-id. If no files can be found, - the Toolbox will list all files on the remote server and attempt to find a match. + Path to a '.txt' file containing a list of file paths, line by line, that will be downloaded directly. These files must be from the same dataset as the one specified dataset with the datasetID option. If no files can be found, the Toolbox will list all files on the remote server and attempt to find a match. create_file_list : str, optional - Option to only create a file containing the names of the targeted files instead of downloading them. - It writes the file in the directory specified with the --output-directory option (default to current directory). - If specified, no other action will be performed. + Option to only create a file containing the names of the targeted files instead of downloading them. It writes the file to the specified output directory (default to current directory). The file name specified should end with '.txt' or '.csv'. If specified, no other action will be performed. index_parts : bool, optional - If True, download index files. Only for INSITU datasets. Temporary option. + Option to get the index files of an INSITU dataset. sync : bool, optional - If True, synchronize the local directory with the remote directory. + Option to synchronize the local directory with the remote directory. See the documentation for more details. sync_delete : bool, optional - If True, delete local files that are not present on the remote server while applying sync. + Option to delete local files that are not present on the remote server while applying sync. dry_run : bool, optional If True, runs query without downloading data. max_concurrent_requests : int, optional - Maximum number of concurrent requests. Defaults to 15. The get command - uses a thread pool executor to manage concurrent requests. + Maximum number of concurrent requests. Default 15. The command uses a thread pool executor to manage concurrent requests. If set to 0, no parallel executions are used. disable_progress_bar : bool, optional Flag to hide progress bar. @@ -98,6 +95,7 @@ def get( ------- ResponseGet A list of files that were downloaded and some metadata. + """ # noqa output_directory = ( pathlib.Path(output_directory) if output_directory else None diff --git a/copernicusmarine/python_interface/login.py b/copernicusmarine/python_interface/login.py index 54d063ab..23007141 100644 --- a/copernicusmarine/python_interface/login.py +++ b/copernicusmarine/python_interface/login.py @@ -15,28 +15,29 @@ def login( check_credentials_valid: bool = False, ) -> bool: """ - Create a configuration file with your Copernicus Marine credentials. + Create a configuration file with your Copernicus Marine credentials under the ``$HOME/.copernicusmarine`` directory (overwritable with the ``overwrite_configuration_file`` option). Parameters ---------- username : str, optional - If not set, searches for the environment variable `COPERNICUSMARINE_SERVICE_USERNAME`, - or else asks for user input. + The username for authentication. password : str, optional - If not set, searches for the environment variable `COPERNICUSMARINE_SERVICE_PASSWORD`, - or else asks for user input. + The password for authentication. configuration_file_directory : Union[pathlib.Path, str] Path to the directory where the configuration file is stored. overwrite_configuration_file : bool - Flag to skip confirmation before overwriting the configuration file. - skip_if_user_logged_in : bool - Flag to check if the credentials are valid. - No other action will be performed. - The validity will be check in this order: + Flag to skip confirmation before overwriting configuration file. + check_credentials_valid : bool + Flag to check if the credentials are valid. No other action will be performed. The validity will be check in this order: 1. Check if the credentials are valid with the provided username and password. - 2. Check if the credentials are valid in the configuration file. - 3. Check if the credentials are valid in the environment variables. - When any is found not valid, will return False immediately., + 2. Check if the credentials are valid in the environment variables. + 3. Check if the credentials are valid in the configuration file. + When any is found (valid or not valid), will return immediately. + + Returns + ------- + bool + True value if the login was successfully completed, False otherwise. """ # noqa return login_function( username=username, diff --git a/copernicusmarine/python_interface/open_dataset.py b/copernicusmarine/python_interface/open_dataset.py index aa6d334a..b15fb669 100644 --- a/copernicusmarine/python_interface/open_dataset.py +++ b/copernicusmarine/python_interface/open_dataset.py @@ -59,50 +59,51 @@ def open_dataset( credentials_file: Optional[Union[pathlib.Path, str]] = None, ) -> xarray.Dataset: """ - Load an xarray dataset using "lazy-loading" mode from a Copernicus Marine data source using either the ARCO series protocol. + Load an xarray dataset using 'lazy-loading' mode from a Copernicus Marine data source. This means that data is only loaded into memory when a computation is called, optimizing RAM usage by avoiding immediate loading. It supports various parameters for customization, such as specifying geographical bounds, temporal range, depth range, and more. + Parameters ---------- dataset_id : str - The ID of the dataset. `dataset_id` is mandatory. + The datasetID, required. dataset_version : str, optional - Force the use of a specific dataset version. + Force the selection of a specific dataset version. dataset_part : str, optional - Force the use of a specific dataset part. + Force the selection of a specific dataset part. username : str, optional - Username for authentication, if required. + The username for authentication. password : str, optional - Password for authentication, if required. + The password for authentication. variables : List[str], optional - List of variable names to be loaded from the dataset. + List of variable names to extract. minimum_longitude : float, optional - The minimum longitude for subsetting the data. + Minimum longitude for the subset. The value will be transposed to the interval [-180; 360[. maximum_longitude : float, optional - The maximum longitude for subsetting the data. + Maximum longitude for the subset. The value will be transposed to the interval [-180; 360[. minimum_latitude : float, optional - The minimum latitude for subsetting the data. + Minimum latitude for the subset. Requires a float from -90 degrees to +90. maximum_latitude : float, optional - The maximum latitude for subsetting the data. + Maximum latitude for the subset. Requires a float from -90 degrees to +90. minimum_depth : float, optional - The minimum depth for subsetting the data. + Minimum depth for the subset. Requires a positive float (or 0). maximum_depth : float, optional - The maximum depth for subsetting the data. + Maximum depth for the subset. Requires a positive float (or 0). coordinates_selection_method : str, optional - The method in which the coordinates will be retrieved. If 'strict', the retrieved selection will be inside the requested interval. If 'strict', the retrieved selection will be inside the requested interval and an error will raise if there doesn't exist the values. If 'nearest', the returned interval extremes will be the closest to what has been asked for. A warning will be displayed if outside of bounds. If 'outisde', the extremes will be taken to contain all the requested interval. A warning will also be displayed if the subset is outside of the dataset bounds. + If ``inside``, the selection retrieved will be inside the requested range. If ``strict-inside``, the selection retrieved will be inside the requested range, and an error will be raised if the values don't exist. If ``nearest``, the extremes closest to the requested values will be returned. If ``outside``, the extremes will be taken to contain all the requested interval. The methods ``inside``, ``nearest`` and ``outside`` will display a warning if the request is out of bounds. vertical_dimension_output : str, optional - Consolidate the vertical dimension (the z-axis) as requested: 'depth' with descending positive values. - 'elevation' with ascending positive values. Default is 'depth'. - start_datetime : datetime, optional - The start datetime for temporal subsetting. - end_datetime : datetime, optional - The end datetime for temporal subsetting. + Consolidate the vertical dimension (the z-axis) as requested: depth with descending positive values, elevation with ascending positive values. Default is depth. + start_datetime : Union[datetime, str], optional + The start datetime of the temporal subset. Supports common format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing). + end_datetime : Union[datetime, str], optional + The end datetime of the temporal subset. Supports common format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing). service : str, optional - Force the use of a specific service (ARCO geo series or time series). + Force download through one of the available services using the service name among ['arco-geo-series', 'arco-time-series', 'omi-arco', 'static-arco'] or its short name among ['arco-geo-series', 'arco-time-series', 'omi-arco', 'static-arco']. credentials_file : Union[pathlib.Path, str], optional - Path to a file containing authentication credentials. + Path to a credentials file if not in its default directory (``$HOME/.copernicusmarine``). Accepts .copernicusmarine-credentials / .netrc or _netrc / motuclient-python.ini files. + Returns ------- diff --git a/copernicusmarine/python_interface/read_dataframe.py b/copernicusmarine/python_interface/read_dataframe.py index 70c0d365..322618bb 100644 --- a/copernicusmarine/python_interface/read_dataframe.py +++ b/copernicusmarine/python_interface/read_dataframe.py @@ -55,55 +55,54 @@ def read_dataframe( coordinates_selection_method: CoordinatesSelectionMethod = ( DEFAULT_COORDINATES_SELECTION_METHOD ), - force_service: Optional[str] = None, + service: Optional[str] = None, credentials_file: Optional[Union[pathlib.Path, str]] = None, ) -> pandas.DataFrame: """ Immediately loads a Pandas DataFrame into memory from a specified dataset. - Unlike "lazy-loading," the data is loaded as soon as this function is executed, - which may be preferable when rapid access to the entire dataset is required, - but may require careful memory management. + Unlike 'lazy-loading,' the data is loaded as soon as this function is executed, which may be preferable when rapid access to the entire dataset is required, but may require careful memory management. + Parameters ---------- - dataset_id : str, optional - The identifier of the dataset. + dataset_id : str + The datasetID, required. dataset_version : str, optional - Force a specific dataset version. + Force the selection of a specific dataset version. dataset_part : str, optional - Force a specific dataset part. + Force the selection of a specific dataset part. username : str, optional - Username for authentication. + The username for authentication. password : str, optional - Password for authentication. + The password for authentication. variables : List[str], optional - List of variable names to load. + List of variable names to extract. minimum_longitude : float, optional - Minimum longitude for spatial subset. + Minimum longitude for the subset. The value will be transposed to the interval [-180; 360[. maximum_longitude : float, optional - Maximum longitude for spatial subset. + Maximum longitude for the subset. The value will be transposed to the interval [-180; 360[. minimum_latitude : float, optional - Minimum latitude for spatial subset. + Minimum latitude for the subset. Requires a float from -90 degrees to +90. maximum_latitude : float, optional - Maximum latitude for spatial subset. + Maximum latitude for the subset. Requires a float from -90 degrees to +90. minimum_depth : float, optional - Minimum depth for vertical subset. + Minimum depth for the subset. Requires a positive float (or 0). maximum_depth : float, optional - Maximum depth for vertical subset. + Maximum depth for the subset. Requires a positive float (or 0). vertical_dimension_output : str, optional - Consolidate the vertical dimension (the z-axis) as requested: 'depth' with descending positive values. - 'elevation' with ascending positive values. Default is 'depth'. - start_datetime : datetime, optional - Start datetime for temporal subset. - end_datetime : datetime, optional - End datetime for temporal subset. + Consolidate the vertical dimension (the z-axis) as requested: depth with descending positive values, elevation with ascending positive values. Default is depth. + start_datetime : Union[datetime, str], optional + The start datetime of the temporal subset. Supports common format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing). + end_datetime : Union[datetime, str], optional + The end datetime of the temporal subset. Supports common format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing). coordinates_selection_method : str, optional - The method in which the coordinates will be retrieved.If 'strict', the retrieved selection will be inside the requested interval. If 'strict', the retrieved selection will be inside the requested interval and an error will raise if there doesn't exist the values. If 'nearest', the returned interval extremes will be the closest to what has been asked for. A warning will be displayed if outside of bounds. If 'outisde', the extremes will be taken to contain all the requested interval. A warning will also be displayed if the subset is outside of the dataset bounds. - force_service : str, optional - Force a specific service for data download. + If ``inside``, the selection retrieved will be inside the requested range. If ``strict-inside``, the selection retrieved will be inside the requested range, and an error will be raised if the values don't exist. If ``nearest``, the extremes closest to the requested values will be returned. If ``outside``, the extremes will be taken to contain all the requested interval. The methods ``inside``, ``nearest`` and ``outside`` will display a warning if the request is out of bounds. + service : str, optional + Force download through one of the available services using the service name among ['arco-geo-series', 'arco-time-series', 'omi-arco', 'static-arco'] or its short name among ['arco-geo-series', 'arco-time-series', 'omi-arco', 'static-arco']. credentials_file : Union[pathlib.Path, str], optional - Path to a credentials file for authentication. + Path to a credentials file if not in its default directory (``$HOME/.copernicusmarine``). Accepts .copernicusmarine-credentials / .netrc or _netrc / motuclient-python.ini files. + Returns ------- @@ -143,7 +142,7 @@ def read_dataframe( maximum_depth=maximum_depth, vertical_dimension_output=vertical_dimension_output, ), - force_service=force_service, + force_service=service, credentials_file=credentials_file, ) dataset = load_data_object_from_load_request( diff --git a/copernicusmarine/python_interface/subset.py b/copernicusmarine/python_interface/subset.py index 21e9f96f..5f836c20 100644 --- a/copernicusmarine/python_interface/subset.py +++ b/copernicusmarine/python_interface/subset.py @@ -59,73 +59,74 @@ def subset( netcdf3_compatible: bool = False, ) -> ResponseSubset: """ - Extracts a subset of data from a specified dataset using given parameters. + Extracts a subset of data from a specified dataset using given parameters." + + The datasetID is required and can be found via the ``describe`` command. Parameters ---------- dataset_id : str, optional - The unique identifier of the dataset. + The datasetID, required either as an argument or in the request_file option. dataset_version : str, optional - Force the use of a specific dataset version. + Force the selection of a specific dataset version. dataset_part : str, optional - Force the use of a specific dataset part. + Force the selection of a specific dataset part. username : str, optional - The username for authentication. See also :func:`~copernicusmarine.login`. + The username for authentication. See also :func:`~copernicusmarine.login` password : str, optional - The password for authentication. See also :func:`~copernicusmarine.login`. + The password for authentication. See also :func:`~copernicusmarine.login` output_directory : Union[pathlib.Path, str], optional - The directory where downloaded files will be saved. + The destination folder for the downloaded files. Default is the current directory. credentials_file : Union[pathlib.Path, str], optional - Path to a file containing authentication credentials. + Path to a credentials file if not in its default directory (``$HOME/.copernicusmarine``). Accepts .copernicusmarine-credentials / .netrc or _netrc / motuclient-python.ini files. force_download : bool, optional - Skip confirmation before download. + Flag to skip confirmation before download. overwrite_output_data : bool, optional - If True, overwrite existing output files. + If specified and if the file already exists on destination, then it will be overwritten instead of creating new one with unique index. request_file : Union[pathlib.Path, str], optional - Path to a file containing request parameters. For more information, please refer to the README. + Option to pass a file containing the arguments. For more information please refer to the documentation or use option ``--create-template`` from the command line interface for an example template. service : str, optional - Force the use of a specific service. + Force download through one of the available services using the service name among ['arco-geo-series', 'arco-time-series', 'omi-arco', 'static-arco'] or its short name among ['arco-geo-series', 'arco-time-series', 'omi-arco', 'static-arco']. variables : List[str], optional List of variable names to extract. minimum_longitude : float, optional - Minimum longitude value for spatial subset. + Minimum longitude for the subset. The value will be transposed to the interval [-180; 360[. maximum_longitude : float, optional - Maximum longitude value for spatial subset. + Maximum longitude for the subset. The value will be transposed to the interval [-180; 360[. minimum_latitude : float, optional - Minimum latitude value for spatial subset. + Minimum latitude for the subset. Requires a float from -90 degrees to +90. maximum_latitude : float, optional - Maximum latitude value for spatial subset. + Maximum latitude for the subset. Requires a float from -90 degrees to +90. minimum_depth : float, optional - Minimum depth value for vertical subset. + Minimum depth for the subset. Requires a positive float (or 0). maximum_depth : float, optional - Maximum depth value for vertical subset. + Maximum depth for the subset. Requires a positive float (or 0). vertical_dimension_output : str, optional - Consolidate the vertical dimension (the z-axis) as requested: 'depth' with descending positive values. - 'elevation' with ascending positive values. Default is 'depth'. - start_datetime : datetime, optional - Start datetime for temporal subset. - end_datetime : datetime, optional - End datetime for temporal subset. + Consolidate the vertical dimension (the z-axis) as requested: depth with descending positive values, elevation with ascending positive values. Default is depth. + start_datetime : Union[datetime, str], optional + The start datetime of the temporal subset. Supports common format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing). + end_datetime : Union[datetime, str], optional + The end datetime of the temporal subset. Supports common format parsed by pendulum (https://pendulum.eustace.io/docs/#parsing). coordinates_selection_method : str, optional - The method in which the coordinates will be retrieved. If 'strict', the retrieved selection will be inside the requested interval. If 'strict', the retrieved selection will be inside the requested interval and an error will raise if there doesn't exist the values. If 'nearest', the returned interval extremes will be the closest to what has been asked for. A warning will be displayed if outside of bounds. If 'outisde', the extremes will be taken to contain all the requested interval. A warning will also be displayed if the subset is outside of the dataset bounds. + If ``inside``, the selection retrieved will be inside the requested range. If ``strict-inside``, the selection retrieved will be inside the requested range, and an error will be raised if the values don't exist. If ``nearest``, the extremes closest to the requested values will be returned. If ``outside``, the extremes will be taken to contain all the requested interval. The methods ``inside``, ``nearest`` and ``outside`` will display a warning if the request is out of bounds. output_filename : str, optional - Output filename for the subsetted data. + Save the downloaded data with the given file name (under the output directory). file_format : str, optional - Extension format for the filename. + Format of the downloaded dataset. Default to NetCDF '.nc'. motu_api_request : str, optional - MOTU API request string. + Option to pass a complete MOTU API request as a string. Caution, user has to replace double quotes “ with single quotes ' in the request. dry_run : bool, optional If True, runs query without downloading data. netcdf_compression_level : int, optional - Specify a compression level to apply on the NetCDF output file. A value of 0 means no compression, and 9 is the - highest level of compression available. + Specify a compression level to apply on the NetCDF output file. A value of 0 means no compression, and 9 is the highest level of compression available. netcdf3_compatible : bool, optional - Enable downloading the dataset in a netCDF 3 compatible format. + Enable downloading the dataset in a netCDF3 compatible format. Returns ------- ResponseSubset A description of the downloaded data and its destination. + """ # noqa request_file = pathlib.Path(request_file) if request_file else None output_directory = ( diff --git a/doc/command-line-interface.rst b/doc/command-line-interface.rst index 18968277..4654ff11 100644 --- a/doc/command-line-interface.rst +++ b/doc/command-line-interface.rst @@ -8,7 +8,7 @@ Command line interface :nested: short :commands: login, get, subset, describe - +.. _cli-describe: .. click:: copernicusmarine.command_line_interface.group_describe:describe :prog: describe :nested: short diff --git a/doc/usage/subset-usage.rst b/doc/usage/subset-usage.rst index 6b4fb27a..d652bcfc 100644 --- a/doc/usage/subset-usage.rst +++ b/doc/usage/subset-usage.rst @@ -55,7 +55,7 @@ Note that any longitudes can be requested. The system applies a modulus operatio About ``--netcdf-compression-level`` options """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" -If writing data to a NetCDF file (the default format), the ``--netcdf-compression-level`` option can be set to compress the downloaded file. This reduces file size but increases writing time. Without this option, the file is written faster but with a larger size. For Zarr format (`.zarr` extension), the default compression of the Copernicus Marine Data Store is applied, making the download fast and compressed without using ``--netcdf-compression-level``. +If writing data to a NetCDF file (the default format), the ``--netcdf-compression-level`` option can be set to compress the downloaded file. This reduces file size but increases writing time. Without this option, the file is written faster but with a larger size. For Zarr format ('.zarr' extension), the default compression of the Copernicus Marine Data Store is applied, making the download fast and compressed without using ``--netcdf-compression-level``. Default NetCDF compression settings for xarray: @@ -71,26 +71,39 @@ About ``--netcdf3-compatible`` option The ``--netcdf3-compatible`` option enables compatibility with the netCDF3 format. This uses the ``format="NETCDF3_CLASSIC"`` setting in the xarray `to_netcdf` method. (cf. `xarray documentation `_.) -About ``--bounding-box-method`` option -"""""""""""""""""""""""""""""""""""""""" +About ``--coordinates-selection-method`` option +"""""""""""""""""""""""""""""""""""""""""""""""""" -The ``--bounding-box-method`` option lets you specify how the requested interval selects data points: +The ``--coordinates-selection-method`` option lets you specify how the requested interval selects data points: - **inside** (default): Returns points strictly within the requested area. +- **strict-inside**: Returns points strictly within the requested area. Fails with an error if the requested area is outside the dataset. - **nearest**: Returns points closest to the requested interval. - **outside**: Returns all points covering the requested area. This applies to all dimensions: longitude, latitude, time, and depth. **Example of longitude requests:** +Imagine a dataset with longitudes from 5.0 to 36.5, with steps of 0.5. + +- ``--coordinates-selection-method`` = **inside**, with requested interval = [0.4, 35.9]: + + - Returns longitudes within the range: [0.5, 35.5] + +- ``--coordinates-selection-method`` = **strict-inside**, with requested interval = [0.4, 35.9]: + + - Returns longitudes within the range: [0.5, 35.5] + +- ``--coordinates-selection-method`` = **strict-inside**, with requested interval = [0.0, 40]: + + - Returns an error, see :class:`copernicusmarine.CoordinatesOutOfDatasetBounds`. + +- ``--coordinates-selection-method`` = **outside**, with requested interval = [0.4, 35.9]: -- ``--bounding-box-method inside``: - - Returns longitudes within the range: [0.08334, 0.917] + - Returns longitudes within the range: [0.0, 36.0] -- ``--bounding-box-method nearest``: - - Returns longitudes: [0.0, 2.917] +- ``--coordinates-selection-method`` = **nearest**, with requested interval = [0.4, 35.9]: -- ``--bounding-box-method outside``: - - Outputs longitudes from: [0.0, 3.0] + - Returns longitudes within the range: [0.5, 36.0] If you request a single point, the nearest point in that dimension will be returned. diff --git a/tests/__snapshots__/test_help_command_interface.ambr b/tests/__snapshots__/test_help_command_interface.ambr index 92c3fc2a..629e69a7 100644 --- a/tests/__snapshots__/test_help_command_interface.ambr +++ b/tests/__snapshots__/test_help_command_interface.ambr @@ -20,15 +20,10 @@ list([ "CompletedProcess(args=['copernicusmarine', 'describe', '--help'], returncode=0, stdout=b'Usage: copernicusmarine describe [OPTIONS]", '', - ' Print Copernicus Marine catalogue as JSON.', + ' Retrieve and parse the metadata information from the Copernicus Marine', + ' catalogue.', '', - ' The default display contains information on the products, and more data can', - ' be displayed using the ``--include-`` flags.', - '', - ' The ``--contains`` option allows the user to specify one or several strings', - ' to filter through the catalogue display. The search is performed recursively', - ' on all attributes of the catalog, and the tokens only need to be contained', - ' in one of the attributes (i.e., not an exact match).', + ' Returns JSON A dictionary containing the retrieved metadata information.', '', 'Options:', ' --include-description Include product description in output.', @@ -42,10 +37,9 @@ ' -c, --contains TEXT Filter catalogue output. Returns products', ' with attributes matching a string token.', ' --max-concurrent-requests INTEGER', - ' Maximum number of concurrent requests.', - ' Default 15. The describe command uses a', - ' thread pool executor to manage concurrent', - ' requests.', + ' Maximum number of concurrent requests (>=1).', + ' Default 15. The command uses a thread pool', + ' executor to manage concurrent requests.', ' --disable-progress-bar Flag to hide progress bar.', ' --log-level [DEBUG|INFO|WARN|ERROR|CRITICAL|QUIET]', ' Set the details printed to console by the', @@ -59,47 +53,44 @@ ' copernicusmarine describe --contains METOFFICE-GLO-SST-L4-NRT-OBS-SST-V2 --include-datasets', '', '', - ' copernicusmarine describe -c METOFFICE-GLO-SST-L4-NRT-OBS-SST-V2', + ' copernicusmarine describe -c METOFFICE-GLO-SST-L4-NRT-OBS-SST-V2 ', + '', ' ', "', stderr=b'')", ]) # --- # name: TestHelpCommandLineInterface.test_help_from_get_is_as_expected list([ - "CompletedProcess(args=['copernicusmarine', 'get', '--help'], returncode=0, stdout=b'Usage: copernicusmarine get [OPTIONS]", + 'CompletedProcess(args=[\'copernicusmarine\', \'get\', \'--help\'], returncode=0, stdout=b"Usage: copernicusmarine get [OPTIONS]', '', ' Download originally produced data files.', '', - ' The ``--dataset-id`` is required (can be found via the "describe" command).', - ' The function fetches the files recursively if a folder path is passed as a', - ' URL. When provided a dataset ID, all the files in the corresponding folder', - ' will be downloaded if none of the ``--filter`` or ``--regex`` options is', - ' specified.', + ' The datasetID is required (either as an argument or in a request file) and', + ' can be found via the ``describe`` command. See :ref:`describe `.', + '', + ' Returns JSON A list of files that were downloaded and some metadata.', '', 'Options:', - ' -i, --dataset-id TEXT The datasetID.', + ' -i, --dataset-id TEXT The datasetID, required either as an', + ' argument or in the request_file option.', ' --dataset-version TEXT Force the selection of a specific dataset', ' version.', ' --dataset-part TEXT Force the selection of a specific dataset', ' part.', - ' --username TEXT If not set, search for environment variable', - ' COPERNICUSMARINE_SERVICE_USERNAME, or else', - ' look for configuration files, or else ask', - ' for user input.', - ' --password TEXT If not set, search for environment variable', - ' COPERNICUSMARINE_SERVICE_PASSWORD, or else', - ' look for configuration files, or else ask', - ' for user input.', - ' -nd, --no-directories Option to not recreate folder hierarchy in', - ' ouput directory. \\x08 NOTE:', - ' This argument is mutually exclusive with', - ' arguments: [sync].', + ' --username TEXT The username for authentication.', + ' --password TEXT The password for authentication.', + ' -nd, --no-directories If True, downloaded files will not be', + ' organized into directories.', + ' \\x08 NOTE: This argument is mutually exclusive', + ' with arguments: [sync].', ' --show-outputnames Option to display the names of the output', ' files before download.', - ' -o, --output-directory PATH The destination directory for the downloaded', + ' -o, --output-directory PATH The destination folder for the downloaded', ' files. Default is the current directory.', ' --credentials-file PATH Path to a credentials file if not in its', - ' default directory. Accepts', + ' default directory', + ' (``$HOME/.copernicusmarine``). Accepts', ' .copernicusmarine-credentials / .netrc or', ' _netrc / motuclient-python.ini files.', ' --force-download Flag to skip confirmation before download.', @@ -108,36 +99,38 @@ ' on destination, then it will be overwritten', ' instead of creating new one with unique', ' index.', - ' --create-template Option to create a file get_template.json in', - ' your current directory containing CLI', - ' arguments. If specified, no other action', - ' will be performed.', - ' --request-file PATH Option to pass a file containing CLI', - ' arguments. The file MUST follow the', - " structure of dataclass \\'GetRequest\\'. For", - ' more information please refer to the README.', + ' --create-template Option to create a file', + ' _template.json in your current', + ' directory containing the arguments. If', + ' specified, no other action will be', + ' performed.', + ' --request-file PATH Option to pass a file containing the', + ' arguments. For more information please refer', + ' to the documentation or use option', + ' ``--create-template`` from the command line', + ' interface for an example template.', ' --filter, --filter-with-globbing-pattern TEXT', ' A pattern that must match the absolute paths', ' of the files to download.', ' --regex, --filter-with-regular-expression TEXT', ' The regular expression that must match the', ' absolute paths of the files to download.', - ' --file-list PATH Path to a .txt file containing a list of', + " --file-list PATH Path to a '.txt' file containing a list of", ' file paths, line by line, that will be', ' downloaded directly. These files must be', - ' from the specified dataset using the', - ' --dataset-id. If no files can be found, the', - ' Toolbox will list all files on the remote', - ' server and attempt to find a match.', + ' from the same dataset as the one specified', + ' dataset with the datasetID option. If no', + ' files can be found, the Toolbox will list', + ' all files on the remote server and attempt', + ' to find a match.', ' --create-file-list TEXT Option to only create a file containing the', ' names of the targeted files instead of', - ' downloading them. It writes the file in the', - ' directory specified with the --output-', - ' directory option (default to current', - ' directory). The file name specified should', - " end with \\'.txt\\' or \\'.csv\\' If specified, no", - ' other action will be performed. Please find', - ' more information in the README.', + ' downloading them. It writes the file to the', + ' specified output directory (default to', + ' current directory). The file name specified', + " should end with '.txt' or '.csv'. If", + ' specified, no other action will be', + ' performed.', ' --sync Option to synchronize the local directory', ' with the remote directory. See the', ' documentation for more details.', @@ -149,12 +142,14 @@ ' is mutually exclusive with arguments: [no-', ' directories].', ' --index-parts Option to get the index files of an INSITU', - ' dataset. Temporary option.', - ' --dry-run Runs query without downloading data.', + ' dataset.', + ' --dry-run If True, runs query without downloading', + ' data.', ' --max-concurrent-requests INTEGER', ' Maximum number of concurrent requests.', - ' Default 15. The get command uses a thread', - ' pool executor to manage concurrent requests.', + ' Default 15. The command uses a thread pool', + ' executor to manage concurrent requests. If', + ' set to 0, no parallel executions are used.', ' --disable-progress-bar Flag to hide progress bar.', ' --log-level [DEBUG|INFO|WARN|ERROR|CRITICAL|QUIET]', ' Set the details printed to console by the', @@ -165,27 +160,26 @@ ' Example to download all the files from a given dataset:', '', '', - ' copernicusmarine get -i cmems_mod_nws_bgc-pft_myint_7km-3D-diato_P1M-m', + ' copernicusmarine get -i cmems_mod_nws_bgc-pft_myint_7km-3D-diato_P1M-m ', + '', ' ', - "', stderr=b'')", + '", stderr=b\'\')', ]) # --- # name: TestHelpCommandLineInterface.test_help_from_login_is_as_expected list([ "CompletedProcess(args=['copernicusmarine', 'login', '--help'], returncode=0, stdout=b'Usage: copernicusmarine login [OPTIONS]", '', - ' Create a configuration file with your Copernicus Marine credentials.', + ' Create a configuration file with your Copernicus Marine credentials under', + ' the ``$HOME/.copernicusmarine`` directory (overwritable with the', + ' ``overwrite_configuration_file`` option).', '', - ' Create a configuration file under the ``$HOME/.copernicusmarine`` directory', - ' (overwritable with the ``--credentials-file`` option).', + ' Returns Exit code 0 exit code if the login was successfully completed, 1', + ' otherwise.', '', 'Options:', - ' --username TEXT If not set, search for environment variable', - ' COPERNICUSMARINE_SERVICE_USERNAME, or else', - ' ask for user input.', - ' --password TEXT If not set, search for environment variable', - ' COPERNICUSMARINE_SERVICE_PASSWORD, or else', - ' ask for user input.', + ' --username TEXT The username for authentication.', + ' --password TEXT The password for authentication.', ' --configuration-file-directory PATH', ' Path to the directory where the', ' configuration file is stored.', @@ -196,12 +190,12 @@ ' No other action will be performed. The', ' validity will be check in this order: 1.', ' Check if the credentials are valid with the', - ' provided username and password.2. Check if', - ' the credentials are valid in the', - ' configuration file.3. Check if the', - ' credentials are valid in the environment', - ' variables.When any is found not valid, will', - ' return False immediately.', + ' provided username and password. 2. Check if', + ' the credentials are valid in the environment', + ' variables. 3. Check if the credentials are', + ' valid in the configuration file. When any is', + ' found (valid or not valid), will return', + ' immediately.', ' --log-level [DEBUG|INFO|WARN|ERROR|CRITICAL|QUIET]', ' Set the details printed to console by the', ' command (based on standard logging library).', @@ -232,90 +226,85 @@ # --- # name: TestHelpCommandLineInterface.test_help_from_subset_is_as_expected list([ - "CompletedProcess(args=['copernicusmarine', 'subset', '--help'], returncode=0, stdout=b'Usage: copernicusmarine subset [OPTIONS]", + 'CompletedProcess(args=[\'copernicusmarine\', \'subset\', \'--help\'], returncode=0, stdout=b"Usage: copernicusmarine subset [OPTIONS]', + '', + ' Extracts a subset of data from a specified dataset using given parameters.', '', - ' Download subsets of datasets as NetCDF files or Zarr stores.', + ' The datasetID is required and can be found via the ``describe`` command. See', + ' :ref:`describe `.', '', - ' The ``--dataset-id`` is required (can be found via the "describe" command).', - ' The argument values passed individually through the CLI take precedence over', - ' the values from the ``--motu-api-request`` option, which takes precedence', - ' over the ones from the ``--request-file`` option.', + ' Returns JSON A description of the downloaded data and its destination.', '', 'Options:', - ' -i, --dataset-id TEXT The datasetID.', + ' -i, --dataset-id TEXT The datasetID, required either as an', + ' argument or in the request_file option.', ' --dataset-version TEXT Force the selection of a specific dataset', ' version.', ' --dataset-part TEXT Force the selection of a specific dataset', ' part.', - ' --username TEXT If not set, search for environment variable', - ' COPERNICUSMARINE_SERVICE_USERNAME, or else', - ' look for configuration files, or else ask', - ' for user input.', - ' --password TEXT If not set, search for environment variable', - ' COPERNICUSMARINE_SERVICE_PASSWORD, or else', - ' look for configuration files, or else ask', - ' for user input.', + ' --username TEXT The username for authentication.', + ' --password TEXT The password for authentication.', ' -v, --variable TEXT Specify dataset variable. Can be used', ' multiple times.', ' -x, --minimum-longitude FLOAT Minimum longitude for the subset. The value', - ' will be reduced to the interval [-180; 360[.', + ' will be transposed to the interval [-180;', + ' 360[.', ' -X, --maximum-longitude FLOAT Maximum longitude for the subset. The value', - ' will be reduced to the interval [-180; 360[.', + ' will be transposed to the interval [-180;', + ' 360[.', ' -y, --minimum-latitude FLOAT RANGE', ' Minimum latitude for the subset. Requires a', - ' float within this range: [-90<=x<=90]', + ' float from -90 degrees to +90. [-90<=x<=90]', ' -Y, --maximum-latitude FLOAT RANGE', ' Maximum latitude for the subset. Requires a', - ' float within this range: [-90<=x<=90]', + ' float from -90 degrees to +90. [-90<=x<=90]', ' -z, --minimum-depth FLOAT RANGE', ' Minimum depth for the subset. Requires a', - ' float within this range: [x>=0]', + ' positive float (or 0). [x>=0]', ' -Z, --maximum-depth FLOAT RANGE', ' Maximum depth for the subset. Requires a', - ' float within this range: [x>=0]', + ' positive float (or 0). [x>=0]', ' -V, --vertical-dimension-output [depth|elevation]', ' Consolidate the vertical dimension (the', - ' z-axis) as requested: `depth` with', - ' descending positive values. `elevation` with', - ' ascending positive values. Default is', - ' `depth`.', + ' z-axis) as requested: depth with descending', + ' positive values, elevation with ascending', + ' positive values. Default is depth.', ' -t, --start-datetime TEXT The start datetime of the temporal subset.', - ' Caution: encapsulate date with " " to ensure', - ' valid expression for format "%Y-%m-%d', - ' %H:%M:%S". Supports common format parsed by', - ' pendulum. See', - ' https://pendulum.eustace.io/docs/#parsing', + ' Supports common format parsed by pendulum (h', + ' ttps://pendulum.eustace.io/docs/#parsing).Ca', + ' ution: encapsulate date with \\xe2\\x80\\x9c \\xe2\\x80\\x9c to ensure', + ' valid expression for format \\xe2\\x80\\x9c%Y-%m-%d', + ' %H:%M:%S\\xe2\\x80\\x9d.', ' -T, --end-datetime TEXT The end datetime of the temporal subset.', - ' Caution: encapsulate date with " " to ensure', - ' valid expression for format "%Y-%m-%d', - ' %H:%M:%S". Supports common format parsed by', - ' pendulum. See', - ' https://pendulum.eustace.io/docs/#parsing', + ' Supports common format parsed by pendulum (h', + ' ttps://pendulum.eustace.io/docs/#parsing).Ca', + ' ution: encapsulate date with \\xe2\\x80\\x9c \\xe2\\x80\\x9c to ensure', + ' valid expression for format \\xe2\\x80\\x9c%Y-%m-%d', + ' %H:%M:%S\\xe2\\x80\\x9d.', ' --coordinates-selection-method [inside|strict-inside|nearest|outside]', - ' The method in which the coordinates will be', - " retrieved. If \\'inside\\', the retrieved", - ' selection will be inside the requested', - " interval. If \\'strict-inside\\', the retrieved", - ' selection will be inside the requested', - ' interval and an error will raise if there', - " doesn\\'t exist the values. If \\'nearest\\', the", - ' returned interval extremes will be the', - ' closest to what has been asked for. A', - ' warning will be displayed if outside of', - " bounds. If \\'outisde\\', the extremes will be", - ' taken to contain all the requested interval.', - ' A warning will also be displayed if the', - ' subset is outside of the dataset bounds.', + ' If ``inside``, the selection retrieved will', + ' be inside the requested range. If ``strict-', + ' inside``, the selection retrieved will be', + ' inside the requested range, and an error', + " will be raised if the values don't exist. If", + ' ``nearest``, the extremes closest to the', + ' requested values will be returned. If', + ' ``outside``, the extremes will be taken to', + ' contain all the requested interval. The', + ' methods ``inside``, ``nearest`` and', + ' ``outside`` will display a warning if the', + ' request is out of bounds.', ' -o, --output-directory PATH The destination folder for the downloaded', ' files. Default is the current directory.', ' --credentials-file PATH Path to a credentials file if not in its', - ' default directory. Accepts', + ' default directory', + ' (``$HOME/.copernicusmarine``). Accepts', ' .copernicusmarine-credentials / .netrc or', ' _netrc / motuclient-python.ini files.', - ' -f, --output-filename TEXT Concatenate the downloaded data in the given', - ' file name (under the output directory).', + ' -f, --output-filename TEXT Save the downloaded data with the given file', + ' name (under the output directory).', ' --file-format [netcdf|zarr] Format of the downloaded dataset. Default to', - ' NetCDF (.nc).', + " NetCDF '.nc'.", ' --force-download Flag to skip confirmation before download.', ' --overwrite-output-data, --overwrite', ' If specified and if the file already exists', @@ -324,23 +313,26 @@ ' index.', ' -s, --service TEXT Force download through one of the available', ' services using the service name among', - " [\\'arco-geo-series\\', \\'arco-time-series\\',", - " \\'omi-arco\\', \\'static-arco\\'] or its short name", - " among [\\'geoseries\\', \\'timeseries\\', \\'omi-", - " arco\\', \\'static-arco\\'].", - ' --create-template Option to create a file subset_template.json', - ' in your current directory containing CLI', - ' arguments. If specified, no other action', - ' will be performed.', - ' --request-file PATH Option to pass a file containing CLI', - ' arguments. The file MUST follow the', - " structure of dataclass \\'SubsetRequest\\'. For", - ' more information please refer to the README.', + " ['arco-geo-series', 'arco-time-series',", + " 'omi-arco', 'static-arco'] or its short name", + " among ['arco-geo-series', 'arco-time-", + " series', 'omi-arco', 'static-arco'].", + ' --create-template Option to create a file', + ' _template.json in your current', + ' directory containing the arguments. If', + ' specified, no other action will be', + ' performed.', + ' --request-file PATH Option to pass a file containing the', + ' arguments. For more information please refer', + ' to the documentation or use option', + ' ``--create-template`` from the command line', + ' interface for an example template.', ' --motu-api-request TEXT Option to pass a complete MOTU API request', ' as a string. Caution, user has to replace', - ' double quotes " with single quotes \\\' in the', + " double quotes \\xe2\\x80\\x9c with single quotes ' in the", ' request.', - ' --dry-run Runs query without downloading data.', + ' --dry-run If True, runs query without downloading', + ' data.', ' --disable-progress-bar Flag to hide progress bar.', ' --log-level [DEBUG|INFO|WARN|ERROR|CRITICAL|QUIET]', ' Set the details printed to console by the', @@ -349,8 +341,9 @@ ' Specify a compression level to apply on the', ' NetCDF output file. A value of 0 means no', ' compression, and 9 is the highest level of', - ' compression available [0<=x<=9]', - ' --netcdf3-compatible Enable downloading the dataset in a netCDF 3', + ' compression available. If used as a flag,', + ' the assigned value will be 1. [0<=x<=9]', + ' --netcdf3-compatible Enable downloading the dataset in a netCDF3', ' compatible format.', ' -h, --help Show this message and exit.', '', @@ -363,8 +356,9 @@ ' Equivalent to:', '', '', - ' copernicusmarine subset -i cmems_mod_ibi_phy_my_0.083deg-3D_P1D-m -v thetao -v so -t 2021-01-01 -T 2021-01-03 -x 0.0 -X 0.1 -y 28.0 -Y 28.1 -z 1 -Z 2', + ' copernicusmarine subset -i cmems_mod_ibi_phy_my_0.083deg-3D_P1D-m -v thetao -v so -t 2021-01-01 -T 2021-01-03 -x 0.0 -X 0.1 -y 28.0 -Y 28.1 -z 1 -Z 2 ', + '', ' ', - "', stderr=b'')", + '", stderr=b\'\')', ]) # --- diff --git a/tests/test_documentation.py b/tests/test_documentation.py new file mode 100644 index 00000000..27a4cb6e --- /dev/null +++ b/tests/test_documentation.py @@ -0,0 +1,137 @@ +from numpydoc.docscrape import FunctionDoc + +import copernicusmarine +from copernicusmarine.core_functions import documentation_utils + +LIST_OF_EXCEPTIONS = ["username", "password"] + + +class TestDocumentation: + def test_subset(self): + text_subset = FunctionDoc(copernicusmarine.subset) + + for i in range(len(text_subset["Parameters"])): + name_of_variable = text_subset["Parameters"][i].name + if name_of_variable in ["start_datetime", "end_datetime"]: + assert text_subset["Parameters"][i].desc == [ + documentation_utils.SUBSET[ + name_of_variable.upper() + "_HELP" + ] + ] + continue + if name_of_variable == "variables": + assert text_subset["Parameters"][i].desc == [ + "List of variable names to extract." + ] + continue + if name_of_variable == "netcdf_compression_level": + assert text_subset["Parameters"][i].desc == [ + documentation_utils.SUBSET[ + name_of_variable.upper() + "_HELP" + ] + ] + continue + if name_of_variable in LIST_OF_EXCEPTIONS: + continue + assert text_subset["Parameters"][i].desc == [ + documentation_utils.SUBSET[name_of_variable.upper() + "_HELP"] + ] + + def test_get(self): + text_get = FunctionDoc(copernicusmarine.get) + + for i in range(len(text_get["Parameters"])): + name_of_variable = text_get["Parameters"][i].name + if name_of_variable in LIST_OF_EXCEPTIONS: + continue + assert text_get["Parameters"][i].desc == [ + documentation_utils.GET[name_of_variable.upper() + "_HELP"] + ] + + def test_login(self): + text_login = FunctionDoc(copernicusmarine.login) + + for i in range(len(text_login["Parameters"])): + name_of_variable = text_login["Parameters"][i].name + if len(text_login["Parameters"][i].desc) > 1: + assert ( + " ".join(text_login["Parameters"][i].desc) + == documentation_utils.LOGIN[ + name_of_variable.upper() + "_HELP" + ] + ) + continue + if name_of_variable in LIST_OF_EXCEPTIONS: + continue + assert text_login["Parameters"][i].desc == [ + documentation_utils.LOGIN[name_of_variable.upper() + "_HELP"] + ] + + def test_describe(self): + text_describe = FunctionDoc(copernicusmarine.describe) + + for i in range(len(text_describe["Parameters"])): + name_of_variable = text_describe["Parameters"][i].name + assert text_describe["Parameters"][i].desc == [ + documentation_utils.DESCRIBE[ + name_of_variable.upper() + "_HELP" + ] + ] + + def test_open_dataset(self): + text_open_dataset = FunctionDoc(copernicusmarine.open_dataset) + + for i in range(len(text_open_dataset["Parameters"])): + name_of_variable = text_open_dataset["Parameters"][i].name + if name_of_variable in ["start_datetime", "end_datetime"]: + assert text_open_dataset["Parameters"][i].desc == [ + documentation_utils.SUBSET[ + name_of_variable.upper() + "_HELP" + ] + ] + continue + if name_of_variable == "variables": + assert text_open_dataset["Parameters"][i].desc == [ + "List of variable names to extract." + ] + continue + if name_of_variable == "dataset_id": + assert text_open_dataset["Parameters"][i].desc == [ + "The datasetID, required." + ] + continue + if name_of_variable in LIST_OF_EXCEPTIONS: + continue + assert text_open_dataset["Parameters"][i].desc == [ + documentation_utils.SUBSET[name_of_variable.upper() + "_HELP"] + ] + + def test_read_dataframe(self): + text_read_dataframe = FunctionDoc(copernicusmarine.read_dataframe) + + for i in range(len(text_read_dataframe["Parameters"])): + name_of_variable = text_read_dataframe["Parameters"][i].name + if name_of_variable in ["start_datetime", "end_datetime"]: + assert text_read_dataframe["Parameters"][i].desc == [ + documentation_utils.SUBSET[ + name_of_variable.upper() + "_HELP" + ] + ] + continue + if name_of_variable == "variables": + assert text_read_dataframe["Parameters"][i].desc == [ + "List of variable names to extract." + ] + continue + if name_of_variable == "dataset_id": + assert text_read_dataframe["Parameters"][i].desc == [ + "The datasetID, required." + ] + continue + if name_of_variable in LIST_OF_EXCEPTIONS: + continue + print(name_of_variable) + + assert text_read_dataframe["Parameters"][i].desc == [ + documentation_utils.SUBSET[name_of_variable.upper() + "_HELP"] + ] diff --git a/tests/test_get_create_file_list.py b/tests/test_get_create_file_list.py index 22c80d75..56bdbbbd 100644 --- a/tests/test_get_create_file_list.py +++ b/tests/test_get_create_file_list.py @@ -16,7 +16,7 @@ def test_get_create_file_list_without_extension_raises(self): ] self.output = execute_in_terminal(self.command) assert ( - b"Assertion error: Download file list must be a .txt or .csv file." + b"Assertion error: Download file list must be a '.txt' or '.csv' file." in self.output.stderr ) @@ -58,7 +58,10 @@ def test_get_create_file_list_without_extension_raises_python(self): create_file_list="hello", ) except AssertionError as e: - assert str(e) == "Download file list must be a .txt or .csv file. " + assert ( + str(e) + == "Download file list must be a '.txt' or '.csv' file. " + ) def test_get_create_file_list_python(self): get(