From 9aa19912e09e962f1e843633fd7e5d6c0a13d806 Mon Sep 17 00:00:00 2001 From: gantian127 Date: Fri, 14 Oct 2016 15:08:10 -0600 Subject: [PATCH 1/3] [#43] initial implementation to allow key value pair metadata for resource creation --- hs_restclient/__init__.py | 6 +++++- tests/test_hs_restclient.py | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/hs_restclient/__init__.py b/hs_restclient/__init__.py index 3a23526..f3d84fd 100644 --- a/hs_restclient/__init__.py +++ b/hs_restclient/__init__.py @@ -592,7 +592,7 @@ def getResourceTypes(self): def createResource(self, resource_type, title, resource_file=None, resource_filename=None, abstract=None, keywords=None, edit_users=None, view_users=None, edit_groups=None, view_groups=None, - metadata=None, progress_callback=None): + metadata=None, extra_metadata=None, progress_callback=None): """ Create a new resource. :param resource_type: string representing the a HydroShare resource type recognized by this @@ -611,6 +611,7 @@ def createResource(self, resource_type, title, resource_file=None, resource_file :param edit_groups: list of HydroShare group names that will be given edit permissions :param view_groups: list of HydroShare group names that will be given view permissions :param metadata: json string data for each of the metadata elements + :param extra_metadata: json string data for key/value pair metadata elements defined by user :param progress_callback: user-defined function to provide feedback to the user about the progress of the upload of resource_file. For more information, see: http://toolbelt.readthedocs.org/en/latest/uploading-data.html#monitoring-your-streaming-multipart-upload @@ -651,6 +652,9 @@ def createResource(self, resource_type, title, resource_file=None, resource_file if metadata: params['metadata'] = metadata + if extra_metadata: + params['extra_metadata'] = extra_metadata + if resource_file: close_fd = self._prepareFileForUpload(params, resource_file, resource_filename) diff --git a/tests/test_hs_restclient.py b/tests/test_hs_restclient.py index 96868dc..b8064d6 100644 --- a/tests/test_hs_restclient.py +++ b/tests/test_hs_restclient.py @@ -117,10 +117,12 @@ def test_create_get_delete_resource(self): {'creator': {'name': 'John Smith'}}, {'contributor': {'name': 'Lisa Miller'}}]) + extra_metadata = json.dumps({'latitude': '40', 'longitude': '-111'}) + with HTTMock(mocks.hydroshare.createResourceCRUD): # Create newres = hs.createResource(rtype, title, resource_file=fname, keywords=keywords, - abstract=abstract, metadata=metadata) + abstract=abstract, metadata=metadata, extra_metadata=extra_metadata) self.assertIsNotNone(newres) sysmeta = hs.getSystemMetadata(newres) self.assertEqual(sysmeta['resource_id'], newres) From 06209183fad0475e53b54ee56f937d655c97f75d Mon Sep 17 00:00:00 2001 From: pkdash Date: Tue, 6 Dec 2016 16:38:15 -0700 Subject: [PATCH 2/3] [#46] added function to retrieve resourcemap xml document --- hs_restclient/__init__.py | 81 ++++++++++++++++++- tests/mocks/hydroshare.py | 12 +++ tests/test_hs_restclient.py | 9 +++ .../map/resourcemap.xml | 51 ++++++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 tests/www.hydroshare.org/hsapi/resource/6dbb0dfb8f3a498881e4de428cb1587c/map/resourcemap.xml diff --git a/hs_restclient/__init__.py b/hs_restclient/__init__.py index f3d84fd..d6f778f 100644 --- a/hs_restclient/__init__.py +++ b/hs_restclient/__init__.py @@ -472,6 +472,85 @@ def getScienceMetadata(self, pid): return str(r.content) + def getResourceMap(self, pid): + """ Get resource map metadata for a resource + + :param pid: The HydroShare ID of the resource + :raises: HydroShareNotAuthorized if the user is not authorized to view the metadata. + :raises: HydroShareNotFound if the resource was not found. + :raises: HydroShareHTTPException to signal an HTTP error. + :return: A string representing the XML+RDF serialization of resource map metadata. + Example of data returned: + + + + + Foresite Toolkit (Python) + foresite@googlegroups.com + + + Generic + http://www.hydroshare.org/terms + + + http://www.hydroshare.org/resource/03c862ccf17b4853ac4288d63ab2d766/data/resourcemap.xml#aggregation + text/plain + + + 03c862ccf17b4853ac4288d63ab2d766 + + + application/rdf+xml + + 2016-11-29T16:17:52Z + 2016-11-29T16:17:52Z + + + http://www.openarchives.org/ore/terms/ + ResourceMap + + + http://www.hydroshare.org/resource/03c862ccf17b4853ac4288d63ab2d766/data/resourcemetadata.xml + Gen Res-1 + + http://www.hydroshare.org/resource/03c862ccf17b4853ac4288d63ab2d766/data/resourcemap.xml + + + + + + http://www.hydroshare.org/resource/03c862ccf17b4853ac4288d63ab2d766/data/resourcemap.xml#aggregation + http://www.hydroshare.org/resource/03c862ccf17b4853ac4288d63ab2d766/data/resourcemap.xml#aggregation + Dublin Core science metadata document describing the HydroShare resource + application/rdf+xml + + + Aggregation + http://www.openarchives.org/ore/terms/ + + + """ + url = "{url_base}/resource/{pid}/map/".format(url_base=self.url_base, + pid=pid) + r = self._request('GET', url) + if r.status_code != 200: + if r.status_code == 403: + raise HydroShareNotAuthorized(('GET', url)) + elif r.status_code == 404: + raise HydroShareNotFound((pid,)) + else: + raise HydroShareHTTPException((url, 'GET', r.status_code)) + + return str(r.content) + def getResource(self, pid, destination=None, unzip=False, wait_for_bag_creation=True): """ Get a resource in BagIt format @@ -627,7 +706,7 @@ def createResource(self, resource_type, title, resource_file=None, resource_file close_fd = False - if not resource_type in self.resource_types: + if resource_type not in self.resource_types: raise HydroShareArgumentException("Resource type {0} is not among known resources: {1}".format(resource_type, ", ".join([r for r in self.resource_types]))) diff --git a/tests/mocks/hydroshare.py b/tests/mocks/hydroshare.py index da6e89f..76db9a6 100644 --- a/tests/mocks/hydroshare.py +++ b/tests/mocks/hydroshare.py @@ -219,6 +219,18 @@ def scimeta_get(url, request): return response(404, {}, HEADERS, None, 5, request) return response(200, content, HEADERS, None, 5, request) +@urlmatch(netloc=NETLOC, method=GET) +def resourcemap_get(url, request): + file_path = url.netloc + url.path + 'resourcemap.xml' + + try: + content = Resource(file_path).get() + except EnvironmentError: + # catch any environment errors (i.e. file does not exist) and return a + # 404. + return response(404, {}, HEADERS, None, 5, request) + return response(200, content, HEADERS, None, 5, request) + @urlmatch(netloc=NETLOC, method=GET) def resourceFileList_get(url, request): if url.query == '': diff --git a/tests/test_hs_restclient.py b/tests/test_hs_restclient.py index b8064d6..dc59acd 100644 --- a/tests/test_hs_restclient.py +++ b/tests/test_hs_restclient.py @@ -195,6 +195,15 @@ def test_get_scimeta(self): self.assertTrue(scimeta.find("""""") != -1) +class TestGetResourceMap(unittest.TestCase): + + @with_httmock(mocks.hydroshare.resourcemap_get) + def test_get_resourcemap(self): + hs = HydroShare() + resourcemap = hs.getResourceMap('6dbb0dfb8f3a498881e4de428cb1587c') + self.assertTrue(resourcemap.find("""""") != -1) + + class TestGetResourceFileList(unittest.TestCase): def setUp(self): diff --git a/tests/www.hydroshare.org/hsapi/resource/6dbb0dfb8f3a498881e4de428cb1587c/map/resourcemap.xml b/tests/www.hydroshare.org/hsapi/resource/6dbb0dfb8f3a498881e4de428cb1587c/map/resourcemap.xml new file mode 100644 index 0000000..a282ff0 --- /dev/null +++ b/tests/www.hydroshare.org/hsapi/resource/6dbb0dfb8f3a498881e4de428cb1587c/map/resourcemap.xml @@ -0,0 +1,51 @@ + + + + + RHESSys model of Dead Run 5 watershed, Baltimore County, Maryland, USA (with rain gardens) + + + + 3-m spatial resolution RHESSys model for Dead Run 5 watershed in Baltimore County, Maryland. This model contains example implementation of rain gardens. + + + + + Brian Miles + 1 + brian_miles@unc.edu + + + + + 2015-07-27T18:35:27.954135+00:00 + + + + + 2015-08-07T13:44:44.757870+00:00 + + + application/zip + + + http://www.hydroshare.org/resource/6dbb0dfb8f3a498881e4de428cb1587c + + + eng + + + This resource is shared under the Creative Commons Attribution CC BY. + + + + RHESSys + Baltimore Ecosystem Study + green infrastructure + + + Generic + http://www.hydroshare.org/terms + + From 8ebc4f0302fec0a1106db72b432cbb833fd4cb05 Mon Sep 17 00:00:00 2001 From: pkdash Date: Wed, 7 Dec 2016 12:58:48 -0700 Subject: [PATCH 3/3] 1.2.5 release --- RELEASE_NOTES.md | 9 +++++++++ docs/index.rst | 15 ++++++++++++++- hs_restclient/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1fd1f6e..5453b3a 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,12 @@ +# 1.2.5 - 12/7/2016 + - Add ability to supply key/value metadata (in addition to 'title', 'abstract', 'keywords', and 'metadata') + to createResource() + - Add getResourceMap (/hsapi/resource/\map/) + +# 1.2.4 - 9/2/2016 + - Add support for async resource bag (BagIt archive) creation prior to downloading + the bag file in getResource() + # 1.2.3 - 7/12/2016 - Add ability to supply metadata (in addition to 'title', 'abstract', and 'keywords') to createResource() diff --git a/docs/index.rst b/docs/index.rst index 1c84b17..7d18c7e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -164,7 +164,8 @@ To create a resource: >>> rtype = 'GenericResource' >>> fpath = '/path/to/a/file' >>> metadata = '[{"coverage":{"type":"period", "value":{"start":"01/01/2000", "end":"12/12/2010"}}}, {"creator":{"name":"John Smith"}}, {"creator":{"name":"Lisa Miller"}}]' - >>> resource_id = hs.createResource(rtype, title, resource_file=fpath, keywords=keywords, abstract=abstract, metadata=metadata) + >>> extra_metadata = '{"key-1": "value-1", "key-2": "value-2"}' + >>> resource_id = hs.createResource(rtype, title, resource_file=fpath, keywords=keywords, abstract=abstract, metadata=metadata, extra_metadata=extra_metadata) To make a resource public: @@ -204,7 +205,19 @@ To delete a file from a resource: >>> fname = 'somefile.txt' >>> resource_id = hs.deleteResourceFile('ID OF RESOURCE GOES HERE', fname) +To get resource map xml data for a resource: + >>> from hs_restclient import HydroShare, HydroShareAuthBasic + >>> auth = HydroShareAuthBasic(username='myusername', password='mypassword') + >>> hs = HydroShare(auth=auth) + >>> resource_map_xml = hs.getResourceMap('ID OF RESOURCE GOES HERE') + +To get science xml data for a resource: + + >>> from hs_restclient import HydroShare, HydroShareAuthBasic + >>> auth = HydroShareAuthBasic(username='myusername', password='mypassword') + >>> hs = HydroShare(auth=auth) + >>> science_metadata_xml = hs.getScienceMetadata('ID OF RESOURCE GOES HERE') Index ----- diff --git a/hs_restclient/__init__.py b/hs_restclient/__init__.py index d6f778f..1db3a5b 100644 --- a/hs_restclient/__init__.py +++ b/hs_restclient/__init__.py @@ -5,7 +5,7 @@ """ __title__ = 'hs_restclient' -__version__ = '1.2.3' +__version__ = '1.2.5' import os diff --git a/setup.py b/setup.py index 53ac6bd..e2f55c7 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html - version='1.2.3', + version='1.2.5', description='HydroShare REST API client library', long_description=long_description,