pax_global_header00006660000000000000000000000064147017627520014525gustar00rootroot0000000000000052 comment=de52006152c57e9868a52f401ea10feba122c6a9 CDSETool-0.2.13/000077500000000000000000000000001470176275200131645ustar00rootroot00000000000000CDSETool-0.2.13/.github/000077500000000000000000000000001470176275200145245ustar00rootroot00000000000000CDSETool-0.2.13/.github/ISSUE_TEMPLATE/000077500000000000000000000000001470176275200167075ustar00rootroot00000000000000CDSETool-0.2.13/.github/ISSUE_TEMPLATE/bug-report.md000066400000000000000000000012051470176275200213150ustar00rootroot00000000000000--- name: "Bug report \U0001F41E" about: Create a bug report labels: bug --- ## Describe the bug A clear and concise description of what the bug is. ### Steps to reproduce Code snippets and steps to reproduce the behavior. e.g. ```python from cdsetool.query import query_features query_features("InvalidCollection") ``` ### Expected behavior A clear and concise description of what you expected to happen. ### Environment - OS: [e.g. Arch Linux] - Package version: [e.g. cdsetool==X.Y.Z] - Python version: [e.g. 3.11.2] - Other details that you think may affect. ### Additional context Add any other context about the problem here. CDSETool-0.2.13/.github/ISSUE_TEMPLATE/feature-request.md000066400000000000000000000004431470176275200223530ustar00rootroot00000000000000--- name: "Feature request \U0001F680" about: Suggest an idea labels: enhancement --- ## Summary Brief explanation of the feature. ### Basic example Include a basic example or links here. ### Motivation Why are we doing this? What use cases does it support? What is the expected outcome?CDSETool-0.2.13/.github/dependabot.yml000066400000000000000000000010161470176275200173520ustar00rootroot00000000000000# To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" CDSETool-0.2.13/.github/workflows/000077500000000000000000000000001470176275200165615ustar00rootroot00000000000000CDSETool-0.2.13/.github/workflows/lint.yml000066400000000000000000000024031470176275200202510ustar00rootroot00000000000000name: Lint on: [push, pull_request] jobs: ruff: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: chartboost/ruff-action@v1 with: args: 'format --check --diff' pylint: runs-on: ubuntu-latest strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install .[test] - name: Analysing the code with pylint run: | pylint $(git ls-files 'src/*.py') pyright: runs-on: ubuntu-latest strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e .[test] - uses: jakebailey/pyright-action@v2 CDSETool-0.2.13/.github/workflows/publish.yml000066400000000000000000000020741470176275200207550ustar00rootroot00000000000000# This workflow will upload a Python Package using Twine when a release is created # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. name: Upload Python Package on: release: types: [published] permissions: contents: read jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x' - name: Install dependencies run: | python -m pip install --upgrade pip pip install build - name: Build package run: python -m build - name: Publish package uses: pypa/gh-action-pypi-publish@f7600683efdcb7656dec5b29656edb7bc586e597 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} CDSETool-0.2.13/.github/workflows/pytest.yml000066400000000000000000000015731470176275200206420ustar00rootroot00000000000000name: Pytest on: push: branches: [ "main" ] pull_request: branches: [ "main" ] permissions: contents: read jobs: pytest: runs-on: ubuntu-latest strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] permissions: pull-requests: write contents: write steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip pip install -e .[test] - name: Test with pytest run: | pytest --cov=cdsetool --cov-report xml # - name: Python Coverage # uses: orgoro/coverage@v3.1 # with: # coverageFile: coverage.xml # token: ${{ secrets.GITHUB_TOKEN }} CDSETool-0.2.13/.gitignore000066400000000000000000000060661470176275200151640ustar00rootroot00000000000000.DS_Store .coverage environment main.py # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/#use-with-ide .pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. .idea/ .vscode/ CDSETool-0.2.13/LICENSE000066400000000000000000000021151470176275200141700ustar00rootroot00000000000000MIT License Copyright (c) 2023 Styrelsen for Dataforsyning og Infrastruktur Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CDSETool-0.2.13/README.md000066400000000000000000000205211470176275200144430ustar00rootroot00000000000000# CDSETool ## About CDSETool This script downloads copernicus data from the Copernicus Data Space Ecosystem ## Quick start ```python from cdsetool.query import query_features, shape_to_wkt from cdsetool.credentials import Credentials from cdsetool.download import download_features from cdsetool.monitor import StatusMonitor from datetime import date features = query_features( "Sentinel1", { "startDate": "2020-12-20", "completionDate": date(2020, 12, 25), "processingLevel": "LEVEL1", "sensorMode": "IW", "productType": "IW_GRDH_1S", "geometry": shape_to_wkt("path/to/shapefile.shp"), }, ) list( download_features( features, "path/to/output/folder/", { "concurrency": 4, "monitor": StatusMonitor(), "credentials": Credentials("username", "password"), }, ) ) ``` Or use the CLI: ```bash cdsetool query search Sentinel2 --search-term startDate=2020-01-01 --search-term completionDate=2020-01-10 --search-term processingLevel=S2MSI2A --search-term box="4","51","4.5","52" cdsetool download Sentinel2 PATH/TO/DIR --concurrency 4 --search-term startDate=2020-01-01 --search-term completionDate=2020-01-10 --search-term processingLevel=S2MSI2A --search-term box="4","51","4.5","52" ``` ## Table of Contents - [CDSETool](#cdsetool) * [About CDSETool](#about-cdsetool) * [Quick Start](#quick-start) * [Table of Contents](#table-of-contents) * [Installatson](#installation) * [Usage](#usage) + [Querying features](#querying-features) - [Querying by shapes](#querying-by-shapes) - [Querying by lists of parameters](#querying-by-lists-of-parameters) - [Querying by dates](#querying-by-dates) - [Listing search terms](#listing-search-terms) + [Downloading features](#downloading-features) - [Authenticating](#authenticating) - [Concurrently downloading features](#concurrently-downloading-features) - [Sequentially downloading features](#sequentially-downloading-features) * [Roadmap](#roadmap) * [Contributing](#contributing) * [LICENSE](#license) ## Installation Install `cdsetool` using pip: ```bash pip install cdsetool==0.2.13 ``` ## Usage ### Querying features Querying is always done in batches, returning `len(results) <= maxRecords` records each time. A local buffer is filled and gradually emptied as results are yielded. When the buffer is empty, more results will be requested and the process repeated until no more results are available, or the iterator is discarded. Since downloading features is the most common use-case, `query_features` assumes that the query will run till the end. Because of this, the batch size is set to `2000`, which is the size limit set by CDSE. ```python from cdsetool.query import query_features collection = "Sentinel2" search_terms = { "maxRecords": "100", # batch size, between 1 and 2000 (default: 2000). "startDate": "1999-01-01", "processingLevel": "S2MSI1C" } # wait for a single batch to finish, yield results immediately for feature in query_features(collection, search_terms): # do something with feature # wait for all batch requests to complete, returning list features = list(query_features(collection, search_terms)) # manually iterate iterator = query_features(collection, search_terms) featureA = next(iterator) featureB = next(iterator) # ... ``` #### Querying by shapes To query by shapes, you must first convert your shape to Well Known Text (WKT). The included `shape_to_wkt` can solve this. ```python from cdsetool.query import query_features, shape_to_wkt geometry = shape_to_wkt("path/to/shape.shp") features = query_features("Sentinel3", {"geometry": geometry}) ``` #### Querying by lists of parameters Most search terms only accept a single argument. To query by a list of arguments, loop the arguments and pass them one by one to the query function. ```python from cdsetool.query import query_features tile_ids = ["32TPT", "32UPU", "32UPU", "31RFL", "37XDA"] for tile_id in tile_ids: features = query_features("Sentinel2", {"tileId": tile_id}) for feature in features: # do things with feature ``` #### Querying by dates Its quite common to query for features created before, after or between dates. ```python from cdsetool.query import query_features from datetime import date, datetime date_from = date(2020, 1, 1) # or datetime(2020, 1, 1, 23, 59, 59, 123456) or "2020-01-01" or "2020-01-01T23:59:59.123456Z" date_to = date(2020, 12, 31) features = query_features("Sentinel2", {"startDate": date_from, "completionDate": date_to}) ``` #### Listing search terms To get a list of all search terms for a given collection, you may either use the `describe_collection` function or use the CLI: ```python from cdsetool.query import describe_collection search_terms = describe_collection("Sentinel2").keys() print(search_terms) ``` And the CLI: ```bash $ cdsetool query search-terms Sentinel2 ``` ### Downloading features #### Authenticating An account is required to download features from the Copernicus distribution service. To authenticate using an account, instantiate `Credentials` and pass your username and password ```python from cdsetool.credentials import Credentials username = "konata@izumi.com" password = "password123" credentials = Credentials(username, password) ``` Alternatively, `Credentials` can pull from `~/.netrc` when username and password are left blank. ```python # ~/.netrc machine https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token login konata@izumi.com password password123 # main.py from cdsetool.credentials import Credentials credentials = Credentials() ``` The credentials object may then be passed to a download function. If left out, the download functions will default to using `.netrc`. ```python credentials = Credentials() download_features(features, "/some/download/path", {"credentials": credentials}) ``` Credentials can be validated using the `validate_credentials` function which will return a boolean. ```python from cdsetool.credentials import validate_credentials validate_credentials(username='user', password='password') ``` If None are passed to username and password, `validate_credentials` will validate `.netrc` #### Concurrently downloading features CDSETool provides a method for concurrently downloading features. The concurrency level should match your accounts privileges. See [CDSE quotas](https://documentation.dataspace.copernicus.eu/Quotas.html) The downloaded feature ids are yielded, so its required to await the results. ```python from cdsetool.query import query_features from cdsetool.download import download_features features = query_features("Sentinel2") download_path = "/path/to/download/folder" downloads = download_features(features, download_path, {"concurrency": 4}) for id in downloads: print(f"feature {id} downloaded") # or list(downloads) ``` #### Sequentially downloading features Its possible to download features sequentially in a single thread if desired. ```python from cdsetool.query import query_features from cdsetool.download import download_feature features = query_features("Sentinel2") download_path = "/path/to/download/folder" for feature in features: download_feature(feature, download_path) ``` ## Roadmap - [X] Query schema validation - [ ] High-level API - [ ] Query features - [ ] Download features - [ ] Download single feature - [ ] Download list of features - [ ] Download by ID - [ ] Download by URL - [ ] Command-Line Interface - [ ] Update to match the high-level API - [ ] Better `--help` messages - [ ] Quickstart guide in README.md - [ ] Test suite - [ ] Query - [ ] Credentials - [ ] Download - [ ] Monitor - [ ] Strategy for handling HTTP and connection errors ## Contributing Any contributions you make are **greatly appreciated**. If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". 1. Fork the Project 2. Create your Feature Branch (`git checkout -b feature/cool-new-feature`) 3. Commit your Changes (`git commit -m 'Add some feature'`) 4. Push to the Branch (`git push origin feature/cool-new-feature`) 5. Open a Pull Request ## LICENSE Distributed under the MIT License. See [LICENSE](LICENSE) for more information. CDSETool-0.2.13/pyproject.toml000066400000000000000000000025511470176275200161030ustar00rootroot00000000000000[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "cdsetool" version = "0.2.13" authors = [ { name="Jacob Vejby", email="javej@sdfi.dk" }, ] description = "Tools & CLI for interacting with CDSE product APIs" readme = "README.md" requires-python = ">=3.9" classifiers = [ "Programming Language :: Python :: 3", "Operating System :: OS Independent", ] dependencies = [ "typer >= 0.9,< 1", "rich >= 13.6,< 14", "requests >= 2.28.1,< 3", "pyjwt[crypto] >= 2.8,< 2.10", "geopandas >= 0.13.2", ] [project.optional-dependencies] test = [ "pylint==3.3.1", "pytest==8.3.3", "pytest-cov==5.0.0", "requests-mock==1.12.1", "ruff==0.6.6", "pytest-mock==3.14.0", ] [project.urls] "Homepage" = "https://github.com/CDSETool/CDSETool" "Bug Tracker" = "https://github.com/CDSETool/CDSETool/issues" [project.scripts] cdsetool = "cdsetool:cli.main" [tool.pylint.design] max-locals = 20 [tool.pylint.format] max-line-length = "88" disable="fixme" [tool.pyright] exclude = ["**/__pycache__", ".venv"] # Can be strict too, see more fine-grained settings at: # https://github.com/microsoft/pyright/blob/main/docs/configuration.md#diagnostic-settings-defaults typeCheckingMode = "standard" executionEnvironments = [ { root = "./" } ] [tool.pytest.ini_options] addopts = [ "--import-mode=importlib", ] CDSETool-0.2.13/src/000077500000000000000000000000001470176275200137535ustar00rootroot00000000000000CDSETool-0.2.13/src/cdsetool/000077500000000000000000000000001470176275200155675ustar00rootroot00000000000000CDSETool-0.2.13/src/cdsetool/__init__.py000066400000000000000000000000001470176275200176660ustar00rootroot00000000000000CDSETool-0.2.13/src/cdsetool/_processing.py000066400000000000000000000043101470176275200204520ustar00rootroot00000000000000""" This module provides functions for processing data concurrently """ from concurrent.futures import Future, wait, FIRST_COMPLETED from concurrent.futures import ThreadPoolExecutor from typing import Callable, Generator, Iterable, List, Union from cdsetool.query import FeatureQuery def _concurrent_process( fun: Callable[[FeatureQuery], Union[str, None]], iterable: Iterable, workers: int = 4, ) -> Generator[Union[str, None], None, None]: """ Process items in an iterable concurrently Items are taken from the iterable as soon as a worker becomes available Returns an iterable of the results """ # Futures are submitted in batches instead of all at once to avoid # requesting too many items from the iterable at once, which is important if # the iterable is a generator that is producing items on the fly. # # The 1.5 factor is a small overhead to keep jobs > workers at all times, instead # of jobs == workers, which could cause the workers to be idle while waiting for # the iterable to produce more items. low_water_mark = int(workers * 1.5) iterator = iter(iterable) with ThreadPoolExecutor(max_workers=workers) as executor: futures: List[Future[Union[str, None]]] = [] # pylint: disable=E1136 # Pluck an item from the iterable and submit it to the executor. # If the iterable is exhausted, this function is a no-op. def submit_item() -> None: item = next(iterator, None) if item is not None: futures.append(executor.submit(fun, item)) # Fill the futures list up to the low water mark def fill_futures() -> None: for _ in range(low_water_mark - len(futures)): submit_item() # Submit the first batch of items fill_futures() # Continue until no more futures are queued while futures: # Wait for the first future(s) to complete done, not_done = wait(futures, return_when=FIRST_COMPLETED) futures = list(not_done) for future in done: yield future.result() # Submit items to replace the ones that are done. fill_futures() CDSETool-0.2.13/src/cdsetool/cli.py000066400000000000000000000064111470176275200167120ustar00rootroot00000000000000""" Command line interface """ import os import sys import json as JSON from typing import Dict, List, Optional from typing_extensions import Annotated import typer from cdsetool.query import describe_collection, query_features from cdsetool.monitor import StatusMonitor from cdsetool.download import download_features app = typer.Typer(no_args_is_help=True) query_app = typer.Typer(no_args_is_help=True) app.add_typer(query_app, name="query") @query_app.command("search-terms") def query_search_terms(collection: str) -> None: """ List the available search terms for a collection """ print(f"Available search terms for collection {collection}:") # TODO: print validators for key, attributes in describe_collection(collection).items(): print(f" - {key}") if attributes.get("title"): print(f" - Description: {attributes.get('title')}") if attributes.get("pattern"): print(f" - Pattern: {attributes.get('pattern')}") if attributes.get("minInclusive"): print(f" - Min: {attributes.get('minInclusive')}") if attributes.get("maxInclusive"): print(f" - Max: {attributes.get('maxInclusive')}") print() # TODO: implement limit @query_app.command("search") def query_search( collection: str, search_term: Annotated[ Optional[List[str]], typer.Option( help="Search by term=value pairs. " + "Pass multiple times for multiple search terms" ), ] = None, json: Annotated[bool, typer.Option(help="Output JSON")] = False, ) -> None: """ Search for features matching the search terms """ search_term = search_term or [] features = query_features(collection, _to_dict(search_term)) for feature in features: if json: print(JSON.dumps(feature)) else: print(feature.get("properties").get("title")) # TODO: implement limit @app.command("download") def download( collection: str, path: str, concurrency: Annotated[ int, typer.Option(help="Number of concurrent connections") ] = 1, overwrite_existing: Annotated[ bool, typer.Option(help="Overwrite already downloaded files") ] = False, search_term: Annotated[ Optional[List[str]], typer.Option( help="Search by term=value pairs. " + "Pass multiple times for multiple search terms" ), ] = None, ) -> None: """ Download all features matching the search terms """ if not os.path.exists(path): print(f"Path {path} does not exist") sys.exit(1) search_term = search_term or [] features = query_features(collection, _to_dict(search_term)) list( download_features( features, path, { "monitor": StatusMonitor(), "concurrency": concurrency, "overwrite_existing": overwrite_existing, }, ) ) def main(): """ Main entry point """ app() def _to_dict(term_list: List[str]) -> Dict[str, str]: search_terms = {} for item in term_list: key, value = item.split("=") search_terms[key] = value return search_terms if __name__ == "__main__": main() CDSETool-0.2.13/src/cdsetool/credentials.py000066400000000000000000000215101470176275200204350ustar00rootroot00000000000000""" This module provides a class for handling credentials for the Copernicus Identity and Access Management (IAM) system. """ from datetime import datetime, timedelta import netrc import threading from typing import Any, Dict, List, Union import requests import jwt from requests.adapters import HTTPAdapter from urllib3.util import Retry class NoCredentialsException(Exception): """ Raised when no credentials are found """ class InvalidCredentialsException(Exception): """ Raised when credentials are invalid """ class DeprecatedNoTokenException(Exception): """ Deprecated """ def NoTokenException(*args, **kwargs): # pylint: disable=invalid-name """ Raised when no token is available """ from warnings import warn # pylint: disable=import-outside-toplevel error_msg = [ "Warning! NoTokenException is deprecated, and will be removed in" "the next major release." ] warn(" ".join(error_msg)) return DeprecatedNoTokenException(*args, **kwargs) class TokenExchangeException(Exception): """ Raised when token exchange fails """ class TokenClientConnectionError(Exception): """ Raised when token connection fails. """ class TokenExpiredSignatureError(Exception): """ Raised when token signature has expired. """ class Credentials: # pylint: disable=too-few-public-methods disable=too-many-instance-attributes """ A class for handling credentials for the Copernicus Identity and Access Management (IAM) system """ RETRY_CODES = frozenset([413, 429, 500, 502, 503]) RETRIES = Retry( total=5, backoff_factor=0.5, raise_on_status=False, status_forcelist=RETRY_CODES, ) def __init__( self, username: Union[str, None] = None, password: Union[str, None] = None, openid_configuration_endpoint: Union[str, None] = None, proxies: Union[Dict[str, str], None] = None, ) -> None: self.__username: Union[str, None] = username self.__password: Union[str, None] = password self.__proxies: Union[Dict[str, str], None] = proxies self.__openid_conf = None self.__jwks = None self.__openid_configuration_endpoint: str = ( openid_configuration_endpoint or "https://identity.dataspace.copernicus.eu" + "/auth/realms/CDSE/.well-known/openid-configuration" ) self.__access_token: Union[str, None] = None self.__refresh_token: Union[str, None] = None self.__access_token_expires: datetime = datetime.now() - timedelta(hours=8) self.__refresh_token_expires: datetime = self.__access_token_expires self.__lock = threading.Lock() if self.__username is None or self.__password is None: self.__read_credentials() self.__ensure_tokens() def get_session(self) -> requests.Session: """ Returns a session with the credentials set as the Authorization header """ return self.make_session(self, True, self.RETRIES, self.__proxies) @staticmethod def make_session( caller, authorization: bool, max_retries: Retry, proxies: Union[Dict[str, str], None], ) -> requests.Session: """ Creates a new session. Authorization is only available from callers that are subclasses of Credentials. """ if authorization: caller.__ensure_tokens() # pylint: disable=protected-access session = requests.Session() session.mount("http://", HTTPAdapter(max_retries=max_retries)) session.mount("https://", HTTPAdapter(max_retries=max_retries)) if proxies is not None: session.proxies.update(proxies) if authorization: token = caller.__access_token # pylint: disable=protected-access session.headers.update({"Authorization": f"Bearer {token}"}) return session def __token_exchange(self, data: Dict[str, str]) -> timedelta: # Make a session that will retry post, respecting the retry-after # header when we get a 503 and a few other temporary failures. session = self.make_session( caller=self, authorization=False, max_retries=Retry( total=15, backoff_factor=0.5, allowed_methods=None, raise_on_status=False, status_forcelist=self.RETRY_CODES, ), proxies=self.__proxies, ) response = session.post(self.__token_endpoint, data=data, timeout=120) if response.status_code == 401: raise InvalidCredentialsException( "Unable to exchange token with " + f"username: {self.__username} and " + f"password: {len(self.__password or '') * '*'}" ) if response.status_code != 200: raise TokenExchangeException(f"Token exchange failed: {response.text}") response = response.json() self.__access_token = response["access_token"] self.__refresh_token = response["refresh_token"] return timedelta(seconds=response["refresh_expires_in"]) def __ensure_tokens(self) -> None: with self.__lock: refresh_expire_delta = None if self.__access_token_expires < datetime.now(): if self.__refresh_token_expires < datetime.now(): data = { "grant_type": "password", "username": self.__username, "password": self.__password, "client_id": "cdse-public", } else: data = { "grant_type": "refresh_token", "refresh_token": self.__refresh_token, "client_id": "cdse-public", } refresh_expire_delta = self.__token_exchange(data) if not self.__access_token: raise InvalidCredentialsException( "Internal error: access token not available" ) try: key = self.__jwk_client.get_signing_key_from_jwt(self.__access_token) except jwt.PyJWKClientConnectionError as e: raise TokenClientConnectionError from e try: data = jwt.decode( self.__access_token, key=key.key, algorithms=self.__id_token_signing_algos, # pylint: disable=protected-access options={"verify_aud": False}, ) except jwt.ExpiredSignatureError as e: raise TokenExpiredSignatureError from e if refresh_expire_delta is not None: self.__access_token_expires = datetime.fromtimestamp(data["exp"]) self.__refresh_token_expires = ( datetime.fromtimestamp(data["iat"]) + refresh_expire_delta ) def __read_credentials(self) -> None: rv = netrc.netrc().authenticators(self.__token_endpoint) if isinstance(rv, tuple): self.__username, _, self.__password = rv else: raise NoCredentialsException("No credentials found") @property def __openid_configuration(self) -> Dict[str, Any]: if self.__openid_conf: return self.__openid_conf session = self.make_session( caller=self, authorization=False, max_retries=self.RETRIES, proxies=self.__proxies, ) response = session.get(self.__openid_configuration_endpoint, timeout=120) response.raise_for_status() self.__openid_conf = response.json() return self.__openid_conf @property def __token_endpoint(self) -> str: return self.__openid_configuration["token_endpoint"] @property def __jwks_uri(self) -> str: return self.__openid_configuration["jwks_uri"] @property def __id_token_signing_algos(self) -> List[str]: return self.__openid_configuration["id_token_signing_alg_values_supported"] @property def __jwk_client(self) -> jwt.PyJWKClient: if self.__jwks: return self.__jwks self.__jwks = jwt.PyJWKClient(self.__jwks_uri) return self.__jwks def validate_credentials( username: Union[str, None] = None, password: Union[str, None] = None ) -> bool: """ This function validates CDSE credentials and returns a bool. If credentials are none, .netrc will be validated """ try: Credentials(username, password) return True except NoCredentialsException: return False except InvalidCredentialsException: return False except TokenExchangeException: return False CDSETool-0.2.13/src/cdsetool/download.py000066400000000000000000000124021470176275200177470ustar00rootroot00000000000000""" Download features from a Copernicus Data Space Ecosystem OpenSearch API result Provides a function to download a single feature, and a function to download all features in a result set. """ import os import random import tempfile import time import shutil from typing import Any, Dict, Generator, Union from requests import Session from requests.exceptions import ChunkedEncodingError from urllib3.exceptions import ProtocolError from cdsetool._processing import _concurrent_process from cdsetool.credentials import ( Credentials, TokenClientConnectionError, TokenExpiredSignatureError, ) from cdsetool.logger import NoopLogger from cdsetool.monitor import NoopMonitor, StatusMonitor from cdsetool.query import FeatureQuery def download_feature( feature, path: str, options: Union[Dict[str, Any], None] = None ) -> Union[str, None]: """ Download a single feature Returns the feature ID """ options = options or {} log = _get_logger(options) url = _get_feature_url(feature) title = feature.get("properties").get("title") temp_dir_usr = _get_temp_dir(options) if not url or not title: log.debug(f"Bad URL ('{url}') or title ('{title}')") return None filename = title + ".zip" result_path = os.path.join(path, filename) if not options.get("overwrite_existing", False) and os.path.exists(result_path): log.debug(f"File {result_path} already exists, skipping..") return filename with _get_monitor(options).status() as status: status.set_filename(filename) attempts = 0 while attempts < 10: attempts += 1 # Always get a new session, credentials might have expired. try: session = _get_credentials(options).get_session() except TokenClientConnectionError: log.warning("Token client connection failed, retrying..") continue except TokenExpiredSignatureError: log.warning("Token signature expired, retrying..") continue url = _follow_redirect(url, session) name_dir_prefix = filename.replace(".zip", "____") with ( session.get(url, stream=True) as response, tempfile.TemporaryDirectory( prefix=name_dir_prefix, dir=temp_dir_usr ) as temp_dir, ): if response.status_code != 200: log.warning(f"Status code {response.status_code}, retrying..") time.sleep(60 * (1 + (random.random() / 4))) continue status.set_filesize(int(response.headers["Content-Length"])) tmp_file = os.path.join(temp_dir, "download.zip") with open(tmp_file, "wb") as file: # Server might not send all bytes specified by the # Content-Length header before closing connection. # Log as a warning and try again. try: for chunk in response.iter_content(chunk_size=1024 * 1024 * 5): file.write(chunk) status.add_progress(len(chunk)) except ( ChunkedEncodingError, ConnectionResetError, ProtocolError, ) as e: log.warning(e) continue # Close file before copy so all buffers are flushed. shutil.copy(tmp_file, result_path) return filename log.error(f"Failed to download {filename}") return None def download_features( features: FeatureQuery, path: str, options: Union[Dict[str, Any], None] = None ) -> Generator[Union[str, None], None, None]: """ Generator function that downloads all features in a result set Feature IDs are yielded as they are downloaded """ options = options or {} options["credentials"] = _get_credentials(options) options["logger"] = _get_logger(options) options["monitor"] = _get_monitor(options) options["monitor"].start() def _download_feature(feature) -> Union[str, None]: return download_feature(feature, path, options) yield from _concurrent_process( _download_feature, features, options.get("concurrency", 1) ) options["monitor"].stop() def _get_feature_url(feature) -> str: return feature.get("properties").get("services").get("download").get("url") def _follow_redirect(url: str, session: Session) -> str: response = session.head(url, allow_redirects=False) while response.status_code in range(300, 400): url = response.headers["Location"] response = session.head(url, allow_redirects=False) return url def _get_logger(options: Dict) -> NoopLogger: return options.get("logger") or NoopLogger() def _get_monitor(options: Dict) -> Union[StatusMonitor, NoopMonitor]: return options.get("monitor") or NoopMonitor() def _get_credentials(options: Dict) -> Credentials: return options.get("credentials") or Credentials( proxies=options.get("proxies", None) ) def _get_temp_dir(options: Dict) -> Union[str, None]: return options.get("tmpdir") or None CDSETool-0.2.13/src/cdsetool/logger.py000066400000000000000000000010461470176275200174210ustar00rootroot00000000000000""" Logging utilities. This module provides a NoopLogger class that outputs nothing. """ class NoopLogger: """ A logger that does nothing. """ def debug(self, msg, *args, **kwargs): """ Log a debug message. """ def error(self, msg, *args, **kwargs): """ Log an error message. """ def info(self, msg, *args, **kwargs): """ Log an info message. """ def warning(self, msg, *args, **kwargs): """ Log a warning message. """ CDSETool-0.2.13/src/cdsetool/monitor.py000066400000000000000000000173251470176275200176400ustar00rootroot00000000000000""" File download monitoring. This module provides a StatusMonitor class that can be used to monitor the progress of file downloads. For non-interactive programs the NoopMonitor class can be used to disable status monitoring. """ import time import threading import sys import os import signal import shutil from typing import List, Tuple, Union IS_IPYTHON = True try: from IPython import get_ipython # type:ignore[reportMissingImports] from IPython.display import clear_output # type:ignore[reportMissingImports] if "IPKernelApp" not in get_ipython().config: IS_IPYTHON = False except ImportError: IS_IPYTHON = False except AttributeError: IS_IPYTHON = False class StatusMonitor(threading.Thread): """ A monitor that prints a status bar for each download Usage: with StatusMonitor() as monitor: with monitor.status() as status: status.set_filename("filename.txt") status.set_filesize(1024) status.add_progress(512) time.sleep(10) status.add_progress(512) """ line_length: int = 80 __is_running: bool = True __progress_lines: int = 0 __download_speed_deltas: List[int] = [] __done = [] __status = [] def start(self) -> None: """ Start the monitor """ def _set_line_length(_signal_num, _stack): self.line_length, _ = shutil.get_terminal_size() _set_line_length(None, None) if os.name != "nt": signal.signal(signal.SIGWINCH, _set_line_length) super().start() def stop(self) -> None: """ Stop the monitor """ self.__is_running = False def status(self) -> "Status": """ Returns a status bar for a single download """ status = Status(self) self.__status.append(status) return status def remove_status(self, status: "Status") -> None: """ Remove a status from the monitor, marking it as done """ self.__done.append(status) self.__status.remove(status) def run(self) -> None: """ Main loop for the monitor, printing the status bars every second until stopped """ while True: self.__track_download_speed() if self.__is_running is False: break self.__clear_progress_lines() self.__print_done_lines() self.__draw() print("") @property def __download_speed(self) -> float: if len(self.__download_speed_deltas) < 2: return 0 return sum(self.__download_speed_deltas) / len(self.__download_speed_deltas) def __track_download_speed(self) -> None: speed_t0 = self.__total_downloaded time.sleep(1) speed_t1 = self.__total_downloaded self.__download_speed_deltas.append(speed_t1 - speed_t0) if len(self.__download_speed_deltas) > 10: self.__download_speed_deltas.pop(0) def __print_done_lines(self) -> None: for status in self.__done: print(status.done_line()) def __clear_progress_lines(self) -> None: if IS_IPYTHON: clear_output(wait=True) # type:ignore[reportPossiblyUnboundVariable] return sys.stdout.write("\033[K") for _ in range(self.__progress_lines + 2): sys.stdout.write("\033[F\033[K") for _ in self.__done: sys.stdout.write("\033[F\033[K") print("") print("") def __draw(self) -> None: self.__progress_lines = 1 print( " | ".join( [ "[[ ", f"{len(self.__status)} files in progress", f"{len(self.__done)} files done", f"{bytes_to_human(self.__total_downloaded)} total downloaded", f"{bytes_to_human(int(self.__download_speed))}/s ]]", ] ) ) for status in self.__status: filename_line, progress_line = status.status_lines() print(filename_line.ljust(self.line_length, " ")) print(progress_line.ljust(self.line_length, " ")) self.__progress_lines += 2 @property def __total_downloaded(self) -> int: return sum(status.downloaded for status in self.__status) + sum( status.size for status in self.__done ) def __enter__(self): self.start() return self def __exit__(self, exc_type, exc_val, exc_tb): self.stop() class NoopMonitor: """ A monitor that does nothing """ def status(self) -> "Status": """ Returns a status bar for a single download """ return Status(self) def remove_status(self, status) -> None: """ Remove a status from the monitor """ def start(self) -> None: """ Start the monitor """ def stop(self) -> None: """ Stop the monitor """ def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): pass class Status: """ A status bar for a single download """ __monitor: Union[NoopMonitor, StatusMonitor, None] = None filename: Union[str, None] = None size: int = 0 downloaded: int = 0 def done_line(self) -> str: """ Returns a line to print when the download is complete """ if self.size == 0 and self.downloaded == 0: return f"{self.filename} skipped" return f"{self.filename} ({bytes_to_human(self.size)})" def status_lines(self) -> Tuple[str, str]: """ Returns a tuple of lines to print for the status bar """ if ( not self.__monitor or isinstance(self.__monitor, NoopMonitor) or not self.filename ): return ("", "") line_length = self.__monitor.line_length if self.downloaded == 0: return ( "Thread waiting for connection to start...", f"[{' ' * (line_length - 2)}]", ) progress = self.downloaded / self.size filename_line = ( f"{self.filename[0:line_length - 6]} " + f"{bytes_to_human(self.size)} ({int(progress * 100)}%)" ) progress_line = ( "[" + f"{'â–ˆ' * int(progress * (line_length - 2))}" + f"{' ' * (line_length - int(progress * (line_length - 2)) - 2)}" + "]" ) return filename_line, progress_line def add_progress(self, chunk_bytes) -> None: """ Add to the number of bytes downloaded """ self.downloaded += chunk_bytes def set_filename(self, filename: str) -> None: """ Set the name of the file being downloaded """ self.filename = filename def set_filesize(self, size: int) -> None: """ Set the size of the file being downloaded """ self.size = size def __init__(self, monitor) -> None: self.__monitor = monitor def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb) -> None: if self.__monitor: self.__monitor.remove_status(self) def bytes_to_human(num_bytes: int) -> str: """ Convert a number of bytes to a human-readable string """ if num_bytes < 1000: return f"{num_bytes} B" if num_bytes < 1000000: return f"{num_bytes / 1000:.2f} KB" if num_bytes < 1000000000: return f"{num_bytes / 1000000:.2f} MB" if num_bytes < 1000000000000: return f"{num_bytes / 1000000000:.2f} GB" return f"{num_bytes / 1000000000000:.2f} TB" CDSETool-0.2.13/src/cdsetool/py.typed000066400000000000000000000000001470176275200172540ustar00rootroot00000000000000CDSETool-0.2.13/src/cdsetool/query.py000066400000000000000000000220431470176275200173070ustar00rootroot00000000000000""" Query the Copernicus Data Space Ecosystem OpenSearch API https://documentation.dataspace.copernicus.eu/APIs/OpenSearch.html """ from typing import Any, Dict, Union from xml.etree import ElementTree from datetime import datetime, date import re import json from random import random from time import sleep import geopandas as gpd from requests.exceptions import ChunkedEncodingError from urllib3.exceptions import ProtocolError from cdsetool.credentials import Credentials from cdsetool.logger import NoopLogger class _FeatureIterator: def __init__(self, feature_query) -> None: self.index = 0 self.feature_query = feature_query def __len__(self) -> int: return len(self.feature_query) def __iter__(self): return self def __next__(self): try: item = self.feature_query[self.index] self.index += 1 return item except IndexError as exc: raise StopIteration from exc class FeatureQuery: """ An iterator over the features matching the search terms Queries the API in batches (default: 50) features, and returns them one by one. Queries the next batch when the current batch is exhausted. """ total_results: int = -1 def __init__( self, collection: str, search_terms: Dict[str, Any], proxies: Union[Dict[str, str], None] = None, options: Union[Dict[str, Any], None] = None, ) -> None: self.features = [] self.proxies = proxies self.log = (options or {}).get("logger") or NoopLogger() self.next_url = _query_url( collection, {**search_terms, "exactCount": "1"}, proxies=proxies ) def __iter__(self): return _FeatureIterator(self) def __len__(self) -> int: if self.total_results < 0: self.__fetch_features() return self.total_results def __getitem__(self, index): while index >= len(self.features) and self.next_url is not None: self.__fetch_features() return self.features[index] def __fetch_features(self) -> None: if self.next_url is None: return session = Credentials.make_session( None, False, Credentials.RETRIES, self.proxies ) attempts = 0 while attempts < 10: attempts += 1 try: with session.get(self.next_url) as response: if response.status_code != 200: self.log.warning( f"Status code {response.status_code}, retrying.." ) sleep(60 * (1 + (random() / 4))) continue res = response.json() self.features += res.get("features") or [] total_results = res.get("properties", {}).get("totalResults") if total_results is not None: self.total_results = total_results self.__set_next_url(res) return except (ChunkedEncodingError, ConnectionResetError, ProtocolError) as e: self.log.warning(e) continue def __set_next_url(self, res) -> None: links = res.get("properties", {}).get("links") or [] self.next_url = next( (link for link in links if link.get("rel") == "next"), {} ).get("href") if self.next_url: self.next_url = self.next_url.replace("exactCount=1", "exactCount=0") def query_features( collection: str, search_terms: Dict[str, Any], proxies: Union[Dict[str, str], None] = None, options: Union[Dict[str, Any], None] = None, ) -> FeatureQuery: """ Returns an iterator over the features matching the search terms """ return FeatureQuery( collection, {"maxRecords": 2000, **search_terms}, proxies, options ) def shape_to_wkt(shape: str) -> str: """ Convert a shapefile to a WKT string """ coordinates = list(gpd.read_file(shape).geometry[0].exterior.coords) return ( "POLYGON((" + ", ".join(" ".join(map(str, coord)) for coord in coordinates) + "))" ) def geojson_to_wkt(geojson_in: Union[str, Dict]) -> str: """ Convert a geojson geometry to a WKT string """ geojson = json.loads(geojson_in) if isinstance(geojson_in, str) else geojson_in if geojson.get("type") == "Feature": geojson = geojson["geometry"] elif geojson.get("type") == "FeatureCollection" and len(geojson["features"]) == 1: geojson = geojson["features"][0]["geometry"] coordinates = str( tuple(item for sublist in geojson["coordinates"][0] for item in sublist) ) paired_coord = ",".join( [ f"{a}{b}" for a, b in zip(coordinates.split(",")[0::2], coordinates.split(",")[1::2]) ] ) return f"POLYGON({paired_coord})" def describe_collection( collection: str, proxies: Union[Dict[str, str], None] = None ) -> Dict[str, Any]: """ Get a list of valid options for a given collection in key value pairs """ content = _get_describe_doc(collection, proxies=proxies) tree = ElementTree.fromstring(content) parameter_node_parent = tree.find( "{http://a9.com/-/spec/opensearch/1.1/}Url[@type='application/json']" ) parameters = {} if parameter_node_parent is None: return parameters for parameter_node in parameter_node_parent: name = parameter_node.attrib.get("name") pattern = parameter_node.attrib.get("pattern") min_inclusive = parameter_node.attrib.get("minInclusive") max_inclusive = parameter_node.attrib.get("maxInclusive") title = parameter_node.attrib.get("title") if name: parameters[name] = { "pattern": pattern, "minInclusive": min_inclusive, "maxInclusive": max_inclusive, "title": title, } return parameters def _query_url( collection: str, search_terms: Dict[str, Any], proxies: Union[Dict[str, str], None] = None, ) -> str: description = describe_collection(collection, proxies=proxies) query_list = [] for key, value in search_terms.items(): val = _serialize_search_term(value) _validate_search_term(key, val, description) query_list.append(f"{key}={val}") return ( "https://catalogue.dataspace.copernicus.eu" + f"/resto/api/collections/{collection}/search.json?{'&'.join(query_list)}" ) def _serialize_search_term(search_term: Any) -> str: if isinstance(search_term, list): return ",".join(search_term) if isinstance(search_term, datetime): return search_term.strftime("%Y-%m-%dT%H:%M:%SZ") if isinstance(search_term, date): return search_term.strftime("%Y-%m-%d") return str(search_term) def _validate_search_term(key: str, search_term: str, description) -> None: _assert_valid_key(key, description) _assert_match_pattern(search_term, description.get(key).get("pattern")) _assert_min_inclusive(search_term, description.get(key).get("minInclusive")) _assert_max_inclusive(search_term, description.get(key).get("maxInclusive")) def _assert_valid_key(key: str, description: Dict[str, Any]) -> None: assert key in description.keys(), ( f'search_term with name "{key}" ' + "was not found for collection." + f" Available terms are: {', '.join(description.keys())}" ) def _assert_match_pattern(search_term: str, pattern: Union[str, None]) -> None: if not pattern: return assert re.match( pattern, search_term ), f"search_term {search_term} does not match pattern {pattern}" def _assert_min_inclusive(search_term: str, min_inclusive: Union[str, None]) -> None: if not min_inclusive: return assert int(search_term) >= int( min_inclusive ), f"search_term {search_term} is less than min_inclusive {min_inclusive}" def _assert_max_inclusive(search_term: str, max_inclusive: Union[str, None]) -> None: if not max_inclusive: return assert int(search_term) <= int( max_inclusive ), f"search_term {search_term} is greater than max_inclusive {max_inclusive}" _describe_docs: Dict[str, bytes] = {} def _get_describe_doc( collection: str, proxies: Union[Dict[str, str], None] = None ) -> bytes: docs = _describe_docs.get(collection) if docs: return docs session = Credentials.make_session(None, False, Credentials.RETRIES, proxies) with session.get( "https://catalogue.dataspace.copernicus.eu" + f"/resto/api/collections/{collection}/describe.xml", ) as res: assert res.status_code == 200, ( f"Unable to find collection with name {collection}. Please see " + "https://documentation.dataspace.copernicus.eu" + "/APIs/OpenSearch.html#collections " + "for a list of available collections" ) _describe_docs[collection] = res.content return res.content CDSETool-0.2.13/tests/000077500000000000000000000000001470176275200143265ustar00rootroot00000000000000CDSETool-0.2.13/tests/credentials/000077500000000000000000000000001470176275200166235ustar00rootroot00000000000000CDSETool-0.2.13/tests/credentials/credentials_test.py000066400000000000000000000204521470176275200225340ustar00rootroot00000000000000# pyright: reportAttributeAccessIssue=false import json import pytest import requests import datetime import jwt import base64 from cryptography.hazmat.primitives.asymmetric import rsa private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) from cdsetool.credentials import ( Credentials, NoCredentialsException, InvalidCredentialsException, TokenExchangeException, ) def _mock_openid(requests_mock) -> None: with open("tests/credentials/mock/openid-configuration.json") as f: requests_mock.get( "https://identity.dataspace.copernicus.eu/auth/realms/CDSE/.well-known/openid-configuration", text=f.read(), ) def _mock_token(requests_mock) -> None: headers = {"alg": "RS256", "typ": "JWT", "kid": "key-9000"} now = datetime.datetime.now() payload = { "exp": now.timestamp() + 3600, "iat": now.timestamp(), "jti": "bb4d3fab-1a39-442c-9a6f-072a167543c0", "iss": "https://identity.dataspace.copernicus.eu/auth/realms/CDSE", "aud": ["CLOUDFERRO_PUBLIC", "account"], "sub": "bfb3df17-4506-4adf-86ab-9bb9d03f11f1", "typ": "Bearer", "azp": "cdse-public", "session_state": "4adfd9e9-27d2-496d-9c10-bd3a54c8f1a3", "allowed-origins": [ "https://localhost:4200", "*", "https://workspace.staging-cdse-data-explorer.apps.staging.intra.cloudferro.com", ], "realm_access": { "roles": [ "offline_access", "uma_authorization", "default-roles-cdas", "copernicus-general", ] }, "resource_access": { "account": { "roles": ["manage-account", "manage-account-links", "view-profile"] } }, "scope": "AUDIENCE_PUBLIC openid email profile user-context", "sid": "03a2986d-ccfa-45e7-8e3a-55982e7e2a6e", "group_membership": [ "/access_groups/user_typology/copernicus_general", "/organizations/default-4f0080be-2b79-4837-b6a2-7f10c2b9ee1d/regular_user", ], "email_verified": True, "organizations": ["default-4f0080be-2b79-4837-b6a2-7f10c2b9ee1d"], "name": "User Full Name", "user_context_id": "b9ab6ae1-83b0-433d-828f-e9e06adcc4a2", "context_roles": {}, "context_groups": [ "/access_groups/user_typology/copernicus_general/", "/organizations/default-4f0080be-2b79-4837-b6a2-7f10c2b9ee1d/regular_user/", ], "preferred_username": "user@example.com", "given_name": "User first name", "user_context": "default-4f0080be-2b79-4837-b6a2-7f10c2b9ee1d", "family_name": "User last name", "email": "user@example.com", } response = json.dumps( { "access_token": jwt.encode( payload, private_key, algorithm="RS256", headers=headers ), "expires_in": 600, "refresh_expires_in": 3600, "refresh_token": "check-for-refresh-token-not-implementation-yet", "token_type": "Bearer", "not-before-policy": 0, "session_state": "4adfd9e9-27d2-496d-9c10-bd3a54c8f1a3", "scope": "AUDIENCE_PUBLIC openid email profile user-context", } ) requests_mock.post( "https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token", text=response, ) def _mock_jwks(mocker) -> None: class MockResponse: def __init__(self, json_data): self.json_data = json_data def __enter__(self): return self def read(self): return json.dumps(self.json_data).encode("utf-8") def __exit__(self, exc_type, exc_value, traceback): pass n = private_key.public_key().public_numbers().n e = private_key.public_key().public_numbers().e n = base64.urlsafe_b64encode( n.to_bytes((n.bit_length() + 7) // 8, byteorder="big") ).decode("utf-8") e = base64.urlsafe_b64encode( e.to_bytes((e.bit_length() + 7) // 8, byteorder="big") ).decode("utf-8") jwks = { "keys": [ { "kid": "key-9000", "kty": "RSA", "alg": "RS256", "use": "sig", "n": n, "e": e, } ] } mocker.patch("urllib.request.urlopen", return_value=MockResponse(jwks)) def test_ensure_tokens(requests_mock, mocker) -> None: _mock_openid(requests_mock) _mock_token(requests_mock) _mock_jwks(mocker) credentials = Credentials("username", "password") assert credentials._Credentials__access_token is not None assert credentials._Credentials__refresh_token is not None credentials._Credentials__access_token_expires = ( datetime.datetime.now() - datetime.timedelta(hours=100) ) spy = mocker.spy(credentials, "_Credentials__token_exchange") credentials._Credentials__ensure_tokens() spy.assert_called_once() credentials._Credentials__access_token_expires = ( datetime.datetime.now() - datetime.timedelta(hours=100) ) credentials._Credentials__refresh_token_expires = ( datetime.datetime.now() - datetime.timedelta(hours=100) ) credentials._Credentials__ensure_tokens() assert spy.call_count == 2 def test_read_credentials(requests_mock, mocker) -> None: _mock_openid(requests_mock) _mock_token(requests_mock) _mock_jwks(mocker) mocker.patch( "netrc.netrc", return_value=mocker.Mock( authenticators=lambda x: ("username", None, "password") ), ) credentials = Credentials() assert credentials._Credentials__username == "username" assert credentials._Credentials__password == "password" mocker.patch("netrc.netrc", return_value=mocker.Mock(authenticators=lambda x: None)) with pytest.raises(NoCredentialsException): credentials = Credentials() def test_refresh_token(requests_mock, mocker) -> None: _mock_openid(requests_mock) _mock_token(requests_mock) _mock_jwks(mocker) credentials = Credentials("username", "password") assert credentials._Credentials__access_token is not None assert credentials._Credentials__refresh_token is not None _mock_token(requests_mock) # mock again to return a new token prev_access_token = credentials._Credentials__access_token credentials._Credentials__access_token_expires = datetime.datetime.now() credentials._Credentials__refresh_token_expires = datetime.datetime.now() credentials._Credentials__ensure_tokens() assert credentials._Credentials__access_token is not None assert credentials._Credentials__refresh_token is not None assert prev_access_token != credentials._Credentials__access_token def test_get_session(requests_mock, mocker) -> None: _mock_openid(requests_mock) _mock_token(requests_mock) _mock_jwks(mocker) credentials = Credentials("username", "password") session = credentials.get_session() assert isinstance(session, requests.Session) assert ( session.headers.get("Authorization") == f"Bearer {credentials._Credentials__access_token}" ) def test_token_exchange(requests_mock, mocker) -> None: _mock_openid(requests_mock) _mock_token(requests_mock) _mock_jwks(mocker) credentials = Credentials("myuser123123", "password") data = { "grant_type": "password", "username": credentials._Credentials__username, "password": credentials._Credentials__password, "client_id": "cdse-public", } credentials._Credentials__token_exchange(data) requests_mock.post( "https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token", text="{}", status_code=401, ) with pytest.raises( InvalidCredentialsException, match="with username: myuser123123" ): credentials._Credentials__token_exchange(data) requests_mock.post( "https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token", text="Failure 123123", status_code=500, ) with pytest.raises(TokenExchangeException, match="Failure 123123"): credentials._Credentials__token_exchange(data) CDSETool-0.2.13/tests/credentials/mock/000077500000000000000000000000001470176275200175545ustar00rootroot00000000000000CDSETool-0.2.13/tests/credentials/mock/openid-configuration.json000066400000000000000000000144751470176275200246050ustar00rootroot00000000000000{"issuer":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE","authorization_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/auth","token_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token","introspection_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token/introspect","userinfo_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/userinfo","end_session_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/logout","frontchannel_logout_session_supported":true,"frontchannel_logout_supported":true,"jwks_uri":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/certs","check_session_iframe":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/login-status-iframe.html","grant_types_supported":["authorization_code","implicit","refresh_token","password","client_credentials","urn:ietf:params:oauth:grant-type:device_code","urn:openid:params:grant-type:ciba","urn:ietf:params:oauth:grant-type:token-exchange"],"acr_values_supported":["0","1"],"response_types_supported":["code","none","id_token","token","id_token token","code id_token","code token","code id_token token"],"subject_types_supported":["public","pairwise"],"id_token_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"id_token_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"id_token_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"userinfo_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"userinfo_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"userinfo_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"request_object_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512","none"],"request_object_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"request_object_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"response_modes_supported":["query","fragment","form_post","query.jwt","fragment.jwt","form_post.jwt","jwt"],"registration_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/clients-registrations/openid-connect","token_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"token_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"introspection_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"introspection_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"authorization_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"authorization_encryption_alg_values_supported":["RSA-OAEP","RSA-OAEP-256","RSA1_5"],"authorization_encryption_enc_values_supported":["A256GCM","A192GCM","A128GCM","A128CBC-HS256","A192CBC-HS384","A256CBC-HS512"],"claims_supported":["aud","sub","iss","auth_time","name","given_name","family_name","preferred_username","email","acr"],"claim_types_supported":["normal"],"claims_parameter_supported":true,"scopes_supported":["openid","additional_scope","acr","web-origins","microprofile-jwt","AUDIENCE_PUBLIC","phone","zipper_session_scope","Geographic_origin","address","openid","email","ondemand_processing","offline_access","roles","profile","user-context"],"request_parameter_supported":true,"request_uri_parameter_supported":true,"require_request_uri_registration":true,"code_challenge_methods_supported":["plain","S256"],"tls_client_certificate_bound_access_tokens":true,"revocation_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/revoke","revocation_endpoint_auth_methods_supported":["private_key_jwt","client_secret_basic","client_secret_post","tls_client_auth","client_secret_jwt"],"revocation_endpoint_auth_signing_alg_values_supported":["PS384","ES384","RS384","HS256","HS512","ES256","RS256","HS384","ES512","PS256","PS512","RS512"],"backchannel_logout_supported":true,"backchannel_logout_session_supported":true,"device_authorization_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/auth/device","backchannel_token_delivery_modes_supported":["poll","ping"],"backchannel_authentication_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/ext/ciba/auth","backchannel_authentication_request_signing_alg_values_supported":["PS384","ES384","RS384","ES256","RS256","ES512","PS256","PS512","RS512"],"require_pushed_authorization_requests":false,"pushed_authorization_request_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/ext/par/request","mtls_endpoint_aliases":{"token_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token","revocation_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/revoke","introspection_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token/introspect","device_authorization_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/auth/device","registration_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/clients-registrations/openid-connect","userinfo_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/userinfo","pushed_authorization_request_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/ext/par/request","backchannel_authentication_endpoint":"https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/ext/ciba/auth"}}CDSETool-0.2.13/tests/logger/000077500000000000000000000000001470176275200156055ustar00rootroot00000000000000CDSETool-0.2.13/tests/logger/logger_test.py000066400000000000000000000020121470176275200204700ustar00rootroot00000000000000import pytest from unittest.mock import MagicMock from cdsetool.logger import NoopLogger from cdsetool.download import download_feature def test_noop_logger_is_default() -> None: NoopLogger.debug = MagicMock() assert NoopLogger.debug.call_count == 0 download_feature( { "bad_object": True, "properties": { "title": "myfile.xml", "services": {"download": {}}, # missing url }, }, "somewhere", ) assert NoopLogger.debug.call_count == 1 def test_noop_does_not_error() -> None: try: download_feature( { "bad_object": True, "properties": { "title": "myfile.xml", "services": {"download": {}}, # missing url }, }, "somewhere", ) NoopLogger().debug("NoopLogger did not raise an exception") except Exception as e: pytest.fail(f"Unexpected exception: {e}") CDSETool-0.2.13/tests/query/000077500000000000000000000000001470176275200154735ustar00rootroot00000000000000CDSETool-0.2.13/tests/query/mock/000077500000000000000000000000001470176275200164245ustar00rootroot00000000000000CDSETool-0.2.13/tests/query/mock/sentinel_1/000077500000000000000000000000001470176275200204655ustar00rootroot00000000000000CDSETool-0.2.13/tests/query/mock/sentinel_1/describe.xml000066400000000000000000000225101470176275200227670ustar00rootroot00000000000000 Sentinel-1 Sentinel-1 Collection info@creodias.eu CEOS-OS-BP-V1.0 CREODIAS esa sentinel sentinel1 s1 radar Sentinel-1 Collection CloudFerro Sp. z o.o. CREODIAS, Copyright 2019, All Rights Reserved; ESA. Copyright 2019, All Rights Reserved open false en UTF-8 UTF-8 CDSETool-0.2.13/tests/query/mock/sentinel_1/page_1.json000066400000000000000000000553001470176275200225170ustar00rootroot00000000000000{"type":"FeatureCollection","properties":{"id":"95175430-77b3-5c4e-b686-cf8d8a7608ad","totalResults":48,"exactCount":1,"startIndex":1,"itemsPerPage":10,"query":{"originalFilters":{"collection":"SENTINEL-1"},"appliedFilters":{"collection":"SENTINEL-1"},"processingTime":10.105902424},"links":[{"rel":"self","type":"application/json","title":"self","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=1"},{"rel":"search","type":"application/opensearchdescription+xml","title":"OpenSearch Description Document","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/describe.xml"},{"rel":"next","type":"application/json","title":"next","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=1&page=2"},{"rel":"last","type":"application/json","title":"last","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=1&page=1245289"}]},"features":[{"type":"Feature","id":"171fd093-b1bc-4528-910b-73156cd0b5d3","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/29/S1A_OPER_AUX_GNSSRD_POD__20171211T101148_V20140628T235949_20140629T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T101148_V20140628T235949_20140629T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-29T00:00:05.000Z","completionDate":"2014-06-29T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:25.755Z","published":"2023-10-25T09:24:50.660Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/171fd093-b1bc-4528-910b-73156cd0b5d3","mimeType":"application/octet-stream","size":2655944}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 171fd093-b1bc-4528-910b-73156cd0b5d3","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/171fd093-b1bc-4528-910b-73156cd0b5d3.json"}]}},{"type":"Feature","id":"b176f138-5ff6-4d00-b520-935d5cdaa780","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/27/S1A_OPER_AUX_GNSSRD_POD__20171211T100937_V20140626T235949_20140627T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T100937_V20140626T235949_20140627T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-27T00:00:05.000Z","completionDate":"2014-06-27T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:16.884Z","published":"2023-10-25T09:24:54.347Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/b176f138-5ff6-4d00-b520-935d5cdaa780","mimeType":"application/octet-stream","size":2654347}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for b176f138-5ff6-4d00-b520-935d5cdaa780","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/b176f138-5ff6-4d00-b520-935d5cdaa780.json"}]}},{"type":"Feature","id":"eee137c1-58e0-4de0-906e-61bd4dfbd336","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/15/S1A_OPER_AUX_GNSSRD_POD__20171211T095728_V20140614T235949_20140615T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T095728_V20140614T235949_20140615T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-15T00:00:05.000Z","completionDate":"2014-06-15T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:12.935Z","published":"2023-10-25T09:24:52.478Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/eee137c1-58e0-4de0-906e-61bd4dfbd336","mimeType":"application/octet-stream","size":2659208}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for eee137c1-58e0-4de0-906e-61bd4dfbd336","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/eee137c1-58e0-4de0-906e-61bd4dfbd336.json"}]}},{"type":"Feature","id":"e8c2b1eb-0a06-45a8-9328-1006b59654d0","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/05/S1A_OPER_AUX_GNSSRD_POD__20171211T094729_V20140604T235949_20140605T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T094729_V20140604T235949_20140605T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-05T00:00:05.000Z","completionDate":"2014-06-05T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:19.415Z","published":"2023-10-25T09:24:41.278Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/e8c2b1eb-0a06-45a8-9328-1006b59654d0","mimeType":"application/octet-stream","size":2642391}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for e8c2b1eb-0a06-45a8-9328-1006b59654d0","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/e8c2b1eb-0a06-45a8-9328-1006b59654d0.json"}]}},{"type":"Feature","id":"e74ff0cc-b8c2-46e2-b6e7-f5cf8cacd0cc","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/04/S1A_OPER_AUX_GNSSRD_POD__20171211T094636_V20140603T235949_20140604T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T094636_V20140603T235949_20140604T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-04T00:00:05.000Z","completionDate":"2014-06-04T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:12.660Z","published":"2023-10-25T09:24:43.802Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/e74ff0cc-b8c2-46e2-b6e7-f5cf8cacd0cc","mimeType":"application/octet-stream","size":2643467}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for e74ff0cc-b8c2-46e2-b6e7-f5cf8cacd0cc","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/e74ff0cc-b8c2-46e2-b6e7-f5cf8cacd0cc.json"}]}},{"type":"Feature","id":"f0e7cb45-aba3-4351-8e1e-e35894e36cea","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/21/S1A_OPER_AUX_GNSSRD_POD__20171211T100324_V20140620T235949_20140621T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T100324_V20140620T235949_20140621T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-21T00:00:05.000Z","completionDate":"2014-06-21T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:10.467Z","published":"2023-10-25T09:24:24.683Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/f0e7cb45-aba3-4351-8e1e-e35894e36cea","mimeType":"application/octet-stream","size":2660808}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for f0e7cb45-aba3-4351-8e1e-e35894e36cea","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/f0e7cb45-aba3-4351-8e1e-e35894e36cea.json"}]}},{"type":"Feature","id":"9f35a88f-40cc-44e2-bd92-db64775d2a78","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/22/S1A_OPER_AUX_GNSSRD_POD__20171211T100425_V20140621T235949_20140622T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T100425_V20140621T235949_20140622T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-22T00:00:05.000Z","completionDate":"2014-06-22T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:00.134Z","published":"2023-10-25T09:24:22.613Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/9f35a88f-40cc-44e2-bd92-db64775d2a78","mimeType":"application/octet-stream","size":2662470}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 9f35a88f-40cc-44e2-bd92-db64775d2a78","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/9f35a88f-40cc-44e2-bd92-db64775d2a78.json"}]}},{"type":"Feature","id":"2c4eadf8-31b4-43bb-87c0-b31ce532415d","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/09/S1A_OPER_AUX_GNSSRD_POD__20171211T095126_V20140608T235949_20140609T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T095126_V20140608T235949_20140609T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-09T00:00:05.000Z","completionDate":"2014-06-09T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:01:55.980Z","published":"2023-10-25T09:24:18.205Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/2c4eadf8-31b4-43bb-87c0-b31ce532415d","mimeType":"application/octet-stream","size":2654252}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 2c4eadf8-31b4-43bb-87c0-b31ce532415d","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/2c4eadf8-31b4-43bb-87c0-b31ce532415d.json"}]}},{"type":"Feature","id":"b732b7c9-648d-45e1-927e-c3a69c638599","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/24/S1A_OPER_AUX_GNSSRD_POD__20171211T100627_V20140623T235949_20140624T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T100627_V20140623T235949_20140624T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-24T00:00:05.000Z","completionDate":"2014-06-24T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:01:29.093Z","published":"2023-10-25T09:24:17.062Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/b732b7c9-648d-45e1-927e-c3a69c638599","mimeType":"application/octet-stream","size":2662693}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for b732b7c9-648d-45e1-927e-c3a69c638599","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/b732b7c9-648d-45e1-927e-c3a69c638599.json"}]}},{"type":"Feature","id":"7ee1535f-b947-4c59-8a5c-f73da054fa2a","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/27/S1A_OPER_AUX_POEORB_OPOD_20210302T165817_V20140627T225944_20140629T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T165817_V20140627T225944_20140629T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-27T22:59:44.000Z","completionDate":"2014-06-29T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:03:52.073Z","published":"2023-10-25T16:30:56.080Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/7ee1535f-b947-4c59-8a5c-f73da054fa2a","mimeType":"application/octet-stream","size":4409765}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 7ee1535f-b947-4c59-8a5c-f73da054fa2a","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/7ee1535f-b947-4c59-8a5c-f73da054fa2a.json"}]}}]} CDSETool-0.2.13/tests/query/mock/sentinel_1/page_2.json000066400000000000000000000555751470176275200225360ustar00rootroot00000000000000{"type":"FeatureCollection","properties":{"id":"95175430-77b3-5c4e-b686-cf8d8a7608ad","totalResults":null,"exactCount":0,"startIndex":11,"itemsPerPage":10,"query":{"originalFilters":{"collection":"SENTINEL-1"},"appliedFilters":{"collection":"SENTINEL-1"},"processingTime":0.016495391},"links":[{"rel":"self","type":"application/json","title":"self","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=2"},{"rel":"search","type":"application/opensearchdescription+xml","title":"OpenSearch Description Document","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/describe.xml"},{"rel":"previous","type":"application/json","title":"previous","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=1"},{"rel":"first","type":"application/json","title":"first","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=1"},{"rel":"next","type":"application/json","title":"next","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=3"}]},"features":[{"type":"Feature","id":"1af93c0e-f3d1-4948-8ac7-4371a29ef6d4","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/10/S1A_OPER_AUX_PROQUA_POD__20210408T172636_V20140609T235944_20140610T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T172636_V20140609T235944_20140610T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-10T00:00:00.000Z","completionDate":"2014-06-10T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:49:46.309Z","published":"2023-10-25T16:04:49.135Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/1af93c0e-f3d1-4948-8ac7-4371a29ef6d4","mimeType":"application/octet-stream","size":1546666}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 1af93c0e-f3d1-4948-8ac7-4371a29ef6d4","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/1af93c0e-f3d1-4948-8ac7-4371a29ef6d4.json"}]}},{"type":"Feature","id":"6ea24bc5-7744-4689-9b52-f7190f85dfbf","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/23/S1A_OPER_AUX_PROQUA_POD__20210408T183946_V20140622T235944_20140623T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T183946_V20140622T235944_20140623T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-23T00:00:00.000Z","completionDate":"2014-06-23T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:03:02.990Z","published":"2023-10-25T15:57:19.143Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/6ea24bc5-7744-4689-9b52-f7190f85dfbf","mimeType":"application/octet-stream","size":1538251}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 6ea24bc5-7744-4689-9b52-f7190f85dfbf","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/6ea24bc5-7744-4689-9b52-f7190f85dfbf.json"}]}},{"type":"Feature","id":"bc9bde44-6222-4bdf-95e4-9eae6b4929f5","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/26/S1A_OPER_AUX_GNSSRD_POD__20171211T100838_V20140625T235949_20140626T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T100838_V20140625T235949_20140626T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-26T00:00:05.000Z","completionDate":"2014-06-26T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:23.736Z","published":"2023-10-25T09:24:56.085Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/bc9bde44-6222-4bdf-95e4-9eae6b4929f5","mimeType":"application/octet-stream","size":2656576}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for bc9bde44-6222-4bdf-95e4-9eae6b4929f5","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/bc9bde44-6222-4bdf-95e4-9eae6b4929f5.json"}]}},{"type":"Feature","id":"f01b4f7e-7dff-4b33-8760-546e2144b32e","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/10/S1A_OPER_AUX_GNSSRD_POD__20171211T095233_V20140609T235949_20140610T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T095233_V20140609T235949_20140610T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-10T00:00:05.000Z","completionDate":"2014-06-10T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:08.454Z","published":"2023-10-25T09:25:04.936Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/f01b4f7e-7dff-4b33-8760-546e2144b32e","mimeType":"application/octet-stream","size":2646229}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for f01b4f7e-7dff-4b33-8760-546e2144b32e","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/f01b4f7e-7dff-4b33-8760-546e2144b32e.json"}]}},{"type":"Feature","id":"cdaf523e-7a69-4227-8cb9-6f14bc0004e8","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/12/S1A_OPER_AUX_GNSSRD_POD__20171211T095430_V20140611T235949_20140612T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T095430_V20140611T235949_20140612T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-12T00:00:05.000Z","completionDate":"2014-06-12T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:07.004Z","published":"2023-10-25T09:25:00.724Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/cdaf523e-7a69-4227-8cb9-6f14bc0004e8","mimeType":"application/octet-stream","size":2656745}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for cdaf523e-7a69-4227-8cb9-6f14bc0004e8","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/cdaf523e-7a69-4227-8cb9-6f14bc0004e8.json"}]}},{"type":"Feature","id":"faa96789-1081-43ad-9ba9-9fe7a6b3cb8e","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/06/S1A_OPER_AUX_PROQUA_POD__20210408T170518_V20140605T235944_20140606T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T170518_V20140605T235944_20140606T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-06T00:00:00.000Z","completionDate":"2014-06-06T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:58:03.713Z","published":"2023-10-25T15:51:33.270Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/faa96789-1081-43ad-9ba9-9fe7a6b3cb8e","mimeType":"application/octet-stream","size":1547464}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for faa96789-1081-43ad-9ba9-9fe7a6b3cb8e","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/faa96789-1081-43ad-9ba9-9fe7a6b3cb8e.json"}]}},{"type":"Feature","id":"5dae21f7-29c2-4d08-b4e3-281abd3a531d","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/29/S1A_OPER_AUX_PROQUA_POD__20210408T191440_V20140628T235944_20140629T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T191440_V20140628T235944_20140629T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-29T00:00:00.000Z","completionDate":"2014-06-29T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:54:50.308Z","published":"2023-10-25T15:58:55.138Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/5dae21f7-29c2-4d08-b4e3-281abd3a531d","mimeType":"application/octet-stream","size":1543301}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 5dae21f7-29c2-4d08-b4e3-281abd3a531d","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/5dae21f7-29c2-4d08-b4e3-281abd3a531d.json"}]}},{"type":"Feature","id":"f55c6e56-8491-401d-8574-cf8c6b9931e8","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/25/S1A_OPER_AUX_PROQUA_POD__20210408T185048_V20140624T235944_20140625T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T185048_V20140624T235944_20140625T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-25T00:00:00.000Z","completionDate":"2014-06-25T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:53:06.764Z","published":"2023-10-25T15:51:08.971Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/f55c6e56-8491-401d-8574-cf8c6b9931e8","mimeType":"application/octet-stream","size":1541286}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for f55c6e56-8491-401d-8574-cf8c6b9931e8","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/f55c6e56-8491-401d-8574-cf8c6b9931e8.json"}]}},{"type":"Feature","id":"49bc85b3-ec0b-41e8-95f5-a9f72a4a60d8","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/08/S1A_OPER_AUX_PROQUA_POD__20210408T171601_V20140607T235944_20140608T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T171601_V20140607T235944_20140608T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-08T00:00:00.000Z","completionDate":"2014-06-08T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:52:27.272Z","published":"2023-10-25T15:48:02.438Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/49bc85b3-ec0b-41e8-95f5-a9f72a4a60d8","mimeType":"application/octet-stream","size":1546470}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 49bc85b3-ec0b-41e8-95f5-a9f72a4a60d8","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/49bc85b3-ec0b-41e8-95f5-a9f72a4a60d8.json"}]}},{"type":"Feature","id":"eda054be-6a01-4130-8c01-3d5ad3a94693","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_GNSSRD/2014/06/13/S1A_OPER_AUX_GNSSRD_POD__20171211T095530_V20140612T235949_20140613T235939","parentIdentifier":null,"title":"S1A_OPER_AUX_GNSSRD_POD__20171211T095530_V20140612T235949_20140613T235939","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-13T00:00:05.000Z","completionDate":"2014-06-13T23:59:55.000Z","productType":"AUX_GNSSRD","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:02:26.940Z","published":"2023-10-25T09:24:55.940Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/eda054be-6a01-4130-8c01-3d5ad3a94693","mimeType":"application/octet-stream","size":2662665}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for eda054be-6a01-4130-8c01-3d5ad3a94693","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/eda054be-6a01-4130-8c01-3d5ad3a94693.json"}]}}]}CDSETool-0.2.13/tests/query/mock/sentinel_1/page_3.json000066400000000000000000000556151470176275200225320ustar00rootroot00000000000000{"type":"FeatureCollection","properties":{"id":"95175430-77b3-5c4e-b686-cf8d8a7608ad","totalResults":null,"exactCount":0,"startIndex":21,"itemsPerPage":10,"query":{"originalFilters":{"collection":"SENTINEL-1"},"appliedFilters":{"collection":"SENTINEL-1"},"processingTime":0.024684707},"links":[{"rel":"self","type":"application/json","title":"self","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=3"},{"rel":"search","type":"application/opensearchdescription+xml","title":"OpenSearch Description Document","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/describe.xml"},{"rel":"previous","type":"application/json","title":"previous","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=2"},{"rel":"first","type":"application/json","title":"first","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=1"},{"rel":"next","type":"application/json","title":"next","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=4"}]},"features":[{"type":"Feature","id":"b52b7e05-fe2c-4c9d-9950-73235bc7e64f","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/21/S1A_OPER_AUX_POEORB_OPOD_20210302T141715_V20140621T225944_20140623T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T141715_V20140621T225944_20140623T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-21T22:59:44.000Z","completionDate":"2014-06-23T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:27.889Z","published":"2023-10-25T16:29:40.650Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/b52b7e05-fe2c-4c9d-9950-73235bc7e64f","mimeType":"application/octet-stream","size":4409603}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for b52b7e05-fe2c-4c9d-9950-73235bc7e64f","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/b52b7e05-fe2c-4c9d-9950-73235bc7e64f.json"}]}},{"type":"Feature","id":"7587e5ff-7edd-4ce5-8c37-f6c502e5d206","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/12/S1A_OPER_AUX_POEORB_OPOD_20210302T112025_V20140612T225944_20140614T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T112025_V20140612T225944_20140614T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-12T22:59:44.000Z","completionDate":"2014-06-14T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:01:43.946Z","published":"2023-10-25T16:29:02.236Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/7587e5ff-7edd-4ce5-8c37-f6c502e5d206","mimeType":"application/octet-stream","size":4413738}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 7587e5ff-7edd-4ce5-8c37-f6c502e5d206","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/7587e5ff-7edd-4ce5-8c37-f6c502e5d206.json"}]}},{"type":"Feature","id":"81c86ff2-3b17-4603-a2cf-4b07f5977dba","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/07/S1A_OPER_AUX_PROQUA_POD__20210408T171042_V20140606T235944_20140607T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T171042_V20140606T235944_20140607T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-07T00:00:00.000Z","completionDate":"2014-06-07T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:51:22.623Z","published":"2023-10-25T16:10:46.095Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/81c86ff2-3b17-4603-a2cf-4b07f5977dba","mimeType":"application/octet-stream","size":1547609}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 81c86ff2-3b17-4603-a2cf-4b07f5977dba","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/81c86ff2-3b17-4603-a2cf-4b07f5977dba.json"}]}},{"type":"Feature","id":"ae3831db-5a5d-47fd-b765-0e8681c2597f","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/28/S1A_OPER_AUX_PROQUA_POD__20210408T190815_V20140627T235944_20140628T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T190815_V20140627T235944_20140628T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-28T00:00:00.000Z","completionDate":"2014-06-28T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:03:30.069Z","published":"2023-10-25T16:07:11.013Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/ae3831db-5a5d-47fd-b765-0e8681c2597f","mimeType":"application/octet-stream","size":1541442}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for ae3831db-5a5d-47fd-b765-0e8681c2597f","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/ae3831db-5a5d-47fd-b765-0e8681c2597f.json"}]}},{"type":"Feature","id":"ce4e2a32-fdee-4ef5-9ebe-756206594850","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/16/S1A_OPER_AUX_PROQUA_POD__20210408T180049_V20140615T235944_20140616T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T180049_V20140615T235944_20140616T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-16T00:00:00.000Z","completionDate":"2014-06-16T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:03:17.296Z","published":"2023-10-25T16:07:36.737Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/ce4e2a32-fdee-4ef5-9ebe-756206594850","mimeType":"application/octet-stream","size":1540079}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for ce4e2a32-fdee-4ef5-9ebe-756206594850","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/ce4e2a32-fdee-4ef5-9ebe-756206594850.json"}]}},{"type":"Feature","id":"8b2707d9-4c4c-4578-8a35-19316f6685fe","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/14/S1A_OPER_AUX_PROQUA_POD__20210408T174826_V20140613T235944_20140614T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T174826_V20140613T235944_20140614T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-14T00:00:00.000Z","completionDate":"2014-06-14T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:59:54.184Z","published":"2023-10-25T16:04:43.064Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/8b2707d9-4c4c-4578-8a35-19316f6685fe","mimeType":"application/octet-stream","size":1541886}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 8b2707d9-4c4c-4578-8a35-19316f6685fe","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/8b2707d9-4c4c-4578-8a35-19316f6685fe.json"}]}},{"type":"Feature","id":"d48fbc83-7662-4005-976d-d811f65df5cc","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/11/S1A_OPER_AUX_PROQUA_POD__20210408T173143_V20140610T235944_20140611T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T173143_V20140610T235944_20140611T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-11T00:00:00.000Z","completionDate":"2014-06-11T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:58:46.832Z","published":"2023-10-25T16:04:41.238Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/d48fbc83-7662-4005-976d-d811f65df5cc","mimeType":"application/octet-stream","size":1544323}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for d48fbc83-7662-4005-976d-d811f65df5cc","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/d48fbc83-7662-4005-976d-d811f65df5cc.json"}]}},{"type":"Feature","id":"7456aebf-3628-4a6c-8877-37a58547457a","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/27/S1A_OPER_AUX_PROQUA_POD__20210408T190132_V20140626T235944_20140627T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T190132_V20140626T235944_20140627T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-27T00:00:00.000Z","completionDate":"2014-06-27T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:55:23.735Z","published":"2023-10-25T16:07:43.039Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/7456aebf-3628-4a6c-8877-37a58547457a","mimeType":"application/octet-stream","size":1539735}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 7456aebf-3628-4a6c-8877-37a58547457a","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/7456aebf-3628-4a6c-8877-37a58547457a.json"}]}},{"type":"Feature","id":"59f4b530-1e3d-4c08-939e-bc17d4c417b8","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/17/S1A_OPER_AUX_PROQUA_POD__20210408T180606_V20140616T235944_20140617T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T180606_V20140616T235944_20140617T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-17T00:00:00.000Z","completionDate":"2014-06-17T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:55:04.525Z","published":"2023-10-25T16:07:16.736Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/59f4b530-1e3d-4c08-939e-bc17d4c417b8","mimeType":"application/octet-stream","size":1540847}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 59f4b530-1e3d-4c08-939e-bc17d4c417b8","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/59f4b530-1e3d-4c08-939e-bc17d4c417b8.json"}]}},{"type":"Feature","id":"eea5a489-4283-4f08-842e-d1cb8d84bed5","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/09/S1A_OPER_AUX_PROQUA_POD__20210408T172140_V20140608T235944_20140609T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T172140_V20140608T235944_20140609T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-09T00:00:00.000Z","completionDate":"2014-06-09T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:51:04.210Z","published":"2023-10-25T16:06:33.054Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/eea5a489-4283-4f08-842e-d1cb8d84bed5","mimeType":"application/octet-stream","size":1545639}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for eea5a489-4283-4f08-842e-d1cb8d84bed5","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/eea5a489-4283-4f08-842e-d1cb8d84bed5.json"}]}}]}CDSETool-0.2.13/tests/query/mock/sentinel_1/page_4.json000066400000000000000000000556551470176275200225370ustar00rootroot00000000000000{"type":"FeatureCollection","properties":{"id":"95175430-77b3-5c4e-b686-cf8d8a7608ad","totalResults":null,"exactCount":0,"startIndex":31,"itemsPerPage":10,"query":{"originalFilters":{"collection":"SENTINEL-1"},"appliedFilters":{"collection":"SENTINEL-1"},"processingTime":0.025793563},"links":[{"rel":"self","type":"application/json","title":"self","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=4"},{"rel":"search","type":"application/opensearchdescription+xml","title":"OpenSearch Description Document","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/describe.xml"},{"rel":"previous","type":"application/json","title":"previous","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=3"},{"rel":"first","type":"application/json","title":"first","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=1"},{"rel":"next","type":"application/json","title":"next","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=5"}]},"features":[{"type":"Feature","id":"de2f7e92-9b04-44e7-be6f-b370eec2a5d2","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/18/S1A_OPER_AUX_POEORB_OPOD_20210302T131937_V20140618T225944_20140620T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T131937_V20140618T225944_20140620T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-18T22:59:44.000Z","completionDate":"2014-06-20T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:38.804Z","published":"2023-10-25T16:29:51.842Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/de2f7e92-9b04-44e7-be6f-b370eec2a5d2","mimeType":"application/octet-stream","size":4409702}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for de2f7e92-9b04-44e7-be6f-b370eec2a5d2","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/de2f7e92-9b04-44e7-be6f-b370eec2a5d2.json"}]}},{"type":"Feature","id":"59866e1f-af70-46fe-b9c4-64c5cfd4c210","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/13/S1A_OPER_AUX_POEORB_OPOD_20210302T113935_V20140613T225944_20140615T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T113935_V20140613T225944_20140615T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-13T22:59:44.000Z","completionDate":"2014-06-15T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:37.333Z","published":"2023-10-25T16:29:49.887Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/59866e1f-af70-46fe-b9c4-64c5cfd4c210","mimeType":"application/octet-stream","size":4409704}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 59866e1f-af70-46fe-b9c4-64c5cfd4c210","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/59866e1f-af70-46fe-b9c4-64c5cfd4c210.json"}]}},{"type":"Feature","id":"43cc17a6-b16f-4b5d-a063-66828ec5a814","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/08/S1A_OPER_AUX_POEORB_OPOD_20210302T094557_V20140608T225944_20140610T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T094557_V20140608T225944_20140610T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-08T22:59:44.000Z","completionDate":"2014-06-10T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:36.185Z","published":"2023-10-25T16:29:48.950Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/43cc17a6-b16f-4b5d-a063-66828ec5a814","mimeType":"application/octet-stream","size":4409712}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 43cc17a6-b16f-4b5d-a063-66828ec5a814","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/43cc17a6-b16f-4b5d-a063-66828ec5a814.json"}]}},{"type":"Feature","id":"a72be50c-46f2-40c8-88fd-b390a1f5b34f","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/15/S1A_OPER_AUX_POEORB_OPOD_20210302T121837_V20140615T225944_20140617T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T121837_V20140615T225944_20140617T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-15T22:59:44.000Z","completionDate":"2014-06-17T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:32.615Z","published":"2023-10-25T16:29:45.520Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/a72be50c-46f2-40c8-88fd-b390a1f5b34f","mimeType":"application/octet-stream","size":4409901}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for a72be50c-46f2-40c8-88fd-b390a1f5b34f","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/a72be50c-46f2-40c8-88fd-b390a1f5b34f.json"}]}},{"type":"Feature","id":"a5cc9ac1-8d61-4153-8bd9-3478484c7b3e","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/19/S1A_OPER_AUX_POEORB_OPOD_20210302T133908_V20140619T225944_20140621T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T133908_V20140619T225944_20140621T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-19T22:59:44.000Z","completionDate":"2014-06-21T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:32.149Z","published":"2023-10-25T16:29:44.679Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/a5cc9ac1-8d61-4153-8bd9-3478484c7b3e","mimeType":"application/octet-stream","size":4409480}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for a5cc9ac1-8d61-4153-8bd9-3478484c7b3e","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/a5cc9ac1-8d61-4153-8bd9-3478484c7b3e.json"}]}},{"type":"Feature","id":"7c86dd5a-56e2-4666-8985-f15ef5979e5c","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/12/S1A_OPER_AUX_PROQUA_POD__20210408T173653_V20140611T235944_20140612T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T173653_V20140611T235944_20140612T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-12T00:00:00.000Z","completionDate":"2014-06-12T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T23:03:28.825Z","published":"2023-10-25T16:14:24.254Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/7c86dd5a-56e2-4666-8985-f15ef5979e5c","mimeType":"application/octet-stream","size":1541744}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 7c86dd5a-56e2-4666-8985-f15ef5979e5c","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/7c86dd5a-56e2-4666-8985-f15ef5979e5c.json"}]}},{"type":"Feature","id":"84fc9731-6e22-4c8b-b755-fe157558bbe4","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/30/S1A_OPER_AUX_PROQUA_POD__20210408T192043_V20140629T235944_20140630T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T192043_V20140629T235944_20140630T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-30T00:00:00.000Z","completionDate":"2014-06-30T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:59:19.053Z","published":"2023-10-25T16:19:58.122Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/84fc9731-6e22-4c8b-b755-fe157558bbe4","mimeType":"application/octet-stream","size":1541940}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 84fc9731-6e22-4c8b-b755-fe157558bbe4","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/84fc9731-6e22-4c8b-b755-fe157558bbe4.json"}]}},{"type":"Feature","id":"0d1fc992-70d5-4cac-8da9-fb186caaa9e7","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/22/S1A_OPER_AUX_PROQUA_POD__20210408T183323_V20140621T235944_20140622T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T183323_V20140621T235944_20140622T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-22T00:00:00.000Z","completionDate":"2014-06-22T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:51:37.129Z","published":"2023-10-25T16:12:07.871Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/0d1fc992-70d5-4cac-8da9-fb186caaa9e7","mimeType":"application/octet-stream","size":1540022}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 0d1fc992-70d5-4cac-8da9-fb186caaa9e7","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/0d1fc992-70d5-4cac-8da9-fb186caaa9e7.json"}]}},{"type":"Feature","id":"2411a381-dfca-4324-b633-b6d6fa272b5d","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_PROQUA/2014/06/21/S1A_OPER_AUX_PROQUA_POD__20210408T182802_V20140620T235944_20140621T235943","parentIdentifier":null,"title":"S1A_OPER_AUX_PROQUA_POD__20210408T182802_V20140620T235944_20140621T235943","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-21T00:00:00.000Z","completionDate":"2014-06-21T23:59:59.000Z","productType":"AUX_PROQUA","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-11-14T22:51:24.620Z","published":"2023-10-25T16:15:39.122Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/2411a381-dfca-4324-b633-b6d6fa272b5d","mimeType":"application/octet-stream","size":1540894}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 2411a381-dfca-4324-b633-b6d6fa272b5d","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/2411a381-dfca-4324-b633-b6d6fa272b5d.json"}]}},{"type":"Feature","id":"3435e8d4-00a6-498e-9ba0-6a1e79d5408f","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/05/S1A_OPER_AUX_POEORB_OPOD_20210302T084858_V20140605T225944_20140607T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T084858_V20140605T225944_20140607T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-05T22:59:44.000Z","completionDate":"2014-06-07T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:01:11.578Z","published":"2023-10-25T16:28:33.454Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/3435e8d4-00a6-498e-9ba0-6a1e79d5408f","mimeType":"application/octet-stream","size":4413219}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 3435e8d4-00a6-498e-9ba0-6a1e79d5408f","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/3435e8d4-00a6-498e-9ba0-6a1e79d5408f.json"}]}}]}CDSETool-0.2.13/tests/query/mock/sentinel_1/page_5.json000066400000000000000000000446651470176275200225370ustar00rootroot00000000000000{"type":"FeatureCollection","properties":{"id":"95175430-77b3-5c4e-b686-cf8d8a7608ad","totalResults":null,"exactCount":0,"startIndex":41,"itemsPerPage":10,"query":{"originalFilters":{"collection":"SENTINEL-1"},"appliedFilters":{"collection":"SENTINEL-1"},"processingTime":0.028784816},"links":[{"rel":"self","type":"application/json","title":"self","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=5"},{"rel":"search","type":"application/opensearchdescription+xml","title":"OpenSearch Description Document","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/describe.xml"},{"rel":"previous","type":"application/json","title":"previous","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=4"},{"rel":"first","type":"application/json","title":"first","href":"https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=1"}]},"features":[{"type":"Feature","id":"baf154b1-11b1-48bf-92f0-71c085f09b5b","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/20/S1A_OPER_AUX_POEORB_OPOD_20210302T135813_V20140620T225944_20140622T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T135813_V20140620T225944_20140622T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-20T22:59:44.000Z","completionDate":"2014-06-22T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:03:55.944Z","published":"2023-10-25T16:30:59.140Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/baf154b1-11b1-48bf-92f0-71c085f09b5b","mimeType":"application/octet-stream","size":4409919}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for baf154b1-11b1-48bf-92f0-71c085f09b5b","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/baf154b1-11b1-48bf-92f0-71c085f09b5b.json"}]}},{"type":"Feature","id":"04fe8338-0ea8-4533-856a-f9e7373b8066","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/23/S1A_OPER_AUX_POEORB_OPOD_20210302T151136_V20140623T225944_20140625T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T151136_V20140623T225944_20140625T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-23T22:59:44.000Z","completionDate":"2014-06-25T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:03:49.639Z","published":"2023-10-25T16:30:54.899Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/04fe8338-0ea8-4533-856a-f9e7373b8066","mimeType":"application/octet-stream","size":4419593}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 04fe8338-0ea8-4533-856a-f9e7373b8066","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/04fe8338-0ea8-4533-856a-f9e7373b8066.json"}]}},{"type":"Feature","id":"34deb337-bc53-47f8-a4a2-438face25f8a","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/02/S1A_OPER_AUX_POEORB_OPOD_20210302T073606_V20140602T225944_20140604T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T073606_V20140602T225944_20140604T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-02T22:59:44.000Z","completionDate":"2014-06-04T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:03:44.270Z","published":"2023-10-25T16:30:51.359Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/34deb337-bc53-47f8-a4a2-438face25f8a","mimeType":"application/octet-stream","size":4416098}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 34deb337-bc53-47f8-a4a2-438face25f8a","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/34deb337-bc53-47f8-a4a2-438face25f8a.json"}]}},{"type":"Feature","id":"63498c95-6dd9-484a-89f5-3d41465a9ca8","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/10/S1A_OPER_AUX_POEORB_OPOD_20210302T103249_V20140610T225944_20140612T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T103249_V20140610T225944_20140612T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-10T22:59:44.000Z","completionDate":"2014-06-12T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:03:33.391Z","published":"2023-10-25T16:30:44.063Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/63498c95-6dd9-484a-89f5-3d41465a9ca8","mimeType":"application/octet-stream","size":4415831}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 63498c95-6dd9-484a-89f5-3d41465a9ca8","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/63498c95-6dd9-484a-89f5-3d41465a9ca8.json"}]}},{"type":"Feature","id":"c8260501-8024-4d67-a217-573456b5599a","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/09/S1A_OPER_AUX_POEORB_OPOD_20210302T100717_V20140609T225944_20140611T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T100717_V20140609T225944_20140611T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-09T22:59:44.000Z","completionDate":"2014-06-11T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:03:24.466Z","published":"2023-10-25T16:30:36.255Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/c8260501-8024-4d67-a217-573456b5599a","mimeType":"application/octet-stream","size":4412117}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for c8260501-8024-4d67-a217-573456b5599a","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/c8260501-8024-4d67-a217-573456b5599a.json"}]}},{"type":"Feature","id":"7b67be9a-4937-49f0-bcb0-f5a7a45d6743","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/17/S1A_OPER_AUX_POEORB_OPOD_20210302T130012_V20140617T225944_20140619T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T130012_V20140617T225944_20140619T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-17T22:59:44.000Z","completionDate":"2014-06-19T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:52.375Z","published":"2023-10-25T16:30:04.652Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/7b67be9a-4937-49f0-bcb0-f5a7a45d6743","mimeType":"application/octet-stream","size":4409781}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 7b67be9a-4937-49f0-bcb0-f5a7a45d6743","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/7b67be9a-4937-49f0-bcb0-f5a7a45d6743.json"}]}},{"type":"Feature","id":"be6eecb9-fd59-4d67-bfcb-790940177601","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/16/S1A_OPER_AUX_POEORB_OPOD_20210302T124121_V20140616T225944_20140618T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T124121_V20140616T225944_20140618T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-16T22:59:44.000Z","completionDate":"2014-06-18T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:48.615Z","published":"2023-10-25T16:30:00.773Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/be6eecb9-fd59-4d67-bfcb-790940177601","mimeType":"application/octet-stream","size":4413571}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for be6eecb9-fd59-4d67-bfcb-790940177601","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/be6eecb9-fd59-4d67-bfcb-790940177601.json"}]}},{"type":"Feature","id":"23b0ea94-ac19-4200-9c7d-4b9537b95dc3","geometry":[],"properties":{"collection":"SENTINEL-1","status":"ONLINE","license":{"licenseId":"unlicensed","hasToBeSigned":"never","grantedCountries":null,"grantedOrganizationCountries":null,"grantedFlags":null,"viewService":"public","signatureQuota":-1,"description":{"shortName":"No license"}},"productIdentifier":"/eodata/Sentinel-1/AUX/AUX_POEORB/2014/06/26/S1A_OPER_AUX_POEORB_OPOD_20210302T163905_V20140626T225944_20140628T005944.EOF","parentIdentifier":null,"title":"S1A_OPER_AUX_POEORB_OPOD_20210302T163905_V20140626T225944_20140628T005944.EOF","description":"The Sentinel-1 mission is the European Radar Observatory for the Copernicus joint initiative of the European Commission (EC) and the European Space Agency (ESA). The Sentinel-1 mission includes C-band imaging operating in four exclusive imaging modes with different resolution (down to 5 m) and coverage (up to 400 km). It provides dual polarization capability, short revisit times and rapid product delivery. Additionally, precise measurements of spacecraft position and attitude are available for every observation [https://dataspace.copernicus.eu/explore-data/data-collections/sentinel-data/sentinel-1].","organisationName":null,"startDate":"2014-06-26T22:59:44.000Z","completionDate":"2014-06-28T00:59:44.000Z","productType":"AUX_POEORB","processingLevel":null,"platform":"SENTINEL-1","instrument":"SAR","resolution":0,"sensorMode":null,"orbitNumber":0,"quicklook":null,"thumbnail":null,"updated":"2023-10-25T18:02:44.174Z","published":"2023-10-25T16:29:57.369Z","snowCover":0,"cloudCover":0,"gmlgeometry":null,"centroid":{"type":null,"coordinates":null},"orbitDirection":null,"timeliness":null,"relativeOrbitNumber":0,"processingBaseline":0,"polarisation":null,"swath":null,"services":{"download":{"url":"https://catalogue.dataspace.copernicus.eu/download/23b0ea94-ac19-4200-9c7d-4b9537b95dc3","mimeType":"application/octet-stream","size":4415528}},"links":[{"rel":"self","type":"application/json","title":"GeoJSON link for 23b0ea94-ac19-4200-9c7d-4b9537b95dc3","href":"https://catalogue.dataspace.copernicus.eu/resto/collections/SENTINEL-1/23b0ea94-ac19-4200-9c7d-4b9537b95dc3.json"}]}}]} CDSETool-0.2.13/tests/query/query_features_test.py000066400000000000000000000065341470176275200221570ustar00rootroot00000000000000from cdsetool.query import query_features, FeatureQuery def _mock_describe(requests_mock): url = "https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/describe.xml" with open( "tests/query/mock/sentinel_1/describe.xml", "r", encoding="utf-8" ) as file: requests_mock.get(url, text=file.read()) def _mock_sentinel_1(requests_mock): urls = [ ( "tests/query/mock/sentinel_1/page_1.json", "https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=1", ), ( "tests/query/mock/sentinel_1/page_2.json", "https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=2", ), ( "tests/query/mock/sentinel_1/page_3.json", "https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=3", ), ( "tests/query/mock/sentinel_1/page_4.json", "https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=4", ), ( "tests/query/mock/sentinel_1/page_5.json", "https://catalogue.dataspace.copernicus.eu/resto/api/collections/Sentinel1/search.json?maxRecords=10&exactCount=0&page=5", ), ] for file, url in urls: with open(file, "r", encoding="utf-8") as file: requests_mock.get(url, text=file.read()) def test_query_features_length(requests_mock) -> None: _mock_describe(requests_mock) _mock_sentinel_1(requests_mock) query = query_features("Sentinel1", {"maxRecords": 10}) assert len(query) == 48 manual_count = 0 for feature in query: manual_count += 1 assert manual_count == 48 def test_query_features_reusable(requests_mock) -> None: _mock_describe(requests_mock) _mock_sentinel_1(requests_mock) query = query_features("Sentinel1", {"maxRecords": 10}) assert len(query) == len(query) assert len(query) == 48 # query is not exhausted after first len call assert list(query) == list(query) # query is not exhausted after first iteration def test_query_features_random_access(requests_mock) -> None: _mock_describe(requests_mock) _mock_sentinel_1(requests_mock) query = query_features("Sentinel1", {"maxRecords": 10}) assert ( query[0]["properties"]["title"] == "S1A_OPER_AUX_GNSSRD_POD__20171211T101148_V20140628T235949_20140629T235939" ) assert len(query.features) == 10 assert ( query[9]["properties"]["title"] == "S1A_OPER_AUX_POEORB_OPOD_20210302T165817_V20140627T225944_20140629T005944.EOF" ) assert len(query.features) == 10 assert ( query[13]["properties"]["title"] == "S1A_OPER_AUX_GNSSRD_POD__20171211T095233_V20140609T235949_20140610T235939" ) assert len(query.features) == 20 assert ( query[2]["properties"]["title"] == "S1A_OPER_AUX_GNSSRD_POD__20171211T095728_V20140614T235949_20140615T235939" ) assert len(query.features) == 20 assert ( query[34]["properties"]["title"] == "S1A_OPER_AUX_POEORB_OPOD_20210302T133908_V20140619T225944_20140621T005944.EOF" ) assert len(query.features) == 40 CDSETool-0.2.13/tests/query/query_test.py000066400000000000000000000112431470176275200202520ustar00rootroot00000000000000import pytest from cdsetool.query import ( _serialize_search_term, _validate_search_term, _assert_match_pattern, _assert_valid_key, _assert_min_inclusive, _assert_max_inclusive, shape_to_wkt, geojson_to_wkt, ) from datetime import date, datetime def test_serialize_search_term() -> None: assert _serialize_search_term("foo") == "foo" assert _serialize_search_term(["foo", "bar"]) == "foo,bar" assert _serialize_search_term(date(2020, 1, 1)) == "2020-01-01" assert ( _serialize_search_term(datetime(2020, 1, 1, 12, 0, 0)) == "2020-01-01T12:00:00Z" ) def test_validate_search_term() -> None: description = { "productType": {"pattern": "^(S2MSI1C|S2MSI2A)$"}, "orbitNumber": { "minInclusive": "1", "pattern": "^(\\[|\\]|[0-9])?[0-9]+$|^[0-9]+?(\\[|\\])$|^(\\[|\\])[0-9]+,[0-9]+(\\[|\\])$", }, } _validate_search_term("productType", "S2MSI1C", description) _validate_search_term("orbitNumber", "1", description) _validate_search_term("orbitNumber", "43212", description) with pytest.raises(AssertionError): _validate_search_term("productType", "foo", description) with pytest.raises(AssertionError): _validate_search_term("orbitNumber", "0", description) with pytest.raises(AssertionError): _validate_search_term("orbitNumber", "-100", description) with pytest.raises(AssertionError): _validate_search_term("orbitNumber", "foobar", description) def test_assert_valid_key() -> None: _assert_valid_key("someKey", {"someKey": True}) with pytest.raises(AssertionError): _assert_valid_key("otherKey", {"someKey": True}) def test_assert_match_pattern() -> None: pattern = "^[0-9]{4}-[0-9]{2}-[0-9]{2}(T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]+)?(|Z|[\\+\\-][0-9]{2}:[0-9]{2}))?$" with pytest.raises(AssertionError): _assert_match_pattern("foo", pattern) with pytest.raises(AssertionError): _assert_match_pattern("01-01-2020", pattern) _assert_match_pattern("2020-01-01", None) _assert_match_pattern("2020-01-01", pattern) _assert_match_pattern("2020-01-01T20:31:28.888Z", pattern) pattern = "^(asc|desc|ascending|descending)$" with pytest.raises(AssertionError): _assert_match_pattern("foo", pattern) with pytest.raises(AssertionError): _assert_match_pattern("01-01-2020", pattern) _assert_match_pattern("asc", pattern) _assert_match_pattern("descending", pattern) def test_assert_min_inclusive() -> None: _assert_min_inclusive("1", "1") _assert_min_inclusive("2", "1") with pytest.raises(AssertionError): _assert_min_inclusive("0", "1") def test_assert_max_inclusive() -> None: _assert_max_inclusive("1", "1") _assert_max_inclusive("0", "1") with pytest.raises(AssertionError): _assert_max_inclusive("2", "1") def test_shape_to_wkt() -> None: wkt = "POLYGON((10.172406299744779 55.48259118004532, 10.172406299744779 55.38234270718456, 10.42371976928382 55.38234270718456, 10.42371976928382 55.48259118004532, 10.172406299744779 55.48259118004532))" assert shape_to_wkt("tests/shape/POLYGON.shp") == wkt def test_geojson_to_wkt() -> None: wkt = "POLYGON((10.172406299744779 55.48259118004532, 10.172406299744779 55.38234270718456, 10.42371976928382 55.38234270718456, 10.42371976928382 55.48259118004532, 10.172406299744779 55.48259118004532))" geojson = '{ "type": "Feature", "properties": { }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 10.172406299744779, 55.482591180045318 ], [ 10.172406299744779, 55.382342707184563 ], [ 10.423719769283821, 55.382342707184563 ], [ 10.423719769283821, 55.482591180045318 ], [ 10.172406299744779, 55.482591180045318 ] ] ] } }' assert geojson_to_wkt(geojson) == wkt geojson = '{ "type": "Polygon", "coordinates": [ [ [ 10.172406299744779, 55.482591180045318 ], [ 10.172406299744779, 55.382342707184563 ], [ 10.423719769283821, 55.382342707184563 ], [ 10.423719769283821, 55.482591180045318 ], [ 10.172406299744779, 55.482591180045318 ] ] ] }' assert geojson_to_wkt(geojson) == wkt wkt = "POLYGON((17.58127378553624 59.88489715357605, 17.58127378553624 59.80687027682205, 17.73996723627809 59.80687027682205, 17.73996723627809 59.88489715357605, 17.58127378553624 59.88489715357605))" geojson = '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{ },"geometry":{"coordinates":[[[17.58127378553624,59.88489715357605],[17.58127378553624,59.80687027682205],[17.73996723627809,59.80687027682205],[17.73996723627809,59.88489715357605],[17.58127378553624,59.88489715357605]]],"type":"Polygon" } } ] }' assert geojson_to_wkt(geojson) == wkt CDSETool-0.2.13/tests/shape/000077500000000000000000000000001470176275200154265ustar00rootroot00000000000000CDSETool-0.2.13/tests/shape/POLYGON.dbf000066400000000000000000000000431470176275200172270ustar00rootroot00000000000000{ ! CDSETool-0.2.13/tests/shape/POLYGON.prj000066400000000000000000000002171470176275200172720ustar00rootroot00000000000000GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]CDSETool-0.2.13/tests/shape/POLYGON.shp000066400000000000000000000003541470176275200172730ustar00rootroot00000000000000' vèpv£EX$@dœ›ð°K@@|/ÌñØ$@üÐ;ŒÅ½K@@pv£EX$@dœ›ð°K@@|/ÌñØ$@üÐ;ŒÅ½K@pv£EX$@üÐ;ŒÅ½K@pv£EX$@dœ›ð°K@@|/ÌñØ$@dœ›ð°K@@|/ÌñØ$@üÐ;ŒÅ½K@pv£EX$@üÐ;ŒÅ½K@CDSETool-0.2.13/tests/shape/POLYGON.shx000066400000000000000000000001541470176275200173010ustar00rootroot00000000000000' 6èpv£EX$@dœ›ð°K@@|/ÌñØ$@üÐ;ŒÅ½K@2@