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: adds page size validation #26

Merged
merged 1 commit into from
Feb 16, 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
4 changes: 2 additions & 2 deletions src/posit/connect/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from .auth import Auth
from .config import Config
from .users import LazyUsers, Users
from .users import Users, CachedUsers


@contextmanager
Expand Down Expand Up @@ -54,7 +54,7 @@ def __init__(
session.hooks["response"].append(hooks.handle_errors)

# Initialize the Users instance.
self.users: Users = LazyUsers(config=config, session=session)
self.users: CachedUsers = Users(config=config, session=session)
# Store the Session object.
self._session = session

Expand Down
6 changes: 3 additions & 3 deletions src/posit/connect/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def test(self, Client: MagicMock):


class TestClient:
@patch("posit.connect.client.LazyUsers")
@patch("posit.connect.client.Users")
@patch("posit.connect.client.Session")
@patch("posit.connect.client.Config")
@patch("posit.connect.client.Auth")
Expand All @@ -22,7 +22,7 @@ def test_init(
Auth: MagicMock,
Config: MagicMock,
Session: MagicMock,
LazyUsers: MagicMock,
Users: MagicMock,
):
api_key = "foobar"
endpoint = "http://foo.bar"
Expand All @@ -31,7 +31,7 @@ def test_init(
Auth.assert_called_once_with(config=config)
Config.assert_called_once_with(api_key=api_key, endpoint=endpoint)
Session.assert_called_once()
LazyUsers.assert_called_once_with(config=config, session=Session.return_value)
Users.assert_called_once_with(config=config, session=Session.return_value)

@patch("posit.connect.client.Session")
@patch("posit.connect.client.Auth")
Expand Down
6 changes: 3 additions & 3 deletions src/posit/connect/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ class Resource(TypedDict):
T = TypeVar("T", bound=Resource)


class Resources(ABC, Generic[T], Iterator[T]):
class CachedResources(ABC, Generic[T], Iterator[T]):
def __init__(self, data: List[T] = []) -> None:
super().__init__()
self.data = data

@abstractmethod
def find(self, *args, **kwargs) -> Resources[T]:
def find(self, *args, **kwargs) -> CachedResources[T]:
raise NotImplementedError()

@abstractmethod
Expand Down Expand Up @@ -50,7 +50,7 @@ def to_pandas(self):
return None


class LazyResources(Resources[T]):
class Resources(CachedResources[T]):
def __init__(self, data: List[T] = []) -> None:
super().__init__(data)
self.data = data
Expand Down
12 changes: 6 additions & 6 deletions src/posit/connect/resources_test.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from typing import Iterator, Tuple, Optional
from unittest.mock import Mock

from .resources import Resource, Resources, LazyResources
from .resources import Resource, CachedResources, Resources


class FakeResource(Resource):
pass


class FakeResources(Resources[FakeResource]):
def find(self) -> Resources[FakeResource]:
class FakeCachedResources(CachedResources[FakeResource]):
def find(self) -> CachedResources[FakeResource]:
return self

def find_one(self) -> Optional[FakeResource]:
Expand All @@ -21,20 +21,20 @@ def get(self, _: str) -> FakeResource:

class TestResources:
def test(self):
resources = FakeResources()
resources = FakeCachedResources()
assert resources == resources.find()
assert resources.find_one()
assert resources.get(None)


class FakeLazyResources(FakeResources, LazyResources):
class FakeResources(FakeCachedResources, Resources):
def fetch(self, index) -> Tuple[Optional[Iterator[FakeResource]], bool]:
return iter([FakeResource()]), len(self.data) > 0


class TestFakeLazyResources:
def test(self):
resources = FakeLazyResources()
resources = FakeResources()
assert resources == resources.find()
assert resources.find_one()
assert resources.get(None)
16 changes: 11 additions & 5 deletions src/posit/connect/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
from requests import Session

from .config import Config
from .resources import LazyResources, Resource, Resources
from .resources import Resources, Resource, CachedResources

# The maximum page size supported by the API.
_MAX_PAGE_SIZE = 500


Expand All @@ -27,9 +28,9 @@ class User(Resource, total=False):
locked: bool


class Users(Resources[User]):
def find(self, filter: Callable[[User], bool] = lambda _: True) -> Users:
return Users([user for user in self if filter(user)])
class CachedUsers(CachedResources[User]):
def find(self, filter: Callable[[User], bool] = lambda _: True) -> CachedUsers:
return CachedUsers([user for user in self if filter(user)])

def find_one(self, filter: Callable[[User], bool] = lambda _: True) -> User | None:
return next((user for user in self if filter(user)), None)
Expand All @@ -41,10 +42,15 @@ def get(self, id: str) -> User:
return user


class LazyUsers(Users, LazyResources[User]):
class Users(CachedUsers, Resources[User]):
def __init__(
self, config: Config, session: Session, *, page_size=_MAX_PAGE_SIZE
) -> None:
if page_size > _MAX_PAGE_SIZE:
raise ValueError(
f"page_size must be less than or equal to {_MAX_PAGE_SIZE}"
)

super().__init__()
self.config = config
self.session = session
Expand Down
23 changes: 23 additions & 0 deletions src/posit/connect/users_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pytest

from unittest.mock import patch

from .users import Users


@pytest.fixture
def mock_config():
with patch("posit.connect.users.Config") as mock:
yield mock.return_value


@pytest.fixture
def mock_session():
with patch("posit.connect.users.Session") as mock:
yield mock.return_value


class TestUsers:
def test_init(self, mock_config, mock_session):
with pytest.raises(ValueError):
Users(mock_config, mock_session, page_size=9999)
Loading