+ Returns information about this Collection fetched from the API server.
+ If the Collection exists in Keep but not the API server, currently
+ returns None. Future versions may provide a synthetic response.
+ """
+ return self._api_response
+
+ def open(self, path, mode):
+ mode = mode.replace("b", "")
+ if len(mode) == 0 or mode[0] not in ("r", "w", "a"):
+ raise ArgumentError("Bad mode '%s'" % mode)
+ create = (mode != "r")
+
+ f = self.find(path, create=create)
+ if f is None:
+ raise ArgumentError("File not found")
+ if not isinstance(f, ArvadosFile):
+ raise ArgumentError("Path must refer to a file.")
+
+ if mode[0] == "w":
+ f.truncate(0)
+
+ if mode == "r":
+ return ArvadosFileReader(f, path, mode)
+ else:
+ return ArvadosFileWriter(f, path, mode)
+
+ @_populate_first
+ def modified(self):
+ for k,v in self._items.items():
+ if v.modified():
+ return True
+ return False
+
+ @_populate_first
+ def set_unmodified(self):
+ for k,v in self._items.items():
+ v.set_unmodified()
+
+ @_populate_first
+ def __iter__(self):
+ self._items.iterkeys()
+
+ @_populate_first
+ def iterkeys(self):
+ self._items.iterkeys()
+
+ @_populate_first
+ def __getitem__(self, k):
+ r = self.find(k)
+ if r:
+ return r
+ else:
+ raise KeyError(k)
+
+ @_populate_first
+ def __contains__(self, k):
+ return self.find(k) is not None
+
+ @_populate_first
+ def __len__(self):
+ return len(self._items)
+
+ @_populate_first
+ def __delitem__(self, p):
+ p = path.split("/")
+ if p[0] == '.':
+ del p[0]
+
+ if len(p) > 0:
+ item = self._items.get(p[0])
+ if item is None:
+ raise NotFoundError()
+ if len(p) == 1:
+ del self._items[p[0]]
+ else:
+ del p[0]
+ del item["/".join(p)]
+ else:
+ raise NotFoundError()
+
+ @_populate_first
+ def keys(self):
+ return self._items.keys()
+
+ @_populate_first
+ def values(self):
+ return self._items.values()
+
+ @_populate_first
+ def items(self):
+ return self._items.items()
+
+ @_populate_first
+ def manifest_text(self, strip=False, normalize=False):
+ if self.modified() or self._manifest_text is None or normalize:
+ return export_manifest(self, stream_name=".", portable_locators=strip)
+ else:
+ if strip:
+ return self.stripped_manifest()
+ else:
+ return self._manifest_text
+
+ def portable_data_hash(self):
+ stripped = self.manifest_text(strip=True)
+ return hashlib.md5(stripped).hexdigest() + '+' + str(len(stripped))
+
+ @_populate_first
+ def commit_bufferblocks(self):
+ pass
+
+ @_populate_first
+ def save(self):
+ if self.modified():
+ self._my_keep().put(self.manifest_text(strip=True))
+ if re.match(util.collection_uuid_pattern, self._manifest_locator):
+ self._api_response = self._api_client.collections().update(
+ uuid=self._manifest_locator,
+ body={'manifest_text': self.manifest_text(strip=False)}
+ ).execute(
+ num_retries=self.num_retries)
+ else:
+ raise AssertionError("Collection manifest_locator must be a collection uuid. Use save_as() for new collections.")
+ self.set_unmodified()
+
+ @_populate_first
+ def save_as(self, name, owner_uuid=None):
+ self._my_keep().put(self.manifest_text(strip=True))
+ body = {"manifest_text": self.manifest_text(strip=False),
+ "name": name}
+ if owner_uuid:
+ body["owner_uuid"] = owner_uuid
+ self._api_response = self._api_client.collections().create(body=body).execute(num_retries=self.num_retries)
+ self._manifest_locator = self._api_response["uuid"]
+ self.set_unmodified()
+
+
+def import_manifest(manifest_text, into_collection=None, api_client=None, keep=None, num_retries=None):
+ if into_collection is not None:
+ if len(into_collection) > 0:
+ raise ArgumentError("Can only import manifest into an empty collection")
+ c = into_collection
+ else:
+ c = Collection(api_client=api_client, keep_client=keep, num_retries=num_retries)