def update_metadata(self, bucket, label, params): '''Update the metadata with the provided dictionary of params. :param parmams: dictionary of key values (json serializable). ''' if self.mode !="r": try: payload = self._get_bucket_md(bucket) except OFSFileNotFound: # No MD found... create it payload = {} for l in self.list_labels(bucket): payload[l] = {} payload[l]['_label'] = l if not self.quiet: print("Had to create md file for %s" % bucket) except OFSException as e: raise OFSException(e) if not label in payload: payload[label] = {} payload[label].update(params) self.put_stream(bucket, MD_FILE, json.dumps(payload).encode('utf-8'), params={}, replace=True, add_md=False) return payload[label] else: raise OFSException("Cannot update MD in archive in 'r' mode")
def _get_bucket_md(self, bucket): name = self._zf(bucket, MD_FILE) if not self.exists(bucket, MD_FILE): raise OFSFileNotFound if self.mode !="w": #z = ZipFile(self.zipfile, "r", self.compression, self.allowZip64) json_doc = self.z.read(name) #z.close() try: jsn = json.loads(json_doc) return jsn except ValueError: raise OFSException("Cannot read metadata for %s" % bucket) else: raise OFSException("Cannot read from archive in 'w' mode")
def get_stream(self, bucket, label, as_stream=True): urlfp = self._request('/' + bucket + '/' + label) if urlfp.code >= 400: raise OFSException(urlfp.read()) if not as_stream: return urlfp.read() return urlfp
def put_stream(self, bucket, label, stream_object, params=None, replace=True, add_md=True): '''Put a bitstream (stream_object) for the specified bucket:label identifier. :param bucket: as standard :param label: as standard :param stream_object: file-like object to read from or bytestring. :param params: update metadata with these params (see `update_metadata`) ''' if self.mode == "r": raise OFSException("Cannot write into archive in 'r' mode") else: params = params or {} fn = self._zf(bucket, label) params['_creation_date'] = datetime.now().isoformat().split(".")[0] ## '2010-07-08T19:56:47' params['_label'] = label if self.exists(bucket, label) and replace==True: # Add then Replace? Let's see if that works... #z = ZipFile(self.zipfile, self.mode, self.compression, self.allowZip64) zinfo = self.z.getinfo(fn) size, chksum = self._write(self.z, bucket, label, stream_object) self._del_stream(zinfo) #z.close() params['_content_length'] = size if chksum: params['_checksum'] = chksum else: #z = ZipFile(self.zipfile, self.mode, self.compression, self.allowZip64) size, chksum = self._write(self.z, bucket, label, stream_object) #z.close() params['_content_length'] = size if chksum: params['_checksum'] = chksum if add_md: params = self.update_metadata(bucket, label, params) return params
def del_metadata_keys(self, bucket, label, keys): '''Delete the metadata corresponding to the specified keys. ''' if self.mode !="r": try: payload = self._get_bucket_md(bucket) except OFSFileNotFound: # No MD found... raise OFSFileNotFound("Couldn't find a md file for %s bucket" % bucket) except OFSException as e: raise OFSException(e) if payload.has_key(label): for key in [x for x in keys if payload[label].has_key(x)]: del payload[label][key] self.put_stream(bucket, MD_FILE, json.dumps(payload), params={}, replace=True, add_md=False) else: raise OFSException("Cannot update MD in archive in 'r' mode")
def get_metadata(self, bucket, label): '''Get the metadata for this bucket:label identifier. ''' if self.mode !="w": try: jsn = self._get_bucket_md(bucket) except OFSFileNotFound: # No MD found... return {} except OFSException as e: raise OFSException(e) if label in jsn: return jsn[label] else: return {} else: raise OFSException("Cannot read md from archive in 'w' mode")
def _request_json(self, path, data=None, headers={}, method='GET'): hdr = { 'Accept': 'application/json', 'Content-Type': 'application/json' } hdr.update(headers) if data is None: data = {} data = json.dumps(data) urlfp = self._request(path, data=data, headers=hdr, method=method) try: ret_data = urlfp.read() try: ret_data = json.loads(ret_data) except ValueError: raise OFSException(urlfp.msg) if isinstance(ret_data, dict) and 'error' in ret_data.keys(): raise OFSException(ret_data.get('message')) return ret_data finally: urlfp.close()
def put_stream(self, bucket, label, stream_object, params={}): content_type = params.get('_format', 'application/octet-stream') params['_label'] = label params['_bucket'] = bucket content_type, body = self._multipart_encode(params, stream_object, label, content_type) headers = {'Accept': 'application/json', 'Content-Type': content_type} if self.exists(bucket, label): urlfp = self._request('/' + bucket + '/' + label, data=body, headers=headers, method='PUT') else: urlfp = self._request('/' + bucket, data=body, headers=headers, method='POST') try: ret_data = json.loads(urlfp.read()) except ValueError: raise OFSException(urlfp.msg) if 'error' in ret_data.keys(): raise OFSException(ret_data.get('message'))
def get_stream(self, bucket, label, as_stream=True): '''Get a bitstream for the given bucket:label combination. :param bucket: the bucket to use. :return: bitstream as a file-like object ''' if self.mode == "w": raise OFSException("Cannot read from archive in 'w' mode") elif self.exists(bucket, label): fn = self._zf(bucket, label) if as_stream: return self.z.open(fn) else: return self.z.read(fn) else: raise OFSFileNotFound
def _require_key(self, bucket, label): key = self._get_key(bucket, label) if key is None: raise OFSException("%s->%s does not exist!" % (bucket.name, label)) return key
def _require_bucket(self, bucket_name): """ Also try to create the bucket. """ if not self.exists(bucket_name) and not self.claim_bucket(bucket_name): raise OFSException("Invalid bucket: %s" % bucket_name) return self._get_bucket(bucket_name)