Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
tdstein committed Feb 15, 2024
1 parent b5d8a18 commit 14c8464
Show file tree
Hide file tree
Showing 8 changed files with 362 additions and 296 deletions.
27 changes: 25 additions & 2 deletions .github/workflows/push.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: Test
name: Push
on: [push]
concurrency:
group: ${{ github.head_ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
Expand All @@ -20,5 +23,25 @@ jobs:
python-version: ${{ matrix.python-version }}
- run: just deps
- run: just test
- run: just cov
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: extractions/setup-just@v1
- uses: actions/setup-python@v5
- run: just deps
- run: just lint
cov:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: extractions/setup-just@v1
- uses: actions/setup-python@v5
- run: just deps
- run: just test
- run: just cov xml
- if: always()
uses: orgoro/[email protected]
with:
coverageFile: coverage.xml
token: ${{ secrets.GITHUB_TOKEN }}
6 changes: 2 additions & 4 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 Users
from .users import LazyUsers, Users


@contextmanager
Expand All @@ -32,8 +32,6 @@ def create_client(


class Client:
users: Users

def __init__(
self,
api_key: Optional[str] = None,
Expand All @@ -56,7 +54,7 @@ def __init__(
session.hooks["response"].append(hooks.handle_errors)

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

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


class TestClient:
@patch("posit.connect.client.Users")
@patch("posit.connect.client.LazyUsers")
@patch("posit.connect.client.Session")
@patch("posit.connect.client.Config")
@patch("posit.connect.client.Auth")
def test_init(
self, Auth: MagicMock, Config: MagicMock, Session: MagicMock, Users: MagicMock
self,
Auth: MagicMock,
Config: MagicMock,
Session: MagicMock,
LazyUsers: MagicMock,
):
api_key = "foobar"
endpoint = "http://foo.bar"
Expand All @@ -27,12 +31,11 @@ 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()
Users.assert_called_once_with(config=config, session=Session.return_value)
LazyUsers.assert_called_once_with(config=config, session=Session.return_value)

@patch("posit.connect.client.Users")
@patch("posit.connect.client.Session")
@patch("posit.connect.client.Auth")
def test_del(self, Auth: MagicMock, Session: MagicMock, Users: MagicMock):
def test_del(self, Auth: MagicMock, Session: MagicMock):
api_key = "foobar"
endpoint = "http://foo.bar"
client = Client(api_key=api_key, endpoint=endpoint)
Expand Down
81 changes: 81 additions & 0 deletions src/posit/connect/resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from __future__ import annotations


from abc import ABC, abstractmethod
from typing import Generic, Iterator, Optional, TypeVar, List, TypedDict, Tuple


class Resource(TypedDict):
pass


T = TypeVar("T", bound=Resource)


class Resources(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]:
raise NotImplementedError()

@abstractmethod
def find_one(self, *args, **kwargs) -> Optional[T]:
raise NotImplementedError()

@abstractmethod
def get(self, id: str) -> T:
raise NotImplementedError()

def __iter__(self) -> Iterator[T]:
self.index = 0
return self

def __next__(self) -> T:
if self.index >= len(self.data):
raise StopIteration

v = self.data[self.index]
self.index += 1
return v

def to_pandas(self):
try:
from pandas import DataFrame

return DataFrame(self)
except ImportError:
return None


class LazyResources(Resources[T]):
def __init__(self, data: List[T] = []) -> None:
super().__init__(data)
self.data = data
self.exhausted = False
self.index = 0

@abstractmethod
def fetch(self, index) -> Tuple[Optional[Iterator[T]], bool]:
raise NotImplementedError()

def __iter__(self) -> Iterator[T]:
self.index = 0
return self

def __next__(self) -> T:
if self.index >= len(self.data):
if self.exhausted:
raise StopIteration

results, self.exhausted = self.fetch(self.index)
if not results:
raise StopIteration

self.data += results

v = self.data[self.index]
self.index += 1
return v
40 changes: 40 additions & 0 deletions src/posit/connect/resources_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import Iterator, Tuple, Optional
from unittest.mock import Mock

from .resources import Resource, Resources, LazyResources


class FakeResource(Resource):
pass


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

def find_one(self) -> Optional[FakeResource]:
return Mock(spec=FakeResource)

def get(self, _: str) -> FakeResource:
return Mock(spec=FakeResource)


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


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


class TestFakeLazyResources:
def test(self):
resources = FakeLazyResources()
assert resources == resources.find()
assert resources.find_one()
assert resources.get(None)
Loading

0 comments on commit 14c8464

Please sign in to comment.