diff --git a/.github/workflows/check-templates-consistency.yml b/.github/workflows/check-templates-consistency.yml index 3c52d127..7953ee0e 100644 --- a/.github/workflows/check-templates-consistency.yml +++ b/.github/workflows/check-templates-consistency.yml @@ -10,4 +10,4 @@ jobs: check-template-consistency: uses: fingerprintjs/dx-team-toolkit/.github/workflows/check-template-consistency.yml@v1 with: - generate-command: 'bash ./generate.sh' \ No newline at end of file + generate-command: 'python3 -m pip install ruff && bash ./generate.sh' \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..c219b964 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,32 @@ +name: lint + +on: + push: + branches-ignore: + - main + workflow_dispatch: + +jobs: + lint: + name: "Lint" + runs-on: "ubuntu-latest" + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: "Install dependencies" + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r test-requirements.txt + + - name: "Run Ruff format check" + run: "ruff format --check ." + + - name: "Run Ruff linter" + run: "ruff check ." + + - name: "Run MyPy type checker" + run: "mypy fingerprint_server_sdk" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..2f1cc501 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,15 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.8.6 + hooks: + - id: ruff-format + - id: ruff + args: [--fix] + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.14.1 + hooks: + - id: mypy + additional_dependencies: + - pydantic>=2 + - types-python-dateutil>=2.8.19.14 + args: [--config-file=pyproject.toml] diff --git a/contributing.md b/contributing.md index 513123e8..3f7c1700 100644 --- a/contributing.md +++ b/contributing.md @@ -16,6 +16,39 @@ You can just run `./generate.sh` script and it will do all the work. To download fresh OpenAPI schema run `./sync.sh` +## Linting and Formatting + +This project uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting, and [MyPy](https://mypy.readthedocs.io/) for type checking. + +### Running locally + +```bash +# Format code +ruff format . + +# Run linter +ruff check --fix . + +# Run type checker +mypy fingerprint_server_sdk +``` + +### Updating templates + +When modifying templates in the `template/` directory, try to generate code that minimizes formatter changes. This includes: + +- Using single quotes instead of double quotes +- Sorting imports (standard library -> third-party -> local) +- Using modern type annotations (`list`, `dict`, `tuple` instead of `List`, `Dict`, `Tuple`) +- Removing `# coding: utf-8` headers (we are already aiming Python 3.9+) + +However, some formatting issues are difficult or impossible to fix in Mustache templates due to: +- Vendor extensions injecting imports that may duplicate template imports +- Conditional blocks creating extra whitespaces +- Mustache's limited control over output formatting + +In these cases, it's acceptable to let the formatter handle the adjustments. The goal is to minimize unnecessary changes, not eliminate them entirely. + ### Configuration Project configuration is described in `config.json` file. To read about available parameters run the command below: diff --git a/delete_visitor_example.py b/delete_visitor_example.py index a054a674..22a40e19 100644 --- a/delete_visitor_example.py +++ b/delete_visitor_example.py @@ -1,28 +1,29 @@ import os +from dotenv import load_dotenv + import fingerprint_server_sdk from fingerprint_server_sdk.configuration import Region from fingerprint_server_sdk.rest import ApiException -from dotenv import load_dotenv - load_dotenv() # configure -region_str = os.environ.get("REGION", "us").upper() +region_str = os.environ.get('REGION', 'us').upper() configuration = fingerprint_server_sdk.Configuration( - api_key=os.environ["PRIVATE_KEY"], region=Region[region_str]) + api_key=os.environ['PRIVATE_KEY'], region=Region[region_str] +) # create an instance of the API class api_instance = fingerprint_server_sdk.FingerprintApi(configuration) -visitor_id = os.environ["VISITOR_ID_TO_DELETE"] +visitor_id = os.environ['VISITOR_ID_TO_DELETE'] try: api_instance.delete_visitor_data(visitor_id) except ApiException as e: - print("Exception when calling DefaultApi->delete_visitor_data: %s\n" % e) + print(f'Exception when calling delete_visitor_data: {e}\n') exit(1) -print("Visitor data deleted!") +print('Visitor data deleted!') exit(0) diff --git a/fingerprint_server_sdk/__init__.py b/fingerprint_server_sdk/__init__.py index ca8db12e..997f8292 100644 --- a/fingerprint_server_sdk/__init__.py +++ b/fingerprint_server_sdk/__init__.py @@ -1,94 +1,91 @@ -# coding: utf-8 - -# flake8: noqa +# ruff: noqa: E501, I001 """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - -__version__ = "8.11.0" +__version__ = '8.11.0' # Define package exports __all__ = [ - "__version__", - "FingerprintApi", - "ApiResponse", - "ApiClient", - "Configuration", - "OpenApiException", - "ApiTypeError", - "ApiValueError", - "ApiKeyError", - "ApiAttributeError", - "ApiException", - "BadRequestException", - "UnauthorizedException", - "ForbiddenException", - "NotFoundException", - "ConflictException", - "UnprocessableEntityException", - "TooManyRequestsException", - "ServiceException", - "WebhookValidation", - "DecryptionKey", - "DecryptionAlgorithm", - "UnsealError", - "UnsealAggregateError", - "unseal_event_response", - "BotInfo", - "BotResult", - "BrowserDetails", - "Canvas", - "Emoji", - "Error", - "ErrorCode", - "ErrorResponse", - "Event", - "EventRuleAction", - "EventRuleActionAllow", - "EventRuleActionBlock", - "EventSearch", - "EventUpdate", - "FontPreferences", - "Geolocation", - "GeolocationSubdivisionsInner", - "IPBlockList", - "IPInfo", - "IPInfoV4", - "IPInfoV6", - "Identification", - "IdentificationConfidence", - "Integration", - "IntegrationSubintegration", - "PluginsInner", - "PluginsInnerMimeTypesInner", - "Proximity", - "ProxyConfidence", - "ProxyDetails", - "RawDeviceAttributes", - "RequestHeaderModifications", - "RuleActionHeaderField", - "RuleActionType", - "SDK", - "SupplementaryIDHighRecall", - "TamperingDetails", - "TouchSupport", - "TriggeredByInner", - "Velocity", - "VelocityData", - "VpnConfidence", - "VpnMethods", - "WebGlBasics", - "WebGlExtensions", + '__version__', + 'FingerprintApi', + 'ApiResponse', + 'ApiClient', + 'Configuration', + 'OpenApiException', + 'ApiTypeError', + 'ApiValueError', + 'ApiKeyError', + 'ApiAttributeError', + 'ApiException', + 'BadRequestException', + 'UnauthorizedException', + 'ForbiddenException', + 'NotFoundException', + 'ConflictException', + 'UnprocessableEntityException', + 'TooManyRequestsException', + 'ServiceException', + 'WebhookValidation', + 'DecryptionKey', + 'DecryptionAlgorithm', + 'UnsealError', + 'UnsealAggregateError', + 'unseal_event_response', + 'BotInfo', + 'BotResult', + 'BrowserDetails', + 'Canvas', + 'Emoji', + 'Error', + 'ErrorCode', + 'ErrorResponse', + 'Event', + 'EventRuleAction', + 'EventRuleActionAllow', + 'EventRuleActionBlock', + 'EventSearch', + 'EventUpdate', + 'FontPreferences', + 'Geolocation', + 'GeolocationSubdivisionsInner', + 'IPBlockList', + 'IPInfo', + 'IPInfoV4', + 'IPInfoV6', + 'Identification', + 'IdentificationConfidence', + 'Integration', + 'IntegrationSubintegration', + 'PluginsInner', + 'PluginsInnerMimeTypesInner', + 'Proximity', + 'ProxyConfidence', + 'ProxyDetails', + 'RawDeviceAttributes', + 'RequestHeaderModifications', + 'RuleActionHeaderField', + 'RuleActionType', + 'SDK', + 'SupplementaryIDHighRecall', + 'TamperingDetails', + 'TouchSupport', + 'TriggeredByInner', + 'Velocity', + 'VelocityData', + 'VpnConfidence', + 'VpnMethods', + 'WebGlBasics', + 'WebGlExtensions', ] # import apis into sdk package @@ -130,7 +127,9 @@ from fingerprint_server_sdk.models.event_update import EventUpdate from fingerprint_server_sdk.models.font_preferences import FontPreferences from fingerprint_server_sdk.models.geolocation import Geolocation -from fingerprint_server_sdk.models.geolocation_subdivisions_inner import GeolocationSubdivisionsInner +from fingerprint_server_sdk.models.geolocation_subdivisions_inner import ( + GeolocationSubdivisionsInner, +) from fingerprint_server_sdk.models.ip_block_list import IPBlockList from fingerprint_server_sdk.models.ip_info import IPInfo from fingerprint_server_sdk.models.ip_info_v4 import IPInfoV4 @@ -159,7 +158,13 @@ from fingerprint_server_sdk.models.vpn_methods import VpnMethods from fingerprint_server_sdk.models.web_gl_basics import WebGlBasics from fingerprint_server_sdk.models.web_gl_extensions import WebGlExtensions + # import custom methods into sdk package +from fingerprint_server_sdk.sealed import ( + DecryptionAlgorithm, + DecryptionKey, + UnsealAggregateError, + UnsealError, + unseal_event_response, +) from fingerprint_server_sdk.webhook_validation import WebhookValidation -from fingerprint_server_sdk.sealed import DecryptionAlgorithm, DecryptionKey, \ - UnsealError, UnsealAggregateError, unseal_event_response diff --git a/fingerprint_server_sdk/api/__init__.py b/fingerprint_server_sdk/api/__init__.py index bdcc4430..9698eb65 100644 --- a/fingerprint_server_sdk/api/__init__.py +++ b/fingerprint_server_sdk/api/__init__.py @@ -1,4 +1,4 @@ -# flake8: noqa +# ruff: noqa: F401 # import apis into api package from fingerprint_server_sdk.api.fingerprint_api import FingerprintApi diff --git a/fingerprint_server_sdk/api/fingerprint_api.py b/fingerprint_server_sdk/api/fingerprint_api.py index aab6e274..7549a3b2 100644 --- a/fingerprint_server_sdk/api/fingerprint_api.py +++ b/fingerprint_server_sdk/api/fingerprint_api.py @@ -1,34 +1,37 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 -import warnings -from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt -from typing import Any, Dict, List, Optional, Tuple, Union -from typing_extensions import Annotated +from typing import Annotated, Any, Optional, Union # noqa: UP035 -from pydantic import Field, StrictBool, StrictFloat, StrictInt, StrictStr, field_validator -from typing import List, Optional, Union -from typing_extensions import Annotated -from fingerprint_server_sdk.models.event import Event -from fingerprint_server_sdk.models.event_search import EventSearch -from fingerprint_server_sdk.models.event_update import EventUpdate +from pydantic import ( + Field, + StrictBool, + StrictFloat, + StrictInt, + StrictStr, + validate_call, +) -from fingerprint_server_sdk.configuration import Configuration from fingerprint_server_sdk.api_client import ApiClient, RequestSerialized from fingerprint_server_sdk.api_response import ApiResponse +from fingerprint_server_sdk.configuration import Configuration +from fingerprint_server_sdk.models.event import Event +from fingerprint_server_sdk.models.event_search import EventSearch +from fingerprint_server_sdk.models.event_update import EventUpdate from fingerprint_server_sdk.rest import RESTResponseType +# Type alias for query and form parameter values +ParamValue = Union[str, int, float, bool, list[str]] + class FingerprintApi: """NOTE: This class is auto generated by OpenAPI Generator @@ -40,27 +43,27 @@ class FingerprintApi: def __init__(self, configuration: Configuration) -> None: self.api_client = ApiClient(configuration) - @validate_call def delete_visitor_data( self, - visitor_id: Annotated[StrictStr, Field(description="The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete.")], + visitor_id: Annotated[ + StrictStr, + Field( + description='The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete.' + ), + ], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> None: """Delete data by visitor ID - Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. ### Which data is deleted? - Browser (or device) properties - Identification requests made from this browser (or device) #### Browser (or device) properties - Represents the data that Fingerprint collected from this specific browser (or device) and everything inferred and derived from it. - Upon request to delete, this data is deleted asynchronously (typically within a few minutes) and it will no longer be used to identify this browser (or device) for your [Fingerprint Workspace](https://dev.fingerprint.com/docs/glossary#fingerprint-workspace). #### Identification requests made from this browser (or device) - Fingerprint stores the identification requests made from a browser (or device) for up to 30 (or 90) days depending on your plan. To learn more, see [Data Retention](https://dev.fingerprint.com/docs/regions#data-retention). - Upon request to delete, the identification requests that were made by this browser - Within the past 10 days are deleted within 24 hrs. - Outside of 10 days are allowed to purge as per your data retention period. ### Corollary After requesting to delete a visitor ID, - If the same browser (or device) requests to identify, it will receive a different visitor ID. - If you request [`/v4/events` API](https://dev.fingerprint.com/reference/getevent) with an `event_id` that was made outside of the 10 days, you will still receive a valid response. ### Interested? Please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403. + Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. ### Which data is deleted? - Browser (or device) properties - Identification requests made from this browser (or device) #### Browser (or device) properties - Represents the data that Fingerprint collected from this specific browser (or device) and everything inferred and derived from it. - Upon request to delete, this data is deleted asynchronously (typically within a few minutes) and it will no longer be used to identify this browser (or device) for your [Fingerprint Workspace](https://dev.fingerprint.com/docs/glossary#fingerprint-workspace). #### Identification requests made from this browser (or device) - Fingerprint stores the identification requests made from a browser (or device) for up to 30 (or 90) days depending on your plan. To learn more, see [Data Retention](https://dev.fingerprint.com/docs/regions#data-retention). - Upon request to delete, the identification requests that were made by this browser - Within the past 10 days are deleted within 24 hrs. - Outside of 10 days are allowed to purge as per your data retention period. ### Corollary After requesting to delete a visitor ID, - If the same browser (or device) requests to identify, it will receive a different visitor ID. - If you request [`/v4/events` API](https://dev.fingerprint.com/reference/getevent) with an `event_id` that was made outside of the 10 days, you will still receive a valid response. ### Interested? Please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403. :param visitor_id: The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete. (required) :type visitor_id: str @@ -79,59 +82,52 @@ def delete_visitor_data( 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 + """ # noqa: E501 _param = self._delete_visitor_data_serialize( visitor_id=visitor_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { + _response_types_map: dict[str, Optional[str]] = { '200': None, - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '429': "ErrorResponse", + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '429': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) response_data.read() - return self.api_client.response_deserialize( + self.api_client.response_deserialize( response_data=response_data, response_types_map=_response_types_map, - ).data - + ) @validate_call def delete_visitor_data_with_http_info( self, - visitor_id: Annotated[StrictStr, Field(description="The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete.")], + visitor_id: Annotated[ + StrictStr, + Field( + description='The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete.' + ), + ], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> ApiResponse[None]: """Delete data by visitor ID - Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. ### Which data is deleted? - Browser (or device) properties - Identification requests made from this browser (or device) #### Browser (or device) properties - Represents the data that Fingerprint collected from this specific browser (or device) and everything inferred and derived from it. - Upon request to delete, this data is deleted asynchronously (typically within a few minutes) and it will no longer be used to identify this browser (or device) for your [Fingerprint Workspace](https://dev.fingerprint.com/docs/glossary#fingerprint-workspace). #### Identification requests made from this browser (or device) - Fingerprint stores the identification requests made from a browser (or device) for up to 30 (or 90) days depending on your plan. To learn more, see [Data Retention](https://dev.fingerprint.com/docs/regions#data-retention). - Upon request to delete, the identification requests that were made by this browser - Within the past 10 days are deleted within 24 hrs. - Outside of 10 days are allowed to purge as per your data retention period. ### Corollary After requesting to delete a visitor ID, - If the same browser (or device) requests to identify, it will receive a different visitor ID. - If you request [`/v4/events` API](https://dev.fingerprint.com/reference/getevent) with an `event_id` that was made outside of the 10 days, you will still receive a valid response. ### Interested? Please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403. + Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. ### Which data is deleted? - Browser (or device) properties - Identification requests made from this browser (or device) #### Browser (or device) properties - Represents the data that Fingerprint collected from this specific browser (or device) and everything inferred and derived from it. - Upon request to delete, this data is deleted asynchronously (typically within a few minutes) and it will no longer be used to identify this browser (or device) for your [Fingerprint Workspace](https://dev.fingerprint.com/docs/glossary#fingerprint-workspace). #### Identification requests made from this browser (or device) - Fingerprint stores the identification requests made from a browser (or device) for up to 30 (or 90) days depending on your plan. To learn more, see [Data Retention](https://dev.fingerprint.com/docs/regions#data-retention). - Upon request to delete, the identification requests that were made by this browser - Within the past 10 days are deleted within 24 hrs. - Outside of 10 days are allowed to purge as per your data retention period. ### Corollary After requesting to delete a visitor ID, - If the same browser (or device) requests to identify, it will receive a different visitor ID. - If you request [`/v4/events` API](https://dev.fingerprint.com/reference/getevent) with an `event_id` that was made outside of the 10 days, you will still receive a valid response. ### Interested? Please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403. :param visitor_id: The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete. (required) :type visitor_id: str @@ -150,59 +146,52 @@ def delete_visitor_data_with_http_info( 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 + """ # noqa: E501 _param = self._delete_visitor_data_serialize( visitor_id=visitor_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { + _response_types_map: dict[str, Optional[str]] = { '200': None, - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '429': "ErrorResponse", + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '429': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + 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 delete_visitor_data_without_preload_content( self, - visitor_id: Annotated[StrictStr, Field(description="The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete.")], + visitor_id: Annotated[ + StrictStr, + Field( + description='The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete.' + ), + ], _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> RESTResponseType: """Delete data by visitor ID - Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. ### Which data is deleted? - Browser (or device) properties - Identification requests made from this browser (or device) #### Browser (or device) properties - Represents the data that Fingerprint collected from this specific browser (or device) and everything inferred and derived from it. - Upon request to delete, this data is deleted asynchronously (typically within a few minutes) and it will no longer be used to identify this browser (or device) for your [Fingerprint Workspace](https://dev.fingerprint.com/docs/glossary#fingerprint-workspace). #### Identification requests made from this browser (or device) - Fingerprint stores the identification requests made from a browser (or device) for up to 30 (or 90) days depending on your plan. To learn more, see [Data Retention](https://dev.fingerprint.com/docs/regions#data-retention). - Upon request to delete, the identification requests that were made by this browser - Within the past 10 days are deleted within 24 hrs. - Outside of 10 days are allowed to purge as per your data retention period. ### Corollary After requesting to delete a visitor ID, - If the same browser (or device) requests to identify, it will receive a different visitor ID. - If you request [`/v4/events` API](https://dev.fingerprint.com/reference/getevent) with an `event_id` that was made outside of the 10 days, you will still receive a valid response. ### Interested? Please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403. + Request deleting all data associated with the specified visitor ID. This API is useful for compliance with privacy regulations. ### Which data is deleted? - Browser (or device) properties - Identification requests made from this browser (or device) #### Browser (or device) properties - Represents the data that Fingerprint collected from this specific browser (or device) and everything inferred and derived from it. - Upon request to delete, this data is deleted asynchronously (typically within a few minutes) and it will no longer be used to identify this browser (or device) for your [Fingerprint Workspace](https://dev.fingerprint.com/docs/glossary#fingerprint-workspace). #### Identification requests made from this browser (or device) - Fingerprint stores the identification requests made from a browser (or device) for up to 30 (or 90) days depending on your plan. To learn more, see [Data Retention](https://dev.fingerprint.com/docs/regions#data-retention). - Upon request to delete, the identification requests that were made by this browser - Within the past 10 days are deleted within 24 hrs. - Outside of 10 days are allowed to purge as per your data retention period. ### Corollary After requesting to delete a visitor ID, - If the same browser (or device) requests to identify, it will receive a different visitor ID. - If you request [`/v4/events` API](https://dev.fingerprint.com/reference/getevent) with an `event_id` that was made outside of the 10 days, you will still receive a valid response. ### Interested? Please [contact our support team](https://fingerprint.com/support/) to enable it for you. Otherwise, you will receive a 403. :param visitor_id: The [visitor ID](https://dev.fingerprint.com/reference/get-function#visitorid) you want to delete. (required) :type visitor_id: str @@ -221,80 +210,57 @@ def delete_visitor_data_without_preload_content( 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 + """ # noqa: E501 _param = self._delete_visitor_data_serialize( visitor_id=visitor_id, _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { + _response_types_map: dict[str, Optional[str]] = { '200': None, - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '429': "ErrorResponse", + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '429': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + return response_data.response def _delete_visitor_data_serialize( self, - visitor_id, - _request_auth, - _content_type, - _headers, - _host_index, + visitor_id: str, + _request_auth: Optional[dict[StrictStr, Any]], + _content_type: Optional[StrictStr], + _headers: Optional[dict[StrictStr, Any]], ) -> RequestSerialized: - _host = None + _collection_formats: dict[str, str] = {} - _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]]] + _path_params: dict[str, str] = {} + _query_params: list[tuple[str, ParamValue]] = [] + _header_params: dict[str, Optional[str]] = _headers or {} + _form_params: list[tuple[str, ParamValue]] = [] + _files: dict[ + str, + Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]], ] = {} - _body_params: Optional[bytes] = None + _body_params: Optional[Any] = None # process the path parameters if visitor_id is not None: _path_params['visitor_id'] = visitor_id - - - - - # set the HTTP header `Accept` if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) - + _header_params['Accept'] = self.api_client.select_header_accept(['application/json']) # authentication setting - _auth_settings: List[str] = [ - 'bearerAuth' - ] + _auth_settings: list[str] = ['bearerAuth'] return self.api_client.param_serialize( method='DELETE', @@ -307,38 +273,40 @@ def _delete_visitor_data_serialize( files=_files, auth_settings=_auth_settings, collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth + _request_auth=_request_auth, ) - - - @validate_call def get_event( self, - event_id: Annotated[StrictStr, Field(description="The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place).")], - ruleset_id: Annotated[Optional[StrictStr], Field(description="The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. ")] = None, + event_id: Annotated[ + StrictStr, + Field( + description='The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place).' + ), + ], + ruleset_id: Annotated[ + Optional[StrictStr], + Field( + description='The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. ' + ), + ] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> Event: """Get an event by event ID - Get a detailed analysis of an individual identification event, including Smart Signals. Use `event_id` as the URL path parameter. This API method is scoped to a request, i.e. all returned information is by `event_id`. + Get a detailed analysis of an individual identification event, including Smart Signals. Use `event_id` as the URL path parameter. This API method is scoped to a request, i.e. all returned information is by `event_id`. :param event_id: The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place). (required) :type event_id: str - :param ruleset_id: The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. + :param ruleset_id: The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. :type ruleset_id: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -355,12 +323,8 @@ def get_event( 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 + """ # noqa: E501 _param = self._get_event_serialize( event_id=event_id, @@ -368,53 +332,55 @@ def get_event( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { - '200': "Event", - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '429': "ErrorResponse", - '500': "ErrorResponse", + _response_types_map: dict[str, Optional[str]] = { + '200': 'Event', + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '429': 'ErrorResponse', + '500': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + 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 get_event_with_http_info( self, - event_id: Annotated[StrictStr, Field(description="The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place).")], - ruleset_id: Annotated[Optional[StrictStr], Field(description="The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. ")] = None, + event_id: Annotated[ + StrictStr, + Field( + description='The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place).' + ), + ], + ruleset_id: Annotated[ + Optional[StrictStr], + Field( + description='The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. ' + ), + ] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> ApiResponse[Event]: """Get an event by event ID - Get a detailed analysis of an individual identification event, including Smart Signals. Use `event_id` as the URL path parameter. This API method is scoped to a request, i.e. all returned information is by `event_id`. + Get a detailed analysis of an individual identification event, including Smart Signals. Use `event_id` as the URL path parameter. This API method is scoped to a request, i.e. all returned information is by `event_id`. :param event_id: The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place). (required) :type event_id: str - :param ruleset_id: The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. + :param ruleset_id: The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. :type ruleset_id: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -431,12 +397,8 @@ def get_event_with_http_info( 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 + """ # noqa: E501 _param = self._get_event_serialize( event_id=event_id, @@ -444,53 +406,55 @@ def get_event_with_http_info( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { - '200': "Event", - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '429': "ErrorResponse", - '500': "ErrorResponse", + _response_types_map: dict[str, Optional[str]] = { + '200': 'Event', + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '429': 'ErrorResponse', + '500': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + 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 get_event_without_preload_content( self, - event_id: Annotated[StrictStr, Field(description="The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place).")], - ruleset_id: Annotated[Optional[StrictStr], Field(description="The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. ")] = None, + event_id: Annotated[ + StrictStr, + Field( + description='The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place).' + ), + ], + ruleset_id: Annotated[ + Optional[StrictStr], + Field( + description='The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. ' + ), + ] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> RESTResponseType: """Get an event by event ID - Get a detailed analysis of an individual identification event, including Smart Signals. Use `event_id` as the URL path parameter. This API method is scoped to a request, i.e. all returned information is by `event_id`. + Get a detailed analysis of an individual identification event, including Smart Signals. Use `event_id` as the URL path parameter. This API method is scoped to a request, i.e. all returned information is by `event_id`. :param event_id: The unique [identifier](https://dev.fingerprint.com/reference/get-function#requestid) of each identification request (`requestId` can be used in its place). (required) :type event_id: str - :param ruleset_id: The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. + :param ruleset_id: The ID of the ruleset to evaluate against the event, producing the action to take for this event. The resulting action is returned in the `rule_action` attribute of the response. :type ruleset_id: str :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -507,12 +471,8 @@ def get_event_without_preload_content( 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 + """ # noqa: E501 _param = self._get_event_serialize( event_id=event_id, @@ -520,47 +480,40 @@ def get_event_without_preload_content( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { - '200': "Event", - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '429': "ErrorResponse", - '500': "ErrorResponse", + _response_types_map: dict[str, Optional[str]] = { + '200': 'Event', + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '429': 'ErrorResponse', + '500': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + return response_data.response def _get_event_serialize( self, - event_id, - ruleset_id, - _request_auth, - _content_type, - _headers, - _host_index, + event_id: str, + ruleset_id: Optional[str], + _request_auth: Optional[dict[StrictStr, Any]], + _content_type: Optional[StrictStr], + _headers: Optional[dict[StrictStr, Any]], ) -> RequestSerialized: - _host = None - - _collection_formats: Dict[str, str] = { - } + _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]]] + _path_params: dict[str, str] = {} + _query_params: list[tuple[str, ParamValue]] = [] + _header_params: dict[str, Optional[str]] = _headers or {} + _form_params: list[tuple[str, ParamValue]] = [] + _files: dict[ + str, + Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]], ] = {} - _body_params: Optional[bytes] = None + _body_params: Optional[Any] = None # process the path parameters if event_id is not None: @@ -568,27 +521,14 @@ def _get_event_serialize( # process the query parameters if ruleset_id is not None: - _query_params.append(('ruleset_id', ruleset_id)) - - - - - # set the HTTP header `Accept` if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) - + _header_params['Accept'] = self.api_client.select_header_accept(['application/json']) # authentication setting - _auth_settings: List[str] = [ - 'bearerAuth' - ] + _auth_settings: list[str] = ['bearerAuth'] return self.api_client.param_serialize( method='GET', @@ -601,149 +541,324 @@ def _get_event_serialize( files=_files, auth_settings=_auth_settings, collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth + _request_auth=_request_auth, ) - - - @validate_call def search_events( self, - limit: Annotated[Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], Field(description="Limit the number of events returned. ")] = None, - pagination_key: Annotated[Optional[StrictStr], Field(description="Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` ")] = None, - visitor_id: Annotated[Optional[StrictStr], Field(description="Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. ")] = None, - bot: Annotated[Optional[StrictStr], Field(description="Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. ")] = None, - ip_address: Annotated[Optional[StrictStr], Field(description="Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 ")] = None, + limit: Annotated[ + Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], + Field(description='Limit the number of events returned. '), + ] = None, + pagination_key: Annotated[ + Optional[StrictStr], + Field( + description='Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` ' + ), + ] = None, + visitor_id: Annotated[ + Optional[StrictStr], + Field( + description='Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. ' + ), + ] = None, + bot: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. ' + ), + ] = None, + ip_address: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 ' + ), + ] = None, asn: Optional[StrictStr] = None, - linked_id: Annotated[Optional[StrictStr], Field(description="Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. ")] = None, - url: Annotated[Optional[StrictStr], Field(description="Filter events by the URL (`url` property) associated with the event. ")] = None, - bundle_id: Annotated[Optional[StrictStr], Field(description="Filter events by the Bundle ID (iOS) associated with the event. ")] = None, - package_name: Annotated[Optional[StrictStr], Field(description="Filter events by the Package Name (Android) associated with the event. ")] = None, - origin: Annotated[Optional[StrictStr], Field(description="Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) ")] = None, - start: Annotated[Optional[StrictInt], Field(description="Filter events with a timestamp greater than the start time, in Unix time (milliseconds). ")] = None, - end: Annotated[Optional[StrictInt], Field(description="Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). ")] = None, - reverse: Annotated[Optional[StrictBool], Field(description="Sort events in reverse timestamp order. ")] = None, - suspect: Annotated[Optional[StrictBool], Field(description="Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. ")] = None, - vpn: Annotated[Optional[StrictBool], Field(description="Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. ")] = None, - virtual_machine: Annotated[Optional[StrictBool], Field(description="Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. ")] = None, - tampering: Annotated[Optional[StrictBool], Field(description="Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ")] = None, - anti_detect_browser: Annotated[Optional[StrictBool], Field(description="Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ")] = None, - incognito: Annotated[Optional[StrictBool], Field(description="Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. ")] = None, - privacy_settings: Annotated[Optional[StrictBool], Field(description="Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. ")] = None, - jailbroken: Annotated[Optional[StrictBool], Field(description="Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. ")] = None, - frida: Annotated[Optional[StrictBool], Field(description="Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. ")] = None, - factory_reset: Annotated[Optional[StrictBool], Field(description="Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. ")] = None, - cloned_app: Annotated[Optional[StrictBool], Field(description="Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. ")] = None, - emulator: Annotated[Optional[StrictBool], Field(description="Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. ")] = None, - root_apps: Annotated[Optional[StrictBool], Field(description="Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. ")] = None, - vpn_confidence: Annotated[Optional[StrictStr], Field(description="Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. ")] = None, - min_suspect_score: Annotated[Optional[Union[StrictFloat, StrictInt]], Field(description="Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. ")] = None, - developer_tools: Annotated[Optional[StrictBool], Field(description="Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. ")] = None, - location_spoofing: Annotated[Optional[StrictBool], Field(description="Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. ")] = None, - mitm_attack: Annotated[Optional[StrictBool], Field(description="Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. ")] = None, - proxy: Annotated[Optional[StrictBool], Field(description="Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. ")] = None, - sdk_version: Annotated[Optional[StrictStr], Field(description="Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` ")] = None, - sdk_platform: Annotated[Optional[StrictStr], Field(description="Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. ")] = None, - environment: Annotated[Optional[List[StrictStr]], Field(description="Filter for events by providing one or more environment IDs (`environment_id` property). ")] = None, - proximity_id: Annotated[Optional[StrictStr], Field(description="Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. ")] = None, - total_hits: Annotated[Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], Field(description="When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. ")] = None, - tor_node: Annotated[Optional[StrictBool], Field(description="Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. ")] = None, + linked_id: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. ' + ), + ] = None, + url: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the URL (`url` property) associated with the event. ' + ), + ] = None, + bundle_id: Annotated[ + Optional[StrictStr], + Field(description='Filter events by the Bundle ID (iOS) associated with the event. '), + ] = None, + package_name: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the Package Name (Android) associated with the event. ' + ), + ] = None, + origin: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) ' + ), + ] = None, + start: Annotated[ + Optional[StrictInt], + Field( + description='Filter events with a timestamp greater than the start time, in Unix time (milliseconds). ' + ), + ] = None, + end: Annotated[ + Optional[StrictInt], + Field( + description='Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). ' + ), + ] = None, + reverse: Annotated[ + Optional[StrictBool], Field(description='Sort events in reverse timestamp order. ') + ] = None, + suspect: Annotated[ + Optional[StrictBool], + Field( + description='Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. ' + ), + ] = None, + vpn: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. ' + ), + ] = None, + virtual_machine: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. ' + ), + ] = None, + tampering: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ' + ), + ] = None, + anti_detect_browser: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ' + ), + ] = None, + incognito: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. ' + ), + ] = None, + privacy_settings: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. ' + ), + ] = None, + jailbroken: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. ' + ), + ] = None, + frida: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. ' + ), + ] = None, + factory_reset: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. ' + ), + ] = None, + cloned_app: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. ' + ), + ] = None, + emulator: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. ' + ), + ] = None, + root_apps: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. ' + ), + ] = None, + vpn_confidence: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. ' + ), + ] = None, + min_suspect_score: Annotated[ + Optional[Union[StrictFloat, StrictInt]], + Field( + description='Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. ' + ), + ] = None, + developer_tools: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. ' + ), + ] = None, + location_spoofing: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. ' + ), + ] = None, + mitm_attack: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. ' + ), + ] = None, + proxy: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. ' + ), + ] = None, + sdk_version: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` ' + ), + ] = None, + sdk_platform: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. ' + ), + ] = None, + environment: Annotated[ + Optional[list[StrictStr]], + Field( + description='Filter for events by providing one or more environment IDs (`environment_id` property). ' + ), + ] = None, + proximity_id: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. ' + ), + ] = None, + total_hits: Annotated[ + Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], + Field( + description='When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. ' + ), + ] = None, + tor_node: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. ' + ), + ] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> EventSearch: """Search events - ## Search The `/v4/events` endpoint provides a convenient way to search for past events based on specific parameters. Typical use cases and queries include: - Searching for events associated with a single `visitor_id` within a time range to get historical behavior of a visitor. - Searching for events associated with a single `linked_id` within a time range to get all events associated with your internal account identifier. - Excluding all bot traffic from the query (`good` and `bad` bots) If you don't provide `start` or `end` parameters, the default search range is the **last 7 days**. ### Filtering events with the `suspect` flag The `/v4/events` endpoint unlocks a powerful method for fraud protection analytics. The `suspect` flag is exposed in all events where it was previously set by the update API. You can also apply the `suspect` query parameter as a filter to find all potentially fraudulent activity that you previously marked as `suspect`. This helps identify patterns of fraudulent behavior. ### Environment scoping If you use a secret key that is scoped to an environment, you will only get events associated with the same environment. With a workspace-scoped environment, you will get events from all environments. Smart Signals not activated for your workspace or are not included in the response. + ## Search The `/v4/events` endpoint provides a convenient way to search for past events based on specific parameters. Typical use cases and queries include: - Searching for events associated with a single `visitor_id` within a time range to get historical behavior of a visitor. - Searching for events associated with a single `linked_id` within a time range to get all events associated with your internal account identifier. - Excluding all bot traffic from the query (`good` and `bad` bots) If you don't provide `start` or `end` parameters, the default search range is the **last 7 days**. ### Filtering events with the `suspect` flag The `/v4/events` endpoint unlocks a powerful method for fraud protection analytics. The `suspect` flag is exposed in all events where it was previously set by the update API. You can also apply the `suspect` query parameter as a filter to find all potentially fraudulent activity that you previously marked as `suspect`. This helps identify patterns of fraudulent behavior. ### Environment scoping If you use a secret key that is scoped to an environment, you will only get events associated with the same environment. With a workspace-scoped environment, you will get events from all environments. Smart Signals not activated for your workspace or are not included in the response. - :param limit: Limit the number of events returned. + :param limit: Limit the number of events returned. :type limit: int - :param pagination_key: Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` + :param pagination_key: Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` :type pagination_key: str - :param visitor_id: Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. + :param visitor_id: Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. :type visitor_id: str - :param bot: Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. + :param bot: Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. :type bot: str - :param ip_address: Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 + :param ip_address: Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 :type ip_address: str :param asn: :type asn: str - :param linked_id: Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. + :param linked_id: Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. :type linked_id: str - :param url: Filter events by the URL (`url` property) associated with the event. + :param url: Filter events by the URL (`url` property) associated with the event. :type url: str - :param bundle_id: Filter events by the Bundle ID (iOS) associated with the event. + :param bundle_id: Filter events by the Bundle ID (iOS) associated with the event. :type bundle_id: str - :param package_name: Filter events by the Package Name (Android) associated with the event. + :param package_name: Filter events by the Package Name (Android) associated with the event. :type package_name: str - :param origin: Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) + :param origin: Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) :type origin: str - :param start: Filter events with a timestamp greater than the start time, in Unix time (milliseconds). + :param start: Filter events with a timestamp greater than the start time, in Unix time (milliseconds). :type start: int - :param end: Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). + :param end: Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). :type end: int - :param reverse: Sort events in reverse timestamp order. + :param reverse: Sort events in reverse timestamp order. :type reverse: bool - :param suspect: Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. + :param suspect: Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. :type suspect: bool - :param vpn: Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. + :param vpn: Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. :type vpn: bool - :param virtual_machine: Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. + :param virtual_machine: Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. :type virtual_machine: bool - :param tampering: Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. + :param tampering: Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. :type tampering: bool - :param anti_detect_browser: Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. + :param anti_detect_browser: Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. :type anti_detect_browser: bool - :param incognito: Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. + :param incognito: Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. :type incognito: bool - :param privacy_settings: Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. + :param privacy_settings: Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. :type privacy_settings: bool - :param jailbroken: Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. + :param jailbroken: Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. :type jailbroken: bool - :param frida: Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. + :param frida: Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. :type frida: bool - :param factory_reset: Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. + :param factory_reset: Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. :type factory_reset: bool - :param cloned_app: Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. + :param cloned_app: Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. :type cloned_app: bool - :param emulator: Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. + :param emulator: Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. :type emulator: bool - :param root_apps: Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. + :param root_apps: Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. :type root_apps: bool - :param vpn_confidence: Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. + :param vpn_confidence: Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. :type vpn_confidence: str - :param min_suspect_score: Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. + :param min_suspect_score: Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. :type min_suspect_score: float - :param developer_tools: Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. + :param developer_tools: Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. :type developer_tools: bool - :param location_spoofing: Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. + :param location_spoofing: Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. :type location_spoofing: bool - :param mitm_attack: Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. + :param mitm_attack: Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. :type mitm_attack: bool - :param proxy: Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. + :param proxy: Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. :type proxy: bool - :param sdk_version: Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` + :param sdk_version: Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` :type sdk_version: str - :param sdk_platform: Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. + :param sdk_platform: Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. :type sdk_platform: str - :param environment: Filter for events by providing one or more environment IDs (`environment_id` property). + :param environment: Filter for events by providing one or more environment IDs (`environment_id` property). :type environment: List[str] - :param proximity_id: Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. + :param proximity_id: Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. :type proximity_id: str - :param total_hits: When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. + :param total_hits: When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. :type total_hits: int - :param tor_node: Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. + :param tor_node: Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. :type tor_node: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -760,12 +875,8 @@ def search_events( 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 + """ # noqa: E501 _param = self._search_events_serialize( limit=limit, @@ -810,162 +921,337 @@ def search_events( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { - '200': "EventSearch", - '400': "ErrorResponse", - '403': "ErrorResponse", - '500': "ErrorResponse", + _response_types_map: dict[str, Optional[str]] = { + '200': 'EventSearch', + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '500': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + 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 search_events_with_http_info( self, - limit: Annotated[Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], Field(description="Limit the number of events returned. ")] = None, - pagination_key: Annotated[Optional[StrictStr], Field(description="Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` ")] = None, - visitor_id: Annotated[Optional[StrictStr], Field(description="Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. ")] = None, - bot: Annotated[Optional[StrictStr], Field(description="Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. ")] = None, - ip_address: Annotated[Optional[StrictStr], Field(description="Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 ")] = None, + limit: Annotated[ + Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], + Field(description='Limit the number of events returned. '), + ] = None, + pagination_key: Annotated[ + Optional[StrictStr], + Field( + description='Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` ' + ), + ] = None, + visitor_id: Annotated[ + Optional[StrictStr], + Field( + description='Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. ' + ), + ] = None, + bot: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. ' + ), + ] = None, + ip_address: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 ' + ), + ] = None, asn: Optional[StrictStr] = None, - linked_id: Annotated[Optional[StrictStr], Field(description="Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. ")] = None, - url: Annotated[Optional[StrictStr], Field(description="Filter events by the URL (`url` property) associated with the event. ")] = None, - bundle_id: Annotated[Optional[StrictStr], Field(description="Filter events by the Bundle ID (iOS) associated with the event. ")] = None, - package_name: Annotated[Optional[StrictStr], Field(description="Filter events by the Package Name (Android) associated with the event. ")] = None, - origin: Annotated[Optional[StrictStr], Field(description="Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) ")] = None, - start: Annotated[Optional[StrictInt], Field(description="Filter events with a timestamp greater than the start time, in Unix time (milliseconds). ")] = None, - end: Annotated[Optional[StrictInt], Field(description="Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). ")] = None, - reverse: Annotated[Optional[StrictBool], Field(description="Sort events in reverse timestamp order. ")] = None, - suspect: Annotated[Optional[StrictBool], Field(description="Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. ")] = None, - vpn: Annotated[Optional[StrictBool], Field(description="Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. ")] = None, - virtual_machine: Annotated[Optional[StrictBool], Field(description="Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. ")] = None, - tampering: Annotated[Optional[StrictBool], Field(description="Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ")] = None, - anti_detect_browser: Annotated[Optional[StrictBool], Field(description="Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ")] = None, - incognito: Annotated[Optional[StrictBool], Field(description="Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. ")] = None, - privacy_settings: Annotated[Optional[StrictBool], Field(description="Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. ")] = None, - jailbroken: Annotated[Optional[StrictBool], Field(description="Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. ")] = None, - frida: Annotated[Optional[StrictBool], Field(description="Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. ")] = None, - factory_reset: Annotated[Optional[StrictBool], Field(description="Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. ")] = None, - cloned_app: Annotated[Optional[StrictBool], Field(description="Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. ")] = None, - emulator: Annotated[Optional[StrictBool], Field(description="Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. ")] = None, - root_apps: Annotated[Optional[StrictBool], Field(description="Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. ")] = None, - vpn_confidence: Annotated[Optional[StrictStr], Field(description="Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. ")] = None, - min_suspect_score: Annotated[Optional[Union[StrictFloat, StrictInt]], Field(description="Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. ")] = None, - developer_tools: Annotated[Optional[StrictBool], Field(description="Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. ")] = None, - location_spoofing: Annotated[Optional[StrictBool], Field(description="Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. ")] = None, - mitm_attack: Annotated[Optional[StrictBool], Field(description="Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. ")] = None, - proxy: Annotated[Optional[StrictBool], Field(description="Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. ")] = None, - sdk_version: Annotated[Optional[StrictStr], Field(description="Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` ")] = None, - sdk_platform: Annotated[Optional[StrictStr], Field(description="Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. ")] = None, - environment: Annotated[Optional[List[StrictStr]], Field(description="Filter for events by providing one or more environment IDs (`environment_id` property). ")] = None, - proximity_id: Annotated[Optional[StrictStr], Field(description="Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. ")] = None, - total_hits: Annotated[Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], Field(description="When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. ")] = None, - tor_node: Annotated[Optional[StrictBool], Field(description="Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. ")] = None, + linked_id: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. ' + ), + ] = None, + url: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the URL (`url` property) associated with the event. ' + ), + ] = None, + bundle_id: Annotated[ + Optional[StrictStr], + Field(description='Filter events by the Bundle ID (iOS) associated with the event. '), + ] = None, + package_name: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the Package Name (Android) associated with the event. ' + ), + ] = None, + origin: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) ' + ), + ] = None, + start: Annotated[ + Optional[StrictInt], + Field( + description='Filter events with a timestamp greater than the start time, in Unix time (milliseconds). ' + ), + ] = None, + end: Annotated[ + Optional[StrictInt], + Field( + description='Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). ' + ), + ] = None, + reverse: Annotated[ + Optional[StrictBool], Field(description='Sort events in reverse timestamp order. ') + ] = None, + suspect: Annotated[ + Optional[StrictBool], + Field( + description='Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. ' + ), + ] = None, + vpn: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. ' + ), + ] = None, + virtual_machine: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. ' + ), + ] = None, + tampering: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ' + ), + ] = None, + anti_detect_browser: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ' + ), + ] = None, + incognito: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. ' + ), + ] = None, + privacy_settings: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. ' + ), + ] = None, + jailbroken: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. ' + ), + ] = None, + frida: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. ' + ), + ] = None, + factory_reset: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. ' + ), + ] = None, + cloned_app: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. ' + ), + ] = None, + emulator: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. ' + ), + ] = None, + root_apps: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. ' + ), + ] = None, + vpn_confidence: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. ' + ), + ] = None, + min_suspect_score: Annotated[ + Optional[Union[StrictFloat, StrictInt]], + Field( + description='Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. ' + ), + ] = None, + developer_tools: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. ' + ), + ] = None, + location_spoofing: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. ' + ), + ] = None, + mitm_attack: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. ' + ), + ] = None, + proxy: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. ' + ), + ] = None, + sdk_version: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` ' + ), + ] = None, + sdk_platform: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. ' + ), + ] = None, + environment: Annotated[ + Optional[list[StrictStr]], + Field( + description='Filter for events by providing one or more environment IDs (`environment_id` property). ' + ), + ] = None, + proximity_id: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. ' + ), + ] = None, + total_hits: Annotated[ + Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], + Field( + description='When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. ' + ), + ] = None, + tor_node: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. ' + ), + ] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> ApiResponse[EventSearch]: """Search events - ## Search The `/v4/events` endpoint provides a convenient way to search for past events based on specific parameters. Typical use cases and queries include: - Searching for events associated with a single `visitor_id` within a time range to get historical behavior of a visitor. - Searching for events associated with a single `linked_id` within a time range to get all events associated with your internal account identifier. - Excluding all bot traffic from the query (`good` and `bad` bots) If you don't provide `start` or `end` parameters, the default search range is the **last 7 days**. ### Filtering events with the `suspect` flag The `/v4/events` endpoint unlocks a powerful method for fraud protection analytics. The `suspect` flag is exposed in all events where it was previously set by the update API. You can also apply the `suspect` query parameter as a filter to find all potentially fraudulent activity that you previously marked as `suspect`. This helps identify patterns of fraudulent behavior. ### Environment scoping If you use a secret key that is scoped to an environment, you will only get events associated with the same environment. With a workspace-scoped environment, you will get events from all environments. Smart Signals not activated for your workspace or are not included in the response. + ## Search The `/v4/events` endpoint provides a convenient way to search for past events based on specific parameters. Typical use cases and queries include: - Searching for events associated with a single `visitor_id` within a time range to get historical behavior of a visitor. - Searching for events associated with a single `linked_id` within a time range to get all events associated with your internal account identifier. - Excluding all bot traffic from the query (`good` and `bad` bots) If you don't provide `start` or `end` parameters, the default search range is the **last 7 days**. ### Filtering events with the `suspect` flag The `/v4/events` endpoint unlocks a powerful method for fraud protection analytics. The `suspect` flag is exposed in all events where it was previously set by the update API. You can also apply the `suspect` query parameter as a filter to find all potentially fraudulent activity that you previously marked as `suspect`. This helps identify patterns of fraudulent behavior. ### Environment scoping If you use a secret key that is scoped to an environment, you will only get events associated with the same environment. With a workspace-scoped environment, you will get events from all environments. Smart Signals not activated for your workspace or are not included in the response. - :param limit: Limit the number of events returned. + :param limit: Limit the number of events returned. :type limit: int - :param pagination_key: Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` + :param pagination_key: Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` :type pagination_key: str - :param visitor_id: Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. + :param visitor_id: Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. :type visitor_id: str - :param bot: Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. + :param bot: Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. :type bot: str - :param ip_address: Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 + :param ip_address: Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 :type ip_address: str :param asn: :type asn: str - :param linked_id: Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. + :param linked_id: Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. :type linked_id: str - :param url: Filter events by the URL (`url` property) associated with the event. + :param url: Filter events by the URL (`url` property) associated with the event. :type url: str - :param bundle_id: Filter events by the Bundle ID (iOS) associated with the event. + :param bundle_id: Filter events by the Bundle ID (iOS) associated with the event. :type bundle_id: str - :param package_name: Filter events by the Package Name (Android) associated with the event. + :param package_name: Filter events by the Package Name (Android) associated with the event. :type package_name: str - :param origin: Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) + :param origin: Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) :type origin: str - :param start: Filter events with a timestamp greater than the start time, in Unix time (milliseconds). + :param start: Filter events with a timestamp greater than the start time, in Unix time (milliseconds). :type start: int - :param end: Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). + :param end: Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). :type end: int - :param reverse: Sort events in reverse timestamp order. + :param reverse: Sort events in reverse timestamp order. :type reverse: bool - :param suspect: Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. + :param suspect: Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. :type suspect: bool - :param vpn: Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. + :param vpn: Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. :type vpn: bool - :param virtual_machine: Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. + :param virtual_machine: Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. :type virtual_machine: bool - :param tampering: Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. + :param tampering: Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. :type tampering: bool - :param anti_detect_browser: Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. + :param anti_detect_browser: Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. :type anti_detect_browser: bool - :param incognito: Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. + :param incognito: Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. :type incognito: bool - :param privacy_settings: Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. + :param privacy_settings: Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. :type privacy_settings: bool - :param jailbroken: Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. + :param jailbroken: Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. :type jailbroken: bool - :param frida: Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. + :param frida: Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. :type frida: bool - :param factory_reset: Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. + :param factory_reset: Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. :type factory_reset: bool - :param cloned_app: Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. + :param cloned_app: Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. :type cloned_app: bool - :param emulator: Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. + :param emulator: Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. :type emulator: bool - :param root_apps: Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. + :param root_apps: Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. :type root_apps: bool - :param vpn_confidence: Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. + :param vpn_confidence: Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. :type vpn_confidence: str - :param min_suspect_score: Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. + :param min_suspect_score: Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. :type min_suspect_score: float - :param developer_tools: Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. + :param developer_tools: Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. :type developer_tools: bool - :param location_spoofing: Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. + :param location_spoofing: Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. :type location_spoofing: bool - :param mitm_attack: Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. + :param mitm_attack: Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. :type mitm_attack: bool - :param proxy: Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. + :param proxy: Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. :type proxy: bool - :param sdk_version: Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` + :param sdk_version: Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` :type sdk_version: str - :param sdk_platform: Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. + :param sdk_platform: Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. :type sdk_platform: str - :param environment: Filter for events by providing one or more environment IDs (`environment_id` property). + :param environment: Filter for events by providing one or more environment IDs (`environment_id` property). :type environment: List[str] - :param proximity_id: Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. + :param proximity_id: Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. :type proximity_id: str - :param total_hits: When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. + :param total_hits: When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. :type total_hits: int - :param tor_node: Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. + :param tor_node: Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. :type tor_node: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -982,12 +1268,8 @@ def search_events_with_http_info( 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 + """ # noqa: E501 _param = self._search_events_serialize( limit=limit, @@ -1032,162 +1314,337 @@ def search_events_with_http_info( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { - '200': "EventSearch", - '400': "ErrorResponse", - '403': "ErrorResponse", - '500': "ErrorResponse", + _response_types_map: dict[str, Optional[str]] = { + '200': 'EventSearch', + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '500': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + 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 search_events_without_preload_content( self, - limit: Annotated[Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], Field(description="Limit the number of events returned. ")] = None, - pagination_key: Annotated[Optional[StrictStr], Field(description="Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` ")] = None, - visitor_id: Annotated[Optional[StrictStr], Field(description="Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. ")] = None, - bot: Annotated[Optional[StrictStr], Field(description="Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. ")] = None, - ip_address: Annotated[Optional[StrictStr], Field(description="Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 ")] = None, + limit: Annotated[ + Optional[Annotated[int, Field(le=100, strict=True, ge=1)]], + Field(description='Limit the number of events returned. '), + ] = None, + pagination_key: Annotated[ + Optional[StrictStr], + Field( + description='Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` ' + ), + ] = None, + visitor_id: Annotated[ + Optional[StrictStr], + Field( + description='Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. ' + ), + ] = None, + bot: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. ' + ), + ] = None, + ip_address: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 ' + ), + ] = None, asn: Optional[StrictStr] = None, - linked_id: Annotated[Optional[StrictStr], Field(description="Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. ")] = None, - url: Annotated[Optional[StrictStr], Field(description="Filter events by the URL (`url` property) associated with the event. ")] = None, - bundle_id: Annotated[Optional[StrictStr], Field(description="Filter events by the Bundle ID (iOS) associated with the event. ")] = None, - package_name: Annotated[Optional[StrictStr], Field(description="Filter events by the Package Name (Android) associated with the event. ")] = None, - origin: Annotated[Optional[StrictStr], Field(description="Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) ")] = None, - start: Annotated[Optional[StrictInt], Field(description="Filter events with a timestamp greater than the start time, in Unix time (milliseconds). ")] = None, - end: Annotated[Optional[StrictInt], Field(description="Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). ")] = None, - reverse: Annotated[Optional[StrictBool], Field(description="Sort events in reverse timestamp order. ")] = None, - suspect: Annotated[Optional[StrictBool], Field(description="Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. ")] = None, - vpn: Annotated[Optional[StrictBool], Field(description="Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. ")] = None, - virtual_machine: Annotated[Optional[StrictBool], Field(description="Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. ")] = None, - tampering: Annotated[Optional[StrictBool], Field(description="Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ")] = None, - anti_detect_browser: Annotated[Optional[StrictBool], Field(description="Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ")] = None, - incognito: Annotated[Optional[StrictBool], Field(description="Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. ")] = None, - privacy_settings: Annotated[Optional[StrictBool], Field(description="Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. ")] = None, - jailbroken: Annotated[Optional[StrictBool], Field(description="Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. ")] = None, - frida: Annotated[Optional[StrictBool], Field(description="Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. ")] = None, - factory_reset: Annotated[Optional[StrictBool], Field(description="Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. ")] = None, - cloned_app: Annotated[Optional[StrictBool], Field(description="Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. ")] = None, - emulator: Annotated[Optional[StrictBool], Field(description="Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. ")] = None, - root_apps: Annotated[Optional[StrictBool], Field(description="Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. ")] = None, - vpn_confidence: Annotated[Optional[StrictStr], Field(description="Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. ")] = None, - min_suspect_score: Annotated[Optional[Union[StrictFloat, StrictInt]], Field(description="Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. ")] = None, - developer_tools: Annotated[Optional[StrictBool], Field(description="Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. ")] = None, - location_spoofing: Annotated[Optional[StrictBool], Field(description="Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. ")] = None, - mitm_attack: Annotated[Optional[StrictBool], Field(description="Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. ")] = None, - proxy: Annotated[Optional[StrictBool], Field(description="Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. ")] = None, - sdk_version: Annotated[Optional[StrictStr], Field(description="Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` ")] = None, - sdk_platform: Annotated[Optional[StrictStr], Field(description="Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. ")] = None, - environment: Annotated[Optional[List[StrictStr]], Field(description="Filter for events by providing one or more environment IDs (`environment_id` property). ")] = None, - proximity_id: Annotated[Optional[StrictStr], Field(description="Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. ")] = None, - total_hits: Annotated[Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], Field(description="When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. ")] = None, - tor_node: Annotated[Optional[StrictBool], Field(description="Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. ")] = None, + linked_id: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. ' + ), + ] = None, + url: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the URL (`url` property) associated with the event. ' + ), + ] = None, + bundle_id: Annotated[ + Optional[StrictStr], + Field(description='Filter events by the Bundle ID (iOS) associated with the event. '), + ] = None, + package_name: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the Package Name (Android) associated with the event. ' + ), + ] = None, + origin: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) ' + ), + ] = None, + start: Annotated[ + Optional[StrictInt], + Field( + description='Filter events with a timestamp greater than the start time, in Unix time (milliseconds). ' + ), + ] = None, + end: Annotated[ + Optional[StrictInt], + Field( + description='Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). ' + ), + ] = None, + reverse: Annotated[ + Optional[StrictBool], Field(description='Sort events in reverse timestamp order. ') + ] = None, + suspect: Annotated[ + Optional[StrictBool], + Field( + description='Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. ' + ), + ] = None, + vpn: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. ' + ), + ] = None, + virtual_machine: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. ' + ), + ] = None, + tampering: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ' + ), + ] = None, + anti_detect_browser: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. ' + ), + ] = None, + incognito: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. ' + ), + ] = None, + privacy_settings: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. ' + ), + ] = None, + jailbroken: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. ' + ), + ] = None, + frida: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. ' + ), + ] = None, + factory_reset: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. ' + ), + ] = None, + cloned_app: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. ' + ), + ] = None, + emulator: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. ' + ), + ] = None, + root_apps: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. ' + ), + ] = None, + vpn_confidence: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. ' + ), + ] = None, + min_suspect_score: Annotated[ + Optional[Union[StrictFloat, StrictInt]], + Field( + description='Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. ' + ), + ] = None, + developer_tools: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. ' + ), + ] = None, + location_spoofing: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. ' + ), + ] = None, + mitm_attack: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. ' + ), + ] = None, + proxy: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. ' + ), + ] = None, + sdk_version: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` ' + ), + ] = None, + sdk_platform: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. ' + ), + ] = None, + environment: Annotated[ + Optional[list[StrictStr]], + Field( + description='Filter for events by providing one or more environment IDs (`environment_id` property). ' + ), + ] = None, + proximity_id: Annotated[ + Optional[StrictStr], + Field( + description='Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. ' + ), + ] = None, + total_hits: Annotated[ + Optional[Annotated[int, Field(le=1000, strict=True, ge=1)]], + Field( + description='When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. ' + ), + ] = None, + tor_node: Annotated[ + Optional[StrictBool], + Field( + description='Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. ' + ), + ] = None, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> RESTResponseType: """Search events - ## Search The `/v4/events` endpoint provides a convenient way to search for past events based on specific parameters. Typical use cases and queries include: - Searching for events associated with a single `visitor_id` within a time range to get historical behavior of a visitor. - Searching for events associated with a single `linked_id` within a time range to get all events associated with your internal account identifier. - Excluding all bot traffic from the query (`good` and `bad` bots) If you don't provide `start` or `end` parameters, the default search range is the **last 7 days**. ### Filtering events with the `suspect` flag The `/v4/events` endpoint unlocks a powerful method for fraud protection analytics. The `suspect` flag is exposed in all events where it was previously set by the update API. You can also apply the `suspect` query parameter as a filter to find all potentially fraudulent activity that you previously marked as `suspect`. This helps identify patterns of fraudulent behavior. ### Environment scoping If you use a secret key that is scoped to an environment, you will only get events associated with the same environment. With a workspace-scoped environment, you will get events from all environments. Smart Signals not activated for your workspace or are not included in the response. + ## Search The `/v4/events` endpoint provides a convenient way to search for past events based on specific parameters. Typical use cases and queries include: - Searching for events associated with a single `visitor_id` within a time range to get historical behavior of a visitor. - Searching for events associated with a single `linked_id` within a time range to get all events associated with your internal account identifier. - Excluding all bot traffic from the query (`good` and `bad` bots) If you don't provide `start` or `end` parameters, the default search range is the **last 7 days**. ### Filtering events with the `suspect` flag The `/v4/events` endpoint unlocks a powerful method for fraud protection analytics. The `suspect` flag is exposed in all events where it was previously set by the update API. You can also apply the `suspect` query parameter as a filter to find all potentially fraudulent activity that you previously marked as `suspect`. This helps identify patterns of fraudulent behavior. ### Environment scoping If you use a secret key that is scoped to an environment, you will only get events associated with the same environment. With a workspace-scoped environment, you will get events from all environments. Smart Signals not activated for your workspace or are not included in the response. - :param limit: Limit the number of events returned. + :param limit: Limit the number of events returned. :type limit: int - :param pagination_key: Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` + :param pagination_key: Use `pagination_key` to get the next page of results. When more results are available (e.g., you requested up to 100 results for your query using `limit`, but there are more than 100 events total matching your request), the `pagination_key` field is added to the response. The key corresponds to the `timestamp` of the last returned event. In the following request, use that value in the `pagination_key` parameter to get the next page of results: 1. First request, returning most recent 200 events: `GET api-base-url/events?limit=100` 2. Use `response.pagination_key` to get the next page of results: `GET api-base-url/events?limit=100&pagination_key=1740815825085` :type pagination_key: str - :param visitor_id: Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. + :param visitor_id: Unique [visitor identifier](https://dev.fingerprint.com/reference/get-function#visitorid) issued by Fingerprint Identification and all active Smart Signals. Filter for events matching this `visitor_id`. :type visitor_id: str - :param bot: Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. + :param bot: Filter events by the Bot Detection result, specifically: `all` - events where any kind of bot was detected. `good` - events where a good bot was detected. `bad` - events where a bad bot was detected. `none` - events where no bot was detected. > Note: When using this parameter, only events with the `botd.bot` property set to a valid value are returned. Events without a `botd` Smart Signal result are left out of the response. :type bot: str - :param ip_address: Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 + :param ip_address: Filter events by IP address or IP range (if CIDR notation is used). If CIDR notation is not used, a /32 for IPv4 or /128 for IPv6 is assumed. Examples of range based queries: 10.0.0.0/24, 192.168.0.1/32 :type ip_address: str :param asn: :type asn: str - :param linked_id: Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. + :param linked_id: Filter events by your custom identifier. You can use [linked Ids](https://dev.fingerprint.com/reference/get-function#linkedid) to associate identification requests with your own identifier, for example, session Id, purchase Id, or transaction Id. You can then use this `linked_id` parameter to retrieve all events associated with your custom identifier. :type linked_id: str - :param url: Filter events by the URL (`url` property) associated with the event. + :param url: Filter events by the URL (`url` property) associated with the event. :type url: str - :param bundle_id: Filter events by the Bundle ID (iOS) associated with the event. + :param bundle_id: Filter events by the Bundle ID (iOS) associated with the event. :type bundle_id: str - :param package_name: Filter events by the Package Name (Android) associated with the event. + :param package_name: Filter events by the Package Name (Android) associated with the event. :type package_name: str - :param origin: Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) + :param origin: Filter events by the origin field of the event. This is applicable to web events only (e.g., https://example.com) :type origin: str - :param start: Filter events with a timestamp greater than the start time, in Unix time (milliseconds). + :param start: Filter events with a timestamp greater than the start time, in Unix time (milliseconds). :type start: int - :param end: Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). + :param end: Filter events with a timestamp smaller than the end time, in Unix time (milliseconds). :type end: int - :param reverse: Sort events in reverse timestamp order. + :param reverse: Sort events in reverse timestamp order. :type reverse: bool - :param suspect: Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. + :param suspect: Filter events previously tagged as suspicious via the [Update API](https://dev.fingerprint.com/reference/updateevent). > Note: When using this parameter, only events with the `suspect` property explicitly set to `true` or `false` are returned. Events with undefined `suspect` property are left out of the response. :type suspect: bool - :param vpn: Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. + :param vpn: Filter events by VPN Detection result. > Note: When using this parameter, only events with the `vpn` property set to `true` or `false` are returned. Events without a `vpn` Smart Signal result are left out of the response. :type vpn: bool - :param virtual_machine: Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. + :param virtual_machine: Filter events by Virtual Machine Detection result. > Note: When using this parameter, only events with the `virtual_machine` property set to `true` or `false` are returned. Events without a `virtual_machine` Smart Signal result are left out of the response. :type virtual_machine: bool - :param tampering: Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. + :param tampering: Filter events by Browser Tampering Detection result. > Note: When using this parameter, only events with the `tampering.result` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. :type tampering: bool - :param anti_detect_browser: Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. + :param anti_detect_browser: Filter events by Anti-detect Browser Detection result. > Note: When using this parameter, only events with the `tampering.anti_detect_browser` property set to `true` or `false` are returned. Events without a `tampering` Smart Signal result are left out of the response. :type anti_detect_browser: bool - :param incognito: Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. + :param incognito: Filter events by Browser Incognito Detection result. > Note: When using this parameter, only events with the `incognito` property set to `true` or `false` are returned. Events without an `incognito` Smart Signal result are left out of the response. :type incognito: bool - :param privacy_settings: Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. + :param privacy_settings: Filter events by Privacy Settings Detection result. > Note: When using this parameter, only events with the `privacy_settings` property set to `true` or `false` are returned. Events without a `privacy_settings` Smart Signal result are left out of the response. :type privacy_settings: bool - :param jailbroken: Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. + :param jailbroken: Filter events by Jailbroken Device Detection result. > Note: When using this parameter, only events with the `jailbroken` property set to `true` or `false` are returned. Events without a `jailbroken` Smart Signal result are left out of the response. :type jailbroken: bool - :param frida: Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. + :param frida: Filter events by Frida Detection result. > Note: When using this parameter, only events with the `frida` property set to `true` or `false` are returned. Events without a `frida` Smart Signal result are left out of the response. :type frida: bool - :param factory_reset: Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. + :param factory_reset: Filter events by Factory Reset Detection result. > Note: When using this parameter, only events with a `factory_reset` time. Events without a `factory_reset` Smart Signal result are left out of the response. :type factory_reset: bool - :param cloned_app: Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. + :param cloned_app: Filter events by Cloned App Detection result. > Note: When using this parameter, only events with the `cloned_app` property set to `true` or `false` are returned. Events without a `cloned_app` Smart Signal result are left out of the response. :type cloned_app: bool - :param emulator: Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. + :param emulator: Filter events by Android Emulator Detection result. > Note: When using this parameter, only events with the `emulator` property set to `true` or `false` are returned. Events without an `emulator` Smart Signal result are left out of the response. :type emulator: bool - :param root_apps: Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. + :param root_apps: Filter events by Rooted Device Detection result. > Note: When using this parameter, only events with the `root_apps` property set to `true` or `false` are returned. Events without a `root_apps` Smart Signal result are left out of the response. :type root_apps: bool - :param vpn_confidence: Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. + :param vpn_confidence: Filter events by VPN Detection result confidence level. `high` - events with high VPN Detection confidence. `medium` - events with medium VPN Detection confidence. `low` - events with low VPN Detection confidence. > Note: When using this parameter, only events with the `vpn.confidence` property set to a valid value are returned. Events without a `vpn` Smart Signal result are left out of the response. :type vpn_confidence: str - :param min_suspect_score: Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. + :param min_suspect_score: Filter events with Suspect Score result above a provided minimum threshold. > Note: When using this parameter, only events where the `suspect_score` property set to a value exceeding your threshold are returned. Events without a `suspect_score` Smart Signal result are left out of the response. :type min_suspect_score: float - :param developer_tools: Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. + :param developer_tools: Filter events by Developer Tools detection result. > Note: When using this parameter, only events with the `developer_tools` property set to `true` or `false` are returned. Events without a `developer_tools` Smart Signal result are left out of the response. :type developer_tools: bool - :param location_spoofing: Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. + :param location_spoofing: Filter events by Location Spoofing detection result. > Note: When using this parameter, only events with the `location_spoofing` property set to `true` or `false` are returned. Events without a `location_spoofing` Smart Signal result are left out of the response. :type location_spoofing: bool - :param mitm_attack: Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. + :param mitm_attack: Filter events by MITM (Man-in-the-Middle) Attack detection result. > Note: When using this parameter, only events with the `mitm_attack` property set to `true` or `false` are returned. Events without a `mitm_attack` Smart Signal result are left out of the response. :type mitm_attack: bool - :param proxy: Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. + :param proxy: Filter events by Proxy detection result. > Note: When using this parameter, only events with the `proxy` property set to `true` or `false` are returned. Events without a `proxy` Smart Signal result are left out of the response. :type proxy: bool - :param sdk_version: Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` + :param sdk_version: Filter events by a specific SDK version associated with the identification event (`sdk.version` property). Example: `3.11.14` :type sdk_version: str - :param sdk_platform: Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. + :param sdk_platform: Filter events by the SDK Platform associated with the identification event (`sdk.platform` property) . `js` - Javascript agent (Web). `ios` - Apple iOS based devices. `android` - Android based devices. :type sdk_platform: str - :param environment: Filter for events by providing one or more environment IDs (`environment_id` property). + :param environment: Filter for events by providing one or more environment IDs (`environment_id` property). :type environment: List[str] - :param proximity_id: Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. + :param proximity_id: Filter events by the most precise Proximity ID provided by default. > Note: When using this parameter, only events with the `proximity.id` property matching the provided ID are returned. Events without a `proximity` result are left out of the response. :type proximity_id: str - :param total_hits: When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. + :param total_hits: When set, the response will include a `total_hits` property with a count of total query matches across all pages, up to the specified limit. :type total_hits: int - :param tor_node: Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. + :param tor_node: Filter events by Tor Node detection result. > Note: When using this parameter, only events with the `tor_node` property set to `true` or `false` are returned. Events without a `tor_node` detection result are left out of the response. :type tor_node: bool :param _request_timeout: timeout setting for this request. If one number provided, it will be total request @@ -1204,12 +1661,8 @@ def search_events_without_preload_content( 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 + """ # noqa: E501 _param = self._search_events_serialize( limit=limit, @@ -1254,298 +1707,240 @@ def search_events_without_preload_content( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { - '200': "EventSearch", - '400': "ErrorResponse", - '403': "ErrorResponse", - '500': "ErrorResponse", + _response_types_map: dict[str, Optional[str]] = { + '200': 'EventSearch', + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '500': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + return response_data.response def _search_events_serialize( self, - limit, - pagination_key, - visitor_id, - bot, - ip_address, - asn, - linked_id, - url, - bundle_id, - package_name, - origin, - start, - end, - reverse, - suspect, - vpn, - virtual_machine, - tampering, - anti_detect_browser, - incognito, - privacy_settings, - jailbroken, - frida, - factory_reset, - cloned_app, - emulator, - root_apps, - vpn_confidence, - min_suspect_score, - developer_tools, - location_spoofing, - mitm_attack, - proxy, - sdk_version, - sdk_platform, - environment, - proximity_id, - total_hits, - tor_node, - _request_auth, - _content_type, - _headers, - _host_index, + limit: Optional[int], + pagination_key: Optional[str], + visitor_id: Optional[str], + bot: Optional[str], + ip_address: Optional[str], + asn: Optional[str], + linked_id: Optional[str], + url: Optional[str], + bundle_id: Optional[str], + package_name: Optional[str], + origin: Optional[str], + start: Optional[int], + end: Optional[int], + reverse: Optional[bool], + suspect: Optional[bool], + vpn: Optional[bool], + virtual_machine: Optional[bool], + tampering: Optional[bool], + anti_detect_browser: Optional[bool], + incognito: Optional[bool], + privacy_settings: Optional[bool], + jailbroken: Optional[bool], + frida: Optional[bool], + factory_reset: Optional[bool], + cloned_app: Optional[bool], + emulator: Optional[bool], + root_apps: Optional[bool], + vpn_confidence: Optional[str], + min_suspect_score: Optional[float], + developer_tools: Optional[bool], + location_spoofing: Optional[bool], + mitm_attack: Optional[bool], + proxy: Optional[bool], + sdk_version: Optional[str], + sdk_platform: Optional[str], + environment: Optional[list[str]], + proximity_id: Optional[str], + total_hits: Optional[int], + tor_node: Optional[bool], + _request_auth: Optional[dict[StrictStr, Any]], + _content_type: Optional[StrictStr], + _headers: Optional[dict[StrictStr, Any]], ) -> RequestSerialized: - _host = None - - _collection_formats: Dict[str, str] = { + _collection_formats: dict[str, str] = { 'environment': 'multi', } - _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]]] + _path_params: dict[str, str] = {} + _query_params: list[tuple[str, ParamValue]] = [] + _header_params: dict[str, Optional[str]] = _headers or {} + _form_params: list[tuple[str, ParamValue]] = [] + _files: dict[ + str, + Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]], ] = {} - _body_params: Optional[bytes] = None - + _body_params: Optional[Any] = None # process the query parameters if limit is not None: - _query_params.append(('limit', limit)) - + # process the query parameters if pagination_key is not None: - _query_params.append(('pagination_key', pagination_key)) - + # process the query parameters if visitor_id is not None: - _query_params.append(('visitor_id', visitor_id)) - + # process the query parameters if bot is not None: - _query_params.append(('bot', bot)) - + # process the query parameters if ip_address is not None: - _query_params.append(('ip_address', ip_address)) - + # process the query parameters if asn is not None: - _query_params.append(('asn', asn)) - + # process the query parameters if linked_id is not None: - _query_params.append(('linked_id', linked_id)) - + # process the query parameters if url is not None: - _query_params.append(('url', url)) - + # process the query parameters if bundle_id is not None: - _query_params.append(('bundle_id', bundle_id)) - + # process the query parameters if package_name is not None: - _query_params.append(('package_name', package_name)) - + # process the query parameters if origin is not None: - _query_params.append(('origin', origin)) - + # process the query parameters if start is not None: - _query_params.append(('start', start)) - + # process the query parameters if end is not None: - _query_params.append(('end', end)) - + # process the query parameters if reverse is not None: - _query_params.append(('reverse', reverse)) - + # process the query parameters if suspect is not None: - _query_params.append(('suspect', suspect)) - + # process the query parameters if vpn is not None: - _query_params.append(('vpn', vpn)) - + # process the query parameters if virtual_machine is not None: - _query_params.append(('virtual_machine', virtual_machine)) - + # process the query parameters if tampering is not None: - _query_params.append(('tampering', tampering)) - + # process the query parameters if anti_detect_browser is not None: - _query_params.append(('anti_detect_browser', anti_detect_browser)) - + # process the query parameters if incognito is not None: - _query_params.append(('incognito', incognito)) - + # process the query parameters if privacy_settings is not None: - _query_params.append(('privacy_settings', privacy_settings)) - + # process the query parameters if jailbroken is not None: - _query_params.append(('jailbroken', jailbroken)) - + # process the query parameters if frida is not None: - _query_params.append(('frida', frida)) - + # process the query parameters if factory_reset is not None: - _query_params.append(('factory_reset', factory_reset)) - + # process the query parameters if cloned_app is not None: - _query_params.append(('cloned_app', cloned_app)) - + # process the query parameters if emulator is not None: - _query_params.append(('emulator', emulator)) - + # process the query parameters if root_apps is not None: - _query_params.append(('root_apps', root_apps)) - + # process the query parameters if vpn_confidence is not None: - _query_params.append(('vpn_confidence', vpn_confidence)) - + # process the query parameters if min_suspect_score is not None: - _query_params.append(('min_suspect_score', min_suspect_score)) - + # process the query parameters if developer_tools is not None: - _query_params.append(('developer_tools', developer_tools)) - + # process the query parameters if location_spoofing is not None: - _query_params.append(('location_spoofing', location_spoofing)) - + # process the query parameters if mitm_attack is not None: - _query_params.append(('mitm_attack', mitm_attack)) - + # process the query parameters if proxy is not None: - _query_params.append(('proxy', proxy)) - + # process the query parameters if sdk_version is not None: - _query_params.append(('sdk_version', sdk_version)) - + # process the query parameters if sdk_platform is not None: - _query_params.append(('sdk_platform', sdk_platform)) - + # process the query parameters if environment is not None: - _query_params.append(('environment', environment)) - + # process the query parameters if proximity_id is not None: - _query_params.append(('proximity_id', proximity_id)) - + # process the query parameters if total_hits is not None: - _query_params.append(('total_hits', total_hits)) - + # process the query parameters if tor_node is not None: - _query_params.append(('tor_node', tor_node)) - - - - - # set the HTTP header `Accept` if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) - + _header_params['Accept'] = self.api_client.select_header_accept(['application/json']) # authentication setting - _auth_settings: List[str] = [ - 'bearerAuth' - ] + _auth_settings: list[str] = ['bearerAuth'] return self.api_client.param_serialize( method='GET', @@ -1558,34 +1953,31 @@ def _search_events_serialize( files=_files, auth_settings=_auth_settings, collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth + _request_auth=_request_auth, ) - - - @validate_call def update_event( self, - event_id: Annotated[StrictStr, Field(description="The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id).")], + event_id: Annotated[ + StrictStr, + Field( + description='The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id).' + ), + ], event_update: EventUpdate, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> None: """Update an event - Change information in existing events specified by `event_id` or *flag suspicious events*. When an event is created, it can be assigned `linked_id` and `tags` submitted through the JS agent parameters. This information might not have been available on the client initially, so the Server API permits updating these attributes after the fact. **Warning** It's not possible to update events older than one month. **Warning** Trying to update an event immediately after creation may temporarily result in an error (HTTP 409 Conflict. The event is not mutable yet.) as the event is fully propagated across our systems. In such a case, simply retry the request. + Change information in existing events specified by `event_id` or *flag suspicious events*. When an event is created, it can be assigned `linked_id` and `tags` submitted through the JS agent parameters. This information might not have been available on the client initially, so the Server API permits updating these attributes after the fact. **Warning** It's not possible to update events older than one month. **Warning** Trying to update an event immediately after creation may temporarily result in an error (HTTP 409 Conflict. The event is not mutable yet.) as the event is fully propagated across our systems. In such a case, simply retry the request. :param event_id: The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id). (required) :type event_id: str @@ -1606,12 +1998,8 @@ def update_event( 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 + """ # noqa: E501 _param = self._update_event_serialize( event_id=event_id, @@ -1619,48 +2007,45 @@ def update_event( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { + _response_types_map: dict[str, Optional[str]] = { '200': None, - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '409': "ErrorResponse", + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '409': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) response_data.read() - return self.api_client.response_deserialize( + self.api_client.response_deserialize( response_data=response_data, response_types_map=_response_types_map, - ).data - + ) @validate_call def update_event_with_http_info( self, - event_id: Annotated[StrictStr, Field(description="The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id).")], + event_id: Annotated[ + StrictStr, + Field( + description='The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id).' + ), + ], event_update: EventUpdate, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> ApiResponse[None]: """Update an event - Change information in existing events specified by `event_id` or *flag suspicious events*. When an event is created, it can be assigned `linked_id` and `tags` submitted through the JS agent parameters. This information might not have been available on the client initially, so the Server API permits updating these attributes after the fact. **Warning** It's not possible to update events older than one month. **Warning** Trying to update an event immediately after creation may temporarily result in an error (HTTP 409 Conflict. The event is not mutable yet.) as the event is fully propagated across our systems. In such a case, simply retry the request. + Change information in existing events specified by `event_id` or *flag suspicious events*. When an event is created, it can be assigned `linked_id` and `tags` submitted through the JS agent parameters. This information might not have been available on the client initially, so the Server API permits updating these attributes after the fact. **Warning** It's not possible to update events older than one month. **Warning** Trying to update an event immediately after creation may temporarily result in an error (HTTP 409 Conflict. The event is not mutable yet.) as the event is fully propagated across our systems. In such a case, simply retry the request. :param event_id: The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id). (required) :type event_id: str @@ -1681,12 +2066,8 @@ def update_event_with_http_info( 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 + """ # noqa: E501 _param = self._update_event_serialize( event_id=event_id, @@ -1694,48 +2075,45 @@ def update_event_with_http_info( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { + _response_types_map: dict[str, Optional[str]] = { '200': None, - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '409': "ErrorResponse", + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '409': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) + + 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 update_event_without_preload_content( self, - event_id: Annotated[StrictStr, Field(description="The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id).")], + event_id: Annotated[ + StrictStr, + Field( + description='The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id).' + ), + ], event_update: EventUpdate, _request_timeout: Union[ None, Annotated[StrictFloat, Field(gt=0)], - Tuple[ - Annotated[StrictFloat, Field(gt=0)], - Annotated[StrictFloat, Field(gt=0)] - ] + tuple[Annotated[StrictFloat, Field(gt=0)], Annotated[StrictFloat, Field(gt=0)]], ] = None, - _request_auth: Optional[Dict[StrictStr, Any]] = 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, + _headers: Optional[dict[StrictStr, Any]] = None, ) -> RESTResponseType: """Update an event - Change information in existing events specified by `event_id` or *flag suspicious events*. When an event is created, it can be assigned `linked_id` and `tags` submitted through the JS agent parameters. This information might not have been available on the client initially, so the Server API permits updating these attributes after the fact. **Warning** It's not possible to update events older than one month. **Warning** Trying to update an event immediately after creation may temporarily result in an error (HTTP 409 Conflict. The event is not mutable yet.) as the event is fully propagated across our systems. In such a case, simply retry the request. + Change information in existing events specified by `event_id` or *flag suspicious events*. When an event is created, it can be assigned `linked_id` and `tags` submitted through the JS agent parameters. This information might not have been available on the client initially, so the Server API permits updating these attributes after the fact. **Warning** It's not possible to update events older than one month. **Warning** Trying to update an event immediately after creation may temporarily result in an error (HTTP 409 Conflict. The event is not mutable yet.) as the event is fully propagated across our systems. In such a case, simply retry the request. :param event_id: The unique event [identifier](https://dev.fingerprint.com/reference/get-function#event_id). (required) :type event_id: str @@ -1756,12 +2134,8 @@ def update_event_without_preload_content( 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 + """ # noqa: E501 _param = self._update_event_serialize( event_id=event_id, @@ -1769,85 +2143,64 @@ def update_event_without_preload_content( _request_auth=_request_auth, _content_type=_content_type, _headers=_headers, - _host_index=_host_index ) - _response_types_map: Dict[str, Optional[str]] = { + _response_types_map: dict[str, Optional[str]] = { '200': None, - '400': "ErrorResponse", - '403': "ErrorResponse", - '404': "ErrorResponse", - '409': "ErrorResponse", + '400': 'ErrorResponse', + '403': 'ErrorResponse', + '404': 'ErrorResponse', + '409': 'ErrorResponse', } - response_data = self.api_client.call_api( - *_param, - _request_timeout=_request_timeout - ) - return response_data.response + response_data = self.api_client.call_api(*_param, _request_timeout=_request_timeout) + return response_data.response def _update_event_serialize( self, - event_id, - event_update, - _request_auth, - _content_type, - _headers, - _host_index, + event_id: str, + event_update: EventUpdate, + _request_auth: Optional[dict[StrictStr, Any]], + _content_type: Optional[StrictStr], + _headers: Optional[dict[StrictStr, Any]], ) -> RequestSerialized: - _host = None - - _collection_formats: Dict[str, str] = { - } + _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]]] + _path_params: dict[str, str] = {} + _query_params: list[tuple[str, ParamValue]] = [] + _header_params: dict[str, Optional[str]] = _headers or {} + _form_params: list[tuple[str, ParamValue]] = [] + _files: dict[ + str, + Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]], ] = {} - _body_params: Optional[bytes] = None + _body_params: Optional[Any] = None # process the path parameters if event_id is not None: _path_params['event_id'] = event_id - - - # process the body parameter if event_update is not None: _body_params = event_update - # set the HTTP header `Accept` if 'Accept' not in _header_params: - _header_params['Accept'] = self.api_client.select_header_accept( - [ - 'application/json' - ] - ) + _header_params['Accept'] = self.api_client.select_header_accept(['application/json']) # set the HTTP header `Content-Type` if _content_type: _header_params['Content-Type'] = _content_type else: - _default_content_type = ( - self.api_client.select_header_content_type( - [ - 'application/json' - ] - ) + _default_content_type = self.api_client.select_header_content_type( + ['application/json'] ) if _default_content_type is not None: _header_params['Content-Type'] = _default_content_type # authentication setting - _auth_settings: List[str] = [ - 'bearerAuth' - ] + _auth_settings: list[str] = ['bearerAuth'] return self.api_client.param_serialize( method='PATCH', @@ -1860,8 +2213,5 @@ def _update_event_serialize( files=_files, auth_settings=_auth_settings, collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth + _request_auth=_request_auth, ) - - diff --git a/fingerprint_server_sdk/api_client.py b/fingerprint_server_sdk/api_client.py index 47c93af2..6eb6a36f 100644 --- a/fingerprint_server_sdk/api_client.py +++ b/fingerprint_server_sdk/api_client.py @@ -1,21 +1,18 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 +from __future__ import annotations import datetime -from dateutil.parser import parse -from enum import Enum import decimal import json import mimetypes @@ -23,26 +20,29 @@ import re import tempfile import uuid - +from enum import Enum +from types import TracebackType +from typing import Any, Optional, Union from urllib.parse import quote -from typing import Tuple, Optional, List, Dict, Union, Any + +from dateutil.parser import parse from pydantic import SecretStr -from fingerprint_server_sdk.configuration import Configuration -from fingerprint_server_sdk.api_response import ApiResponse, T as ApiResponseT import fingerprint_server_sdk.models -from fingerprint_server_sdk import rest, __version__ +from fingerprint_server_sdk import __version__, rest +from fingerprint_server_sdk.api_response import ApiResponse +from fingerprint_server_sdk.api_response import T as ApiResponseT +from fingerprint_server_sdk.configuration import Configuration from fingerprint_server_sdk.exceptions import ( - ApiValueError, ApiException, - BadRequestException, - UnauthorizedException, - ForbiddenException, - NotFoundException, - ServiceException + ApiValueError, ) -RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]] +RequestSerialized = tuple[str, str, dict[str, Any], Optional[Any], Any] +FilesType = dict[ + str, Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]] +] + class ApiClient: """Generic API client for OpenAPI client library builds. @@ -63,7 +63,6 @@ class ApiClient: PRIMITIVE_TYPES = (float, bool, bytes, str, int) NATIVE_TYPES_MAPPING = { 'int': int, - 'long': int, # TODO remove as only py3 is supported? 'float': float, 'str': str, 'bool': bool, @@ -75,57 +74,59 @@ class ApiClient: def __init__( self, - configuration, - header_name=None, - header_value=None, - cookie=None + configuration: Configuration, + header_name: Optional[str] = None, + header_value: Optional[str] = None, + cookie: Optional[str] = None, ) -> None: self.configuration = configuration self.rest_client = rest.RESTClientObject(configuration) - self.default_headers = {} - if header_name is not None: + self.default_headers: dict[str, str] = {} + if header_name is not None and header_value is not None: self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = 'fingerprint-server-python-sdk/{__version__}' + self.user_agent = f'fingerprint-server-python-sdk/{__version__}' self.client_side_validation = configuration.client_side_validation - def __enter__(self): + def __enter__(self) -> ApiClient: return self - def __exit__(self, exc_type, exc_value, traceback): + def __exit__( + self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: pass @property - def user_agent(self) -> Optional[str]: + def user_agent(self) -> str: """User agent for this API client""" return self.default_headers['User-Agent'] @user_agent.setter - def user_agent(self, value: str): + def user_agent(self, value: str) -> None: self.default_headers['User-Agent'] = value - def set_default_header(self, header_name: str, header_value: str): + def set_default_header(self, header_name: str, header_value: str) -> None: self.default_headers[header_name] = header_value - def param_serialize( self, - method, - resource_path, - path_params=None, - query_params=None, - header_params=None, - body=None, - post_params=None, - files=None, - auth_settings=None, - collection_formats=None, - _host=None, - _request_auth=None + method: str, + resource_path: str, + path_params: Optional[dict[str, Any]] = None, + query_params: Optional[list[tuple[str, Any]]] = None, + header_params: Optional[dict[str, Any]] = None, + body: Optional[Any] = None, + post_params: Optional[list[tuple[str, Any]]] = None, + files: Optional[FilesType] = None, + auth_settings: Optional[list[str]] = None, + collection_formats: Optional[dict[str, str]] = None, + _request_auth: Optional[dict[str, Any]] = None, ) -> RequestSerialized: - """Builds the HTTP request params needed by the request. :param method: Method to call. :param resource_path: Path to method endpoint. @@ -157,34 +158,30 @@ def param_serialize( header_params['Cookie'] = self.cookie if header_params: header_params = self.sanitize_for_serialization(header_params) - header_params = dict( - self.parameters_to_tuples(header_params, collection_formats) - ) + header_params = dict(self.parameters_to_tuples(header_params, collection_formats)) # path parameters if path_params: - path_params = self.sanitize_for_serialization(path_params) - path_params = self.parameters_to_tuples( - path_params, - collection_formats + path_params_sanitized = self.sanitize_for_serialization(path_params) + path_params_tuples = self.parameters_to_tuples( + path_params_sanitized, collection_formats ) - for k, v in path_params: + for k, v in path_params_tuples: # specified safe chars, encode everything resource_path = resource_path.replace( - '{%s}' % k, - quote(str(v), safe=config.safe_chars_for_path_param) + '{' + k + '}', quote(str(v), safe=config.safe_chars_for_path_param) ) # post parameters + post_params_result: Any = None if post_params or files: - post_params = post_params if post_params else [] - post_params = self.sanitize_for_serialization(post_params) - post_params = self.parameters_to_tuples( - post_params, - collection_formats + post_params_list = post_params if post_params else [] + post_params_sanitized = self.sanitize_for_serialization(post_params_list) + post_params_result = self.parameters_to_tuples( + post_params_sanitized, collection_formats ) if files: - post_params.extend(self.files_parameters(files)) + post_params_result.extend(self.files_parameters(files)) # auth setting self.update_params_for_auth( @@ -194,7 +191,7 @@ def param_serialize( resource_path, method, body, - request_auth=_request_auth + request_auth=_request_auth, ) # body @@ -202,14 +199,10 @@ def param_serialize( body = self.sanitize_for_serialization(body) # request url - if _host is None: - url = self.configuration.host + resource_path - else: - # use server/host defined in path or operation instead - url = _host + resource_path + url = self.configuration.host + resource_path query_params = list(query_params or []) - if getattr(self.configuration, "default_query_params", None): + if getattr(self.configuration, 'default_query_params', None): existing_keys = {k for k, _ in query_params} for k, v in self.configuration.default_query_params: if k not in existing_keys: @@ -218,23 +211,19 @@ def param_serialize( # query parameters if query_params: query_params = self.sanitize_for_serialization(query_params) - url_query = self.parameters_to_url_query( - query_params, - collection_formats - ) - url += "?" + url_query - - return method, url, header_params, body, post_params + url_query = self.parameters_to_url_query(query_params, collection_formats) + url += '?' + url_query + return method, url, header_params, body, post_params_result def call_api( self, method: str, url: str, - header_params: Optional[Dict[str, Any]] = None, + header_params: Optional[dict[str, Any]] = None, body: Any = None, - post_params: Optional[List[Tuple[str, Any]]] = None, - _request_timeout: Optional[int] = None + post_params: Optional[list[Any]] = None, + _request_timeout: Optional[Union[int, float, tuple[float, float]]] = None, ) -> rest.RESTResponse: """Makes the HTTP request (synchronous) :param method: Method to call. @@ -256,7 +245,7 @@ def call_api( headers=header_params, body=body, post_params=post_params, - _request_timeout=_request_timeout + _request_timeout=_request_timeout, ) except ApiException as e: @@ -267,7 +256,7 @@ def call_api( def response_deserialize( self, response_data: rest.RESTResponse, - response_types_map: Optional[Dict[str, ApiResponseT]]=None + response_types_map: Optional[dict[str, Any]] = None, ) -> ApiResponse[ApiResponseT]: """Deserializes response into an object. :param response_data: RESTResponse object to be deserialized. @@ -275,33 +264,35 @@ def response_deserialize( :return: ApiResponse """ - msg = "RESTResponse.read() must be called before passing it to response_deserialize()" + msg = 'RESTResponse.read() must be called before passing it to response_deserialize()' assert response_data.data is not None, msg - response_type = response_types_map.get(str(response_data.status), None) + if response_types_map is None: + response_types_map = {} + + response_type = response_types_map.get(str(response_data.status)) if ( not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599 ): # if not found, look for '1XX', '2XX', etc. - response_type = response_types_map.get( - str(response_data.status)[0] + "XX", None) + response_type = response_types_map.get(str(response_data.status)[0] + 'XX') # deserialize response data - response_text = None - return_data = None + response_text: Optional[str] = None + return_data: Any = None try: - if response_type == "bytearray": + if response_type == 'bytearray': return_data = response_data.data - elif response_type == "file": + elif response_type == 'file': return_data = self.__deserialize_file(response_data) elif response_type is not None: match = None content_type = response_data.getheader('content-type') if content_type is not None: - match = re.search(r"charset=([a-zA-Z\-\d]+)[\s;]?", content_type) - encoding = match.group(1) if match else "utf-8" + match = re.search(r'charset=([a-zA-Z\-\d]+)[\s;]?', content_type) + encoding = match.group(1) if match else 'utf-8' response_text = response_data.data.decode(encoding) return_data = self.deserialize(response_text, response_type, content_type) finally: @@ -313,13 +304,13 @@ def response_deserialize( ) return ApiResponse( - status_code = response_data.status, - data = return_data, - headers = response_data.getheaders(), - raw_data = response_data.data + status_code=response_data.status, + data=return_data, + headers=response_data.getheaders(), + raw_data=response_data.data, ) - def sanitize_for_serialization(self, obj): + def sanitize_for_serialization(self, obj: Any) -> Any: """Builds a JSON POST object. If obj is None, return None. @@ -346,13 +337,9 @@ def sanitize_for_serialization(self, obj): elif isinstance(obj, uuid.UUID): return str(obj) elif isinstance(obj, list): - return [ - self.sanitize_for_serialization(sub_obj) for sub_obj in obj - ] + return [self.sanitize_for_serialization(sub_obj) for sub_obj in obj] elif isinstance(obj, tuple): - return tuple( - self.sanitize_for_serialization(sub_obj) for sub_obj in obj - ) + return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj) elif isinstance(obj, (datetime.datetime, datetime.date)): return obj.isoformat() elif isinstance(obj, decimal.Decimal): @@ -366,21 +353,21 @@ def sanitize_for_serialization(self, obj): # and attributes which value is not None. # Convert attribute name to json key in # model definition for request. - if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')): + if hasattr(obj, 'to_dict') and callable(obj.to_dict): obj_dict = obj.to_dict() else: obj_dict = obj.__dict__ if isinstance(obj_dict, list): - # here we handle instances that can either be a list or something else, and only became a real list by calling to_dict() + # here we handle instances that can either be a list or something else, + # and only became a real list by calling to_dict() return self.sanitize_for_serialization(obj_dict) - return { - key: self.sanitize_for_serialization(val) - for key, val in obj_dict.items() - } + return {key: self.sanitize_for_serialization(val) for key, val in obj_dict.items()} - def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]): + def deserialize( + self, response_text: str, response_type: str, content_type: Optional[str] + ) -> Any: """Deserializes response into an object. :param response: RESTResponse object to be deserialized. @@ -397,22 +384,21 @@ def deserialize(self, response_text: str, response_type: str, content_type: Opti data = json.loads(response_text) except ValueError: data = response_text - elif re.match(r'^application/(json|[\w!#$&.+\-^_]+\+json)\s*(;|$)', content_type, re.IGNORECASE): - if response_text == "": - data = "" + elif re.match( + r'^application/(json|[\w!#$&.+\-^_]+\+json)\s*(;|$)', content_type, re.IGNORECASE + ): + if response_text == '': + data = '' else: data = json.loads(response_text) elif re.match(r'^text\/[a-z.+-]+\s*(;|$)', content_type, re.IGNORECASE): data = response_text else: - raise ApiException( - status=0, - reason="Unsupported content type: {0}".format(content_type) - ) + raise ApiException(status=0, reason=f'Unsupported content type: {content_type}') return self.__deserialize(data, response_type) - def __deserialize(self, data, klass): + def __deserialize(self, data: Any, klass: Any) -> Any: """Deserializes dict, list, str into an object. :param data: dict, list or str. @@ -426,17 +412,15 @@ def __deserialize(self, data, klass): if isinstance(klass, str): if klass.startswith('List['): m = re.match(r'List\[(.*)]', klass) - assert m is not None, "Malformed List type definition" + assert m is not None, 'Malformed List type definition' sub_kls = m.group(1) - return [self.__deserialize(sub_data, sub_kls) - for sub_data in data] + return [self.__deserialize(sub_data, sub_kls) for sub_data in data] if klass.startswith('Dict['): m = re.match(r'Dict\[([^,]*), (.*)]', klass) - assert m is not None, "Malformed Dict type definition" + assert m is not None, 'Malformed Dict type definition' sub_kls = m.group(2) - return {k: self.__deserialize(v, sub_kls) - for k, v in data.items()} + return {k: self.__deserialize(v, sub_kls) for k, v in data.items()} # convert str to class if klass in self.NATIVE_TYPES_MAPPING: @@ -459,14 +443,18 @@ def __deserialize(self, data, klass): else: return self.__deserialize_model(data, klass) - def parameters_to_tuples(self, params, collection_formats): + def parameters_to_tuples( + self, + params: Union[dict[str, Any], list[tuple[str, Any]]], + collection_formats: Optional[dict[str, str]], + ) -> list[tuple[str, str]]: """Get parameters as list of tuples, formatting collections. :param params: Parameters as dict or list of two-tuples :param dict collection_formats: Parameter collection formats :return: Parameters as list of tuples, collections formatted """ - new_params: List[Tuple[str, str]] = [] + new_params: list[tuple[str, str]] = [] if collection_formats is None: collection_formats = {} for k, v in params.items() if isinstance(params, dict) else params: @@ -483,20 +471,23 @@ def parameters_to_tuples(self, params, collection_formats): delimiter = '|' else: # csv is the default delimiter = ',' - new_params.append( - (k, delimiter.join(str(value) for value in v))) + new_params.append((k, delimiter.join(str(value) for value in v))) else: new_params.append((k, v)) return new_params - def parameters_to_url_query(self, params, collection_formats): + def parameters_to_url_query( + self, + params: Union[dict[str, Any], list[tuple[str, Any]]], + collection_formats: Optional[dict[str, str]], + ) -> str: """Get parameters as list of tuples, formatting collections. :param params: Parameters as dict or list of two-tuples :param dict collection_formats: Parameter collection formats :return: URL query string (e.g. a=Hello%20World&b=123) """ - new_params: List[Tuple[str, str]] = [] + new_params: list[tuple[str, str]] = [] if collection_formats is None: collection_formats = {} for k, v in params.items() if isinstance(params, dict) else params: @@ -520,18 +511,16 @@ def parameters_to_url_query(self, params, collection_formats): delimiter = '|' else: # csv is the default delimiter = ',' - new_params.append( - (k, delimiter.join(quote(str(value)) for value in v)) - ) + new_params.append((k, delimiter.join(quote(str(value)) for value in v))) else: new_params.append((k, quote(str(v)))) - return "&".join(["=".join(map(str, item)) for item in new_params]) + return '&'.join(['='.join(map(str, item)) for item in new_params]) def files_parameters( self, - files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]], - ): + files: FilesType, + ) -> list[tuple[Any, Any]]: """Builds form parameters. :param files: File parameters. @@ -553,17 +542,12 @@ def files_parameters( params.extend(self.files_parameters({k: file_param})) continue else: - raise ValueError("Unsupported file value") - mimetype = ( - mimetypes.guess_type(filename)[0] - or 'application/octet-stream' - ) - params.append( - tuple([k, tuple([filename, filedata, mimetype])]) - ) + raise ValueError('Unsupported file value') + mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream' + params.append((k, (filename, filedata, mimetype))) return params - def select_header_accept(self, accepts: List[str]) -> Optional[str]: + def select_header_accept(self, accepts: list[str]) -> Optional[str]: """Returns `Accept` based on an array of accepts provided. :param accepts: List of headers. @@ -578,7 +562,7 @@ def select_header_accept(self, accepts: List[str]) -> Optional[str]: return accepts[0] - def select_header_content_type(self, content_types): + def select_header_content_type(self, content_types: list[str]) -> Optional[str]: """Returns `Content-Type` based on an array of content_types provided. :param content_types: List of content-types. @@ -595,13 +579,13 @@ def select_header_content_type(self, content_types): def update_params_for_auth( self, - headers, - queries, - auth_settings, - resource_path, - method, - body, - request_auth=None + headers: dict[str, str], + queries: Optional[list[tuple[str, Any]]], + auth_settings: Optional[list[str]], + resource_path: str, + method: str, + body: Any, + request_auth: Optional[dict[str, Any]] = None, ) -> None: """Updates header and query params based on authentication setting. @@ -619,14 +603,7 @@ def update_params_for_auth( return if request_auth: - self._apply_auth_params( - headers, - queries, - resource_path, - method, - body, - request_auth - ) + self._apply_auth_params(headers, queries, resource_path, method, body, request_auth) else: for auth in auth_settings: auth_setting = self.configuration.auth_settings().get(auth) @@ -637,17 +614,17 @@ def update_params_for_auth( resource_path, method, body, - auth_setting + auth_setting, # type: ignore[arg-type] ) def _apply_auth_params( self, - headers, - queries, - resource_path, - method, - body, - auth_setting + headers: dict[str, str], + queries: Optional[list[tuple[str, Any]]], + resource_path: str, + method: str, + body: Any, + auth_setting: dict[str, Any], ) -> None: """Updates the request parameters based on a single auth_setting @@ -665,13 +642,12 @@ def _apply_auth_params( if auth_setting['type'] != 'http-signature': headers[auth_setting['key']] = auth_setting['value'] elif auth_setting['in'] == 'query': - queries.append((auth_setting['key'], auth_setting['value'])) + if queries is not None: + queries.append((auth_setting['key'], auth_setting['value'])) else: - raise ApiValueError( - 'Authentication token must be in `query` or `header`' - ) + raise ApiValueError('Authentication token must be in `query` or `header`') - def __deserialize_file(self, response): + def __deserialize_file(self, response: rest.RESTResponse) -> Any: """Deserializes body to file Saves response body into a file in a temporary folder, @@ -683,26 +659,24 @@ def __deserialize_file(self, response): :param response: RESTResponse. :return: file path. """ - fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + fd, path = tempfile.mkstemp(dir=getattr(self.configuration, 'temp_folder_path', None)) os.close(fd) os.remove(path) - content_disposition = response.getheader("Content-Disposition") + content_disposition = response.getheader('Content-Disposition') if content_disposition: - m = re.search( - r'filename=[\'"]?([^\'"\s]+)[\'"]?', - content_disposition - ) + m = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', content_disposition) assert m is not None, "Unexpected 'content-disposition' header value" filename = m.group(1) path = os.path.join(os.path.dirname(path), filename) - with open(path, "wb") as f: - f.write(response.data) + with open(path, 'wb') as f: + if response.data is not None: + f.write(response.data) return path - def __deserialize_primitive(self, data, klass): + def __deserialize_primitive(self, data: Any, klass: type) -> Any: """Deserializes string to primitive type. :param data: str. @@ -717,14 +691,14 @@ def __deserialize_primitive(self, data, klass): except TypeError: return data - def __deserialize_object(self, value): + def __deserialize_object(self, value: Any) -> Any: """Return an original value. :return: object. """ return value - def __deserialize_date(self, string): + def __deserialize_date(self, string: str) -> datetime.date: """Deserializes string to date. :param string: str. @@ -733,14 +707,13 @@ def __deserialize_date(self, string): try: return parse(string).date() except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason="Failed to parse `{0}` as date object".format(string) - ) + return string # type: ignore[return-value] + except ValueError as err: + raise ApiException( + status=0, reason=f'Failed to parse `{string}` as date object' + ) from err - def __deserialize_datetime(self, string): + def __deserialize_datetime(self, string: str) -> datetime.datetime: """Deserializes string to datetime. The string should be in iso8601 datetime format. @@ -751,17 +724,13 @@ def __deserialize_datetime(self, string): try: return parse(string) except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason=( - "Failed to parse `{0}` as datetime object" - .format(string) - ) - ) + return string # type: ignore[return-value] + except ValueError as err: + raise ApiException( + status=0, reason=(f'Failed to parse `{string}` as datetime object') + ) from err - def __deserialize_enum(self, data, klass): + def __deserialize_enum(self, data: Any, klass: type[Enum]) -> Enum: """Deserializes primitive type to enum. :param data: primitive type. @@ -770,16 +739,12 @@ def __deserialize_enum(self, data, klass): """ try: return klass(data) - except ValueError: - raise rest.ApiException( - status=0, - reason=( - "Failed to parse `{0}` as `{1}`" - .format(data, klass) - ) - ) + except ValueError as err: + raise ApiException( + status=0, reason=(f'Failed to parse `{data}` as `{klass}`') + ) from err - def __deserialize_model(self, data, klass): + def __deserialize_model(self, data: Any, klass: Any) -> Any: """Deserializes list or dict to model. :param data: dict, list. @@ -787,4 +752,4 @@ def __deserialize_model(self, data, klass): :return: model object. """ - return klass.from_dict(data) \ No newline at end of file + return klass.from_dict(data) diff --git a/fingerprint_server_sdk/api_response.py b/fingerprint_server_sdk/api_response.py index 9bc7c11f..9dd29d86 100644 --- a/fingerprint_server_sdk/api_response.py +++ b/fingerprint_server_sdk/api_response.py @@ -1,21 +1,23 @@ """API response object.""" from __future__ import annotations -from typing import Optional, Generic, Mapping, TypeVar -from pydantic import Field, StrictInt, StrictBytes, BaseModel -T = TypeVar("T") +from collections.abc import Mapping +from typing import Generic, Optional, TypeVar + +from pydantic import BaseModel, Field, StrictBytes, StrictInt + +T = TypeVar('T') + class ApiResponse(BaseModel, Generic[T]): """ API response object """ - status_code: StrictInt = Field(description="HTTP status code") - headers: Optional[Mapping[str, str]] = Field(None, description="HTTP headers") - data: T = Field(description="Deserialized data given the data type") - raw_data: StrictBytes = Field(description="Raw data (HTTP response body)") + status_code: StrictInt = Field(description='HTTP status code') + headers: Optional[Mapping[str, str]] = Field(None, description='HTTP headers') + data: T = Field(description='Deserialized data given the data type') + raw_data: StrictBytes = Field(description='Raw data (HTTP response body)') - model_config = { - "arbitrary_types_allowed": True - } + model_config = {'arbitrary_types_allowed': True} diff --git a/fingerprint_server_sdk/configuration.py b/fingerprint_server_sdk/configuration.py index d9648185..0a4f42cf 100644 --- a/fingerprint_server_sdk/configuration.py +++ b/fingerprint_server_sdk/configuration.py @@ -1,74 +1,63 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - import copy import http.client as httplib import logging -from logging import FileHandler import multiprocessing import sys -from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict, Union, Tuple -from typing_extensions import NotRequired, Self -from fingerprint_server_sdk import __version__ from enum import Enum +from logging import FileHandler +from typing import Any, ClassVar, Literal, Optional, TypedDict, Union +from typing_extensions import Self + +from fingerprint_server_sdk import __version__ JSON_SCHEMA_VALIDATION_KEYWORDS = { - 'multipleOf', 'maximum', 'exclusiveMaximum', - 'minimum', 'exclusiveMinimum', 'maxLength', - 'minLength', 'pattern', 'maxItems', 'minItems' + 'multipleOf', + 'maximum', + 'exclusiveMaximum', + 'minimum', + 'exclusiveMinimum', + 'maxLength', + 'minLength', + 'pattern', + 'maxItems', + 'minItems', } -ServerVariablesT = Dict[str, str] +ServerVariablesT = dict[str, str] BearerFormatAuthSetting = TypedDict( - "BearerFormatAuthSetting", + 'BearerFormatAuthSetting', { - "type": Literal["bearer"], - "in": Literal["header"], - "format": Literal["JWT"], - "key": Literal["Authorization"], - "value": str, + 'type': Literal['bearer'], + 'in': Literal['header'], + 'format': Literal['JWT'], + 'key': Literal['Authorization'], + 'value': str, }, ) -AuthSettings = TypedDict( - "AuthSettings", - { - "bearerAuth": BearerFormatAuthSetting, - }, - total=False, -) - -class HostSettingVariable(TypedDict): - description: str - default_value: str - enum_values: List[str] - - -class HostSetting(TypedDict): - url: str - description: str - variables: NotRequired[Dict[str, HostSettingVariable]] +class AuthSettings(TypedDict, total=False): + bearerAuth: BearerFormatAuthSetting class Region(Enum): - US = "us" - EU = "eu" - AP = "ap" + US = 'us' + EU = 'eu' + AP = 'ap' class Configuration: @@ -91,16 +80,15 @@ def __init__( self, api_key: str, region: Region = Region.US, - host: Optional[str]=None, - ssl_ca_cert: Optional[str]=None, + host: Optional[str] = None, + ssl_ca_cert: Optional[str] = None, retries: Optional[int] = None, ca_cert_data: Optional[Union[str, bytes]] = None, - default_query_params: Optional[List[Tuple[str, str]]] = None, + default_query_params: Optional[list[tuple[str, str]]] = None, *, debug: Optional[bool] = None, ) -> None: - """Constructor - """ + """Constructor""" if host: self._base_path = host else: @@ -111,8 +99,8 @@ def __init__( self.logger = {} """Logging Settings """ - self.logger["package_logger"] = logging.getLogger("fingerprint_server_sdk") - self.logger["urllib3_logger"] = logging.getLogger("urllib3") + self.logger['package_logger'] = logging.getLogger('fingerprint_server_sdk') + self.logger['urllib3_logger'] = logging.getLogger('urllib3') self.logger_format = '%(asctime)s %(levelname)s %(message)s' """Log format """ @@ -185,20 +173,21 @@ def __init__( """Options to pass down to the underlying urllib3 socket """ - self.datetime_format = "%Y-%m-%dT%H:%M:%S.%f%z" + self.datetime_format = '%Y-%m-%dT%H:%M:%S.%f%z' """datetime format """ - self.date_format = "%Y-%m-%d" + self.date_format = '%Y-%m-%d' """date format """ - if default_query_params: - self.default_query_params = default_query_params - else: - self.default_query_params: List[Tuple[str, str]] = [("ii", f"fingerprint-server-python-sdk/{__version__}")] + self.default_query_params: list[tuple[str, str]] = ( + default_query_params + if default_query_params + else [('ii', f'fingerprint-server-python-sdk/{__version__}')] + ) - def __deepcopy__(self, memo: Dict[int, Any]) -> Self: + def __deepcopy__(self, memo: dict[int, Any]) -> Self: cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result @@ -319,7 +308,7 @@ def auth_settings(self) -> AuthSettings: 'in': 'header', 'format': 'JWT', 'key': 'Authorization', - 'value': 'Bearer ' + self.api_key + 'value': 'Bearer ' + self.api_key, } auth['bearerAuth'] = bearerAuth @@ -330,20 +319,21 @@ def to_debug_report(self) -> str: :return: The report for debugging. """ - return "Python SDK Debug Report:\n"\ - "OS: {env}\n"\ - "Python Version: {pyversion}\n"\ - "Version of the API: 4\n"\ - "SDK Package Version: 8.11.0".\ - format(env=sys.platform, pyversion=sys.version) + return ( + 'Python SDK Debug Report:\n' + f'OS: {sys.platform}\n' + f'Python Version: {sys.version}\n' + 'Version of the API: 4\n' + 'SDK Package Version: 8.11.0' + ) @staticmethod def get_host(region: Region) -> str: return { - Region.US: "https://api.fpjs.io/v4", - Region.EU: "https://eu.api.fpjs.io/v4", - Region.AP: "https://ap.api.fpjs.io/v4", - }.get(region, "https://api.fpjs.io/v4") + Region.US: 'https://api.fpjs.io/v4', + Region.EU: 'https://eu.api.fpjs.io/v4', + Region.AP: 'https://ap.api.fpjs.io/v4', + }.get(region, 'https://api.fpjs.io/v4') @property def host(self) -> str: diff --git a/fingerprint_server_sdk/exceptions.py b/fingerprint_server_sdk/exceptions.py index eb62fcca..4cf97a6d 100644 --- a/fingerprint_server_sdk/exceptions.py +++ b/fingerprint_server_sdk/exceptions.py @@ -1,28 +1,39 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 -from typing import Any, Optional +from __future__ import annotations + +import contextlib +from typing import TYPE_CHECKING, Any, Optional + from typing_extensions import Self +if TYPE_CHECKING: + from fingerprint_server_sdk.rest import RESTResponse + + class OpenApiException(Exception): """The base exception class for all OpenAPIExceptions""" class ApiTypeError(OpenApiException, TypeError): - def __init__(self, msg, path_to_item=None, valid_classes=None, - key_type=None) -> None: - """ Raises an exception for TypeErrors + def __init__( + self, + msg: str, + path_to_item: Optional[list[Any]] = None, + valid_classes: Optional[tuple[type, ...]] = None, + key_type: Optional[bool] = None, + ) -> None: + """Raises an exception for TypeErrors Args: msg (str): the exception message @@ -44,12 +55,12 @@ def __init__(self, msg, path_to_item=None, valid_classes=None, self.key_type = key_type full_msg = msg if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiTypeError, self).__init__(full_msg) + full_msg = f'{msg} at {render_path(path_to_item)}' + super().__init__(full_msg) class ApiValueError(OpenApiException, ValueError): - def __init__(self, msg, path_to_item=None) -> None: + def __init__(self, msg: str, path_to_item: Optional[list[Any]] = None) -> None: """ Args: msg (str): the exception message @@ -62,12 +73,12 @@ def __init__(self, msg, path_to_item=None) -> None: self.path_to_item = path_to_item full_msg = msg if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiValueError, self).__init__(full_msg) + full_msg = f'{msg} at {render_path(path_to_item)}' + super().__init__(full_msg) class ApiAttributeError(OpenApiException, AttributeError): - def __init__(self, msg, path_to_item=None) -> None: + def __init__(self, msg: str, path_to_item: Optional[list[Any]] = None) -> None: """ Raised when an attribute reference or assignment fails. @@ -81,12 +92,12 @@ def __init__(self, msg, path_to_item=None) -> None: self.path_to_item = path_to_item full_msg = msg if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiAttributeError, self).__init__(full_msg) + full_msg = f'{msg} at {render_path(path_to_item)}' + super().__init__(full_msg) class ApiKeyError(OpenApiException, KeyError): - def __init__(self, msg, path_to_item=None) -> None: + def __init__(self, msg: str, path_to_item: Optional[list[Any]] = None) -> None: """ Args: msg (str): the exception message @@ -98,17 +109,16 @@ def __init__(self, msg, path_to_item=None) -> None: self.path_to_item = path_to_item full_msg = msg if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiKeyError, self).__init__(full_msg) + full_msg = f'{msg} at {render_path(path_to_item)}' + super().__init__(full_msg) class ApiException(OpenApiException): - def __init__( self, - status=None, - reason=None, - http_resp=None, + status: Optional[int] = None, + reason: Optional[str] = None, + http_resp: Optional[RESTResponse] = None, *, body: Optional[str] = None, data: Optional[Any] = None, @@ -124,18 +134,16 @@ def __init__( self.status = http_resp.status if self.reason is None: self.reason = http_resp.reason - if self.body is None: - try: + if self.body is None and http_resp.data is not None: + with contextlib.suppress(UnicodeDecodeError): self.body = http_resp.data.decode('utf-8') - except Exception: - pass self.headers = http_resp.headers @classmethod def from_response( cls, *, - http_resp, + http_resp: RESTResponse, body: Optional[str], data: Optional[Any], ) -> Self: @@ -165,19 +173,17 @@ def from_response( raise ServiceException(http_resp=http_resp, body=body, data=data) raise ApiException(http_resp=http_resp, body=body, data=data) - def __str__(self): + def __str__(self) -> str: """Custom error messages for exception""" - error_message = "({0})\n"\ - "Reason: {1}\n".format(self.status, self.reason) + error_message = f'({self.status})\nReason: {self.reason}\n' if self.headers: - error_message += "HTTP response headers: {0}\n".format( - self.headers) + error_message += f'HTTP response headers: {self.headers}\n' if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) + error_message += f'HTTP response body: {self.body}\n' if self.data: - error_message += "HTTP response data: {0}\n".format(self.data) + error_message += f'HTTP response data: {self.data}\n' return error_message @@ -204,25 +210,28 @@ class ServiceException(ApiException): class ConflictException(ApiException): """Exception for HTTP 409 Conflict.""" + pass class UnprocessableEntityException(ApiException): """Exception for HTTP 422 Unprocessable Entity.""" + pass class TooManyRequestsException(ApiException): """Exception for HTTP 429 Too Many Requests.""" + pass -def render_path(path_to_item): +def render_path(path_to_item: list[Any]) -> str: """Returns a string representation of a path""" - result = "" + result = '' for pth in path_to_item: if isinstance(pth, int): - result += "[{0}]".format(pth) + result += f'[{pth}]' else: - result += "['{0}']".format(pth) - return result \ No newline at end of file + result += f"['{pth}']" + return result diff --git a/fingerprint_server_sdk/models/__init__.py b/fingerprint_server_sdk/models/__init__.py index e65f2581..f3e0c0dc 100644 --- a/fingerprint_server_sdk/models/__init__.py +++ b/fingerprint_server_sdk/models/__init__.py @@ -1,16 +1,14 @@ -# coding: utf-8 - -# flake8: noqa +# ruff: noqa: E501, F401, I001 """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 # import models into model package @@ -30,7 +28,9 @@ from fingerprint_server_sdk.models.event_update import EventUpdate from fingerprint_server_sdk.models.font_preferences import FontPreferences from fingerprint_server_sdk.models.geolocation import Geolocation -from fingerprint_server_sdk.models.geolocation_subdivisions_inner import GeolocationSubdivisionsInner +from fingerprint_server_sdk.models.geolocation_subdivisions_inner import ( + GeolocationSubdivisionsInner, +) from fingerprint_server_sdk.models.ip_block_list import IPBlockList from fingerprint_server_sdk.models.ip_info import IPInfo from fingerprint_server_sdk.models.ip_info_v4 import IPInfoV4 @@ -59,4 +59,3 @@ from fingerprint_server_sdk.models.vpn_methods import VpnMethods from fingerprint_server_sdk.models.web_gl_basics import WebGlBasics from fingerprint_server_sdk.models.web_gl_extensions import WebGlExtensions - diff --git a/fingerprint_server_sdk/models/bot_info.py b/fingerprint_server_sdk/models/bot_info.py index 038bd40c..f3d10232 100644 --- a/fingerprint_server_sdk/models/bot_info.py +++ b/fingerprint_server_sdk/models/bot_info.py @@ -1,49 +1,61 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class BotInfo(BaseModel): """ Extended bot information. - """ # noqa: E501 - category: StrictStr = Field(description="The type and purpose of the bot.") - provider: StrictStr = Field(description="The organization or company operating the bot.") - provider_url: Optional[StrictStr] = Field(default=None, description="The URL of the bot provider's website.") - name: StrictStr = Field(description="The specific name or identifier of the bot.") - identity: StrictStr = Field(description="The verification status of the bot's identity: * `verified` - well-known bot with publicly verifiable identity, directed by the bot provider. * `signed` - bot that signs its platform via Web Bot Auth, directed by the bot provider’s customers. * `spoofed` - bot that claims a public identity but fails verification. * `unknown` - bot that does not publish a verifiable identity. ") - confidence: StrictStr = Field(description="Confidence level of the bot identification.") - __properties: ClassVar[List[str]] = ["category", "provider", "provider_url", "name", "identity", "confidence"] + """ + + category: StrictStr = Field(description='The type and purpose of the bot.') + provider: StrictStr = Field(description='The organization or company operating the bot.') + provider_url: Optional[StrictStr] = Field( + default=None, description="The URL of the bot provider's website." + ) + name: StrictStr = Field(description='The specific name or identifier of the bot.') + identity: StrictStr = Field( + description="The verification status of the bot's identity: * `verified` - well-known bot with publicly verifiable identity, directed by the bot provider. * `signed` - bot that signs its platform via Web Bot Auth, directed by the bot provider’s customers. * `spoofed` - bot that claims a public identity but fails verification. * `unknown` - bot that does not publish a verifiable identity. " + ) + confidence: StrictStr = Field(description='Confidence level of the bot identification.') + __properties: ClassVar[list[str]] = [ + 'category', + 'provider', + 'provider_url', + 'name', + 'identity', + 'confidence', + ] @field_validator('identity') - def identity_validate_enum(cls, value): + def identity_validate_enum(cls, value: Any) -> Any: """Validates the enum""" if value not in set(['verified', 'signed', 'spoofed', 'unknown']): - raise ValueError("must be one of enum values ('verified', 'signed', 'spoofed', 'unknown')") + raise ValueError( + "must be one of enum values ('verified', 'signed', 'spoofed', 'unknown')" + ) return value @field_validator('confidence') - def confidence_validate_enum(cls, value): + def confidence_validate_enum(cls, value: Any) -> Any: """Validates the enum""" if value not in set(['low', 'medium', 'high']): raise ValueError("must be one of enum values ('low', 'medium', 'high')") @@ -55,7 +67,6 @@ def confidence_validate_enum(cls, value): 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)) @@ -70,7 +81,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of BotInfo from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -80,8 +91,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -91,7 +101,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of BotInfo from a dict""" if obj is None: return None @@ -99,14 +109,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "category": obj.get("category"), - "provider": obj.get("provider"), - "provider_url": obj.get("provider_url"), - "name": obj.get("name"), - "identity": obj.get("identity"), - "confidence": obj.get("confidence") - }) + _obj = cls.model_validate( + { + 'category': obj.get('category'), + 'provider': obj.get('provider'), + 'provider_url': obj.get('provider_url'), + 'name': obj.get('name'), + 'identity': obj.get('identity'), + 'confidence': obj.get('confidence'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/bot_result.py b/fingerprint_server_sdk/models/bot_result.py index 41dc280a..50e5abc3 100644 --- a/fingerprint_server_sdk/models/bot_result.py +++ b/fingerprint_server_sdk/models/bot_result.py @@ -1,27 +1,26 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + import json from enum import Enum + from typing_extensions import Self class BotResult(str, Enum): """ - Bot detection result: * `bad` - bad bot detected, such as Selenium, Puppeteer, Playwright, headless browsers, and so on * `good` - good bot detected, such as Google bot, Baidu Spider, AlexaBot and so on * `not_detected` - the visitor is not a bot + Bot detection result: * `bad` - bad bot detected, such as Selenium, Puppeteer, Playwright, headless browsers, and so on * `good` - good bot detected, such as Google bot, Baidu Spider, AlexaBot and so on * `not_detected` - the visitor is not a bot """ """ @@ -35,5 +34,3 @@ class BotResult(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of BotResult from a JSON string""" return cls(json.loads(json_str)) - - diff --git a/fingerprint_server_sdk/models/browser_details.py b/fingerprint_server_sdk/models/browser_details.py index ed847562..ef4847b7 100644 --- a/fingerprint_server_sdk/models/browser_details.py +++ b/fingerprint_server_sdk/models/browser_details.py @@ -1,39 +1,45 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List -from typing import Optional, Set from typing_extensions import Self + class BrowserDetails(BaseModel): """ BrowserDetails - """ # noqa: E501 + """ + browser_name: StrictStr browser_major_version: StrictStr browser_full_version: StrictStr os: StrictStr os_version: StrictStr device: StrictStr - __properties: ClassVar[List[str]] = ["browser_name", "browser_major_version", "browser_full_version", "os", "os_version", "device"] + __properties: ClassVar[list[str]] = [ + 'browser_name', + 'browser_major_version', + 'browser_full_version', + 'os', + 'os_version', + 'device', + ] model_config = ConfigDict( populate_by_name=True, @@ -41,7 +47,6 @@ class BrowserDetails(BaseModel): 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)) @@ -56,7 +61,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of BrowserDetails from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,8 +71,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -77,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of BrowserDetails from a dict""" if obj is None: return None @@ -85,14 +89,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "browser_name": obj.get("browser_name"), - "browser_major_version": obj.get("browser_major_version"), - "browser_full_version": obj.get("browser_full_version"), - "os": obj.get("os"), - "os_version": obj.get("os_version"), - "device": obj.get("device") - }) + _obj = cls.model_validate( + { + 'browser_name': obj.get('browser_name'), + 'browser_major_version': obj.get('browser_major_version'), + 'browser_full_version': obj.get('browser_full_version'), + 'os': obj.get('os'), + 'os_version': obj.get('os_version'), + 'device': obj.get('device'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/canvas.py b/fingerprint_server_sdk/models/canvas.py index 5321df68..653faf0d 100644 --- a/fingerprint_server_sdk/models/canvas.py +++ b/fingerprint_server_sdk/models/canvas.py @@ -1,36 +1,39 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class Canvas(BaseModel): """ Canvas fingerprint containing winding flag plus geometry/text hashes. - """ # noqa: E501 + """ + winding: Optional[StrictBool] = None - geometry: Optional[StrictStr] = Field(default=None, description="Hash of geometry rendering output or `unsupported` markers.") - text: Optional[StrictStr] = Field(default=None, description="Hash of text rendering output or `unsupported` markers.") - __properties: ClassVar[List[str]] = ["winding", "geometry", "text"] + geometry: Optional[StrictStr] = Field( + default=None, description='Hash of geometry rendering output or `unsupported` markers.' + ) + text: Optional[StrictStr] = Field( + default=None, description='Hash of text rendering output or `unsupported` markers.' + ) + __properties: ClassVar[list[str]] = ['winding', 'geometry', 'text'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +41,6 @@ class Canvas(BaseModel): 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)) @@ -53,7 +55,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Canvas from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +65,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +75,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Canvas from a dict""" if obj is None: return None @@ -82,11 +83,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "winding": obj.get("winding"), - "geometry": obj.get("geometry"), - "text": obj.get("text") - }) + _obj = cls.model_validate( + { + 'winding': obj.get('winding'), + 'geometry': obj.get('geometry'), + 'text': obj.get('text'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/emoji.py b/fingerprint_server_sdk/models/emoji.py index 22a51b8d..9410a2b1 100644 --- a/fingerprint_server_sdk/models/emoji.py +++ b/fingerprint_server_sdk/models/emoji.py @@ -1,33 +1,34 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional, Union -from typing import Optional, Set from typing_extensions import Self + class Emoji(BaseModel): """ Bounding box metrics describing how the emoji glyph renders. - """ # noqa: E501 - font: Optional[StrictStr] = Field(default=None, description="Font family reported by the browser when drawing the emoji.") + """ + + font: Optional[StrictStr] = Field( + default=None, description='Font family reported by the browser when drawing the emoji.' + ) width: Optional[Union[StrictFloat, StrictInt]] = None height: Optional[Union[StrictFloat, StrictInt]] = None top: Optional[Union[StrictFloat, StrictInt]] = None @@ -36,7 +37,17 @@ class Emoji(BaseModel): right: Optional[Union[StrictFloat, StrictInt]] = None x: Optional[Union[StrictFloat, StrictInt]] = None y: Optional[Union[StrictFloat, StrictInt]] = None - __properties: ClassVar[List[str]] = ["font", "width", "height", "top", "bottom", "left", "right", "x", "y"] + __properties: ClassVar[list[str]] = [ + 'font', + 'width', + 'height', + 'top', + 'bottom', + 'left', + 'right', + 'x', + 'y', + ] model_config = ConfigDict( populate_by_name=True, @@ -44,7 +55,6 @@ class Emoji(BaseModel): 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)) @@ -59,7 +69,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Emoji from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -69,8 +79,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -80,7 +89,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Emoji from a dict""" if obj is None: return None @@ -88,17 +97,17 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "font": obj.get("font"), - "width": obj.get("width"), - "height": obj.get("height"), - "top": obj.get("top"), - "bottom": obj.get("bottom"), - "left": obj.get("left"), - "right": obj.get("right"), - "x": obj.get("x"), - "y": obj.get("y") - }) + _obj = cls.model_validate( + { + 'font': obj.get('font'), + 'width': obj.get('width'), + 'height': obj.get('height'), + 'top': obj.get('top'), + 'bottom': obj.get('bottom'), + 'left': obj.get('left'), + 'right': obj.get('right'), + 'x': obj.get('x'), + 'y': obj.get('y'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/error.py b/fingerprint_server_sdk/models/error.py index 2df9a6af..020f5b3d 100644 --- a/fingerprint_server_sdk/models/error.py +++ b/fingerprint_server_sdk/models/error.py @@ -1,36 +1,36 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List -from fingerprint_server_sdk.models.error_code import ErrorCode -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.error_code import ErrorCode + + class Error(BaseModel): """ Error - """ # noqa: E501 + """ + code: ErrorCode message: StrictStr - __properties: ClassVar[List[str]] = ["code", "message"] + __properties: ClassVar[list[str]] = ['code', 'message'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +38,6 @@ class Error(BaseModel): 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)) @@ -53,7 +52,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Error from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +62,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +72,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Error from a dict""" if obj is None: return None @@ -82,10 +80,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "code": obj.get("code"), - "message": obj.get("message") - }) + _obj = cls.model_validate({'code': obj.get('code'), 'message': obj.get('message')}) return _obj - - diff --git a/fingerprint_server_sdk/models/error_code.py b/fingerprint_server_sdk/models/error_code.py index 37528758..11d9cfb6 100644 --- a/fingerprint_server_sdk/models/error_code.py +++ b/fingerprint_server_sdk/models/error_code.py @@ -1,27 +1,26 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + import json from enum import Enum + from typing_extensions import Self class ErrorCode(str, Enum): """ - Error code: * `request_cannot_be_parsed` - The query parameters or JSON payload contains some errors that prevented us from parsing it (wrong type/surpassed limits). * `secret_api_key_required` - secret API key in header is missing or empty. * `secret_api_key_not_found` - No Fingerprint workspace found for specified secret API key. * `public_api_key_required` - public API key in header is missing or empty. * `public_api_key_not_found` - No Fingerprint workspace found for specified public API key. * `subscription_not_active` - Fingerprint workspace is not active. * `wrong_region` - Server and workspace region differ. * `feature_not_enabled` - This feature (for example, Delete API) is not enabled for your workspace. * `request_not_found` - The specified event ID was not found. It never existed, expired, or it has been deleted. * `visitor_not_found` - The specified visitor ID was not found. It never existed or it may have already been deleted. * `too_many_requests` - The limit on secret API key requests per second has been exceeded. * `state_not_ready` - The event specified with event ID is not ready for updates yet. Try again. This error happens in rare cases when update API is called immediately after receiving the event ID on the client. In case you need to send information right away, we recommend using the JS agent API instead. * `failed` - Internal server error. * `event_not_found` - The specified event ID was not found. It never existed, expired, or it has been deleted. * `missing_module` - The request is invalid because it is missing a required module. * `payload_too_large` - The request payload is too large and cannot be processed. * `service_unavailable` - The service was unable to process the request. * `ruleset_not_found` - The specified ruleset was not found. It never existed or it has been deleted. + Error code: * `request_cannot_be_parsed` - The query parameters or JSON payload contains some errors that prevented us from parsing it (wrong type/surpassed limits). * `secret_api_key_required` - secret API key in header is missing or empty. * `secret_api_key_not_found` - No Fingerprint workspace found for specified secret API key. * `public_api_key_required` - public API key in header is missing or empty. * `public_api_key_not_found` - No Fingerprint workspace found for specified public API key. * `subscription_not_active` - Fingerprint workspace is not active. * `wrong_region` - Server and workspace region differ. * `feature_not_enabled` - This feature (for example, Delete API) is not enabled for your workspace. * `request_not_found` - The specified event ID was not found. It never existed, expired, or it has been deleted. * `visitor_not_found` - The specified visitor ID was not found. It never existed or it may have already been deleted. * `too_many_requests` - The limit on secret API key requests per second has been exceeded. * `state_not_ready` - The event specified with event ID is not ready for updates yet. Try again. This error happens in rare cases when update API is called immediately after receiving the event ID on the client. In case you need to send information right away, we recommend using the JS agent API instead. * `failed` - Internal server error. * `event_not_found` - The specified event ID was not found. It never existed, expired, or it has been deleted. * `missing_module` - The request is invalid because it is missing a required module. * `payload_too_large` - The request payload is too large and cannot be processed. * `service_unavailable` - The service was unable to process the request. * `ruleset_not_found` - The specified ruleset was not found. It never existed or it has been deleted. """ """ @@ -50,5 +49,3 @@ class ErrorCode(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of ErrorCode from a JSON string""" return cls(json.loads(json_str)) - - diff --git a/fingerprint_server_sdk/models/error_response.py b/fingerprint_server_sdk/models/error_response.py index e0bb54cf..0959355e 100644 --- a/fingerprint_server_sdk/models/error_response.py +++ b/fingerprint_server_sdk/models/error_response.py @@ -1,35 +1,35 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List -from fingerprint_server_sdk.models.error import Error -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.error import Error + + class ErrorResponse(BaseModel): """ ErrorResponse - """ # noqa: E501 + """ + error: Error - __properties: ClassVar[List[str]] = ["error"] + __properties: ClassVar[list[str]] = ['error'] model_config = ConfigDict( populate_by_name=True, @@ -37,7 +37,6 @@ class ErrorResponse(BaseModel): 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)) @@ -52,7 +51,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of ErrorResponse from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -62,8 +61,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -76,7 +74,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of ErrorResponse from a dict""" if obj is None: return None @@ -84,9 +82,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "error": Error.from_dict(obj["error"]) if obj.get("error") is not None else None - }) + _obj = cls.model_validate( + {'error': Error.from_dict(obj['error']) if obj.get('error') is not None else None} + ) return _obj - - diff --git a/fingerprint_server_sdk/models/event.py b/fingerprint_server_sdk/models/event.py index a011c134..5f73c0bc 100644 --- a/fingerprint_server_sdk/models/event.py +++ b/fingerprint_server_sdk/models/event.py @@ -1,25 +1,25 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Self + from fingerprint_server_sdk.models.bot_info import BotInfo from fingerprint_server_sdk.models.bot_result import BotResult from fingerprint_server_sdk.models.browser_details import BrowserDetails @@ -37,64 +37,208 @@ from fingerprint_server_sdk.models.velocity import Velocity from fingerprint_server_sdk.models.vpn_confidence import VpnConfidence from fingerprint_server_sdk.models.vpn_methods import VpnMethods -from typing import Optional, Set -from typing_extensions import Self + class Event(BaseModel): """ Contains results from Fingerprint Identification and all active Smart Signals. - """ # noqa: E501 - event_id: StrictStr = Field(description="Unique identifier of the user's request. The first portion of the event_id is a unix epoch milliseconds timestamp For example: `1758130560902.8tRtrH` ") - timestamp: StrictInt = Field(description="Timestamp of the event with millisecond precision in Unix time.") - linked_id: Optional[StrictStr] = Field(default=None, description="A customer-provided id that was sent with the request.") - environment_id: Optional[StrictStr] = Field(default=None, description="Environment Id of the event. For example: `ae_47abaca3db2c7c43` ") - suspect: Optional[StrictBool] = Field(default=None, description="Field is `true` if you have previously set the `suspect` flag for this event using the [Server API Update event endpoint](https://dev.fingerprint.com/reference/updateevent).") + """ + + event_id: StrictStr = Field( + description="Unique identifier of the user's request. The first portion of the event_id is a unix epoch milliseconds timestamp For example: `1758130560902.8tRtrH` " + ) + timestamp: StrictInt = Field( + description='Timestamp of the event with millisecond precision in Unix time.' + ) + linked_id: Optional[StrictStr] = Field( + default=None, description='A customer-provided id that was sent with the request.' + ) + environment_id: Optional[StrictStr] = Field( + default=None, + description='Environment Id of the event. For example: `ae_47abaca3db2c7c43` ', + ) + suspect: Optional[StrictBool] = Field( + default=None, + description='Field is `true` if you have previously set the `suspect` flag for this event using the [Server API Update event endpoint](https://dev.fingerprint.com/reference/updateevent).', + ) sdk: Optional[SDK] = None - replayed: Optional[StrictBool] = Field(default=None, description="`true` if we determined that this payload was replayed, `false` otherwise. ") + replayed: Optional[StrictBool] = Field( + default=None, + description='`true` if we determined that this payload was replayed, `false` otherwise. ', + ) identification: Optional[Identification] = None supplementary_id_high_recall: Optional[SupplementaryIDHighRecall] = None - tags: Optional[Dict[str, Any]] = Field(default=None, description="A customer-provided value or an object that was sent with the identification request or updated later.") - url: Optional[StrictStr] = Field(default=None, description="Page URL from which the request was sent. For example `https://example.com/` ") - bundle_id: Optional[StrictStr] = Field(default=None, description="Bundle Id of the iOS application integrated with the Fingerprint SDK for the event. For example: `com.foo.app` ") - package_name: Optional[StrictStr] = Field(default=None, description="Package name of the Android application integrated with the Fingerprint SDK for the event. For example: `com.foo.app` ") - ip_address: Optional[StrictStr] = Field(default=None, description="IP address of the requesting browser or bot.") - user_agent: Optional[StrictStr] = Field(default=None, description="User Agent of the client, for example: `Mozilla/5.0 (Windows NT 6.1; Win64; x64) ....` ") - client_referrer: Optional[StrictStr] = Field(default=None, description="Client Referrer field corresponds to the `document.referrer` field gathered during an identification request. The value is an empty string if the user navigated to the page directly (not through a link, but, for example, by using a bookmark) For example: `https://example.com/blog/my-article` ") + tags: Optional[dict[str, Any]] = Field( + default=None, + description='A customer-provided value or an object that was sent with the identification request or updated later.', + ) + url: Optional[StrictStr] = Field( + default=None, + description='Page URL from which the request was sent. For example `https://example.com/` ', + ) + bundle_id: Optional[StrictStr] = Field( + default=None, + description='Bundle Id of the iOS application integrated with the Fingerprint SDK for the event. For example: `com.foo.app` ', + ) + package_name: Optional[StrictStr] = Field( + default=None, + description='Package name of the Android application integrated with the Fingerprint SDK for the event. For example: `com.foo.app` ', + ) + ip_address: Optional[StrictStr] = Field( + default=None, description='IP address of the requesting browser or bot.' + ) + user_agent: Optional[StrictStr] = Field( + default=None, + description='User Agent of the client, for example: `Mozilla/5.0 (Windows NT 6.1; Win64; x64) ....` ', + ) + client_referrer: Optional[StrictStr] = Field( + default=None, + description='Client Referrer field corresponds to the `document.referrer` field gathered during an identification request. The value is an empty string if the user navigated to the page directly (not through a link, but, for example, by using a bookmark) For example: `https://example.com/blog/my-article` ', + ) browser_details: Optional[BrowserDetails] = None proximity: Optional[Proximity] = None bot: Optional[BotResult] = None - bot_type: Optional[StrictStr] = Field(default=None, description="Additional classification of the bot type if detected. ") + bot_type: Optional[StrictStr] = Field( + default=None, description='Additional classification of the bot type if detected. ' + ) bot_info: Optional[BotInfo] = None - cloned_app: Optional[StrictBool] = Field(default=None, description="Android specific cloned application detection. There are 2 values: * `true` - Presence of app cloners work detected (e.g. fully cloned application found or launch of it inside of a not main working profile detected). * `false` - No signs of cloned application detected or the client is not Android. ") - developer_tools: Optional[StrictBool] = Field(default=None, description="`true` if the browser is Chrome with DevTools open or Firefox with Developer Tools open, `false` otherwise. ") - emulator: Optional[StrictBool] = Field(default=None, description="Android specific emulator detection. There are 2 values: * `true` - Emulated environment detected (e.g. launch inside of AVD). * `false` - No signs of emulated environment detected or the client is not Android. ") - factory_reset_timestamp: Optional[StrictInt] = Field(default=None, description="The time of the most recent factory reset that happened on the **mobile device** is expressed as Unix epoch time. When a factory reset cannot be detected on the mobile device or when the request is initiated from a browser, this field will correspond to the *epoch* time (i.e 1 Jan 1970 UTC) as a value of 0. See [Factory Reset Detection](https://dev.fingerprint.com/docs/smart-signals-overview#factory-reset-detection) to learn more about this Smart Signal. ") - frida: Optional[StrictBool] = Field(default=None, description="[Frida](https://frida.re/docs/) detection for Android and iOS devices. There are 2 values: * `true` - Frida detected * `false` - No signs of Frida or the client is not a mobile device. ") + cloned_app: Optional[StrictBool] = Field( + default=None, + description='Android specific cloned application detection. There are 2 values: * `true` - Presence of app cloners work detected (e.g. fully cloned application found or launch of it inside of a not main working profile detected). * `false` - No signs of cloned application detected or the client is not Android. ', + ) + developer_tools: Optional[StrictBool] = Field( + default=None, + description='`true` if the browser is Chrome with DevTools open or Firefox with Developer Tools open, `false` otherwise. ', + ) + emulator: Optional[StrictBool] = Field( + default=None, + description='Android specific emulator detection. There are 2 values: * `true` - Emulated environment detected (e.g. launch inside of AVD). * `false` - No signs of emulated environment detected or the client is not Android. ', + ) + factory_reset_timestamp: Optional[StrictInt] = Field( + default=None, + description='The time of the most recent factory reset that happened on the **mobile device** is expressed as Unix epoch time. When a factory reset cannot be detected on the mobile device or when the request is initiated from a browser, this field will correspond to the *epoch* time (i.e 1 Jan 1970 UTC) as a value of 0. See [Factory Reset Detection](https://dev.fingerprint.com/docs/smart-signals-overview#factory-reset-detection) to learn more about this Smart Signal. ', + ) + frida: Optional[StrictBool] = Field( + default=None, + description='[Frida](https://frida.re/docs/) detection for Android and iOS devices. There are 2 values: * `true` - Frida detected * `false` - No signs of Frida or the client is not a mobile device. ', + ) ip_blocklist: Optional[IPBlockList] = None ip_info: Optional[IPInfo] = None - proxy: Optional[StrictBool] = Field(default=None, description="IP address was used by a public proxy provider or belonged to a known recent residential proxy ") + proxy: Optional[StrictBool] = Field( + default=None, + description='IP address was used by a public proxy provider or belonged to a known recent residential proxy ', + ) proxy_confidence: Optional[ProxyConfidence] = None proxy_details: Optional[ProxyDetails] = None - incognito: Optional[StrictBool] = Field(default=None, description="`true` if we detected incognito mode used in the browser, `false` otherwise. ") - jailbroken: Optional[StrictBool] = Field(default=None, description="iOS specific jailbreak detection. There are 2 values: * `true` - Jailbreak detected. * `false` - No signs of jailbreak or the client is not iOS. ") - location_spoofing: Optional[StrictBool] = Field(default=None, description="Flag indicating whether the request came from a mobile device with location spoofing enabled.") - mitm_attack: Optional[StrictBool] = Field(default=None, description="* `true` - When requests made from your users' mobile devices to Fingerprint servers have been intercepted and potentially modified. * `false` - Otherwise or when the request originated from a browser. See [MitM Attack Detection](https://dev.fingerprint.com/docs/smart-signals-reference#mitm-attack-detection) to learn more about this Smart Signal. ") - privacy_settings: Optional[StrictBool] = Field(default=None, description="`true` if the request is from a privacy aware browser (e.g. Tor) or from a browser in which fingerprinting is blocked. Otherwise `false`. ") - root_apps: Optional[StrictBool] = Field(default=None, description="Android specific root management apps detection. There are 2 values: * `true` - Root Management Apps detected (e.g. Magisk). * `false` - No Root Management Apps detected or the client isn't Android. ") + incognito: Optional[StrictBool] = Field( + default=None, + description='`true` if we detected incognito mode used in the browser, `false` otherwise. ', + ) + jailbroken: Optional[StrictBool] = Field( + default=None, + description='iOS specific jailbreak detection. There are 2 values: * `true` - Jailbreak detected. * `false` - No signs of jailbreak or the client is not iOS. ', + ) + location_spoofing: Optional[StrictBool] = Field( + default=None, + description='Flag indicating whether the request came from a mobile device with location spoofing enabled.', + ) + mitm_attack: Optional[StrictBool] = Field( + default=None, + description="* `true` - When requests made from your users' mobile devices to Fingerprint servers have been intercepted and potentially modified. * `false` - Otherwise or when the request originated from a browser. See [MitM Attack Detection](https://dev.fingerprint.com/docs/smart-signals-reference#mitm-attack-detection) to learn more about this Smart Signal. ", + ) + privacy_settings: Optional[StrictBool] = Field( + default=None, + description='`true` if the request is from a privacy aware browser (e.g. Tor) or from a browser in which fingerprinting is blocked. Otherwise `false`. ', + ) + root_apps: Optional[StrictBool] = Field( + default=None, + description="Android specific root management apps detection. There are 2 values: * `true` - Root Management Apps detected (e.g. Magisk). * `false` - No Root Management Apps detected or the client isn't Android. ", + ) rule_action: Optional[EventRuleAction] = None - suspect_score: Optional[StrictInt] = Field(default=None, description="Suspect Score is an easy way to integrate Smart Signals into your fraud protection work flow. It is a weighted representation of all Smart Signals present in the payload that helps identify suspicious activity. The value range is [0; S] where S is sum of all Smart Signals weights. See more details here: https://dev.fingerprint.com/docs/suspect-score ") - tampering: Optional[StrictBool] = Field(default=None, description="Flag indicating browser tampering was detected. This happens when either: * There are inconsistencies in the browser configuration that cross internal tampering thresholds (see `tampering_details.anomaly_score`). * The browser signature resembles an \"anti-detect\" browser specifically designed to evade fingerprinting (see `tampering_details.anti_detect_browser`). ") + suspect_score: Optional[StrictInt] = Field( + default=None, + description='Suspect Score is an easy way to integrate Smart Signals into your fraud protection work flow. It is a weighted representation of all Smart Signals present in the payload that helps identify suspicious activity. The value range is [0; S] where S is sum of all Smart Signals weights. See more details here: https://dev.fingerprint.com/docs/suspect-score ', + ) + tampering: Optional[StrictBool] = Field( + default=None, + description='Flag indicating browser tampering was detected. This happens when either: * There are inconsistencies in the browser configuration that cross internal tampering thresholds (see `tampering_details.anomaly_score`). * The browser signature resembles an "anti-detect" browser specifically designed to evade fingerprinting (see `tampering_details.anti_detect_browser`). ', + ) tampering_details: Optional[TamperingDetails] = None velocity: Optional[Velocity] = None - virtual_machine: Optional[StrictBool] = Field(default=None, description="`true` if the request came from a browser running inside a virtual machine (e.g. VMWare), `false` otherwise. ") - vpn: Optional[StrictBool] = Field(default=None, description="VPN or other anonymizing service has been used when sending the request. ") + virtual_machine: Optional[StrictBool] = Field( + default=None, + description='`true` if the request came from a browser running inside a virtual machine (e.g. VMWare), `false` otherwise. ', + ) + vpn: Optional[StrictBool] = Field( + default=None, + description='VPN or other anonymizing service has been used when sending the request. ', + ) vpn_confidence: Optional[VpnConfidence] = None - vpn_origin_timezone: Optional[StrictStr] = Field(default=None, description="Local timezone which is used in timezone_mismatch method. ") - vpn_origin_country: Optional[StrictStr] = Field(default=None, description="Country of the request (only for Android SDK version >= 2.4.0, ISO 3166 format or unknown). ") + vpn_origin_timezone: Optional[StrictStr] = Field( + default=None, description='Local timezone which is used in timezone_mismatch method. ' + ) + vpn_origin_country: Optional[StrictStr] = Field( + default=None, + description='Country of the request (only for Android SDK version >= 2.4.0, ISO 3166 format or unknown). ', + ) vpn_methods: Optional[VpnMethods] = None - high_activity_device: Optional[StrictBool] = Field(default=None, description="Flag indicating if the request came from a high-activity visitor.") + high_activity_device: Optional[StrictBool] = Field( + default=None, + description='Flag indicating if the request came from a high-activity visitor.', + ) raw_device_attributes: Optional[RawDeviceAttributes] = None - __properties: ClassVar[List[str]] = ["event_id", "timestamp", "linked_id", "environment_id", "suspect", "sdk", "replayed", "identification", "supplementary_id_high_recall", "tags", "url", "bundle_id", "package_name", "ip_address", "user_agent", "client_referrer", "browser_details", "proximity", "bot", "bot_type", "bot_info", "cloned_app", "developer_tools", "emulator", "factory_reset_timestamp", "frida", "ip_blocklist", "ip_info", "proxy", "proxy_confidence", "proxy_details", "incognito", "jailbroken", "location_spoofing", "mitm_attack", "privacy_settings", "root_apps", "rule_action", "suspect_score", "tampering", "tampering_details", "velocity", "virtual_machine", "vpn", "vpn_confidence", "vpn_origin_timezone", "vpn_origin_country", "vpn_methods", "high_activity_device", "raw_device_attributes"] + __properties: ClassVar[list[str]] = [ + 'event_id', + 'timestamp', + 'linked_id', + 'environment_id', + 'suspect', + 'sdk', + 'replayed', + 'identification', + 'supplementary_id_high_recall', + 'tags', + 'url', + 'bundle_id', + 'package_name', + 'ip_address', + 'user_agent', + 'client_referrer', + 'browser_details', + 'proximity', + 'bot', + 'bot_type', + 'bot_info', + 'cloned_app', + 'developer_tools', + 'emulator', + 'factory_reset_timestamp', + 'frida', + 'ip_blocklist', + 'ip_info', + 'proxy', + 'proxy_confidence', + 'proxy_details', + 'incognito', + 'jailbroken', + 'location_spoofing', + 'mitm_attack', + 'privacy_settings', + 'root_apps', + 'rule_action', + 'suspect_score', + 'tampering', + 'tampering_details', + 'velocity', + 'virtual_machine', + 'vpn', + 'vpn_confidence', + 'vpn_origin_timezone', + 'vpn_origin_country', + 'vpn_methods', + 'high_activity_device', + 'raw_device_attributes', + ] model_config = ConfigDict( populate_by_name=True, @@ -102,7 +246,6 @@ class Event(BaseModel): 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)) @@ -117,7 +260,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Event from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -127,8 +270,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -180,7 +322,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Event from a dict""" if obj is None: return None @@ -188,58 +330,88 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "event_id": obj.get("event_id"), - "timestamp": obj.get("timestamp"), - "linked_id": obj.get("linked_id"), - "environment_id": obj.get("environment_id"), - "suspect": obj.get("suspect"), - "sdk": SDK.from_dict(obj["sdk"]) if obj.get("sdk") is not None else None, - "replayed": obj.get("replayed"), - "identification": Identification.from_dict(obj["identification"]) if obj.get("identification") is not None else None, - "supplementary_id_high_recall": SupplementaryIDHighRecall.from_dict(obj["supplementary_id_high_recall"]) if obj.get("supplementary_id_high_recall") is not None else None, - "tags": obj.get("tags"), - "url": obj.get("url"), - "bundle_id": obj.get("bundle_id"), - "package_name": obj.get("package_name"), - "ip_address": obj.get("ip_address"), - "user_agent": obj.get("user_agent"), - "client_referrer": obj.get("client_referrer"), - "browser_details": BrowserDetails.from_dict(obj["browser_details"]) if obj.get("browser_details") is not None else None, - "proximity": Proximity.from_dict(obj["proximity"]) if obj.get("proximity") is not None else None, - "bot": obj.get("bot"), - "bot_type": obj.get("bot_type"), - "bot_info": BotInfo.from_dict(obj["bot_info"]) if obj.get("bot_info") is not None else None, - "cloned_app": obj.get("cloned_app"), - "developer_tools": obj.get("developer_tools"), - "emulator": obj.get("emulator"), - "factory_reset_timestamp": obj.get("factory_reset_timestamp"), - "frida": obj.get("frida"), - "ip_blocklist": IPBlockList.from_dict(obj["ip_blocklist"]) if obj.get("ip_blocklist") is not None else None, - "ip_info": IPInfo.from_dict(obj["ip_info"]) if obj.get("ip_info") is not None else None, - "proxy": obj.get("proxy"), - "proxy_confidence": obj.get("proxy_confidence"), - "proxy_details": ProxyDetails.from_dict(obj["proxy_details"]) if obj.get("proxy_details") is not None else None, - "incognito": obj.get("incognito"), - "jailbroken": obj.get("jailbroken"), - "location_spoofing": obj.get("location_spoofing"), - "mitm_attack": obj.get("mitm_attack"), - "privacy_settings": obj.get("privacy_settings"), - "root_apps": obj.get("root_apps"), - "rule_action": EventRuleAction.from_dict(obj["rule_action"]) if obj.get("rule_action") is not None else None, - "suspect_score": obj.get("suspect_score"), - "tampering": obj.get("tampering"), - "tampering_details": TamperingDetails.from_dict(obj["tampering_details"]) if obj.get("tampering_details") is not None else None, - "velocity": Velocity.from_dict(obj["velocity"]) if obj.get("velocity") is not None else None, - "virtual_machine": obj.get("virtual_machine"), - "vpn": obj.get("vpn"), - "vpn_confidence": obj.get("vpn_confidence"), - "vpn_origin_timezone": obj.get("vpn_origin_timezone"), - "vpn_origin_country": obj.get("vpn_origin_country"), - "vpn_methods": VpnMethods.from_dict(obj["vpn_methods"]) if obj.get("vpn_methods") is not None else None, - "high_activity_device": obj.get("high_activity_device"), - "raw_device_attributes": RawDeviceAttributes.from_dict(obj["raw_device_attributes"]) if obj.get("raw_device_attributes") is not None else None - }) + _obj = cls.model_validate( + { + 'event_id': obj.get('event_id'), + 'timestamp': obj.get('timestamp'), + 'linked_id': obj.get('linked_id'), + 'environment_id': obj.get('environment_id'), + 'suspect': obj.get('suspect'), + 'sdk': SDK.from_dict(obj['sdk']) if obj.get('sdk') is not None else None, + 'replayed': obj.get('replayed'), + 'identification': Identification.from_dict(obj['identification']) + if obj.get('identification') is not None + else None, + 'supplementary_id_high_recall': SupplementaryIDHighRecall.from_dict( + obj['supplementary_id_high_recall'] + ) + if obj.get('supplementary_id_high_recall') is not None + else None, + 'tags': obj.get('tags'), + 'url': obj.get('url'), + 'bundle_id': obj.get('bundle_id'), + 'package_name': obj.get('package_name'), + 'ip_address': obj.get('ip_address'), + 'user_agent': obj.get('user_agent'), + 'client_referrer': obj.get('client_referrer'), + 'browser_details': BrowserDetails.from_dict(obj['browser_details']) + if obj.get('browser_details') is not None + else None, + 'proximity': Proximity.from_dict(obj['proximity']) + if obj.get('proximity') is not None + else None, + 'bot': obj.get('bot'), + 'bot_type': obj.get('bot_type'), + 'bot_info': BotInfo.from_dict(obj['bot_info']) + if obj.get('bot_info') is not None + else None, + 'cloned_app': obj.get('cloned_app'), + 'developer_tools': obj.get('developer_tools'), + 'emulator': obj.get('emulator'), + 'factory_reset_timestamp': obj.get('factory_reset_timestamp'), + 'frida': obj.get('frida'), + 'ip_blocklist': IPBlockList.from_dict(obj['ip_blocklist']) + if obj.get('ip_blocklist') is not None + else None, + 'ip_info': IPInfo.from_dict(obj['ip_info']) + if obj.get('ip_info') is not None + else None, + 'proxy': obj.get('proxy'), + 'proxy_confidence': obj.get('proxy_confidence'), + 'proxy_details': ProxyDetails.from_dict(obj['proxy_details']) + if obj.get('proxy_details') is not None + else None, + 'incognito': obj.get('incognito'), + 'jailbroken': obj.get('jailbroken'), + 'location_spoofing': obj.get('location_spoofing'), + 'mitm_attack': obj.get('mitm_attack'), + 'privacy_settings': obj.get('privacy_settings'), + 'root_apps': obj.get('root_apps'), + 'rule_action': EventRuleAction.from_dict(obj['rule_action']) + if obj.get('rule_action') is not None + else None, + 'suspect_score': obj.get('suspect_score'), + 'tampering': obj.get('tampering'), + 'tampering_details': TamperingDetails.from_dict(obj['tampering_details']) + if obj.get('tampering_details') is not None + else None, + 'velocity': Velocity.from_dict(obj['velocity']) + if obj.get('velocity') is not None + else None, + 'virtual_machine': obj.get('virtual_machine'), + 'vpn': obj.get('vpn'), + 'vpn_confidence': obj.get('vpn_confidence'), + 'vpn_origin_timezone': obj.get('vpn_origin_timezone'), + 'vpn_origin_country': obj.get('vpn_origin_country'), + 'vpn_methods': VpnMethods.from_dict(obj['vpn_methods']) + if obj.get('vpn_methods') is not None + else None, + 'high_activity_device': obj.get('high_activity_device'), + 'raw_device_attributes': RawDeviceAttributes.from_dict( + obj['raw_device_attributes'] + ) + if obj.get('raw_device_attributes') is not None + else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/event_rule_action.py b/fingerprint_server_sdk/models/event_rule_action.py index ac342114..f0a7bf35 100644 --- a/fingerprint_server_sdk/models/event_rule_action.py +++ b/fingerprint_server_sdk/models/event_rule_action.py @@ -1,87 +1,95 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + import json import pprint -from pydantic import BaseModel, ConfigDict, Field, StrictStr, ValidationError, field_validator -from typing import Any, List, Optional +from typing import Any, Optional, Union + +from pydantic import BaseModel, ConfigDict, ValidationError, field_validator +from typing_extensions import Self + from fingerprint_server_sdk.models.event_rule_action_allow import EventRuleActionAllow from fingerprint_server_sdk.models.event_rule_action_block import EventRuleActionBlock -from pydantic import StrictStr, Field -from typing import Union, List, Set, Optional, Dict -from typing_extensions import Literal, Self -EVENTRULEACTION_ONE_OF_SCHEMAS = ["EventRuleActionAllow", "EventRuleActionBlock"] +EVENTRULEACTION_ONE_OF_SCHEMAS = ['EventRuleActionAllow', 'EventRuleActionBlock'] + class EventRuleAction(BaseModel): """ Describes the action the client should take, according to the rule in the ruleset that matched the event. When getting an event by event ID, the rule_action will only be included when the ruleset_id query parameter is specified. """ + # data type: EventRuleActionAllow oneof_schema_1_validator: Optional[EventRuleActionAllow] = None # data type: EventRuleActionBlock oneof_schema_2_validator: Optional[EventRuleActionBlock] = None actual_instance: Optional[Union[EventRuleActionAllow, EventRuleActionBlock]] = None - one_of_schemas: Set[str] = { "EventRuleActionAllow", "EventRuleActionBlock" } + one_of_schemas: set[str] = {'EventRuleActionAllow', 'EventRuleActionBlock'} model_config = ConfigDict( validate_assignment=True, protected_namespaces=(), ) + discriminator_value_class_map: dict[str, str] = {} - discriminator_value_class_map: Dict[str, str] = { - } - - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: if args: if len(args) > 1: - raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + raise ValueError( + 'If a position argument is used, only 1 is allowed to set `actual_instance`' + ) if kwargs: - raise ValueError("If a position argument is used, keyword arguments cannot be used.") + raise ValueError( + 'If a position argument is used, keyword arguments cannot be used.' + ) super().__init__(actual_instance=args[0]) else: super().__init__(**kwargs) @field_validator('actual_instance') - def actual_instance_must_validate_oneof(cls, v): - instance = EventRuleAction.model_construct() + def actual_instance_must_validate_oneof(cls, v: Any) -> Any: + EventRuleAction.model_construct() error_messages = [] match = 0 # validate data type: EventRuleActionAllow if not isinstance(v, EventRuleActionAllow): - error_messages.append(f"Error! Input type `{type(v)}` is not `EventRuleActionAllow`") + error_messages.append(f'Error! Input type `{type(v)}` is not `EventRuleActionAllow`') else: match += 1 # validate data type: EventRuleActionBlock if not isinstance(v, EventRuleActionBlock): - error_messages.append(f"Error! Input type `{type(v)}` is not `EventRuleActionBlock`") + error_messages.append(f'Error! Input type `{type(v)}` is not `EventRuleActionBlock`') else: match += 1 if match > 1: # more than 1 match - raise ValueError("Multiple matches found when setting `actual_instance` in EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: " + ", ".join(error_messages)) + raise ValueError( + 'Multiple matches found when setting `actual_instance` in EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: ' + + ', '.join(error_messages) + ) elif match == 0: # no match - raise ValueError("No match found when setting `actual_instance` in EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: " + ", ".join(error_messages)) + raise ValueError( + 'No match found when setting `actual_instance` in EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: ' + + ', '.join(error_messages) + ) else: return v @classmethod - def from_dict(cls, obj: Union[str, Dict[str, Any]]) -> Self: + def from_dict(cls, obj: Union[str, dict[str, Any]]) -> Self: return cls.from_json(json.dumps(obj)) @classmethod @@ -106,29 +114,37 @@ def from_json(cls, json_str: str) -> Self: if match > 1: # more than 1 match - raise ValueError("Multiple matches found when deserializing the JSON string into EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: " + ", ".join(error_messages)) + raise ValueError( + 'Multiple matches found when deserializing the JSON string into EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: ' + + ', '.join(error_messages) + ) elif match == 0: # no match - raise ValueError("No match found when deserializing the JSON string into EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: " + ", ".join(error_messages)) + raise ValueError( + 'No match found when deserializing the JSON string into EventRuleAction with oneOf schemas: EventRuleActionAllow, EventRuleActionBlock. Details: ' + + ', '.join(error_messages) + ) else: return instance def to_json(self) -> str: """Returns the JSON representation of the actual instance""" if self.actual_instance is None: - return "null" + return 'null' - if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + if hasattr(self.actual_instance, 'to_json') and callable(self.actual_instance.to_json): return self.actual_instance.to_json() else: return json.dumps(self.actual_instance) - def to_dict(self) -> Optional[Union[Dict[str, Any], EventRuleActionAllow, EventRuleActionBlock]]: + def to_dict( + self, + ) -> Optional[Union[dict[str, Any], EventRuleActionAllow, EventRuleActionBlock]]: """Returns the dict representation of the actual instance""" if self.actual_instance is None: return None - if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + if hasattr(self.actual_instance, 'to_dict') and callable(self.actual_instance.to_dict): return self.actual_instance.to_dict() else: # primitive type @@ -137,5 +153,3 @@ def to_dict(self) -> Optional[Union[Dict[str, Any], EventRuleActionAllow, EventR def to_str(self) -> str: """Returns the string representation of the actual instance""" return pprint.pformat(self.model_dump()) - - diff --git a/fingerprint_server_sdk/models/event_rule_action_allow.py b/fingerprint_server_sdk/models/event_rule_action_allow.py index 4888a5c2..6fed5e65 100644 --- a/fingerprint_server_sdk/models/event_rule_action_allow.py +++ b/fingerprint_server_sdk/models/event_rule_action_allow.py @@ -1,37 +1,37 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Self + from fingerprint_server_sdk.models.request_header_modifications import RequestHeaderModifications from fingerprint_server_sdk.models.rule_action_type import RuleActionType -from typing import Optional, Set -from typing_extensions import Self + class EventRuleActionAllow(BaseModel): """ Informs the client that the request should be forwarded to the origin with optional request header modifications. - """ # noqa: E501 + """ + type: RuleActionType request_header_modifications: Optional[RequestHeaderModifications] = None - __properties: ClassVar[List[str]] = ["type", "request_header_modifications"] + __properties: ClassVar[list[str]] = ['type', 'request_header_modifications'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +39,6 @@ class EventRuleActionAllow(BaseModel): 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)) @@ -54,7 +53,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of EventRuleActionAllow from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -64,8 +63,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -78,7 +76,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of EventRuleActionAllow from a dict""" if obj is None: return None @@ -86,10 +84,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "type": obj.get("type"), - "request_header_modifications": RequestHeaderModifications.from_dict(obj["request_header_modifications"]) if obj.get("request_header_modifications") is not None else None - }) + _obj = cls.model_validate( + { + 'type': obj.get('type'), + 'request_header_modifications': RequestHeaderModifications.from_dict( + obj['request_header_modifications'] + ) + if obj.get('request_header_modifications') is not None + else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/event_rule_action_block.py b/fingerprint_server_sdk/models/event_rule_action_block.py index 8b782e78..1b69fe80 100644 --- a/fingerprint_server_sdk/models/event_rule_action_block.py +++ b/fingerprint_server_sdk/models/event_rule_action_block.py @@ -1,39 +1,43 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Self + from fingerprint_server_sdk.models.rule_action_header_field import RuleActionHeaderField from fingerprint_server_sdk.models.rule_action_type import RuleActionType -from typing import Optional, Set -from typing_extensions import Self + class EventRuleActionBlock(BaseModel): """ Informs the client the request should be blocked using the response described by this rule action. - """ # noqa: E501 + """ + type: RuleActionType - status_code: Optional[StrictInt] = Field(default=None, description="A valid HTTP status code.") - headers: Optional[List[RuleActionHeaderField]] = Field(default=None, description="A list of headers to send.") - body: Optional[StrictStr] = Field(default=None, description="The response body to send to the client.") - __properties: ClassVar[List[str]] = ["type", "status_code", "headers", "body"] + status_code: Optional[StrictInt] = Field(default=None, description='A valid HTTP status code.') + headers: Optional[list[RuleActionHeaderField]] = Field( + default=None, description='A list of headers to send.' + ) + body: Optional[StrictStr] = Field( + default=None, description='The response body to send to the client.' + ) + __properties: ClassVar[list[str]] = ['type', 'status_code', 'headers', 'body'] model_config = ConfigDict( populate_by_name=True, @@ -41,7 +45,6 @@ class EventRuleActionBlock(BaseModel): 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)) @@ -56,7 +59,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of EventRuleActionBlock from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,8 +69,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -84,7 +86,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of EventRuleActionBlock from a dict""" if obj is None: return None @@ -92,12 +94,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "type": obj.get("type"), - "status_code": obj.get("status_code"), - "headers": [RuleActionHeaderField.from_dict(_item) for _item in obj["headers"]] if obj.get("headers") is not None else None, - "body": obj.get("body") - }) + _obj = cls.model_validate( + { + 'type': obj.get('type'), + 'status_code': obj.get('status_code'), + 'headers': [RuleActionHeaderField.from_dict(_item) for _item in obj['headers']] + if obj.get('headers') is not None + else None, + 'body': obj.get('body'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/event_search.py b/fingerprint_server_sdk/models/event_search.py index eb581f76..85672e00 100644 --- a/fingerprint_server_sdk/models/event_search.py +++ b/fingerprint_server_sdk/models/event_search.py @@ -1,37 +1,43 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.event import Event -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.event import Event + + class EventSearch(BaseModel): """ Contains a list of all identification events matching the specified search criteria. - """ # noqa: E501 - events: List[Event] - pagination_key: Optional[StrictStr] = Field(default=None, description="Use this value in the `pagination_key` parameter to request the next page of search results.") - total_hits: Optional[StrictInt] = Field(default=None, description="This value represents the total number of events matching the search query, up to the limit provided in the `total_hits` query parameter. Only present if the `total_hits` query parameter was provided.") - __properties: ClassVar[List[str]] = ["events", "pagination_key", "total_hits"] + """ + + events: list[Event] + pagination_key: Optional[StrictStr] = Field( + default=None, + description='Use this value in the `pagination_key` parameter to request the next page of search results.', + ) + total_hits: Optional[StrictInt] = Field( + default=None, + description='This value represents the total number of events matching the search query, up to the limit provided in the `total_hits` query parameter. Only present if the `total_hits` query parameter was provided.', + ) + __properties: ClassVar[list[str]] = ['events', 'pagination_key', 'total_hits'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +45,6 @@ class EventSearch(BaseModel): 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)) @@ -54,7 +59,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of EventSearch from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -64,8 +69,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -82,7 +86,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of EventSearch from a dict""" if obj is None: return None @@ -90,11 +94,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "events": [Event.from_dict(_item) for _item in obj["events"]] if obj.get("events") is not None else None, - "pagination_key": obj.get("pagination_key"), - "total_hits": obj.get("total_hits") - }) + _obj = cls.model_validate( + { + 'events': [Event.from_dict(_item) for _item in obj['events']] + if obj.get('events') is not None + else None, + 'pagination_key': obj.get('pagination_key'), + 'total_hits': obj.get('total_hits'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/event_update.py b/fingerprint_server_sdk/models/event_update.py index 114c91c6..59ef0eb0 100644 --- a/fingerprint_server_sdk/models/event_update.py +++ b/fingerprint_server_sdk/models/event_update.py @@ -1,36 +1,42 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class EventUpdate(BaseModel): """ EventUpdate - """ # noqa: E501 - linked_id: Optional[StrictStr] = Field(default=None, description="Linked Id value to assign to the existing event") - tags: Optional[Dict[str, Any]] = Field(default=None, description="A customer-provided value or an object that was sent with the identification request or updated later.") - suspect: Optional[StrictBool] = Field(default=None, description="Suspect flag indicating observed suspicious or fraudulent event") - __properties: ClassVar[List[str]] = ["linked_id", "tags", "suspect"] + """ + + linked_id: Optional[StrictStr] = Field( + default=None, description='Linked Id value to assign to the existing event' + ) + tags: Optional[dict[str, Any]] = Field( + default=None, + description='A customer-provided value or an object that was sent with the identification request or updated later.', + ) + suspect: Optional[StrictBool] = Field( + default=None, description='Suspect flag indicating observed suspicious or fraudulent event' + ) + __properties: ClassVar[list[str]] = ['linked_id', 'tags', 'suspect'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +44,6 @@ class EventUpdate(BaseModel): 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)) @@ -53,7 +58,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of EventUpdate from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +68,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +78,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of EventUpdate from a dict""" if obj is None: return None @@ -82,11 +86,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "linked_id": obj.get("linked_id"), - "tags": obj.get("tags"), - "suspect": obj.get("suspect") - }) + _obj = cls.model_validate( + { + 'linked_id': obj.get('linked_id'), + 'tags': obj.get('tags'), + 'suspect': obj.get('suspect'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/font_preferences.py b/fingerprint_server_sdk/models/font_preferences.py index 1e62a556..234b93d8 100644 --- a/fingerprint_server_sdk/models/font_preferences.py +++ b/fingerprint_server_sdk/models/font_preferences.py @@ -1,32 +1,31 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt -from typing import Any, ClassVar, Dict, List, Optional, Union -from typing import Optional, Set from typing_extensions import Self + class FontPreferences(BaseModel): """ - Baseline measurement of canonical fonts rendered on the device. Numeric width metrics, in CSS pixels, for the canonical fonts collected by the agent. - """ # noqa: E501 + Baseline measurement of canonical fonts rendered on the device. Numeric width metrics, in CSS pixels, for the canonical fonts collected by the agent. + """ + default: Optional[Union[StrictFloat, StrictInt]] = None serif: Optional[Union[StrictFloat, StrictInt]] = None sans: Optional[Union[StrictFloat, StrictInt]] = None @@ -34,7 +33,15 @@ class FontPreferences(BaseModel): apple: Optional[Union[StrictFloat, StrictInt]] = None min: Optional[Union[StrictFloat, StrictInt]] = None system: Optional[Union[StrictFloat, StrictInt]] = None - __properties: ClassVar[List[str]] = ["default", "serif", "sans", "mono", "apple", "min", "system"] + __properties: ClassVar[list[str]] = [ + 'default', + 'serif', + 'sans', + 'mono', + 'apple', + 'min', + 'system', + ] model_config = ConfigDict( populate_by_name=True, @@ -42,7 +49,6 @@ class FontPreferences(BaseModel): 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)) @@ -57,7 +63,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of FontPreferences from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -67,8 +73,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -78,7 +83,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of FontPreferences from a dict""" if obj is None: return None @@ -86,15 +91,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "default": obj.get("default"), - "serif": obj.get("serif"), - "sans": obj.get("sans"), - "mono": obj.get("mono"), - "apple": obj.get("apple"), - "min": obj.get("min"), - "system": obj.get("system") - }) + _obj = cls.model_validate( + { + 'default': obj.get('default'), + 'serif': obj.get('serif'), + 'sans': obj.get('sans'), + 'mono': obj.get('mono'), + 'apple': obj.get('apple'), + 'min': obj.get('min'), + 'system': obj.get('system'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/geolocation.py b/fingerprint_server_sdk/models/geolocation.py index d92eedaa..0270e9c2 100644 --- a/fingerprint_server_sdk/models/geolocation.py +++ b/fingerprint_server_sdk/models/geolocation.py @@ -1,37 +1,51 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Annotated, Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional, Union -from typing_extensions import Annotated -from fingerprint_server_sdk.models.geolocation_subdivisions_inner import GeolocationSubdivisionsInner -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.geolocation_subdivisions_inner import ( + GeolocationSubdivisionsInner, +) + + class Geolocation(BaseModel): """ Geolocation - """ # noqa: E501 - accuracy_radius: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=None, description="The IP address is likely to be within this radius (in km) of the specified location.") - latitude: Optional[Union[Annotated[float, Field(le=90, strict=True, ge=-90)], Annotated[int, Field(le=90, strict=True, ge=-90)]]] = None - longitude: Optional[Union[Annotated[float, Field(le=180, strict=True, ge=-180)], Annotated[int, Field(le=180, strict=True, ge=-180)]]] = None + """ + + accuracy_radius: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field( + default=None, + description='The IP address is likely to be within this radius (in km) of the specified location.', + ) + latitude: Optional[ + Union[ + Annotated[float, Field(le=90, strict=True, ge=-90)], + Annotated[int, Field(le=90, strict=True, ge=-90)], + ] + ] = None + longitude: Optional[ + Union[ + Annotated[float, Field(le=180, strict=True, ge=-180)], + Annotated[int, Field(le=180, strict=True, ge=-180)], + ] + ] = None postal_code: Optional[StrictStr] = None timezone: Optional[StrictStr] = None city_name: Optional[StrictStr] = None @@ -39,9 +53,21 @@ class Geolocation(BaseModel): country_name: Optional[StrictStr] = None continent_code: Optional[Annotated[str, Field(min_length=2, strict=True, max_length=2)]] = None continent_name: Optional[StrictStr] = None - subdivisions: Optional[List[GeolocationSubdivisionsInner]] = None - additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["accuracy_radius", "latitude", "longitude", "postal_code", "timezone", "city_name", "country_code", "country_name", "continent_code", "continent_name", "subdivisions"] + subdivisions: Optional[list[GeolocationSubdivisionsInner]] = None + additional_properties: dict[str, Any] = {} + __properties: ClassVar[list[str]] = [ + 'accuracy_radius', + 'latitude', + 'longitude', + 'postal_code', + 'timezone', + 'city_name', + 'country_code', + 'country_name', + 'continent_code', + 'continent_name', + 'subdivisions', + ] model_config = ConfigDict( populate_by_name=True, @@ -49,7 +75,6 @@ class Geolocation(BaseModel): 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)) @@ -64,7 +89,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Geolocation from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -75,9 +100,11 @@ def to_dict(self) -> Dict[str, Any]: are ignored. * Fields in `self.additional_properties` are added to the output dict. """ - excluded_fields: Set[str] = set([ - "additional_properties", - ]) + excluded_fields: set[str] = set( + [ + 'additional_properties', + ] + ) _dict = self.model_dump( by_alias=True, @@ -99,7 +126,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Geolocation from a dict""" if obj is None: return None @@ -107,24 +134,28 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "accuracy_radius": obj.get("accuracy_radius"), - "latitude": obj.get("latitude"), - "longitude": obj.get("longitude"), - "postal_code": obj.get("postal_code"), - "timezone": obj.get("timezone"), - "city_name": obj.get("city_name"), - "country_code": obj.get("country_code"), - "country_name": obj.get("country_name"), - "continent_code": obj.get("continent_code"), - "continent_name": obj.get("continent_name"), - "subdivisions": [GeolocationSubdivisionsInner.from_dict(_item) for _item in obj["subdivisions"]] if obj.get("subdivisions") is not None else None - }) + _obj = cls.model_validate( + { + 'accuracy_radius': obj.get('accuracy_radius'), + 'latitude': obj.get('latitude'), + 'longitude': obj.get('longitude'), + 'postal_code': obj.get('postal_code'), + 'timezone': obj.get('timezone'), + 'city_name': obj.get('city_name'), + 'country_code': obj.get('country_code'), + 'country_name': obj.get('country_name'), + 'continent_code': obj.get('continent_code'), + 'continent_name': obj.get('continent_name'), + 'subdivisions': [ + GeolocationSubdivisionsInner.from_dict(_item) for _item in obj['subdivisions'] + ] + if obj.get('subdivisions') is not None + else None, + } + ) # store additional fields in additional_properties - for _key in obj.keys(): + for _key in obj: if _key not in cls.__properties: _obj.additional_properties[_key] = obj.get(_key) return _obj - - diff --git a/fingerprint_server_sdk/models/geolocation_subdivisions_inner.py b/fingerprint_server_sdk/models/geolocation_subdivisions_inner.py index 073d855c..8102658a 100644 --- a/fingerprint_server_sdk/models/geolocation_subdivisions_inner.py +++ b/fingerprint_server_sdk/models/geolocation_subdivisions_inner.py @@ -1,35 +1,34 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List -from typing import Optional, Set from typing_extensions import Self + class GeolocationSubdivisionsInner(BaseModel): """ GeolocationSubdivisionsInner - """ # noqa: E501 + """ + iso_code: StrictStr name: StrictStr - __properties: ClassVar[List[str]] = ["iso_code", "name"] + __properties: ClassVar[list[str]] = ['iso_code', 'name'] model_config = ConfigDict( populate_by_name=True, @@ -37,7 +36,6 @@ class GeolocationSubdivisionsInner(BaseModel): 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)) @@ -52,7 +50,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of GeolocationSubdivisionsInner from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -62,8 +60,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -73,7 +70,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of GeolocationSubdivisionsInner from a dict""" if obj is None: return None @@ -81,10 +78,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "iso_code": obj.get("iso_code"), - "name": obj.get("name") - }) + _obj = cls.model_validate({'iso_code': obj.get('iso_code'), 'name': obj.get('name')}) return _obj - - diff --git a/fingerprint_server_sdk/models/identification.py b/fingerprint_server_sdk/models/identification.py index 3bfc3e0b..99493488 100644 --- a/fingerprint_server_sdk/models/identification.py +++ b/fingerprint_server_sdk/models/identification.py @@ -1,39 +1,55 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.identification_confidence import IdentificationConfidence -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.identification_confidence import IdentificationConfidence + + class Identification(BaseModel): """ Identification - """ # noqa: E501 - visitor_id: StrictStr = Field(description="String of 20 characters that uniquely identifies the visitor's browser or mobile device.") + """ + + visitor_id: StrictStr = Field( + description="String of 20 characters that uniquely identifies the visitor's browser or mobile device." + ) confidence: Optional[IdentificationConfidence] = None - visitor_found: StrictBool = Field(description="Attribute represents if a visitor had been identified before.") - first_seen_at: Optional[StrictInt] = Field(default=None, description="Unix epoch time milliseconds timestamp indicating the time at which this visitor ID was first seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ") - last_seen_at: Optional[StrictInt] = Field(default=None, description="Unix epoch time milliseconds timestamp indicating the time at which this visitor ID was last seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ") - __properties: ClassVar[List[str]] = ["visitor_id", "confidence", "visitor_found", "first_seen_at", "last_seen_at"] + visitor_found: StrictBool = Field( + description='Attribute represents if a visitor had been identified before.' + ) + first_seen_at: Optional[StrictInt] = Field( + default=None, + description='Unix epoch time milliseconds timestamp indicating the time at which this visitor ID was first seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ', + ) + last_seen_at: Optional[StrictInt] = Field( + default=None, + description='Unix epoch time milliseconds timestamp indicating the time at which this visitor ID was last seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ', + ) + __properties: ClassVar[list[str]] = [ + 'visitor_id', + 'confidence', + 'visitor_found', + 'first_seen_at', + 'last_seen_at', + ] model_config = ConfigDict( populate_by_name=True, @@ -41,7 +57,6 @@ class Identification(BaseModel): 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)) @@ -56,7 +71,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Identification from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,8 +81,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -80,7 +94,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Identification from a dict""" if obj is None: return None @@ -88,13 +102,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "visitor_id": obj.get("visitor_id"), - "confidence": IdentificationConfidence.from_dict(obj["confidence"]) if obj.get("confidence") is not None else None, - "visitor_found": obj.get("visitor_found"), - "first_seen_at": obj.get("first_seen_at"), - "last_seen_at": obj.get("last_seen_at") - }) + _obj = cls.model_validate( + { + 'visitor_id': obj.get('visitor_id'), + 'confidence': IdentificationConfidence.from_dict(obj['confidence']) + if obj.get('confidence') is not None + else None, + 'visitor_found': obj.get('visitor_found'), + 'first_seen_at': obj.get('first_seen_at'), + 'last_seen_at': obj.get('last_seen_at'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/identification_confidence.py b/fingerprint_server_sdk/models/identification_confidence.py index 41c777f2..72a53543 100644 --- a/fingerprint_server_sdk/models/identification_confidence.py +++ b/fingerprint_server_sdk/models/identification_confidence.py @@ -1,37 +1,43 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Annotated, Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional, Union -from typing_extensions import Annotated -from typing import Optional, Set from typing_extensions import Self + class IdentificationConfidence(BaseModel): """ IdentificationConfidence - """ # noqa: E501 - score: Union[Annotated[float, Field(le=1, strict=True, ge=0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="The confidence score is a floating-point number between 0 and 1 that represents the probability of accurate identification.") - version: Optional[StrictStr] = Field(default=None, description="The version name of the method used to calculate the Confidence score. This field is only present for customers who opted in to an alternative calculation method.") + """ + + score: Union[ + Annotated[float, Field(le=1, strict=True, ge=0)], + Annotated[int, Field(le=1, strict=True, ge=0)], + ] = Field( + description='The confidence score is a floating-point number between 0 and 1 that represents the probability of accurate identification.' + ) + version: Optional[StrictStr] = Field( + default=None, + description='The version name of the method used to calculate the Confidence score. This field is only present for customers who opted in to an alternative calculation method.', + ) comment: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["score", "version", "comment"] + __properties: ClassVar[list[str]] = ['score', 'version', 'comment'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +45,6 @@ class IdentificationConfidence(BaseModel): 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)) @@ -54,7 +59,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of IdentificationConfidence from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -64,8 +69,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -75,7 +79,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of IdentificationConfidence from a dict""" if obj is None: return None @@ -83,11 +87,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "score": obj.get("score"), - "version": obj.get("version"), - "comment": obj.get("comment") - }) + _obj = cls.model_validate( + { + 'score': obj.get('score'), + 'version': obj.get('version'), + 'comment': obj.get('comment'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/integration.py b/fingerprint_server_sdk/models/integration.py index b722c3ad..f9618dfe 100644 --- a/fingerprint_server_sdk/models/integration.py +++ b/fingerprint_server_sdk/models/integration.py @@ -1,38 +1,43 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.integration_subintegration import IntegrationSubintegration -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.integration_subintegration import IntegrationSubintegration + + class Integration(BaseModel): """ Integration - """ # noqa: E501 - name: Optional[StrictStr] = Field(default=None, description="The name of the specific integration, e.g. \"fingerprint-pro-react\".") - version: Optional[StrictStr] = Field(default=None, description="The version of the specific integration, e.g. \"3.11.10\".") + """ + + name: Optional[StrictStr] = Field( + default=None, + description='The name of the specific integration, e.g. "fingerprint-pro-react".', + ) + version: Optional[StrictStr] = Field( + default=None, description='The version of the specific integration, e.g. "3.11.10".' + ) subintegration: Optional[IntegrationSubintegration] = None - additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["name", "version", "subintegration"] + additional_properties: dict[str, Any] = {} + __properties: ClassVar[list[str]] = ['name', 'version', 'subintegration'] model_config = ConfigDict( populate_by_name=True, @@ -40,7 +45,6 @@ class Integration(BaseModel): 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)) @@ -55,7 +59,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Integration from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,9 +70,11 @@ def to_dict(self) -> Dict[str, Any]: are ignored. * Fields in `self.additional_properties` are added to the output dict. """ - excluded_fields: Set[str] = set([ - "additional_properties", - ]) + excluded_fields: set[str] = set( + [ + 'additional_properties', + ] + ) _dict = self.model_dump( by_alias=True, @@ -86,7 +92,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Integration from a dict""" if obj is None: return None @@ -94,16 +100,18 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "name": obj.get("name"), - "version": obj.get("version"), - "subintegration": IntegrationSubintegration.from_dict(obj["subintegration"]) if obj.get("subintegration") is not None else None - }) + _obj = cls.model_validate( + { + 'name': obj.get('name'), + 'version': obj.get('version'), + 'subintegration': IntegrationSubintegration.from_dict(obj['subintegration']) + if obj.get('subintegration') is not None + else None, + } + ) # store additional fields in additional_properties - for _key in obj.keys(): + for _key in obj: if _key not in cls.__properties: _obj.additional_properties[_key] = obj.get(_key) return _obj - - diff --git a/fingerprint_server_sdk/models/integration_subintegration.py b/fingerprint_server_sdk/models/integration_subintegration.py index 9f2e3905..e4b29299 100644 --- a/fingerprint_server_sdk/models/integration_subintegration.py +++ b/fingerprint_server_sdk/models/integration_subintegration.py @@ -1,35 +1,38 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class IntegrationSubintegration(BaseModel): """ IntegrationSubintegration - """ # noqa: E501 - name: Optional[StrictStr] = Field(default=None, description="The name of the specific subintegration, e.g. \"preact\".") - version: Optional[StrictStr] = Field(default=None, description="The version of the specific subintegration, e.g. \"10.21.0\".") - __properties: ClassVar[List[str]] = ["name", "version"] + """ + + name: Optional[StrictStr] = Field( + default=None, description='The name of the specific subintegration, e.g. "preact".' + ) + version: Optional[StrictStr] = Field( + default=None, description='The version of the specific subintegration, e.g. "10.21.0".' + ) + __properties: ClassVar[list[str]] = ['name', 'version'] model_config = ConfigDict( populate_by_name=True, @@ -37,7 +40,6 @@ class IntegrationSubintegration(BaseModel): 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)) @@ -52,7 +54,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of IntegrationSubintegration from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -62,8 +64,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -73,7 +74,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of IntegrationSubintegration from a dict""" if obj is None: return None @@ -81,10 +82,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "name": obj.get("name"), - "version": obj.get("version") - }) + _obj = cls.model_validate({'name': obj.get('name'), 'version': obj.get('version')}) return _obj - - diff --git a/fingerprint_server_sdk/models/ip_block_list.py b/fingerprint_server_sdk/models/ip_block_list.py index 87bb5d93..ba93ae82 100644 --- a/fingerprint_server_sdk/models/ip_block_list.py +++ b/fingerprint_server_sdk/models/ip_block_list.py @@ -1,36 +1,41 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class IPBlockList(BaseModel): """ IPBlockList - """ # noqa: E501 - email_spam: Optional[StrictBool] = Field(default=None, description="IP address was part of a known email spam attack (SMTP).") - attack_source: Optional[StrictBool] = Field(default=None, description="IP address was part of a known network attack (SSH/HTTPS).") - tor_node: Optional[StrictBool] = Field(default=None, description="IP address was part of known TOR network activity.") - __properties: ClassVar[List[str]] = ["email_spam", "attack_source", "tor_node"] + """ + + email_spam: Optional[StrictBool] = Field( + default=None, description='IP address was part of a known email spam attack (SMTP).' + ) + attack_source: Optional[StrictBool] = Field( + default=None, description='IP address was part of a known network attack (SSH/HTTPS).' + ) + tor_node: Optional[StrictBool] = Field( + default=None, description='IP address was part of known TOR network activity.' + ) + __properties: ClassVar[list[str]] = ['email_spam', 'attack_source', 'tor_node'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +43,6 @@ class IPBlockList(BaseModel): 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)) @@ -53,7 +57,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of IPBlockList from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +67,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +77,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of IPBlockList from a dict""" if obj is None: return None @@ -82,11 +85,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "email_spam": obj.get("email_spam"), - "attack_source": obj.get("attack_source"), - "tor_node": obj.get("tor_node") - }) + _obj = cls.model_validate( + { + 'email_spam': obj.get('email_spam'), + 'attack_source': obj.get('attack_source'), + 'tor_node': obj.get('tor_node'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/ip_info.py b/fingerprint_server_sdk/models/ip_info.py index 869eb44a..abb8dee2 100644 --- a/fingerprint_server_sdk/models/ip_info.py +++ b/fingerprint_server_sdk/models/ip_info.py @@ -1,37 +1,37 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Self + from fingerprint_server_sdk.models.ip_info_v4 import IPInfoV4 from fingerprint_server_sdk.models.ip_info_v6 import IPInfoV6 -from typing import Optional, Set -from typing_extensions import Self + class IPInfo(BaseModel): """ Details about the request IP address. Has separate fields for v4 and v6 IP address versions. - """ # noqa: E501 + """ + v4: Optional[IPInfoV4] = None v6: Optional[IPInfoV6] = None - __properties: ClassVar[List[str]] = ["v4", "v6"] + __properties: ClassVar[list[str]] = ['v4', 'v6'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +39,6 @@ class IPInfo(BaseModel): 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)) @@ -54,7 +53,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of IPInfo from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -64,8 +63,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -81,7 +79,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of IPInfo from a dict""" if obj is None: return None @@ -89,10 +87,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "v4": IPInfoV4.from_dict(obj["v4"]) if obj.get("v4") is not None else None, - "v6": IPInfoV6.from_dict(obj["v6"]) if obj.get("v6") is not None else None - }) + _obj = cls.model_validate( + { + 'v4': IPInfoV4.from_dict(obj['v4']) if obj.get('v4') is not None else None, + 'v6': IPInfoV6.from_dict(obj['v6']) if obj.get('v6') is not None else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/ip_info_v4.py b/fingerprint_server_sdk/models/ip_info_v4.py index 03fa0c78..edfd29d6 100644 --- a/fingerprint_server_sdk/models/ip_info_v4.py +++ b/fingerprint_server_sdk/models/ip_info_v4.py @@ -1,33 +1,33 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.geolocation import Geolocation -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.geolocation import Geolocation + + class IPInfoV4(BaseModel): """ IPInfoV4 - """ # noqa: E501 + """ + address: StrictStr geolocation: Optional[Geolocation] = None asn: Optional[StrictStr] = None @@ -36,7 +36,16 @@ class IPInfoV4(BaseModel): asn_type: Optional[StrictStr] = None datacenter_result: Optional[StrictBool] = None datacenter_name: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["address", "geolocation", "asn", "asn_name", "asn_network", "asn_type", "datacenter_result", "datacenter_name"] + __properties: ClassVar[list[str]] = [ + 'address', + 'geolocation', + 'asn', + 'asn_name', + 'asn_network', + 'asn_type', + 'datacenter_result', + 'datacenter_name', + ] model_config = ConfigDict( populate_by_name=True, @@ -44,7 +53,6 @@ class IPInfoV4(BaseModel): 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)) @@ -59,7 +67,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of IPInfoV4 from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -69,8 +77,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -83,7 +90,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of IPInfoV4 from a dict""" if obj is None: return None @@ -91,16 +98,18 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "address": obj.get("address"), - "geolocation": Geolocation.from_dict(obj["geolocation"]) if obj.get("geolocation") is not None else None, - "asn": obj.get("asn"), - "asn_name": obj.get("asn_name"), - "asn_network": obj.get("asn_network"), - "asn_type": obj.get("asn_type"), - "datacenter_result": obj.get("datacenter_result"), - "datacenter_name": obj.get("datacenter_name") - }) + _obj = cls.model_validate( + { + 'address': obj.get('address'), + 'geolocation': Geolocation.from_dict(obj['geolocation']) + if obj.get('geolocation') is not None + else None, + 'asn': obj.get('asn'), + 'asn_name': obj.get('asn_name'), + 'asn_network': obj.get('asn_network'), + 'asn_type': obj.get('asn_type'), + 'datacenter_result': obj.get('datacenter_result'), + 'datacenter_name': obj.get('datacenter_name'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/ip_info_v6.py b/fingerprint_server_sdk/models/ip_info_v6.py index cf9e8dcd..6e901771 100644 --- a/fingerprint_server_sdk/models/ip_info_v6.py +++ b/fingerprint_server_sdk/models/ip_info_v6.py @@ -1,33 +1,33 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictBool, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.geolocation import Geolocation -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.geolocation import Geolocation + + class IPInfoV6(BaseModel): """ IPInfoV6 - """ # noqa: E501 + """ + address: StrictStr geolocation: Optional[Geolocation] = None asn: Optional[StrictStr] = None @@ -36,7 +36,16 @@ class IPInfoV6(BaseModel): asn_type: Optional[StrictStr] = None datacenter_result: Optional[StrictBool] = None datacenter_name: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["address", "geolocation", "asn", "asn_name", "asn_network", "asn_type", "datacenter_result", "datacenter_name"] + __properties: ClassVar[list[str]] = [ + 'address', + 'geolocation', + 'asn', + 'asn_name', + 'asn_network', + 'asn_type', + 'datacenter_result', + 'datacenter_name', + ] model_config = ConfigDict( populate_by_name=True, @@ -44,7 +53,6 @@ class IPInfoV6(BaseModel): 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)) @@ -59,7 +67,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of IPInfoV6 from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -69,8 +77,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -83,7 +90,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of IPInfoV6 from a dict""" if obj is None: return None @@ -91,16 +98,18 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "address": obj.get("address"), - "geolocation": Geolocation.from_dict(obj["geolocation"]) if obj.get("geolocation") is not None else None, - "asn": obj.get("asn"), - "asn_name": obj.get("asn_name"), - "asn_network": obj.get("asn_network"), - "asn_type": obj.get("asn_type"), - "datacenter_result": obj.get("datacenter_result"), - "datacenter_name": obj.get("datacenter_name") - }) + _obj = cls.model_validate( + { + 'address': obj.get('address'), + 'geolocation': Geolocation.from_dict(obj['geolocation']) + if obj.get('geolocation') is not None + else None, + 'asn': obj.get('asn'), + 'asn_name': obj.get('asn_name'), + 'asn_network': obj.get('asn_network'), + 'asn_type': obj.get('asn_type'), + 'datacenter_result': obj.get('datacenter_result'), + 'datacenter_name': obj.get('datacenter_name'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/plugins_inner.py b/fingerprint_server_sdk/models/plugins_inner.py index a9b57934..8b9d6cb8 100644 --- a/fingerprint_server_sdk/models/plugins_inner.py +++ b/fingerprint_server_sdk/models/plugins_inner.py @@ -1,37 +1,37 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.plugins_inner_mime_types_inner import PluginsInnerMimeTypesInner -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.plugins_inner_mime_types_inner import PluginsInnerMimeTypesInner + + class PluginsInner(BaseModel): """ PluginsInner - """ # noqa: E501 + """ + name: StrictStr description: Optional[StrictStr] = None - mime_types: Optional[List[PluginsInnerMimeTypesInner]] = Field(default=None, alias="mimeTypes") - __properties: ClassVar[List[str]] = ["name", "description", "mimeTypes"] + mime_types: Optional[list[PluginsInnerMimeTypesInner]] = Field(default=None, alias='mimeTypes') + __properties: ClassVar[list[str]] = ['name', 'description', 'mimeTypes'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +39,6 @@ class PluginsInner(BaseModel): 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)) @@ -54,7 +53,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of PluginsInner from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -64,8 +63,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -82,7 +80,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of PluginsInner from a dict""" if obj is None: return None @@ -90,11 +88,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "name": obj.get("name"), - "description": obj.get("description"), - "mimeTypes": [PluginsInnerMimeTypesInner.from_dict(_item) for _item in obj["mimeTypes"]] if obj.get("mimeTypes") is not None else None - }) + _obj = cls.model_validate( + { + 'name': obj.get('name'), + 'description': obj.get('description'), + 'mimeTypes': [ + PluginsInnerMimeTypesInner.from_dict(_item) for _item in obj['mimeTypes'] + ] + if obj.get('mimeTypes') is not None + else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/plugins_inner_mime_types_inner.py b/fingerprint_server_sdk/models/plugins_inner_mime_types_inner.py index cd788bae..17d873fe 100644 --- a/fingerprint_server_sdk/models/plugins_inner_mime_types_inner.py +++ b/fingerprint_server_sdk/models/plugins_inner_mime_types_inner.py @@ -1,36 +1,35 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class PluginsInnerMimeTypesInner(BaseModel): """ PluginsInnerMimeTypesInner - """ # noqa: E501 + """ + type: Optional[StrictStr] = None suffixes: Optional[StrictStr] = None description: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["type", "suffixes", "description"] + __properties: ClassVar[list[str]] = ['type', 'suffixes', 'description'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +37,6 @@ class PluginsInnerMimeTypesInner(BaseModel): 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)) @@ -53,7 +51,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of PluginsInnerMimeTypesInner from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +61,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +71,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of PluginsInnerMimeTypesInner from a dict""" if obj is None: return None @@ -82,11 +79,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "type": obj.get("type"), - "suffixes": obj.get("suffixes"), - "description": obj.get("description") - }) + _obj = cls.model_validate( + { + 'type': obj.get('type'), + 'suffixes': obj.get('suffixes'), + 'description': obj.get('description'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/proximity.py b/fingerprint_server_sdk/models/proximity.py index 0a1948dc..dcb6d980 100644 --- a/fingerprint_server_sdk/models/proximity.py +++ b/fingerprint_server_sdk/models/proximity.py @@ -1,43 +1,52 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Annotated, Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List, Union -from typing_extensions import Annotated -from typing import Optional, Set from typing_extensions import Self + class Proximity(BaseModel): """ - Proximity ID represents a fixed geographical zone in a discrete global grid within which the device is observed. - """ # noqa: E501 - id: StrictStr = Field(description="A stable privacy-preserving identifier for a given proximity zone. ") - precision_radius: StrictInt = Field(description="The radius of the proximity zone’s precision level, in meters. ") - confidence: Union[Annotated[float, Field(le=1, strict=True, ge=0)], Annotated[int, Field(le=1, strict=True, ge=0)]] = Field(description="A value between `0` and `1` representing the likelihood that the true device location lies within the mapped proximity zone. * Scores closer to `1` indicate high confidence that the location is inside the mapped proximity zone. * Scores closer to `0` indicate lower confidence, suggesting the true location may fall in an adjacent zone. ") - __properties: ClassVar[List[str]] = ["id", "precision_radius", "confidence"] + Proximity ID represents a fixed geographical zone in a discrete global grid within which the device is observed. + """ + + id: StrictStr = Field( + description='A stable privacy-preserving identifier for a given proximity zone. ' + ) + precision_radius: StrictInt = Field( + description='The radius of the proximity zone’s precision level, in meters. ' + ) + confidence: Union[ + Annotated[float, Field(le=1, strict=True, ge=0)], + Annotated[int, Field(le=1, strict=True, ge=0)], + ] = Field( + description='A value between `0` and `1` representing the likelihood that the true device location lies within the mapped proximity zone. * Scores closer to `1` indicate high confidence that the location is inside the mapped proximity zone. * Scores closer to `0` indicate lower confidence, suggesting the true location may fall in an adjacent zone. ' + ) + __properties: ClassVar[list[str]] = ['id', 'precision_radius', 'confidence'] @field_validator('precision_radius') - def precision_radius_validate_enum(cls, value): + def precision_radius_validate_enum(cls, value: Any) -> Any: """Validates the enum""" if value not in set([10, 25, 65, 175, 450, 1200, 3300, 8500, 22500]): - raise ValueError("must be one of enum values (10, 25, 65, 175, 450, 1200, 3300, 8500, 22500)") + raise ValueError( + 'must be one of enum values (10, 25, 65, 175, 450, 1200, 3300, 8500, 22500)' + ) return value model_config = ConfigDict( @@ -46,7 +55,6 @@ def precision_radius_validate_enum(cls, value): 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)) @@ -61,7 +69,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Proximity from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -71,8 +79,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -82,7 +89,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Proximity from a dict""" if obj is None: return None @@ -90,11 +97,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "id": obj.get("id"), - "precision_radius": obj.get("precision_radius"), - "confidence": obj.get("confidence") - }) + _obj = cls.model_validate( + { + 'id': obj.get('id'), + 'precision_radius': obj.get('precision_radius'), + 'confidence': obj.get('confidence'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/proxy_confidence.py b/fingerprint_server_sdk/models/proxy_confidence.py index 45d2a9c0..f0af2611 100644 --- a/fingerprint_server_sdk/models/proxy_confidence.py +++ b/fingerprint_server_sdk/models/proxy_confidence.py @@ -1,27 +1,26 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + import json from enum import Enum + from typing_extensions import Self class ProxyConfidence(str, Enum): """ - Confidence level of the proxy detection. If a proxy is not detected, confidence is \"high\". If it's detected, can be \"low\", \"medium\", or \"high\". + Confidence level of the proxy detection. If a proxy is not detected, confidence is \"high\". If it's detected, can be \"low\", \"medium\", or \"high\". """ """ @@ -35,5 +34,3 @@ class ProxyConfidence(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of ProxyConfidence from a JSON string""" return cls(json.loads(json_str)) - - diff --git a/fingerprint_server_sdk/models/proxy_details.py b/fingerprint_server_sdk/models/proxy_details.py index 01d5f743..2885ddf5 100644 --- a/fingerprint_server_sdk/models/proxy_details.py +++ b/fingerprint_server_sdk/models/proxy_details.py @@ -1,39 +1,46 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class ProxyDetails(BaseModel): """ Proxy detection details (present if `proxy` is `true`) - """ # noqa: E501 - proxy_type: StrictStr = Field(description="Residential proxies use real user IP addresses to appear as legitimate traffic, while data center proxies are public proxies hosted in data centers ") - last_seen_at: Optional[StrictInt] = Field(default=None, description="Unix millisecond timestamp with hourly resolution of when this IP was last seen as a proxy ") - provider: Optional[StrictStr] = Field(default=None, description="String representing the last proxy service provider detected when this IP was synced. An IP can be shared by multiple service providers. ") - __properties: ClassVar[List[str]] = ["proxy_type", "last_seen_at", "provider"] + """ + + proxy_type: StrictStr = Field( + description='Residential proxies use real user IP addresses to appear as legitimate traffic, while data center proxies are public proxies hosted in data centers ' + ) + last_seen_at: Optional[StrictInt] = Field( + default=None, + description='Unix millisecond timestamp with hourly resolution of when this IP was last seen as a proxy ', + ) + provider: Optional[StrictStr] = Field( + default=None, + description='String representing the last proxy service provider detected when this IP was synced. An IP can be shared by multiple service providers. ', + ) + __properties: ClassVar[list[str]] = ['proxy_type', 'last_seen_at', 'provider'] @field_validator('proxy_type') - def proxy_type_validate_enum(cls, value): + def proxy_type_validate_enum(cls, value: Any) -> Any: """Validates the enum""" if value not in set(['residential', 'data_center']): raise ValueError("must be one of enum values ('residential', 'data_center')") @@ -45,7 +52,6 @@ def proxy_type_validate_enum(cls, value): 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)) @@ -60,7 +66,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of ProxyDetails from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -70,8 +76,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -81,7 +86,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of ProxyDetails from a dict""" if obj is None: return None @@ -89,11 +94,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "proxy_type": obj.get("proxy_type"), - "last_seen_at": obj.get("last_seen_at"), - "provider": obj.get("provider") - }) + _obj = cls.model_validate( + { + 'proxy_type': obj.get('proxy_type'), + 'last_seen_at': obj.get('last_seen_at'), + 'provider': obj.get('provider'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/raw_device_attributes.py b/fingerprint_server_sdk/models/raw_device_attributes.py index 6205eaa8..127d117a 100644 --- a/fingerprint_server_sdk/models/raw_device_attributes.py +++ b/fingerprint_server_sdk/models/raw_device_attributes.py @@ -1,26 +1,25 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Annotated, Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional, Union -from typing_extensions import Annotated +from typing_extensions import Self + from fingerprint_server_sdk.models.canvas import Canvas from fingerprint_server_sdk.models.emoji import Emoji from fingerprint_server_sdk.models.font_preferences import FontPreferences @@ -28,39 +27,101 @@ from fingerprint_server_sdk.models.touch_support import TouchSupport from fingerprint_server_sdk.models.web_gl_basics import WebGlBasics from fingerprint_server_sdk.models.web_gl_extensions import WebGlExtensions -from typing import Optional, Set -from typing_extensions import Self + class RawDeviceAttributes(BaseModel): """ - A curated subset of raw browser/device attributes that the API surface exposes. Each property contains a value or object with the data for the collected signal. - """ # noqa: E501 + A curated subset of raw browser/device attributes that the API surface exposes. Each property contains a value or object with the data for the collected signal. + """ + font_preferences: Optional[FontPreferences] = None emoji: Optional[Emoji] = None - fonts: Optional[List[StrictStr]] = Field(default=None, description="List of fonts detected on the device.") - device_memory: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field(default=None, description="Rounded amount of RAM (in gigabytes) reported by the browser.") - timezone: Optional[StrictStr] = Field(default=None, description="Timezone identifier detected on the client.") + fonts: Optional[list[StrictStr]] = Field( + default=None, description='List of fonts detected on the device.' + ) + device_memory: Optional[Annotated[int, Field(strict=True, ge=0)]] = Field( + default=None, description='Rounded amount of RAM (in gigabytes) reported by the browser.' + ) + timezone: Optional[StrictStr] = Field( + default=None, description='Timezone identifier detected on the client.' + ) canvas: Optional[Canvas] = None - languages: Optional[List[List[StrictStr]]] = Field(default=None, description="Navigator languages reported by the agent including fallbacks. Each inner array represents ordered language preferences reported by different APIs. ") + languages: Optional[list[list[StrictStr]]] = Field( + default=None, + description='Navigator languages reported by the agent including fallbacks. Each inner array represents ordered language preferences reported by different APIs. ', + ) webgl_extensions: Optional[WebGlExtensions] = None webgl_basics: Optional[WebGlBasics] = None - screen_resolution: Optional[Annotated[List[StrictInt], Field(min_length=2, max_length=2)]] = Field(default=None, description="Current screen resolution.") + screen_resolution: Optional[Annotated[list[StrictInt], Field(min_length=2, max_length=2)]] = ( + Field(default=None, description='Current screen resolution.') + ) touch_support: Optional[TouchSupport] = None - oscpu: Optional[StrictStr] = Field(default=None, description="Navigator `oscpu` string.") - architecture: Optional[StrictInt] = Field(default=None, description="Integer representing the CPU architecture exposed by the browser.") - cookies_enabled: Optional[StrictBool] = Field(default=None, description="Whether the cookies are enabled in the browser.") - hardware_concurrency: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field(default=None, description="Number of logical CPU cores reported by the browser.") - date_time_locale: Optional[StrictStr] = Field(default=None, description="Locale derived from the Intl.DateTimeFormat API. Negative values indicate known error states. The negative statuses can be: - \"-1\": A permanent status for browsers that don't support Intl API. - \"-2\": A permanent status for browsers that don't supportDateTimeFormat constructor. - \"-3\": A permanent status for browsers in which DateTimeFormat locale is undefined or null. ") - vendor: Optional[StrictStr] = Field(default=None, description="Navigator vendor string.") - color_depth: Optional[StrictInt] = Field(default=None, description="Screen color depth in bits.") - platform: Optional[StrictStr] = Field(default=None, description="Navigator platform string.") - session_storage: Optional[StrictBool] = Field(default=None, description="Whether sessionStorage is available.") - local_storage: Optional[StrictBool] = Field(default=None, description="Whether localStorage is available.") - audio: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, description="AudioContext fingerprint or negative status when unavailable. The negative statuses can be: - -1: A permanent status for those browsers which are known to always suspend audio context - -2: A permanent status for browsers that don't support the signal - -3: A temporary status that means that an unexpected timeout has happened ") - plugins: Optional[List[PluginsInner]] = Field(default=None, description="Browser plugins reported by `navigator.plugins`.") - indexed_db: Optional[StrictBool] = Field(default=None, description="Whether IndexedDB is available.") - math: Optional[StrictStr] = Field(default=None, description="Hash of Math APIs used for entropy collection.") - __properties: ClassVar[List[str]] = ["font_preferences", "emoji", "fonts", "device_memory", "timezone", "canvas", "languages", "webgl_extensions", "webgl_basics", "screen_resolution", "touch_support", "oscpu", "architecture", "cookies_enabled", "hardware_concurrency", "date_time_locale", "vendor", "color_depth", "platform", "session_storage", "local_storage", "audio", "plugins", "indexed_db", "math"] + oscpu: Optional[StrictStr] = Field(default=None, description='Navigator `oscpu` string.') + architecture: Optional[StrictInt] = Field( + default=None, + description='Integer representing the CPU architecture exposed by the browser.', + ) + cookies_enabled: Optional[StrictBool] = Field( + default=None, description='Whether the cookies are enabled in the browser.' + ) + hardware_concurrency: Optional[Annotated[int, Field(strict=True, ge=1)]] = Field( + default=None, description='Number of logical CPU cores reported by the browser.' + ) + date_time_locale: Optional[StrictStr] = Field( + default=None, + description='Locale derived from the Intl.DateTimeFormat API. Negative values indicate known error states. The negative statuses can be: - "-1": A permanent status for browsers that don\'t support Intl API. - "-2": A permanent status for browsers that don\'t supportDateTimeFormat constructor. - "-3": A permanent status for browsers in which DateTimeFormat locale is undefined or null. ', + ) + vendor: Optional[StrictStr] = Field(default=None, description='Navigator vendor string.') + color_depth: Optional[StrictInt] = Field( + default=None, description='Screen color depth in bits.' + ) + platform: Optional[StrictStr] = Field(default=None, description='Navigator platform string.') + session_storage: Optional[StrictBool] = Field( + default=None, description='Whether sessionStorage is available.' + ) + local_storage: Optional[StrictBool] = Field( + default=None, description='Whether localStorage is available.' + ) + audio: Optional[Union[StrictFloat, StrictInt]] = Field( + default=None, + description="AudioContext fingerprint or negative status when unavailable. The negative statuses can be: - -1: A permanent status for those browsers which are known to always suspend audio context - -2: A permanent status for browsers that don't support the signal - -3: A temporary status that means that an unexpected timeout has happened ", + ) + plugins: Optional[list[PluginsInner]] = Field( + default=None, description='Browser plugins reported by `navigator.plugins`.' + ) + indexed_db: Optional[StrictBool] = Field( + default=None, description='Whether IndexedDB is available.' + ) + math: Optional[StrictStr] = Field( + default=None, description='Hash of Math APIs used for entropy collection.' + ) + __properties: ClassVar[list[str]] = [ + 'font_preferences', + 'emoji', + 'fonts', + 'device_memory', + 'timezone', + 'canvas', + 'languages', + 'webgl_extensions', + 'webgl_basics', + 'screen_resolution', + 'touch_support', + 'oscpu', + 'architecture', + 'cookies_enabled', + 'hardware_concurrency', + 'date_time_locale', + 'vendor', + 'color_depth', + 'platform', + 'session_storage', + 'local_storage', + 'audio', + 'plugins', + 'indexed_db', + 'math', + ] model_config = ConfigDict( populate_by_name=True, @@ -68,7 +129,6 @@ class RawDeviceAttributes(BaseModel): 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)) @@ -83,7 +143,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of RawDeviceAttributes from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -93,8 +153,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -129,7 +188,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of RawDeviceAttributes from a dict""" if obj is None: return None @@ -137,33 +196,45 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "font_preferences": FontPreferences.from_dict(obj["font_preferences"]) if obj.get("font_preferences") is not None else None, - "emoji": Emoji.from_dict(obj["emoji"]) if obj.get("emoji") is not None else None, - "fonts": obj.get("fonts"), - "device_memory": obj.get("device_memory"), - "timezone": obj.get("timezone"), - "canvas": Canvas.from_dict(obj["canvas"]) if obj.get("canvas") is not None else None, - "languages": obj.get("languages"), - "webgl_extensions": WebGlExtensions.from_dict(obj["webgl_extensions"]) if obj.get("webgl_extensions") is not None else None, - "webgl_basics": WebGlBasics.from_dict(obj["webgl_basics"]) if obj.get("webgl_basics") is not None else None, - "screen_resolution": obj.get("screen_resolution"), - "touch_support": TouchSupport.from_dict(obj["touch_support"]) if obj.get("touch_support") is not None else None, - "oscpu": obj.get("oscpu"), - "architecture": obj.get("architecture"), - "cookies_enabled": obj.get("cookies_enabled"), - "hardware_concurrency": obj.get("hardware_concurrency"), - "date_time_locale": obj.get("date_time_locale"), - "vendor": obj.get("vendor"), - "color_depth": obj.get("color_depth"), - "platform": obj.get("platform"), - "session_storage": obj.get("session_storage"), - "local_storage": obj.get("local_storage"), - "audio": obj.get("audio"), - "plugins": [PluginsInner.from_dict(_item) for _item in obj["plugins"]] if obj.get("plugins") is not None else None, - "indexed_db": obj.get("indexed_db"), - "math": obj.get("math") - }) + _obj = cls.model_validate( + { + 'font_preferences': FontPreferences.from_dict(obj['font_preferences']) + if obj.get('font_preferences') is not None + else None, + 'emoji': Emoji.from_dict(obj['emoji']) if obj.get('emoji') is not None else None, + 'fonts': obj.get('fonts'), + 'device_memory': obj.get('device_memory'), + 'timezone': obj.get('timezone'), + 'canvas': Canvas.from_dict(obj['canvas']) + if obj.get('canvas') is not None + else None, + 'languages': obj.get('languages'), + 'webgl_extensions': WebGlExtensions.from_dict(obj['webgl_extensions']) + if obj.get('webgl_extensions') is not None + else None, + 'webgl_basics': WebGlBasics.from_dict(obj['webgl_basics']) + if obj.get('webgl_basics') is not None + else None, + 'screen_resolution': obj.get('screen_resolution'), + 'touch_support': TouchSupport.from_dict(obj['touch_support']) + if obj.get('touch_support') is not None + else None, + 'oscpu': obj.get('oscpu'), + 'architecture': obj.get('architecture'), + 'cookies_enabled': obj.get('cookies_enabled'), + 'hardware_concurrency': obj.get('hardware_concurrency'), + 'date_time_locale': obj.get('date_time_locale'), + 'vendor': obj.get('vendor'), + 'color_depth': obj.get('color_depth'), + 'platform': obj.get('platform'), + 'session_storage': obj.get('session_storage'), + 'local_storage': obj.get('local_storage'), + 'audio': obj.get('audio'), + 'plugins': [PluginsInner.from_dict(_item) for _item in obj['plugins']] + if obj.get('plugins') is not None + else None, + 'indexed_db': obj.get('indexed_db'), + 'math': obj.get('math'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/request_header_modifications.py b/fingerprint_server_sdk/models/request_header_modifications.py index e9e98be6..92a6729c 100644 --- a/fingerprint_server_sdk/models/request_header_modifications.py +++ b/fingerprint_server_sdk/models/request_header_modifications.py @@ -1,37 +1,44 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.rule_action_header_field import RuleActionHeaderField -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.rule_action_header_field import RuleActionHeaderField + + class RequestHeaderModifications(BaseModel): """ The set of header modifications to apply, in the following order: remove, set, append. - """ # noqa: E501 - remove: Optional[List[StrictStr]] = Field(default=None, description="The list of headers to remove.") - set: Optional[List[RuleActionHeaderField]] = Field(default=None, description="The list of headers to set, overwriting any existing headers with the same name.") - append: Optional[List[RuleActionHeaderField]] = Field(default=None, description="The list of headers to append.") - __properties: ClassVar[List[str]] = ["remove", "set", "append"] + """ + + remove: Optional[list[StrictStr]] = Field( + default=None, description='The list of headers to remove.' + ) + set: Optional[list[RuleActionHeaderField]] = Field( + default=None, + description='The list of headers to set, overwriting any existing headers with the same name.', + ) + append: Optional[list[RuleActionHeaderField]] = Field( + default=None, description='The list of headers to append.' + ) + __properties: ClassVar[list[str]] = ['remove', 'set', 'append'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +46,6 @@ class RequestHeaderModifications(BaseModel): 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)) @@ -54,7 +60,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of RequestHeaderModifications from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -64,8 +70,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -89,7 +94,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of RequestHeaderModifications from a dict""" if obj is None: return None @@ -97,11 +102,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "remove": obj.get("remove"), - "set": [RuleActionHeaderField.from_dict(_item) for _item in obj["set"]] if obj.get("set") is not None else None, - "append": [RuleActionHeaderField.from_dict(_item) for _item in obj["append"]] if obj.get("append") is not None else None - }) + _obj = cls.model_validate( + { + 'remove': obj.get('remove'), + 'set': [RuleActionHeaderField.from_dict(_item) for _item in obj['set']] + if obj.get('set') is not None + else None, + 'append': [RuleActionHeaderField.from_dict(_item) for _item in obj['append']] + if obj.get('append') is not None + else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/rule_action_header_field.py b/fingerprint_server_sdk/models/rule_action_header_field.py index c83cd567..d8bc62ad 100644 --- a/fingerprint_server_sdk/models/rule_action_header_field.py +++ b/fingerprint_server_sdk/models/rule_action_header_field.py @@ -1,35 +1,34 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr -from typing import Any, ClassVar, Dict, List -from typing import Optional, Set from typing_extensions import Self + class RuleActionHeaderField(BaseModel): """ RuleActionHeaderField - """ # noqa: E501 - name: StrictStr = Field(description="The header field name.") - value: StrictStr = Field(description="The value of the header field.") - __properties: ClassVar[List[str]] = ["name", "value"] + """ + + name: StrictStr = Field(description='The header field name.') + value: StrictStr = Field(description='The value of the header field.') + __properties: ClassVar[list[str]] = ['name', 'value'] model_config = ConfigDict( populate_by_name=True, @@ -37,7 +36,6 @@ class RuleActionHeaderField(BaseModel): 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)) @@ -52,7 +50,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of RuleActionHeaderField from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -62,8 +60,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -73,7 +70,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of RuleActionHeaderField from a dict""" if obj is None: return None @@ -81,10 +78,5 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "name": obj.get("name"), - "value": obj.get("value") - }) + _obj = cls.model_validate({'name': obj.get('name'), 'value': obj.get('value')}) return _obj - - diff --git a/fingerprint_server_sdk/models/rule_action_type.py b/fingerprint_server_sdk/models/rule_action_type.py index f8681c3a..3dc0f091 100644 --- a/fingerprint_server_sdk/models/rule_action_type.py +++ b/fingerprint_server_sdk/models/rule_action_type.py @@ -1,21 +1,20 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + import json from enum import Enum + from typing_extensions import Self @@ -34,5 +33,3 @@ class RuleActionType(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of RuleActionType from a JSON string""" return cls(json.loads(json_str)) - - diff --git a/fingerprint_server_sdk/models/sdk.py b/fingerprint_server_sdk/models/sdk.py index 0299ddf6..48374082 100644 --- a/fingerprint_server_sdk/models/sdk.py +++ b/fingerprint_server_sdk/models/sdk.py @@ -1,40 +1,44 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.integration import Integration -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.integration import Integration + + class SDK(BaseModel): """ Contains information about the SDK used to perform the request. - """ # noqa: E501 - platform: StrictStr = Field(description="Platform of the SDK used for the identification request.") - version: StrictStr = Field(description="Version string of the SDK used for the identification request. For example: `\"3.12.1\"` ") - integrations: Optional[List[Integration]] = None - __properties: ClassVar[List[str]] = ["platform", "version", "integrations"] + """ + + platform: StrictStr = Field( + description='Platform of the SDK used for the identification request.' + ) + version: StrictStr = Field( + description='Version string of the SDK used for the identification request. For example: `"3.12.1"` ' + ) + integrations: Optional[list[Integration]] = None + __properties: ClassVar[list[str]] = ['platform', 'version', 'integrations'] @field_validator('platform') - def platform_validate_enum(cls, value): + def platform_validate_enum(cls, value: Any) -> Any: """Validates the enum""" if value not in set(['js', 'android', 'ios', 'unknown']): raise ValueError("must be one of enum values ('js', 'android', 'ios', 'unknown')") @@ -46,7 +50,6 @@ def platform_validate_enum(cls, value): 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)) @@ -61,7 +64,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of SDK from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -71,8 +74,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -89,7 +91,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of SDK from a dict""" if obj is None: return None @@ -97,11 +99,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "platform": obj.get("platform"), - "version": obj.get("version"), - "integrations": [Integration.from_dict(_item) for _item in obj["integrations"]] if obj.get("integrations") is not None else None - }) + _obj = cls.model_validate( + { + 'platform': obj.get('platform'), + 'version': obj.get('version'), + 'integrations': [Integration.from_dict(_item) for _item in obj['integrations']] + if obj.get('integrations') is not None + else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/supplementary_id_high_recall.py b/fingerprint_server_sdk/models/supplementary_id_high_recall.py index afda3141..b0398021 100644 --- a/fingerprint_server_sdk/models/supplementary_id_high_recall.py +++ b/fingerprint_server_sdk/models/supplementary_id_high_recall.py @@ -1,39 +1,55 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.identification_confidence import IdentificationConfidence -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.identification_confidence import IdentificationConfidence + + class SupplementaryIDHighRecall(BaseModel): """ A supplementary browser identifier that prioritizes coverage over precision. The High Recall ID algorithm matches more generously, i.e., this identifier will remain the same even when there are subtle differences between two requests. This algorithm does not create as many new visitor IDs as the standard algorithms do, but there could be an increase in false-positive identification. - """ # noqa: E501 - visitor_id: StrictStr = Field(description="String of 20 characters that uniquely identifies the visitor's browser or mobile device.") - visitor_found: StrictBool = Field(description="Attribute represents if a visitor had been identified before.") + """ + + visitor_id: StrictStr = Field( + description="String of 20 characters that uniquely identifies the visitor's browser or mobile device." + ) + visitor_found: StrictBool = Field( + description='Attribute represents if a visitor had been identified before.' + ) confidence: Optional[IdentificationConfidence] = None - first_seen_at: Optional[StrictInt] = Field(default=None, description="Unix epoch time milliseconds timestamp indicating the time at which this ID was first seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ") - last_seen_at: Optional[StrictInt] = Field(default=None, description="Unix epoch time milliseconds timestamp indicating the time at which this ID was last seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ") - __properties: ClassVar[List[str]] = ["visitor_id", "visitor_found", "confidence", "first_seen_at", "last_seen_at"] + first_seen_at: Optional[StrictInt] = Field( + default=None, + description='Unix epoch time milliseconds timestamp indicating the time at which this ID was first seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ', + ) + last_seen_at: Optional[StrictInt] = Field( + default=None, + description='Unix epoch time milliseconds timestamp indicating the time at which this ID was last seen. example: `1758069706642` - Corresponding to Wed Sep 17 2025 00:41:46 GMT+0000 ', + ) + __properties: ClassVar[list[str]] = [ + 'visitor_id', + 'visitor_found', + 'confidence', + 'first_seen_at', + 'last_seen_at', + ] model_config = ConfigDict( populate_by_name=True, @@ -41,7 +57,6 @@ class SupplementaryIDHighRecall(BaseModel): 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)) @@ -56,7 +71,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of SupplementaryIDHighRecall from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,8 +81,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -80,7 +94,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of SupplementaryIDHighRecall from a dict""" if obj is None: return None @@ -88,13 +102,15 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "visitor_id": obj.get("visitor_id"), - "visitor_found": obj.get("visitor_found"), - "confidence": IdentificationConfidence.from_dict(obj["confidence"]) if obj.get("confidence") is not None else None, - "first_seen_at": obj.get("first_seen_at"), - "last_seen_at": obj.get("last_seen_at") - }) + _obj = cls.model_validate( + { + 'visitor_id': obj.get('visitor_id'), + 'visitor_found': obj.get('visitor_found'), + 'confidence': IdentificationConfidence.from_dict(obj['confidence']) + if obj.get('confidence') is not None + else None, + 'first_seen_at': obj.get('first_seen_at'), + 'last_seen_at': obj.get('last_seen_at'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/tampering_details.py b/fingerprint_server_sdk/models/tampering_details.py index c50ed622..1d4a1e58 100644 --- a/fingerprint_server_sdk/models/tampering_details.py +++ b/fingerprint_server_sdk/models/tampering_details.py @@ -1,36 +1,45 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Annotated, Any, ClassVar, Optional, Union from pydantic import BaseModel, ConfigDict, Field, StrictBool -from typing import Any, ClassVar, Dict, List, Optional, Union -from typing_extensions import Annotated -from typing import Optional, Set from typing_extensions import Self + class TamperingDetails(BaseModel): """ TamperingDetails - """ # noqa: E501 - anomaly_score: Optional[Union[Annotated[float, Field(le=1, strict=True, ge=0)], Annotated[int, Field(le=1, strict=True, ge=0)]]] = Field(default=None, description="Confidence score (`0.0 - 1.0`) for tampering detection: * Values above `0.5` indicate tampering. * Values below `0.5` indicate genuine browsers. ") - anti_detect_browser: Optional[StrictBool] = Field(default=None, description="True if the identified browser resembles an \"anti-detect\" browser, such as Incognition, which attempts to evade identification by manipulating its fingerprint. ") - __properties: ClassVar[List[str]] = ["anomaly_score", "anti_detect_browser"] + """ + + anomaly_score: Optional[ + Union[ + Annotated[float, Field(le=1, strict=True, ge=0)], + Annotated[int, Field(le=1, strict=True, ge=0)], + ] + ] = Field( + default=None, + description='Confidence score (`0.0 - 1.0`) for tampering detection: * Values above `0.5` indicate tampering. * Values below `0.5` indicate genuine browsers. ', + ) + anti_detect_browser: Optional[StrictBool] = Field( + default=None, + description='True if the identified browser resembles an "anti-detect" browser, such as Incognition, which attempts to evade identification by manipulating its fingerprint. ', + ) + __properties: ClassVar[list[str]] = ['anomaly_score', 'anti_detect_browser'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +47,6 @@ class TamperingDetails(BaseModel): 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)) @@ -53,7 +61,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of TamperingDetails from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +71,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of TamperingDetails from a dict""" if obj is None: return None @@ -82,10 +89,10 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "anomaly_score": obj.get("anomaly_score"), - "anti_detect_browser": obj.get("anti_detect_browser") - }) + _obj = cls.model_validate( + { + 'anomaly_score': obj.get('anomaly_score'), + 'anti_detect_browser': obj.get('anti_detect_browser'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/touch_support.py b/fingerprint_server_sdk/models/touch_support.py index fbc11077..a55197a6 100644 --- a/fingerprint_server_sdk/models/touch_support.py +++ b/fingerprint_server_sdk/models/touch_support.py @@ -1,36 +1,35 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictBool, StrictInt -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class TouchSupport(BaseModel): """ Browser-reported touch capabilities. - """ # noqa: E501 + """ + touch_event: Optional[StrictBool] = None touch_start: Optional[StrictBool] = None max_touch_points: Optional[StrictInt] = None - __properties: ClassVar[List[str]] = ["touch_event", "touch_start", "max_touch_points"] + __properties: ClassVar[list[str]] = ['touch_event', 'touch_start', 'max_touch_points'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +37,6 @@ class TouchSupport(BaseModel): 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)) @@ -53,7 +51,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of TouchSupport from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +61,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +71,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of TouchSupport from a dict""" if obj is None: return None @@ -82,11 +79,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "touch_event": obj.get("touch_event"), - "touch_start": obj.get("touch_start"), - "max_touch_points": obj.get("max_touch_points") - }) + _obj = cls.model_validate( + { + 'touch_event': obj.get('touch_event'), + 'touch_start': obj.get('touch_start'), + 'max_touch_points': obj.get('max_touch_points'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/triggered_by_inner.py b/fingerprint_server_sdk/models/triggered_by_inner.py index b5ecbef5..b185ed4a 100644 --- a/fingerprint_server_sdk/models/triggered_by_inner.py +++ b/fingerprint_server_sdk/models/triggered_by_inner.py @@ -1,37 +1,36 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List -from typing import Optional, Set from typing_extensions import Self + class TriggeredByInner(BaseModel): """ TriggeredByInner - """ # noqa: E501 + """ + id: StrictStr name: StrictStr description: StrictStr - additional_properties: Dict[str, Any] = {} - __properties: ClassVar[List[str]] = ["id", "name", "description"] + additional_properties: dict[str, Any] = {} + __properties: ClassVar[list[str]] = ['id', 'name', 'description'] model_config = ConfigDict( populate_by_name=True, @@ -39,7 +38,6 @@ class TriggeredByInner(BaseModel): 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)) @@ -54,7 +52,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of TriggeredByInner from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -65,9 +63,11 @@ def to_dict(self) -> Dict[str, Any]: are ignored. * Fields in `self.additional_properties` are added to the output dict. """ - excluded_fields: Set[str] = set([ - "additional_properties", - ]) + excluded_fields: set[str] = set( + [ + 'additional_properties', + ] + ) _dict = self.model_dump( by_alias=True, @@ -82,7 +82,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of TriggeredByInner from a dict""" if obj is None: return None @@ -90,16 +90,12 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "id": obj.get("id"), - "name": obj.get("name"), - "description": obj.get("description") - }) + _obj = cls.model_validate( + {'id': obj.get('id'), 'name': obj.get('name'), 'description': obj.get('description')} + ) # store additional fields in additional_properties - for _key in obj.keys(): + for _key in obj: if _key not in cls.__properties: _obj.additional_properties[_key] = obj.get(_key) return _obj - - diff --git a/fingerprint_server_sdk/models/velocity.py b/fingerprint_server_sdk/models/velocity.py index d41fa812..6f6d0a8f 100644 --- a/fingerprint_server_sdk/models/velocity.py +++ b/fingerprint_server_sdk/models/velocity.py @@ -1,33 +1,33 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict -from typing import Any, ClassVar, Dict, List, Optional -from fingerprint_server_sdk.models.velocity_data import VelocityData -from typing import Optional, Set from typing_extensions import Self +from fingerprint_server_sdk.models.velocity_data import VelocityData + + class Velocity(BaseModel): """ - Sums key data points for a specific `visitor_id`, `ip_address` and `linked_id` at three distinct time intervals: 5 minutes, 1 hour, and 24 hours as follows: - Number of distinct IP addresses associated to the visitor Id. - Number of distinct linked Ids associated with the visitor Id. - Number of distinct countries associated with the visitor Id. - Number of identification events associated with the visitor Id. - Number of identification events associated with the detected IP address. - Number of distinct IP addresses associated with the provided linked Id. - Number of distinct visitor Ids associated with the provided linked Id. The `24h` interval of `distinct_ip`, `distinct_linked_id`, `distinct_country`, `distinct_ip_by_linked_id` and `distinct_visitor_id_by_linked_id` will be omitted if the number of `events` for the visitor Id in the last 24 hours (`events.['24h']`) is higher than 20.000. All will not necessarily be returned in a response, some may be omitted if the associated event does not have the required data, such as a linked_id. - """ # noqa: E501 + Sums key data points for a specific `visitor_id`, `ip_address` and `linked_id` at three distinct time intervals: 5 minutes, 1 hour, and 24 hours as follows: - Number of distinct IP addresses associated to the visitor Id. - Number of distinct linked Ids associated with the visitor Id. - Number of distinct countries associated with the visitor Id. - Number of identification events associated with the visitor Id. - Number of identification events associated with the detected IP address. - Number of distinct IP addresses associated with the provided linked Id. - Number of distinct visitor Ids associated with the provided linked Id. The `24h` interval of `distinct_ip`, `distinct_linked_id`, `distinct_country`, `distinct_ip_by_linked_id` and `distinct_visitor_id_by_linked_id` will be omitted if the number of `events` for the visitor Id in the last 24 hours (`events.['24h']`) is higher than 20.000. All will not necessarily be returned in a response, some may be omitted if the associated event does not have the required data, such as a linked_id. + """ + distinct_ip: Optional[VelocityData] = None distinct_linked_id: Optional[VelocityData] = None distinct_country: Optional[VelocityData] = None @@ -35,7 +35,15 @@ class Velocity(BaseModel): ip_events: Optional[VelocityData] = None distinct_ip_by_linked_id: Optional[VelocityData] = None distinct_visitor_id_by_linked_id: Optional[VelocityData] = None - __properties: ClassVar[List[str]] = ["distinct_ip", "distinct_linked_id", "distinct_country", "events", "ip_events", "distinct_ip_by_linked_id", "distinct_visitor_id_by_linked_id"] + __properties: ClassVar[list[str]] = [ + 'distinct_ip', + 'distinct_linked_id', + 'distinct_country', + 'events', + 'ip_events', + 'distinct_ip_by_linked_id', + 'distinct_visitor_id_by_linked_id', + ] model_config = ConfigDict( populate_by_name=True, @@ -43,7 +51,6 @@ class Velocity(BaseModel): 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)) @@ -58,7 +65,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of Velocity from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -68,8 +75,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -96,11 +102,13 @@ def to_dict(self) -> Dict[str, Any]: _dict['distinct_ip_by_linked_id'] = self.distinct_ip_by_linked_id.to_dict() # override the default output from pydantic by calling `to_dict()` of distinct_visitor_id_by_linked_id if self.distinct_visitor_id_by_linked_id: - _dict['distinct_visitor_id_by_linked_id'] = self.distinct_visitor_id_by_linked_id.to_dict() + _dict['distinct_visitor_id_by_linked_id'] = ( + self.distinct_visitor_id_by_linked_id.to_dict() + ) return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of Velocity from a dict""" if obj is None: return None @@ -108,15 +116,31 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "distinct_ip": VelocityData.from_dict(obj["distinct_ip"]) if obj.get("distinct_ip") is not None else None, - "distinct_linked_id": VelocityData.from_dict(obj["distinct_linked_id"]) if obj.get("distinct_linked_id") is not None else None, - "distinct_country": VelocityData.from_dict(obj["distinct_country"]) if obj.get("distinct_country") is not None else None, - "events": VelocityData.from_dict(obj["events"]) if obj.get("events") is not None else None, - "ip_events": VelocityData.from_dict(obj["ip_events"]) if obj.get("ip_events") is not None else None, - "distinct_ip_by_linked_id": VelocityData.from_dict(obj["distinct_ip_by_linked_id"]) if obj.get("distinct_ip_by_linked_id") is not None else None, - "distinct_visitor_id_by_linked_id": VelocityData.from_dict(obj["distinct_visitor_id_by_linked_id"]) if obj.get("distinct_visitor_id_by_linked_id") is not None else None - }) + _obj = cls.model_validate( + { + 'distinct_ip': VelocityData.from_dict(obj['distinct_ip']) + if obj.get('distinct_ip') is not None + else None, + 'distinct_linked_id': VelocityData.from_dict(obj['distinct_linked_id']) + if obj.get('distinct_linked_id') is not None + else None, + 'distinct_country': VelocityData.from_dict(obj['distinct_country']) + if obj.get('distinct_country') is not None + else None, + 'events': VelocityData.from_dict(obj['events']) + if obj.get('events') is not None + else None, + 'ip_events': VelocityData.from_dict(obj['ip_events']) + if obj.get('ip_events') is not None + else None, + 'distinct_ip_by_linked_id': VelocityData.from_dict(obj['distinct_ip_by_linked_id']) + if obj.get('distinct_ip_by_linked_id') is not None + else None, + 'distinct_visitor_id_by_linked_id': VelocityData.from_dict( + obj['distinct_visitor_id_by_linked_id'] + ) + if obj.get('distinct_visitor_id_by_linked_id') is not None + else None, + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/velocity_data.py b/fingerprint_server_sdk/models/velocity_data.py index 57d02645..f336c74d 100644 --- a/fingerprint_server_sdk/models/velocity_data.py +++ b/fingerprint_server_sdk/models/velocity_data.py @@ -1,36 +1,45 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictInt -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class VelocityData(BaseModel): """ - Is absent if the velocity data could not be generated for the visitor Id. - """ # noqa: E501 - var_5_minutes: StrictInt = Field(description="Count for the last 5 minutes of velocity data, from the time of the event. ", alias="5_minutes") - var_1_hour: StrictInt = Field(description="Count for the last 1 hour of velocity data, from the time of the event. ", alias="1_hour") - var_24_hours: Optional[StrictInt] = Field(default=None, description="The `24_hours` interval of `distinct_ip`, `distinct_linked_id`, `distinct_country`, `distinct_ip_by_linked_id` and `distinct_visitor_id_by_linked_id` will be omitted if the number of `events` for the visitor Id in the last 24 hours (`events.['24_hours']`) is higher than 20.000. ", alias="24_hours") - __properties: ClassVar[List[str]] = ["5_minutes", "1_hour", "24_hours"] + Is absent if the velocity data could not be generated for the visitor Id. + """ + + var_5_minutes: StrictInt = Field( + description='Count for the last 5 minutes of velocity data, from the time of the event. ', + alias='5_minutes', + ) + var_1_hour: StrictInt = Field( + description='Count for the last 1 hour of velocity data, from the time of the event. ', + alias='1_hour', + ) + var_24_hours: Optional[StrictInt] = Field( + default=None, + description="The `24_hours` interval of `distinct_ip`, `distinct_linked_id`, `distinct_country`, `distinct_ip_by_linked_id` and `distinct_visitor_id_by_linked_id` will be omitted if the number of `events` for the visitor Id in the last 24 hours (`events.['24_hours']`) is higher than 20.000. ", + alias='24_hours', + ) + __properties: ClassVar[list[str]] = ['5_minutes', '1_hour', '24_hours'] model_config = ConfigDict( populate_by_name=True, @@ -38,7 +47,6 @@ class VelocityData(BaseModel): 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)) @@ -53,7 +61,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of VelocityData from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -63,8 +71,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -74,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of VelocityData from a dict""" if obj is None: return None @@ -82,11 +89,11 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "5_minutes": obj.get("5_minutes"), - "1_hour": obj.get("1_hour"), - "24_hours": obj.get("24_hours") - }) + _obj = cls.model_validate( + { + '5_minutes': obj.get('5_minutes'), + '1_hour': obj.get('1_hour'), + '24_hours': obj.get('24_hours'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/vpn_confidence.py b/fingerprint_server_sdk/models/vpn_confidence.py index acf360af..a8a5bae9 100644 --- a/fingerprint_server_sdk/models/vpn_confidence.py +++ b/fingerprint_server_sdk/models/vpn_confidence.py @@ -1,21 +1,20 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + import json from enum import Enum + from typing_extensions import Self @@ -35,5 +34,3 @@ class VpnConfidence(str, Enum): def from_json(cls, json_str: str) -> Self: """Create an instance of VpnConfidence from a JSON string""" return cls(json.loads(json_str)) - - diff --git a/fingerprint_server_sdk/models/vpn_methods.py b/fingerprint_server_sdk/models/vpn_methods.py index 9bca0696..19da9b18 100644 --- a/fingerprint_server_sdk/models/vpn_methods.py +++ b/fingerprint_server_sdk/models/vpn_methods.py @@ -1,38 +1,58 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, Field, StrictBool -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class VpnMethods(BaseModel): """ VpnMethods - """ # noqa: E501 - timezone_mismatch: Optional[StrictBool] = Field(default=None, description="The browser timezone doesn't match the timezone inferred from the request IP address.") - public_vpn: Optional[StrictBool] = Field(default=None, description="Request IP address is owned and used by a public VPN service provider.") - auxiliary_mobile: Optional[StrictBool] = Field(default=None, description="This method applies to mobile devices only. Indicates the result of additional methods used to detect a VPN in mobile devices.") - os_mismatch: Optional[StrictBool] = Field(default=None, description="The browser runs on a different operating system than the operating system inferred from the request network signature.") - relay: Optional[StrictBool] = Field(default=None, description="Request IP address belongs to a relay service provider, indicating the use of relay services like [Apple Private relay](https://support.apple.com/en-us/102602) or [Cloudflare Warp](https://developers.cloudflare.com/warp-client/). * Like VPNs, relay services anonymize the visitor's true IP address. * Unlike traditional VPNs, relay services don't let visitors spoof their location by choosing an exit node in a different country. This field allows you to differentiate VPN users and relay service users in your fraud prevention logic. ") - __properties: ClassVar[List[str]] = ["timezone_mismatch", "public_vpn", "auxiliary_mobile", "os_mismatch", "relay"] + """ + + timezone_mismatch: Optional[StrictBool] = Field( + default=None, + description="The browser timezone doesn't match the timezone inferred from the request IP address.", + ) + public_vpn: Optional[StrictBool] = Field( + default=None, + description='Request IP address is owned and used by a public VPN service provider.', + ) + auxiliary_mobile: Optional[StrictBool] = Field( + default=None, + description='This method applies to mobile devices only. Indicates the result of additional methods used to detect a VPN in mobile devices.', + ) + os_mismatch: Optional[StrictBool] = Field( + default=None, + description='The browser runs on a different operating system than the operating system inferred from the request network signature.', + ) + relay: Optional[StrictBool] = Field( + default=None, + description="Request IP address belongs to a relay service provider, indicating the use of relay services like [Apple Private relay](https://support.apple.com/en-us/102602) or [Cloudflare Warp](https://developers.cloudflare.com/warp-client/). * Like VPNs, relay services anonymize the visitor's true IP address. * Unlike traditional VPNs, relay services don't let visitors spoof their location by choosing an exit node in a different country. This field allows you to differentiate VPN users and relay service users in your fraud prevention logic. ", + ) + __properties: ClassVar[list[str]] = [ + 'timezone_mismatch', + 'public_vpn', + 'auxiliary_mobile', + 'os_mismatch', + 'relay', + ] model_config = ConfigDict( populate_by_name=True, @@ -40,7 +60,6 @@ class VpnMethods(BaseModel): 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)) @@ -55,7 +74,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of VpnMethods from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -65,8 +84,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -76,7 +94,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of VpnMethods from a dict""" if obj is None: return None @@ -84,13 +102,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "timezone_mismatch": obj.get("timezone_mismatch"), - "public_vpn": obj.get("public_vpn"), - "auxiliary_mobile": obj.get("auxiliary_mobile"), - "os_mismatch": obj.get("os_mismatch"), - "relay": obj.get("relay") - }) + _obj = cls.model_validate( + { + 'timezone_mismatch': obj.get('timezone_mismatch'), + 'public_vpn': obj.get('public_vpn'), + 'auxiliary_mobile': obj.get('auxiliary_mobile'), + 'os_mismatch': obj.get('os_mismatch'), + 'relay': obj.get('relay'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/web_gl_basics.py b/fingerprint_server_sdk/models/web_gl_basics.py index e85a8c5c..cf1f8046 100644 --- a/fingerprint_server_sdk/models/web_gl_basics.py +++ b/fingerprint_server_sdk/models/web_gl_basics.py @@ -1,39 +1,45 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class WebGlBasics(BaseModel): """ Render and vendor strings reported by the WebGL context. - """ # noqa: E501 + """ + version: Optional[StrictStr] = None vendor: Optional[StrictStr] = None vendor_unmasked: Optional[StrictStr] = None renderer: Optional[StrictStr] = None renderer_unmasked: Optional[StrictStr] = None shading_language_version: Optional[StrictStr] = None - __properties: ClassVar[List[str]] = ["version", "vendor", "vendor_unmasked", "renderer", "renderer_unmasked", "shading_language_version"] + __properties: ClassVar[list[str]] = [ + 'version', + 'vendor', + 'vendor_unmasked', + 'renderer', + 'renderer_unmasked', + 'shading_language_version', + ] model_config = ConfigDict( populate_by_name=True, @@ -41,7 +47,6 @@ class WebGlBasics(BaseModel): 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)) @@ -56,7 +61,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of WebGlBasics from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,8 +71,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -77,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of WebGlBasics from a dict""" if obj is None: return None @@ -85,14 +89,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "version": obj.get("version"), - "vendor": obj.get("vendor"), - "vendor_unmasked": obj.get("vendor_unmasked"), - "renderer": obj.get("renderer"), - "renderer_unmasked": obj.get("renderer_unmasked"), - "shading_language_version": obj.get("shading_language_version") - }) + _obj = cls.model_validate( + { + 'version': obj.get('version'), + 'vendor': obj.get('vendor'), + 'vendor_unmasked': obj.get('vendor_unmasked'), + 'renderer': obj.get('renderer'), + 'renderer_unmasked': obj.get('renderer_unmasked'), + 'shading_language_version': obj.get('shading_language_version'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/models/web_gl_extensions.py b/fingerprint_server_sdk/models/web_gl_extensions.py index f8e320d1..3b7e07b3 100644 --- a/fingerprint_server_sdk/models/web_gl_extensions.py +++ b/fingerprint_server_sdk/models/web_gl_extensions.py @@ -1,39 +1,45 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - from __future__ import annotations + +import json import pprint import re # noqa: F401 -import json +from typing import Any, ClassVar, Optional from pydantic import BaseModel, ConfigDict, StrictStr -from typing import Any, ClassVar, Dict, List, Optional -from typing import Optional, Set from typing_extensions import Self + class WebGlExtensions(BaseModel): """ Hashes of WebGL context attributes and extension support. - """ # noqa: E501 + """ + context_attributes: Optional[StrictStr] = None parameters: Optional[StrictStr] = None shader_precisions: Optional[StrictStr] = None extensions: Optional[StrictStr] = None extension_parameters: Optional[StrictStr] = None - unsupported_extensions: Optional[List[StrictStr]] = None - __properties: ClassVar[List[str]] = ["context_attributes", "parameters", "shader_precisions", "extensions", "extension_parameters", "unsupported_extensions"] + unsupported_extensions: Optional[list[StrictStr]] = None + __properties: ClassVar[list[str]] = [ + 'context_attributes', + 'parameters', + 'shader_precisions', + 'extensions', + 'extension_parameters', + 'unsupported_extensions', + ] model_config = ConfigDict( populate_by_name=True, @@ -41,7 +47,6 @@ class WebGlExtensions(BaseModel): 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)) @@ -56,7 +61,7 @@ def from_json(cls, json_str: str) -> Optional[Self]: """Create an instance of WebGlExtensions from a JSON string""" return cls.from_dict(json.loads(json_str)) - def to_dict(self) -> Dict[str, Any]: + 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 @@ -66,8 +71,7 @@ def to_dict(self) -> Dict[str, Any]: were set at model initialization. Other fields with value `None` are ignored. """ - excluded_fields: Set[str] = set([ - ]) + excluded_fields: set[str] = set([]) _dict = self.model_dump( by_alias=True, @@ -77,7 +81,7 @@ def to_dict(self) -> Dict[str, Any]: return _dict @classmethod - def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: """Create an instance of WebGlExtensions from a dict""" if obj is None: return None @@ -85,14 +89,14 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: if not isinstance(obj, dict): return cls.model_validate(obj) - _obj = cls.model_validate({ - "context_attributes": obj.get("context_attributes"), - "parameters": obj.get("parameters"), - "shader_precisions": obj.get("shader_precisions"), - "extensions": obj.get("extensions"), - "extension_parameters": obj.get("extension_parameters"), - "unsupported_extensions": obj.get("unsupported_extensions") - }) + _obj = cls.model_validate( + { + 'context_attributes': obj.get('context_attributes'), + 'parameters': obj.get('parameters'), + 'shader_precisions': obj.get('shader_precisions'), + 'extensions': obj.get('extensions'), + 'extension_parameters': obj.get('extension_parameters'), + 'unsupported_extensions': obj.get('unsupported_extensions'), + } + ) return _obj - - diff --git a/fingerprint_server_sdk/rest.py b/fingerprint_server_sdk/rest.py index 706824f7..4e17c64b 100644 --- a/fingerprint_server_sdk/rest.py +++ b/fingerprint_server_sdk/rest.py @@ -1,35 +1,38 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 +from __future__ import annotations import io import json import re import ssl +from typing import TYPE_CHECKING, Any, Optional, Union import urllib3 from fingerprint_server_sdk.exceptions import ApiException, ApiValueError -SUPPORTED_SOCKS_PROXIES = {"socks5", "socks5h", "socks4", "socks4a"} +if TYPE_CHECKING: + from fingerprint_server_sdk.configuration import Configuration + +SUPPORTED_SOCKS_PROXIES = {'socks5', 'socks5h', 'socks4', 'socks4a'} RESTResponseType = urllib3.HTTPResponse -def is_socks_proxy_url(url): +def is_socks_proxy_url(url: Optional[str]) -> bool: if url is None: return False - split_section = url.split("://") + split_section = url.split('://') if len(split_section) < 2: return False else: @@ -37,35 +40,33 @@ def is_socks_proxy_url(url): class RESTResponse(io.IOBase): - - def __init__(self, resp) -> None: + def __init__(self, resp: urllib3.HTTPResponse) -> None: self.response = resp self.status = resp.status self.reason = resp.reason - self.data = None + self.data: Optional[bytes] = None - def read(self): + def read(self) -> bytes: if self.data is None: self.data = self.response.data return self.data @property - def headers(self): + def headers(self) -> urllib3.HTTPHeaderDict: """Returns a dictionary of response headers.""" return self.response.headers - def getheaders(self): + def getheaders(self) -> urllib3.HTTPHeaderDict: """Returns a dictionary of the response headers; use ``headers`` instead.""" return self.response.headers - def getheader(self, name, default=None): + def getheader(self, name: str, default: Optional[str] = None) -> Optional[str]: """Returns a given response header; use ``headers.get()`` instead.""" return self.response.headers.get(name, default) class RESTClientObject: - - def __init__(self, configuration) -> None: + def __init__(self, configuration: Configuration) -> None: # urllib3.PoolManager will pass all kw parameters to connectionpool # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 @@ -77,17 +78,15 @@ def __init__(self, configuration) -> None: else: cert_reqs = ssl.CERT_NONE - pool_args = { - "cert_reqs": cert_reqs, - "ca_certs": configuration.ssl_ca_cert, - "cert_file": configuration.cert_file, - "key_file": configuration.key_file, - "ca_cert_data": configuration.ca_cert_data, + pool_args: dict[str, Any] = { + 'cert_reqs': cert_reqs, + 'ca_certs': configuration.ssl_ca_cert, + 'cert_file': configuration.cert_file, + 'key_file': configuration.key_file, + 'ca_cert_data': configuration.ca_cert_data, } if configuration.assert_hostname is not None: - pool_args['assert_hostname'] = ( - configuration.assert_hostname - ) + pool_args['assert_hostname'] = configuration.assert_hostname if configuration.retries is not None: pool_args['retries'] = configuration.retries @@ -95,7 +94,6 @@ def __init__(self, configuration) -> None: if configuration.tls_server_name: pool_args['server_hostname'] = configuration.tls_server_name - if configuration.socket_options is not None: pool_args['socket_options'] = configuration.socket_options @@ -108,25 +106,26 @@ def __init__(self, configuration) -> None: if configuration.proxy: if is_socks_proxy_url(configuration.proxy): from urllib3.contrib.socks import SOCKSProxyManager - pool_args["proxy_url"] = configuration.proxy - pool_args["headers"] = configuration.proxy_headers + + pool_args['proxy_url'] = configuration.proxy + pool_args['headers'] = configuration.proxy_headers self.pool_manager = SOCKSProxyManager(**pool_args) else: - pool_args["proxy_url"] = configuration.proxy - pool_args["proxy_headers"] = configuration.proxy_headers + pool_args['proxy_url'] = configuration.proxy + pool_args['proxy_headers'] = configuration.proxy_headers self.pool_manager = urllib3.ProxyManager(**pool_args) else: self.pool_manager = urllib3.PoolManager(**pool_args) def request( self, - method, - url, - headers=None, - body=None, - post_params=None, - _request_timeout=None - ): + method: str, + url: str, + headers: Optional[dict[str, str]] = None, + body: Optional[Any] = None, + post_params: Optional[list[tuple[str, Any]]] = None, + _request_timeout: Optional[Union[float, tuple[float, float]]] = None, + ) -> RESTResponse: """Perform requests. :param method: http request method @@ -142,47 +141,27 @@ def request( (connection, read) timeouts. """ method = method.upper() - assert method in [ - 'GET', - 'HEAD', - 'DELETE', - 'POST', - 'PUT', - 'PATCH', - 'OPTIONS' - ] + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH', 'OPTIONS'] if post_params and body: - raise ApiValueError( - "body parameter cannot be used with post_params parameter." - ) + raise ApiValueError('body parameter cannot be used with post_params parameter.') - post_params = post_params or {} + post_params = post_params or [] headers = headers or {} timeout = None if _request_timeout: if isinstance(_request_timeout, (int, float)): timeout = urllib3.Timeout(total=_request_timeout) - elif ( - isinstance(_request_timeout, tuple) - and len(_request_timeout) == 2 - ): - timeout = urllib3.Timeout( - connect=_request_timeout[0], - read=_request_timeout[1] - ) + elif isinstance(_request_timeout, tuple) and len(_request_timeout) == 2: + timeout = urllib3.Timeout(connect=_request_timeout[0], read=_request_timeout[1]) try: # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: - # no content type provided or payload is json content_type = headers.get('Content-Type') - if ( - not content_type - or re.search('json', content_type, re.IGNORECASE) - ): + if not content_type or re.search('json', content_type, re.IGNORECASE): request_body = None if body is not None: request_body = json.dumps(body) @@ -192,7 +171,7 @@ def request( body=request_body, timeout=timeout, headers=headers, - preload_content=False + preload_content=False, ) elif content_type == 'application/x-www-form-urlencoded': r = self.pool_manager.request( @@ -202,7 +181,7 @@ def request( encode_multipart=False, timeout=timeout, headers=headers, - preload_content=False + preload_content=False, ) elif content_type == 'multipart/form-data': # must del headers['Content-Type'], or the correct @@ -210,7 +189,10 @@ def request( # overwritten. del headers['Content-Type'] # Ensures that dict objects are serialized - post_params = [(a, json.dumps(b)) if isinstance(b, dict) else (a,b) for a, b in post_params] + post_params = [ + (a, json.dumps(b)) if isinstance(b, dict) else (a, b) + for a, b in post_params + ] r = self.pool_manager.request( method, url, @@ -218,29 +200,30 @@ def request( encode_multipart=True, timeout=timeout, headers=headers, - preload_content=False + preload_content=False, ) # Pass a `string` parameter directly in the body to support # other content types than JSON when `body` argument is # provided in serialized form. - elif isinstance(body, str) or isinstance(body, bytes): + elif isinstance(body, (str, bytes)): r = self.pool_manager.request( method, url, body=body, timeout=timeout, headers=headers, - preload_content=False + preload_content=False, ) elif headers['Content-Type'].startswith('text/') and isinstance(body, bool): - request_body = "true" if body else "false" + request_body = 'true' if body else 'false' r = self.pool_manager.request( method, url, body=request_body, preload_content=False, timeout=timeout, - headers=headers) + headers=headers, + ) else: # Cannot generate the request from given parameters msg = """Cannot prepare a request message for provided @@ -250,15 +233,10 @@ def request( # For `GET`, `HEAD` else: r = self.pool_manager.request( - method, - url, - fields={}, - timeout=timeout, - headers=headers, - preload_content=False + method, url, fields={}, timeout=timeout, headers=headers, preload_content=False ) except urllib3.exceptions.SSLError as e: - msg = "\n".join([type(e).__name__, str(e)]) - raise ApiException(status=0, reason=msg) + msg = '\n'.join([type(e).__name__, str(e)]) + raise ApiException(status=0, reason=msg) from e - return RESTResponse(r) + return RESTResponse(r) # type: ignore[arg-type] diff --git a/fingerprint_server_sdk/sealed.py b/fingerprint_server_sdk/sealed.py index 2f0cd2f2..ac9c8fb6 100644 --- a/fingerprint_server_sdk/sealed.py +++ b/fingerprint_server_sdk/sealed.py @@ -1,13 +1,12 @@ import json -from typing import List +import zlib -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend -import zlib +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from fingerprint_server_sdk.models.event import Event -SEALED_HEADER = bytes([0x9e, 0x85, 0xdc, 0xed]) +SEALED_HEADER = bytes([0x9E, 0x85, 0xDC, 0xED]) DecryptionAlgorithm = { 'Aes256Gcm': 'aes-256-gcm', } @@ -15,7 +14,8 @@ class DecryptionKey: """Key for decryption of sealed data.""" - exception: Exception + + key: bytes algorithm: str def __init__(self, key: bytes, algorithm: str): @@ -25,6 +25,7 @@ def __init__(self, key: bytes, algorithm: str): class UnsealError(Exception): """Error during unsealing.""" + exception: Exception key: DecryptionKey @@ -35,14 +36,15 @@ def __init__(self, exception: Exception, key: DecryptionKey): class UnsealAggregateError(Exception): """Aggregated error during unsealing.""" - errors: List[UnsealError] - def __init__(self, errors: List[UnsealError]): + errors: list[UnsealError] + + def __init__(self, errors: list[UnsealError]): self.errors = errors - super().__init__("Unable to decrypt sealed data") + super().__init__('Unable to decrypt sealed data') -def unseal_event_response(sealed_data: bytes, decryption_keys: List[DecryptionKey]) -> Event: +def unseal_event_response(sealed_data: bytes, decryption_keys: list[DecryptionKey]) -> Event: """Unseal event response with one of the provided keys.""" unsealed = __unseal(sealed_data, decryption_keys) return __parse_event_response(unsealed) @@ -55,13 +57,15 @@ def __parse_event_response(unsealed: str) -> Event: if 'event_id' not in json_data: raise ValueError('Sealed data is not valid event response') - result: Event = Event.from_dict(json_data) + result = Event.from_dict(json_data) + if result is None: + raise ValueError('Failed to parse event response') return result -def __unseal(sealed_data: bytes, decryption_keys: List[DecryptionKey]) -> str: +def __unseal(sealed_data: bytes, decryption_keys: list[DecryptionKey]) -> str: """Unseal data with one of the provided keys.""" - if sealed_data[:len(SEALED_HEADER)].hex() != SEALED_HEADER.hex(): + if sealed_data[: len(SEALED_HEADER)].hex() != SEALED_HEADER.hex(): raise ValueError('Invalid sealed data header') errors = [] @@ -73,7 +77,7 @@ def __unseal(sealed_data: bytes, decryption_keys: List[DecryptionKey]) -> str: errors.append(UnsealError(e, decryption_key)) continue else: - raise ValueError(f"Unsupported decryption algorithm: {decryption_key.algorithm}") + raise ValueError(f'Unsupported decryption algorithm: {decryption_key.algorithm}') raise UnsealAggregateError(errors) @@ -81,17 +85,15 @@ def __unseal(sealed_data: bytes, decryption_keys: List[DecryptionKey]) -> str: def __unseal_aes256gcm(sealed_data: bytes, decryption_key: bytes) -> str: """Unseal data with AES-256-GCM.""" nonce_length = 12 - nonce = sealed_data[len(SEALED_HEADER):len(SEALED_HEADER) + nonce_length] + nonce = sealed_data[len(SEALED_HEADER) : len(SEALED_HEADER) + nonce_length] auth_tag_length = 16 auth_tag = sealed_data[-auth_tag_length:] - ciphertext = sealed_data[len(SEALED_HEADER) + nonce_length:-auth_tag_length] + ciphertext = sealed_data[len(SEALED_HEADER) + nonce_length : -auth_tag_length] decipher = Cipher( - algorithms.AES(decryption_key), - modes.GCM(nonce, auth_tag), - backend=default_backend() + algorithms.AES(decryption_key), modes.GCM(nonce, auth_tag), backend=default_backend() ).decryptor() compressed = decipher.update(ciphertext) + decipher.finalize() diff --git a/fingerprint_server_sdk/webhook_validation.py b/fingerprint_server_sdk/webhook_validation.py index cf684f09..3e6e5116 100644 --- a/fingerprint_server_sdk/webhook_validation.py +++ b/fingerprint_server_sdk/webhook_validation.py @@ -1,9 +1,10 @@ -import hmac import hashlib +import hmac class WebhookValidation: """Manages work with webhooks.""" + @staticmethod def is_valid_hmac_signature(signature: str, data: bytes, secret: str) -> bool: """Validates an HMAC signature.""" @@ -13,9 +14,12 @@ def is_valid_hmac_signature(signature: str, data: bytes, secret: str) -> bool: @staticmethod def is_valid_webhook_signature(header: str, data: bytes, secret: str) -> bool: - """Verifies the HMAC signature extracted from the "fpjs-event-signature" header of the incoming request. - This is a part of the webhook signing process, which is available only for enterprise customers. - If you wish to enable it, please contact our support: https://fingerprint.com/support""" + """Verifies the HMAC signature extracted from the "fpjs-event-signature" header. + + This is a part of the webhook signing process, which is available only for + enterprise customers. If you wish to enable it, please contact our support: + https://fingerprint.com/support + """ signatures = header.split(',') @@ -23,8 +27,9 @@ def is_valid_webhook_signature(header: str, data: bytes, secret: str) -> bool: parts = signature.split('=') if len(parts) == 2: version, hash_value = parts - if version == "v1" and WebhookValidation.is_valid_hmac_signature(hash_value, data, secret): + if version == 'v1' and WebhookValidation.is_valid_hmac_signature( + hash_value, data, secret + ): return True return False - diff --git a/generate.sh b/generate.sh index 37e25515..a614f00a 100755 --- a/generate.sh +++ b/generate.sh @@ -23,10 +23,15 @@ rm -Rf docs OPENAPI_GENERATOR_IMAGE_VERSION="v7.19.0" -docker run --rm -v "${PWD}:/local" -w /local "openapitools/openapi-generator-cli:${OPENAPI_GENERATOR_IMAGE_VERSION}" generate \ +docker run --rm -u "$(id -u):$(id -g)" -v "${PWD}:/local" -w /local "openapitools/openapi-generator-cli:${OPENAPI_GENERATOR_IMAGE_VERSION}" generate \ -i ./res/fingerprint-server-api.yaml \ -g python \ -o ./ \ -t ./template \ -c ./config.json \ --additional-properties=packageVersion="$VERSION" + +# Linting and formatting +PYTHON_CMD="${PYTHON:-$(command -v python3 || command -v python)}" +"$PYTHON_CMD" -m ruff format . +"$PYTHON_CMD" -m ruff check --fix --unsafe-fixes . \ No newline at end of file diff --git a/generate_coverage_summary.py b/generate_coverage_summary.py index dc857984..602b612e 100644 --- a/generate_coverage_summary.py +++ b/generate_coverage_summary.py @@ -1,14 +1,10 @@ import json -with open('coverage.json', 'r') as f: +with open('coverage.json') as f: json_report = json.load(f) json_summary = { - 'total': { - 'statements': { - 'pct': round(json_report['totals']['percent_covered'], 2) - } - } + 'total': {'statements': {'pct': round(json_report['totals']['percent_covered'], 2)}} } with open('coverage-summary.json', 'w') as json_file: diff --git a/pyproject.toml b/pyproject.toml index 11182462..1e5d1534 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,9 +28,10 @@ requires-poetry = ">=2.0" pytest = ">= 7.2.1" pytest-cov = ">= 2.8.1" tox = ">= 3.9.0" -flake8 = ">= 4.0.0" types-python-dateutil = ">= 2.8.19.14" mypy = ">= 1.5" +ruff = "== 0.15.0" +pre-commit = ">= 4.0.0" [build-system] @@ -74,4 +75,33 @@ disallow_untyped_calls = true disallow_incomplete_defs = true disallow_untyped_defs = true no_implicit_reexport = true -warn_return_any = true \ No newline at end of file +warn_return_any = true + +[tool.ruff] +line-length = 99 +target-version = "py39" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # Pyflakes + "I", # isort + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify +] +# UP007/UP045 require Python 3.10+, we target Python 3.9+ +# SIM108: ternary operators can reduce readability for longer expressions +ignore = ["UP007", "UP045", "SIM108"] + +[tool.ruff.lint.per-file-ignores] +# Generated files have long descriptions from OpenAPI spec +"fingerprint_server_sdk/models/*" = ["E501"] +"fingerprint_server_sdk/api/*" = ["E501"] + +[tool.ruff.format] +quote-style = "single" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" \ No newline at end of file diff --git a/run_checks.py b/run_checks.py index 6796efa9..3f4e5a69 100644 --- a/run_checks.py +++ b/run_checks.py @@ -2,37 +2,42 @@ import sys from dataclasses import dataclass from datetime import datetime, timedelta, timezone + from dotenv import load_dotenv -from typing import Tuple -from fingerprint_server_sdk import FingerprintApi, Configuration +from fingerprint_server_sdk import Configuration, FingerprintApi from fingerprint_server_sdk.configuration import Region from fingerprint_server_sdk.rest import ApiException + @dataclass(frozen=True) class AppConfig: api_key: str region: Region + def load_config() -> AppConfig: load_dotenv() - api_key = os.getenv("PRIVATE_KEY") + api_key = os.getenv('PRIVATE_KEY') if not api_key: - print("Error: PRIVATE_KEY environment variable not set", file=sys.stderr) + print('Error: PRIVATE_KEY environment variable not set', file=sys.stderr) sys.exit(1) - region_str = (os.getenv("REGION") or "us").upper() + region_str = (os.getenv('REGION') or 'us').upper() region = Region[region_str] return AppConfig(api_key=api_key, region=region) + def make_client(cfg: AppConfig) -> FingerprintApi: configuration = Configuration(api_key=cfg.api_key, region=cfg.region) return FingerprintApi(configuration) -def create_range(days: int) -> Tuple[int, int]: + +def create_range(days: int) -> tuple[int, int]: end = datetime.now(tz=timezone.utc) start = end - timedelta(days=days) return int(start.timestamp() * 1000), int(end.timestamp() * 1000) + def main() -> int: cfg = load_config() api = make_client(cfg) @@ -43,53 +48,54 @@ def main() -> int: try: search_events_response = api.search_events(2, start=start, end=end) if len(search_events_response.events) == 0: - print("FingerprintApi.search_events: is empty", file=sys.stderr) + print('FingerprintApi.search_events: is empty', file=sys.stderr) return 1 first_event = search_events_response.events[0] - visitor_id = first_event.identification.visitor_id event_id = first_event.event_id - print("\n\n\nSearch events response: \n", search_events_response) - search_events_response_second_page = api.search_events(2, start=start, end=end, - pagination_key=search_events_response.pagination_key) + print('\n\n\nSearch events response: \n', search_events_response) + search_events_response_second_page = api.search_events( + 2, start=start, end=end, pagination_key=search_events_response.pagination_key + ) if len(search_events_response_second_page.events) == 0: - print("Second page of FingerprintApi.search_events: is empty", file=sys.stderr) + print('Second page of FingerprintApi.search_events: is empty', file=sys.stderr) return 1 except ApiException as e: - print("Exception when calling FingerprintApi.search_events: %s\n" % e, file=sys.stderr) + print(f'Exception when calling FingerprintApi.search_events: {e}\n', file=sys.stderr) return 1 # Use existing event_id from FingerprintApi->search_events response to check get_event method try: event_response = api.get_event(event_id) - print("\n\n\nEvent response: \n", event_response) + print('\n\n\nEvent response: \n', event_response) except ApiException as e: - print("Exception when calling FingerprintApi.get_event: %s\n" % e, file=sys.stderr) + print(f'Exception when calling FingerprintApi.get_event: {e}\n', file=sys.stderr) return 1 # Check that old events are still match expected format try: search_events_response_old = api.search_events(1, start=start, end=end, reverse=True) if len(search_events_response_old.events) == 0: - print("FingerprintApi.search_events: is empty for old events\n", file=sys.stderr) + print('FingerprintApi.search_events: is empty for old events\n', file=sys.stderr) return 1 old_event = search_events_response_old.events[0] event_id_old = old_event.event_id if event_id_old == event_id: - print("Old events are identical to new\n", file=sys.stderr) + print('Old events are identical to new\n', file=sys.stderr) return 1 api.get_event(event_id_old) - print("\n\n\nOld events are good\n") + print('\n\n\nOld events are good\n') except ApiException as e: - print("Exception when trying to read old data: %s\n" % e, file=sys.stderr) + print(f'Exception when trying to read old data: {e}\n', file=sys.stderr) return 1 - print("Checks passed!") + print('Checks passed!') return 0 -if __name__ == "__main__": + +if __name__ == '__main__': sys.exit(main()) diff --git a/sealed_results_example.py b/sealed_results_example.py index 39bb627e..d9ec8f58 100644 --- a/sealed_results_example.py +++ b/sealed_results_example.py @@ -3,20 +3,22 @@ from dotenv import load_dotenv -from fingerprint_server_sdk.sealed import unseal_event_response, DecryptionKey, DecryptionAlgorithm +from fingerprint_server_sdk.sealed import DecryptionAlgorithm, DecryptionKey, unseal_event_response load_dotenv() -sealed_result = base64.b64decode(os.environ["BASE64_SEALED_RESULT"]) -key = base64.b64decode(os.environ["BASE64_KEY"]) +sealed_result = base64.b64decode(os.environ['BASE64_SEALED_RESULT']) +key = base64.b64decode(os.environ['BASE64_KEY']) try: - event_response = unseal_event_response(sealed_result, [DecryptionKey(key, DecryptionAlgorithm['Aes256Gcm'])]) - print("\n\n\nEvent response: \n", event_response) + event_response = unseal_event_response( + sealed_result, [DecryptionKey(key, DecryptionAlgorithm['Aes256Gcm'])] + ) + print('\n\n\nEvent response: \n', event_response) except Exception as e: - print("Exception when calling unsealing events response: %s\n" % e) + print(f'Exception when calling unsealing events response: {e}\n') exit(1) -print("Unseal successful!") +print('Unseal successful!') exit(0) diff --git a/setup.py b/setup.py index e9c39cb6..c561c552 100644 --- a/setup.py +++ b/setup.py @@ -1,19 +1,16 @@ -# coding: utf-8 - """ - Server API - - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. +Server API +Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. +Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. - The version of the OpenAPI document: 4 - Contact: support@fingerprint.com - Generated by OpenAPI Generator (https://openapi-generator.tech) +The version of the OpenAPI document: 4 +Contact: support@fingerprint.com +Generated by OpenAPI Generator (https://openapi-generator.tech) - Do not edit the class manually. +Do not edit the class manually. """ # noqa: E501 - -from setuptools import setup, find_packages # noqa: H301 +from setuptools import find_packages, setup # To install the library, run the following # @@ -21,32 +18,32 @@ # # prerequisite: setuptools # http://pypi.python.org/pypi/setuptools -NAME = "fingerprint-server-sdk" -VERSION = "8.11.0" -PYTHON_REQUIRES = ">= 3.9" +NAME = 'fingerprint-server-sdk' +VERSION = '8.11.0' +PYTHON_REQUIRES = '>= 3.9' REQUIRES = [ - "urllib3 >= 2.1.0, < 3.0.0", - "python-dateutil >= 2.8.2", - "pydantic >= 2", - "typing-extensions >= 4.7.1", - "cryptography", + 'urllib3 >= 2.1.0, < 3.0.0', + 'python-dateutil >= 2.8.2', + 'pydantic >= 2', + 'typing-extensions >= 4.7.1', + 'cryptography', ] setup( name=NAME, version=VERSION, - description="Server API", - author="Fingerprint Support", - author_email="support@fingerprint.com", - url="https://github.com/fingerprintjs/python-sdk", - keywords=["OpenAPI", "OpenAPI-Generator", "Server API"], + description='Server API', + author='Fingerprint Support', + author_email='support@fingerprint.com', + url='https://github.com/fingerprintjs/python-sdk', + keywords=['OpenAPI', 'OpenAPI-Generator', 'Server API'], install_requires=REQUIRES, - packages=find_packages(exclude=["test"]), + packages=find_packages(exclude=['test']), include_package_data=True, - license="MIT", + license='MIT', long_description_content_type='text/markdown', long_description="""\ - Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. + Fingerprint Server API allows you to get, search, and update Events in a server environment. It can be used for data exports, decision-making, and data analysis scenarios. Server API is intended for server-side usage, it's not intended to be used from the client side, whether it's a browser or a mobile device. """, # noqa: E501 - package_data={"fingerprint_server_sdk": ["py.typed"]}, -) \ No newline at end of file + package_data={'fingerprint_server_sdk': ['py.typed']}, +) diff --git a/template/__init__api.mustache b/template/__init__api.mustache index f3863e94..0579832f 100644 --- a/template/__init__api.mustache +++ b/template/__init__api.mustache @@ -1,4 +1,4 @@ -# flake8: noqa +# ruff: noqa: F401 {{^lazyImports}} {{>exports_api}} diff --git a/template/__init__model.mustache b/template/__init__model.mustache new file mode 100644 index 00000000..3bd9f46a --- /dev/null +++ b/template/__init__model.mustache @@ -0,0 +1,6 @@ +# ruff: noqa: E501, F401, I001 +{{>partial_header}} + +# import models into model package +{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} +{{/model}}{{/models}} diff --git a/template/__init__package.mustache b/template/__init__package.mustache index afd24e00..591e9898 100644 --- a/template/__init__package.mustache +++ b/template/__init__package.mustache @@ -1,11 +1,8 @@ -# coding: utf-8 - -# flake8: noqa +# ruff: noqa: E501, I001 {{>partial_header}} - -__version__ = "{{packageVersion}}" +__version__ = '{{packageVersion}}' # Define package exports __all__ = [ @@ -63,6 +60,11 @@ else: __import__('sys').setrecursionlimit({{{.}}}) {{/recursionLimit}} # import custom methods into sdk package +from {{packageName}}.sealed import ( + DecryptionAlgorithm, + DecryptionKey, + UnsealAggregateError, + UnsealError, + unseal_event_response, +) from {{packageName}}.webhook_validation import WebhookValidation -from {{packageName}}.sealed import DecryptionAlgorithm, DecryptionKey, \ - UnsealError, UnsealAggregateError, unseal_event_response diff --git a/template/api.mustache b/template/api.mustache index c93a0438..a195a106 100644 --- a/template/api.mustache +++ b/template/api.mustache @@ -1,21 +1,21 @@ -# coding: utf-8 - {{>partial_header}} -import warnings -from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt -from typing import Any, Dict, List, Optional, Tuple, Union +from typing import Any, Optional, Union # noqa: UP035 + +from pydantic import Field, StrictBool, StrictFloat, StrictInt, StrictStr, validate_call from typing_extensions import Annotated {{#imports}} {{import}} {{/imports}} - -from {{packageName}}.configuration import Configuration from {{packageName}}.api_client import ApiClient, RequestSerialized from {{packageName}}.api_response import ApiResponse +from {{packageName}}.configuration import Configuration from {{packageName}}.rest import RESTResponseType +# Type alias for query and form parameter values +ParamValue = Union[str, int, float, bool, list[str]] + {{#operations}} class {{classname}}: @@ -39,10 +39,18 @@ class {{classname}}: _request_timeout=_request_timeout ) {{#async}}await {{/async}}response_data.read() +{{#returnType}} return self.api_client.response_deserialize( response_data=response_data, response_types_map=_response_types_map, ).data +{{/returnType}} +{{^returnType}} + self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) +{{/returnType}} @validate_call @@ -74,25 +82,14 @@ class {{classname}}: def _{{operationId}}_serialize( self, {{#allParams}} - {{paramName}}, + {{paramName}}: {{^required}}Optional[{{/required}}{{{dataType}}}{{^required}}]{{/required}}, {{/allParams}} - _request_auth, - _content_type, - _headers, - _host_index, + _request_auth: Optional[dict[StrictStr, Any]], + _content_type: Optional[StrictStr], + _headers: Optional[dict[StrictStr, Any]], ) -> RequestSerialized: - {{#servers.0}} - _hosts = [{{#servers}} - '{{{url}}}'{{^-last}},{{/-last}}{{/servers}} - ] - _host = _hosts[_host_index] - {{/servers.0}} - {{^servers.0}} - _host = None - {{/servers.0}} - - _collection_formats: Dict[str, str] = { + _collection_formats: dict[str, str] = { {{#allParams}} {{#isArray}} '{{baseName}}': '{{collectionFormat}}', @@ -100,14 +97,15 @@ class {{classname}}: {{/allParams}} } - _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]]] + _path_params: dict[str, str] = {} + _query_params: list[tuple[str, ParamValue]] = [] + _header_params: dict[str, Optional[str]] = _headers or {} + _form_params: list[tuple[str, ParamValue]] = [] + _files: dict[ + str, + Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]], ] = {} - _body_params: Optional[bytes] = None + _body_params: Optional[Any] = None {{#pathParams}} # process the path parameters @@ -223,7 +221,7 @@ class {{classname}}: {{/hasConsumes}} # authentication setting - _auth_settings: List[str] = [{{#authMethods}} + _auth_settings: list[str] = [{{#authMethods}} '{{name}}'{{^-last}}, {{/-last}}{{/authMethods}} ] @@ -238,8 +236,7 @@ class {{classname}}: files=_files, auth_settings=_auth_settings, collection_formats=_collection_formats, - _host=_host, - _request_auth=_request_auth + _request_auth=_request_auth, ) diff --git a/template/api_client.mustache b/template/api_client.mustache index faa1a805..5fbc7f4f 100644 --- a/template/api_client.mustache +++ b/template/api_client.mustache @@ -1,11 +1,7 @@ -# coding: utf-8 - {{>partial_header}} - +from __future__ import annotations import datetime -from dateutil.parser import parse -from enum import Enum import decimal import json import mimetypes @@ -13,29 +9,32 @@ import os import re import tempfile import uuid - +from enum import Enum +from types import TracebackType +from typing import Any, Optional, Union from urllib.parse import quote -from typing import Tuple, Optional, List, Dict, Union, Any + +from dateutil.parser import parse from pydantic import SecretStr {{#tornado}} import tornado.gen {{/tornado}} -from {{packageName}}.configuration import Configuration -from {{packageName}}.api_response import ApiResponse, T as ApiResponseT import {{modelPackage}} -from {{packageName}} import rest, __version__ +from {{packageName}} import __version__, rest +from {{packageName}}.api_response import ApiResponse +from {{packageName}}.api_response import T as ApiResponseT +from {{packageName}}.configuration import Configuration from {{packageName}}.exceptions import ( - ApiValueError, ApiException, - BadRequestException, - UnauthorizedException, - ForbiddenException, - NotFoundException, - ServiceException + ApiValueError, ) -RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]] +RequestSerialized = tuple[str, str, dict[str, Any], Optional[Any], Any] +FilesType = dict[ + str, Union[str, bytes, list[str], list[bytes], tuple[str, bytes], list[tuple[str, bytes]]] +] + class ApiClient: """Generic API client for OpenAPI client library builds. @@ -56,7 +55,6 @@ class ApiClient: PRIMITIVE_TYPES = (float, bool, bytes, str, int) NATIVE_TYPES_MAPPING = { 'int': int, - 'long': int, # TODO remove as only py3 is supported? 'float': float, 'str': str, 'bool': bool, @@ -68,20 +66,20 @@ class ApiClient: def __init__( self, - configuration, - header_name=None, - header_value=None, - cookie=None + configuration: Configuration, + header_name: Optional[str] = None, + header_value: Optional[str] = None, + cookie: Optional[str] = None ) -> None: self.configuration = configuration self.rest_client = rest.RESTClientObject(configuration) - self.default_headers = {} - if header_name is not None: + self.default_headers: dict[str, str] = {} + if header_name is not None and header_value is not None: self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = '{{{httpUserAgent}}}{{^httpUserAgent}}fingerprint-server-python-sdk/{__version__}{{/httpUserAgent}}' + self.user_agent = {{#httpUserAgent}}'{{{httpUserAgent}}}'{{/httpUserAgent}}{{^httpUserAgent}}f'fingerprint-server-python-sdk/{__version__}'{{/httpUserAgent}} self.client_side_validation = configuration.client_side_validation {{#async}} @@ -95,40 +93,44 @@ class ApiClient: await self.rest_client.close() {{/async}} {{^async}} - def __enter__(self): + def __enter__(self) -> ApiClient: return self - def __exit__(self, exc_type, exc_value, traceback): + def __exit__( + self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + traceback: Optional[TracebackType], + ) -> None: pass {{/async}} @property - def user_agent(self) -> Optional[str]: + def user_agent(self) -> str: """User agent for this API client""" return self.default_headers['User-Agent'] @user_agent.setter - def user_agent(self, value: str): + def user_agent(self, value: str) -> None: self.default_headers['User-Agent'] = value - def set_default_header(self, header_name: str, header_value: str): + def set_default_header(self, header_name: str, header_value: str) -> None: self.default_headers[header_name] = header_value def param_serialize( self, - method, - resource_path, - path_params=None, - query_params=None, - header_params=None, - body=None, - post_params=None, - files=None, - auth_settings=None, - collection_formats=None, - _host=None, - _request_auth=None + method: str, + resource_path: str, + path_params: Optional[dict[str, Any]] = None, + query_params: Optional[list[tuple[str, Any]]] = None, + header_params: Optional[dict[str, Any]] = None, + body: Optional[Any] = None, + post_params: Optional[list[tuple[str, Any]]] = None, + files: Optional[FilesType] = None, + auth_settings: Optional[list[str]] = None, + collection_formats: Optional[dict[str, str]] = None, + _request_auth: Optional[dict[str, Any]] = None, ) -> RequestSerialized: """Builds the HTTP request params needed by the request. @@ -168,28 +170,26 @@ class ApiClient: # path parameters if path_params: - path_params = self.sanitize_for_serialization(path_params) - path_params = self.parameters_to_tuples( - path_params, - collection_formats + path_params_sanitized = self.sanitize_for_serialization(path_params) + path_params_tuples = self.parameters_to_tuples( + path_params_sanitized, collection_formats ) - for k, v in path_params: + for k, v in path_params_tuples: # specified safe chars, encode everything resource_path = resource_path.replace( - '{%s}' % k, - quote(str(v), safe=config.safe_chars_for_path_param) + '{' + k + '}', quote(str(v), safe=config.safe_chars_for_path_param) ) # post parameters + post_params_result: Any = None if post_params or files: - post_params = post_params if post_params else [] - post_params = self.sanitize_for_serialization(post_params) - post_params = self.parameters_to_tuples( - post_params, - collection_formats + post_params_list = post_params if post_params else [] + post_params_sanitized = self.sanitize_for_serialization(post_params_list) + post_params_result = self.parameters_to_tuples( + post_params_sanitized, collection_formats ) if files: - post_params.extend(self.files_parameters(files)) + post_params_result.extend(self.files_parameters(files)) # auth setting self.update_params_for_auth( @@ -207,11 +207,7 @@ class ApiClient: body = self.sanitize_for_serialization(body) # request url - if _host is None: - url = self.configuration.host + resource_path - else: - # use server/host defined in path or operation instead - url = _host + resource_path + url = self.configuration.host + resource_path query_params = list(query_params or []) if getattr(self.configuration, "default_query_params", None): @@ -229,7 +225,7 @@ class ApiClient: ) url += "?" + url_query - return method, url, header_params, body, post_params + return method, url, header_params, body, post_params_result {{#tornado}} @@ -239,10 +235,10 @@ class ApiClient: self, method: str, url: str, - header_params: Optional[Dict[str, Any]] = None, + header_params: Optional[dict[str, Any]] = None, body: Any = None, - post_params: Optional[List[Tuple[str, Any]]] = None, - _request_timeout: Optional[int] = None + post_params: Optional[list[Any]] = None, + _request_timeout: Optional[Union[int, float, tuple[float, float]]] = None, ) -> rest.RESTResponse: """Makes the HTTP request (synchronous) :param method: Method to call. @@ -275,7 +271,7 @@ class ApiClient: def response_deserialize( self, response_data: rest.RESTResponse, - response_types_map: Optional[Dict[str, ApiResponseT]]=None + response_types_map: Optional[dict[str, Any]] = None, ) -> ApiResponse[ApiResponseT]: """Deserializes response into an object. :param response_data: RESTResponse object to be deserialized. @@ -286,19 +282,21 @@ class ApiClient: msg = "RESTResponse.read() must be called before passing it to response_deserialize()" assert response_data.data is not None, msg - response_type = response_types_map.get(str(response_data.status), None) + if response_types_map is None: + response_types_map = {} + + response_type = response_types_map.get(str(response_data.status)) if ( not response_type and isinstance(response_data.status, int) and 100 <= response_data.status <= 599 ): # if not found, look for '1XX', '2XX', etc. - response_type = response_types_map.get( - str(response_data.status)[0] + "XX", None) + response_type = response_types_map.get(str(response_data.status)[0] + 'XX') # deserialize response data - response_text = None - return_data = None + response_text: Optional[str] = None + return_data: Any = None try: if response_type == "bytearray": return_data = response_data.data @@ -327,7 +325,7 @@ class ApiClient: raw_data = response_data.data ) - def sanitize_for_serialization(self, obj): + def sanitize_for_serialization(self, obj: Any) -> Any: """Builds a JSON POST object. If obj is None, return None. @@ -374,13 +372,14 @@ class ApiClient: # and attributes which value is not None. # Convert attribute name to json key in # model definition for request. - if hasattr(obj, 'to_dict') and callable(getattr(obj, 'to_dict')): + if hasattr(obj, 'to_dict') and callable(obj.to_dict): obj_dict = obj.to_dict() else: obj_dict = obj.__dict__ if isinstance(obj_dict, list): - # here we handle instances that can either be a list or something else, and only became a real list by calling to_dict() + # here we handle instances that can either be a list or something else, + # and only became a real list by calling to_dict() return self.sanitize_for_serialization(obj_dict) return { @@ -388,7 +387,9 @@ class ApiClient: for key, val in obj_dict.items() } - def deserialize(self, response_text: str, response_type: str, content_type: Optional[str]): + def deserialize( + self, response_text: str, response_type: str, content_type: Optional[str] + ) -> Any: """Deserializes response into an object. :param response: RESTResponse object to be deserialized. @@ -413,14 +414,11 @@ class ApiClient: elif re.match(r'^text\/[a-z.+-]+\s*(;|$)', content_type, re.IGNORECASE): data = response_text else: - raise ApiException( - status=0, - reason="Unsupported content type: {0}".format(content_type) - ) + raise ApiException(status=0, reason=f'Unsupported content type: {content_type}') return self.__deserialize(data, response_type) - def __deserialize(self, data, klass): + def __deserialize(self, data: Any, klass: Any) -> Any: """Deserializes dict, list, str into an object. :param data: dict, list or str. @@ -467,14 +465,18 @@ class ApiClient: else: return self.__deserialize_model(data, klass) - def parameters_to_tuples(self, params, collection_formats): + def parameters_to_tuples( + self, + params: Union[dict[str, Any], list[tuple[str, Any]]], + collection_formats: Optional[dict[str, str]], + ) -> list[tuple[str, str]]: """Get parameters as list of tuples, formatting collections. :param params: Parameters as dict or list of two-tuples :param dict collection_formats: Parameter collection formats :return: Parameters as list of tuples, collections formatted """ - new_params: List[Tuple[str, str]] = [] + new_params: list[tuple[str, str]] = [] if collection_formats is None: collection_formats = {} for k, v in params.items() if isinstance(params, dict) else params: @@ -497,14 +499,18 @@ class ApiClient: new_params.append((k, v)) return new_params - def parameters_to_url_query(self, params, collection_formats): + def parameters_to_url_query( + self, + params: Union[dict[str, Any], list[tuple[str, Any]]], + collection_formats: Optional[dict[str, str]], + ) -> str: """Get parameters as list of tuples, formatting collections. :param params: Parameters as dict or list of two-tuples :param dict collection_formats: Parameter collection formats :return: URL query string (e.g. a=Hello%20World&b=123) """ - new_params: List[Tuple[str, str]] = [] + new_params: list[tuple[str, str]] = [] if collection_formats is None: collection_formats = {} for k, v in params.items() if isinstance(params, dict) else params: @@ -538,8 +544,8 @@ class ApiClient: def files_parameters( self, - files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]], - ): + files: FilesType, + ) -> list[tuple[Any, Any]]: """Builds form parameters. :param files: File parameters. @@ -566,12 +572,10 @@ class ApiClient: mimetypes.guess_type(filename)[0] or 'application/octet-stream' ) - params.append( - tuple([k, tuple([filename, filedata, mimetype])]) - ) + params.append((k, (filename, filedata, mimetype))) return params - def select_header_accept(self, accepts: List[str]) -> Optional[str]: + def select_header_accept(self, accepts: list[str]) -> Optional[str]: """Returns `Accept` based on an array of accepts provided. :param accepts: List of headers. @@ -586,7 +590,7 @@ class ApiClient: return accepts[0] - def select_header_content_type(self, content_types): + def select_header_content_type(self, content_types: list[str]) -> Optional[str]: """Returns `Content-Type` based on an array of content_types provided. :param content_types: List of content-types. @@ -603,13 +607,13 @@ class ApiClient: def update_params_for_auth( self, - headers, - queries, - auth_settings, - resource_path, - method, - body, - request_auth=None + headers: dict[str, str], + queries: Optional[list[tuple[str, Any]]], + auth_settings: Optional[list[str]], + resource_path: str, + method: str, + body: Any, + request_auth: Optional[dict[str, Any]] = None, ) -> None: """Updates header and query params based on authentication setting. @@ -645,17 +649,17 @@ class ApiClient: resource_path, method, body, - auth_setting + auth_setting, # type: ignore[arg-type] ) def _apply_auth_params( self, - headers, - queries, - resource_path, - method, - body, - auth_setting + headers: dict[str, str], + queries: Optional[list[tuple[str, Any]]], + resource_path: str, + method: str, + body: Any, + auth_setting: dict[str, Any], ) -> None: """Updates the request parameters based on a single auth_setting @@ -682,13 +686,14 @@ class ApiClient: headers.update(auth_headers) {{/hasHttpSignatureMethods}} elif auth_setting['in'] == 'query': - queries.append((auth_setting['key'], auth_setting['value'])) + if queries is not None: + queries.append((auth_setting['key'], auth_setting['value'])) else: raise ApiValueError( 'Authentication token must be in `query` or `header`' ) - def __deserialize_file(self, response): + def __deserialize_file(self, response: rest.RESTResponse) -> Any: """Deserializes body to file Saves response body into a file in a temporary folder, @@ -700,7 +705,7 @@ class ApiClient: :param response: RESTResponse. :return: file path. """ - fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + fd, path = tempfile.mkstemp(dir=getattr(self.configuration, "temp_folder_path", None)) os.close(fd) os.remove(path) @@ -714,12 +719,13 @@ class ApiClient: filename = m.group(1) path = os.path.join(os.path.dirname(path), filename) - with open(path, "wb") as f: - f.write(response.data) + with open(path, 'wb') as f: + if response.data is not None: + f.write(response.data) return path - def __deserialize_primitive(self, data, klass): + def __deserialize_primitive(self, data: Any, klass: type) -> Any: """Deserializes string to primitive type. :param data: str. @@ -734,14 +740,14 @@ class ApiClient: except TypeError: return data - def __deserialize_object(self, value): + def __deserialize_object(self, value: Any) -> Any: """Return an original value. :return: object. """ return value - def __deserialize_date(self, string): + def __deserialize_date(self, string: str) -> datetime.date: """Deserializes string to date. :param string: str. @@ -750,14 +756,14 @@ class ApiClient: try: return parse(string).date() except ImportError: - return string - except ValueError: - raise rest.ApiException( + return string # type: ignore[return-value] + except ValueError as err: + raise ApiException( status=0, reason="Failed to parse `{0}` as date object".format(string) - ) + ) from err - def __deserialize_datetime(self, string): + def __deserialize_datetime(self, string: str) -> datetime.datetime: """Deserializes string to datetime. The string should be in iso8601 datetime format. @@ -768,17 +774,17 @@ class ApiClient: try: return parse(string) except ImportError: - return string - except ValueError: - raise rest.ApiException( + return string # type: ignore[return-value] + except ValueError as err: + raise ApiException( status=0, reason=( "Failed to parse `{0}` as datetime object" .format(string) ) - ) + ) from err - def __deserialize_enum(self, data, klass): + def __deserialize_enum(self, data: Any, klass: type[Enum]) -> Enum: """Deserializes primitive type to enum. :param data: primitive type. @@ -787,16 +793,16 @@ class ApiClient: """ try: return klass(data) - except ValueError: - raise rest.ApiException( + except ValueError as err: + raise ApiException( status=0, reason=( "Failed to parse `{0}` as `{1}`" .format(data, klass) ) - ) + ) from err - def __deserialize_model(self, data, klass): + def __deserialize_model(self, data: Any, klass: Any) -> Any: """Deserializes list or dict to model. :param data: dict, list. diff --git a/template/configuration.mustache b/template/configuration.mustache index c1885113..27158011 100644 --- a/template/configuration.mustache +++ b/template/configuration.mustache @@ -1,24 +1,22 @@ -# coding: utf-8 - {{>partial_header}} - {{#async}} import base64 {{/async}} import copy import http.client as httplib import logging -from logging import FileHandler {{^async}} import multiprocessing {{/async}} import sys -from typing import Any, ClassVar, Dict, List, Literal, Optional, TypedDict, Union, Tuple -from typing_extensions import NotRequired, Self -from {{packageName}} import __version__ from enum import Enum +from logging import FileHandler +from typing import Any, ClassVar, Literal, Optional, TypedDict, Union + +from typing_extensions import Self +from {{packageName}} import __version__ {{#hasHttpSignatureMethods}} from {{packageName}}.signing import HttpSigningConfiguration {{/hasHttpSignatureMethods}} @@ -29,7 +27,7 @@ JSON_SCHEMA_VALIDATION_KEYWORDS = { 'minLength', 'pattern', 'maxItems', 'minItems' } -ServerVariablesT = Dict[str, str] +ServerVariablesT = dict[str, str] BearerFormatAuthSetting = TypedDict( "BearerFormatAuthSetting", @@ -42,6 +40,7 @@ BearerFormatAuthSetting = TypedDict( }, ) + AuthSettings = TypedDict( "AuthSettings", { @@ -74,18 +73,6 @@ AuthSettings = TypedDict( ) -class HostSettingVariable(TypedDict): - description: str - default_value: str - enum_values: List[str] - - -class HostSetting(TypedDict): - url: str - description: str - variables: NotRequired[Dict[str, HostSettingVariable]] - - class Region(Enum): US = "us" EU = "eu" @@ -112,11 +99,11 @@ class Configuration: self, api_key: str, region: Region = Region.US, - host: Optional[str]=None, - ssl_ca_cert: Optional[str]=None, + host: Optional[str] = None, + ssl_ca_cert: Optional[str] = None, retries: Optional[int] = None, ca_cert_data: Optional[Union[str, bytes]] = None, - default_query_params: Optional[List[Tuple[str, str]]] = None, + default_query_params: Optional[list[tuple[str, str]]] = None, *, debug: Optional[bool] = None, ) -> None: @@ -224,12 +211,13 @@ class Configuration: """date format """ - if default_query_params: - self.default_query_params = default_query_params - else: - self.default_query_params: List[Tuple[str, str]] = [("ii", f"fingerprint-server-python-sdk/{__version__}")] + self.default_query_params: list[tuple[str, str]] = ( + default_query_params + if default_query_params + else [("ii", f"fingerprint-server-python-sdk/{__version__}")] + ) - def __deepcopy__(self, memo: Dict[int, Any]) -> Self: + def __deepcopy__(self, memo: dict[int, Any]) -> Self: cls = self.__class__ result = cls.__new__(cls) memo[id(self)] = result diff --git a/template/exceptions.mustache b/template/exceptions.mustache index 2a1d60ab..454cb056 100644 --- a/template/exceptions.mustache +++ b/template/exceptions.mustache @@ -1,17 +1,27 @@ -# coding: utf-8 - {{>partial_header}} +from __future__ import annotations + +import contextlib +from typing import TYPE_CHECKING, Any, Optional -from typing import Any, Optional from typing_extensions import Self +if TYPE_CHECKING: + from {{packageName}}.rest import RESTResponse + + class OpenApiException(Exception): """The base exception class for all OpenAPIExceptions""" class ApiTypeError(OpenApiException, TypeError): - def __init__(self, msg, path_to_item=None, valid_classes=None, - key_type=None) -> None: + def __init__( + self, + msg: str, + path_to_item: Optional[list[Any]] = None, + valid_classes: Optional[tuple[type, ...]] = None, + key_type: Optional[bool] = None, + ) -> None: """ Raises an exception for TypeErrors Args: @@ -35,11 +45,11 @@ class ApiTypeError(OpenApiException, TypeError): full_msg = msg if path_to_item: full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiTypeError, self).__init__(full_msg) + super().__init__(full_msg) class ApiValueError(OpenApiException, ValueError): - def __init__(self, msg, path_to_item=None) -> None: + def __init__(self, msg: str, path_to_item: Optional[list[Any]] = None) -> None: """ Args: msg (str): the exception message @@ -53,11 +63,11 @@ class ApiValueError(OpenApiException, ValueError): full_msg = msg if path_to_item: full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiValueError, self).__init__(full_msg) + super().__init__(full_msg) class ApiAttributeError(OpenApiException, AttributeError): - def __init__(self, msg, path_to_item=None) -> None: + def __init__(self, msg: str, path_to_item: Optional[list[Any]] = None) -> None: """ Raised when an attribute reference or assignment fails. @@ -72,11 +82,11 @@ class ApiAttributeError(OpenApiException, AttributeError): full_msg = msg if path_to_item: full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiAttributeError, self).__init__(full_msg) + super().__init__(full_msg) class ApiKeyError(OpenApiException, KeyError): - def __init__(self, msg, path_to_item=None) -> None: + def __init__(self, msg: str, path_to_item: Optional[list[Any]] = None) -> None: """ Args: msg (str): the exception message @@ -89,16 +99,15 @@ class ApiKeyError(OpenApiException, KeyError): full_msg = msg if path_to_item: full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiKeyError, self).__init__(full_msg) + super().__init__(full_msg) class ApiException(OpenApiException): - def __init__( self, - status=None, - reason=None, - http_resp=None, + status: Optional[int] = None, + reason: Optional[str] = None, + http_resp: Optional["RESTResponse"] = None, *, body: Optional[str] = None, data: Optional[Any] = None, @@ -114,18 +123,16 @@ class ApiException(OpenApiException): self.status = http_resp.status if self.reason is None: self.reason = http_resp.reason - if self.body is None: - try: + if self.body is None and http_resp.data is not None: + with contextlib.suppress(UnicodeDecodeError): self.body = http_resp.data.decode('utf-8') - except Exception: - pass self.headers = http_resp.headers @classmethod def from_response( cls, *, - http_resp, + http_resp: RESTResponse, body: Optional[str], data: Optional[Any], ) -> Self: @@ -155,7 +162,7 @@ class ApiException(OpenApiException): raise ServiceException(http_resp=http_resp, body=body, data=data) raise ApiException(http_resp=http_resp, body=body, data=data) - def __str__(self): + def __str__(self) -> str: """Custom error messages for exception""" error_message = "({0})\n"\ "Reason: {1}\n".format(self.status, self.reason) @@ -207,7 +214,7 @@ class TooManyRequestsException(ApiException): pass -def render_path(path_to_item): +def render_path(path_to_item: list[Any]) -> str: """Returns a string representation of a path""" result = "" for pth in path_to_item: diff --git a/template/model.mustache b/template/model.mustache new file mode 100644 index 00000000..d2d61f21 --- /dev/null +++ b/template/model.mustache @@ -0,0 +1,12 @@ +{{>partial_header}} + +{{#models}} +{{#model}} +{{#isEnum}} +{{>model_enum}} +{{/isEnum}} +{{^isEnum}} +{{#oneOf}}{{#-first}}{{>model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}}{{#anyOf}}{{#-first}}{{>model_anyof}}{{/-first}}{{/anyOf}}{{^anyOf}}{{>model_generic}}{{/anyOf}}{{/oneOf}} +{{/isEnum}} +{{/model}} +{{/models}} diff --git a/template/model_generic.mustache b/template/model_generic.mustache new file mode 100644 index 00000000..40a04841 --- /dev/null +++ b/template/model_generic.mustache @@ -0,0 +1,405 @@ +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Optional + +{{#vendorExtensions.x-py-other-imports}} +{{{.}}} +{{/vendorExtensions.x-py-other-imports}} +{{#vendorExtensions.x-py-model-imports}} +{{{.}}} +{{/vendorExtensions.x-py-model-imports}} +from typing_extensions import Self + +{{#hasChildren}} +{{#discriminator}} +{{! If this model is a super class, importlib is used. So import the necessary modules for the type here. }} +from typing import TYPE_CHECKING +if TYPE_CHECKING: +{{#mappedModels}} + from {{packageName}}.models.{{model.classFilename}} import {{modelName}} +{{/mappedModels}} + +{{/discriminator}} +{{/hasChildren}} + +class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}): + """ + {{#description}}{{{description}}}{{/description}}{{^description}}{{{classname}}}{{/description}} + """ + +{{#vars}} + {{name}}: {{{vendorExtensions.x-py-typing}}} +{{/vars}} +{{#isAdditionalPropertiesTrue}} + additional_properties: dict[str, Any] = {} +{{/isAdditionalPropertiesTrue}} + __properties: ClassVar[list[str]] = [{{#allVars}}'{{baseName}}'{{^-last}}, {{/-last}}{{/allVars}}] +{{#vars}} + {{#vendorExtensions.x-regex}} + + @field_validator('{{{name}}}') + def {{{name}}}_validate_regular_expression(cls, value: Any) -> Any: + """Validates the regular expression""" + {{^required}} + if value is None: + return value + + {{/required}} + {{#required}} + {{#isNullable}} + if value is None: + return value + + {{/isNullable}} + {{/required}} + if not re.match(r"{{{.}}}", value{{#vendorExtensions.x-modifiers}} ,re.{{{.}}}{{/vendorExtensions.x-modifiers}}): + raise ValueError(r"must validate the regular expression {{{vendorExtensions.x-pattern}}}") + return value + {{/vendorExtensions.x-regex}} + {{#isEnum}} + + @field_validator('{{{name}}}') + def {{{name}}}_validate_enum(cls, value: Any) -> Any: + """Validates the enum""" + {{^required}} + if value is None: + return value + + {{/required}} + {{#required}} + {{#isNullable}} + if value is None: + return value + + {{/isNullable}} + {{/required}} + {{#isContainer}} + {{#isArray}} + for i in value: + if i not in set([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]): + raise ValueError("each list item must be one of ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})") + {{/isArray}} + {{#isMap}} + for i in value.values(): + if i not in set([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]): + raise ValueError("dict values must be one of enum values ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})") + {{/isMap}} + {{/isContainer}} + {{^isContainer}} + if value not in set([{{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}}]): + raise ValueError("must be one of enum values ({{#allowableValues}}{{#enumVars}}{{{value}}}{{^-last}}, {{/-last}}{{/enumVars}}{{/allowableValues}})") + {{/isContainer}} + return value + {{/isEnum}} +{{/vars}} + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + +{{#hasChildren}} +{{#discriminator}} + # JSON field name that stores the object type + __discriminator_property_name: ClassVar[str] = '{{discriminator.propertyBaseName}}' + + # discriminator mappings + __discriminator_value_class_map: ClassVar[dict[str, str]] = { + {{#mappedModels}}'{{{mappingName}}}': '{{{modelName}}}'{{^-last}},{{/-last}}{{/mappedModels}} + } + + @classmethod + def get_discriminator_value(cls, obj: dict[str, Any]) -> Optional[str]: + """Returns the discriminator value (object type) of the data""" + discriminator_value = obj[cls.__discriminator_property_name] + if discriminator_value: + return cls.__discriminator_value_class_map.get(discriminator_value) + else: + return None + +{{/discriminator}} +{{/hasChildren}} + 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[{{^hasChildren}}Self{{/hasChildren}}{{#hasChildren}}{{#discriminator}}Union[{{#mappedModels}}{{{modelName}}}{{^-last}}, {{/-last}}{{/mappedModels}}]{{/discriminator}}{{^discriminator}}Self{{/discriminator}}{{/hasChildren}}]: + """Create an instance of {{{classname}}} 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. + {{#vendorExtensions.x-py-readonly}} + * OpenAPI `readOnly` fields are excluded. + {{/vendorExtensions.x-py-readonly}} + {{#isAdditionalPropertiesTrue}} + * Fields in `self.additional_properties` are added to the output dict. + {{/isAdditionalPropertiesTrue}} + """ + excluded_fields: set[str] = set([ + {{#vendorExtensions.x-py-readonly}} + "{{{.}}}", + {{/vendorExtensions.x-py-readonly}} + {{#isAdditionalPropertiesTrue}} + "additional_properties", + {{/isAdditionalPropertiesTrue}} + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + {{#allVars}} + {{#isContainer}} + {{#isArray}} + {{#items.isArray}} + {{^items.items.isPrimitiveType}} + # override the default output from pydantic by calling `to_dict()` of each item in {{{name}}} (list of list) + _items = [] + if self.{{{name}}}: + for _item_{{{name}}} in self.{{{name}}}: + if _item_{{{name}}}: + _items.append( + [_inner_item.to_dict() for _inner_item in _item_{{{name}}} if _inner_item is not None] + ) + _dict['{{{baseName}}}'] = _items + {{/items.items.isPrimitiveType}} + {{/items.isArray}} + {{^items.isArray}} + {{^items.isPrimitiveType}} + {{^items.isEnumOrRef}} + # override the default output from pydantic by calling `to_dict()` of each item in {{{name}}} (list) + _items = [] + if self.{{{name}}}: + for _item_{{{name}}} in self.{{{name}}}: + if _item_{{{name}}}: + _items.append(_item_{{{name}}}.to_dict()) + _dict['{{{baseName}}}'] = _items + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{/items.isArray}} + {{/isArray}} + {{#isMap}} + {{#items.isArray}} + {{^items.items.isPrimitiveType}} + # override the default output from pydantic by calling `to_dict()` of each value in {{{name}}} (dict of array) + _field_dict_of_array = {} + if self.{{{name}}}: + for _key_{{{name}}} in self.{{{name}}}: + if self.{{{name}}}[_key_{{{name}}}] is not None: + _field_dict_of_array[_key_{{{name}}}] = [ + _item.to_dict() for _item in self.{{{name}}}[_key_{{{name}}}] + ] + _dict['{{{baseName}}}'] = _field_dict_of_array + {{/items.items.isPrimitiveType}} + {{/items.isArray}} + {{^items.isArray}} + {{^items.isPrimitiveType}} + {{^items.isEnumOrRef}} + # override the default output from pydantic by calling `to_dict()` of each value in {{{name}}} (dict) + _field_dict = {} + if self.{{{name}}}: + for _key_{{{name}}} in self.{{{name}}}: + if self.{{{name}}}[_key_{{{name}}}]: + _field_dict[_key_{{{name}}}] = self.{{{name}}}[_key_{{{name}}}].to_dict() + _dict['{{{baseName}}}'] = _field_dict + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{/items.isArray}} + {{/isMap}} + {{/isContainer}} + {{^isContainer}} + {{^isPrimitiveType}} + {{^isEnumOrRef}} + # override the default output from pydantic by calling `to_dict()` of {{{name}}} + if self.{{{name}}}: + _dict['{{{baseName}}}'] = self.{{{name}}}.to_dict() + {{/isEnumOrRef}} + {{/isPrimitiveType}} + {{/isContainer}} + {{/allVars}} + {{#isAdditionalPropertiesTrue}} + # 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 + + {{/isAdditionalPropertiesTrue}} + {{#allVars}} + {{#isNullable}} + # set to None if {{{name}}} (nullable) is None + # and model_fields_set contains the field + if self.{{name}} is None and "{{{name}}}" in self.model_fields_set: + _dict['{{{baseName}}}'] = None + + {{/isNullable}} + {{/allVars}} + return _dict + + {{#hasChildren}} + @classmethod + def from_dict(cls, obj: dict[str, Any]) -> Optional[{{#discriminator}}Union[{{#mappedModels}}{{{modelName}}}{{^-last}}, {{/-last}}{{/mappedModels}}]{{/discriminator}}{{^discriminator}}Self{{/discriminator}}]: + """Create an instance of {{{classname}}} from a dict""" + {{#discriminator}} + # look up the object type based on discriminator mapping + object_type = cls.get_discriminator_value(obj) + {{#mappedModels}} + if object_type == '{{{modelName}}}': + return import_module("{{packageName}}.models.{{model.classFilename}}").{{modelName}}.from_dict(obj) + {{/mappedModels}} + + raise ValueError("{{{classname}}} failed to lookup discriminator value from " + + json.dumps(obj) + ". Discriminator property name: " + cls.__discriminator_property_name + + ", mapping: " + json.dumps(cls.__discriminator_value_class_map)) + {{/discriminator}} + {{/hasChildren}} + {{^hasChildren}} + @classmethod + def from_dict(cls, obj: Optional[dict[str, Any]]) -> Optional[Self]: + """Create an instance of {{{classname}}} from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + {{#disallowAdditionalPropertiesIfNotPresent}} + {{^isAdditionalPropertiesTrue}} + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in {{classname}}) in the input: " + _key) + + {{/isAdditionalPropertiesTrue}} + {{/disallowAdditionalPropertiesIfNotPresent}} + _obj = cls.model_validate({ + {{#allVars}} + {{#isContainer}} + {{#isArray}} + {{#items.isArray}} + {{#items.items.isPrimitiveType}} + "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{/items.items.isPrimitiveType}} + {{^items.items.isPrimitiveType}} + "{{{baseName}}}": [ + [{{{items.items.dataType}}}.from_dict(_inner_item) for _inner_item in _item] + for _item in obj["{{{baseName}}}"] + ] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{/items.items.isPrimitiveType}} + {{/items.isArray}} + {{^items.isArray}} + {{^items.isPrimitiveType}} + {{#items.isEnumOrRef}} + "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{/items.isEnumOrRef}} + {{^items.isEnumOrRef}} + "{{{baseName}}}": [{{{items.dataType}}}.from_dict(_item) for _item in obj["{{{baseName}}}"]] if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{#items.isPrimitiveType}} + "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{/items.isPrimitiveType}} + {{/items.isArray}} + {{/isArray}} + {{#isMap}} + {{^items.isPrimitiveType}} + {{^items.isEnumOrRef}} + {{#items.isContainer}} + {{#items.isMap}} + "{{{baseName}}}": dict( + (_k, dict( + (_ik, {{{items.items.dataType}}}.from_dict(_iv)) + for _ik, _iv in _v.items() + ) + if _v is not None + else None + ) + for _k, _v in obj.get("{{{baseName}}}").items() + ) + if obj.get("{{{baseName}}}") is not None + else None{{^-last}},{{/-last}} + {{/items.isMap}} + {{#items.isArray}} + "{{{baseName}}}": dict( + (_k, + [{{{items.items.dataType}}}.from_dict(_item) for _item in _v] + if _v is not None + else None + ) + for _k, _v in obj.get("{{{baseName}}}", {}).items() + ){{^-last}},{{/-last}} + {{/items.isArray}} + {{/items.isContainer}} + {{^items.isContainer}} + "{{{baseName}}}": dict( + (_k, {{{items.dataType}}}.from_dict(_v)) + for _k, _v in obj["{{{baseName}}}"].items() + ) + if obj.get("{{{baseName}}}") is not None + else None{{^-last}},{{/-last}} + {{/items.isContainer}} + {{/items.isEnumOrRef}} + {{#items.isEnumOrRef}} + "{{{baseName}}}": dict((_k, _v) for _k, _v in obj.get("{{{baseName}}}").items()) if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{/items.isEnumOrRef}} + {{/items.isPrimitiveType}} + {{#items.isPrimitiveType}} + "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{/items.isPrimitiveType}} + {{/isMap}} + {{/isContainer}} + {{^isContainer}} + {{^isPrimitiveType}} + {{^isEnumOrRef}} + "{{{baseName}}}": {{{dataType}}}.from_dict(obj["{{{baseName}}}"]) if obj.get("{{{baseName}}}") is not None else None{{^-last}},{{/-last}} + {{/isEnumOrRef}} + {{#isEnumOrRef}} + "{{{baseName}}}": obj.get("{{{baseName}}}"){{#defaultValue}} if obj.get("{{baseName}}") is not None else {{{defaultValue}}}{{/defaultValue}}{{^-last}},{{/-last}} + {{/isEnumOrRef}} + {{/isPrimitiveType}} + {{#isPrimitiveType}} + {{#defaultValue}} + "{{{baseName}}}": obj.get("{{{baseName}}}") if obj.get("{{{baseName}}}") is not None else {{{defaultValue}}}{{^-last}},{{/-last}} + {{/defaultValue}} + {{^defaultValue}} + "{{{baseName}}}": obj.get("{{{baseName}}}"){{^-last}},{{/-last}} + {{/defaultValue}} + {{/isPrimitiveType}} + {{/isContainer}} + {{/allVars}} + }) + {{#isAdditionalPropertiesTrue}} + # store additional fields in additional_properties + for _key in obj: + if _key not in cls.__properties: + _obj.additional_properties[_key] = obj.get(_key) + + {{/isAdditionalPropertiesTrue}} + return _obj + {{/hasChildren}} + +{{#vendorExtensions.x-py-postponed-model-imports.size}} +{{#vendorExtensions.x-py-postponed-model-imports}} +{{{.}}} +{{/vendorExtensions.x-py-postponed-model-imports}} +# TODO: Rewrite to not use raise_errors +{{classname}}.model_rebuild(raise_errors=False) +{{/vendorExtensions.x-py-postponed-model-imports.size}} diff --git a/template/model_oneof.mustache b/template/model_oneof.mustache new file mode 100644 index 00000000..958812d7 --- /dev/null +++ b/template/model_oneof.mustache @@ -0,0 +1,208 @@ +from __future__ import annotations +import json +import pprint +from typing import Any, Optional, Union +{{#vendorExtensions.x-py-other-imports}} +{{{.}}} +{{/vendorExtensions.x-py-other-imports}} +{{#vendorExtensions.x-py-model-imports}} +{{{.}}} +{{/vendorExtensions.x-py-model-imports}} +from typing_extensions import Self + +{{#lambda.uppercase}}{{{classname}}}{{/lambda.uppercase}}_ONE_OF_SCHEMAS = [{{#oneOf}}"{{.}}"{{^-last}}, {{/-last}}{{/oneOf}}] + +class {{classname}}({{#parent}}{{{.}}}{{/parent}}{{^parent}}BaseModel{{/parent}}): + """ + {{{description}}}{{^description}}{{{classname}}}{{/description}} + """ +{{#composedSchemas.oneOf}} + # data type: {{{dataType}}} + {{vendorExtensions.x-py-name}}: {{{vendorExtensions.x-py-typing}}} +{{/composedSchemas.oneOf}} + actual_instance: Optional[Union[{{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}]] = None + one_of_schemas: set[str] = { {{#oneOf}}"{{.}}"{{^-last}}, {{/-last}}{{/oneOf}} } + + model_config = ConfigDict( + validate_assignment=True, + protected_namespaces=(), + ) + +{{#discriminator}} + + discriminator_value_class_map: dict[str, str] = { +{{#children}} + '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},{{/-last}} +{{/children}} + } +{{/discriminator}} + + def __init__(self, *args: Any, **kwargs: Any) -> None: + if args: + if len(args) > 1: + raise ValueError("If a position argument is used, only 1 is allowed to set `actual_instance`") + if kwargs: + raise ValueError("If a position argument is used, keyword arguments cannot be used.") + super().__init__(actual_instance=args[0]) + else: + super().__init__(**kwargs) + + @field_validator('actual_instance') + def actual_instance_must_validate_oneof(cls, v: Any) -> Any: + {{#isNullable}} + if v is None: + return v + + {{/isNullable}} + {{{classname}}}.model_construct() + error_messages = [] + match = 0 + {{#composedSchemas.oneOf}} + # validate data type: {{{dataType}}} + {{#isContainer}} + try: + instance.{{vendorExtensions.x-py-name}} = v + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + {{/isContainer}} + {{^isContainer}} + {{#isPrimitiveType}} + try: + instance.{{vendorExtensions.x-py-name}} = v + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + {{/isPrimitiveType}} + {{^isPrimitiveType}} + if not isinstance(v, {{{dataType}}}): + error_messages.append(f"Error! Input type `{type(v)}` is not `{{{dataType}}}`") + else: + match += 1 + {{/isPrimitiveType}} + {{/isContainer}} + {{/composedSchemas.oneOf}} + if match > 1: + # more than 1 match + raise ValueError("Multiple matches found when setting `actual_instance` in {{{classname}}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. Details: " + ", ".join(error_messages)) + elif match == 0: + # no match + raise ValueError("No match found when setting `actual_instance` in {{{classname}}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. Details: " + ", ".join(error_messages)) + else: + return v + + @classmethod + def from_dict(cls, obj: Union[str, dict[str, Any]]) -> Self: + return cls.from_json(json.dumps(obj)) + + @classmethod + {{#isNullable}} + def from_json(cls, json_str: Optional[str]) -> Self: + {{/isNullable}} + {{^isNullable}} + def from_json(cls, json_str: str) -> Self: + {{/isNullable}} + """Returns the object represented by the json string""" + instance = cls.model_construct() + {{#isNullable}} + if json_str is None: + return instance + + {{/isNullable}} + error_messages = [] + match = 0 + + {{#useOneOfDiscriminatorLookup}} + {{#discriminator}} + {{#mappedModels}} + {{#-first}} + # use oneOf discriminator to lookup the data type + _data_type = json.loads(json_str).get("{{{propertyBaseName}}}") + if not _data_type: + raise ValueError("Failed to lookup data type from the field `{{{propertyBaseName}}}` in the input.") + + {{/-first}} + # check if data type is `{{{modelName}}}` + if _data_type == "{{{mappingName}}}": + instance.actual_instance = {{{modelName}}}.from_json(json_str) + return instance + + {{/mappedModels}} + {{/discriminator}} + {{/useOneOfDiscriminatorLookup}} + {{#composedSchemas.oneOf}} + {{#isContainer}} + # deserialize data into {{{dataType}}} + try: + # validation + instance.{{vendorExtensions.x-py-name}} = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.{{vendorExtensions.x-py-name}} + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + {{/isContainer}} + {{^isContainer}} + {{#isPrimitiveType}} + # deserialize data into {{{dataType}}} + try: + # validation + instance.{{vendorExtensions.x-py-name}} = json.loads(json_str) + # assign value to actual_instance + instance.actual_instance = instance.{{vendorExtensions.x-py-name}} + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + {{/isPrimitiveType}} + {{^isPrimitiveType}} + # deserialize data into {{{dataType}}} + try: + instance.actual_instance = {{{dataType}}}.from_json(json_str) + match += 1 + except (ValidationError, ValueError) as e: + error_messages.append(str(e)) + {{/isPrimitiveType}} + {{/isContainer}} + {{/composedSchemas.oneOf}} + + if match > 1: + # more than 1 match + raise ValueError("Multiple matches found when deserializing the JSON string into {{{classname}}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. Details: " + ", ".join(error_messages)) + elif match == 0: + # no match + raise ValueError("No match found when deserializing the JSON string into {{{classname}}} with oneOf schemas: {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}. Details: " + ", ".join(error_messages)) + else: + return instance + + def to_json(self) -> str: + """Returns the JSON representation of the actual instance""" + if self.actual_instance is None: + return "null" + + if hasattr(self.actual_instance, "to_json") and callable(self.actual_instance.to_json): + return self.actual_instance.to_json() + else: + return json.dumps(self.actual_instance) + + def to_dict(self) -> Optional[Union[dict[str, Any], {{#oneOf}}{{{.}}}{{^-last}}, {{/-last}}{{/oneOf}}]]: + """Returns the dict representation of the actual instance""" + if self.actual_instance is None: + return None + + if hasattr(self.actual_instance, "to_dict") and callable(self.actual_instance.to_dict): + return self.actual_instance.to_dict() + else: + # primitive type + return self.actual_instance + + def to_str(self) -> str: + """Returns the string representation of the actual instance""" + return pprint.pformat(self.model_dump()) + +{{#vendorExtensions.x-py-postponed-model-imports.size}} +{{#vendorExtensions.x-py-postponed-model-imports}} +{{{.}}} +{{/vendorExtensions.x-py-postponed-model-imports}} +# TODO: Rewrite to not use raise_errors +{{classname}}.model_rebuild(raise_errors=False) +{{/vendorExtensions.x-py-postponed-model-imports.size}} diff --git a/template/partial_api.mustache b/template/partial_api.mustache new file mode 100644 index 00000000..25c272e0 --- /dev/null +++ b/template/partial_api.mustache @@ -0,0 +1,47 @@ + """{{#isDeprecated}}(Deprecated) {{/isDeprecated}}{{{summary}}}{{^summary}}{{operationId}}{{/summary}} + + {{#notes}} + {{{.}}} + {{/notes}} + + {{#allParams}} + :param {{paramName}}:{{#description}} {{{.}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} + :type {{paramName}}: {{dataType}}{{#optional}}, optional{{/optional}} + {{/allParams}} + :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 + :return: Returns the result object. + """ # noqa: E501 + {{#isDeprecated}} + warnings.warn("{{{httpMethod}}} {{{path}}} is deprecated.", DeprecationWarning) + {{/isDeprecated}} + + _param = self._{{operationId}}_serialize( + {{#allParams}} + {{paramName}}={{paramName}}, + {{/allParams}} + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + ) + + _response_types_map: dict[str, Optional[str]] = { + {{#responses}} + {{^isWildcard}} + '{{code}}': {{#dataType}}"{{.}}"{{/dataType}}{{^dataType}}None{{/dataType}}, + {{/isWildcard}} + {{/responses}} + } diff --git a/template/partial_api_args.mustache b/template/partial_api_args.mustache new file mode 100644 index 00000000..21eea6ed --- /dev/null +++ b/template/partial_api_args.mustache @@ -0,0 +1,17 @@ +( + self, + {{#allParams}} + {{paramName}}: {{{vendorExtensions.x-py-typing}}}{{^required}} = None{{/required}}, + {{/allParams}} + _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, + ) \ No newline at end of file diff --git a/template/partial_header.mustache b/template/partial_header.mustache new file mode 100644 index 00000000..32e17b49 --- /dev/null +++ b/template/partial_header.mustache @@ -0,0 +1,17 @@ +""" +{{#appName}} +{{{.}}} +{{/appName}} +{{#appDescription}} +{{{appDescriptionWithNewLines}}} +{{/appDescription}} +{{#version}} +The version of the OpenAPI document: {{{.}}} +{{/version}} +{{#infoEmail}} +Contact: {{{.}}} +{{/infoEmail}} +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 \ No newline at end of file diff --git a/template/pyproject.mustache b/template/pyproject.mustache index 07d3d0fa..f84df07e 100644 --- a/template/pyproject.mustache +++ b/template/pyproject.mustache @@ -107,9 +107,10 @@ requires-poetry = ">=2.0" pytest = ">= 7.2.1" pytest-cov = ">= 2.8.1" tox = ">= 3.9.0" -flake8 = ">= 4.0.0" types-python-dateutil = ">= 2.8.19.14" mypy = ">= 1.5" +ruff = "== 0.15.0" +pre-commit = ">= 4.0.0" [build-system] @@ -153,4 +154,33 @@ disallow_untyped_calls = true disallow_incomplete_defs = true disallow_untyped_defs = true no_implicit_reexport = true -warn_return_any = true \ No newline at end of file +warn_return_any = true + +[tool.ruff] +line-length = 99 +target-version = "py39" + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # Pyflakes + "I", # isort + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify +] +# UP007/UP045 require Python 3.10+, we target Python 3.9+ +# SIM108: ternary operators can reduce readability for longer expressions +ignore = ["UP007", "UP045", "SIM108"] + +[tool.ruff.lint.per-file-ignores] +# Generated files have long descriptions from OpenAPI spec +"{{{packageName}}}/models/*" = ["E501"] +"{{{packageName}}}/api/*" = ["E501"] + +[tool.ruff.format] +quote-style = "single" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" \ No newline at end of file diff --git a/template/rest.mustache b/template/rest.mustache new file mode 100644 index 00000000..6aae24de --- /dev/null +++ b/template/rest.mustache @@ -0,0 +1,254 @@ +{{>partial_header}} +from __future__ import annotations + +import io +import json +import re +import ssl +from typing import TYPE_CHECKING, Any, Optional, Union + +import urllib3 + +from {{packageName}}.exceptions import ApiException, ApiValueError + +if TYPE_CHECKING: + from {{packageName}}.configuration import Configuration + +SUPPORTED_SOCKS_PROXIES = {'socks5', 'socks5h', 'socks4', 'socks4a'} +RESTResponseType = urllib3.HTTPResponse + + +def is_socks_proxy_url(url: Optional[str]) -> bool: + if url is None: + return False + split_section = url.split("://") + if len(split_section) < 2: + return False + else: + return split_section[0].lower() in SUPPORTED_SOCKS_PROXIES + + +class RESTResponse(io.IOBase): + def __init__(self, resp: urllib3.HTTPResponse) -> None: + self.response = resp + self.status = resp.status + self.reason = resp.reason + self.data: Optional[bytes] = None + + def read(self) -> bytes: + if self.data is None: + self.data = self.response.data + return self.data + + @property + def headers(self) -> urllib3.HTTPHeaderDict: + """Returns a dictionary of response headers.""" + return self.response.headers + + def getheaders(self) -> urllib3.HTTPHeaderDict: + """Returns a dictionary of the response headers; use ``headers`` instead.""" + return self.response.headers + + def getheader(self, name: str, default: Optional[str] = None) -> Optional[str]: + """Returns a given response header; use ``headers.get()`` instead.""" + return self.response.headers.get(name, default) + + +class RESTClientObject: + def __init__(self, configuration: Configuration) -> None: + # urllib3.PoolManager will pass all kw parameters to connectionpool + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 + # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 + + # cert_reqs + if configuration.verify_ssl: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + + pool_args: dict[str, Any] = { + "cert_reqs": cert_reqs, + "ca_certs": configuration.ssl_ca_cert, + "cert_file": configuration.cert_file, + "key_file": configuration.key_file, + "ca_cert_data": configuration.ca_cert_data, + } + if configuration.assert_hostname is not None: + pool_args['assert_hostname'] = ( + configuration.assert_hostname + ) + + if configuration.retries is not None: + pool_args['retries'] = configuration.retries + + if configuration.tls_server_name: + pool_args['server_hostname'] = configuration.tls_server_name + + + if configuration.socket_options is not None: + pool_args['socket_options'] = configuration.socket_options + + if configuration.connection_pool_maxsize is not None: + pool_args['maxsize'] = configuration.connection_pool_maxsize + + # https pool manager + self.pool_manager: urllib3.PoolManager + + if configuration.proxy: + if is_socks_proxy_url(configuration.proxy): + from urllib3.contrib.socks import SOCKSProxyManager + pool_args["proxy_url"] = configuration.proxy + pool_args["headers"] = configuration.proxy_headers + self.pool_manager = SOCKSProxyManager(**pool_args) + else: + pool_args["proxy_url"] = configuration.proxy + pool_args["proxy_headers"] = configuration.proxy_headers + self.pool_manager = urllib3.ProxyManager(**pool_args) + else: + self.pool_manager = urllib3.PoolManager(**pool_args) + + def request( + self, + method: str, + url: str, + headers: Optional[dict[str, str]] = None, + body: Optional[Any] = None, + post_params: Optional[list[tuple[str, Any]]] = None, + _request_timeout: Optional[Union[float, tuple[float, float]]] = None, + ) -> RESTResponse: + """Perform requests. + + :param method: http request method + :param url: http request url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :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. + """ + method = method.upper() + assert method in [ + 'GET', + 'HEAD', + 'DELETE', + 'POST', + 'PUT', + 'PATCH', + 'OPTIONS' + ] + + if post_params and body: + raise ApiValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or [] + headers = headers or {} + + timeout = None + if _request_timeout: + if isinstance(_request_timeout, (int, float)): + timeout = urllib3.Timeout(total=_request_timeout) + elif ( + isinstance(_request_timeout, tuple) + and len(_request_timeout) == 2 + ): + timeout = urllib3.Timeout( + connect=_request_timeout[0], + read=_request_timeout[1] + ) + + try: + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + + # no content type provided or payload is json + content_type = headers.get('Content-Type') + if ( + not content_type + or re.search('json', content_type, re.IGNORECASE) + ): + request_body = None + if body is not None: + request_body = json.dumps(body{{#setEnsureAsciiToFalse}}, ensure_ascii=False{{/setEnsureAsciiToFalse}}) + r = self.pool_manager.request( + method, + url, + body=request_body, + timeout=timeout, + headers=headers, + preload_content=False + ) + elif content_type == 'application/x-www-form-urlencoded': + r = self.pool_manager.request( + method, + url, + fields=post_params, + encode_multipart=False, + timeout=timeout, + headers=headers, + preload_content=False + ) + elif content_type == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by urllib3 will be + # overwritten. + del headers['Content-Type'] + # Ensures that dict objects are serialized + post_params = [(a, json.dumps(b)) if isinstance(b, dict) else (a,b) for a, b in post_params] + r = self.pool_manager.request( + method, + url, + fields=post_params, + encode_multipart=True, + timeout=timeout, + headers=headers, + preload_content=False + ) + # Pass a `string` parameter directly in the body to support + # other content types than JSON when `body` argument is + # provided in serialized form. + elif isinstance(body, (str, bytes)): + r = self.pool_manager.request( + method, + url, + body=body, + timeout=timeout, + headers=headers, + preload_content=False + ) + elif headers['Content-Type'].startswith('text/') and isinstance(body, bool): + request_body = "true" if body else "false" + r = self.pool_manager.request( + method, + url, + body=request_body, + preload_content=False, + timeout=timeout, + headers=headers) + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + # For `GET`, `HEAD` + else: + r = self.pool_manager.request( + method, + url, + fields={}, + timeout=timeout, + headers=headers, + preload_content=False + ) + except urllib3.exceptions.SSLError as e: + msg = "\n".join([type(e).__name__, str(e)]) + raise ApiException(status=0, reason=msg) from e + + return RESTResponse(r) # type: ignore[arg-type] diff --git a/template/sealed.py.mustache b/template/sealed.py.mustache index dd25bd56..0ccf21ec 100644 --- a/template/sealed.py.mustache +++ b/template/sealed.py.mustache @@ -1,9 +1,8 @@ import json -from typing import List +import zlib -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend -import zlib +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from {{packageName}}.models.event import Event @@ -15,7 +14,7 @@ DecryptionAlgorithm = { class DecryptionKey: """Key for decryption of sealed data.""" - exception: Exception + key: bytes algorithm: str def __init__(self, key: bytes, algorithm: str): @@ -35,14 +34,14 @@ class UnsealError(Exception): class UnsealAggregateError(Exception): """Aggregated error during unsealing.""" - errors: List[UnsealError] + errors: list[UnsealError] - def __init__(self, errors: List[UnsealError]): + def __init__(self, errors: list[UnsealError]): self.errors = errors super().__init__("Unable to decrypt sealed data") -def unseal_event_response(sealed_data: bytes, decryption_keys: List[DecryptionKey]) -> Event: +def unseal_event_response(sealed_data: bytes, decryption_keys: list[DecryptionKey]) -> Event: """Unseal event response with one of the provided keys.""" unsealed = __unseal(sealed_data, decryption_keys) return __parse_event_response(unsealed) @@ -55,11 +54,13 @@ def __parse_event_response(unsealed: str) -> Event: if 'event_id' not in json_data: raise ValueError('Sealed data is not valid event response') - result: Event = Event.from_dict(json_data) + result = Event.from_dict(json_data) + if result is None: + raise ValueError('Failed to parse event response') return result -def __unseal(sealed_data: bytes, decryption_keys: List[DecryptionKey]) -> str: +def __unseal(sealed_data: bytes, decryption_keys: list[DecryptionKey]) -> str: """Unseal data with one of the provided keys.""" if sealed_data[:len(SEALED_HEADER)].hex() != SEALED_HEADER.hex(): raise ValueError('Invalid sealed data header') diff --git a/template/setup.mustache b/template/setup.mustache index 846fc218..e6d26ad4 100644 --- a/template/setup.mustache +++ b/template/setup.mustache @@ -1,9 +1,6 @@ -# coding: utf-8 - {{>partial_header}} - -from setuptools import setup, find_packages # noqa: H301 +from setuptools import find_packages, setup # To install the library, run the following # diff --git a/template/test-requirements.mustache b/template/test-requirements.mustache new file mode 100644 index 00000000..1ae7ef85 --- /dev/null +++ b/template/test-requirements.mustache @@ -0,0 +1,7 @@ +pytest >= 7.2.1 +pytest-cov >= 2.8.1 +tox >= 3.9.0 +types-python-dateutil >= 2.8.19.14 +mypy >= 1.5 +ruff == 0.15.0 +pre-commit >= 4.0.0 diff --git a/template/webhook_validation.py b/template/webhook_validation.py index cf684f09..3e6e5116 100644 --- a/template/webhook_validation.py +++ b/template/webhook_validation.py @@ -1,9 +1,10 @@ -import hmac import hashlib +import hmac class WebhookValidation: """Manages work with webhooks.""" + @staticmethod def is_valid_hmac_signature(signature: str, data: bytes, secret: str) -> bool: """Validates an HMAC signature.""" @@ -13,9 +14,12 @@ def is_valid_hmac_signature(signature: str, data: bytes, secret: str) -> bool: @staticmethod def is_valid_webhook_signature(header: str, data: bytes, secret: str) -> bool: - """Verifies the HMAC signature extracted from the "fpjs-event-signature" header of the incoming request. - This is a part of the webhook signing process, which is available only for enterprise customers. - If you wish to enable it, please contact our support: https://fingerprint.com/support""" + """Verifies the HMAC signature extracted from the "fpjs-event-signature" header. + + This is a part of the webhook signing process, which is available only for + enterprise customers. If you wish to enable it, please contact our support: + https://fingerprint.com/support + """ signatures = header.split(',') @@ -23,8 +27,9 @@ def is_valid_webhook_signature(header: str, data: bytes, secret: str) -> bool: parts = signature.split('=') if len(parts) == 2: version, hash_value = parts - if version == "v1" and WebhookValidation.is_valid_hmac_signature(hash_value, data, secret): + if version == 'v1' and WebhookValidation.is_valid_hmac_signature( + hash_value, data, secret + ): return True return False - diff --git a/test-requirements.txt b/test-requirements.txt index e98555c1..1ae7ef85 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,6 +1,7 @@ pytest >= 7.2.1 pytest-cov >= 2.8.1 tox >= 3.9.0 -flake8 >= 4.0.0 types-python-dateutil >= 2.8.19.14 mypy >= 1.5 +ruff == 0.15.0 +pre-commit >= 4.0.0 diff --git a/test/mock_pool_manager.py b/test/mock_pool_manager.py index e374bdc3..9b4e415b 100644 --- a/test/mock_pool_manager.py +++ b/test/mock_pool_manager.py @@ -1,15 +1,15 @@ from collections import Counter from pathlib import Path -from urllib.parse import urlsplit, parse_qsl, urlunsplit, urlencode -from fingerprint_server_sdk import __version__ +from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit import urllib3 -MOCK_SEARCH_EVENTS_200 = 'events/get_event_200.json' +from fingerprint_server_sdk import __version__ +MOCK_SEARCH_EVENTS_200 = 'events/get_event_200.json' -class MockPoolManager(object): +class MockPoolManager: def __init__(self, tc, request_headers=None): self.request_headers = request_headers self._tc = tc @@ -35,9 +35,9 @@ def request(self, *args, **kwargs): self._tc.maxDiff = None self._tc.assertEqual(request_method, args[0]) - url, ii_value = self._strip_query_param(args[1], "ii") + url, ii_value = self._strip_query_param(args[1], 'ii') self._tc.assertIsInstance(ii_value, str) - self._tc.assertEqual(f"fingerprint-server-python-sdk/{__version__}", ii_value) + self._tc.assertEqual(f'fingerprint-server-python-sdk/{__version__}', ii_value) self._tc.assertEqual(request_url, url) self._tc.assertEqual(set(request_config.keys()), set(kwargs.keys())) @@ -49,14 +49,18 @@ def request(self, *args, **kwargs): if response_text is not None: response_body = response_text.encode('utf-8') elif response_data_file is not None: - if not isinstance(response_data_file, Path) and not isinstance(response_data_file, str): + if not isinstance(response_data_file, Path) and not isinstance( + response_data_file, str + ): raise TypeError('response_data_file must be str or Path') base_dir = Path(__file__).resolve().parent / 'mocks' mock_file_path = base_dir / response_data_file with mock_file_path.open('r', encoding='utf-8') as mock_file: response_body = mock_file.read().encode('utf-8') - return urllib3.HTTPResponse(status=response_status_code, body=response_body, headers=response_headers) + return urllib3.HTTPResponse( + status=response_status_code, body=response_body, headers=response_headers + ) @staticmethod def _strip_query_param(url: str, name: str): @@ -66,4 +70,4 @@ def _strip_query_param(url: str, name: str): kept = [(k, v) for k, v in pairs if k != name] new_query = urlencode(kept, doseq=True) new_url = urlunsplit((s.scheme, s.netloc, s.path, new_query, s.fragment)) - return new_url, (values[0] if values else None) \ No newline at end of file + return new_url, (values[0] if values else None) diff --git a/test/test_fingerprint_api.py b/test/test_fingerprint_api.py index 7b47446d..0cc25104 100644 --- a/test/test_fingerprint_api.py +++ b/test/test_fingerprint_api.py @@ -1,10 +1,20 @@ -# coding: utf-8 - import unittest from urllib.parse import urlencode -from fingerprint_server_sdk import Configuration, __version__, Event, EventSearch, EventUpdate, BadRequestException, \ - ErrorResponse, ErrorCode, ForbiddenException, NotFoundException, TooManyRequestsException, ConflictException +from fingerprint_server_sdk import ( + BadRequestException, + Configuration, + ConflictException, + ErrorCode, + ErrorResponse, + Event, + EventSearch, + EventUpdate, + ForbiddenException, + NotFoundException, + TooManyRequestsException, + __version__, +) from fingerprint_server_sdk.api.fingerprint_api import FingerprintApi from fingerprint_server_sdk.configuration import Region from test.mock_pool_manager import MockPoolManager @@ -18,12 +28,12 @@ class TestFingerprintApi(unittest.TestCase): def setUp(self) -> None: configuration = Configuration(api_key=API_KEY, region=REGION) - self.integration_info = ('ii', 'fingerprint-server-python-sdk/%s' % __version__) + self.integration_info = ('ii', f'fingerprint-server-python-sdk/{__version__}') self.request_headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {API_KEY}', 'Accept': 'application/json', - 'User-Agent': 'fingerprint-server-python-sdk/%s' % __version__ + 'User-Agent': f'fingerprint-server-python-sdk/{__version__}', } self.api = FingerprintApi(configuration) @@ -33,12 +43,12 @@ def tearDown(self) -> None: @staticmethod def get_event_path(event_id, region: Region = Region.US): base = Configuration.get_host(region) - return '%s/events/%s' % (base, event_id) + return f'{base}/events/{event_id}' @staticmethod def get_search_events_path(params: dict, region: Region = Region.US): base = Configuration.get_host(region) - url = '%s/events' % base + url = f'{base}/events' if not params: return url @@ -54,12 +64,12 @@ def get_search_events_path(params: dict, region: Region = Region.US): else: query_param_pairs.append((k, str(v))) - return f"{url}?{urlencode(query_param_pairs, doseq=True)}" if query_param_pairs else url + return f'{url}?{urlencode(query_param_pairs, doseq=True)}' if query_param_pairs else url @staticmethod def delete_visitor_path(visitor_id, region: Region = Region.US): base = Configuration.get_host(region) - return '%s/visitors/%s' % (base, visitor_id) + return f'{base}/visitors/{visitor_id}' def test_delete_visitor_data(self) -> None: """Test case for delete_visitor_data @@ -68,10 +78,16 @@ def test_delete_visitor_data(self) -> None: """ mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - visitor_id = "XXXXXXXXXXXXXXXXXXXX" - mock_pool.expect_request('DELETE', TestFingerprintApi.delete_visitor_path(visitor_id), - body=None, response_text="{}", headers=self.request_headers, - preload_content=True, timeout=None) + visitor_id = 'XXXXXXXXXXXXXXXXXXXX' + mock_pool.expect_request( + 'DELETE', + TestFingerprintApi.delete_visitor_path(visitor_id), + body=None, + response_text='{}', + headers=self.request_headers, + preload_content=True, + timeout=None, + ) self.api.delete_visitor_data(visitor_id) @@ -79,8 +95,17 @@ def test_delete_visitor_data_bad_request(self) -> None: """Test case for delete_visitor_data with 400 Bad Request response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - visitor_id = "invalid_visitor_id" - mock_pool.expect_request('DELETE',TestFingerprintApi.delete_visitor_path(visitor_id), body=None, headers=self.request_headers, preload_content=True, timeout=None, response_status_code=400, response_data_file="errors/400_visitor_id_invalid.json") + visitor_id = 'invalid_visitor_id' + mock_pool.expect_request( + 'DELETE', + TestFingerprintApi.delete_visitor_path(visitor_id), + body=None, + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=400, + response_data_file='errors/400_visitor_id_invalid.json', + ) with self.assertRaises(BadRequestException) as context: self.api.delete_visitor_data(visitor_id) @@ -93,10 +118,17 @@ def test_delete_visitor_data_forbidden(self) -> None: """Test case for delete_visitor_data with 403 Forbidden response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - visitor_id = "XXXXXXXXXXXXXXXXXXXX" - mock_pool.expect_request('DELETE', TestFingerprintApi.delete_visitor_path(visitor_id), body=None, - headers=self.request_headers, preload_content=True, timeout=None, - response_status_code=403, response_data_file="errors/403_feature_not_enabled.json") + visitor_id = 'XXXXXXXXXXXXXXXXXXXX' + mock_pool.expect_request( + 'DELETE', + TestFingerprintApi.delete_visitor_path(visitor_id), + body=None, + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=403, + response_data_file='errors/403_feature_not_enabled.json', + ) with self.assertRaises(ForbiddenException) as context: self.api.delete_visitor_data(visitor_id) @@ -109,10 +141,17 @@ def test_delete_visitor_data_not_found(self) -> None: """Test case for delete_visitor_data with 404 Not Found response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - visitor_id = "nonexistent_visitor_id" - mock_pool.expect_request('DELETE', TestFingerprintApi.delete_visitor_path(visitor_id), body=None, - headers=self.request_headers, preload_content=True, timeout=None, - response_status_code=404, response_data_file="errors/404_visitor_not_found.json") + visitor_id = 'nonexistent_visitor_id' + mock_pool.expect_request( + 'DELETE', + TestFingerprintApi.delete_visitor_path(visitor_id), + body=None, + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=404, + response_data_file='errors/404_visitor_not_found.json', + ) with self.assertRaises(NotFoundException) as context: self.api.delete_visitor_data(visitor_id) @@ -125,10 +164,18 @@ def test_delete_visitor_data_too_many_requests(self) -> None: """Test case for delete_visitor_data with 429 Too Many Requests response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - visitor_id = "XXXXXXXXXXXXXXXXXXXX" - mock_pool.expect_request('DELETE', TestFingerprintApi.delete_visitor_path(visitor_id), body=None, - headers=self.request_headers, preload_content=True, timeout=None, - response_status_code=429, response_data_file="errors/429_too_many_requests.json", response_headers={'Retry-After': '5'}) + visitor_id = 'XXXXXXXXXXXXXXXXXXXX' + mock_pool.expect_request( + 'DELETE', + TestFingerprintApi.delete_visitor_path(visitor_id), + body=None, + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=429, + response_data_file='errors/429_too_many_requests.json', + response_headers={'Retry-After': '5'}, + ) with self.assertRaises(TooManyRequestsException) as context: self.api.delete_visitor_data(visitor_id) @@ -144,10 +191,16 @@ def test_get_event(self) -> None: """ mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" - mock_pool.expect_request('GET', TestFingerprintApi.get_event_path(event_id), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, response_data_file="events/get_event_200.json") + event_id = '0000000000000.XXXXX' + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_event_path(event_id), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_data_file='events/get_event_200.json', + ) event_response = self.api.get_event(event_id) self.assertIsInstance(event_response, Event) @@ -156,11 +209,17 @@ def test_get_event_bad_request(self) -> None: """Test case for get_event with 400 Bad Request response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "invalid" - mock_pool.expect_request('GET', TestFingerprintApi.get_event_path(event_id), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, - response_status_code=400, response_data_file="errors/400_event_id_invalid.json") + event_id = 'invalid' + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_event_path(event_id), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=400, + response_data_file='errors/400_event_id_invalid.json', + ) with self.assertRaises(BadRequestException) as context: self.api.get_event(event_id) @@ -173,11 +232,17 @@ def test_get_event_forbidden(self) -> None: """Test case for get_event with 403 Forbidden response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" - mock_pool.expect_request('GET', TestFingerprintApi.get_event_path(event_id), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, - response_status_code=403, response_data_file="errors/403_secret_api_key_required.json") + event_id = '0000000000000.XXXXX' + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_event_path(event_id), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=403, + response_data_file='errors/403_secret_api_key_required.json', + ) with self.assertRaises(ForbiddenException) as context: self.api.get_event(event_id) @@ -190,11 +255,17 @@ def test_get_event_not_found(self) -> None: """Test case for get_event with 404 Not Found response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "nonexistent_event_id" - mock_pool.expect_request('GET', TestFingerprintApi.get_event_path(event_id), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, - response_status_code=404, response_data_file="errors/404_event_not_found.json") + event_id = 'nonexistent_event_id' + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_event_path(event_id), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=404, + response_data_file='errors/404_event_not_found.json', + ) with self.assertRaises(NotFoundException) as context: self.api.get_event(event_id) @@ -207,11 +278,17 @@ def test_get_event_too_many_requests(self) -> None: """Test case for get_event with 429 Too Many Requests response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" - mock_pool.expect_request('GET', TestFingerprintApi.get_event_path(event_id), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, - response_status_code=429, response_data_file="errors/429_too_many_requests.json") + event_id = '0000000000000.XXXXX' + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_event_path(event_id), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=429, + response_data_file='errors/429_too_many_requests.json', + ) with self.assertRaises(TooManyRequestsException) as context: self.api.get_event(event_id) @@ -225,21 +302,25 @@ def test_search_events(self) -> None: Search events """ - params = { - 'limit': 2 - } + params = {'limit': 2} mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - mock_pool.expect_request('GET', TestFingerprintApi.get_search_events_path(params), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, response_data_file="events/search/get_event_search_200.json") + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_search_events_path(params), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_data_file='events/search/get_event_search_200.json', + ) event_response = self.api.search_events(**params) self.assertIsInstance(event_response, EventSearch) self.assertEqual(len(event_response.events), 1) first_event = event_response.events[0] self.assertIsInstance(first_event, Event) - self.assertEqual(first_event.event_id, "1708102555327.NLOjmg") + self.assertEqual(first_event.event_id, '1708102555327.NLOjmg') def test_search_events_bad_request(self) -> None: """Test case for search_events with 400 Bad Request response""" @@ -247,10 +328,16 @@ def test_search_events_bad_request(self) -> None: mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - mock_pool.expect_request('GET', TestFingerprintApi.get_search_events_path(params), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, - response_status_code=400, response_data_file="errors/400_request_body_invalid.json") + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_search_events_path(params), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=400, + response_data_file='errors/400_request_body_invalid.json', + ) with self.assertRaises(BadRequestException) as context: self.api.search_events(**params) @@ -265,10 +352,16 @@ def test_search_events_forbidden(self) -> None: mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - mock_pool.expect_request('GET', TestFingerprintApi.get_search_events_path(params), - fields=[], headers=self.request_headers, - preload_content=True, timeout=None, - response_status_code=403, response_data_file="errors/403_secret_api_key_required.json") + mock_pool.expect_request( + 'GET', + TestFingerprintApi.get_search_events_path(params), + fields=[], + headers=self.request_headers, + preload_content=True, + timeout=None, + response_status_code=403, + response_data_file='errors/403_secret_api_key_required.json', + ) with self.assertRaises(ForbiddenException) as context: self.api.search_events(**params) @@ -277,7 +370,6 @@ def test_search_events_forbidden(self) -> None: self.assertIsInstance(context.exception.data, ErrorResponse) self.assertEqual(context.exception.data.error.code, ErrorCode.SECRET_API_KEY_REQUIRED) - def test_update_event(self) -> None: """Test case for update_event @@ -288,20 +380,27 @@ def test_update_event(self) -> None: (EventUpdate(tags={'qwe': 123}), '{"tags": {"qwe": 123}}'), (EventUpdate(suspect=False), '{"suspect": false}'), (EventUpdate(suspect=True), '{"suspect": true}'), - (EventUpdate(linked_id='qwe', tags={'qwe': 123}, suspect=False), - '{"linkedId": "qwe", "tags": {"qwe": 123}, "suspect": false}') + ( + EventUpdate(linked_id='qwe', tags={'qwe': 123}, suspect=False), + '{"linkedId": "qwe", "tags": {"qwe": 123}, "suspect": false}', + ), ] mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" + event_id = '0000000000000.XXXXX' - for (update_body, serialized_body) in test_cases: - mock_pool.expect_request('PATCH', - TestFingerprintApi.get_event_path(event_id), - headers=self.request_headers, preload_content=True, timeout=None, - body=serialized_body, response_text="OK") + for update_body, serialized_body in test_cases: + mock_pool.expect_request( + 'PATCH', + TestFingerprintApi.get_event_path(event_id), + headers=self.request_headers, + preload_content=True, + timeout=None, + body=serialized_body, + response_text='OK', + ) self.api.update_event(event_id, update_body) @@ -309,12 +408,18 @@ def test_update_event_bad_request(self) -> None: """Test case for update_event with 400 Bad Request response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" + event_id = '0000000000000.XXXXX' update_body = EventUpdate(linked_id='test') - mock_pool.expect_request('PATCH', TestFingerprintApi.get_event_path(event_id), - headers=self.request_headers, preload_content=True, timeout=None, - body='{"linkedId": "test"}', - response_status_code=400, response_data_file="errors/400_request_body_invalid.json") + mock_pool.expect_request( + 'PATCH', + TestFingerprintApi.get_event_path(event_id), + headers=self.request_headers, + preload_content=True, + timeout=None, + body='{"linkedId": "test"}', + response_status_code=400, + response_data_file='errors/400_request_body_invalid.json', + ) with self.assertRaises(BadRequestException) as context: self.api.update_event(event_id, update_body) @@ -327,12 +432,18 @@ def test_update_event_forbidden(self) -> None: """Test case for update_event with 403 Forbidden response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" + event_id = '0000000000000.XXXXX' update_body = EventUpdate(suspect=True) - mock_pool.expect_request('PATCH', TestFingerprintApi.get_event_path(event_id), - headers=self.request_headers, preload_content=True, timeout=None, - body='{"suspect": true}', - response_status_code=403, response_data_file="errors/403_secret_api_key_required.json") + mock_pool.expect_request( + 'PATCH', + TestFingerprintApi.get_event_path(event_id), + headers=self.request_headers, + preload_content=True, + timeout=None, + body='{"suspect": true}', + response_status_code=403, + response_data_file='errors/403_secret_api_key_required.json', + ) with self.assertRaises(ForbiddenException) as context: self.api.update_event(event_id, update_body) @@ -345,12 +456,18 @@ def test_update_event_not_found(self) -> None: """Test case for update_event with 404 Not Found response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "nonexistent_event_id" + event_id = 'nonexistent_event_id' update_body = EventUpdate(suspect=True) - mock_pool.expect_request('PATCH', TestFingerprintApi.get_event_path(event_id), - headers=self.request_headers, preload_content=True, timeout=None, - body='{"suspect": true}', - response_status_code=404, response_data_file="errors/404_event_not_found.json") + mock_pool.expect_request( + 'PATCH', + TestFingerprintApi.get_event_path(event_id), + headers=self.request_headers, + preload_content=True, + timeout=None, + body='{"suspect": true}', + response_status_code=404, + response_data_file='errors/404_event_not_found.json', + ) with self.assertRaises(NotFoundException) as context: self.api.update_event(event_id, update_body) @@ -363,12 +480,18 @@ def test_update_event_conflict(self) -> None: """Test case for update_event with 409 Conflict response""" mock_pool = MockPoolManager(self) self.api.api_client.rest_client.pool_manager = mock_pool - event_id = "0000000000000.XXXXX" + event_id = '0000000000000.XXXXX' update_body = EventUpdate(suspect=True) - mock_pool.expect_request('PATCH', TestFingerprintApi.get_event_path(event_id), - headers=self.request_headers, preload_content=True, timeout=None, - body='{"suspect": true}', - response_status_code=409, response_data_file="errors/409_state_not_ready.json") + mock_pool.expect_request( + 'PATCH', + TestFingerprintApi.get_event_path(event_id), + headers=self.request_headers, + preload_content=True, + timeout=None, + body='{"suspect": true}', + response_status_code=409, + response_data_file='errors/409_state_not_ready.json', + ) with self.assertRaises(ConflictException) as context: self.api.update_event(event_id, update_body) diff --git a/test/test_sealed.py b/test/test_sealed.py index 0e4def76..79b8a58b 100644 --- a/test/test_sealed.py +++ b/test/test_sealed.py @@ -1,15 +1,22 @@ import base64 import unittest -from fingerprint_server_sdk import DecryptionAlgorithm, DecryptionKey, \ - unseal_event_response, UnsealError, UnsealAggregateError, Event +from fingerprint_server_sdk import ( + DecryptionAlgorithm, + DecryptionKey, + Event, + UnsealAggregateError, + UnsealError, + unseal_event_response, +) + class TestSealed(unittest.TestCase): valid_key = base64.b64decode('p2PA7MGy5tx56cnyJaFZMr96BCFwZeHjZV2EqMvTq53=') invalid_key = base64.b64decode('a2PA7MGy5tx56cnyJaFZMr96BCFwZeHjZV2EqMvTq53=') def test_unseal_aes256gcm(self): - sealed_result = '''{ + sealed_result = """{ "linked_id": "somelinkedId", "tags": {}, "timestamp": 1708102555327, @@ -176,98 +183,135 @@ def test_unseal_aes256gcm(self): "version": "3.11.10" }, "replayed": false -}''' +}""" expected_result = Event.from_json(sealed_result) sealed_data = base64.b64decode( - 'noXc7Xu7PIKu1tbMkMxLbQG4XU46Bv5dED98hqTkPYZnmb8PG81Q83Kpg541Vt4NQdkzfezDSVk8FP9ZzJ08L0MMb4S8bT78c10Op1LyKwZU6DGr1e3V+ZWcNzHVG1rPoL+eUHN6yR9MQp8/CmSUBQUPOOAUXdoqWohbfIGxoQIuQ5BtfpSJuYD6kTyswSi56wxzY/s24dMwgS2KnA81Y1pdi3ZVJKBdwGYGg4T5Dvcqu0GWv3sScKD9b4Tagfbe2m8nbXY/QtN770c7J1xo/TNXXdq4lyqaMyqIayHOwRBP58tNF8mACusm1pogOVIt456wIMetCGKxicPJr7m/Q02ONzhkMtzzXwgwriglGHfM7UbtTsCytCBP7J2vp0tEkHiq/X3qtuvSLJqNyRzwFJhgisKGftc5CIaT2VxVKKxkL/6Ws6FPm4sQB1UGtMCMftKpyb1lFzG9lwFkKvYN9+FGtvRM50mbrzz7ONDxbwykkxihAab36MIuk7dfhvnVLFAjrpuCkEFdWrtjVyWmM0xVeXpEUtP6Ijk5P+VuPZ1alV/JV1q4WvfrGMizEZbwbp6eQZg9mwKe4IX+FVi7sPF2S/CCLI/d90S5Yz6bBP9uiQ3pCVlYbVOkpwS0YQxnR+h5J50qodY7LuswNO5VlEgI0ztkjPQBr8koT4SM54X2z14tA2tKCxSv1psEL5HOk4IWN+9f3RVfDKBDruDiDd+BtZquhYLmOFat9K4h41NrPGAqv5tKmmJtx3llMs6LFHPKBlNlI5zgqE7T47xv2AWw5nqWM107t8lpRETIgJx+YN/Jv6byJSQm7afaeDtHXGceMPOKMziH1XgsiQiS56OsmyyRgaq5YCmMuaPw8gcgVa7RNZSafkP34aQBAuJOA3JFs5xcYcubKutD3h1mk697A8vwdtR/Gj0zTvuUnQ/9o3qHSLseAEIiY9/dS6WJnKXRKTonQi2F6DV9NTzFVQl99AH22jq6lIsjbEEKcq/ydFDUpgAq4lyp9nPBHuPXSojdG+1BWuUyjYykaqnLzzqKgRalGzeWmRHd2qeNw8Bz5OWYBw82C3gHRS2BB9VquIgEYktDvgJ5yRfDYkp8qgxHoYeR88ijccWgdvk+WH78OPdwqA7rqdAYcWqn9KNozoxuYddc0fnrHbgaWpanCmPp0gNEeb4r+i9FDGPSkgYBdyrEPHblsDN/Ad1dhLIHEDEtQyv13s6tDRgLVvhowrzqIM+5cm/abyTDhXzSYDfCw2Wf90cBOMsbQBB2N2YRqnrpA50PGp+0IwlPL7qZj1N4JGhvQD0ux8Ood6AiXpdguj7DMP+T0laHIjWee5/xGZB6g3EsCdOZJjVj7hSE/L3eV4No0WcLqJ5DPOgw+FnvQpxndCTc8DW83tNm624lm7scu0A499vEFj1dhtq5gUxsGcqzm09+Vk2V/d0sa77Xocqe3bcfS5lXc/pHrOc1qKlK8kTr2AYNwjeJJ14euuin361WBETd1I6n8eIs02HyBas09o9lT7Nq05jsnbxej6d0q6GH7IYusiBFTJaAZ6UXOV5i1NOcw9jaGyHms3M2N/b2cmXFYTIFZSjSfbqoI6YZF73sMPhEZqfZ5Jjq+ZLMC3A+yFPFJOW/0oolUGbcC8TBVmLi37Z9Wgc338w2Jf+I94SdViku') + 'noXc7Xu7PIKu1tbMkMxLbQG4XU46Bv5dED98hqTkPYZnmb8PG81Q83Kpg541Vt4NQdkzfezDSVk8FP9ZzJ08L0MMb4S8bT78c10Op1LyKwZU6DGr1e3V+ZWcNzHVG1rPoL+eUHN6yR9MQp8/CmSUBQUPOOAUXdoqWohbfIGxoQIuQ5BtfpSJuYD6kTyswSi56wxzY/s24dMwgS2KnA81Y1pdi3ZVJKBdwGYGg4T5Dvcqu0GWv3sScKD9b4Tagfbe2m8nbXY/QtN770c7J1xo/TNXXdq4lyqaMyqIayHOwRBP58tNF8mACusm1pogOVIt456wIMetCGKxicPJr7m/Q02ONzhkMtzzXwgwriglGHfM7UbtTsCytCBP7J2vp0tEkHiq/X3qtuvSLJqNyRzwFJhgisKGftc5CIaT2VxVKKxkL/6Ws6FPm4sQB1UGtMCMftKpyb1lFzG9lwFkKvYN9+FGtvRM50mbrzz7ONDxbwykkxihAab36MIuk7dfhvnVLFAjrpuCkEFdWrtjVyWmM0xVeXpEUtP6Ijk5P+VuPZ1alV/JV1q4WvfrGMizEZbwbp6eQZg9mwKe4IX+FVi7sPF2S/CCLI/d90S5Yz6bBP9uiQ3pCVlYbVOkpwS0YQxnR+h5J50qodY7LuswNO5VlEgI0ztkjPQBr8koT4SM54X2z14tA2tKCxSv1psEL5HOk4IWN+9f3RVfDKBDruDiDd+BtZquhYLmOFat9K4h41NrPGAqv5tKmmJtx3llMs6LFHPKBlNlI5zgqE7T47xv2AWw5nqWM107t8lpRETIgJx+YN/Jv6byJSQm7afaeDtHXGceMPOKMziH1XgsiQiS56OsmyyRgaq5YCmMuaPw8gcgVa7RNZSafkP34aQBAuJOA3JFs5xcYcubKutD3h1mk697A8vwdtR/Gj0zTvuUnQ/9o3qHSLseAEIiY9/dS6WJnKXRKTonQi2F6DV9NTzFVQl99AH22jq6lIsjbEEKcq/ydFDUpgAq4lyp9nPBHuPXSojdG+1BWuUyjYykaqnLzzqKgRalGzeWmRHd2qeNw8Bz5OWYBw82C3gHRS2BB9VquIgEYktDvgJ5yRfDYkp8qgxHoYeR88ijccWgdvk+WH78OPdwqA7rqdAYcWqn9KNozoxuYddc0fnrHbgaWpanCmPp0gNEeb4r+i9FDGPSkgYBdyrEPHblsDN/Ad1dhLIHEDEtQyv13s6tDRgLVvhowrzqIM+5cm/abyTDhXzSYDfCw2Wf90cBOMsbQBB2N2YRqnrpA50PGp+0IwlPL7qZj1N4JGhvQD0ux8Ood6AiXpdguj7DMP+T0laHIjWee5/xGZB6g3EsCdOZJjVj7hSE/L3eV4No0WcLqJ5DPOgw+FnvQpxndCTc8DW83tNm624lm7scu0A499vEFj1dhtq5gUxsGcqzm09+Vk2V/d0sa77Xocqe3bcfS5lXc/pHrOc1qKlK8kTr2AYNwjeJJ14euuin361WBETd1I6n8eIs02HyBas09o9lT7Nq05jsnbxej6d0q6GH7IYusiBFTJaAZ6UXOV5i1NOcw9jaGyHms3M2N/b2cmXFYTIFZSjSfbqoI6YZF73sMPhEZqfZ5Jjq+ZLMC3A+yFPFJOW/0oolUGbcC8TBVmLi37Z9Wgc338w2Jf+I94SdViku' + ) - result = unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + result = unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) self.assertEqual(result, expected_result) self.assertIsInstance(result, Event) - def test_unseal_invalid_header(self): sealed_data = base64.b64decode( - 'noXc7xXO+mqeAGrvBMgObi/S0fXTpP3zupk8qFqsO/1zdtWCD169iLA3VkkZh9ICHpZ0oWRzqG0M9/TnCeKFohgBLqDp6O0zEfXOv6i5q++aucItznQdLwrKLP+O0blfb4dWVI8/aSbd4ELAZuJJxj9bCoVZ1vk+ShbUXCRZTD30OIEAr3eiG9aw00y1UZIqMgX6CkFlU9L9OnKLsNsyomPIaRHTmgVTI5kNhrnVNyNsnzt9rY7fUD52DQxJILVPrUJ1Q+qW7VyNslzGYBPG0DyYlKbRAomKJDQIkdj/Uwa6bhSTq4XYNVvbk5AJ/dGwvsVdOnkMT2Ipd67KwbKfw5bqQj/cw6bj8Cp2FD4Dy4Ud4daBpPRsCyxBM2jOjVz1B/lAyrOp8BweXOXYugwdPyEn38MBZ5oL4D38jIwR/QiVnMHpERh93jtgwh9Abza6i4/zZaDAbPhtZLXSM5ztdctv8bAb63CppLU541Kf4OaLO3QLvfLRXK2n8bwEwzVAqQ22dyzt6/vPiRbZ5akh8JB6QFXG0QJF9DejsIspKF3JvOKjG2edmC9o+GfL3hwDBiihYXCGY9lElZICAdt+7rZm5UxMx7STrVKy81xcvfaIp1BwGh/HyMsJnkE8IczzRFpLlHGYuNDxdLoBjiifrmHvOCUDcV8UvhSV+UAZtAVejdNGo5G/bz0NF21HUO4pVRPu6RqZIs/aX4hlm6iO/0Ru00ct8pfadUIgRcephTuFC2fHyZxNBC6NApRtLSNLfzYTTo/uSjgcu6rLWiNo5G7yfrM45RXjalFEFzk75Z/fu9lCJJa5uLFgDNxlU+IaFjArfXJCll3apbZp4/LNKiU35ZlB7ZmjDTrji1wLep8iRVVEGht/DW00MTok7Zn7Fv+MlxgWmbZB3BuezwTmXb/fNw==') + 'noXc7xXO+mqeAGrvBMgObi/S0fXTpP3zupk8qFqsO/1zdtWCD169iLA3VkkZh9ICHpZ0oWRzqG0M9/TnCeKFohgBLqDp6O0zEfXOv6i5q++aucItznQdLwrKLP+O0blfb4dWVI8/aSbd4ELAZuJJxj9bCoVZ1vk+ShbUXCRZTD30OIEAr3eiG9aw00y1UZIqMgX6CkFlU9L9OnKLsNsyomPIaRHTmgVTI5kNhrnVNyNsnzt9rY7fUD52DQxJILVPrUJ1Q+qW7VyNslzGYBPG0DyYlKbRAomKJDQIkdj/Uwa6bhSTq4XYNVvbk5AJ/dGwvsVdOnkMT2Ipd67KwbKfw5bqQj/cw6bj8Cp2FD4Dy4Ud4daBpPRsCyxBM2jOjVz1B/lAyrOp8BweXOXYugwdPyEn38MBZ5oL4D38jIwR/QiVnMHpERh93jtgwh9Abza6i4/zZaDAbPhtZLXSM5ztdctv8bAb63CppLU541Kf4OaLO3QLvfLRXK2n8bwEwzVAqQ22dyzt6/vPiRbZ5akh8JB6QFXG0QJF9DejsIspKF3JvOKjG2edmC9o+GfL3hwDBiihYXCGY9lElZICAdt+7rZm5UxMx7STrVKy81xcvfaIp1BwGh/HyMsJnkE8IczzRFpLlHGYuNDxdLoBjiifrmHvOCUDcV8UvhSV+UAZtAVejdNGo5G/bz0NF21HUO4pVRPu6RqZIs/aX4hlm6iO/0Ru00ct8pfadUIgRcephTuFC2fHyZxNBC6NApRtLSNLfzYTTo/uSjgcu6rLWiNo5G7yfrM45RXjalFEFzk75Z/fu9lCJJa5uLFgDNxlU+IaFjArfXJCll3apbZp4/LNKiU35ZlB7ZmjDTrji1wLep8iRVVEGht/DW00MTok7Zn7Fv+MlxgWmbZB3BuezwTmXb/fNw==' + ) - with self.assertRaisesRegex(ValueError, "Invalid sealed data header"): - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + with self.assertRaisesRegex(ValueError, 'Invalid sealed data header'): + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) def test_unseal_invalid_algorithm(self): sealed_data = base64.b64decode( - 'noXc7Xu7PIKu1tbMkMxLbQG4XU46Bv5dED98hqTkPYZnmb8PG81Q83Kpg541Vt4NQdkzfezDSVk8FP9ZzJ08L0MMb4S8bT78c10Op1LyKwZU6DGr1e3V+ZWcNzHVG1rPoL+eUHN6yR9MQp8/CmSUBQUPOOAUXdoqWohbfIGxoQIuQ5BtfpSJuYD6kTyswSi56wxzY/s24dMwgS2KnA81Y1pdi3ZVJKBdwGYGg4T5Dvcqu0GWv3sScKD9b4Tagfbe2m8nbXY/QtN770c7J1xo/TNXXdq4lyqaMyqIayHOwRBP58tNF8mACusm1pogOVIt456wIMetCGKxicPJr7m/Q02ONzhkMtzzXwgwriglGHfM7UbtTsCytCBP7J2vp0tEkHiq/X3qtuvSLJqNyRzwFJhgisKGftc5CIaT2VxVKKxkL/6Ws6FPm4sQB1UGtMCMftKpyb1lFzG9lwFkKvYN9+FGtvRM50mbrzz7ONDxbwykkxihAab36MIuk7dfhvnVLFAjrpuCkEFdWrtjVyWmM0xVeXpEUtP6Ijk5P+VuPZ1alV/JV1q4WvfrGMizEZbwbp6eQZg9mwKe4IX+FVi7sPF2S/CCLI/d90S5Yz6bBP9uiQ3pCVlYbVOkpwS0YQxnR+h5J50qodY7LuswNO5VlEgI0ztkjPQBr8koT4SM54X2z14tA2tKCxSv1psEL5HOk4IWN+9f3RVfDKBDruDiDd+BtZquhYLmOFat9K4h41NrPGAqv5tKmmJtx3llMs6LFHPKBlNlI5zgqE7T47xv2AWw5nqWM107t8lpRETIgJx+YN/Jv6byJSQm7afaeDtHXGceMPOKMziH1XgsiQiS56OsmyyRgaq5YCmMuaPw8gcgVa7RNZSafkP34aQBAuJOA3JFs5xcYcubKutD3h1mk697A8vwdtR/Gj0zTvuUnQ/9o3qHSLseAEIiY9/dS6WJnKXRKTonQi2F6DV9NTzFVQl99AH22jq6lIsjbEEKcq/ydFDUpgAq4lyp9nPBHuPXSojdG+1BWuUyjYykaqnLzzqKgRalGzeWmRHd2qeNw8Bz5OWYBw82C3gHRS2BB9VquIgEYktDvgJ5yRfDYkp8qgxHoYeR88ijccWgdvk+WH78OPdwqA7rqdAYcWqn9KNozoxuYddc0fnrHbgaWpanCmPp0gNEeb4r+i9FDGPSkgYBdyrEPHblsDN/Ad1dhLIHEDEtQyv13s6tDRgLVvhowrzqIM+5cm/abyTDhXzSYDfCw2Wf90cBOMsbQBB2N2YRqnrpA50PGp+0IwlPL7qZj1N4JGhvQD0ux8Ood6AiXpdguj7DMP+T0laHIjWee5/xGZB6g3EsCdOZJjVj7hSE/L3eV4No0WcLqJ5DPOgw+FnvQpxndCTc8DW83tNm624lm7scu0A499vEFj1dhtq5gUxsGcqzm09+Vk2V/d0sa77Xocqe3bcfS5lXc/pHrOc1qKlK8kTr2AYNwjeJJ14euuin361WBETd1I6n8eIs02HyBas09o9lT7Nq05jsnbxej6d0q6GH7IYusiBFTJaAZ6UXOV5i1NOcw9jaGyHms3M2N/b2cmXFYTIFZSjSfbqoI6YZF73sMPhEZqfZ5Jjq+ZLMC3A+yFPFJOW/0oolUGbcC8TBVmLi37Z9Wgc338w2Jf+I94SdViku') + 'noXc7Xu7PIKu1tbMkMxLbQG4XU46Bv5dED98hqTkPYZnmb8PG81Q83Kpg541Vt4NQdkzfezDSVk8FP9ZzJ08L0MMb4S8bT78c10Op1LyKwZU6DGr1e3V+ZWcNzHVG1rPoL+eUHN6yR9MQp8/CmSUBQUPOOAUXdoqWohbfIGxoQIuQ5BtfpSJuYD6kTyswSi56wxzY/s24dMwgS2KnA81Y1pdi3ZVJKBdwGYGg4T5Dvcqu0GWv3sScKD9b4Tagfbe2m8nbXY/QtN770c7J1xo/TNXXdq4lyqaMyqIayHOwRBP58tNF8mACusm1pogOVIt456wIMetCGKxicPJr7m/Q02ONzhkMtzzXwgwriglGHfM7UbtTsCytCBP7J2vp0tEkHiq/X3qtuvSLJqNyRzwFJhgisKGftc5CIaT2VxVKKxkL/6Ws6FPm4sQB1UGtMCMftKpyb1lFzG9lwFkKvYN9+FGtvRM50mbrzz7ONDxbwykkxihAab36MIuk7dfhvnVLFAjrpuCkEFdWrtjVyWmM0xVeXpEUtP6Ijk5P+VuPZ1alV/JV1q4WvfrGMizEZbwbp6eQZg9mwKe4IX+FVi7sPF2S/CCLI/d90S5Yz6bBP9uiQ3pCVlYbVOkpwS0YQxnR+h5J50qodY7LuswNO5VlEgI0ztkjPQBr8koT4SM54X2z14tA2tKCxSv1psEL5HOk4IWN+9f3RVfDKBDruDiDd+BtZquhYLmOFat9K4h41NrPGAqv5tKmmJtx3llMs6LFHPKBlNlI5zgqE7T47xv2AWw5nqWM107t8lpRETIgJx+YN/Jv6byJSQm7afaeDtHXGceMPOKMziH1XgsiQiS56OsmyyRgaq5YCmMuaPw8gcgVa7RNZSafkP34aQBAuJOA3JFs5xcYcubKutD3h1mk697A8vwdtR/Gj0zTvuUnQ/9o3qHSLseAEIiY9/dS6WJnKXRKTonQi2F6DV9NTzFVQl99AH22jq6lIsjbEEKcq/ydFDUpgAq4lyp9nPBHuPXSojdG+1BWuUyjYykaqnLzzqKgRalGzeWmRHd2qeNw8Bz5OWYBw82C3gHRS2BB9VquIgEYktDvgJ5yRfDYkp8qgxHoYeR88ijccWgdvk+WH78OPdwqA7rqdAYcWqn9KNozoxuYddc0fnrHbgaWpanCmPp0gNEeb4r+i9FDGPSkgYBdyrEPHblsDN/Ad1dhLIHEDEtQyv13s6tDRgLVvhowrzqIM+5cm/abyTDhXzSYDfCw2Wf90cBOMsbQBB2N2YRqnrpA50PGp+0IwlPL7qZj1N4JGhvQD0ux8Ood6AiXpdguj7DMP+T0laHIjWee5/xGZB6g3EsCdOZJjVj7hSE/L3eV4No0WcLqJ5DPOgw+FnvQpxndCTc8DW83tNm624lm7scu0A499vEFj1dhtq5gUxsGcqzm09+Vk2V/d0sa77Xocqe3bcfS5lXc/pHrOc1qKlK8kTr2AYNwjeJJ14euuin361WBETd1I6n8eIs02HyBas09o9lT7Nq05jsnbxej6d0q6GH7IYusiBFTJaAZ6UXOV5i1NOcw9jaGyHms3M2N/b2cmXFYTIFZSjSfbqoI6YZF73sMPhEZqfZ5Jjq+ZLMC3A+yFPFJOW/0oolUGbcC8TBVmLi37Z9Wgc338w2Jf+I94SdViku' + ) - with self.assertRaisesRegex(ValueError, "Unsupported decryption algorithm: invalid"): - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, 'invalid'), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + with self.assertRaisesRegex(ValueError, 'Unsupported decryption algorithm: invalid'): + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, 'invalid'), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) def test_unseal_invalid_data(self): sealed_data = base64.b64decode( # "{\"invalid\":true}" - 'noXc7VOpBstjjcavDKSKr4HTavt4mdq8h6NC32T0hUtw9S0jXT8lPjZiWL8SyHxmrF3uTGqO+g==') + 'noXc7VOpBstjjcavDKSKr4HTavt4mdq8h6NC32T0hUtw9S0jXT8lPjZiWL8SyHxmrF3uTGqO+g==' + ) - with self.assertRaisesRegex(ValueError, "Sealed data is not valid event response"): - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + with self.assertRaisesRegex(ValueError, 'Sealed data is not valid event response'): + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) def test_unseal_not_compressed_data(self): sealed_data = base64.b64decode( - 'noXc7dtuk0smGE+ZbaoXzrp6Rq8ySxLepejTsu7+jUXlPhV1w+WuHx9gbPhaENJnOQo8BcGmsaRhL5k2NVj+DRNzYO9cQD7wHxmXKCyTbl/dvSYOMoHziUZ2VbQ7tmaorFny26v8jROr/UBGfvPE0dLKC36IN9ZlJ3X0NZJO8SY+8bCr4mTrkVZsv/hpvZp+OjC4h7e5vxcpmnBWXzxfaO79Lq3aMRIEf9XfK7/bVIptHaEqtPKCTwl9rz1KUpUUNQSHTPM0NlqJe9bjYf5mr1uYvWHhcJoXSyRyVMxIv/quRiw3SKJzAMOTBiAvFICpWuRFa+T/xIMHK0g96w/IMQo0jdY1E067ZEvBUOBmsJnGJg1LllS3rbJVe+E2ClFNL8SzFphyvtlcfvYB+SVSD4bzI0w/YCldv5Sq42BFt5bn4n4aE5A6658DYsfSRYWqP6OpqPJx96cY34W7H1t/ZG0ulez6zF5NvWhc1HDQ1gMtXd+K/ogt1n+FyFtn8xzvtSGkmrc2jJgYNI5Pd0Z0ent73z0MKbJx9v2ta/emPEzPr3cndN5amdr6TmRkDU4bq0vyhAh87DJrAnJQLdrvYLddnrr8xTdeXxj1i1Yug6SGncPh9sbTYkdOfuamPAYOuiJVBAMcfYsYEiQndZe8mOQ4bpCr+hxAAqixhZ16pQ8CeUwa247+D2scRymLB8qJXlaERuFZtWGVAZ8VP/GS/9EXjrzpjGX9vlrIPeJP8fh2S5QPzw55cGNJ7JfAdOyManXnoEw2/QzDhSZQARVl+akFgSO0Y13YmbiL7H6HcKWGcJ2ipDKIaj2fJ7GE0Vzyt+CBEezSQR99Igd8x3p2JtvsVKp35iLPksjS1VqtSCTbuIRUlINlfQHNjeQiE/B/61jo3Mf7SmjYjqtvXt5e9RKb+CQku2qH4ZU8xN3DSg+4mLom3BgKBkm/MoyGBpMK41c96d2tRp3tp4hV0F6ac02Crg7P2lw8IUct+i2VJ8VUjcbRfTIPQs0HjNjM6/gLfLCkWOHYrlFjwusXWQCJz91Kq+hVxj7M9LtplPO4AUq6RUMNhlPGUmyOI2tcUMrjq9vMLXGlfdkH185zM4Mk+O7DRLC8683lXZFZvcBEmxr855PqLLH/9SpYKHBoGRatDRdQe3oRp6gHS0jpQ1SW/si4kvLKiUNjiBExvbQVOUV7/VFXvG1RpM9wbzSoOd40gg7ZzD/72QshUC/25DkM/Pm7RBzwtjgmnRKjT+mROeC/7VQLoz3amv09O8Mvbt+h/lX5+51Q834F7NgIGagbB20WtWcMtrmKrvCEZlaoiZrmYVSbi1RfknRK7CTPJkopw9IjO7Ut2EhKZ+jL4rwk6TlVm6EC6Kuj7KNqp6wB/UNe9eM2Eym/aiHAcja8XN4YQhSIuJD2Wxb0n3LkKnAjK1/GY65c8K6rZsVYQ0MQL1j4lMl0UZPjG/vzKyetIsVDyXc4J9ZhOEMYnt/LaxEeSt4EMJGBA9wpTmz33X4h3ij0Y3DY/rH7lrEScUknw20swTZRm5T6q1bnimj7M1OiOkebdI09MZ0nyaTWRHdB7B52C/moh89Q7qa2Fulp5h8Us1FYRkWBLt37a5rGI1IfVeP38KaPbagND+XzWpNqX4HVrAVPLQVK5EwUvGamED3ooJ0FMieTc0IH0N+IeUYG7Q8XmrRVBcw32W8pEfYLO9L71An/J0jQZCIP8DuQnUG0mOvunOuloBGvP/9LvkBlkamh68F0a5f5ny1jloyIFJhRh5dt2SBlbsXS9AKqUwARYSSsA9Ao4WJWOZMyjp8A+qIBAfW65MdhhUDKYMBgIAbMCc3uiptzElQQopE5TT5xIhwfYxa503jVzQbz1Q==') + 'noXc7dtuk0smGE+ZbaoXzrp6Rq8ySxLepejTsu7+jUXlPhV1w+WuHx9gbPhaENJnOQo8BcGmsaRhL5k2NVj+DRNzYO9cQD7wHxmXKCyTbl/dvSYOMoHziUZ2VbQ7tmaorFny26v8jROr/UBGfvPE0dLKC36IN9ZlJ3X0NZJO8SY+8bCr4mTrkVZsv/hpvZp+OjC4h7e5vxcpmnBWXzxfaO79Lq3aMRIEf9XfK7/bVIptHaEqtPKCTwl9rz1KUpUUNQSHTPM0NlqJe9bjYf5mr1uYvWHhcJoXSyRyVMxIv/quRiw3SKJzAMOTBiAvFICpWuRFa+T/xIMHK0g96w/IMQo0jdY1E067ZEvBUOBmsJnGJg1LllS3rbJVe+E2ClFNL8SzFphyvtlcfvYB+SVSD4bzI0w/YCldv5Sq42BFt5bn4n4aE5A6658DYsfSRYWqP6OpqPJx96cY34W7H1t/ZG0ulez6zF5NvWhc1HDQ1gMtXd+K/ogt1n+FyFtn8xzvtSGkmrc2jJgYNI5Pd0Z0ent73z0MKbJx9v2ta/emPEzPr3cndN5amdr6TmRkDU4bq0vyhAh87DJrAnJQLdrvYLddnrr8xTdeXxj1i1Yug6SGncPh9sbTYkdOfuamPAYOuiJVBAMcfYsYEiQndZe8mOQ4bpCr+hxAAqixhZ16pQ8CeUwa247+D2scRymLB8qJXlaERuFZtWGVAZ8VP/GS/9EXjrzpjGX9vlrIPeJP8fh2S5QPzw55cGNJ7JfAdOyManXnoEw2/QzDhSZQARVl+akFgSO0Y13YmbiL7H6HcKWGcJ2ipDKIaj2fJ7GE0Vzyt+CBEezSQR99Igd8x3p2JtvsVKp35iLPksjS1VqtSCTbuIRUlINlfQHNjeQiE/B/61jo3Mf7SmjYjqtvXt5e9RKb+CQku2qH4ZU8xN3DSg+4mLom3BgKBkm/MoyGBpMK41c96d2tRp3tp4hV0F6ac02Crg7P2lw8IUct+i2VJ8VUjcbRfTIPQs0HjNjM6/gLfLCkWOHYrlFjwusXWQCJz91Kq+hVxj7M9LtplPO4AUq6RUMNhlPGUmyOI2tcUMrjq9vMLXGlfdkH185zM4Mk+O7DRLC8683lXZFZvcBEmxr855PqLLH/9SpYKHBoGRatDRdQe3oRp6gHS0jpQ1SW/si4kvLKiUNjiBExvbQVOUV7/VFXvG1RpM9wbzSoOd40gg7ZzD/72QshUC/25DkM/Pm7RBzwtjgmnRKjT+mROeC/7VQLoz3amv09O8Mvbt+h/lX5+51Q834F7NgIGagbB20WtWcMtrmKrvCEZlaoiZrmYVSbi1RfknRK7CTPJkopw9IjO7Ut2EhKZ+jL4rwk6TlVm6EC6Kuj7KNqp6wB/UNe9eM2Eym/aiHAcja8XN4YQhSIuJD2Wxb0n3LkKnAjK1/GY65c8K6rZsVYQ0MQL1j4lMl0UZPjG/vzKyetIsVDyXc4J9ZhOEMYnt/LaxEeSt4EMJGBA9wpTmz33X4h3ij0Y3DY/rH7lrEScUknw20swTZRm5T6q1bnimj7M1OiOkebdI09MZ0nyaTWRHdB7B52C/moh89Q7qa2Fulp5h8Us1FYRkWBLt37a5rGI1IfVeP38KaPbagND+XzWpNqX4HVrAVPLQVK5EwUvGamED3ooJ0FMieTc0IH0N+IeUYG7Q8XmrRVBcw32W8pEfYLO9L71An/J0jQZCIP8DuQnUG0mOvunOuloBGvP/9LvkBlkamh68F0a5f5ny1jloyIFJhRh5dt2SBlbsXS9AKqUwARYSSsA9Ao4WJWOZMyjp8A+qIBAfW65MdhhUDKYMBgIAbMCc3uiptzElQQopE5TT5xIhwfYxa503jVzQbz1Q==' + ) - with self.assertRaisesRegex(UnsealAggregateError, "Unable to decrypt sealed data") as context: - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + with self.assertRaisesRegex( + UnsealAggregateError, 'Unable to decrypt sealed data' + ) as context: + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) exception: UnsealAggregateError = context.exception error: UnsealError = exception.errors[1] - self.assertEqual(str(error.exception), 'Error -3 while decompressing data: invalid distance too far back') + self.assertEqual( + str(error.exception), + 'Error -3 while decompressing data: invalid distance too far back', + ) def test_unseal_all_keys_invalid(self): sealed_data = base64.b64decode( - 'noXc7SXO+mqeAGrvBMgObi/S0fXTpP3zupk8qFqsO/1zdtWCD169iLA3VkkZh9ICHpZ0oWRzqG0M9/TnCeKFohgBLqDp6O0zEfXOv6i5q++aucItznQdLwrKLP+O0blfb4dWVI8/aSbd4ELAZuJJxj9bCoVZ1vk+ShbUXCRZTD30OIEAr3eiG9aw00y1UZIqMgX6CkFlU9L9OnKLsNsyomPIaRHTmgVTI5kNhrnVNyNsnzt9rY7fUD52DQxJILVPrUJ1Q+qW7VyNslzGYBPG0DyYlKbRAomKJDQIkdj/Uwa6bhSTq4XYNVvbk5AJ/dGwvsVdOnkMT2Ipd67KwbKfw5bqQj/cw6bj8Cp2FD4Dy4Ud4daBpPRsCyxBM2jOjVz1B/lAyrOp8BweXOXYugwdPyEn38MBZ5oL4D38jIwR/QiVnMHpERh93jtgwh9Abza6i4/zZaDAbPhtZLXSM5ztdctv8bAb63CppLU541Kf4OaLO3QLvfLRXK2n8bwEwzVAqQ22dyzt6/vPiRbZ5akh8JB6QFXG0QJF9DejsIspKF3JvOKjG2edmC9o+GfL3hwDBiihYXCGY9lElZICAdt+7rZm5UxMx7STrVKy81xcvfaIp1BwGh/HyMsJnkE8IczzRFpLlHGYuNDxdLoBjiifrmHvOCUDcV8UvhSV+UAZtAVejdNGo5G/bz0NF21HUO4pVRPu6RqZIs/aX4hlm6iO/0Ru00ct8pfadUIgRcephTuFC2fHyZxNBC6NApRtLSNLfzYTTo/uSjgcu6rLWiNo5G7yfrM45RXjalFEFzk75Z/fu9lCJJa5uLFgDNKlU+IaFjArfXJCll3apbZp4/LNKiU35ZlB7ZmjDTrji1wLep8iRVVEGht/DW00MTok7Zn7Fv+MlxgWmbZB3BuezwTmXb/fNw==') + 'noXc7SXO+mqeAGrvBMgObi/S0fXTpP3zupk8qFqsO/1zdtWCD169iLA3VkkZh9ICHpZ0oWRzqG0M9/TnCeKFohgBLqDp6O0zEfXOv6i5q++aucItznQdLwrKLP+O0blfb4dWVI8/aSbd4ELAZuJJxj9bCoVZ1vk+ShbUXCRZTD30OIEAr3eiG9aw00y1UZIqMgX6CkFlU9L9OnKLsNsyomPIaRHTmgVTI5kNhrnVNyNsnzt9rY7fUD52DQxJILVPrUJ1Q+qW7VyNslzGYBPG0DyYlKbRAomKJDQIkdj/Uwa6bhSTq4XYNVvbk5AJ/dGwvsVdOnkMT2Ipd67KwbKfw5bqQj/cw6bj8Cp2FD4Dy4Ud4daBpPRsCyxBM2jOjVz1B/lAyrOp8BweXOXYugwdPyEn38MBZ5oL4D38jIwR/QiVnMHpERh93jtgwh9Abza6i4/zZaDAbPhtZLXSM5ztdctv8bAb63CppLU541Kf4OaLO3QLvfLRXK2n8bwEwzVAqQ22dyzt6/vPiRbZ5akh8JB6QFXG0QJF9DejsIspKF3JvOKjG2edmC9o+GfL3hwDBiihYXCGY9lElZICAdt+7rZm5UxMx7STrVKy81xcvfaIp1BwGh/HyMsJnkE8IczzRFpLlHGYuNDxdLoBjiifrmHvOCUDcV8UvhSV+UAZtAVejdNGo5G/bz0NF21HUO4pVRPu6RqZIs/aX4hlm6iO/0Ru00ct8pfadUIgRcephTuFC2fHyZxNBC6NApRtLSNLfzYTTo/uSjgcu6rLWiNo5G7yfrM45RXjalFEFzk75Z/fu9lCJJa5uLFgDNKlU+IaFjArfXJCll3apbZp4/LNKiU35ZlB7ZmjDTrji1wLep8iRVVEGht/DW00MTok7Zn7Fv+MlxgWmbZB3BuezwTmXb/fNw==' + ) with self.assertRaisesRegex(UnsealAggregateError, 'Unable to decrypt sealed data'): - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) def test_unseal_empty_data(self): sealed_data = bytearray(b'') with self.assertRaisesRegex(ValueError, 'Invalid sealed data header'): - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) def test_unseal_invalid_nonce(self): sealed_data = bytes([0x9E, 0x85, 0xDC, 0xED, 0xAA, 0xBB, 0xCC]) - with self.assertRaisesRegex(UnsealAggregateError, 'Unable to decrypt sealed data') as context: - unseal_event_response(sealed_data, [ - DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), - DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), - ]) + with self.assertRaisesRegex( + UnsealAggregateError, 'Unable to decrypt sealed data' + ) as context: + unseal_event_response( + sealed_data, + [ + DecryptionKey(self.invalid_key, DecryptionAlgorithm['Aes256Gcm']), + DecryptionKey(self.valid_key, DecryptionAlgorithm['Aes256Gcm']), + ], + ) exception: UnsealAggregateError = context.exception error: UnsealError = exception.errors[1] - self.assertEqual(str(error.exception), 'initialization_vector must be between 8 and 128 bytes (64 and 1024 bits).') - - + self.assertEqual( + str(error.exception), + 'initialization_vector must be between 8 and 128 bytes (64 and 1024 bits).', + ) diff --git a/test/test_webhook_validation.py b/test/test_webhook_validation.py index 18e80b30..0175459e 100644 --- a/test/test_webhook_validation.py +++ b/test/test_webhook_validation.py @@ -4,37 +4,41 @@ class TestWebhookValidation(unittest.TestCase): - valid_header = "v1=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db" - valid_header_v2 = "v2=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db" - secret = "secret" - data = b"data" + valid_header = 'v1=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db' + valid_header_v2 = 'v2=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db' + secret = 'secret' + data = b'data' def test_valid_header(self): - result = WebhookValidation.is_valid_webhook_signature(self.valid_header, self.data, self.secret) + result = WebhookValidation.is_valid_webhook_signature( + self.valid_header, self.data, self.secret + ) self.assertTrue(result) def test_invalid_header(self): - result = WebhookValidation.is_valid_webhook_signature("v2=invalid", self.data, self.secret) + result = WebhookValidation.is_valid_webhook_signature('v2=invalid', self.data, self.secret) self.assertFalse(result) def test_header_without_version(self): - result = WebhookValidation.is_valid_webhook_signature("invalid", self.data, self.secret) + result = WebhookValidation.is_valid_webhook_signature('invalid', self.data, self.secret) self.assertFalse(result) def test_header_with_unsupported_version(self): - result = WebhookValidation.is_valid_webhook_signature(self.valid_header_v2, self.data, self.secret) + result = WebhookValidation.is_valid_webhook_signature( + self.valid_header_v2, self.data, self.secret + ) self.assertFalse(result) def test_empty_header(self): - result = WebhookValidation.is_valid_webhook_signature("", self.data, self.secret) + result = WebhookValidation.is_valid_webhook_signature('', self.data, self.secret) self.assertFalse(result) def test_empty_secret(self): - result = WebhookValidation.is_valid_webhook_signature("invalid", self.data, "") + result = WebhookValidation.is_valid_webhook_signature('invalid', self.data, '') self.assertFalse(result) def test_empty_data(self): - result = WebhookValidation.is_valid_webhook_signature(self.valid_header, b"", self.secret) + result = WebhookValidation.is_valid_webhook_signature(self.valid_header, b'', self.secret) self.assertFalse(result) diff --git a/update_event_example.py b/update_event_example.py index a6c86b68..0cbfe151 100644 --- a/update_event_example.py +++ b/update_event_example.py @@ -1,12 +1,12 @@ -import os import argparse +import os + +from dotenv import load_dotenv import fingerprint_server_sdk -from fingerprint_server_sdk.rest import ApiException from fingerprint_server_sdk.configuration import Region from fingerprint_server_sdk.models import EventUpdate - -from dotenv import load_dotenv +from fingerprint_server_sdk.rest import ApiException load_dotenv() parser = argparse.ArgumentParser(description='Update an event in the Fingerprint Server API') @@ -18,22 +18,23 @@ print(f'args: {args.linked_id}, {args.tag}, {args.suspect}') # configure -region_str = os.environ.get("REGION", "us").upper() +region_str = os.environ.get('REGION', 'us').upper() configuration = fingerprint_server_sdk.Configuration( - api_key=os.environ["PRIVATE_KEY"], region=Region[region_str]) + api_key=os.environ['PRIVATE_KEY'], region=Region[region_str] +) # create an instance of the API class api_instance = fingerprint_server_sdk.FingerprintApi(configuration) -event_id = os.environ["EVENT_ID_TO_UPDATE"] +event_id = os.environ['EVENT_ID_TO_UPDATE'] try: updateBody = EventUpdate(**vars(args)) print(f'updateBody: {updateBody}') api_instance.update_event(event_id, updateBody) except ApiException as e: - print("Exception when calling update_event operation: %s\n" % e) + print(f'Exception when calling update_event operation: {e}\n') exit(1) -print("Visitor data updated!") +print('Visitor data updated!') exit(0) diff --git a/webhook_signature_example.py b/webhook_signature_example.py index 71def49c..d1cc8a5f 100644 --- a/webhook_signature_example.py +++ b/webhook_signature_example.py @@ -1,9 +1,9 @@ from fingerprint_server_sdk import WebhookValidation -header = "v1=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db" -secret = "secret" -data = b"data" +header = 'v1=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db' +secret = 'secret' +data = b'data' is_valid = WebhookValidation.is_valid_webhook_signature(header, data, secret) -print("Webhook signature is correct!" if is_valid else "Webhook signature is incorrect!") +print('Webhook signature is correct!' if is_valid else 'Webhook signature is incorrect!')