Skip to content

Commit

Permalink
Merge pull request #222 from MerginMaps/project-history
Browse files Browse the repository at this point in the history
Project history : Add functionnalities for the  version viewerin the QGIS plugin
  • Loading branch information
MarcelGeo authored Dec 3, 2024
2 parents 74222e4 + dcbeb22 commit 70c48a9
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 13 deletions.
80 changes: 67 additions & 13 deletions mergin/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,17 @@ def workspace_service(self, workspace_id):

return response

def workspace_usage(self, workspace_id):
"""
This Requests information about a workspace usage from /workspace/{id}/usage endpoint,
if such exists in self.url server.
Returns response from server as JSON dict or None if endpoint is not found
"""

resp = self.get(f"/v1/workspace/{workspace_id}/usage")
return json.load(resp)

def server_type(self):
"""
Returns the deployment type of the server
Expand Down Expand Up @@ -700,41 +711,84 @@ def project_info(self, project_path_or_id, since=None, version=None):
resp = self.get("/v1/project/{}".format(project_path_or_id), params)
return json.load(resp)

def project_versions(self, project_path, since=None, to=None):
def paginated_project_versions(self, project_path, page, per_page=100, descending=False):
"""
Get records of project's versions (history) using calculated pagination.
wrapper around the /v1/project/versions/paginated/{} API end point
:param project_path: Project's full name (<namespace>/<name>)
:type project_path: String | Int
:param page: page number
:type page: Int
:param per_page: number of results per page default 100
:type per_page: Int
:param descending: order of sorting
:type descending: Bool
:rtype: List[Dict], Int
"""
params = {"page": page, "per_page": per_page, "descending": descending}
resp = self.get("/v1/project/versions/paginated/{}".format(project_path), params)
resp_json = json.load(resp)
return resp_json["versions"], resp_json["count"]

def project_versions_count(self, project_path):
"""
return the total count of versions
To note we fetch only one page and one item as we only need the "count" response
:param project_path_or_id: Project's full name (<namespace>/<name>) or id
:type project_path_or_id: String
:rtype: Int
"""
params = {"page": 1, "per_page": 1, "descending": False}
resp = self.get("/v1/project/versions/paginated/{}".format(project_path), params)
resp_json = json.load(resp)
return resp_json["count"]

def project_versions(self, project_path, since=1, to=None):
"""
Get records of project's versions (history) in ascending order.
If neither 'since' nor 'to' is specified it will return all versions.
:param project_path: Project's full name (<namespace>/<name>)
:type project_path: String
:param since: Version to track project history from
:type since: String
:type since: String | Int
:param to: Version to track project history to
:type to: String
:type to: String | Int
:rtype: List[Dict]
"""
versions = []
per_page = 100 # server limit
num_since = int_version(since) if since else 1
num_to = int_version(to) if to else None # we may not know yet

if type(since) == str:
num_since = int_version(since)
else:
# keep the since parameter as is
num_since = since

if type(to) == str:
num_to = int_version(to)
else:
# keep the to parameter as is
num_to = to

start_page = math.ceil(num_since / per_page)
if not num_to:
# let's get first page and count
params = {"page": start_page, "per_page": per_page, "descending": False}
resp = self.get("/v1/project/versions/paginated/{}".format(project_path), params)
resp_json = json.load(resp)
versions = resp_json["versions"]
num_to = resp_json["count"]
versions, num_to = self.paginated_project_versions(project_path, start_page, per_page)

latest_version = int_version(versions[-1]["name"])
if latest_version < num_to:
versions += self.project_versions(project_path, f"v{latest_version+1}", f"v{num_to}")
else:
end_page = math.ceil(num_to / per_page)
for page in range(start_page, end_page + 1):
params = {"page": page, "per_page": per_page, "descending": False}
resp = self.get("/v1/project/versions/paginated/{}".format(project_path), params)
versions += json.load(resp)["versions"]
page_versions, _ = self.paginated_project_versions(project_path, page, per_page)
versions += page_versions

# filter out versions not within range
filtered_versions = list(filter(lambda v: (num_since <= int_version(v["name"]) <= num_to), versions))
Expand Down
2 changes: 2 additions & 0 deletions mergin/client_pull.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,8 @@ def download_diffs_async(mc, project_directory, file_path, versions):
fetch_files = []

for version in versions:
if version not in file_history["history"]:
continue # skip if this file was not modified at this version
version_data = file_history["history"][version]
if "diff" not in version_data:
continue # skip if there is no diff in history
Expand Down
8 changes: 8 additions & 0 deletions mergin/test/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2013,6 +2013,14 @@ def test_project_versions_list(mc):
assert versions[0]["name"] == "v2"
assert versions[-1]["name"] == "v4"

versions_count = mc.project_versions_count(project)
assert versions_count == 5

versions, _ = mc.paginated_project_versions(project, page=1, descending=True)
assert len(versions) == 5
assert versions[0]["name"] == "v5"
assert versions[-1]["name"] == "v1"


def test_report(mc):
test_project = "test_report"
Expand Down

0 comments on commit 70c48a9

Please sign in to comment.