From 91b806637c8a4ac27aac1cede84bc18e4d03ad77 Mon Sep 17 00:00:00 2001 From: Slawomir Koszewski Date: Sun, 2 Nov 2025 18:34:23 +0100 Subject: [PATCH] Applied from_json() to object initialization. --- devops.py | 125 ++++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/devops.py b/devops.py index 6e6143b..2fc4af6 100644 --- a/devops.py +++ b/devops.py @@ -77,70 +77,53 @@ class Organization: # Return a list of Project instances projects_data = r.json().get("value", []) - return [ - Project(self, - id=proj.get("id"), - name=proj.get("name"), - url=proj.get("url"), - description=proj.get("description"), - ) for proj in projects_data - ] -@auto_properties({"name": "name", "url": "url", "description": "description"}) -class Project: - def __init__(self, - org: Organization, - id: str, - name: str | None = None, - url: str | None = None, - description: str | None = None - ): + project_list = [] + for proj in projects_data: + p = Project(self, project_id=proj.get("id")) + p.from_json(proj) + project_list.append(p) + + return project_list + +@auto_properties({ + "name": "name", + "url": "url", + "description": "description" + }) +class Project(): + def _get(self, project_id: str): + r = self._org.get(f"_apis/projects/{project_id}") + self.from_json(r.json()) + + def __init__(self, org: Organization, project_id: str, **kwargs): self._org = org - - # Check, if the id is a valid UUID try: - self._id = str(UUID(id)) + self._id = str(UUID(project_id)) except ValueError: - raise ValueError(f"Invalid project ID: {self._id}") + raise ValueError(f"Invalid project ID: {project_id}") - if name is not None and url is not None and name != "" and url != "": - self._name = name - self._url = url - self._description = description if description is not None else "" # Ensure description is a string - else: - # Fetch project details from the API - r = org.get(f"_apis/projects/{self._id}") - proj_data = r.json() - self._id = proj_data.get("id", "") - self._name = proj_data.get("name", "") - self._url = proj_data.get("url", "") - self._description = proj_data.get("description", "") + self.set_auto_properties(**kwargs) def __str__(self): return f"Project(name={self._name}, id={self._id})" - def get(self, path: str, params: dict = {}): + def get_path(self, path: str, params: dict = {}): return self._org.get(f"{self._id}/{path.lstrip('/')}", params=params) @property def repositories(self): - r = self.get(f"_apis/git/repositories") + r = self.get_path(f"_apis/git/repositories") repos_data = r.json().get("value", []) - # Return a list of Repository instances - return [ - Repository(self, - id_or_name=repo.get("id"), - name=repo.get("name"), - url=repo.get("url"), - default_branch=repo.get("defaultBranch"), - disabled=repo.get("isDisabled"), - in_maintenance=repo.get("isInMaintenance"), - remote_url=repo.get("remoteUrl"), - ssh_url=repo.get("sshUrl"), - web_url=repo.get("webUrl"), - ) for repo in repos_data - ] + + repository_list = [] + for repo in repos_data: + r = Repository(self, id_or_name=repo.get("id")) + r.from_json(repo) + repository_list.append(r) + + return repository_list @auto_properties({ "name": "name", @@ -154,7 +137,8 @@ class Project: }) class Repository: def _get(self, repo_name: str): - r = self._project.get(f"_apis/git/repositories/{urllib.parse.quote(repo_name)}") + r = self._project.get_path(f"_apis/git/repositories/{urllib.parse.quote(repo_name)}") + self._id = r.json().get("id", None) self.from_json(r.json()) def __init__(self,_project: Project, id_or_name: str, **kwargs): @@ -166,6 +150,11 @@ class Repository: except ValueError: # Id not available, use API to get the repository object self._get(id_or_name) + # Successfully retrieved the repository by name, + # throw an error if automatic properties were set and + # id_or_name was not set to repository id + if kwargs: + raise ValueError("Automatic properties cannot be set when retrieving by name.") return # set other properties if provided @@ -174,34 +163,38 @@ class Repository: def __str__(self): return f"Repository(name={self.name}, id={self._id})" - def _get_path(self, path: str, params: dict = {}): - return self._project.get(f"_apis/git/repositories/{self._id}/{path.lstrip('/')}", params=params) + def get_path(self, path: str, params: dict = {}): + return self._project.get_path(f"_apis/git/repositories/{self._id}/{path.lstrip('/')}", params=params) def _get_items(self, scope_path: str = "/", recursion_level: str = "oneLevel"): - r = self._get_path(f"items", params={"scopePath": scope_path, "recursionLevel": recursion_level}) + r = self.get_path(f"items", params={"scopePath": scope_path, "recursionLevel": recursion_level}) return r.json() @property def items(self): # GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/items?api-version=7.1 - items_data = self._get_items().get("value", []) # Return a list of Item instances - return [ - Item(self, - path=item.get("path"), - object_id=item.get("objectId"), - git_object_type=item.get("gitObjectType"), - commit_id=item.get("commitId"), - is_folder=item.get("isFolder"), - url=item.get("url"), - ) for item in items_data - ] + items_data = self._get_items().get("value", []) -@auto_properties({"object_id": "objectId", "git_object_type": "gitObjectType", "commit_id": "commitId", "is_folder": "isFolder", "url": "url"}) + item_list = [] + for item in items_data: + i = Item(self, path=item.get("path")) + i.from_json(item) + item_list.append(i) + + return item_list + +@auto_properties({ + "object_id": "objectId", + "git_object_type": "gitObjectType", + "commit_id": "commitId", + "is_folder": "isFolder", + "url": "url" + }) class Item: def _get(self, path): - r = self._repository._get_path(f"items/{urllib.parse.quote(path)}") + r = self._repository.get_path(f"items/{urllib.parse.quote(path)}") for name in self.__auto_properties__: setattr(self, f"_{name}", r.json().get(name, None))