Compare commits

...

2 Commits

9 changed files with 43 additions and 28 deletions

View File

@ -1,6 +1,6 @@
[project] [project]
name = "pysimplesat" name = "pysimplesat"
version = "0.1.7" version = "0.1.9"
authors = [ authors = [
{ name="Peter Annabel", email="peter.annabel@gmail.com" }, { name="Peter Annabel", email="peter.annabel@gmail.com" },
] ]

View File

@ -77,7 +77,7 @@ class SimpleSatClient(ABC):
method, method,
url, url,
headers=headers, headers=headers,
data=data, json=data,
params=cast(dict[str, Any], params or {}), params=cast(dict[str, Any], params or {}),
stream=stream, stream=stream,
) )

View File

@ -8,6 +8,7 @@ if TYPE_CHECKING:
from pysimplesat.clients.base_client import SimpleSatClient from pysimplesat.clients.base_client import SimpleSatClient
from pysimplesat.types import ( from pysimplesat.types import (
JSON,
RequestData, RequestData,
RequestMethod, RequestMethod,
RequestParams, RequestParams,
@ -112,7 +113,7 @@ class SimpleSatEndpoint:
self, self,
method: RequestMethod, method: RequestMethod,
endpoint: SimpleSatEndpoint | None = None, endpoint: SimpleSatEndpoint | None = None,
data: RequestData | None = None, data: JSON | None = None,
params: RequestParams | None = None, params: RequestParams | None = None,
headers: dict[str, str] | None = None, headers: dict[str, str] | None = None,
stream: bool = False, # noqa: FBT001, FBT002 stream: bool = False, # noqa: FBT001, FBT002

View File

@ -26,6 +26,7 @@ class AnswersSearchEndpoint(
self, self,
page: int, page: int,
params: SimpleSatRequestParams | None = None, params: SimpleSatRequestParams | None = None,
data: JSON | None = None,
) -> PaginatedResponse[Answer]: ) -> PaginatedResponse[Answer]:
""" """
Performs a POST request against the /answers/search endpoint and returns an initialized PaginatedResponse object. Performs a POST request against the /answers/search endpoint and returns an initialized PaginatedResponse object.
@ -41,12 +42,13 @@ class AnswersSearchEndpoint(
else: else:
params = {"page": page} params = {"page": page}
return PaginatedResponse( return PaginatedResponse(
super()._make_request("POST", params=params), super()._make_request("POST", data=data, params=params),
Answer, Answer,
self, self,
"answers", "answers",
page, page,
params, params,
data,
) )
def post(self, data: JSON | None = None, params: SimpleSatRequestParams | None = None) -> Answer: def post(self, data: JSON | None = None, params: SimpleSatRequestParams | None = None) -> Answer:

View File

@ -25,6 +25,7 @@ class QuestionsEndpoint(
self, self,
page: int, page: int,
params: SimpleSatRequestParams | None = None, params: SimpleSatRequestParams | None = None,
data: JSON | None = None,
) -> PaginatedResponse[Question]: ) -> PaginatedResponse[Question]:
""" """
Performs a GET request against the /questions endpoint and returns an initialized PaginatedResponse object. Performs a GET request against the /questions endpoint and returns an initialized PaginatedResponse object.
@ -40,12 +41,13 @@ class QuestionsEndpoint(
else: else:
params = {"page": page} params = {"page": page}
return PaginatedResponse( return PaginatedResponse(
super()._make_request("GET", params=params), super()._make_request("GET", data=data, params=params),
Question, Question,
self, self,
"questions", "questions",
page, page,
params, params,
data,
) )
def get( def get(

View File

@ -26,6 +26,7 @@ class ResponsesSearchEndpoint(
self, self,
page: int, page: int,
params: SimpleSatRequestParams | None = None, params: SimpleSatRequestParams | None = None,
data: JSON | None = None,
) -> PaginatedResponse[Response]: ) -> PaginatedResponse[Response]:
""" """
Performs a POST request against the /responses/search endpoint and returns an initialized PaginatedResponse object. Performs a POST request against the /responses/search endpoint and returns an initialized PaginatedResponse object.
@ -39,14 +40,15 @@ class ResponsesSearchEndpoint(
if params: if params:
params["page"] = page params["page"] = page
else: else:
params = {"page[number]": page} params = {"page": page}
return PaginatedResponse( return PaginatedResponse(
super()._make_request("POST", params=params), super()._make_request("POST", data=data, params=params),
Response, Response,
self, self,
"responses", "responses",
page, page,
params, params,
data,
) )
def post(self, data: JSON | None = None, params: SimpleSatRequestParams | None = None) -> Response: def post(self, data: JSON | None = None, params: SimpleSatRequestParams | None = None) -> Response:

View File

@ -32,6 +32,7 @@ class IPaginateable(IMethodBase, Generic[TModel, TRequestParams]):
self, self,
page: int | None = 1, page: int | None = 1,
params: TRequestParams | None = None, params: TRequestParams | None = None,
data: JSON | None = None,
) -> PaginatedResponse[TModel]: ) -> PaginatedResponse[TModel]:
pass pass

View File

@ -11,7 +11,7 @@ if TYPE_CHECKING:
from pydantic import BaseModel from pydantic import BaseModel
from requests import Response from requests import Response
from pysimplesat.types import RequestParams from pysimplesat.types import RequestParams, JSON
TModel = TypeVar("TModel", bound="BaseModel") TModel = TypeVar("TModel", bound="BaseModel")
@ -43,6 +43,7 @@ class PaginatedResponse(Generic[TModel]):
endpoint: str, endpoint: str,
page: int, page: int,
params: RequestParams | None = None, params: RequestParams | None = None,
data: JSON | None = None,
) -> None: ) -> None:
""" """
PaginatedResponse is a wrapper class for handling paginated responses from the PaginatedResponse is a wrapper class for handling paginated responses from the
@ -57,7 +58,7 @@ class PaginatedResponse(Generic[TModel]):
expected model type for the response data. This allows for type-safe handling expected model type for the response data. This allows for type-safe handling
of model instances throughout the class. of model instances throughout the class.
""" """
self._initialize(response, response_model, endpointmodel, endpoint, page, params) self._initialize(response, response_model, endpointmodel, endpoint, page, params, data)
def _initialize( def _initialize(
self, self,
@ -67,6 +68,7 @@ class PaginatedResponse(Generic[TModel]):
endpoint: str, endpoint: str,
page: int, page: int,
params: RequestParams | None = None, params: RequestParams | None = None,
data: JSON | None = None,
): ):
""" """
Initialize the instance variables using the provided response, endpointmodel, and page size. Initialize the instance variables using the provided response, endpointmodel, and page size.
@ -74,7 +76,7 @@ class PaginatedResponse(Generic[TModel]):
Args: Args:
response: The raw response object from the API. response: The raw response object from the API.
endpointmodel (SimpleSatEndpoint[TModel]): The endpointmodel associated with the response. endpointmodel (SimpleSatEndpoint[TModel]): The endpointmodel associated with the response.
endpoint: The endpoint url to extract the data endpoint: The endpoint url to extract the apidata
""" """
self.response = response self.response = response
self.response_model = response_model self.response_model = response_model
@ -94,8 +96,9 @@ class PaginatedResponse(Generic[TModel]):
self.prev_page = page - 1 if page > 1 else 1 self.prev_page = page - 1 if page > 1 else 1
self.next_page = page + 1 self.next_page = page + 1
self.params = params self.params = params
self.data: list[TModel] = [response_model.model_validate(d) for d in response.json().get(endpoint, {})] self.data = data
self.has_data = self.data and len(self.data) > 0 self.apidata: list[TModel] = [response_model.model_validate(d) for d in response.json().get(endpoint, {})]
self.has_apidata = self.apidata and len(self.apidata) > 0
self.index = 0 self.index = 0
def get_next_page(self) -> PaginatedResponse[TModel]: def get_next_page(self) -> PaginatedResponse[TModel]:
@ -104,13 +107,13 @@ class PaginatedResponse(Generic[TModel]):
Returns: Returns:
PaginatedResponse[TModel]: The updated PaginatedResponse instance PaginatedResponse[TModel]: The updated PaginatedResponse instance
with the data from the next page or None if there is no next page. with the apidata from the next page or None if there is no next page.
""" """
if not self.has_next_page or not self.next_page: if not self.has_next_page or not self.next_page:
self.has_data = False self.has_apidata = False
return self return self
next_response = self.endpointmodel.paginated(self.next_page, self.params) next_response = self.endpointmodel.paginated(self.next_page, self.params, self.data)
self._initialize( self._initialize(
next_response.response, next_response.response,
next_response.response_model, next_response.response_model,
@ -118,6 +121,7 @@ class PaginatedResponse(Generic[TModel]):
next_response.endpoint, next_response.endpoint,
self.next_page, self.next_page,
self.params, self.params,
self.data,
) )
return self return self
@ -127,19 +131,20 @@ class PaginatedResponse(Generic[TModel]):
Returns: Returns:
PaginatedResponse[TModel]: The updated PaginatedResponse instance PaginatedResponse[TModel]: The updated PaginatedResponse instance
with the data from the next page or None if there is no next page. with the apidata from the next page or None if there is no next page.
""" """
if not self.has_prev_page or not self.prev_page: if not self.has_prev_page or not self.prev_page:
self.has_data = False self.has_apidata = False
return self return self
prev_response = self.endpointmodel.paginated(self.prev_page, self.params) prev_response = self.endpointmodel.paginated(self.prev_page, self.params, self.data)
self._initialize( self._initialize(
prev_response.response, prev_response.response,
prev_response.response_model, prev_response.response_model,
prev_response.endpointmodel, prev_response.endpointmodel,
self.prev_page, self.prev_page,
self.params, self.params,
self.data,
) )
return self return self
@ -150,8 +155,8 @@ class PaginatedResponse(Generic[TModel]):
Yields: Yields:
TModel: An instance of the model class for each item in the paginated response. TModel: An instance of the model class for each item in the paginated response.
""" """
while self.has_data: while self.has_apidata:
yield from self.data yield from self.apidata
self.get_next_page() self.get_next_page()
def __iter__(self): def __iter__(self):
@ -170,20 +175,20 @@ class PaginatedResponse(Generic[TModel]):
Returns: Returns:
PaginatedResponse[TModel]: The current instance of the PaginatedResponse. PaginatedResponse[TModel]: The current instance of the PaginatedResponse.
""" """
return self.data return self.apidata
def __next__(self): def __next__(self):
""" """
Implement the iterator protocol by getting the next item in the data. Implement the iterator protocol by getting the next item in the apidata.
Returns: Returns:
TModel: The next item in the data. TModel: The next item in the apidata.
Raises: Raises:
StopIteration: If there are no more items in the data. StopIteration: If there are no more items in the apidata.
""" """
if self.index < len(self.data): if self.index < len(self.apidata):
result = self.data[self.index] result = self.apidata[self.index]
self.index += 1 self.index += 1
return result return result
else: else:

View File

@ -13,9 +13,11 @@ simplesat_api_client = SimpleSatAPIClient(
#surveys = simplesat_api_client.surveys.get() #surveys = simplesat_api_client.surveys.get()
#print(surveys) #print(surveys)
data = {"start_date": "2015-04-11T17:00:00Z"}
page_responses = simplesat_api_client.responses.search.paginated(1) page_responses = simplesat_api_client.responses.search.paginated(1, data=data)
responses = page_responses.all() responses = page_responses.all()
print(responses) print(responses)
for response in responses: for response in responses:
print(response.id) pass
# print(response.id)