From 8c60ad7491b37767ccb0dc6849b2dc6ffed7f4c6 Mon Sep 17 00:00:00 2001 From: tdstein Date: Thu, 21 Mar 2024 14:24:45 -0400 Subject: [PATCH 1/4] refactor: adds override definition for type hinting supported fields --- src/posit/connect/content.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/posit/connect/content.py b/src/posit/connect/content.py index 3bedade8..7cb1cba7 100644 --- a/src/posit/connect/content.py +++ b/src/posit/connect/content.py @@ -11,6 +11,37 @@ from .resources import Resources, Resource +_UPDATE_FIELDS = frozenset( + { + "name", + "title", + "description", + "access_type", + "owner_guid", + "connection_timeout", + "read_timeout", + "init_timeout", + "idle_timeout", + "max_processes", + "min_processes", + "max_conns_per_process", + "load_factor", + "cpu_request", + "cpu_limit", + "memory_request", + "memory_limit", + "amd_gpu_limit", + "nvidia_gpu_limit", + "run_as", + "run_as_current_user", + "default_image_name", + "default_r_environment_management", + "default_py_environment_management", + "service_account_name", + } +) + + class ContentItem(Resource): @property def guid(self) -> str: From 9647a0ae35c368b4c8df1226d2191ff53e6c8d28 Mon Sep 17 00:00:00 2001 From: tdstein Date: Thu, 21 Mar 2024 20:01:24 -0400 Subject: [PATCH 2/4] defers field validation to the server --- src/posit/connect/content.py | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/posit/connect/content.py b/src/posit/connect/content.py index 7cb1cba7..3bedade8 100644 --- a/src/posit/connect/content.py +++ b/src/posit/connect/content.py @@ -11,37 +11,6 @@ from .resources import Resources, Resource -_UPDATE_FIELDS = frozenset( - { - "name", - "title", - "description", - "access_type", - "owner_guid", - "connection_timeout", - "read_timeout", - "init_timeout", - "idle_timeout", - "max_processes", - "min_processes", - "max_conns_per_process", - "load_factor", - "cpu_request", - "cpu_limit", - "memory_request", - "memory_limit", - "amd_gpu_limit", - "nvidia_gpu_limit", - "run_as", - "run_as_current_user", - "default_image_name", - "default_r_environment_management", - "default_py_environment_management", - "service_account_name", - } -) - - class ContentItem(Resource): @property def guid(self) -> str: From 1b712ba17fe1af2fe042a22b37d0ebe8c5925d46 Mon Sep 17 00:00:00 2001 From: tdstein Date: Thu, 21 Mar 2024 19:53:16 -0400 Subject: [PATCH 3/4] refactor: consistent update method signature --- src/posit/connect/content.py | 13 ++++++++++++- src/posit/connect/users.py | 30 +----------------------------- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/src/posit/connect/content.py b/src/posit/connect/content.py index 3bedade8..e1d964bf 100644 --- a/src/posit/connect/content.py +++ b/src/posit/connect/content.py @@ -249,7 +249,18 @@ def update( ... @overload - def update(self, *args, **kwargs) -> None: ... + def update(self, *args, **kwargs) -> None: + """ + Update the content item. + + Args: + *args + **kwargs + + Returns: + None + """ + ... def update(self, *args, **kwargs) -> None: """ diff --git a/src/posit/connect/users.py b/src/posit/connect/users.py index ba48be18..0f41d23c 100644 --- a/src/posit/connect/users.py +++ b/src/posit/connect/users.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import List, Optional +from typing import List import requests @@ -98,34 +98,6 @@ def _update(self, body): response = self.session.put(url, json=body) super().update(**response.json()) - def update( # type: ignore - self, - # Not all properties are settable, so we enumerate them here - # (also for type-hinting purposes) - email: Optional[str] = None, - username: Optional[str] = None, - first_name: Optional[str] = None, - last_name: Optional[str] = None, - user_role: Optional[str] = None, - # TODO(#100): in the API, this goes via POST /v1/users/{guid}/lock - # accept it here and make that request? Or add a .lock() method? - # locked: Optional[bool] = None, - ) -> None: - kwargs = {} - if email is not None: - kwargs["email"] = email - if username is not None: - kwargs["username"] = username - if first_name is not None: - kwargs["first_name"] = first_name - if last_name is not None: - kwargs["last_name"] = last_name - if user_role is not None: - kwargs["user_role"] = user_role - # if locked is not None: - # kwargs["locked"] = locked - self._update(kwargs) - class Users(Resources[User]): def __init__(self, config: Config, session: requests.Session) -> None: From 93566877ef16a4e7391354caf956f6163df5dd87 Mon Sep 17 00:00:00 2001 From: tdstein Date: Fri, 22 Mar 2024 13:21:35 -0400 Subject: [PATCH 4/4] adds update pattern to user --- .coveragerc | 10 ++++++- src/posit/connect/users.py | 55 +++++++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/.coveragerc b/.coveragerc index a86b4247..401dc6fd 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,2 +1,10 @@ +# This file contains the configuration settings for the coverage report generated. + [report] - fail_under = 80 +# exclude '...' (ellipsis literal). This option uses regex, so an escaped literal is required. +# exclude 'raise NotImplementedError()'. +exclude_also = + \.\.\. + raise NotImplementedError() + +fail_under = 80 diff --git a/src/posit/connect/users.py b/src/posit/connect/users.py index 0f41d23c..67fcbdaf 100644 --- a/src/posit/connect/users.py +++ b/src/posit/connect/users.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import List +from typing import List, overload import requests @@ -91,9 +91,56 @@ def unlock(self): self.session.post(url, json=body) super().update(locked=False) - def _update(self, body): - if len(body) == 0: - return + @overload + def update( + self, + email: str = ..., + username: str = ..., + first_name: str = ..., + last_name: str = ..., + user_role: str = ..., + ) -> None: + """ + Update the user. + + Args: + email (str): The email address for the user. + username (str): The username for the user. + first_name (str): The first name for the user. + last_name (str): The last name for the user. + user_role (str): The role for the user. + + Returns: + None + """ + ... + + @overload + def update(self, *args, **kwargs) -> None: + """ + Update the user. + + Args: + *args + **kwargs + + Returns: + None + """ + ... + + def update(self, *args, **kwargs) -> None: + """ + Update the user. + + Args: + *args + **kwargs + + Returns: + None + """ + body = dict(*args, **kwargs) url = urls.append_path(self.config.url, f"v1/users/{self.guid}") response = self.session.put(url, json=body) super().update(**response.json())