Skip to content

Commit

Permalink
feat: adds groups (#227)
Browse files Browse the repository at this point in the history
  • Loading branch information
tdstein authored Jun 25, 2024
1 parent 9a660b5 commit 6ce4066
Show file tree
Hide file tree
Showing 6 changed files with 276 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ quartodoc:
contents:
- connect.bundles
- connect.content
- connect.groups
- connect.permissions
- connect.tasks
- connect.users
Expand Down
23 changes: 23 additions & 0 deletions integration/tests/posit/connect/test_groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from posit import connect


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

def teardown_class(cls):
cls.item.delete()
assert cls.client.groups.count() == 0

def test_count(self):
assert self.client.groups.count() == 1

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

def test_find(self):
assert self.client.groups.find() == [self.item]

def test_find_one(self):
assert self.client.groups.find_one() == self.item
12 changes: 12 additions & 0 deletions src/posit/connect/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .metrics import Metrics
from .tasks import Tasks
from .users import User, Users
from .groups import Groups


class Client:
Expand Down Expand Up @@ -94,6 +95,17 @@ def oauth(self) -> OAuthIntegration:
"""
return OAuthIntegration(config=self.config, session=self.session)

@property
def groups(self) -> Groups:
"""The groups resource interface.
Returns
-------
Groups
The groups resource interface.
"""
return Groups(self.config, self.session)

@property
def tasks(self) -> Tasks:
"""
Expand Down
201 changes: 201 additions & 0 deletions src/posit/connect/groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
"""Group resources."""

from __future__ import annotations
from typing import List, overload

import requests

from . import me, urls

from .config import Config
from .paginator import Paginator
from .resources import Resource, Resources


class Group(Resource):
"""Group resource.
Attributes
----------
guid : str
name: str
owner_guid: str
"""

@property
def guid(self) -> str:
return self.get("guid") # type: ignore

@property
def name(self) -> str:
return self.get("name") # type: ignore

@property
def owner_guid(self) -> str:
return self.get("owner_guid") # type: ignore

# CRUD Methods

def delete(self) -> None:
"""Delete the group."""
path = f"v1/groups/{self.guid}"
url = urls.append(self.config.url, path)
self.session.delete(url)


class Groups(Resources):
"""Groups resource."""

def __init__(self, config: Config, session: requests.Session) -> None:
self.config = config
self.session = session

@overload
def create(self, name: str, unique_id: str | None) -> Group:
"""Create a group.
Parameters
----------
name: str
unique_id: str | None
Returns
-------
Group
"""
...

@overload
def create(self, *args, **kwargs) -> Group:
"""Create a group.
Returns
-------
Group
"""
...

def create(self, *args, **kwargs) -> Group:
"""Create a group.
Parameters
----------
name: str
unique_id: str | None
Returns
-------
Group
"""
...
body = dict(*args, **kwargs)
path = "v1/groups"
url = urls.append(self.config.url, path)
response = self.session.post(url, json=body)
return Group(self.config, self.session, **response.json())

@overload
def find(
self,
prefix: str = ...,
) -> List[Group]: ...

@overload
def find(self, *args, **kwargs) -> List[Group]: ...

def find(self, *args, **kwargs):
"""Find groups.
Parameters
----------
prefix: str
Filter by group name prefix. Casing is ignored.
Returns
-------
List[Group]
"""
params = dict(*args, **kwargs)
path = "v1/groups"
url = urls.append(self.config.url, path)
paginator = Paginator(self.session, url, params=params)
results = paginator.fetch_results()
return [
Group(
config=self.config,
session=self.session,
**result,
)
for result in results
]

@overload
def find_one(
self,
prefix: str = ...,
) -> Group | None: ...

@overload
def find_one(self, *args, **kwargs) -> Group | None: ...

def find_one(self, *args, **kwargs) -> Group | None:
"""Find one group.
Parameters
----------
prefix: str
Filter by group name prefix. Casing is ignored.
Returns
-------
Group | None
"""
params = dict(*args, **kwargs)
path = "v1/groups"
url = urls.append(self.config.url, path)
paginator = Paginator(self.session, url, params=params)
pages = paginator.fetch_pages()
results = (result for page in pages for result in page.results)
groups = (
Group(
config=self.config,
session=self.session,
**result,
)
for result in results
)
return next(groups, None)

def get(self, guid: str) -> Group:
"""Get group.
Parameters
----------
guid : str
Returns
-------
Group
"""
url = urls.append(self.config.url, f"v1/groups/{guid}")
response = self.session.get(url)
return Group(
config=self.config,
session=self.session,
**response.json(),
)

def count(self) -> int:
"""Count the number of groups.
Returns
-------
int
"""
path = "v1/groups"
url = urls.append(self.config.url, path)
response: requests.Response = self.session.get(
url, params={"page_size": 1}
)
result: dict = response.json()
return result["total"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"guid": "6f300623-1e0c-48e6-a473-ddf630c0c0c3",
"name": "Friends",
"owner_guid": "20a79ce3-6e87-4522-9faf-be24228800a4"
}
34 changes: 34 additions & 0 deletions tests/posit/connect/test_groups.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from unittest.mock import Mock

import pytest
import requests
import responses


from posit.connect.client import Client
from posit.connect.config import Config
from posit.connect.groups import Group

from .api import load_mock # type: ignore

session = Mock()
url = Mock()


class TestGroupAttributes:
@classmethod
def setup_class(cls):
guid = "6f300623-1e0c-48e6-a473-ddf630c0c0c3"
config = Config(api_key="12345", url="https://connect.example.com/")
session = requests.Session()
fake_item = load_mock(f"v1/groups/{guid}.json")
cls.item = Group(config, session, **fake_item)

def test_guid(self):
assert self.item.guid == "6f300623-1e0c-48e6-a473-ddf630c0c0c3"

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

def test_owner_guid(self):
assert self.item.owner_guid == "20a79ce3-6e87-4522-9faf-be24228800a4"

0 comments on commit 6ce4066

Please sign in to comment.