def upload_epanet_model(request): return_obj = { 'success': False, 'message': None, 'results': "", } if request.is_ajax() and request.method == 'POST': try: hs = get_oauth_hs(request) except: hs = HydroShare() model_title = request.POST['model_title'] resource_filename = model_title + ".inp" abstract = request.POST[ 'model_description'] + '\n{%EPANET Model Repository%}' title = model_title user_keywords = ["EPANET_2.0"] for keyword in request.POST['model_keywords'].split(","): user_keywords.append(keyword) keywords = (tuple(user_keywords)) rtype = 'ModelInstanceResource' extra_metadata = '{"modelProgram": "EPANET_2.0"}' fd, path = tempfile.mkstemp() with os.fdopen(fd, 'w') as tmp: tmp.write(request.POST['model_file']) fpath = path metadata = '[{"creator":{"name":"' + hs.getUserInfo( )['first_name'] + ' ' + hs.getUserInfo()['last_name'] + '"}}]' resource_id = hs.createResource(rtype, title, resource_file=fpath, resource_filename=resource_filename, keywords=keywords, abstract=abstract, metadata=metadata, extra_metadata=extra_metadata) hs.setAccessRules(resource_id, public=True) return_obj['results'] = resource_id return_obj['success'] = True else: return_obj['message'] = message_template_wrong_req_method.format( method="GET") return JsonResponse(return_obj)
def test_create_get_delete_resource(self): hs = HydroShare() abstract = 'Abstract for hello world resource' title = 'Minimal hello world resource' keywords = ('hello', 'world') rtype = 'GenericResource' fname = 'mocks/data/minimal_resource_file.txt' with HTTMock(mocks.hydroshare.createResourceCRUD): # Create newres = hs.createResource(rtype, title, resource_file=fname, keywords=keywords, abstract=abstract) self.assertIsNotNone(newres) sysmeta = hs.getSystemMetadata(newres) self.assertEqual(sysmeta['resource_id'], newres) self.assertEqual(sysmeta['resource_type'], rtype) self.assertFalse(sysmeta['public']) with HTTMock(mocks.hydroshare.accessRules_put): # Make resource public hs.setAccessRules(newres, public=True) sysmeta = hs.getSystemMetadata(newres) self.assertTrue(sysmeta['public']) with HTTMock(mocks.hydroshare.createResourceCRUD): # Get tmpdir = tempfile.mkdtemp() hs.getResource(newres, destination=tmpdir) with ZipFile( os.path.join(tmpdir, '511debf8858a4ea081f78d66870da76c.zip'), 'r') as zfile: self.assertTrue( '511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt' in zfile.namelist()) downloaded = zfile.open( '511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt', 'r') original = open('mocks/data/minimal_resource_file.txt', 'r') self.assertEqual(downloaded.read(), original.read()) downloaded.close() original.close() shutil.rmtree(tmpdir) # Delete delres = hs.deleteResource(newres) self.assertEqual(delres, newres)
def test_create_get_delete_resource(self): hs = HydroShare(prompt_auth=False) abstract = 'Abstract for hello world resource' title = 'Minimal hello world resource' keywords = ('hello', 'world') rtype = 'GenericResource' fname = 'mocks/data/minimal_resource_file.txt' metadata = json.dumps([{'coverage': {'type': 'period', 'value': {'start': '01/01/2000', 'end': '12/12/2010'}}}, {'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, extra_metadata=extra_metadata) self.assertIsNotNone(newres) sysmeta = hs.getSystemMetadata(newres) self.assertEqual(sysmeta['resource_id'], newres) self.assertEqual(sysmeta['resource_type'], rtype) self.assertFalse(sysmeta['public']) with HTTMock(mocks.hydroshare.accessRules_put): # Make resource public hs.setAccessRules(newres, public=True) sysmeta = hs.getSystemMetadata(newres) self.assertTrue(sysmeta['public']) with HTTMock(mocks.hydroshare.createResourceCRUD): # Get tmpdir = tempfile.mkdtemp() hs.getResource(newres, destination=tmpdir) with ZipFile(os.path.join(tmpdir, '511debf8858a4ea081f78d66870da76c.zip'), 'r') as zfile: self.assertTrue('511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt' in zfile.namelist()) downloaded = zfile.open('511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt', 'r') original = open('mocks/data/minimal_resource_file.txt', 'rb') self.assertEqual(downloaded.read(), original.read()) downloaded.close() original.close() shutil.rmtree(tmpdir) # Delete delres = hs.deleteResource(newres) self.assertEqual(delres, newres)
def test_create_get_delete_resource(self): hs = HydroShare() abstract = 'Abstract for hello world resource' title = 'Minimal hello world resource' keywords = ('hello', 'world') rtype = 'GenericResource' fname = 'mocks/data/minimal_resource_file.txt' with HTTMock(mocks.hydroshare.createResourceCRUD): # Create newres = hs.createResource(rtype, title, resource_file=fname, keywords=keywords, abstract=abstract) self.assertIsNotNone(newres) sysmeta = hs.getSystemMetadata(newres) self.assertEqual(sysmeta['resource_id'], newres) self.assertEqual(sysmeta['resource_type'], rtype) self.assertFalse(sysmeta['public']) with HTTMock(mocks.hydroshare.accessRules_put): # Make resource public hs.setAccessRules(newres, public=True) sysmeta = hs.getSystemMetadata(newres) self.assertTrue(sysmeta['public']) with HTTMock(mocks.hydroshare.createResourceCRUD): # Get tmpdir = tempfile.mkdtemp() hs.getResource(newres, destination=tmpdir) with ZipFile(os.path.join(tmpdir, '511debf8858a4ea081f78d66870da76c.zip'), 'r') as zfile: self.assertTrue('511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt' in zfile.namelist()) downloaded = zfile.open('511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt', 'r') original = open('mocks/data/minimal_resource_file.txt', 'r') self.assertEqual(downloaded.read(), original.read()) downloaded.close() original.close() shutil.rmtree(tmpdir) # Delete delres = hs.deleteResource(newres) self.assertEqual(delres, newres)
def test_create_get_delete_resource(self): hs = HydroShare(prompt_auth=False) abstract = 'Abstract for hello world resource' title = 'Minimal hello world resource' keywords = ('hello', 'world') rtype = 'GenericResource' fname = 'mocks/data/minimal_resource_file.txt' metadata = json.dumps([{ 'coverage': { 'type': 'period', 'value': { 'start': '01/01/2000', 'end': '12/12/2010' } } }, { '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, extra_metadata=extra_metadata) self.assertIsNotNone(newres) sysmeta = hs.getSystemMetadata(newres) self.assertEqual(sysmeta['resource_id'], newres) self.assertEqual(sysmeta['resource_type'], rtype) self.assertFalse(sysmeta['public']) with HTTMock(mocks.hydroshare.accessRules_put): # Make resource public hs.setAccessRules(newres, public=True) sysmeta = hs.getSystemMetadata(newres) self.assertTrue(sysmeta['public']) with HTTMock(mocks.hydroshare.createResourceCRUD): # Get tmpdir = tempfile.mkdtemp() hs.getResource(newres, destination=tmpdir) with ZipFile( os.path.join(tmpdir, '511debf8858a4ea081f78d66870da76c.zip'), 'r') as zfile: self.assertTrue( '511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt' in zfile.namelist()) downloaded = zfile.open( '511debf8858a4ea081f78d66870da76c/data/contents/minimal_resource_file.txt', 'r') original = open('mocks/data/minimal_resource_file.txt', 'rb') self.assertEqual(downloaded.read(), original.read()) downloaded.close() original.close() shutil.rmtree(tmpdir) # Delete hs.deleteResource(newres)
class ResourceManager: """ Class that defines a handler for working with all of a user's resources. This is where they will be able to delete a resource, create a new one, or just get the list of a user's resources in hydroshare or jupyterhub. """ def __init__(self): """Makes an output folder for storing HS files locally, if none exists, and sets up authentication on hydroshare API. """ config = get_config_values(['dataPath', 'hydroShareHostname']) self.hs_hostname = 'www.hydroshare.org' # TODO: Rename to hydroshare_resource_data self.output_folder = Path('local_hs_resources') if config: if 'hydroShareHostname' in config: self.hs_hostname = config['hydroShareHostname'] if 'dataPath' in config: self.output_folder = Path(config['dataPath']) if not self.output_folder.is_dir(): # Let any exceptions that occur bubble up self.output_folder.mkdir(parents=True) self.hs_api_conn = None # Use 'authenticate' to initialize self.username = None def authenticate(self, username=None, password=None, save=False): """ Attempts to authenticate with HydroShare. :param username: the user's HydroShare username :type username: str :param password: the user's HydroShare password :type password: str :param save: whether or not to save the credentials to the config file if the authentication succeeds :type save: bool :return: the user's information (name, email, etc) from HydroShare if successful, None otherwise """ if not username or not password: # Check the config file for a username and password config = get_config_values(['u', 'p']) if not config or 'u' not in config or 'p' not in config: return None # No passed credentials and no saved credentials -- can't authenticate username = config['u'] password = base64.b64decode(config['p']).decode('utf-8') # Try to authenticate auth = HydroShareAuthBasic(username=username, password=password) self.hs_api_conn = HydroShare(auth=auth, hostname=self.hs_hostname) try: user_info = self.hs_api_conn.getUserInfo() self.username = user_info.get('username') except HydroShareHTTPException as e: if e.status_code == 401: # Unauthorized return None # Authentication failed raise e # Some other error -- bubble it up # Authentication succeeded if save: # Save the username and password saved_successfully = set_config_values({ 'u': username, 'p': str( base64.b64encode( password.encode('utf-8')).decode('utf-8')), }) if saved_successfully: logging.info( 'Successfully saved HydroShare credentials to config file.' ) return user_info # Authenticated successfully def is_authenticated(self): if self.hs_api_conn is None: self.authenticate() return self.hs_api_conn is not None def save_resource_locally(self, res_id): """ Downloads a resource to the local filesystem if a copy does not already exist locally :param res_id: the resource ID :type res_id: str """ # Get resource from HS if it doesn't already exist locally if not (self.output_folder / res_id).exists(): logging.info(f"Downloading resource {res_id} from HydroShare...") self.hs_api_conn.getResource(res_id, destination=self.output_folder, unzip=True) def get_user_info(self): """Gets information about the user currently logged into HydroShare """ user_info = None error = None try: user_info = self.hs_api_conn.getUserInfo() except HydroShareHTTPException as e: if e.status_code == 401: # Unauthorized error = HYDROSHARE_AUTHENTICATION_ERROR else: error = { 'type': 'GenericHydroShareHTTPException', 'message': e.status_msg, } return user_info, error def delete_resource_locally(self, res_id): """ Attempts to delete the local copy of the resource files from the disk :param res_id: the ID of the resource to delete :type res_id: str """ resource_path = self.output_folder / res_id if not resource_path.exists(): return { 'type': 'FileNotFoundError', 'message': f'Could not find a local copy of resource {res_id} to delete.', } try: shutil.rmtree(str(resource_path)) except IOError as e: return { 'type': 'IOError', 'message': f'Something went wrong. Could not delete resource {res_id}.', } return None # No error def delete_resource_from_hs(self, res_id): try: self.hs_api_conn.deleteResource(res_id) except HydroShareHTTPException as e: return { 'type': 'GenericHydroShareHTTPException', 'message': e.status_msg, } return None # No error def get_local_resource_ids(self): """ Gets a list of IDs of all the resources saved locally :return a set of strings containing all of the resource IDs :rtype set<str> """ return set(map(lambda p: p.name, self.output_folder.glob('*'))) def get_list_of_user_resources(self): # TODO: speed this up """Gets list of all the resources for the logged in user, including those stored on hydroshare and those stored locally on jupyterhub and information about each one including whether HS ones are stored locally. Assumes there are no local resources that don't exist in HS """ error = None resources = {} # Get local res_ids self.local_res_ids = self.get_local_resource_ids() # Get the user's resources from HydroShare user_hs_resources = self.hs_api_conn.resources(owner=self.username) try: hs_resources = list( user_hs_resources) # Resources can't be listed if auth fails except AttributeError: return None, HYDROSHARE_AUTHENTICATION_ERROR for res in hs_resources: res_id = res['resource_id'] resources[res_id] = { 'abstract': res.get('abstract'), 'authors': res.get('authors'), 'creator': res.get('creator'), 'created': res.get('date_created'), 'lastUpdated': res.get('date_last_updated'), 'localCopyExists': res_id in self.local_res_ids, 'localFiles': res.get('localFiles'), 'id': res_id, 'isPublic': res.get('public'), 'published': res.get('published'), 'status': res.get('status'), 'title': res.get('resource_title'), 'url': res.get('resource_url'), } return list(resources.values()), error def create_HS_resource(self, resource_title, creators, abstract="", privacy="Private"): """ Creates a hydroshare resource from the metadata specified in a dict using the given resource_title and specified creators """ error = None resource_id = None # Type errors for resource_title and creators if not isinstance(resource_title, str): error = { 'type': 'IncorrectType', 'message': 'Resource title should be a string.' } return resource_id, error if not isinstance(creators, list) or not all( isinstance(creator, str) for creator in creators): error = { 'type': 'IncorrectType', 'message': '"Creators" object should be a list of strings.' } return resource_id, error if abstract is None: abstract = "" if privacy == "Public": public = True else: public = False meta_metadata = [] for creator in creators: meta_metadata.append({"creator": {"name": creator}}) meta_metadata = json.dumps(meta_metadata) metadata = { 'abstract': abstract, 'title': resource_title, 'keywords': (), 'rtype': 'GenericResource', 'fpath': '', 'metadata': meta_metadata, 'extra_metadata': '' } resource_id = '' try: resource_id = self.hs_api_conn.createResource( metadata['rtype'], metadata['title'], resource_file=metadata['fpath'], keywords=metadata['keywords'], abstract=metadata['abstract'], metadata=metadata['metadata'], extra_metadata=metadata['extra_metadata']) self.hs_api_conn.setAccessRules(resource_id, public=public) except: error = { 'type': 'UnknownError', 'message': 'Unable to create resource.' } return resource_id, error def create_copy_of_resource_in_hs(self, src_res_id): """ Makes a copy of a resource in HydroShare and updates the local copy of the old resource to point to then ew copy. :param src_res_id: the ID of the resource in HydroShare to duplicate :type src_res_id: str :returns the new resource ID """ response = self.hs_api_conn.resource(src_res_id).copy() new_id = response.content.decode("utf-8") # b'id' is_local = src_res_id in self.local_res_ids # if a local version exists under the old resource ID, rename it to point to the new one if is_local: og_path = self.output_folder / src_res_id / src_res_id new_path = self.output_folder / new_id / new_id shutil.move(str(og_path), str(new_path)) # Change name to 'Copy of []' title = self.hs_api_conn.getScienceMetadata(new_id)['title'] new_title = "Copy of " + title self.hs_api_conn.updateScienceMetadata(new_id, {"title": new_title}) return new_id def get_archive_message(self): """ Gets the message to display on the resource page prompting the user to archive their resources to HydroShare """ loaded_archive_message = get_config_values(['archiveMessage']) if loaded_archive_message and loaded_archive_message['archiveMessage']: archive_message = loaded_archive_message['archiveMessage'] else: archive_message = input("Please enter the archive message: ") #Save the archive message saved_successfully = set_config_values({ 'archiveMessage': archive_message, }) if saved_successfully: logging.info( 'Successfully saved archive message to config file.') return archive_message
class HydroShareUtility: def __init__(self): self.client = None # type: HydroShare self.auth = None self.user_info = None self.re_period = re.compile(r'(?P<tag_start>^start=)(?P<start>[0-9-]{10}T[0-9:]{8}).{2}(?P<tag_end>end=)' r'(?P<end>[0-9-]{10}T[0-9:]{8}).{2}(?P<tag_scheme>scheme=)(?P<scheme>.+$)', re.I) self.xml_ns = { 'dc': "http://purl.org/dc/elements/1.1/", 'dcterms': "http://purl.org/dc/terms/", 'hsterms': "http://hydroshare.org/terms/", 'rdf': "http://www.w3.org/1999/02/22-rdf-syntax-ns#", 'rdfs1': "http://www.w3.org/2001/01/rdf-schema#"} self.time_format = '%Y-%m-%dT%H:%M:%S' self.xml_coverage = 'start={start}; end={end}; scheme=W3C-DTF' def authenticate(self, username, password, client_id=None, client_secret=None): """ Authenticates access to allow read/write access to privileged resource_cache :param username: username for HydroShare.org :param password: password associated with username :param client_id: Client ID obtained from HydroShare :param client_secret: Client Secret provided by HydroShare :return: Returns true if authentication was successful, false otherwise """ if not all([username, password]): self.auth = None return False if client_id is not None and client_secret is not None: self.auth = HydroShareAuthOAuth2(client_id, client_secret, username=username, password=password) else: self.auth = HydroShareAuthBasic(username, password) try: self.client = HydroShare(auth=self.auth) # , verify=False) self.user_info = self.client.getUserInfo() return True except HydroShareException as e: # for incorrect username/password combinations print('Authentication failed: {}'.format(e)) except InvalidGrantError as e: # for failures when attempting to use OAuth2 print('Credentials could not be validated: {}'.format(e)) except InvalidClientError as e: print('Invalid client ID and/or client secret: {}'.format(e)) except Exception as e: print(e) self.auth = None return False def purgeDuplicateGamutFiles(self, resource_id, regex, confirm_delete=False): """ Removes all files that have a duplicate-style naming pattern (e.g. ' (1).csv', '_ASDFGJK9.csv' :param resource_id: Resource to inspect for duplicates :type resource_id: Resource object received from the HydroShare API client :param confirm_delete: If true, requires input that confirm file should be deleted :type confirm_delete: bool """ from collections import defaultdict re_breakdown = re.compile(regex, re.I) resource_files = self.getResourceFileList(resource_id) # type: [dict] duplicates_list = [] for remote_file in resource_files: url = remote_file.get('url', '') results = re_breakdown.match(url) # Check the file URL for expected patterns temp_dict = defaultdict(lambda: '') # type: dict if results: temp_dict['duplicated'] = results.groupdict() if len(temp_dict.get('duplicated', '')): # A non-duplicated file will match with length 0 duplicates_list.append(temp_dict) # Save the file name so we can remove it later for file_detail in duplicates_list: if not confirm_delete: delete_me = True else: user_answer = raw_input("Delete file {} [Y/n]: ".format(file_detail['name'])) if user_answer != 'N' and user_answer != 'n': delete_me = True else: delete_me = False if delete_me: self.client.deleteResourceFile(resource_id, file_detail['name']) print('Deleting file {}...'.format(file_detail['name'])) else: print('Skipping duplicate file {}...'.format(file_detail['name'])) def getResourceFileList(self, resource_id): """ :param resource_id: ID of resource for which to retrieve a file list :type resource_id: str :return: List of files in resource :rtype: list of str """ try: return list(self.client.getResourceFileList(resource_id)) except Exception as e: print('Error while fetching resource files {}'.format(e)) return [] def getAllResources(self): filtered_resources = {} owner = self.user_info['username'] if self.auth is None: raise HydroShareUtilityException("Cannot query resources without authentication") all_resources = self.client.resources(owner=owner) for resource in all_resources: resource_object = HydroShareResource(resource) filtered_resources[resource_object.id] = resource_object return filtered_resources def getMetadataForResource(self, resource): """ :type resource: HydroShareResource """ metadata = self.client.getScienceMetadata(resource.id) resource.title = metadata.get('title', '') resource.subjects = [item['value'] for item in metadata.get('subjects', [])] resource.abstract = metadata.get('description', '') if resource.abstract is None: resource.abstract = '' if 'funding_agencies' in metadata and len(metadata['funding_agencies']) > 0: funding_agency = metadata['funding_agencies'][0] resource.agency_url = funding_agency['agency_url'] if 'agency_url' in funding_agency else '' resource.funding_agency = funding_agency['agency_name'] if 'agency_name' in funding_agency else '' resource.award_number = funding_agency['award_number'] if 'award_number' in funding_agency else '' resource.award_title = funding_agency['award_title'] if 'award_title' in funding_agency else '' def updateResourceMetadata(self, resource): """ :type resource: HydroShareResource """ return self.client.updateScienceMetadata(resource.id, resource.get_metadata()) def _request(self, method, url, params=None, data=None, files=None, headers=None, stream=False): request = self.client.session.request(method, url, params=params, data=data, files=files, headers=headers, stream=stream) return request def requestAccessRules(self, resource): """ Get access rule for a resource. """ url = "{url_base}/resource/{pid}/sysmeta/".format(url_base=self.client.url_base, pid=resource.id) r = self._request('GET', url) if r.status_code != 200: raise Exception("Failed to get system metadata for resource: {}".format(resource.id)) data = r.json() resource.public = data.get('public', False) resource.shareable = data.get('shareable', False) def makePublic(self, resource, public=True): """ Makes a resource public or private :param resource: The resource you want to modify :param public: boolean value, True makes the resource public, False makes it private (wowzer) :return: None """ hs = HydroShare(auth=self.auth) res = hs.resource(resource.id).public(public) if res.status_code == 200 or res.status_code == 202: resource.public = public def updateKeywords(self, resource, keywords=None): if keywords is None: keywords = resource.keywords # remove leading/trailing whitespaces from keywords keywords = map(lambda x: x.strip(), keywords) url = "{url_base}/resource/{id}/scimeta/elements/".format(url_base=self.client.url_base, id=resource.id) subjects = [] for keyword in keywords: subjects.append({"value": keyword}) r = self.client.session.request('PUT', url, json={"subjects": subjects}) if r.status_code != 202: raise HydroShareException((url, 'PUT', r.status_code, keywords)) return r.json() def getFileListForResource(self, resource): resource.files = [os.path.basename(f['url']) for f in self.getResourceFileList(resource.id)] return resource.files def getFilesByResourceId(self, resource_id): return [os.path.basename(f['url']) for f in self.getResourceFileList(resource_id)] def filterResourcesByRegex(self, regex_string=None, owner=None, regex_flags=re.IGNORECASE): """ Apply a regex filter to all available resource_cache. Useful for finding GAMUT resource_cache :param owner: username of the owner of the resource :type owner: string :param regex_string: String to be used as the regex filter :param regex_flags: Flags to be passed to the regex search :return: A list of resource_cache that matched the filter """ filtered_resources = [] if owner is None: owner = self.user_info['username'] if self.auth is None: raise HydroShareUtilityException("Cannot query resources without authentication") all_resources = self.client.resources(owner=owner) regex_filter = re.compile(regex_string, regex_flags) for resource in all_resources: if regex_string is not None and regex_filter.search(resource['resource_title']) is None: continue resource_object = HydroShareResource(resource) resource_object.files = [os.path.basename(f['url']) for f in self.getResourceFileList(resource_object.id)] filtered_resources.append(resource_object) return filtered_resources def UploadFiles(self, files, resource): # type: ([str], HydroShareResource) -> bool if self.auth is None: raise HydroShareUtilityException("Cannot modify resources without authentication") try: for csv_file in files: try: self.client.deleteResourceFile(resource.id, os.path.basename(csv_file)) except HydroShareNotFound: pass # except Exception as e: # if APP_SETTINGS.H2O_DEBUG and APP_SETTINGS.VERBOSE: # print 'File did not exist in remote: {}, {}'.format(type(e), e) if type(csv_file) != str: csv_file = str(csv_file) self.client.addResourceFile(resource.id, csv_file) msg = "File {} uploaded to remote {}".format(os.path.basename(csv_file), repr(resource)) print(msg) pub.sendMessage('logger', message=msg) except HydroShareException as e: print("Upload failed - could not complete upload to HydroShare due to exception: {}".format(e)) return False except KeyError as e: print('Incorrectly formatted arguments given. Expected key not found: {}'.format(e)) return False return True def setResourcesAsPublic(self, resource_ids): if self.auth is None: raise HydroShareUtilityException("Cannot modify resources without authentication") for resource_id in resource_ids: try: print('Setting resource {} as public'.format(resource_id)) self.client.setAccessRules(resource_id, public=True) except HydroShareException as e: print("Access rule edit failed - could not set to public due to exception: {}".format(e)) except KeyError as e: print('Incorrectly formatted arguments given. Expected key not found: {}'.format(e)) def deleteFilesInResource(self, resource): if self.auth is None: raise HydroShareUtilityException("Cannot modify resources without authentication") try: file_list = self.getResourceFileList(resource.id) for file_info in file_list: msg = 'Deleting resource file: {}'.format(os.path.basename(file_info['url'])) print(msg) pub.sendMessage('logger', message=msg) self.client.deleteResourceFile(resource.id, os.path.basename(file_info['url'])) except Exception as e: print('Could not delete files in resource {}\n{}'.format(resource.id, e)) def getResourceCoveragePeriod(self, resource_id): metadata = self.client.getScienceMetadata(resource_id) period_start = None period_end = None try: xml_tree = ElementTree.fromstring(metadata) description_node = xml_tree.find('rdf:Description', namespaces=self.xml_ns) coverage_node = description_node.find('dc:coverage', namespaces=self.xml_ns) period_node = coverage_node.find('dcterms:period', namespaces=self.xml_ns) value_node = period_node.find('rdf:value', namespaces=self.xml_ns) match = self.re_period.match(value_node.text) if match is not None: period_start = dateutil.parser.parse(match.group('start')) period_end = dateutil.parser.parse(match.group('end')) except Exception as e: print("Unable to find coverage data - encountered exception {}".format(e)) return period_start, period_end def deleteResource(self, resource_id, confirm=True): if self.auth is None: raise HydroShareUtilityException("Cannot modify resources without authentication") try: if confirm: user_input = raw_input('Are you sure you want to delete the resource {}? (y/N): '.format(resource_id)) if user_input.lower() != 'y': return print('Deleting resource {}'.format(resource_id)) self.client.deleteResource(resource_id) except Exception as e: print('Exception encountered while deleting resource {}: {}'.format(resource_id, e)) def createNewResource(self, resource): # type: (ResourceTemplate) -> HydroShareResource """ :param resource: :type resource: ResourceTemplate :return: :rtype: str """ if self.auth is None: raise HydroShareUtilityException("Cannot create resource without authentication") # http://hs-restclient.readthedocs.io/en/latest/ if resource is not None: metadata = [] fundingagency = {} fundingagency_attr_map = ( ('funding_agency', 'agency_name'), ('award_title', 'award_title'), ('award_number', 'award_number'), ('agency_url', 'agency_url') ) for reskey, fakey in fundingagency_attr_map: # reskey - resource attribute name # fakey - funding agency attribute name value = getattr(resource, reskey).strip() if len(value): fundingagency[fakey] = value if len(fundingagency.keys()): metadata.append({'fundingagency': fundingagency}) resource_id = self.client.createResource(resource_type='CompositeResource', title=resource.title, abstract=resource.abstract, keywords=resource.keywords, metadata=json.dumps(metadata, encoding='ascii')) hs_resource = HydroShareResource({'resource_id': resource_id}) self.getMetadataForResource(hs_resource) return hs_resource return None