Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove all warnings from attribute access #323

Merged
merged 2 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ def test_find_update_by_content(self):
updated_associations = self.content.oauth.associations.find()
assert len(updated_associations) == 1
assert updated_associations[0]["app_guid"] == self.content["guid"]
assert updated_associations[0]["oauth_integration_guid"] == self.another_integration.guid
assert (
updated_associations[0]["oauth_integration_guid"] == self.another_integration["guid"]
)

# unset content association
self.content.oauth.associations.delete()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_create_update_delete(self):

created.update(name="updated integration name")
updated = self.client.oauth.integrations.get(integration["guid"])
assert updated.name == "updated integration name"
assert updated["name"] == "updated integration name"

# delete the new integration

Expand Down
4 changes: 3 additions & 1 deletion integration/tests/posit/connect/test_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@


class TestGroups:
@classmethod
def setup_class(cls):
cls.client = connect.Client()
cls.item = cls.client.groups.create(name="Friends")

@classmethod
def teardown_class(cls):
cls.item.delete()
assert cls.client.groups.count() == 0
Expand All @@ -14,7 +16,7 @@ def test_count(self):
assert self.client.groups.count() == 1

def test_get(self):
assert self.client.groups.get(self.item.guid)
assert self.client.groups.get(self.item["guid"])

def test_find(self):
assert self.client.groups.find() == [self.item]
Expand Down
8 changes: 4 additions & 4 deletions src/posit/connect/bundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def metadata(self) -> BundleMetadata:

def delete(self) -> None:
"""Delete the bundle."""
path = f"v1/content/{self.content_guid}/bundles/{self.id}"
path = f"v1/content/{self['content_guid']}/bundles/{self['id']}"
url = self.params.url + path
self.params.session.delete(url)

Expand All @@ -39,9 +39,9 @@ def deploy(self) -> tasks.Task:
>>> task.wait_for()
None
"""
path = f"v1/content/{self.content_guid}/deploy"
path = f"v1/content/{self['content_guid']}/deploy"
url = self.params.url + path
response = self.params.session.post(url, json={"bundle_id": self.id})
response = self.params.session.post(url, json={"bundle_id": self["id"]})
result = response.json()
ts = tasks.Tasks(self.params)
return ts.get(result["task_id"])
Expand Down Expand Up @@ -77,7 +77,7 @@ def download(self, output: io.BufferedWriter | str) -> None:
f"download() expected argument type 'io.BufferedWriter` or 'str', but got '{type(output).__name__}'",
)

path = f"v1/content/{self.content_guid}/bundles/{self.id}/download"
path = f"v1/content/{self['content_guid']}/bundles/{self['id']}/download"
url = self.params.url + path
response = self.params.session.get(url, stream=True)
if isinstance(output, io.BufferedWriter):
Expand Down
16 changes: 8 additions & 8 deletions src/posit/connect/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def oauth(self) -> ContentItemOAuth:

def delete(self) -> None:
"""Delete the content item."""
path = f"v1/content/{self.guid}"
path = f"v1/content/{self['guid']}"
url = self.params.url + path
self.params.session.delete(url)

Expand All @@ -75,7 +75,7 @@ def deploy(self) -> tasks.Task:
>>> task.wait_for()
None
"""
path = f"v1/content/{self.guid}/deploy"
path = f"v1/content/{self['guid']}/deploy"
url = self.params.url + path
response = self.params.session.post(url, json={"bundle_id": None})
result = response.json()
Expand All @@ -99,7 +99,7 @@ def render(self) -> Task:

if self.is_rendered:
variants = self._variants.find()
variants = [variant for variant in variants if variant.is_default]
variants = [variant for variant in variants if variant["is_default"]]
if len(variants) != 1:
raise RuntimeError(
f"Found {len(variants)} default variants. Expected 1. Without a single default variant, the content cannot be refreshed. This is indicative of a corrupted state.",
Expand All @@ -108,7 +108,7 @@ def render(self) -> Task:
return variant.render()
else:
raise ValueError(
f"Render not supported for this application mode: {self.app_mode}. Did you need to use the 'restart()' method instead? Note that some application modes do not support 'render()' or 'restart()'.",
f"Render not supported for this application mode: {self['app_mode']}. Did you need to use the 'restart()' method instead? Note that some application modes do not support 'render()' or 'restart()'.",
)

def restart(self) -> None:
Expand All @@ -132,12 +132,12 @@ def restart(self) -> None:
self.environment_variables.create(key, unix_epoch_in_seconds)
self.environment_variables.delete(key)
# GET via the base Connect URL to force create a new worker thread.
url = posixpath.join(dirname(self.params.url), f"content/{self.guid}")
url = posixpath.join(dirname(self.params.url), f"content/{self['guid']}")
self.params.session.get(url)
return None
else:
raise ValueError(
f"Restart not supported for this application mode: {self.app_mode}. Did you need to use the 'render()' method instead? Note that some application modes do not support 'render()' or 'restart()'.",
f"Restart not supported for this application mode: {self['app_mode']}. Did you need to use the 'render()' method instead? Note that some application modes do not support 'render()' or 'restart()'.",
)

@overload
Expand Down Expand Up @@ -276,7 +276,7 @@ def _variants(self) -> Variants:

@property
def is_interactive(self) -> bool:
return self.app_mode in {
return self["app_mode"] in {
"api",
"jupyter-voila",
"python-api",
Expand All @@ -293,7 +293,7 @@ def is_interactive(self) -> bool:

@property
def is_rendered(self) -> bool:
return self.app_mode in {
return self["app_mode"] in {
"rmd-static",
"jupyter-static",
"quarto-static",
Expand Down
2 changes: 1 addition & 1 deletion src/posit/connect/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class Group(Resource):
def delete(self) -> None:
"""Delete the group."""
path = f"v1/groups/{self.guid}"
path = f"v1/groups/{self['guid']}"
url = self.params.url + path
self.params.session.delete(url)

Expand Down
10 changes: 5 additions & 5 deletions src/posit/connect/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
class Permission(Resource):
def delete(self) -> None:
"""Delete the permission."""
path = f"v1/content/{self.content_guid}/permissions/{self.id}"
path = f"v1/content/{self['content_guid']}/permissions/{self['id']}"
url = self.params.url + path
self.params.session.delete(url)

Expand All @@ -33,13 +33,13 @@ def update(self, *args, **kwargs) -> None:
def update(self, *args, **kwargs) -> None:
"""Update the permission."""
body = {
"principal_guid": self.principal_guid,
"principal_type": self.principal_type,
"role": self.role,
"principal_guid": self.get("principal_guid"),
"principal_type": self.get("principal_type"),
"role": self.get("role"),
}
body.update(dict(*args))
body.update(**kwargs)
path = f"v1/content/{self.content_guid}/permissions/{self.id}"
path = f"v1/content/{self['content_guid']}/permissions/{self['id']}"
url = self.params.url + path
response = self.params.session.put(
url,
Expand Down
2 changes: 1 addition & 1 deletion src/posit/connect/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def update(self, *args, **kwargs) -> None:
]
"""
params = dict(*args, **kwargs)
path = f"v1/tasks/{self.id}"
path = f"v1/tasks/{self['id']}"
url = self.params.url + path
response = self.params.session.get(url, params=kwargs)
result = response.json()
Expand Down
2 changes: 1 addition & 1 deletion src/posit/connect/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def lock(self, *, force: bool = False):
>>> user.lock(force=True)
"""
_me = me.get(self.params)
if _me.guid == self["guid"] and not force:
if _me["guid"] == self["guid"] and not force:
raise RuntimeError(
"You cannot lock your own account. Set force=True to override this behavior.",
)
Expand Down
68 changes: 9 additions & 59 deletions tests/posit/connect/oauth/test_integrations.py
Original file line number Diff line number Diff line change
@@ -1,61 +1,11 @@
from unittest import mock

import responses
from responses import matchers

from posit.connect.client import Client
from posit.connect.oauth.associations import IntegrationAssociations
from posit.connect.oauth.integrations import Integration

from ..api import load_mock # type: ignore


class TestIntegrationAttributes:
@classmethod
def setup_class(cls):
guid = "22644575-a27b-4118-ad06-e24459b05126"
fake_item = load_mock(f"v1/oauth/integrations/{guid}.json")
schloerke marked this conversation as resolved.
Show resolved Hide resolved
cls.item = Integration(mock.Mock(), **fake_item)

def test_id(self):
assert self.item.id == "3"

def test_guid(self):
assert self.item.guid == "22644575-a27b-4118-ad06-e24459b05126"

def test_name(self):
assert self.item.name == "keycloak integration"

def test_description(self):
assert self.item.description == "integration description"

def test_template(self):
assert self.item.template == "custom"

def test_config(self):
assert self.item.config["auth_mode"] == "Confidential"
assert (
self.item.config["authorization_uri"]
== "http://keycloak:8080/realms/rsconnect/protocol/openid-connect/auth"
)
assert self.item.config["client_id"] == "rsconnect-oidc"
assert self.item.config["scopes"] == "email"
assert self.item.config["token_endpoint_auth_method"] == "client_secret_basic"
assert (
self.item.config["token_uri"]
== "http://keycloak:8080/realms/rsconnect/protocol/openid-connect/token"
)

def test_created_time(self):
assert self.item.created_time == "2024-07-16T19:28:05Z"

def test_updated_time(self):
assert self.item.updated_time == "2024-07-17T19:28:05Z"

def test_associations(self):
assert isinstance(self.item.associations, IntegrationAssociations)


class TestIntegrationDelete:
@responses.activate
def test(self):
Expand Down Expand Up @@ -96,7 +46,7 @@ def test(self):
c = Client("https://connect.example", "12345")
c.ctx.version = None
integration = c.oauth.integrations.get(guid)
assert integration.guid == guid
assert integration["guid"] == guid

new_name = "New Name"

Expand All @@ -111,7 +61,7 @@ def test(self):

integration.update(name=new_name)
assert mock_update.call_count == 1
assert integration.name == new_name
assert integration["name"] == new_name


class TestIntegrationsCreate:
Expand Down Expand Up @@ -151,10 +101,10 @@ def test(self):

# assert
assert mock_create.call_count == 1
assert integration.name == fake_integration["name"]
assert integration.description == fake_integration["description"]
assert integration.template == fake_integration["template"]
assert integration.config == fake_integration["config"]
assert integration["name"] == fake_integration["name"]
assert integration["description"] == fake_integration["description"]
assert integration["template"] == fake_integration["template"]
assert integration["config"] == fake_integration["config"]


class TestIntegrationsFind:
Expand All @@ -176,8 +126,8 @@ def test(self):
# assert
assert mock_get.call_count == 1
assert len(integrations) == 2
assert integrations[0].id == "3"
assert integrations[1].id == "4"
assert integrations[0]["id"] == "3"
assert integrations[1]["id"] == "4"


class TestIntegrationsGet:
Expand All @@ -197,4 +147,4 @@ def test(self):
integration = c.oauth.integrations.get(guid)

assert mock_get.call_count == 1
assert integration.guid == guid
assert integration["guid"] == guid
40 changes: 4 additions & 36 deletions tests/posit/connect/oauth/test_sessions.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,11 @@
from unittest import mock

import responses
from responses import matchers

from posit.connect.client import Client
from posit.connect.oauth.sessions import Session

from ..api import load_mock # type: ignore


class TestOAuthSessionAttributes:
@classmethod
def setup_class(cls):
guid = "32c04dc6-0318-41b7-bc74-7e321b196f14"
fake_item = load_mock(f"v1/oauth/sessions/{guid}.json")
cls.item = Session(mock.Mock(), **fake_item)

def test_id(self):
assert self.item.id == "54"

def test_guid(self):
assert self.item.guid == "32c04dc6-0318-41b7-bc74-7e321b196f14"

def test_user_guid(self):
assert self.item.user_guid == "217be1f2-6a32-46b9-af78-e3f4b89f2e74"

def test_oauth_integration_guid(self):
assert self.item.oauth_integration_guid == "967f0ad3-3e3b-4491-8539-1a193b35a415"

def test_has_refresh_token(self):
assert self.item.has_refresh_token

def test_created_time(self):
assert self.item.created_time == "2024-07-24T15:59:51Z"

def test_updated_time(self):
assert self.item.updated_time == "2024-07-24T16:59:51Z"


class TestSessionDelete:
@responses.activate
def test(self):
Expand Down Expand Up @@ -82,9 +50,9 @@ def test(self):
# assert
assert mock_get.call_count == 1
assert len(sessions) == 3
assert sessions[0].id == "54"
assert sessions[1].id == "55"
assert sessions[2].id == "56"
assert sessions[0]["id"] == "54"
assert sessions[1]["id"] == "55"
assert sessions[2]["id"] == "56"

@responses.activate
def test_params_all(self):
Expand Down Expand Up @@ -126,4 +94,4 @@ def test(self):

# assert
assert mock_get.call_count == 1
assert session.guid == guid
assert session["guid"] == guid
Loading