Gitlab Community Edition Instance

Commit 192beea9 authored by mhellka's avatar mhellka
Browse files

Added CDStar.delete_* and more methods to handle classes.

parent 1996b90f
...@@ -18,9 +18,9 @@ with cdstar.begin(autocommit=True): # Wrap everything in a transaction (optiona ...@@ -18,9 +18,9 @@ with cdstar.begin(autocommit=True): # Wrap everything in a transaction (optiona
archive_id = cdstar.create_archive(vault_name).id archive_id = cdstar.create_archive(vault_name).id
cdstar.put_file(vault_name, archive_id, "test.py", __file__) cdstar.put_file(vault_name, archive_id, "test.py", __file__)
with cdstar.get_file(vault_name, archive_id, "test.py") as download: with cdstar.get_file(vault_name, archive_id, "test.py") as stream:
with open("/tmp/test.py", "wb") as target: with open("/tmp/test.py", "wb") as target:
for chunk in download.iter_content(buffsize=1024*64): for chunk in stream.iter_content(buffsize=1024*64):
target.write(chunk) target.write(chunk)
``` ```
...@@ -32,11 +32,11 @@ cdstar = CDStar("https://cdstar.gwdg.de/demo/v3/", auth=("USER", "PASS")) ...@@ -32,11 +32,11 @@ cdstar = CDStar("https://cdstar.gwdg.de/demo/v3/", auth=("USER", "PASS"))
with cdstar.begin(autocommit=True): # Wrap everything in a transaction (optional) with cdstar.begin(autocommit=True): # Wrap everything in a transaction (optional)
vault = CDStarVault(cdstar, "demo") vault = CDStarVault(cdstar, "demo")
archive = vault.create_archive() file = vault.new_archive().file("test.py")
archive.put("test.py", __file__) file.put(__file__)
with archive.file("test.py").download() as download: with file.stream() as stream:
download.save_to("/tmp/") stream.save_to("/tmp/")
``` ```
## Command-Line interface ## Command-Line interface
......
...@@ -192,11 +192,12 @@ class CDStar: ...@@ -192,11 +192,12 @@ class CDStar:
def exists(self, vault, archive=None, file=None) -> bool: def exists(self, vault, archive=None, file=None) -> bool:
""" Checks if a vault, archive or file exists """ """ Checks if a vault, archive or file exists """
if file: if file is not None:
return self.raw("HEAD", vault, archive, file, expect_status=[200, 404]).ok return self.raw("HEAD", vault, archive, file, expect_status=[200, 404]).ok
if archive: elif archive is not None:
return self.raw("HEAD", vault, archive, expect_status=[200, 404]).ok return self.raw("HEAD", vault, archive, expect_status=[200, 404]).ok
return self.raw("HEAD", vault, expect_status=[200, 404]).ok else:
return self.raw("HEAD", vault, expect_status=[200, 404]).ok
def service_info(self) -> JsonObject: def service_info(self) -> JsonObject:
""" Get information about the cdstar service instance """ """ Get information about the cdstar service instance """
...@@ -206,22 +207,6 @@ class CDStar: ...@@ -206,22 +207,6 @@ class CDStar:
""" Get information about a vault """ """ Get information about a vault """
return self.rest('GET', vault) return self.rest('GET', vault)
def archive_info(self, vault, archive, meta=False, files=False) -> JsonObject:
""" Get information about an archive """
query = {"info": "true"}
if meta:
query.setdefault("with", []).append("meta")
if files:
query.setdefault("with", []).append("files")
return self.rest("GET", vault, archive, params=query)
def file_info(self, vault, archive, name, meta=False) -> JsonObject:
""" Get information about a file """
query = {"info": "true"}
if meta:
query['with'] = "meta"
return self.rest("GET", vault, archive, _fix_filename(name), params=query)
def create_archive(self, vault, form: FormUpdate = None) -> JsonObject: def create_archive(self, vault, form: FormUpdate = None) -> JsonObject:
""" Create a new archive. """ """ Create a new archive. """
if form: if form:
...@@ -235,41 +220,18 @@ class CDStar: ...@@ -235,41 +220,18 @@ class CDStar:
return self.rest("POST", vault, archive, data=form.body, return self.rest("POST", vault, archive, data=form.body,
headers={'Content-Type': form.content_type}) headers={'Content-Type': form.content_type})
def list_files(self, vault, archive, offset=0, limit=100, meta=False, order=None, reverse=False, def archive_info(self, vault, archive, meta=False, files=False) -> JsonObject:
include_glob=None, exclude_glob=None) -> JsonObject: """ Get information about an archive """
""" Request a FileList for an archive. query = {"info": "true"}
The FileList may be incomplete of more than `limit` files are in an archive. See iter_files() for a
convenient way to get all files as an iterator.
"""
query = {"files": "true", "offset": offset, "limit": limit}
if include_glob:
query["include"] = include_glob
if exclude_glob:
query["exclude"] = exclude_glob
if meta: if meta:
query["with"] = "meta" query.setdefault("with", []).append("meta")
if order: if files:
query["order"] = order query.setdefault("with", []).append("files")
if reverse:
query["reverse"] = "True"
return self.rest("GET", vault, archive, params=query) return self.rest("GET", vault, archive, params=query)
def iter_files(self, vault, archive, offset=0, **args) -> typing.Iterator[JsonObject]: def delete_archive(self, vault, archive) -> bool:
""" Yield all FileInfo entries of an archive. """ Remove an archive. This cannot be undone. """
return self.raw("DELETE", vault, archive).ok
This method may (lazily) issue more than one request if an archive contains more than `limit` files.
"""
while True:
files = self.list_files(vault, archive, offset, **args)
if files['files'] and offset + files['count'] <= files['total']:
yield from files['files']
offset += files['count']
else:
break
def put_file(self, vault, archive, name, source, type=None, replace=True) -> JsonObject: def put_file(self, vault, archive, name, source, type=None, replace=True) -> JsonObject:
""" Create or replace a single file on an existing archive. """ Create or replace a single file on an existing archive.
...@@ -311,6 +273,53 @@ class CDStar: ...@@ -311,6 +273,53 @@ class CDStar:
rs = self.raw("GET", vault, archive, name, stream=True, headers=headers) rs = self.raw("GET", vault, archive, name, stream=True, headers=headers)
return FileDownload(vault, archive, name, rs) return FileDownload(vault, archive, name, rs)
def file_info(self, vault, archive, name, meta=False) -> JsonObject:
""" Get information about a file """
query = {"info": "true"}
if meta:
query['with'] = "meta"
return self.rest("GET", vault, archive, _fix_filename(name), params=query)
def list_files(self, vault, archive, offset=0, limit=100, meta=False, order=None, reverse=False,
include_glob=None, exclude_glob=None) -> JsonObject:
""" Request a FileList for an archive.
The FileList may be incomplete of more than `limit` files are in an archive. See iter_files() for a
convenient way to get all files as an iterator.
"""
query = {"files": "true", "offset": offset, "limit": limit}
if include_glob:
query["include"] = include_glob
if exclude_glob:
query["exclude"] = exclude_glob
if meta:
query["with"] = "meta"
if order:
query["order"] = order
if reverse:
query["reverse"] = "True"
return self.rest("GET", vault, archive, params=query)
def iter_files(self, vault, archive, offset=0, **args) -> typing.Iterator[JsonObject]:
""" Yield all FileInfo entries of an archive.
This method may (lazily) issue more than one request if an archive contains more than `limit` files.
"""
while True:
files = self.list_files(vault, archive, offset, **args)
if files['files'] and offset + files['count'] <= files['total']:
yield from files['files']
offset += files['count']
else:
break
def delete_file(self, vault, archive, file) -> bool:
""" Remove a archive file. This cannot be undone. """
return self.raw("DELETE", vault, archive, file).ok
def search(self, vault, q, order=None, limit=0, scroll=None, groups=None) -> JsonObject: def search(self, vault, q, order=None, limit=0, scroll=None, groups=None) -> JsonObject:
""" Perform a search and return a single page of search results. """ Perform a search and return a single page of search results.
...@@ -371,6 +380,8 @@ class CDStarVault: ...@@ -371,6 +380,8 @@ class CDStarVault:
__slots__ = "api", "name" __slots__ = "api", "name"
def __init__(self, api: CDStar, vault: str): def __init__(self, api: CDStar, vault: str):
if not api or not vault:
raise AssertionError("Parameters must not be none")
self.api = api self.api = api
self.name = vault self.name = vault
...@@ -409,10 +420,27 @@ class CDStarArchive: ...@@ -409,10 +420,27 @@ class CDStarArchive:
""" """
__slots__ = "api", "vault", "id" __slots__ = "api", "vault", "id"
def __init__(self, vault, id): def __init__(self, vault: CDStarVault, archive_id):
if not vault or not archive_id:
raise AssertionError("Parameters must not be none")
self.api = vault.api self.api = vault.api
self.vault = vault self.vault = vault
self.id = id self.id = archive_id
def exists(self):
""" Checks if this archive exists. """
return self.api.exists(self.vault.name, self.id)
def delete(self):
""" Delete this archive. """
return self.api.delete_archive(self.vault.name, self.id)
def file(self, name: str) -> "CDStarFile":
""" Return a file handle.
The file may or may not exist remotely. Check with `exist()`.
"""
return CDStarFile(self, name)
# TODO: Implement meee # TODO: Implement meee
...@@ -425,8 +453,26 @@ class CDStarFile: ...@@ -425,8 +453,26 @@ class CDStarFile:
__slots__ = "api", "archive", "name" __slots__ = "api", "archive", "name"
def __init__(self, archive: CDStarArchive, name: str): def __init__(self, archive: CDStarArchive, name: str):
if not archive or not name:
raise AssertionError("Parameters must not be none")
self.api = archive.api self.api = archive.api
self.archive = archive self.archive = archive
self.name = name self.name = name
def exists(self):
""" Checks if this file exists """
return self.api.exists(self.archive.vault.name, self.archive.id, self.name)
def delete(self):
""" Delete this file from the archive. """
return self.api.delete_file(self.archive.vault.name, self.archive.id, self.name)
def put(self, **ka) -> JsonObject:
""" Create or overwrite file content """
return self.api.put_file(self.archive.vault.name, self.archive.id, self.name, **ka)
def stream(self, **ka) -> FileDownload:
""" Request file content as a stream-able :class:`FileDownload`. """
return self.api.get_file(self.archive.vault.name, self.archive.id, self.name, **ka)
# TODO: Implement meee # TODO: Implement meee
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment