def post( self, *, endpoint: Optional[str] = None, url: Optional[str] = None, data: Any, data_type: Optional[Type] = None, ) -> Any: """Perform a POST to the endpoint specified. Either endpoint or url must be specified. url will take precedence if both are specified. :param Optional[str] endpoint: The endpoint to perform the GET on :param Optional[str] url: The full URL to perform the GET on :param Any data: Some JSON serializable data to send :param Optional[Type] data_type: The data type to deserialize the response to :raises ValueError: If neither url or endpoint are specified :raises AppStoreConnectError: If we get a failure response back from the API :returns: The raw response """ token = self.generate_token() if url is None: if endpoint is None: raise ValueError("Either `endpoint` or `url` must be set") url = self.generate_url(endpoint) raw_response = requests.post( url, json=data, headers={ "Authorization": f"Bearer {token}", "Content-Type": "application/json" }, ) self.verify_response(raw_response) if raw_response.status_code == 201: if data_type is None: return None response_data = self.extract_data(raw_response) return deserialize.deserialize(data_type, response_data["data"]) if raw_response.status_code >= 200 and raw_response.status_code < 300: return None raise AppStoreConnectError(raw_response)
def patch( self, *, data_type: Optional[Type], endpoint: Optional[str] = None, url: Optional[str] = None, data: Any, ) -> Any: """Perform a PATCH to the endpoint specified. Either endpoint or url must be specified. url will take precedence if both are specified. :param Optional[Type] data_type: The class to deserialize the data of the response to :param Optional[str] endpoint: The endpoint to perform the GET on :param Optional[str] url: The full URL to perform the GET on :param Any data: Some JSON serializable data to send :raises AppStoreConnectError: If we don't get a 200 response back :raises ValueError: If neither url or endpoint are specified :returns: The raw response """ token = self.generate_token() if url is None: if endpoint is None: raise ValueError("Either `endpoint` or `url` must be set") url = self.generate_url(endpoint) raw_response = requests.patch( url, json=data, headers={ "Authorization": f"Bearer {token}", "Content-Type": "application/json" }, ) if raw_response.status_code == 204: return None if raw_response.status_code != 200: raise AppStoreConnectError(raw_response.json()) response_data = self.extract_data(raw_response) if data_type is None: return None return deserialize.deserialize(data_type, response_data["data"], throw_on_unhandled=True)
def delete_screenshot(self, *, screenshot_id: str) -> None: """Delete a screenshot. :param screenshot_id: The ID of the screenshot to delete :raises AppStoreConnectError: On failure to delete """ self.log.info(f"Deleting screenshot {screenshot_id}") url = self.http_client.generate_url(f"appScreenshots/{screenshot_id}") raw_response = self.http_client.delete(url=url) if raw_response.status_code != 204: raise AppStoreConnectError(raw_response)
def extract_data(self, response: requests.Response) -> Any: """Validate a response from the API and extract the data :param response: The response to validate :raises AppStoreConnectError: On any failure to validate :returns: Any data in the response """ _ = self if not response.ok: raise AppStoreConnectError(response) return response.json()
def delete_set(self, *, screenshot_set_id: str, delete_all_screenshots: bool = True) -> None: """Delete a screenshot set. :param screenshot_set_id: The ID of the screenshot set to delete :param delete_all_screenshots: If this is True, any screenshots will be deleted first. :raises AppStoreConnectError: On failure to delete """ if delete_all_screenshots: self.delete_screenshots_in_set(screenshot_set_id=screenshot_set_id) url = self.http_client.generate_url( f"appScreenshotSets/{screenshot_set_id}") raw_response = self.http_client.delete(url=url) if raw_response.status_code != 204: raise AppStoreConnectError(raw_response.json())