Repository: posit-dev/posit-sdk-py

Issue:
Use the API response to update the local object

Discussion:
github-actions[bot]: # ☂️ Python Coverage
> current status: ✅
## Overall Coverage
| Lines | Covered | Coverage | Threshold | Status |
| :---: | :-----: | :------: | :-------: | :----: |
|  520  |   432   |    83%   |    80%    |   🟢   |
## New Files
No new covered files...
## Modified Files
| File                        | Coverage | Status |
| :-------------------------- | :------: | :----: |
| src/posit/connect/client.py |   100%   |   🟢   |
| src/posit/connect/users.py  |    91%   |   🟢   |
| **TOTAL**                   |  **96%** |   🟢   |


> **updated for commit: `7bc16b4` by [action](https://github.com/marketplace/actions/python-coverage)🐍**

Patch:
diff --git a/src/posit/connect/client.py b/src/posit/connect/client.py
index 3983c00..e561074 100644
--- a/src/posit/connect/client.py
+++ b/src/posit/connect/client.py
@@ -50,7 +50,11 @@ class Client:
     def me(self) -> User:
         url = urls.append_path(self.config.url, "v1/user")
         response = self.session.get(url)
-        return User(self.session, url, **response.json())
+        body = response.json()
+        # Build the canonical URL for the User based on its GUID
+        guid = body["guid"]
+        url = urls.append_path(self.config.url, f"v1/users/{guid}")
+        return User(self.session, url, **body)
 
     @property
     def oauth(self) -> OAuthIntegration:
diff --git a/src/posit/connect/users.py b/src/posit/connect/users.py
index 6ec062b..41551b8 100644
--- a/src/posit/connect/users.py
+++ b/src/posit/connect/users.py
@@ -58,12 +58,10 @@ class User(Resource):
         return self.get("locked")  # type: ignore
 
     def _update(self, body):
-        self.session.patch(self.url, json=body)
-        # If the request is successful, update the local object
-        super().update(body)
-        # TODO(#99): that patch request returns a payload on success,
-        # so we should instead update the local object with that payload
-        # (includes updated_time)
+        if len(body) == 0:
+            return
+        response = self.session.put(self.url, json=body)
+        super().update(**response.json())
 
     def update(  # type: ignore
         self,


Test patch:
diff --git a/tests/posit/connect/test_client.py b/tests/posit/connect/test_client.py
index ff7bb2f..22b4ac8 100644
--- a/tests/posit/connect/test_client.py
+++ b/tests/posit/connect/test_client.py
@@ -84,7 +84,12 @@ class TestClient:
         )
 
         con = Client(api_key="12345", url="https://connect.example/")
-        assert con.me["username"] == "carlos12"
+        assert con.me.username == "carlos12"
+        # Check that the URL was constructed correctly
+        assert (
+            con.me.url
+            == "https://connect.example/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4"
+        )
 
     def test_request(self, MockSession):
         api_key = "foobar"
diff --git a/tests/posit/connect/test_users.py b/tests/posit/connect/test_users.py
index c12cbe4..237c2d7 100644
--- a/tests/posit/connect/test_users.py
+++ b/tests/posit/connect/test_users.py
@@ -1,9 +1,10 @@
 from unittest.mock import Mock
+
 import pandas as pd
 import pytest
+import requests
 import responses
 
-
 from posit.connect.client import Client
 from posit.connect.users import User
 
@@ -219,9 +220,10 @@ class TestUsers:
             "https://connect.example/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4",
             json=load_mock("v1/users/20a79ce3-6e87-4522-9faf-be24228800a4.json"),
         )
-        patch_request = responses.patch(
+        patch_request = responses.put(
             "https://connect.example/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4",
             match=[responses.matchers.json_params_matcher({"first_name": "Carlitos"})],
+            json={"first_name": "Carlitos"},
         )
 
         con = Client(api_key="12345", url="https://connect.example/")
@@ -234,10 +236,22 @@ class TestUsers:
 
         assert patch_request.call_count == 1
         assert carlos.first_name == "Carlitos"
-        # TODO(#99):
-        # * test setting the other fields
-        # * test invalid field
-        # * error response (e.g. not authorized)
+
+    @responses.activate
+    def test_user_update_server_error(self):
+        responses.get(
+            "https://connect.example/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4",
+            json=load_mock("v1/users/20a79ce3-6e87-4522-9faf-be24228800a4.json"),
+        )
+        responses.put(
+            "https://connect.example/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4",
+            status=500,
+        )
+
+        con = Client(api_key="12345", url="https://connect.example/")
+        carlos = con.users.get("20a79ce3-6e87-4522-9faf-be24228800a4")
+        with pytest.raises(requests.HTTPError, match="500 Server Error"):
+            carlos.update(first_name="Carlitos")
 
     @responses.activate
     def test_user_cant_setattr(self):