Skip to content

Commit 22e38c7

Browse files
authored
feat: always resolve content owner (#224)
1 parent 3a3019b commit 22e38c7

File tree

7 files changed

+102
-13
lines changed

7 files changed

+102
-13
lines changed

integration/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,4 @@ help:
138138
# on local network.
139139
test:
140140
mkdir -p logs
141-
CONNECT_VERSION=${CONNECT_VERSION} CONNECT_API_KEY="$(shell rsconnect bootstrap -i -s http://connect:3939 --raw)" $(PYTHON) -m pytest --junit-xml=./reports/$(CONNECT_VERSION).xml > ./logs/$(CONNECT_VERSION).log
141+
CONNECT_VERSION=${CONNECT_VERSION} CONNECT_API_KEY="$(shell rsconnect bootstrap -i -s http://connect:3939 --raw)" $(PYTHON) -m pytest -s --junit-xml=./reports/$(CONNECT_VERSION).xml | tee ./logs/$(CONNECT_VERSION).log

integration/tests/posit/connect/test_client.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
import os
2-
import pytest
3-
41
from posit import connect
52

63

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from posit import connect
2+
3+
4+
class TestContent:
5+
def setup_class(cls):
6+
cls.client = connect.Client()
7+
cls.item = cls.client.content.create(
8+
name="Sample",
9+
description="Simple sample content for testing",
10+
access_type="acl",
11+
)
12+
13+
def test_count(self):
14+
assert self.client.content.count() == 1
15+
16+
def test_get(self):
17+
assert self.client.content.get(self.item.guid) == self.item
18+
19+
def test_find(self):
20+
assert self.client.content.find()
21+
22+
def test_find_one(self):
23+
assert self.client.content.find_one()
24+
25+
def test_content_item_owner(self):
26+
item = self.client.content.find_one(include=None)
27+
owner = item.owner
28+
assert owner.guid == self.client.me.guid
29+
30+
def test_content_item_owner_from_include(self):
31+
item = self.client.content.find_one(include="owner")
32+
owner = item.owner
33+
assert owner.guid == self.client.me.guid

src/posit/connect/content.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from .bundles import Bundles
1414
from .permissions import Permissions
1515
from .resources import Resources, Resource
16+
from .users import Users
1617

1718

1819
class ContentItemOwner(Resource):
@@ -146,6 +147,17 @@ def bundles(self) -> Bundles:
146147
def permissions(self) -> Permissions:
147148
return Permissions(self.config, self.session, self.guid)
148149

150+
@property
151+
def owner(self) -> ContentItemOwner:
152+
if "owner" not in self:
153+
# It is possible to get a content item that does not contain owner.
154+
# "owner" is an optional additional request param.
155+
# If it's not included, we can retrieve the information by `owner_guid`
156+
self["owner"] = Users(self.config, self.session).get(
157+
self.owner_guid
158+
)
159+
return ContentItemOwner(self.config, self.session, **self["owner"])
160+
149161
# Properties
150162

151163
@property
@@ -308,10 +320,6 @@ def run_as_current_user(self) -> bool:
308320
def owner_guid(self) -> str:
309321
return self.get("owner_guid") # type: ignore
310322

311-
@property
312-
def owner(self) -> ContentItemOwner:
313-
return self.get("owner", {}) # type: ignore
314-
315323
@property
316324
def content_url(self) -> str:
317325
return self.get("content_url") # type: ignore

tests/posit/connect/__api__/v1/content/f2f37341-e21d-3d80-c698-a935ad614066.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
"default_py_environment_management": null,
3838
"run_as": null,
3939
"run_as_current_user": false,
40-
"owner_guid": "87c12c08-11cd-4de1-8da3-12a7579c4998",
40+
"owner_guid": "20a79ce3-6e87-4522-9faf-be24228800a4",
4141
"content_url": "https://connect.example/content/f2f37341-e21d-3d80-c698-a935ad614066/",
4242
"dashboard_url": "https://connect.example/connect/#/apps/f2f37341-e21d-3d80-c698-a935ad614066",
4343
"app_role": "viewer",

tests/posit/connect/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@
1010
"confirmed": true,
1111
"locked": false,
1212
"guid": "20a79ce3-6e87-4522-9faf-be24228800a4"
13-
}
13+
}

tests/posit/connect/test_content.py

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,34 @@
55

66
from posit.connect.client import Client
77
from posit.connect.config import Config
8-
from posit.connect.content import ContentItem
8+
from posit.connect.content import ContentItem, ContentItemOwner
99
from posit.connect.permissions import Permissions
1010

1111
from .api import load_mock # type: ignore
1212

1313

14+
class TestContentOwnerAttributes:
15+
@classmethod
16+
def setup_class(cls):
17+
guid = "20a79ce3-6e87-4522-9faf-be24228800a4"
18+
config = Config(api_key="12345", url="https://connect.example/")
19+
session = requests.Session()
20+
fake_item = load_mock(f"v1/users/{guid}.json")
21+
cls.item = ContentItemOwner(config, session, **fake_item)
22+
23+
def test_guid(self):
24+
assert self.item.guid == "20a79ce3-6e87-4522-9faf-be24228800a4"
25+
26+
def test_username(self):
27+
assert self.item.username == "carlos12"
28+
29+
def test_first_name(self):
30+
assert self.item.first_name == "Carlos"
31+
32+
def test_last_name(self):
33+
assert self.item.last_name == "User"
34+
35+
1436
class TestContentItemAttributes:
1537
@classmethod
1638
def setup_class(cls):
@@ -138,7 +160,7 @@ def test_run_as_current_user(self):
138160
assert self.item.run_as_current_user is False
139161

140162
def test_owner_guid(self):
141-
assert self.item.owner_guid == "87c12c08-11cd-4de1-8da3-12a7579c4998"
163+
assert self.item.owner_guid == "20a79ce3-6e87-4522-9faf-be24228800a4"
142164

143165
def test_content_url(self):
144166
assert (
@@ -156,7 +178,7 @@ def test_app_role(self):
156178
assert self.item.app_role == "viewer"
157179

158180
def test_owner(self):
159-
assert self.item.owner == {}
181+
assert "owner" not in self.item
160182

161183
def test_permissions(self):
162184
assert isinstance(self.item.permissions, Permissions)
@@ -165,6 +187,35 @@ def test_tags(self):
165187
assert self.item.tags == []
166188

167189

190+
class TestContentItemGetContentOwner:
191+
@responses.activate
192+
def test_owner(self):
193+
mock_content = load_mock(
194+
"v1/content/f2f37341-e21d-3d80-c698-a935ad614066.json"
195+
)
196+
responses.get(
197+
"https://connect.example/__api__/v1/content/f2f37341-e21d-3d80-c698-a935ad614066",
198+
json=mock_content,
199+
)
200+
201+
mock_user_get = responses.get(
202+
f"https://connect.example/__api__/v1/users/20a79ce3-6e87-4522-9faf-be24228800a4",
203+
json=load_mock(
204+
f"v1/users/20a79ce3-6e87-4522-9faf-be24228800a4.json"
205+
),
206+
)
207+
208+
c = Client("12345", "https://connect.example")
209+
item = c.content.get("f2f37341-e21d-3d80-c698-a935ad614066")
210+
owner = item.owner
211+
assert owner.guid == "20a79ce3-6e87-4522-9faf-be24228800a4"
212+
213+
# load a second time, assert tha owner is loaded from cached result
214+
owner = item.owner
215+
assert owner.guid == "20a79ce3-6e87-4522-9faf-be24228800a4"
216+
assert mock_user_get.call_count == 1
217+
218+
168219
class TestContentItemDelete:
169220
@responses.activate
170221
def test(self):

0 commit comments

Comments
 (0)