diff --git a/.pylintrc b/.pylintrc index 0ebbb42..af9961e 100644 --- a/.pylintrc +++ b/.pylintrc @@ -3,7 +3,7 @@ ignore=docs [DESIGN] # Our Base class needs a few more attributes than the default allows -max-attributes=8 +max-attributes=9 [MESSAGES CONTROL] diff --git a/redcap/methods/base.py b/redcap/methods/base.py index 3623699..2b3c0da 100644 --- a/redcap/methods/base.py +++ b/redcap/methods/base.py @@ -39,12 +39,22 @@ class Base: """Base attributes and methods for the REDCap API""" - def __init__(self, url: str, token: str, verify_ssl: Union[bool, str] = True): + def __init__( + self, + url: str, + token: str, + verify_ssl: Union[bool, str] = True, + **request_kwargs, + ): """Initialize a Project, validate url and token""" self._validate_url_and_token(url, token) self._url = url self._token = token self.verify_ssl = verify_ssl + + self._validate_request_kwargs(**request_kwargs) + self._request_kwargs = request_kwargs + # attributes which require API calls self._metadata = None self._forms = None @@ -137,6 +147,25 @@ def _validate_url_and_token(url: str, token: str) -> None: f"{ expected_token_len } characters long", ) + @staticmethod + def _validate_request_kwargs(**request_kwargs): + """Run basic validation on user supplied kwargs for requests""" + # list of kwargs hardcoded in _RCRequest.execute(...) and self._call_api(...) + hardcoded_kwargs = [ + "url", + "data", + "verify, verify_ssl", + "return_headers", + "files", + "file", + ] + unallowed_kwargs = [ + kwarg for kwarg in request_kwargs if kwarg in hardcoded_kwargs + ] + assert ( + len(unallowed_kwargs) == 0 + ), f"Not allowed to define {unallowed_kwargs} when initiating object" + # pylint: disable=import-outside-toplevel @staticmethod def _read_csv(buf: StringIO, **df_kwargs) -> "pd.DataFrame": @@ -513,5 +542,8 @@ def _call_api( rcr = _RCRequest(url=self.url, payload=payload, config=config) return rcr.execute( - verify_ssl=self.verify_ssl, return_headers=return_headers, file=file + verify_ssl=self.verify_ssl, + return_headers=return_headers, + file=file, + **self._request_kwargs, ) diff --git a/redcap/request.py b/redcap/request.py index 4738422..53c8b7f 100644 --- a/redcap/request.py +++ b/redcap/request.py @@ -161,6 +161,7 @@ def execute( verify_ssl: Union[bool, str], return_headers: Literal[True], file: Optional[FileUpload], + **kwargs, ) -> Tuple[Union[Json, str, bytes], dict]: ... @@ -170,6 +171,7 @@ def execute( verify_ssl: Union[bool, str], return_headers: Literal[False], file: Optional[FileUpload], + **kwargs, ) -> Union[List[Dict[str, Any]], str, bytes]: ... @@ -178,6 +180,7 @@ def execute( verify_ssl: Union[bool, str], return_headers: bool, file: Optional[FileUpload], + **kwargs, ): """Execute the API request and return data @@ -187,6 +190,8 @@ def execute( Whether or not response headers should be returned along with the request content file: A file object to send along with the request + **kwargs: passed to requesets.request() to control + the configuration to perform requests to the api Returns: Data object from JSON decoding process if format=='json', @@ -198,7 +203,7 @@ def execute( exist, field doesn't exist, etc. """ response = self.session.post( - self.url, data=self.payload, verify=verify_ssl, files=file + self.url, data=self.payload, verify=verify_ssl, files=file, **kwargs ) content = self.get_content(