-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Metadata - Bulk requests - Merge #141
- Loading branch information
Showing
20 changed files
with
1,083 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,9 @@ metadata.json | |
# logs | ||
*.log.* | ||
|
||
# mypy | ||
.mypy_cache | ||
|
||
# PTVS | ||
*.ptvs | ||
*.vs | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
# -*- coding: UTF-8 -*- | ||
#! python3 # noqa E265 | ||
|
||
""" | ||
Isogeo API v1 - API Route for bulk update on resources (= Metadata) | ||
""" | ||
|
||
# ############################################################################# | ||
# ########## Libraries ############# | ||
# ################################## | ||
|
||
# Standard library | ||
import logging | ||
from collections import defaultdict | ||
|
||
# submodules | ||
from isogeo_pysdk.checker import IsogeoChecker | ||
from isogeo_pysdk.decorators import ApiDecorators | ||
from isogeo_pysdk.enums import BulkActions, BulkTargets | ||
from isogeo_pysdk.models import BulkReport, BulkRequest, Metadata | ||
from isogeo_pysdk.utils import IsogeoUtils | ||
|
||
# ############################################################################# | ||
# ########## Globals ############### | ||
# ################################## | ||
|
||
logger = logging.getLogger(__name__) | ||
checker = IsogeoChecker() | ||
utils = IsogeoUtils() | ||
|
||
|
||
# ############################################################################# | ||
# ########## Classes ############### | ||
# ################################## | ||
class ApiBulk: | ||
"""Routes as methods of Isogeo API used to mass edition of metadatas (resources). | ||
:Example: | ||
.. code-block:: python | ||
# retrieve objects to be associated | ||
catalog_1 = isogeo.catalog.get( | ||
workgroup_id={WORKGROUP_UUID}, | ||
catalog_id={CATALOG_UUID_1}, | ||
) | ||
catalog_2 = isogeo.catalog.get( | ||
workgroup_id={WORKGROUP_UUID}, | ||
catalog_id={CATALOG_UUID_2}, | ||
) | ||
keyword = isogeo.keyword.get(keyword_id={KEYWORD_UUID},) | ||
# along the script, prepare the bulk requests | ||
isogeo.metadata.bulk.prepare( | ||
metadatas=( | ||
{METADATA_UUID_1}, | ||
{METADATA_UUID_2}, | ||
), | ||
action="add", | ||
target="catalogs", | ||
models=(catalog_1, catalog_2), | ||
) | ||
isogeo.metadata.bulk.prepare( | ||
metadatas=( | ||
{METADATA_UUID_1}, | ||
), | ||
action="add", | ||
target="keywords", | ||
models=(keyword,), | ||
) | ||
# send the one-shot request | ||
isogeo.metadata.bulk.send() | ||
""" | ||
|
||
BULK_DATA = [] | ||
|
||
def __init__(self, api_client=None): | ||
if api_client is not None: | ||
self.api_client = api_client | ||
|
||
# store API client (Request [Oauthlib] Session) and pass it to the decorators | ||
self.api_client = api_client | ||
ApiDecorators.api_client = api_client | ||
|
||
# ensure platform to request | ||
( | ||
self.platform, | ||
self.api_url, | ||
self.app_url, | ||
self.csw_url, | ||
self.mng_url, | ||
self.oc_url, | ||
self.ssl, | ||
) = utils.set_base_url(self.api_client.platform) | ||
|
||
# initialize | ||
super(ApiBulk, self).__init__() | ||
|
||
def prepare( | ||
self, metadatas: tuple, action: str, target: str, models: tuple | ||
) -> BulkRequest: | ||
"""Prepare requests to be sent later in one shot. | ||
:param tuple metadatas: tuple of metadatas UUIDs or Metadatas to be updated | ||
:param str action: type of action to perform on metadatas. See: `isogeo_pysdk.enums.bulk_actions`. | ||
:param str target: kind of object to add/delete/update to the metadatas. See: `isogeo_pysdk.enums.bulk_targets`. | ||
:param tuple models: tuple of objects to be associated with the metadatas. | ||
""" | ||
# instanciate a new Bulk REquest object | ||
prepared_request = BulkRequest() | ||
|
||
# ensure lowercase | ||
prepared_request.action = action.lower() | ||
prepared_request.target = target.lower() | ||
|
||
# check metadatas uuid | ||
metadatas = list(metadatas) | ||
for i in metadatas: | ||
if isinstance(i, str) and not checker.check_is_uuid(i): | ||
logger.error("Not a correct UUID: {}".format(i)) | ||
metadatas.remove(i) | ||
elif isinstance(i, Metadata) and not checker.check_is_uuid(i._id): | ||
print("bad md") | ||
logger.error( | ||
"Metadata passed but with an incorrect UUID: {}".format(i._id) | ||
) | ||
metadatas.remove(i) | ||
elif isinstance(i, Metadata) and checker.check_is_uuid(i._id): | ||
logger.debug("Metadata passed, extracting the UUID: {}".format(i._id)) | ||
metadatas.append(i._id) | ||
metadatas.remove(i) | ||
else: | ||
continue | ||
|
||
# add it to the prepared request query | ||
prepared_request.query = {"ids": metadatas} | ||
|
||
# check passed objects | ||
obj_type = models[0] | ||
if not all([isinstance(obj, type(obj_type)) for obj in models]): | ||
raise TypeError( | ||
"Models must contain an unique type of objects. First found: {}".format( | ||
obj_type | ||
) | ||
) | ||
|
||
prepared_request.model = [obj.to_dict() for obj in models] | ||
|
||
# add it to be sent later | ||
self.BULK_DATA.append(prepared_request.to_dict()) | ||
|
||
return prepared_request | ||
|
||
@ApiDecorators._check_bearer_validity | ||
def send(self) -> list: | ||
"""Send prepared BULK_DATA to the `POST BULK resources/`.""" | ||
|
||
# build request url | ||
url_metadata_bulk = utils.get_request_base_url(route="resources") | ||
|
||
# request | ||
req_metadata_bulk = self.api_client.post( | ||
url=url_metadata_bulk, | ||
json=self.BULK_DATA, | ||
headers=self.api_client.header, | ||
proxies=self.api_client.proxies, | ||
stream=True, | ||
verify=self.api_client.ssl, | ||
timeout=self.api_client.timeout, | ||
) | ||
|
||
# checking response | ||
req_check = checker.check_api_response(req_metadata_bulk) | ||
if isinstance(req_check, tuple): | ||
return req_check | ||
|
||
# empty bulk data | ||
self.BULK_DATA.clear() | ||
|
||
return [BulkReport(**req) for req in req_metadata_bulk.json()] | ||
|
||
|
||
# ############################################################################## | ||
# ##### Stand alone program ######## | ||
# ################################## | ||
if __name__ == "__main__": | ||
"""standalone execution.""" | ||
sample_test = ApiBulk() | ||
print(sample_test) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# -*- coding: UTF-8 -*- | ||
#! python3 # noqa E265 | ||
|
||
""" | ||
Isogeo API v1 - Enums for Resource entity accepted kinds | ||
See: http://help.isogeo.com/api/complete/index.html#definition-application | ||
""" | ||
|
||
# ############################################################################# | ||
# ########## Libraries ############# | ||
# ################################## | ||
|
||
# standard library | ||
from enum import Enum, auto | ||
|
||
|
||
# ############################################################################# | ||
# ########## Classes ############### | ||
# ################################## | ||
class BulkActions(Enum): | ||
"""Closed list of accepted Application (metadata subresource) kinds in Isogeo API. | ||
:Example: | ||
>>> # parse members and values | ||
>>> print("{0:<30} {1:>20}".format("Enum", "Value")) | ||
>>> for md_kind in BulkActions: | ||
>>> print("{0:<30} {1:>20}".format(md_kind, md_kind.value)) | ||
Enum Value | ||
BulkActions.add 1 | ||
BulkActions.delete 2 | ||
BulkActions.update 3 | ||
>>> # check if a var is an accepted value | ||
>>> print("add" in BulkActions.__members__) | ||
True | ||
>>> print("Delete" in BulkActions.__members__) # case sensitive | ||
False | ||
>>> print("truncate" in BulkActions.__members__) | ||
False | ||
See: https://docs.python.org/3/library/enum.html | ||
""" | ||
|
||
add = auto() | ||
delete = auto() | ||
update = auto() | ||
|
||
|
||
# ############################################################################## | ||
# ##### Stand alone program ######## | ||
# ################################## | ||
if __name__ == "__main__": | ||
"""standalone execution.""" | ||
print("{0:<30} {1:>20}".format("Enum", "Value")) | ||
for md_kind in BulkActions: | ||
print("{0:<30} {1:>20}".format(md_kind, md_kind.value)) | ||
|
||
print(len(BulkActions)) | ||
|
||
print("add" in BulkActions.__members__) | ||
print("Delete" in BulkActions.__members__) | ||
print("truncate" in BulkActions.__members__) |
Oops, something went wrong.