Пример #1
0
def get_pagination_info(arguments):
    """Get pagination arguments"""
    page = get_int(arguments.pop("page", DEFAULT_PAGE))
    # items_per_page can be specified using limit or itemsPerPage
    items_per_page = get_int(arguments.pop("limit", DEFAULT_ITEMS_PER_PAGE))
    items_per_page = get_int(arguments.pop("itemsPerPage", items_per_page))

    if page is not None and page < 0:
        raise ValidationError("invalid page number. Must be positive integer")
    if items_per_page is not None and items_per_page < 0:
        raise ValidationError(
            "invalid number of items per page. Must be positive integer")
    return page, items_per_page
Пример #2
0
 def validate(config_keys):
     """Validate a :class:`~eodag.config.ProviderConfig`"""
     if "name" not in config_keys:
         raise ValidationError("Provider config must have name key")
     if not any(k in config_keys for k in ("api", "search", "download", "auth")):
         raise ValidationError("A provider must implement at least one plugin")
     if "api" in config_keys and any(
         k in config_keys for k in ("search", "download", "auth")
     ):
         raise ValidationError(
             "A provider implementing an Api plugin must not implement any other "
             "type of plugin"
         )
Пример #3
0
def get_geometry(arguments):
    """Get geometry from arguments
    """

    geom = None

    if "bbox" in arguments or "box" in arguments:
        # get bbox
        request_bbox = arguments.pop("bbox", None) or arguments.pop(
            "box", None)
        if request_bbox and isinstance(request_bbox, str):
            request_bbox = request_bbox.split(",")
        elif request_bbox and not isinstance(request_bbox, list):
            raise ValidationError("bbox argument type should be Array")

        try:
            request_bbox_list = [float(coord) for coord in request_bbox]
        except ValueError as e:
            raise ValidationError("invalid bbox coordinate type: %s" % e)
        # lonmin, latmin, lonmax, latmax
        if len(request_bbox_list) < 4:
            raise ValidationError("invalid bbox length (%s) for bbox %s" %
                                  (len(request_bbox_list), request_bbox))
        geom = Polygon((
            (request_bbox_list[0], request_bbox_list[1]),
            (request_bbox_list[0], request_bbox_list[3]),
            (request_bbox_list[2], request_bbox_list[3]),
            (request_bbox_list[2], request_bbox_list[1]),
        ))

    if "intersects" in arguments and geom:
        new_geom = shape(arguments.pop("intersects"))
        if new_geom.intersects(geom):
            geom = new_geom.intersection(geom)
        else:
            geom = new_geom
    elif "intersects" in arguments:
        geom = shape(arguments.pop("intersects"))

    if "geom" in arguments and geom:
        new_geom = shape(arguments.pop("geom"))
        if new_geom.intersects(geom):
            geom = new_geom.intersection(geom)
        else:
            geom = new_geom
    elif "geom" in arguments:
        geom = shape(arguments.pop("geom"))

    return geom
Пример #4
0
def get_int(val):
    """Check if the input can be parsed as an integer"""

    if val:
        try:
            val = int(val)
        except ValueError as e:
            raise ValidationError("invalid input integer value: %s" % e)
    return val
Пример #5
0
def get_date(date):
    """Check if the input date can be parsed as a date"""

    if date:
        try:
            date = (dateutil.parser.parse(date).replace(
                tzinfo=tz.UTC).isoformat().replace("+00:00", ""))
        except ValueError as e:
            exc = ValidationError("invalid input date: %s" % e)
            raise exc
    return date
Пример #6
0
def search_bbox(request_bbox):
    """Transform request bounding box as a bbox suitable for eodag search"""

    eodag_bbox = None
    search_bbox_keys = ["lonmin", "latmin", "lonmax", "latmax"]

    if request_bbox:

        try:
            request_bbox_list = [
                float(coord) for coord in request_bbox.split(",")
            ]
        except ValueError as e:
            raise ValidationError("invalid box coordinate type: %s" % e)

        eodag_bbox = dict(zip(search_bbox_keys, request_bbox_list))
        if len(eodag_bbox) != 4:
            raise ValidationError("input box is invalid: %s" % request_bbox)

    return eodag_bbox
Пример #7
0
def filter_products(products, arguments, **kwargs):
    """Apply an eodag cruncher to filter products"""
    filter_name = arguments.get("filter")
    if filter_name:
        cruncher = crunchers.get(filter_name)
        if not cruncher:
            raise ValidationError("unknown filter name")

        cruncher_config = dict()
        for config_param in cruncher.config_params:
            config_param_value = arguments.get(config_param)
            if not config_param_value:
                raise ValidationError(
                    "filter additional parameters required: %s" %
                    ", ".join(cruncher.config_params))
            cruncher_config[config_param] = config_param_value

        try:
            products = products.crunch(cruncher.clazz(cruncher_config),
                                       **kwargs)
        except MisconfiguredError as e:
            raise ValidationError(e)

    return products
Пример #8
0
 def validate(config_keys):
     """Validate a :class:`~eodag.config.PluginConfig`"""
     if "type" not in config_keys:
         raise ValidationError(
             "A Plugin config must specify the Plugin it configures"
         )
Пример #9
0
    def __build_stac_catalog(self, catalogs=[]):
        """Build nested catalog from catalag list

        :param catalogs: catalogs list
        :type catalogs: list
        :returns: this catalog obj
        :rtype: :class:`eodag.stac.StacCatalog`
        """
        # update conf with user shp locations
        locations_config = self.build_locations_config()

        self.stac_config["catalogs"] = dict(
            copy.deepcopy(self.stac_config["catalogs"]), **locations_config)

        if len(catalogs) == 0:
            # Build root catalog combined with landing page
            self.__update_data_from_catalog_config(
                {
                    "model":
                    dict(
                        copy.deepcopy(self.stac_config["landing_page"]),
                        **{"provider": self.provider},
                    )
                }
                # {"model": copy.deepcopy(self.stac_config["landing_page"])}
            )

            # build children : product_types
            product_types_list = [
                pt for pt in self.eodag_api.list_product_types(
                    provider=self.provider) if pt["ID"] != GENERIC_PRODUCT_TYPE
            ]
            self.set_children([{
                "rel": "child",
                "href": self.url + "/" + product_type["ID"],
                "title": product_type["ID"],
            } for product_type in product_types_list])
        else:
            # use product_types_list as base for building nested catalogs
            self.__update_data_from_catalog_config(
                copy.deepcopy(
                    self.stac_config["catalogs"]["product_types_list"]))

        for idx, cat in enumerate(catalogs):
            if idx % 2 == 0:
                # even: cat is a filtering value ----------------------------------
                cat_data_name = self.catalog_config["child_key"]
                cat_data_value = cat

                # update data
                set_data_method_name = (
                    "set_stac_%s_by_id" % cat_data_name if "catalog_type"
                    not in self.stac_config["catalogs"][cat_data_name].keys()
                    else "set_stac_%s_by_id" %
                    self.stac_config["catalogs"][cat_data_name]["catalog_type"]
                )
                set_data_method = getattr(self, set_data_method_name)
                set_data_method(cat_data_value, catalog_name=cat_data_name)

                if idx == len(catalogs) - 1:
                    # build children : remaining filtering keys
                    remaining_catalogs_list = [
                        c for c in self.stac_config["catalogs"].keys()
                        # keep filters not used yet AND
                        if self.stac_config["catalogs"][c]["model"]["id"]
                        not in catalogs and (
                            # filters with no parent_key constraint (no key, or key=None) OR
                            "parent_key" not in self.stac_config["catalogs"][c]
                            or
                            not self.stac_config["catalogs"][c]["parent_key"]
                            # filters matching parent_key constraint
                            or self.stac_config["catalogs"][c]["parent_key"] ==
                            cat_data_name)
                        # AND filters that match parent attr constraint (locations)
                        and
                        ("parent" not in self.stac_config["catalogs"][c] or
                         not self.stac_config["catalogs"][c]["parent"]["key"]
                         or (self.stac_config["catalogs"][c]["parent"]["key"]
                             == cat_data_name and self.stac_config["catalogs"]
                             [c]["parent"]["attr"] == cat_data_value))
                    ]

                    self.set_children([{
                        "rel":
                        "child",
                        "href":
                        self.url + "/" +
                        self.stac_config["catalogs"][c]["model"]["id"],
                        "title":
                        str(self.stac_config["catalogs"][c]["model"]["id"]),
                    } for c in remaining_catalogs_list] + [{
                        "rel": "items",
                        "href": self.url + "/items",
                        "title": "items",
                    }])

            else:
                # odd: cat is a filtering key -------------------------------------
                try:
                    cat_key = [
                        c for c in self.stac_config["catalogs"].keys() if
                        self.stac_config["catalogs"][c]["model"]["id"] == cat
                    ][0]
                except IndexError:
                    raise ValidationError(
                        "Bad settings for %s in stac_config catalogs" % cat)
                cat_config = copy.deepcopy(
                    self.stac_config["catalogs"][cat_key])
                # update data
                self.__update_data_from_catalog_config(cat_config)

                # get filtering values list
                get_data_method_name = (
                    "get_stac_%s" % cat_key if "catalog_type"
                    not in self.stac_config["catalogs"][cat_key].keys() else
                    "get_stac_%s" %
                    self.stac_config["catalogs"][cat_key]["catalog_type"])
                get_data_method = getattr(self, get_data_method_name)
                cat_data_list = get_data_method(catalog_name=cat_key)

                if idx == len(catalogs) - 1:
                    # filtering values list as children (do not include items)
                    self.set_children([{
                        "rel":
                        "child",
                        "href":
                        self.url + "/" + str(filtering_data),
                        "title":
                        str(filtering_data),
                    } for filtering_data in cat_data_list])

        return self
Пример #10
0
def search_stac_items(url, arguments, root="/", catalogs=[], provider=None):
    """Get items collection dict for given catalogs list

    :param url: requested URL
    :type url: str
    :param arguments: request args
    :type arguments: dict
    :param root: API root
    :type root: str
    :param catalogs: catalogs list
    :type catalogs: list
    :param provider: chosen provider
    :type provider: str
    :returns: catalog dictionnary
    :rtype: dict
    """
    collections = arguments.get("collections", None)

    catalog_url = url.replace("/items", "")

    # use catalogs from path or if it is empty, collections from args
    if catalogs:
        result_catalog = StacCatalog(
            url=catalog_url,
            stac_config=stac_config,
            root=root,
            provider=provider,
            eodag_api=eodag_api,
            catalogs=catalogs,
        )
    elif collections:
        # get collection as product_type
        if isinstance(collections, str):
            collections = collections.split(",")
        elif not isinstance(collections, list):
            raise ValidationError("Collections argument type should be Array")

        result_catalog = StacCatalog(
            url=catalog_url,
            stac_config=stac_config,
            root=root,
            provider=provider,
            eodag_api=eodag_api,
            # handle only one collection per request (STAC allows multiple)
            catalogs=collections[0:1],
        )
        arguments.pop("collections")
    else:
        raise NoMatchingProductType(
            "No product_type found in collections argument")

    # get id
    ids = arguments.get("ids", None)
    if ids:
        # handle only one id per request (STAC allows multiple)
        arguments["id"] = ids.split(",")[0]
        arguments.pop("ids")

    # get datetime
    if "datetime" in arguments.keys():
        dtime_split = arguments.get("datetime", "").split("/")
        if len(dtime_split) > 1:
            arguments["dtstart"] = (dtime_split[0] if dtime_split[0] != ".."
                                    else datetime.datetime.min.isoformat() +
                                    "Z")
            arguments["dtend"] = (
                dtime_split[1]
                if dtime_split[1] != ".." else datetime.datetime.now(
                    datetime.timezone.utc).isoformat().replace("+00:00", "") +
                "Z")
        elif len(dtime_split) == 1:
            # same time for start & end if only one is given
            arguments["dtstart"], arguments["dtend"] = dtime_split[0:1] * 2
        arguments.pop("datetime")

    search_results = search_products(
        product_type=result_catalog.search_args["product_type"],
        arguments=dict(arguments, **result_catalog.search_args,
                       **{"unserialized": "true"}),
    )

    return StacItem(
        url=url,
        stac_config=stac_config,
        provider=provider,
        eodag_api=eodag_api,
        root=root,
    ).get_stac_items(
        search_results=search_results,
        catalog=dict(
            result_catalog.get_stac_catalog(),
            **{
                "url": result_catalog.url,
                "root": result_catalog.root
            },
        ),
    )