|
20 | 20 | from enum import Enum |
21 | 21 | from typing import Optional, Type, Union |
22 | 22 |
|
| 23 | +from .models import ( |
| 24 | + ProjectDelta, |
| 25 | + ProjectDeltaItemDiff, |
| 26 | + ProjectDeltaChange, |
| 27 | + ProjectInfo, |
| 28 | + ProjectFile, |
| 29 | + ProjectWorkspace, |
| 30 | +) |
| 31 | + |
23 | 32 | from .common import ( |
24 | 33 | SYNC_ATTEMPT_WAIT, |
25 | 34 | SYNC_ATTEMPTS, |
@@ -732,6 +741,89 @@ def project_info(self, project_path_or_id, since=None, version=None): |
732 | 741 | resp = self.get("/v1/project/{}".format(project_path_or_id), params) |
733 | 742 | return json.load(resp) |
734 | 743 |
|
| 744 | + def project_info_v2(self, project_id: str, files_at_version=None) -> ProjectInfo: |
| 745 | + """ |
| 746 | + Fetch info about project. |
| 747 | +
|
| 748 | + :param project_id: Project's id |
| 749 | + :type project_id: String |
| 750 | + :param files_at_version: Version to track files at given version |
| 751 | + :type files_at_version: String |
| 752 | + """ |
| 753 | + self.check_v2_project_info_support() |
| 754 | + |
| 755 | + params = {} |
| 756 | + if files_at_version: |
| 757 | + params = {"files_at_version": files_at_version} |
| 758 | + resp = self.get(f"/v2/projects/{project_id}", params) |
| 759 | + resp_json = json.load(resp) |
| 760 | + project_workspace = resp_json.get("workspace") |
| 761 | + return ProjectInfo( |
| 762 | + id=resp_json.get("id"), |
| 763 | + name=resp_json.get("name"), |
| 764 | + created_at=resp_json.get("created_at"), |
| 765 | + updated_at=resp_json.get("updated_at"), |
| 766 | + version=resp_json.get("version"), |
| 767 | + public=resp_json.get("public"), |
| 768 | + role=resp_json.get("role"), |
| 769 | + size=resp_json.get("size"), |
| 770 | + workspace=ProjectWorkspace( |
| 771 | + id=project_workspace.get("id"), |
| 772 | + name=project_workspace.get("name"), |
| 773 | + ), |
| 774 | + files=[ |
| 775 | + ProjectFile( |
| 776 | + checksum=f.get("checksum"), |
| 777 | + mtime=f.get("mtime"), |
| 778 | + path=f.get("path"), |
| 779 | + size=f.get("size"), |
| 780 | + ) |
| 781 | + for f in resp_json.get("files", []) |
| 782 | + ], |
| 783 | + ) |
| 784 | + |
| 785 | + def get_project_delta(self, project_id: str, since: str, to: typing.Optional[str] = None) -> ProjectDelta: |
| 786 | + """ |
| 787 | + Fetch info about project delta since given version. |
| 788 | +
|
| 789 | + :param project_id: Project's id |
| 790 | + :type project_id: String |
| 791 | + :param since: Version to track history of files from |
| 792 | + :type since: String (e.g. v1) |
| 793 | + :param to: Optional version to track history of files to, if not given latest version is used |
| 794 | + :type to: String (e.g. v2) |
| 795 | + """ |
| 796 | + # If it is not enabled on the server, raise error |
| 797 | + if not self.server_features().get("v2_pull_enabled", False): |
| 798 | + raise ClientError("Project delta is not supported by the server") |
| 799 | + |
| 800 | + params = {"since": since} |
| 801 | + if to: |
| 802 | + params["to"] = to |
| 803 | + resp = self.get(f"/v2/projects/{project_id}/delta", params) |
| 804 | + resp_parsed = json.load(resp) |
| 805 | + return ProjectDelta( |
| 806 | + to_version=resp_parsed.get("to_version"), |
| 807 | + changes=[ |
| 808 | + ProjectDeltaChange( |
| 809 | + path=item["path"], |
| 810 | + size=item.get("size"), |
| 811 | + checksum=item.get("checksum"), |
| 812 | + version=item.get("version"), |
| 813 | + type=item.get("change"), |
| 814 | + diffs=( |
| 815 | + [ |
| 816 | + ProjectDeltaItemDiff( |
| 817 | + id=diff.get("id"), |
| 818 | + ) |
| 819 | + for diff in item.get("diffs", []) |
| 820 | + ] |
| 821 | + ), |
| 822 | + ) |
| 823 | + for item in resp_parsed.get("items", []) |
| 824 | + ], |
| 825 | + ) |
| 826 | + |
735 | 827 | def paginated_project_versions(self, project_path, page, per_page=100, descending=False): |
736 | 828 | """ |
737 | 829 | Get records of project's versions (history) using calculated pagination. |
@@ -822,11 +914,11 @@ def download_project(self, project_path, directory, version=None): |
822 | 914 | :param project_path: Project's full name (<namespace>/<name>) |
823 | 915 | :type project_path: String |
824 | 916 |
|
825 | | - :param version: Project version to download, e.g. v42 |
826 | | - :type version: String |
827 | | -
|
828 | 917 | :param directory: Target directory |
829 | 918 | :type directory: String |
| 919 | +
|
| 920 | + :param version: Project version to download, e.g. v42 |
| 921 | + :type version: String |
830 | 922 | """ |
831 | 923 | job = download_project_async(self, project_path, directory, version) |
832 | 924 | download_project_wait(job) |
@@ -1070,7 +1162,7 @@ def project_status(self, directory): |
1070 | 1162 | mp = MerginProject(directory) |
1071 | 1163 | server_info = self.project_info(mp.project_full_name(), since=mp.version()) |
1072 | 1164 |
|
1073 | | - pull_changes = mp.get_pull_changes(server_info["files"]) |
| 1165 | + pull_changes = mp.get_pull_changes(server_info.get("files", []), server_info.get("version")) |
1074 | 1166 |
|
1075 | 1167 | push_changes = mp.get_push_changes() |
1076 | 1168 | push_changes_summary = mp.get_list_of_push_changes(push_changes) |
@@ -1341,13 +1433,21 @@ def check_collaborators_members_support(self): |
1341 | 1433 | if not is_version_acceptable(self.server_version(), f"{min_version}"): |
1342 | 1434 | raise NotImplementedError(f"This needs server at version {min_version} or later") |
1343 | 1435 |
|
| 1436 | + def check_v2_project_info_support(self): |
| 1437 | + """ |
| 1438 | + Check if the server is compatible with v2 endpoint for project info |
| 1439 | + """ |
| 1440 | + min_version = "2025.8.2" |
| 1441 | + if not is_version_acceptable(self.server_version(), f"{min_version}"): |
| 1442 | + raise NotImplementedError(f"This needs server at version {min_version} or later") |
| 1443 | + |
1344 | 1444 | def create_user( |
1345 | 1445 | self, |
1346 | 1446 | email: str, |
1347 | 1447 | password: str, |
1348 | 1448 | workspace_id: int, |
1349 | 1449 | workspace_role: Union[str, WorkspaceRole], |
1350 | | - username: str = None, |
| 1450 | + username: Optional[str] = None, |
1351 | 1451 | notify_user: bool = False, |
1352 | 1452 | ) -> dict: |
1353 | 1453 | """ |
|
0 commit comments