diff --git a/.markdownlint.json b/.markdownlint.json deleted file mode 100644 index f2a375a..0000000 --- a/.markdownlint.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "MD024": false -} diff --git a/.release.json b/.release.json index 4971d03..909c183 100644 --- a/.release.json +++ b/.release.json @@ -1,9 +1,9 @@ { "source": { "repo_url": "https://github.com/onfido/onfido-openapi-spec", - "short_sha": "db5a1b5", - "long_sha": "db5a1b59681fa467b324b4116de24d88d56d7452", - "version": "v5.0.0" + "short_sha": "1f90650", + "long_sha": "1f906509f36a1f5056df0c74b774795f8754e4ca", + "version": "" }, - "release": "v5.0.0" + "release": "v5.1.0" } diff --git a/onfido/__init__.py b/onfido/__init__.py index aa031b1..2a72d2f 100644 --- a/onfido/__init__.py +++ b/onfido/__init__.py @@ -14,7 +14,7 @@ """ # noqa: E501 -__version__ = "5.0.0" +__version__ = "5.1.0" # import apis into sdk package from onfido.api.default_api import DefaultApi @@ -37,6 +37,7 @@ from onfido.models.addresses_list import AddressesList from onfido.models.applicant import Applicant from onfido.models.applicant_builder import ApplicantBuilder +from onfido.models.applicant_consent import ApplicantConsent from onfido.models.applicant_consent_builder import ApplicantConsentBuilder from onfido.models.applicant_consent_name import ApplicantConsentName from onfido.models.applicant_create import ApplicantCreate diff --git a/onfido/api/default_api.py b/onfido/api/default_api.py index 46011a2..9ad3b9e 100644 --- a/onfido/api/default_api.py +++ b/onfido/api/default_api.py @@ -23,6 +23,7 @@ from onfido.models.addresses_list import AddressesList from onfido.models.applicant import Applicant from onfido.models.applicant_builder import ApplicantBuilder +from onfido.models.applicant_consent import ApplicantConsent from onfido.models.applicant_updater import ApplicantUpdater from onfido.models.applicants_list import ApplicantsList from onfido.models.check import Check @@ -7293,6 +7294,267 @@ def _find_applicant_serialize( + @validate_call + def find_applicant_consents( + self, + applicant_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[ApplicantConsent]: + """Retrieve Applicant Consents + + Retrieves consents for single applicant. + + :param applicant_id: (required) + :type applicant_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._find_applicant_consents_serialize( + applicant_id=applicant_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[ApplicantConsent]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def find_applicant_consents_with_http_info( + self, + applicant_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[ApplicantConsent]]: + """Retrieve Applicant Consents + + Retrieves consents for single applicant. + + :param applicant_id: (required) + :type applicant_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._find_applicant_consents_serialize( + applicant_id=applicant_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[ApplicantConsent]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def find_applicant_consents_without_preload_content( + self, + applicant_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """Retrieve Applicant Consents + + Retrieves consents for single applicant. + + :param applicant_id: (required) + :type applicant_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._find_applicant_consents_serialize( + applicant_id=applicant_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[ApplicantConsent]", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _find_applicant_consents_serialize( + self, + applicant_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if applicant_id is not None: + _path_params['applicant_id'] = applicant_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'Token' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/applicants/{applicant_id}/consents', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + @validate_call def find_check( self, diff --git a/onfido/api_client.py b/onfido/api_client.py index 19e8049..b61d978 100644 --- a/onfido/api_client.py +++ b/onfido/api_client.py @@ -90,7 +90,7 @@ def __init__( self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'onfido-python/5.0.0' + self.user_agent = 'onfido-python/5.1.0' self.client_side_validation = configuration.client_side_validation def __enter__(self): diff --git a/onfido/configuration.py b/onfido/configuration.py index d4bcef4..3d3de9b 100644 --- a/onfido/configuration.py +++ b/onfido/configuration.py @@ -501,7 +501,7 @@ def to_debug_report(self) -> str: "OS: {env}\n"\ "Python Version: {pyversion}\n"\ "Version of the API: v3.6\n"\ - "SDK Package Version: 5.0.0".\ + "SDK Package Version: 5.1.0".\ format(env=sys.platform, pyversion=sys.version) def get_host_settings(self) -> List[HostSetting]: diff --git a/onfido/models/__init__.py b/onfido/models/__init__.py index 6f0a409..fd37aee 100644 --- a/onfido/models/__init__.py +++ b/onfido/models/__init__.py @@ -20,6 +20,7 @@ from onfido.models.addresses_list import AddressesList from onfido.models.applicant import Applicant from onfido.models.applicant_builder import ApplicantBuilder +from onfido.models.applicant_consent import ApplicantConsent from onfido.models.applicant_consent_builder import ApplicantConsentBuilder from onfido.models.applicant_consent_name import ApplicantConsentName from onfido.models.applicant_create import ApplicantCreate diff --git a/onfido/models/applicant_consent.py b/onfido/models/applicant_consent.py new file mode 100644 index 0000000..a64c435 --- /dev/null +++ b/onfido/models/applicant_consent.py @@ -0,0 +1,111 @@ +# coding: utf-8 + +""" + Onfido API v3.6 + + The Onfido API (v3.6) + + The version of the OpenAPI document: v3.6 + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictBool +from typing import Any, ClassVar, Dict, List, Optional +from onfido.models.applicant_consent_name import ApplicantConsentName +from typing import Optional, Set +from typing_extensions import Self + +class ApplicantConsent(BaseModel): + """ + ApplicantConsent + """ # noqa: E501 + name: ApplicantConsentName + granted: StrictBool + granted_at: Optional[datetime] = Field(description="The date and time when this applicant consent was granted, if not granted the value is nil.") + additional_properties: Dict[str, Any] = {} + __properties: ClassVar[List[str]] = ["name", "granted", "granted_at"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ApplicantConsent from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + * Fields in `self.additional_properties` are added to the output dict. + """ + excluded_fields: Set[str] = set([ + "additional_properties", + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # puts key-value pairs in additional_properties in the top level + if self.additional_properties is not None: + for _key, _value in self.additional_properties.items(): + _dict[_key] = _value + + # set to None if granted_at (nullable) is None + # and model_fields_set contains the field + if self.granted_at is None and "granted_at" in self.model_fields_set: + _dict['granted_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ApplicantConsent from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "name": obj.get("name"), + "granted": obj.get("granted"), + "granted_at": obj.get("granted_at") + }) + # store additional fields in additional_properties + for _key in obj.keys(): + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + return _obj + + diff --git a/poetry.lock b/poetry.lock index fcfef73..c1b8811 100644 --- a/poetry.lock +++ b/poetry.lock @@ -16,13 +16,13 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "cachetools" -version = "5.5.1" +version = "5.5.2" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb"}, - {file = "cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95"}, + {file = "cachetools-5.5.2-py3-none-any.whl", hash = "sha256:d26a22bcc62eb95c3beabd9f1ee5e820d3d2704fe2967cbe350e20c8ffcd3f0a"}, + {file = "cachetools-5.5.2.tar.gz", hash = "sha256:1a661caa9175d26759571b2e19580f9d6393969e5dfca11fdb1f947a23e640d4"}, ] [[package]] @@ -500,13 +500,13 @@ testing = ["covdefaults (>=2.3)", "pytest (>=8.3.3)", "pytest-cov (>=5)", "pytes [[package]] name = "pytest" -version = "8.3.4" +version = "8.3.5" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, - {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, ] [package.dependencies] @@ -672,13 +672,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.29.2" +version = "20.29.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" files = [ - {file = "virtualenv-20.29.2-py3-none-any.whl", hash = "sha256:febddfc3d1ea571bdb1dc0f98d7b45d24def7428214d4fb73cc486c9568cce6a"}, - {file = "virtualenv-20.29.2.tar.gz", hash = "sha256:fdaabebf6d03b5ba83ae0a02cfe96f48a716f4fae556461d180825866f75b728"}, + {file = "virtualenv-20.29.3-py3-none-any.whl", hash = "sha256:3e3d00f5807e83b234dfb6122bf37cfadf4be216c53a49ac059d02414f819170"}, + {file = "virtualenv-20.29.3.tar.gz", hash = "sha256:95e39403fcf3940ac45bc717597dba16110b74506131845d9b687d5e73d947ac"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index bc8a6e9..629ff85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "onfido-python" -version = "5.0.0" +version = "5.1.0" description = "Python library for the Onfido API" authors = ["OpenAPI Generator Community "] license = "MIT" diff --git a/setup.py b/setup.py index 4465a86..a4d8929 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,7 @@ # prerequisite: setuptools # http://pypi.python.org/pypi/setuptools NAME = "onfido-python" -VERSION = "5.0.0" +VERSION = "5.1.0" PYTHON_REQUIRES = ">= 3.8" REQUIRES = [ "urllib3 >= 1.25.3, < 3.0.0", diff --git a/tests/test_applicants.py b/tests/test_applicants.py index d76b00d..942ae64 100644 --- a/tests/test_applicants.py +++ b/tests/test_applicants.py @@ -84,6 +84,36 @@ def test_update_applicant(onfido_api, applicant_id): assert updated_applicant.dob == datetime.date(1990, 1, 22) +def test_list_applicant_consents(onfido_api, applicant_id): + + consents = [ + onfido.ApplicantConsentBuilder( + name=onfido.ApplicantConsentName.PHONE_NUMBER_VERIFICATION, + granted=True, + granted_at=datetime.date(1990, 1, 22) + ), + onfido.ApplicantConsentBuilder( + name=onfido.ApplicantConsentName.PRIVACY_NOTICES_READ, + granted=True, + granted_at=datetime.date(1990, 1, 22) + ), + onfido.ApplicantConsentBuilder( + name=onfido.ApplicantConsentName.SSN_VERIFICATION, + granted=True, + granted_at=datetime.date(1990, 1, 22) + ) + ] + + new_applicant_data = onfido.ApplicantUpdater(consents=consents) + + onfido_api.update_applicant(applicant_id, new_applicant_data) + + actual_consents = onfido_api.find_applicant_consents(applicant_id) + + for actual, expected in zip(actual_consents, consents): + assert actual.name == expected.name + assert actual.granted == expected.granted + def test_delete_applicant(onfido_api, applicant_id): onfido_api.delete_applicant(applicant_id)