-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adds partial users implementation based on lists
- Loading branch information
Showing
4 changed files
with
85 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,10 @@ | ||
from .client import Client # noqa | ||
from typing import Optional | ||
|
||
from .client import Client | ||
|
||
|
||
def make_client( | ||
api_key: Optional[str] = None, endpoint: Optional[str] = None | ||
) -> Client: | ||
client = Client(api_key=api_key, endpoint=endpoint) | ||
return client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,75 @@ | ||
from __future__ import annotations | ||
|
||
import os | ||
|
||
from requests import Session, Response | ||
from dataclasses import dataclass, asdict | ||
from datetime import datetime | ||
from requests import Session | ||
from typing import Optional | ||
|
||
|
||
@dataclass | ||
class User: | ||
guid: str | ||
email: str | ||
username: str | ||
first_name: str | ||
last_name: str | ||
user_role: str | ||
created_time: datetime | ||
updated_time: datetime | ||
active_time: datetime | ||
confirmed: bool | ||
locked: bool | ||
|
||
def to_dict(self) -> dict: | ||
return asdict(self) | ||
|
||
|
||
class Users(list[User]): | ||
"""An extension of :class:`list[User]` with additional fetch methods.""" | ||
|
||
_endpoint: str | ||
_session: Session | ||
|
||
class Users: | ||
def __init__(self, endpoint: str, session: Session) -> None: | ||
def __init__(self, endpoint: str, session: Session): | ||
self._endpoint = endpoint | ||
self._session = session | ||
|
||
def get_user(self, user_id: str) -> Response: | ||
endpoint = os.path.join(self._endpoint, "__api__/v1/users", user_id) | ||
return self._session.get(endpoint) | ||
def find(self, params: dict = {}) -> Users: | ||
"""Finds any :class:`User` that matches the provided filter conditions | ||
Keyword Arguments: | ||
params -- filter conditions (default: {{}}) | ||
Returns: | ||
`self` | ||
""" | ||
self.clear() | ||
endpoint = os.path.join(self._endpoint, "__api__/v1/users") | ||
response = self._session.get(endpoint) | ||
data = response.json() | ||
for user in data["results"]: | ||
if all(user.get(k) == v for k, v in params.items()): | ||
self.append(User(**user)) | ||
# todo - implement paging and caching | ||
return self | ||
|
||
def find_one(self, params: dict = {}) -> Optional[User]: | ||
"""Finds one :class:`User` | ||
Keyword Arguments: | ||
params -- filter conditions (default: {{}}) | ||
Returns: | ||
A matching :class:`User`. | ||
""" | ||
if "guid" in params: | ||
# Use the user details API if a 'guid' is provided. | ||
# This is an example of how we can use different API endpoints to optimize execution time. | ||
endpoint = os.path.join(self._endpoint, "__api__/v1/users", params["guid"]) | ||
response = self._session.get(endpoint) | ||
return User(**response.json()) | ||
|
||
def get_current_user(self) -> Response: | ||
endpoint = os.path.join(self._endpoint, "__api__/v1/user") | ||
return self._session.get(endpoint) | ||
# Otherwise, perform a normal search. | ||
return next(iter(self.find(params)), None) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +0,0 @@ | ||
from unittest.mock import Mock | ||
|
||
from .users import Users | ||
|
||
|
||
class TestUsers: | ||
def test_get_user(self): | ||
session = Mock() | ||
session.get = Mock(return_value={}) | ||
users = Users(endpoint="http://foo.bar/", session=session) | ||
response = users.get_user(user_id="foo") | ||
assert response == {} | ||
session.get.assert_called_once_with("http://foo.bar/__api__/v1/users/foo") | ||
|
||
def test_get_current_user(self): | ||
session = Mock() | ||
session.get = Mock(return_value={}) | ||
users = Users(endpoint="http://foo.bar/", session=session) | ||
response = users.get_current_user() | ||
assert response == {} | ||
session.get.assert_called_once_with("http://foo.bar/__api__/v1/user") | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
from posit.connect.client import Client | ||
from posit.connect import make_client | ||
|
||
client = Client() | ||
res = client.users.get_current_user() | ||
print(res.json()) | ||
client = make_client() | ||
for user in client.users.find({"username": "aaron"}): | ||
print(user) | ||
|
||
print(client.users.find_one()) | ||
|
||
print(client.users.find_one({"guid": "f155520a-ca2e-4084-b0a0-12120b7d1add"})) |