Skip to content

Commit

Permalink
Merge pull request #64 from opengisch/patch_project
Browse files Browse the repository at this point in the history
Add endpoint to patch the project and pretty print project data
  • Loading branch information
suricactus authored Oct 4, 2024
2 parents 02cb0bf + 9b6bb22 commit 6c5f53c
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 8 deletions.
53 changes: 46 additions & 7 deletions qfieldcloud_sdk/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import click

from . import sdk
from .utils import log, print_json
from .utils import format_project_table, log, print_json

QFIELDCLOUD_DEFAULT_URL = "https://app.qfield.cloud/api/v1/"

Expand Down Expand Up @@ -200,9 +200,8 @@ def list_projects(ctx: Context, include_public: bool, **opts) -> None:
print_json(projects)
else:
if projects:
log("Projects:")
for project in projects:
log(f'{project["id"]}\t{project["owner"]}/{project["name"]}')
log("Projects the current user has access to:")
log(format_project_table(projects))
else:
log("User does not have any projects yet.")

Expand Down Expand Up @@ -258,9 +257,8 @@ def create_project(ctx: Context, name, owner, description, is_public):
if ctx.obj["format_json"]:
print_json(project)
else:
log(
f'Created project "{project["owner"]}/{project["name"]}" with project id "{project["id"]}".'
)
log("Created project:")
log(format_project_table([project]))


@cli.command()
Expand Down Expand Up @@ -371,6 +369,47 @@ def download_files(
log(f"No files to download for project {project_id}")


@cli.command()
@click.argument("project_id")
@click.option(
"--name",
help="New project name",
)
@click.option(
"--description",
help="New project description",
)
@click.option(
"--owner",
help="Transfer the project to a new owner",
)
@click.option(
"--is-public/--is-no-public",
is_flag=True,
help="Whether the project shall be public",
)
@click.pass_context
def patch_project(
ctx: Context,
project_id: str,
name: Optional[str] = None,
description: Optional[str] = None,
owner: Optional[str] = None,
is_public: Optional[bool] = None,
) -> None:
"""Patch the project with new data. Pass only the parameters that shall be changed."""

project = ctx.obj["client"].patch_project(
project_id, name=name, owner=owner, description=description, is_public=is_public
)

if ctx.obj["format_json"]:
print_json(project)
else:
log("Patched project:")
log(format_project_table([project]))


@cli.command()
@click.argument("project_id")
@click.argument("paths", nargs=-1, required=True)
Expand Down
44 changes: 43 additions & 1 deletion qfieldcloud_sdk/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,48 @@ def delete_project(self, project_id: str) -> requests.Response:

return resp

def patch_project(
self,
project_id: str,
name: Optional[str] = None,
owner: Optional[str] = None,
description: Optional[str] = None,
is_public: Optional[bool] = None,
) -> Dict[str, Any]:
"""Update a project.
Args:
project_id (str): Project ID.
name (str | None): if passed, the new name. Defaults to None.
owner (str | None, optional): if passed, the new owner. Defaults to None.
description (str, optional): if passed, the new description. Defaults to None.
is_public (bool, optional): if passed, the new public setting. Defaults to None.
Returns:
Dict[str, Any]: the updated project
"""
project_data: dict[str, Any] = {}

if name:
project_data["name"] = name

if description:
project_data["description"] = description

if owner:
project_data["owner"] = owner

if is_public:
project_data["is_public"] = is_public

resp = self._request(
"PATCH",
f"projects/{project_id}",
project_data,
)

return resp.json()

def upload_files(
self,
project_id: str,
Expand Down Expand Up @@ -1068,7 +1110,7 @@ def download_file(
progress_bar = tqdm(
total=content_length,
unit_scale=True,
desc=remote_filename,
desc=str(remote_filename),
)
download_file = CallbackIOWrapper(progress_bar.update, f, "write")
else:
Expand Down
45 changes: 45 additions & 0 deletions qfieldcloud_sdk/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import os
import sys
from typing import List


def print_json(data):
Expand Down Expand Up @@ -69,3 +70,47 @@ def calc_etag(filename: str, part_size: int = 8 * 1024 * 1024) -> str:
final_md5sum = hashlib.md5(b"".join(md5sums))

return "{}-{}".format(final_md5sum.hexdigest(), len(md5sums))


def format_table(headers: List[str], data: List[List]) -> str:
length_by_column: List[int] = []

for col in headers:
length_by_column.append(len(col))

for row in data:
for idx, col in enumerate(row):
length_by_column[idx] = max(length_by_column[idx], len(str(col)))

row_tmpl = "|"
for col_length in length_by_column:
row_tmpl += " {:<" + str(col_length) + "} |"

result = row_tmpl.format(*headers)
result += "\r\n"
result += "-" * (sum(length_by_column) + len(headers) * 3 + 1)

for row in data:
result += "\r\n"
result += row_tmpl.format(*row)

return result


def format_project_table(projects: List) -> str:
data = []

for project in projects:
data.append(
[
project["id"],
project["owner"] + "/" + project["name"],
project["is_public"],
project["description"],
]
)

return format_table(
headers=["ID", "OWNER/NAME", "IS PUBLIC", "DESCRIPTION"],
data=data,
)

0 comments on commit 6c5f53c

Please sign in to comment.