From e5ff22dfd708b6676d2a1aae699167f84fcbaab5 Mon Sep 17 00:00:00 2001 From: Javid Date: Fri, 24 Jul 2026 16:48:23 +0330 Subject: [PATCH 1/2] feat: generate Python SDK from public contract --- .corelink-contract.json | 10 + .gitignore | 66 ++ .openapi-generator-ignore | 23 + .openapi-generator/FILES | 51 + .openapi-generator/VERSION | 1 + CODEGEN.md | 18 + README.md | 35 +- corelink_sdk/__init__.py | 46 + corelink_sdk/api/__init__.py | 7 + corelink_sdk/api/commands_api.py | 988 +++++++++++++++++++ corelink_sdk/api/default_api.py | 520 ++++++++++ corelink_sdk/api/devices_api.py | 1272 +++++++++++++++++++++++++ corelink_sdk/api_client.py | 797 ++++++++++++++++ corelink_sdk/api_response.py | 21 + corelink_sdk/configuration.py | 582 +++++++++++ corelink_sdk/exceptions.py | 216 +++++ corelink_sdk/models/__init__.py | 27 + corelink_sdk/models/command.py | 128 +++ corelink_sdk/models/command_create.py | 95 ++ corelink_sdk/models/command_page.py | 101 ++ corelink_sdk/models/command_status.py | 43 + corelink_sdk/models/device.py | 123 +++ corelink_sdk/models/device_create.py | 96 ++ corelink_sdk/models/device_page.py | 101 ++ corelink_sdk/models/device_status.py | 40 + corelink_sdk/models/device_update.py | 102 ++ corelink_sdk/models/health.py | 94 ++ corelink_sdk/models/problem.py | 97 ++ corelink_sdk/py.typed | 0 corelink_sdk/rest.py | 258 +++++ pyproject.toml | 81 ++ requirements.txt | 4 + test/__init__.py | 0 test/test_command.py | 73 ++ test/test_command_create.py | 55 ++ test/test_command_page.py | 88 ++ test/test_command_status.py | 33 + test/test_commands_api.py | 49 + test/test_default_api.py | 43 + test/test_device.py | 67 ++ test/test_device_create.py | 56 ++ test/test_device_page.py | 82 ++ test/test_device_status.py | 33 + test/test_device_update.py | 53 ++ test/test_devices_api.py | 55 ++ test/test_health.py | 52 + test/test_problem.py | 61 ++ 47 files changed, 6829 insertions(+), 14 deletions(-) create mode 100644 .corelink-contract.json create mode 100644 .gitignore create mode 100644 .openapi-generator-ignore create mode 100644 .openapi-generator/FILES create mode 100644 .openapi-generator/VERSION create mode 100644 CODEGEN.md create mode 100644 corelink_sdk/__init__.py create mode 100644 corelink_sdk/api/__init__.py create mode 100644 corelink_sdk/api/commands_api.py create mode 100644 corelink_sdk/api/default_api.py create mode 100644 corelink_sdk/api/devices_api.py create mode 100644 corelink_sdk/api_client.py create mode 100644 corelink_sdk/api_response.py create mode 100644 corelink_sdk/configuration.py create mode 100644 corelink_sdk/exceptions.py create mode 100644 corelink_sdk/models/__init__.py create mode 100644 corelink_sdk/models/command.py create mode 100644 corelink_sdk/models/command_create.py create mode 100644 corelink_sdk/models/command_page.py create mode 100644 corelink_sdk/models/command_status.py create mode 100644 corelink_sdk/models/device.py create mode 100644 corelink_sdk/models/device_create.py create mode 100644 corelink_sdk/models/device_page.py create mode 100644 corelink_sdk/models/device_status.py create mode 100644 corelink_sdk/models/device_update.py create mode 100644 corelink_sdk/models/health.py create mode 100644 corelink_sdk/models/problem.py create mode 100644 corelink_sdk/py.typed create mode 100644 corelink_sdk/rest.py create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 test/__init__.py create mode 100644 test/test_command.py create mode 100644 test/test_command_create.py create mode 100644 test/test_command_page.py create mode 100644 test/test_command_status.py create mode 100644 test/test_commands_api.py create mode 100644 test/test_default_api.py create mode 100644 test/test_device.py create mode 100644 test/test_device_create.py create mode 100644 test/test_device_page.py create mode 100644 test/test_device_status.py create mode 100644 test/test_device_update.py create mode 100644 test/test_devices_api.py create mode 100644 test/test_health.py create mode 100644 test/test_problem.py diff --git a/.corelink-contract.json b/.corelink-contract.json new file mode 100644 index 0000000..e28071f --- /dev/null +++ b/.corelink-contract.json @@ -0,0 +1,10 @@ +{ + "contract": "corelink-public-v1.yaml", + "contractVersion": "1.0.0-draft", + "sourceRepository": "CoreLinkPlatform/api-contracts", + "sourceBranch": "agent/p3-1-contracts", + "sourceCommit": "701e693", + "generator": "openapi-generator-cli", + "generatorVersion": "7.12.0", + "generatorName": "python" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..43995bd --- /dev/null +++ b/.gitignore @@ -0,0 +1,66 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.venv/ +.python-version +.pytest_cache + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/.openapi-generator-ignore b/.openapi-generator-ignore new file mode 100644 index 0000000..7484ee5 --- /dev/null +++ b/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES new file mode 100644 index 0000000..9bc8dd8 --- /dev/null +++ b/.openapi-generator/FILES @@ -0,0 +1,51 @@ +.github/workflows/python.yml +.gitignore +.gitlab-ci.yml +.openapi-generator-ignore +.travis.yml +README.md +corelink_sdk/__init__.py +corelink_sdk/api/__init__.py +corelink_sdk/api/commands_api.py +corelink_sdk/api/default_api.py +corelink_sdk/api/devices_api.py +corelink_sdk/api_client.py +corelink_sdk/api_response.py +corelink_sdk/configuration.py +corelink_sdk/exceptions.py +corelink_sdk/models/__init__.py +corelink_sdk/models/command.py +corelink_sdk/models/command_create.py +corelink_sdk/models/command_page.py +corelink_sdk/models/command_status.py +corelink_sdk/models/device.py +corelink_sdk/models/device_create.py +corelink_sdk/models/device_page.py +corelink_sdk/models/device_status.py +corelink_sdk/models/device_update.py +corelink_sdk/models/health.py +corelink_sdk/models/problem.py +corelink_sdk/py.typed +corelink_sdk/rest.py +git_push.sh +pyproject.toml +requirements.txt +setup.cfg +setup.py +test-requirements.txt +test/__init__.py +test/test_command.py +test/test_command_create.py +test/test_command_page.py +test/test_command_status.py +test/test_commands_api.py +test/test_default_api.py +test/test_device.py +test/test_device_create.py +test/test_device_page.py +test/test_device_status.py +test/test_device_update.py +test/test_devices_api.py +test/test_health.py +test/test_problem.py +tox.ini diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION new file mode 100644 index 0000000..5f84a81 --- /dev/null +++ b/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.12.0 diff --git a/CODEGEN.md b/CODEGEN.md new file mode 100644 index 0000000..390e841 --- /dev/null +++ b/CODEGEN.md @@ -0,0 +1,18 @@ +# Python SDK generation + +This client is generated from `corelink-public-v1.yaml` with OpenAPI Generator +`7.12.0`. The authoritative input for this prerelease was contract commit +`701e693` on `agent/p3-1-contracts`. + +```sh +java -jar openapi-generator-cli-7.12.0.jar generate \ + -i /path/to/corelink-public-v1.yaml \ + -g python \ + -o . \ + --additional-properties=packageName=corelink_sdk,projectName=corelink-sdk,packageVersion=0.1.0.dev0 \ + --global-property=apiDocs=false,modelDocs=false +``` + +Regenerate in a clean worktree, restore this README and package metadata, then +run `python -m compileall corelink_sdk`. A release may only use a merged, +tagged contract commit. diff --git a/README.md b/README.md index 315661c..508c269 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,30 @@ # CoreLink Python SDK -Official Python SDK for CoreLink APIs. +Generated prerelease client for the CoreLink Public API. It is not published or +production-supported until its contract and runtime PRs are merged and sandbox +compatibility tests pass. -> Status: Planned. This repository does not contain a released package yet. +## Contract provenance -## Planned capabilities +- Contract: `corelink-public-v1.yaml`, version `1.0.0-draft` +- Source branch: `agent/p3-1-contracts` +- Source commit: `701e693` +- Generator: OpenAPI Generator `7.12.0`, `python` -- OAuth client credentials -- Device registry -- Provisioning -- Commands -- Pagination -- Typed errors -- Webhook verification +The SDK exposes canonical CoreLink identifiers only. Connector selection and +integration-provider identifiers remain server-side concerns. -## Documentation +## Local verification -See the [CoreLink developer documentation](https://github.com/CoreLinkPlatform/developer-docs). +```sh +python -m compileall corelink_sdk +``` -## License +See [CODEGEN.md](CODEGEN.md) for deterministic regeneration. Generated files +under `corelink_sdk/` are not hand-maintained. -License information will be added before the first public release. +## Release gate + +Publish only after a merged, tagged contract, sandbox compatibility tests, +clean generated diff, package build, and release notes that record the exact +contract commit. diff --git a/corelink_sdk/__init__.py b/corelink_sdk/__init__.py new file mode 100644 index 0000000..d74c60b --- /dev/null +++ b/corelink_sdk/__init__.py @@ -0,0 +1,46 @@ +# coding: utf-8 + +# flake8: noqa + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +__version__ = "0.1.0.dev0" + +# import apis into sdk package +from corelink_sdk.api.commands_api import CommandsApi +from corelink_sdk.api.devices_api import DevicesApi +from corelink_sdk.api.default_api import DefaultApi + +# import ApiClient +from corelink_sdk.api_response import ApiResponse +from corelink_sdk.api_client import ApiClient +from corelink_sdk.configuration import Configuration +from corelink_sdk.exceptions import OpenApiException +from corelink_sdk.exceptions import ApiTypeError +from corelink_sdk.exceptions import ApiValueError +from corelink_sdk.exceptions import ApiKeyError +from corelink_sdk.exceptions import ApiAttributeError +from corelink_sdk.exceptions import ApiException + +# import models into sdk package +from corelink_sdk.models.command import Command +from corelink_sdk.models.command_create import CommandCreate +from corelink_sdk.models.command_page import CommandPage +from corelink_sdk.models.command_status import CommandStatus +from corelink_sdk.models.device import Device +from corelink_sdk.models.device_create import DeviceCreate +from corelink_sdk.models.device_page import DevicePage +from corelink_sdk.models.device_status import DeviceStatus +from corelink_sdk.models.device_update import DeviceUpdate +from corelink_sdk.models.health import Health +from corelink_sdk.models.problem import Problem diff --git a/corelink_sdk/api/__init__.py b/corelink_sdk/api/__init__.py new file mode 100644 index 0000000..376b90e --- /dev/null +++ b/corelink_sdk/api/__init__.py @@ -0,0 +1,7 @@ +# flake8: noqa + +# import apis into api package +from corelink_sdk.api.commands_api import CommandsApi +from corelink_sdk.api.devices_api import DevicesApi +from corelink_sdk.api.default_api import DefaultApi + diff --git a/corelink_sdk/api/commands_api.py b/corelink_sdk/api/commands_api.py new file mode 100644 index 0000000..5c79d97 --- /dev/null +++ b/corelink_sdk/api/commands_api.py @@ -0,0 +1,988 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + 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 pydantic import Field, StrictStr +from typing import Optional +from typing_extensions import Annotated +from corelink_sdk.models.command import Command +from corelink_sdk.models.command_create import CommandCreate +from corelink_sdk.models.command_page import CommandPage + +from corelink_sdk.api_client import ApiClient, RequestSerialized +from corelink_sdk.api_response import ApiResponse +from corelink_sdk.rest import RESTResponseType + + +class CommandsApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_device_command( + self, + idempotency_key: Annotated[str, Field(min_length=1, strict=True, max_length=255)], + tenant_id: StrictStr, + corelink_device_id: StrictStr, + command_create: CommandCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Command: + """create_device_command + + + :param idempotency_key: (required) + :type idempotency_key: str + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param command_create: (required) + :type command_create: CommandCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_device_command_serialize( + idempotency_key=idempotency_key, + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + command_create=command_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "Command", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '404': "Problem", + '409': "Problem", + } + 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 create_device_command_with_http_info( + self, + idempotency_key: Annotated[str, Field(min_length=1, strict=True, max_length=255)], + tenant_id: StrictStr, + corelink_device_id: StrictStr, + command_create: CommandCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Command]: + """create_device_command + + + :param idempotency_key: (required) + :type idempotency_key: str + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param command_create: (required) + :type command_create: CommandCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_device_command_serialize( + idempotency_key=idempotency_key, + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + command_create=command_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "Command", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '404': "Problem", + '409': "Problem", + } + 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 create_device_command_without_preload_content( + self, + idempotency_key: Annotated[str, Field(min_length=1, strict=True, max_length=255)], + tenant_id: StrictStr, + corelink_device_id: StrictStr, + command_create: CommandCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """create_device_command + + + :param idempotency_key: (required) + :type idempotency_key: str + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param command_create: (required) + :type command_create: CommandCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_device_command_serialize( + idempotency_key=idempotency_key, + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + command_create=command_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "Command", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '404': "Problem", + '409': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_device_command_serialize( + self, + idempotency_key, + tenant_id, + corelink_device_id, + command_create, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + if corelink_device_id is not None: + _path_params['corelink_device_id'] = corelink_device_id + # process the query parameters + # process the header parameters + if idempotency_key is not None: + _header_params['Idempotency-Key'] = idempotency_key + # process the form parameters + # process the body parameter + if command_create is not None: + _body_params = command_create + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+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' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/api/v1/tenants/{tenant_id}/devices/{corelink_device_id}/commands', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_device_command( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + command_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Command: + """get_device_command + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param command_id: (required) + :type command_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_device_command_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + command_id=command_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Command", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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_device_command_with_http_info( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + command_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Command]: + """get_device_command + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param command_id: (required) + :type command_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_device_command_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + command_id=command_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Command", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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_device_command_without_preload_content( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + command_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """get_device_command + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param command_id: (required) + :type command_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_device_command_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + command_id=command_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Command", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_device_command_serialize( + self, + tenant_id, + corelink_device_id, + command_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + if corelink_device_id is not None: + _path_params['corelink_device_id'] = corelink_device_id + if command_id is not None: + _path_params['command_id'] = command_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/tenants/{tenant_id}/devices/{corelink_device_id}/commands/{command_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_device_commands( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + limit: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = None, + offset: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> CommandPage: + """list_device_commands + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param limit: + :type limit: int + :param offset: + :type offset: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_device_commands_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + limit=limit, + offset=offset, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CommandPage", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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 list_device_commands_with_http_info( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + limit: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = None, + offset: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[CommandPage]: + """list_device_commands + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param limit: + :type limit: int + :param offset: + :type offset: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_device_commands_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + limit=limit, + offset=offset, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CommandPage", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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 list_device_commands_without_preload_content( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + limit: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = None, + offset: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """list_device_commands + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param limit: + :type limit: int + :param offset: + :type offset: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_device_commands_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + limit=limit, + offset=offset, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "CommandPage", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_device_commands_serialize( + self, + tenant_id, + corelink_device_id, + limit, + offset, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + if corelink_device_id is not None: + _path_params['corelink_device_id'] = corelink_device_id + # process the query parameters + if limit is not None: + + _query_params.append(('limit', limit)) + + if offset is not None: + + _query_params.append(('offset', offset)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/tenants/{tenant_id}/devices/{corelink_device_id}/commands', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/corelink_sdk/api/default_api.py b/corelink_sdk/api/default_api.py new file mode 100644 index 0000000..f8fcc7b --- /dev/null +++ b/corelink_sdk/api/default_api.py @@ -0,0 +1,520 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + 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 corelink_sdk.models.health import Health + +from corelink_sdk.api_client import ApiClient, RequestSerialized +from corelink_sdk.api_response import ApiResponse +from corelink_sdk.rest import RESTResponseType + + +class DefaultApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def get_live_health( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Health: + """get_live_health + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_live_health_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Health", + } + 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_live_health_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Health]: + """get_live_health + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_live_health_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Health", + } + 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_live_health_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """get_live_health + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_live_health_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Health", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_live_health_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/health/live', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_readiness( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Health: + """get_readiness + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_readiness_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Health", + } + 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_readiness_with_http_info( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Health]: + """get_readiness + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_readiness_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Health", + } + 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_readiness_without_preload_content( + self, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """get_readiness + + + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_readiness_serialize( + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Health", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_readiness_serialize( + self, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/health/ready', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/corelink_sdk/api/devices_api.py b/corelink_sdk/api/devices_api.py new file mode 100644 index 0000000..17c6b67 --- /dev/null +++ b/corelink_sdk/api/devices_api.py @@ -0,0 +1,1272 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + 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 pydantic import Field, StrictStr +from typing import Optional +from typing_extensions import Annotated +from corelink_sdk.models.device import Device +from corelink_sdk.models.device_create import DeviceCreate +from corelink_sdk.models.device_page import DevicePage +from corelink_sdk.models.device_status import DeviceStatus +from corelink_sdk.models.device_update import DeviceUpdate + +from corelink_sdk.api_client import ApiClient, RequestSerialized +from corelink_sdk.api_response import ApiResponse +from corelink_sdk.rest import RESTResponseType + + +class DevicesApi: + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None) -> None: + if api_client is None: + api_client = ApiClient.get_default() + self.api_client = api_client + + + @validate_call + def create_device( + self, + tenant_id: StrictStr, + device_create: DeviceCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Device: + """create_device + + + :param tenant_id: (required) + :type tenant_id: str + :param device_create: (required) + :type device_create: DeviceCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_device_serialize( + tenant_id=tenant_id, + device_create=device_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "Device", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '409': "Problem", + } + 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 create_device_with_http_info( + self, + tenant_id: StrictStr, + device_create: DeviceCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Device]: + """create_device + + + :param tenant_id: (required) + :type tenant_id: str + :param device_create: (required) + :type device_create: DeviceCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_device_serialize( + tenant_id=tenant_id, + device_create=device_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "Device", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '409': "Problem", + } + 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 create_device_without_preload_content( + self, + tenant_id: StrictStr, + device_create: DeviceCreate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """create_device + + + :param tenant_id: (required) + :type tenant_id: str + :param device_create: (required) + :type device_create: DeviceCreate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._create_device_serialize( + tenant_id=tenant_id, + device_create=device_create, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '201': "Device", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '409': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _create_device_serialize( + self, + tenant_id, + device_create, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if device_create is not None: + _body_params = device_create + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+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' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='POST', + resource_path='/api/v1/tenants/{tenant_id}/devices', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def get_device( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Device: + """get_device + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_device_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Device", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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_device_with_http_info( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Device]: + """get_device + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_device_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Device", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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_device_without_preload_content( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """get_device + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_device_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Device", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_device_serialize( + self, + tenant_id, + corelink_device_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + if corelink_device_id is not None: + _path_params['corelink_device_id'] = corelink_device_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/tenants/{tenant_id}/devices/{corelink_device_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def list_devices( + self, + tenant_id: StrictStr, + limit: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = None, + offset: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + status: Optional[DeviceStatus] = None, + device_model_id: Optional[StrictStr] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> DevicePage: + """list_devices + + + :param tenant_id: (required) + :type tenant_id: str + :param limit: + :type limit: int + :param offset: + :type offset: int + :param status: + :type status: DeviceStatus + :param device_model_id: + :type device_model_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_devices_serialize( + tenant_id=tenant_id, + limit=limit, + offset=offset, + status=status, + device_model_id=device_model_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DevicePage", + '401': "Problem", + '403': "Problem", + } + 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 list_devices_with_http_info( + self, + tenant_id: StrictStr, + limit: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = None, + offset: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + status: Optional[DeviceStatus] = None, + device_model_id: Optional[StrictStr] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[DevicePage]: + """list_devices + + + :param tenant_id: (required) + :type tenant_id: str + :param limit: + :type limit: int + :param offset: + :type offset: int + :param status: + :type status: DeviceStatus + :param device_model_id: + :type device_model_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_devices_serialize( + tenant_id=tenant_id, + limit=limit, + offset=offset, + status=status, + device_model_id=device_model_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DevicePage", + '401': "Problem", + '403': "Problem", + } + 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 list_devices_without_preload_content( + self, + tenant_id: StrictStr, + limit: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = None, + offset: Optional[Annotated[int, Field(strict=True, ge=0)]] = None, + status: Optional[DeviceStatus] = None, + device_model_id: Optional[StrictStr] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """list_devices + + + :param tenant_id: (required) + :type tenant_id: str + :param limit: + :type limit: int + :param offset: + :type offset: int + :param status: + :type status: DeviceStatus + :param device_model_id: + :type device_model_id: str + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._list_devices_serialize( + tenant_id=tenant_id, + limit=limit, + offset=offset, + status=status, + device_model_id=device_model_id, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "DevicePage", + '401': "Problem", + '403': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _list_devices_serialize( + self, + tenant_id, + limit, + offset, + status, + device_model_id, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + # process the query parameters + if limit is not None: + + _query_params.append(('limit', limit)) + + if offset is not None: + + _query_params.append(('offset', offset)) + + if status is not None: + + _query_params.append(('status', status.value)) + + if device_model_id is not None: + + _query_params.append(('device_model_id', device_model_id)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/tenants/{tenant_id}/devices', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + + + + @validate_call + def update_device( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + device_update: DeviceUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> Device: + """update_device + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param device_update: (required) + :type device_update: DeviceUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_device_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + device_update=device_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Device", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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 update_device_with_http_info( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + device_update: DeviceUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[Device]: + """update_device + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param device_update: (required) + :type device_update: DeviceUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_device_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + device_update=device_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Device", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + 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_device_without_preload_content( + self, + tenant_id: StrictStr, + corelink_device_id: StrictStr, + device_update: DeviceUpdate, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """update_device + + + :param tenant_id: (required) + :type tenant_id: str + :param corelink_device_id: (required) + :type corelink_device_id: str + :param device_update: (required) + :type device_update: DeviceUpdate + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._update_device_serialize( + tenant_id=tenant_id, + corelink_device_id=corelink_device_id, + device_update=device_update, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "Device", + '400': "Problem", + '401': "Problem", + '403': "Problem", + '404': "Problem", + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _update_device_serialize( + self, + tenant_id, + corelink_device_id, + device_update, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> RequestSerialized: + + _host = None + + _collection_formats: Dict[str, str] = { + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[ + str, Union[str, bytes, List[str], List[bytes], List[Tuple[str, bytes]]] + ] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + if tenant_id is not None: + _path_params['tenant_id'] = tenant_id + if corelink_device_id is not None: + _path_params['corelink_device_id'] = corelink_device_id + # process the query parameters + # process the header parameters + # process the form parameters + # process the body parameter + if device_update is not None: + _body_params = device_update + + + # set the HTTP header `Accept` + if 'Accept' not in _header_params: + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json', + 'application/problem+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' + ] + ) + ) + if _default_content_type is not None: + _header_params['Content-Type'] = _default_content_type + + # authentication setting + _auth_settings: List[str] = [ + 'bearerAuth' + ] + + return self.api_client.param_serialize( + method='PATCH', + resource_path='/api/v1/tenants/{tenant_id}/devices/{corelink_device_id}', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/corelink_sdk/api_client.py b/corelink_sdk/api_client.py new file mode 100644 index 0000000..d467b1e --- /dev/null +++ b/corelink_sdk/api_client.py @@ -0,0 +1,797 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import datetime +from dateutil.parser import parse +from enum import Enum +import decimal +import json +import mimetypes +import os +import re +import tempfile + +from urllib.parse import quote +from typing import Tuple, Optional, List, Dict, Union +from pydantic import SecretStr + +from corelink_sdk.configuration import Configuration +from corelink_sdk.api_response import ApiResponse, T as ApiResponseT +import corelink_sdk.models +from corelink_sdk import rest +from corelink_sdk.exceptions import ( + ApiValueError, + ApiException, + BadRequestException, + UnauthorizedException, + ForbiddenException, + NotFoundException, + ServiceException +) + +RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]] + +class ApiClient: + """Generic API client for OpenAPI client library builds. + + OpenAPI generic API client. This client handles the client- + server communication, and is invariant across implementations. Specifics of + the methods and models for each application are generated from the OpenAPI + templates. + + :param configuration: .Configuration object for this client + :param header_name: a header to pass when making calls to the API. + :param header_value: a header value to pass when making calls to + the API. + :param cookie: a cookie to include in the header when making calls + to the API + """ + + 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, + 'date': datetime.date, + 'datetime': datetime.datetime, + 'decimal': decimal.Decimal, + 'object': object, + } + _pool = None + + def __init__( + self, + configuration=None, + header_name=None, + header_value=None, + cookie=None + ) -> None: + # use default configuration if none is provided + if configuration is None: + configuration = Configuration.get_default() + self.configuration = configuration + + self.rest_client = rest.RESTClientObject(configuration) + self.default_headers = {} + if header_name is not None: + self.default_headers[header_name] = header_value + self.cookie = cookie + # Set default User-Agent. + self.user_agent = 'OpenAPI-Generator/0.1.0.dev0/python' + self.client_side_validation = configuration.client_side_validation + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + pass + + @property + def user_agent(self): + """User agent for this API client""" + return self.default_headers['User-Agent'] + + @user_agent.setter + def user_agent(self, value): + self.default_headers['User-Agent'] = value + + def set_default_header(self, header_name, header_value): + self.default_headers[header_name] = header_value + + + _default = None + + @classmethod + def get_default(cls): + """Return new instance of ApiClient. + + This method returns newly created, based on default constructor, + object of ApiClient class or returns a copy of default + ApiClient. + + :return: The ApiClient object. + """ + if cls._default is None: + cls._default = ApiClient() + return cls._default + + @classmethod + def set_default(cls, default): + """Set default instance of ApiClient. + + It stores default ApiClient. + + :param default: object of ApiClient. + """ + cls._default = default + + 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 + ) -> RequestSerialized: + + """Builds the HTTP request params needed by the request. + :param method: Method to call. + :param resource_path: Path to method endpoint. + :param path_params: Path parameters in the url. + :param query_params: Query parameters in the url. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param auth_settings list: Auth Settings names for the request. + :param files dict: key -> filename, value -> filepath, + for `multipart/form-data`. + :param collection_formats: dict of collection formats for path, query, + header, and post parameters. + :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. + :return: tuple of form (path, http_method, query_params, header_params, + body, post_params, files) + """ + + config = self.configuration + + # header parameters + header_params = header_params or {} + header_params.update(self.default_headers) + if self.cookie: + 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) + ) + + # path parameters + if path_params: + path_params = self.sanitize_for_serialization(path_params) + path_params = self.parameters_to_tuples( + path_params, + collection_formats + ) + for k, v in path_params: + # specified safe chars, encode everything + resource_path = resource_path.replace( + '{%s}' % k, + quote(str(v), safe=config.safe_chars_for_path_param) + ) + + # post parameters + 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 + ) + if files: + post_params.extend(self.files_parameters(files)) + + # auth setting + self.update_params_for_auth( + header_params, + query_params, + auth_settings, + resource_path, + method, + body, + request_auth=_request_auth + ) + + # body + if body: + body = self.sanitize_for_serialization(body) + + # request url + if _host is None or self.configuration.ignore_operation_servers: + url = self.configuration.host + resource_path + else: + # use server/host defined in path or operation instead + url = _host + resource_path + + # 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 + + + def call_api( + self, + method, + url, + header_params=None, + body=None, + post_params=None, + _request_timeout=None + ) -> rest.RESTResponse: + """Makes the HTTP request (synchronous) + :param method: Method to call. + :param url: Path to method endpoint. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param _request_timeout: timeout setting for this request. + :return: RESTResponse + """ + + try: + # perform request and return response + response_data = self.rest_client.request( + method, url, + headers=header_params, + body=body, post_params=post_params, + _request_timeout=_request_timeout + ) + + except ApiException as e: + raise e + + return response_data + + def response_deserialize( + self, + response_data: rest.RESTResponse, + response_types_map: Optional[Dict[str, ApiResponseT]]=None + ) -> ApiResponse[ApiResponseT]: + """Deserializes response into an object. + :param response_data: RESTResponse object to be deserialized. + :param response_types_map: dict of response types. + :return: ApiResponse + """ + + 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 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) + + # deserialize response data + response_text = None + return_data = None + try: + if response_type == "bytearray": + return_data = response_data.data + 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" + response_text = response_data.data.decode(encoding) + return_data = self.deserialize(response_text, response_type, content_type) + finally: + if not 200 <= response_data.status <= 299: + raise ApiException.from_response( + http_resp=response_data, + body=response_text, + data=return_data, + ) + + return ApiResponse( + status_code = response_data.status, + data = return_data, + headers = response_data.getheaders(), + raw_data = response_data.data + ) + + def sanitize_for_serialization(self, obj): + """Builds a JSON POST object. + + If obj is None, return None. + If obj is SecretStr, return obj.get_secret_value() + If obj is str, int, long, float, bool, return directly. + If obj is datetime.datetime, datetime.date + convert to string in iso8601 format. + If obj is decimal.Decimal return string representation. + If obj is list, sanitize each element in the list. + If obj is dict, return the dict. + If obj is OpenAPI model, return the properties dict. + + :param obj: The data to serialize. + :return: The serialized form of data. + """ + if obj is None: + return None + elif isinstance(obj, Enum): + return obj.value + elif isinstance(obj, SecretStr): + return obj.get_secret_value() + elif isinstance(obj, self.PRIMITIVE_TYPES): + return obj + elif isinstance(obj, list): + 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 + ) + elif isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + elif isinstance(obj, decimal.Decimal): + return str(obj) + + elif isinstance(obj, dict): + obj_dict = obj + else: + # Convert model obj to dict except + # attributes `openapi_types`, `attribute_map` + # 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')): + obj_dict = obj.to_dict() + else: + obj_dict = obj.__dict__ + + 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]): + """Deserializes response into an object. + + :param response: RESTResponse object to be deserialized. + :param response_type: class literal for + deserialized object, or string of class name. + :param content_type: content type of response. + + :return: deserialized object. + """ + + # fetch data from response object + if content_type is None: + try: + 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 = "" + 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) + ) + + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if isinstance(klass, str): + if klass.startswith('List['): + m = re.match(r'List\[(.*)]', klass) + 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] + + if klass.startswith('Dict['): + m = re.match(r'Dict\[([^,]*), (.*)]', klass) + 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()} + + # convert str to class + if klass in self.NATIVE_TYPES_MAPPING: + klass = self.NATIVE_TYPES_MAPPING[klass] + else: + klass = getattr(corelink_sdk.models, klass) + + if klass in self.PRIMITIVE_TYPES: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object(data) + elif klass == datetime.date: + return self.__deserialize_date(data) + elif klass == datetime.datetime: + return self.__deserialize_datetime(data) + elif klass == decimal.Decimal: + return decimal.Decimal(data) + elif issubclass(klass, Enum): + return self.__deserialize_enum(data, klass) + else: + return self.__deserialize_model(data, klass) + + def parameters_to_tuples(self, params, collection_formats): + """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]] = [] + if collection_formats is None: + collection_formats = {} + for k, v in params.items() if isinstance(params, dict) else params: + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, value) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + 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): + """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]] = [] + if collection_formats is None: + collection_formats = {} + for k, v in params.items() if isinstance(params, dict) else params: + if isinstance(v, bool): + v = str(v).lower() + if isinstance(v, (int, float)): + v = str(v) + if isinstance(v, dict): + v = json.dumps(v) + + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, quote(str(value))) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + 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]) + + def files_parameters( + self, + files: Dict[str, Union[str, bytes, List[str], List[bytes], Tuple[str, bytes]]], + ): + """Builds form parameters. + + :param files: File parameters. + :return: Form parameters with files. + """ + params = [] + for k, v in files.items(): + if isinstance(v, str): + with open(v, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + elif isinstance(v, bytes): + filename = k + filedata = v + elif isinstance(v, tuple): + filename, filedata = v + elif isinstance(v, list): + for file_param in v: + 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])]) + ) + return params + + def select_header_accept(self, accepts: List[str]) -> Optional[str]: + """Returns `Accept` based on an array of accepts provided. + + :param accepts: List of headers. + :return: Accept (e.g. application/json). + """ + if not accepts: + return None + + for accept in accepts: + if re.search('json', accept, re.IGNORECASE): + return accept + + return accepts[0] + + def select_header_content_type(self, content_types): + """Returns `Content-Type` based on an array of content_types provided. + + :param content_types: List of content-types. + :return: Content-Type (e.g. application/json). + """ + if not content_types: + return None + + for content_type in content_types: + if re.search('json', content_type, re.IGNORECASE): + return content_type + + return content_types[0] + + def update_params_for_auth( + self, + headers, + queries, + auth_settings, + resource_path, + method, + body, + request_auth=None + ) -> None: + """Updates header and query params based on authentication setting. + + :param headers: Header parameters dict to be updated. + :param queries: Query parameters tuple list to be updated. + :param auth_settings: Authentication setting identifiers list. + :resource_path: A string representation of the HTTP request resource path. + :method: A string representation of the HTTP request method. + :body: A object representing the body of the HTTP request. + The object type is the return value of sanitize_for_serialization(). + :param request_auth: if set, the provided settings will + override the token in the configuration. + """ + if not auth_settings: + return + + if 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) + if auth_setting: + self._apply_auth_params( + headers, + queries, + resource_path, + method, + body, + auth_setting + ) + + def _apply_auth_params( + self, + headers, + queries, + resource_path, + method, + body, + auth_setting + ) -> None: + """Updates the request parameters based on a single auth_setting + + :param headers: Header parameters dict to be updated. + :param queries: Query parameters tuple list to be updated. + :resource_path: A string representation of the HTTP request resource path. + :method: A string representation of the HTTP request method. + :body: A object representing the body of the HTTP request. + The object type is the return value of sanitize_for_serialization(). + :param auth_setting: auth settings for the endpoint + """ + if auth_setting['in'] == 'cookie': + headers['Cookie'] = auth_setting['value'] + elif auth_setting['in'] == 'header': + 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'])) + else: + raise ApiValueError( + 'Authentication token must be in `query` or `header`' + ) + + def __deserialize_file(self, response): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + handle file downloading + save response body into a tmp file and return the instance + + :param response: RESTResponse. + :return: file path. + """ + fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if 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) + + return path + + def __deserialize_primitive(self, data, klass): + """Deserializes string to primitive type. + + :param data: str. + :param klass: class literal. + + :return: int, long, float, str, bool. + """ + try: + return klass(data) + except UnicodeEncodeError: + return str(data) + except TypeError: + return data + + def __deserialize_object(self, value): + """Return an original value. + + :return: object. + """ + return value + + def __deserialize_date(self, string): + """Deserializes string to date. + + :param string: str. + :return: date. + """ + 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) + ) + + def __deserialize_datetime(self, string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :return: datetime. + """ + 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) + ) + ) + + def __deserialize_enum(self, data, klass): + """Deserializes primitive type to enum. + + :param data: primitive type. + :param klass: class literal. + :return: enum value. + """ + try: + return klass(data) + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as `{1}`" + .format(data, klass) + ) + ) + + def __deserialize_model(self, data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :param klass: class literal. + :return: model object. + """ + + return klass.from_dict(data) diff --git a/corelink_sdk/api_response.py b/corelink_sdk/api_response.py new file mode 100644 index 0000000..9bc7c11 --- /dev/null +++ b/corelink_sdk/api_response.py @@ -0,0 +1,21 @@ +"""API response object.""" + +from __future__ import annotations +from typing import Optional, Generic, Mapping, TypeVar +from pydantic import Field, StrictInt, StrictBytes, BaseModel + +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)") + + model_config = { + "arbitrary_types_allowed": True + } diff --git a/corelink_sdk/configuration.py b/corelink_sdk/configuration.py new file mode 100644 index 0000000..793c4c1 --- /dev/null +++ b/corelink_sdk/configuration.py @@ -0,0 +1,582 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + 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 +from typing_extensions import NotRequired, Self + +import urllib3 + + +JSON_SCHEMA_VALIDATION_KEYWORDS = { + 'multipleOf', 'maximum', 'exclusiveMaximum', + 'minimum', 'exclusiveMinimum', 'maxLength', + 'minLength', 'pattern', 'maxItems', 'minItems' +} + +ServerVariablesT = Dict[str, str] + +GenericAuthSetting = TypedDict( + "GenericAuthSetting", + { + "type": str, + "in": str, + "key": str, + "value": str, + }, +) + + +OAuth2AuthSetting = TypedDict( + "OAuth2AuthSetting", + { + "type": Literal["oauth2"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +APIKeyAuthSetting = TypedDict( + "APIKeyAuthSetting", + { + "type": Literal["api_key"], + "in": str, + "key": str, + "value": Optional[str], + }, +) + + +BasicAuthSetting = TypedDict( + "BasicAuthSetting", + { + "type": Literal["basic"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": Optional[str], + }, +) + + +BearerFormatAuthSetting = TypedDict( + "BearerFormatAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "format": Literal["JWT"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +BearerAuthSetting = TypedDict( + "BearerAuthSetting", + { + "type": Literal["bearer"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": str, + }, +) + + +HTTPSignatureAuthSetting = TypedDict( + "HTTPSignatureAuthSetting", + { + "type": Literal["http-signature"], + "in": Literal["header"], + "key": Literal["Authorization"], + "value": None, + }, +) + + +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 Configuration: + """This class contains various settings of the API client. + + :param host: Base url. + :param ignore_operation_servers + Boolean to ignore operation servers for the API client. + Config will use `host` as the base url regardless of the operation servers. + :param api_key: Dict to store API key(s). + Each entry in the dict specifies an API key. + The dict key is the name of the security scheme in the OAS specification. + The dict value is the API key secret. + :param api_key_prefix: Dict to store API prefix (e.g. Bearer). + The dict key is the name of the security scheme in the OAS specification. + The dict value is an API key prefix when generating the auth data. + :param username: Username for HTTP basic authentication. + :param password: Password for HTTP basic authentication. + :param access_token: Access token. + :param server_index: Index to servers configuration. + :param server_variables: Mapping with string values to replace variables in + templated server configuration. The validation of enums is performed for + variables with defined enum values before. + :param server_operation_index: Mapping from operation ID to an index to server + configuration. + :param server_operation_variables: Mapping from operation ID to a mapping with + string values to replace variables in templated server configuration. + The validation of enums is performed for variables with defined enum + values before. + :param ssl_ca_cert: str - the path to a file of concatenated CA certificates + in PEM format. + :param retries: Number of retries for API requests. + :param ca_cert_data: verify the peer using concatenated CA certificate data + in PEM (str) or DER (bytes) format. + + :Example: + """ + + _default: ClassVar[Optional[Self]] = None + + def __init__( + self, + host: Optional[str]=None, + api_key: Optional[Dict[str, str]]=None, + api_key_prefix: Optional[Dict[str, str]]=None, + username: Optional[str]=None, + password: Optional[str]=None, + access_token: Optional[str]=None, + server_index: Optional[int]=None, + server_variables: Optional[ServerVariablesT]=None, + server_operation_index: Optional[Dict[int, int]]=None, + server_operation_variables: Optional[Dict[int, ServerVariablesT]]=None, + ignore_operation_servers: bool=False, + ssl_ca_cert: Optional[str]=None, + retries: Optional[int] = None, + ca_cert_data: Optional[Union[str, bytes]] = None, + *, + debug: Optional[bool] = None, + ) -> None: + """Constructor + """ + self._base_path = "https://api.corelink.example" if host is None else host + """Default Base url + """ + self.server_index = 0 if server_index is None and host is None else server_index + self.server_operation_index = server_operation_index or {} + """Default server index + """ + self.server_variables = server_variables or {} + self.server_operation_variables = server_operation_variables or {} + """Default server variables + """ + self.ignore_operation_servers = ignore_operation_servers + """Ignore operation servers + """ + self.temp_folder_path = None + """Temp file folder for downloading files + """ + # Authentication Settings + self.api_key = {} + if api_key: + self.api_key = api_key + """dict to store API key(s) + """ + self.api_key_prefix = {} + if api_key_prefix: + self.api_key_prefix = api_key_prefix + """dict to store API prefix (e.g. Bearer) + """ + self.refresh_api_key_hook = None + """function hook to refresh API key if expired + """ + self.username = username + """Username for HTTP basic authentication + """ + self.password = password + """Password for HTTP basic authentication + """ + self.access_token = access_token + """Access token + """ + self.logger = {} + """Logging Settings + """ + self.logger["package_logger"] = logging.getLogger("corelink_sdk") + self.logger["urllib3_logger"] = logging.getLogger("urllib3") + self.logger_format = '%(asctime)s %(levelname)s %(message)s' + """Log format + """ + self.logger_stream_handler = None + """Log stream handler + """ + self.logger_file_handler: Optional[FileHandler] = None + """Log file handler + """ + self.logger_file = None + """Debug file location + """ + if debug is not None: + self.debug = debug + else: + self.__debug = False + """Debug switch + """ + + self.verify_ssl = True + """SSL/TLS verification + Set this to false to skip verifying SSL certificate when calling API + from https server. + """ + self.ssl_ca_cert = ssl_ca_cert + """Set this to customize the certificate file to verify the peer. + """ + self.ca_cert_data = ca_cert_data + """Set this to verify the peer using PEM (str) or DER (bytes) + certificate data. + """ + self.cert_file = None + """client certificate file + """ + self.key_file = None + """client key file + """ + self.assert_hostname = None + """Set this to True/False to enable/disable SSL hostname verification. + """ + self.tls_server_name = None + """SSL/TLS Server Name Indication (SNI) + Set this to the SNI value expected by the server. + """ + + self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 + """urllib3 connection pool's maximum number of connections saved + per pool. urllib3 uses 1 connection as default value, but this is + not the best value when you are making a lot of possibly parallel + requests to the same host, which is often the case here. + cpu_count * 5 is used as default value to increase performance. + """ + + self.proxy: Optional[str] = None + """Proxy URL + """ + self.proxy_headers = None + """Proxy headers + """ + self.safe_chars_for_path_param = '' + """Safe chars for path_param + """ + self.retries = retries + """Adding retries to override urllib3 default value 3 + """ + # Enable client side validation + self.client_side_validation = True + + self.socket_options = None + """Options to pass down to the underlying urllib3 socket + """ + + self.datetime_format = "%Y-%m-%dT%H:%M:%S.%f%z" + """datetime format + """ + + self.date_format = "%Y-%m-%d" + """date format + """ + + def __deepcopy__(self, memo: Dict[int, Any]) -> Self: + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k not in ('logger', 'logger_file_handler'): + setattr(result, k, copy.deepcopy(v, memo)) + # shallow copy of loggers + result.logger = copy.copy(self.logger) + # use setters to configure loggers + result.logger_file = self.logger_file + result.debug = self.debug + return result + + def __setattr__(self, name: str, value: Any) -> None: + object.__setattr__(self, name, value) + + @classmethod + def set_default(cls, default: Optional[Self]) -> None: + """Set default instance of configuration. + + It stores default configuration, which can be + returned by get_default_copy method. + + :param default: object of Configuration + """ + cls._default = default + + @classmethod + def get_default_copy(cls) -> Self: + """Deprecated. Please use `get_default` instead. + + Deprecated. Please use `get_default` instead. + + :return: The configuration object. + """ + return cls.get_default() + + @classmethod + def get_default(cls) -> Self: + """Return the default configuration. + + This method returns newly created, based on default constructor, + object of Configuration class or returns a copy of default + configuration. + + :return: The configuration object. + """ + if cls._default is None: + cls._default = cls() + return cls._default + + @property + def logger_file(self) -> Optional[str]: + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + return self.__logger_file + + @logger_file.setter + def logger_file(self, value: Optional[str]) -> None: + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + self.__logger_file = value + if self.__logger_file: + # If set logging file, + # then add file handler and remove stream handler. + self.logger_file_handler = logging.FileHandler(self.__logger_file) + self.logger_file_handler.setFormatter(self.logger_formatter) + for _, logger in self.logger.items(): + logger.addHandler(self.logger_file_handler) + + @property + def debug(self) -> bool: + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + return self.__debug + + @debug.setter + def debug(self, value: bool) -> None: + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + self.__debug = value + if self.__debug: + # if debug status is True, turn on debug logging + for _, logger in self.logger.items(): + logger.setLevel(logging.DEBUG) + # turn on httplib debug + httplib.HTTPConnection.debuglevel = 1 + else: + # if debug status is False, turn off debug logging, + # setting log level to default `logging.WARNING` + for _, logger in self.logger.items(): + logger.setLevel(logging.WARNING) + # turn off httplib debug + httplib.HTTPConnection.debuglevel = 0 + + @property + def logger_format(self) -> str: + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + return self.__logger_format + + @logger_format.setter + def logger_format(self, value: str) -> None: + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + self.__logger_format = value + self.logger_formatter = logging.Formatter(self.__logger_format) + + def get_api_key_with_prefix(self, identifier: str, alias: Optional[str]=None) -> Optional[str]: + """Gets API key (with prefix if set). + + :param identifier: The identifier of apiKey. + :param alias: The alternative identifier of apiKey. + :return: The token for api key authentication. + """ + if self.refresh_api_key_hook is not None: + self.refresh_api_key_hook(self) + key = self.api_key.get(identifier, self.api_key.get(alias) if alias is not None else None) + if key: + prefix = self.api_key_prefix.get(identifier) + if prefix: + return "%s %s" % (prefix, key) + else: + return key + + return None + + def get_basic_auth_token(self) -> Optional[str]: + """Gets HTTP basic authentication header (string). + + :return: The token for basic HTTP authentication. + """ + username = "" + if self.username is not None: + username = self.username + password = "" + if self.password is not None: + password = self.password + return urllib3.util.make_headers( + basic_auth=username + ':' + password + ).get('authorization') + + def auth_settings(self)-> AuthSettings: + """Gets Auth Settings dict for api client. + + :return: The Auth Settings information dict. + """ + auth: AuthSettings = {} + if self.access_token is not None: + auth['bearerAuth'] = { + 'type': 'bearer', + 'in': 'header', + 'format': 'JWT', + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + } + return auth + + def to_debug_report(self) -> str: + """Gets the essential information for debugging. + + :return: The report for debugging. + """ + return "Python SDK Debug Report:\n"\ + "OS: {env}\n"\ + "Python Version: {pyversion}\n"\ + "Version of the API: 1.0.0-draft\n"\ + "SDK Package Version: 0.1.0.dev0".\ + format(env=sys.platform, pyversion=sys.version) + + def get_host_settings(self) -> List[HostSetting]: + """Gets an array of host settings + + :return: An array of host settings + """ + return [ + { + 'url': "https://api.corelink.example", + 'description': "No description provided", + } + ] + + def get_host_from_settings( + self, + index: Optional[int], + variables: Optional[ServerVariablesT]=None, + servers: Optional[List[HostSetting]]=None, + ) -> str: + """Gets host URL based on the index and variables + :param index: array index of the host settings + :param variables: hash of variable and the corresponding value + :param servers: an array of host settings or None + :return: URL based on host settings + """ + if index is None: + return self._base_path + + variables = {} if variables is None else variables + servers = self.get_host_settings() if servers is None else servers + + try: + server = servers[index] + except IndexError: + raise ValueError( + "Invalid index {0} when selecting the host settings. " + "Must be less than {1}".format(index, len(servers))) + + url = server['url'] + + # go through variables and replace placeholders + for variable_name, variable in server.get('variables', {}).items(): + used_value = variables.get( + variable_name, variable['default_value']) + + if 'enum_values' in variable \ + and used_value not in variable['enum_values']: + raise ValueError( + "The variable `{0}` in the host URL has invalid value " + "{1}. Must be {2}.".format( + variable_name, variables[variable_name], + variable['enum_values'])) + + url = url.replace("{" + variable_name + "}", used_value) + + return url + + @property + def host(self) -> str: + """Return generated host.""" + return self.get_host_from_settings(self.server_index, variables=self.server_variables) + + @host.setter + def host(self, value: str) -> None: + """Fix base path.""" + self._base_path = value + self.server_index = None diff --git a/corelink_sdk/exceptions.py b/corelink_sdk/exceptions.py new file mode 100644 index 0000000..89df8ba --- /dev/null +++ b/corelink_sdk/exceptions.py @@ -0,0 +1,216 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + +from typing import Any, Optional +from typing_extensions import Self + +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 + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list): a list of keys an indices to get to the + current_item + None if unset + valid_classes (tuple): the primitive classes that current item + should be an instance of + None if unset + key_type (bool): False if our value is a value in a dict + True if it is a key in a dict + False if our item is an item in a list + None if unset + """ + self.path_to_item = path_to_item + self.valid_classes = valid_classes + 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) + + +class ApiValueError(OpenApiException, ValueError): + def __init__(self, msg, path_to_item=None) -> None: + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list) the path to the exception in the + received_data dict. None if unset + """ + + 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) + + +class ApiAttributeError(OpenApiException, AttributeError): + def __init__(self, msg, path_to_item=None) -> None: + """ + Raised when an attribute reference or assignment fails. + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + 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) + + +class ApiKeyError(OpenApiException, KeyError): + def __init__(self, msg, path_to_item=None) -> None: + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + 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) + + +class ApiException(OpenApiException): + + def __init__( + self, + status=None, + reason=None, + http_resp=None, + *, + body: Optional[str] = None, + data: Optional[Any] = None, + ) -> None: + self.status = status + self.reason = reason + self.body = body + self.data = data + self.headers = None + + if http_resp: + if self.status is None: + self.status = http_resp.status + if self.reason is None: + self.reason = http_resp.reason + if self.body is None: + try: + self.body = http_resp.data.decode('utf-8') + except Exception: + pass + self.headers = http_resp.getheaders() + + @classmethod + def from_response( + cls, + *, + http_resp, + body: Optional[str], + data: Optional[Any], + ) -> Self: + if http_resp.status == 400: + raise BadRequestException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 401: + raise UnauthorizedException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 403: + raise ForbiddenException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 404: + raise NotFoundException(http_resp=http_resp, body=body, data=data) + + # Added new conditions for 409 and 422 + if http_resp.status == 409: + raise ConflictException(http_resp=http_resp, body=body, data=data) + + if http_resp.status == 422: + raise UnprocessableEntityException(http_resp=http_resp, body=body, data=data) + + if 500 <= http_resp.status <= 599: + raise ServiceException(http_resp=http_resp, body=body, data=data) + raise ApiException(http_resp=http_resp, body=body, data=data) + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.data or self.body: + error_message += "HTTP response body: {0}\n".format(self.data or self.body) + + return error_message + + +class BadRequestException(ApiException): + pass + + +class NotFoundException(ApiException): + pass + + +class UnauthorizedException(ApiException): + pass + + +class ForbiddenException(ApiException): + pass + + +class ServiceException(ApiException): + pass + + +class ConflictException(ApiException): + """Exception for HTTP 409 Conflict.""" + pass + + +class UnprocessableEntityException(ApiException): + """Exception for HTTP 422 Unprocessable Entity.""" + pass + + +def render_path(path_to_item): + """Returns a string representation of a path""" + result = "" + for pth in path_to_item: + if isinstance(pth, int): + result += "[{0}]".format(pth) + else: + result += "['{0}']".format(pth) + return result diff --git a/corelink_sdk/models/__init__.py b/corelink_sdk/models/__init__.py new file mode 100644 index 0000000..d1b7fd7 --- /dev/null +++ b/corelink_sdk/models/__init__.py @@ -0,0 +1,27 @@ +# coding: utf-8 + +# flake8: noqa +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +# import models into model package +from corelink_sdk.models.command import Command +from corelink_sdk.models.command_create import CommandCreate +from corelink_sdk.models.command_page import CommandPage +from corelink_sdk.models.command_status import CommandStatus +from corelink_sdk.models.device import Device +from corelink_sdk.models.device_create import DeviceCreate +from corelink_sdk.models.device_page import DevicePage +from corelink_sdk.models.device_status import DeviceStatus +from corelink_sdk.models.device_update import DeviceUpdate +from corelink_sdk.models.health import Health +from corelink_sdk.models.problem import Problem diff --git a/corelink_sdk/models/command.py b/corelink_sdk/models/command.py new file mode 100644 index 0000000..65455ba --- /dev/null +++ b/corelink_sdk/models/command.py @@ -0,0 +1,128 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from corelink_sdk.models.command_status import CommandStatus +from typing import Optional, Set +from typing_extensions import Self + +class Command(BaseModel): + """ + Command + """ # noqa: E501 + command_id: StrictStr + tenant_id: StrictStr + corelink_device_id: StrictStr + command_type: StrictStr + payload: Dict[str, Any] + status: CommandStatus + attempt_count: StrictInt + timeout_at: Optional[datetime] = None + acknowledged_at: Optional[datetime] = None + completed_at: Optional[datetime] = None + metadata: Dict[str, Any] + created_at: datetime + updated_at: datetime + __properties: ClassVar[List[str]] = ["command_id", "tenant_id", "corelink_device_id", "command_type", "payload", "status", "attempt_count", "timeout_at", "acknowledged_at", "completed_at", "metadata", "created_at", "updated_at"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of Command 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if timeout_at (nullable) is None + # and model_fields_set contains the field + if self.timeout_at is None and "timeout_at" in self.model_fields_set: + _dict['timeout_at'] = None + + # set to None if acknowledged_at (nullable) is None + # and model_fields_set contains the field + if self.acknowledged_at is None and "acknowledged_at" in self.model_fields_set: + _dict['acknowledged_at'] = None + + # set to None if completed_at (nullable) is None + # and model_fields_set contains the field + if self.completed_at is None and "completed_at" in self.model_fields_set: + _dict['completed_at'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of Command from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "command_id": obj.get("command_id"), + "tenant_id": obj.get("tenant_id"), + "corelink_device_id": obj.get("corelink_device_id"), + "command_type": obj.get("command_type"), + "payload": obj.get("payload"), + "status": obj.get("status"), + "attempt_count": obj.get("attempt_count"), + "timeout_at": obj.get("timeout_at"), + "acknowledged_at": obj.get("acknowledged_at"), + "completed_at": obj.get("completed_at"), + "metadata": obj.get("metadata"), + "created_at": obj.get("created_at"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/corelink_sdk/models/command_create.py b/corelink_sdk/models/command_create.py new file mode 100644 index 0000000..ad6ffc4 --- /dev/null +++ b/corelink_sdk/models/command_create.py @@ -0,0 +1,95 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class CommandCreate(BaseModel): + """ + CommandCreate + """ # noqa: E501 + command_type: Annotated[str, Field(min_length=1, strict=True, max_length=150)] + payload: Optional[Dict[str, Any]] = None + timeout_at: Optional[datetime] = None + metadata: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["command_type", "payload", "timeout_at", "metadata"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CommandCreate 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CommandCreate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "command_type": obj.get("command_type"), + "payload": obj.get("payload"), + "timeout_at": obj.get("timeout_at"), + "metadata": obj.get("metadata") + }) + return _obj + + diff --git a/corelink_sdk/models/command_page.py b/corelink_sdk/models/command_page.py new file mode 100644 index 0000000..7924fb6 --- /dev/null +++ b/corelink_sdk/models/command_page.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from corelink_sdk.models.command import Command +from typing import Optional, Set +from typing_extensions import Self + +class CommandPage(BaseModel): + """ + CommandPage + """ # noqa: E501 + items: List[Command] + total: StrictInt + limit: StrictInt + offset: StrictInt + __properties: ClassVar[List[str]] = ["items", "total", "limit", "offset"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of CommandPage 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in items (list) + _items = [] + if self.items: + for _item_items in self.items: + if _item_items: + _items.append(_item_items.to_dict()) + _dict['items'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of CommandPage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "items": [Command.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None, + "total": obj.get("total"), + "limit": obj.get("limit"), + "offset": obj.get("offset") + }) + return _obj + + diff --git a/corelink_sdk/models/command_status.py b/corelink_sdk/models/command_status.py new file mode 100644 index 0000000..11b9fa8 --- /dev/null +++ b/corelink_sdk/models/command_status.py @@ -0,0 +1,43 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +from enum import Enum +from typing_extensions import Self + + +class CommandStatus(str, Enum): + """ + CommandStatus + """ + + """ + allowed enum values + """ + QUEUED = 'queued' + DISPATCHING = 'dispatching' + SENT = 'sent' + ACKNOWLEDGED = 'acknowledged' + SUCCEEDED = 'succeeded' + FAILED = 'failed' + TIMED_OUT = 'timed_out' + CANCELLED = 'cancelled' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of CommandStatus from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/corelink_sdk/models/device.py b/corelink_sdk/models/device.py new file mode 100644 index 0000000..83ebd14 --- /dev/null +++ b/corelink_sdk/models/device.py @@ -0,0 +1,123 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from corelink_sdk.models.device_status import DeviceStatus +from typing import Optional, Set +from typing_extensions import Self + +class Device(BaseModel): + """ + Device + """ # noqa: E501 + corelink_device_id: StrictStr + tenant_id: StrictStr + device_model_id: StrictStr + partner_sku_id: Optional[StrictStr] = None + firmware_release_id: Optional[StrictStr] = None + name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = None + status: DeviceStatus + metadata: Dict[str, Any] + created_at: datetime + updated_at: datetime + __properties: ClassVar[List[str]] = ["corelink_device_id", "tenant_id", "device_model_id", "partner_sku_id", "firmware_release_id", "name", "status", "metadata", "created_at", "updated_at"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of Device 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if partner_sku_id (nullable) is None + # and model_fields_set contains the field + if self.partner_sku_id is None and "partner_sku_id" in self.model_fields_set: + _dict['partner_sku_id'] = None + + # set to None if firmware_release_id (nullable) is None + # and model_fields_set contains the field + if self.firmware_release_id is None and "firmware_release_id" in self.model_fields_set: + _dict['firmware_release_id'] = None + + # 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['name'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of Device from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "corelink_device_id": obj.get("corelink_device_id"), + "tenant_id": obj.get("tenant_id"), + "device_model_id": obj.get("device_model_id"), + "partner_sku_id": obj.get("partner_sku_id"), + "firmware_release_id": obj.get("firmware_release_id"), + "name": obj.get("name"), + "status": obj.get("status"), + "metadata": obj.get("metadata"), + "created_at": obj.get("created_at"), + "updated_at": obj.get("updated_at") + }) + return _obj + + diff --git a/corelink_sdk/models/device_create.py b/corelink_sdk/models/device_create.py new file mode 100644 index 0000000..c4c05eb --- /dev/null +++ b/corelink_sdk/models/device_create.py @@ -0,0 +1,96 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class DeviceCreate(BaseModel): + """ + DeviceCreate + """ # noqa: E501 + device_model_id: StrictStr + partner_sku_id: Optional[StrictStr] = None + firmware_release_id: Optional[StrictStr] = None + name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = None + metadata: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["device_model_id", "partner_sku_id", "firmware_release_id", "name", "metadata"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of DeviceCreate 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of DeviceCreate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "device_model_id": obj.get("device_model_id"), + "partner_sku_id": obj.get("partner_sku_id"), + "firmware_release_id": obj.get("firmware_release_id"), + "name": obj.get("name"), + "metadata": obj.get("metadata") + }) + return _obj + + diff --git a/corelink_sdk/models/device_page.py b/corelink_sdk/models/device_page.py new file mode 100644 index 0000000..af811d1 --- /dev/null +++ b/corelink_sdk/models/device_page.py @@ -0,0 +1,101 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing import Any, ClassVar, Dict, List +from corelink_sdk.models.device import Device +from typing import Optional, Set +from typing_extensions import Self + +class DevicePage(BaseModel): + """ + DevicePage + """ # noqa: E501 + items: List[Device] + total: StrictInt + limit: StrictInt + offset: StrictInt + __properties: ClassVar[List[str]] = ["items", "total", "limit", "offset"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of DevicePage 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in items (list) + _items = [] + if self.items: + for _item_items in self.items: + if _item_items: + _items.append(_item_items.to_dict()) + _dict['items'] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of DevicePage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "items": [Device.from_dict(_item) for _item in obj["items"]] if obj.get("items") is not None else None, + "total": obj.get("total"), + "limit": obj.get("limit"), + "offset": obj.get("offset") + }) + return _obj + + diff --git a/corelink_sdk/models/device_status.py b/corelink_sdk/models/device_status.py new file mode 100644 index 0000000..cc3280a --- /dev/null +++ b/corelink_sdk/models/device_status.py @@ -0,0 +1,40 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +from enum import Enum +from typing_extensions import Self + + +class DeviceStatus(str, Enum): + """ + DeviceStatus + """ + + """ + allowed enum values + """ + INVENTORY = 'inventory' + PROVISIONING = 'provisioning' + ACTIVE = 'active' + SUSPENDED = 'suspended' + RETIRED = 'retired' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of DeviceStatus from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/corelink_sdk/models/device_update.py b/corelink_sdk/models/device_update.py new file mode 100644 index 0000000..3e3d0a1 --- /dev/null +++ b/corelink_sdk/models/device_update.py @@ -0,0 +1,102 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated +from typing import Optional, Set +from typing_extensions import Self + +class DeviceUpdate(BaseModel): + """ + DeviceUpdate + """ # noqa: E501 + firmware_release_id: Optional[StrictStr] = None + name: Optional[Annotated[str, Field(strict=True, max_length=255)]] = None + metadata: Optional[Dict[str, Any]] = None + __properties: ClassVar[List[str]] = ["firmware_release_id", "name", "metadata"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of DeviceUpdate 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if firmware_release_id (nullable) is None + # and model_fields_set contains the field + if self.firmware_release_id is None and "firmware_release_id" in self.model_fields_set: + _dict['firmware_release_id'] = None + + # 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['name'] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of DeviceUpdate from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "firmware_release_id": obj.get("firmware_release_id"), + "name": obj.get("name"), + "metadata": obj.get("metadata") + }) + return _obj + + diff --git a/corelink_sdk/models/health.py b/corelink_sdk/models/health.py new file mode 100644 index 0000000..e433fcd --- /dev/null +++ b/corelink_sdk/models/health.py @@ -0,0 +1,94 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictStr, field_validator +from typing import Any, ClassVar, Dict, List +from typing import Optional, Set +from typing_extensions import Self + +class Health(BaseModel): + """ + Health + """ # noqa: E501 + status: StrictStr + __properties: ClassVar[List[str]] = ["status"] + + @field_validator('status') + def status_validate_enum(cls, value): + """Validates the enum""" + if value not in set(['ok', 'ready']): + raise ValueError("must be one of enum values ('ok', 'ready')") + return value + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of Health 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of Health from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "status": obj.get("status") + }) + return _obj + + diff --git a/corelink_sdk/models/problem.py b/corelink_sdk/models/problem.py new file mode 100644 index 0000000..d2c9c97 --- /dev/null +++ b/corelink_sdk/models/problem.py @@ -0,0 +1,97 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from typing import Any, ClassVar, Dict, List, Optional +from typing import Optional, Set +from typing_extensions import Self + +class Problem(BaseModel): + """ + Problem + """ # noqa: E501 + type: StrictStr + title: StrictStr + status: StrictInt + code: StrictStr + detail: Optional[StrictStr] = None + correlation_id: StrictStr + __properties: ClassVar[List[str]] = ["type", "title", "status", "code", "detail", "correlation_id"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of Problem 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. + """ + excluded_fields: Set[str] = set([ + ]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of Problem from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate({ + "type": obj.get("type"), + "title": obj.get("title"), + "status": obj.get("status"), + "code": obj.get("code"), + "detail": obj.get("detail"), + "correlation_id": obj.get("correlation_id") + }) + return _obj + + diff --git a/corelink_sdk/py.typed b/corelink_sdk/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/corelink_sdk/rest.py b/corelink_sdk/rest.py new file mode 100644 index 0000000..5ea2b7a --- /dev/null +++ b/corelink_sdk/rest.py @@ -0,0 +1,258 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import io +import json +import re +import ssl + +import urllib3 + +from corelink_sdk.exceptions import ApiException, ApiValueError + +SUPPORTED_SOCKS_PROXIES = {"socks5", "socks5h", "socks4", "socks4a"} +RESTResponseType = urllib3.HTTPResponse + + +def is_socks_proxy_url(url): + 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) -> None: + self.response = resp + self.status = resp.status + self.reason = resp.reason + self.data = None + + def read(self): + if self.data is None: + self.data = self.response.data + return self.data + + def getheaders(self): + """Returns a dictionary of the response headers.""" + return self.response.headers + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.response.headers.get(name, default) + + +class RESTClientObject: + + def __init__(self, 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 = { + "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, + url, + headers=None, + body=None, + post_params=None, + _request_timeout=None + ): + """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) + 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) or isinstance(body, 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) + + return RESTResponse(r) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f26f67d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,81 @@ +[build-system] +requires = ["setuptools>=68"] +build-backend = "setuptools.build_meta" + +[project] +name = "corelink-sdk" +version = "0.1.0.dev0" +description = "Generated Python client for the CoreLink Public API" +readme = "README.md" +requires-python = ">=3.9" +authors = [{ name = "CoreLink Platform" }] +license = "Proprietary" +keywords = ["corelink", "openapi", "generated-client"] +dependencies = [ + "urllib3>=1.25.3,<3.0.0", + "python-dateutil>=2.8.2", + "pydantic>=2", + "typing-extensions>=4.7.1", +] + +[project.urls] +Repository = "https://github.com/CoreLinkPlatform/sdk-python" + +[tool.setuptools.packages.find] +include = ["corelink_sdk*"] + +[tool.setuptools.package-data] +corelink_sdk = ["py.typed"] + +[tool.mypy] +files = [ + "corelink_sdk", +] +# TODO: enable "strict" once all these individual checks are passing +# strict = true + +# List from: https://mypy.readthedocs.io/en/stable/existing_code.html#introduce-stricter-options +warn_unused_configs = true +warn_redundant_casts = true +warn_unused_ignores = true + +## Getting these passing should be easy +strict_equality = true +extra_checks = true + +## Strongly recommend enabling this one as soon as you can +check_untyped_defs = true + +## These shouldn't be too much additional work, but may be tricky to +## get passing if you use a lot of untyped libraries +disallow_subclassing_any = true +disallow_untyped_decorators = true +disallow_any_generics = true + +### These next few are various gradations of forcing use of type annotations +#disallow_untyped_calls = true +#disallow_incomplete_defs = true +#disallow_untyped_defs = true +# +### This one isn't too hard to get passing, but return on investment is lower +#no_implicit_reexport = true +# +### This one can be tricky to get passing if you use a lot of untyped libraries +#warn_return_any = true + +[[tool.mypy.overrides]] +module = [ + "corelink_sdk.configuration", +] +warn_unused_ignores = true +strict_equality = true +extra_checks = true +check_untyped_defs = true +disallow_subclassing_any = true +disallow_untyped_decorators = true +disallow_any_generics = true +disallow_untyped_calls = true +disallow_incomplete_defs = true +disallow_untyped_defs = true +no_implicit_reexport = true +warn_return_any = true diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..67f7f68 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +urllib3 >= 1.25.3, < 3.0.0 +python_dateutil >= 2.8.2 +pydantic >= 2 +typing-extensions >= 4.7.1 diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/test_command.py b/test/test_command.py new file mode 100644 index 0000000..126571b --- /dev/null +++ b/test/test_command.py @@ -0,0 +1,73 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.command import Command + +class TestCommand(unittest.TestCase): + """Command unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> Command: + """Test Command + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `Command` + """ + model = Command() + if include_optional: + return Command( + command_id = '', + tenant_id = '', + corelink_device_id = '', + command_type = '', + payload = { }, + status = 'queued', + attempt_count = 56, + timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') + ) + else: + return Command( + command_id = '', + tenant_id = '', + corelink_device_id = '', + command_type = '', + payload = { }, + status = 'queued', + attempt_count = 56, + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + ) + """ + + def testCommand(self): + """Test Command""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_command_create.py b/test/test_command_create.py new file mode 100644 index 0000000..2a95452 --- /dev/null +++ b/test/test_command_create.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.command_create import CommandCreate + +class TestCommandCreate(unittest.TestCase): + """CommandCreate unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> CommandCreate: + """Test CommandCreate + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `CommandCreate` + """ + model = CommandCreate() + if include_optional: + return CommandCreate( + command_type = '0', + payload = { }, + timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + metadata = { } + ) + else: + return CommandCreate( + command_type = '0', + ) + """ + + def testCommandCreate(self): + """Test CommandCreate""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_command_page.py b/test/test_command_page.py new file mode 100644 index 0000000..5d61f26 --- /dev/null +++ b/test/test_command_page.py @@ -0,0 +1,88 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.command_page import CommandPage + +class TestCommandPage(unittest.TestCase): + """CommandPage unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> CommandPage: + """Test CommandPage + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `CommandPage` + """ + model = CommandPage() + if include_optional: + return CommandPage( + items = [ + corelink_sdk.models.command.Command( + command_id = '', + tenant_id = '', + corelink_device_id = '', + command_type = '', + payload = { }, + status = 'queued', + attempt_count = 56, + timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) + ], + total = 56, + limit = 56, + offset = 56 + ) + else: + return CommandPage( + items = [ + corelink_sdk.models.command.Command( + command_id = '', + tenant_id = '', + corelink_device_id = '', + command_type = '', + payload = { }, + status = 'queued', + attempt_count = 56, + timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) + ], + total = 56, + limit = 56, + offset = 56, + ) + """ + + def testCommandPage(self): + """Test CommandPage""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_command_status.py b/test/test_command_status.py new file mode 100644 index 0000000..325d424 --- /dev/null +++ b/test/test_command_status.py @@ -0,0 +1,33 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.command_status import CommandStatus + +class TestCommandStatus(unittest.TestCase): + """CommandStatus unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testCommandStatus(self): + """Test CommandStatus""" + # inst = CommandStatus() + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_commands_api.py b/test/test_commands_api.py new file mode 100644 index 0000000..4fc4743 --- /dev/null +++ b/test/test_commands_api.py @@ -0,0 +1,49 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.api.commands_api import CommandsApi + + +class TestCommandsApi(unittest.TestCase): + """CommandsApi unit test stubs""" + + def setUp(self) -> None: + self.api = CommandsApi() + + def tearDown(self) -> None: + pass + + def test_create_device_command(self) -> None: + """Test case for create_device_command + + """ + pass + + def test_get_device_command(self) -> None: + """Test case for get_device_command + + """ + pass + + def test_list_device_commands(self) -> None: + """Test case for list_device_commands + + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_default_api.py b/test/test_default_api.py new file mode 100644 index 0000000..1a5e348 --- /dev/null +++ b/test/test_default_api.py @@ -0,0 +1,43 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.api.default_api import DefaultApi + + +class TestDefaultApi(unittest.TestCase): + """DefaultApi unit test stubs""" + + def setUp(self) -> None: + self.api = DefaultApi() + + def tearDown(self) -> None: + pass + + def test_get_live_health(self) -> None: + """Test case for get_live_health + + """ + pass + + def test_get_readiness(self) -> None: + """Test case for get_readiness + + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_device.py b/test/test_device.py new file mode 100644 index 0000000..79a9b92 --- /dev/null +++ b/test/test_device.py @@ -0,0 +1,67 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.device import Device + +class TestDevice(unittest.TestCase): + """Device unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> Device: + """Test Device + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `Device` + """ + model = Device() + if include_optional: + return Device( + corelink_device_id = '', + tenant_id = '', + device_model_id = '', + partner_sku_id = '', + firmware_release_id = '', + name = '', + status = 'inventory', + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') + ) + else: + return Device( + corelink_device_id = '', + tenant_id = '', + device_model_id = '', + status = 'inventory', + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + ) + """ + + def testDevice(self): + """Test Device""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_device_create.py b/test/test_device_create.py new file mode 100644 index 0000000..6ab9fba --- /dev/null +++ b/test/test_device_create.py @@ -0,0 +1,56 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.device_create import DeviceCreate + +class TestDeviceCreate(unittest.TestCase): + """DeviceCreate unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> DeviceCreate: + """Test DeviceCreate + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `DeviceCreate` + """ + model = DeviceCreate() + if include_optional: + return DeviceCreate( + device_model_id = '', + partner_sku_id = '', + firmware_release_id = '', + name = '', + metadata = { } + ) + else: + return DeviceCreate( + device_model_id = '', + ) + """ + + def testDeviceCreate(self): + """Test DeviceCreate""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_device_page.py b/test/test_device_page.py new file mode 100644 index 0000000..4014607 --- /dev/null +++ b/test/test_device_page.py @@ -0,0 +1,82 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.device_page import DevicePage + +class TestDevicePage(unittest.TestCase): + """DevicePage unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> DevicePage: + """Test DevicePage + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `DevicePage` + """ + model = DevicePage() + if include_optional: + return DevicePage( + items = [ + corelink_sdk.models.device.Device( + corelink_device_id = '', + tenant_id = '', + device_model_id = '', + partner_sku_id = '', + firmware_release_id = '', + name = '', + status = 'inventory', + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) + ], + total = 56, + limit = 56, + offset = 56 + ) + else: + return DevicePage( + items = [ + corelink_sdk.models.device.Device( + corelink_device_id = '', + tenant_id = '', + device_model_id = '', + partner_sku_id = '', + firmware_release_id = '', + name = '', + status = 'inventory', + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) + ], + total = 56, + limit = 56, + offset = 56, + ) + """ + + def testDevicePage(self): + """Test DevicePage""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_device_status.py b/test/test_device_status.py new file mode 100644 index 0000000..092211a --- /dev/null +++ b/test/test_device_status.py @@ -0,0 +1,33 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.device_status import DeviceStatus + +class TestDeviceStatus(unittest.TestCase): + """DeviceStatus unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testDeviceStatus(self): + """Test DeviceStatus""" + # inst = DeviceStatus() + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_device_update.py b/test/test_device_update.py new file mode 100644 index 0000000..850d11b --- /dev/null +++ b/test/test_device_update.py @@ -0,0 +1,53 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.device_update import DeviceUpdate + +class TestDeviceUpdate(unittest.TestCase): + """DeviceUpdate unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> DeviceUpdate: + """Test DeviceUpdate + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `DeviceUpdate` + """ + model = DeviceUpdate() + if include_optional: + return DeviceUpdate( + firmware_release_id = '', + name = '', + metadata = { } + ) + else: + return DeviceUpdate( + ) + """ + + def testDeviceUpdate(self): + """Test DeviceUpdate""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_devices_api.py b/test/test_devices_api.py new file mode 100644 index 0000000..769f0fc --- /dev/null +++ b/test/test_devices_api.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.api.devices_api import DevicesApi + + +class TestDevicesApi(unittest.TestCase): + """DevicesApi unit test stubs""" + + def setUp(self) -> None: + self.api = DevicesApi() + + def tearDown(self) -> None: + pass + + def test_create_device(self) -> None: + """Test case for create_device + + """ + pass + + def test_get_device(self) -> None: + """Test case for get_device + + """ + pass + + def test_list_devices(self) -> None: + """Test case for list_devices + + """ + pass + + def test_update_device(self) -> None: + """Test case for update_device + + """ + pass + + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_health.py b/test/test_health.py new file mode 100644 index 0000000..b0dd516 --- /dev/null +++ b/test/test_health.py @@ -0,0 +1,52 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.health import Health + +class TestHealth(unittest.TestCase): + """Health unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> Health: + """Test Health + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `Health` + """ + model = Health() + if include_optional: + return Health( + status = 'ok' + ) + else: + return Health( + status = 'ok', + ) + """ + + def testHealth(self): + """Test Health""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/test/test_problem.py b/test/test_problem.py new file mode 100644 index 0000000..5863a07 --- /dev/null +++ b/test/test_problem.py @@ -0,0 +1,61 @@ +# coding: utf-8 + +""" + CoreLink Public API + + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + + The version of the OpenAPI document: 1.0.0-draft + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest + +from corelink_sdk.models.problem import Problem + +class TestProblem(unittest.TestCase): + """Problem unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> Problem: + """Test Problem + include_optional is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `Problem` + """ + model = Problem() + if include_optional: + return Problem( + type = '', + title = '', + status = 56, + code = '', + detail = '', + correlation_id = '' + ) + else: + return Problem( + type = '', + title = '', + status = 56, + code = '', + correlation_id = '', + ) + """ + + def testProblem(self): + """Test Problem""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() From 047fe3cb24ddb35b4a96efd149cd2b9df4f72045 Mon Sep 17 00:00:00 2001 From: Javid Date: Fri, 24 Jul 2026 23:10:16 +0330 Subject: [PATCH 2/2] chore: regenerate SDK from current contract --- .corelink-contract.json | 2 +- CODEGEN.md | 2 +- corelink_sdk/api/default_api.py | 8 +++-- corelink_sdk/models/command.py | 12 ++++++-- corelink_sdk/models/problem.py | 4 ++- pyproject.toml | 2 +- test/test_command.py | 1 + test/test_command_page.py | 52 +++++++++++++++++---------------- test/test_problem.py | 1 + 9 files changed, 51 insertions(+), 33 deletions(-) diff --git a/.corelink-contract.json b/.corelink-contract.json index e28071f..f27c1f1 100644 --- a/.corelink-contract.json +++ b/.corelink-contract.json @@ -3,7 +3,7 @@ "contractVersion": "1.0.0-draft", "sourceRepository": "CoreLinkPlatform/api-contracts", "sourceBranch": "agent/p3-1-contracts", - "sourceCommit": "701e693", + "sourceCommit": "2fb0dc8", "generator": "openapi-generator-cli", "generatorVersion": "7.12.0", "generatorName": "python" diff --git a/CODEGEN.md b/CODEGEN.md index 390e841..4d37d3e 100644 --- a/CODEGEN.md +++ b/CODEGEN.md @@ -2,7 +2,7 @@ This client is generated from `corelink-public-v1.yaml` with OpenAPI Generator `7.12.0`. The authoritative input for this prerelease was contract commit -`701e693` on `agent/p3-1-contracts`. +`2fb0dc8` on `agent/p3-1-contracts`. ```sh java -jar openapi-generator-cli-7.12.0.jar generate \ diff --git a/corelink_sdk/api/default_api.py b/corelink_sdk/api/default_api.py index f8fcc7b..9a32402 100644 --- a/corelink_sdk/api/default_api.py +++ b/corelink_sdk/api/default_api.py @@ -3,7 +3,7 @@ """ CoreLink Public API - Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. The version of the OpenAPI document: 1.0.0-draft Generated by OpenAPI Generator (https://openapi-generator.tech) @@ -328,6 +328,7 @@ def get_readiness( _response_types_map: Dict[str, Optional[str]] = { '200': "Health", + '503': "Problem", } response_data = self.api_client.call_api( *_param, @@ -390,6 +391,7 @@ def get_readiness_with_http_info( _response_types_map: Dict[str, Optional[str]] = { '200': "Health", + '503': "Problem", } response_data = self.api_client.call_api( *_param, @@ -452,6 +454,7 @@ def get_readiness_without_preload_content( _response_types_map: Dict[str, Optional[str]] = { '200': "Health", + '503': "Problem", } response_data = self.api_client.call_api( *_param, @@ -493,7 +496,8 @@ def _get_readiness_serialize( if 'Accept' not in _header_params: _header_params['Accept'] = self.api_client.select_header_accept( [ - 'application/json' + 'application/json', + 'application/problem+json' ] ) diff --git a/corelink_sdk/models/command.py b/corelink_sdk/models/command.py index 65455ba..17f4006 100644 --- a/corelink_sdk/models/command.py +++ b/corelink_sdk/models/command.py @@ -18,8 +18,9 @@ import json from datetime import datetime -from pydantic import BaseModel, ConfigDict, StrictInt, StrictStr +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr from typing import Any, ClassVar, Dict, List, Optional +from typing_extensions import Annotated from corelink_sdk.models.command_status import CommandStatus from typing import Optional, Set from typing_extensions import Self @@ -38,10 +39,11 @@ class Command(BaseModel): timeout_at: Optional[datetime] = None acknowledged_at: Optional[datetime] = None completed_at: Optional[datetime] = None + error_code: Optional[Annotated[str, Field(strict=True, max_length=100)]] = None metadata: Dict[str, Any] created_at: datetime updated_at: datetime - __properties: ClassVar[List[str]] = ["command_id", "tenant_id", "corelink_device_id", "command_type", "payload", "status", "attempt_count", "timeout_at", "acknowledged_at", "completed_at", "metadata", "created_at", "updated_at"] + __properties: ClassVar[List[str]] = ["command_id", "tenant_id", "corelink_device_id", "command_type", "payload", "status", "attempt_count", "timeout_at", "acknowledged_at", "completed_at", "error_code", "metadata", "created_at", "updated_at"] model_config = ConfigDict( populate_by_name=True, @@ -97,6 +99,11 @@ def to_dict(self) -> Dict[str, Any]: if self.completed_at is None and "completed_at" in self.model_fields_set: _dict['completed_at'] = None + # set to None if error_code (nullable) is None + # and model_fields_set contains the field + if self.error_code is None and "error_code" in self.model_fields_set: + _dict['error_code'] = None + return _dict @classmethod @@ -119,6 +126,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "timeout_at": obj.get("timeout_at"), "acknowledged_at": obj.get("acknowledged_at"), "completed_at": obj.get("completed_at"), + "error_code": obj.get("error_code"), "metadata": obj.get("metadata"), "created_at": obj.get("created_at"), "updated_at": obj.get("updated_at") diff --git a/corelink_sdk/models/problem.py b/corelink_sdk/models/problem.py index d2c9c97..c2b1c78 100644 --- a/corelink_sdk/models/problem.py +++ b/corelink_sdk/models/problem.py @@ -31,8 +31,9 @@ class Problem(BaseModel): status: StrictInt code: StrictStr detail: Optional[StrictStr] = None + diagnostics: Optional[Dict[str, Any]] = None correlation_id: StrictStr - __properties: ClassVar[List[str]] = ["type", "title", "status", "code", "detail", "correlation_id"] + __properties: ClassVar[List[str]] = ["type", "title", "status", "code", "detail", "diagnostics", "correlation_id"] model_config = ConfigDict( populate_by_name=True, @@ -90,6 +91,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "status": obj.get("status"), "code": obj.get("code"), "detail": obj.get("detail"), + "diagnostics": obj.get("diagnostics"), "correlation_id": obj.get("correlation_id") }) return _obj diff --git a/pyproject.toml b/pyproject.toml index f26f67d..47d41a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ description = "Generated Python client for the CoreLink Public API" readme = "README.md" requires-python = ">=3.9" authors = [{ name = "CoreLink Platform" }] -license = "Proprietary" +license = "LicenseRef-Proprietary" keywords = ["corelink", "openapi", "generated-client"] dependencies = [ "urllib3>=1.25.3,<3.0.0", diff --git a/test/test_command.py b/test/test_command.py index 126571b..b98bde9 100644 --- a/test/test_command.py +++ b/test/test_command.py @@ -45,6 +45,7 @@ def make_instance(self, include_optional) -> Command: timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + error_code = '', metadata = { }, created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f') diff --git a/test/test_command_page.py b/test/test_command_page.py index 5d61f26..c0d062b 100644 --- a/test/test_command_page.py +++ b/test/test_command_page.py @@ -3,7 +3,7 @@ """ CoreLink Public API - Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. + Versioned public contract for the proven connected-device slice. Integration details are deliberately excluded. All resource identifiers are canonical CoreLink identifiers. The version of the OpenAPI document: 1.0.0-draft Generated by OpenAPI Generator (https://openapi-generator.tech) @@ -37,18 +37,19 @@ def make_instance(self, include_optional) -> CommandPage: return CommandPage( items = [ corelink_sdk.models.command.Command( - command_id = '', - tenant_id = '', - corelink_device_id = '', - command_type = '', - payload = { }, - status = 'queued', - attempt_count = 56, - timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - metadata = { }, - created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + command_id = '', + tenant_id = '', + corelink_device_id = '', + command_type = '', + payload = { }, + status = 'queued', + attempt_count = 56, + timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + error_code = '', + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) ], total = 56, @@ -59,18 +60,19 @@ def make_instance(self, include_optional) -> CommandPage: return CommandPage( items = [ corelink_sdk.models.command.Command( - command_id = '', - tenant_id = '', - corelink_device_id = '', - command_type = '', - payload = { }, - status = 'queued', - attempt_count = 56, - timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), - metadata = { }, - created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + command_id = '', + tenant_id = '', + corelink_device_id = '', + command_type = '', + payload = { }, + status = 'queued', + attempt_count = 56, + timeout_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + acknowledged_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + completed_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), + error_code = '', + metadata = { }, + created_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), updated_at = datetime.datetime.strptime('2013-10-20 19:20:30.00', '%Y-%m-%d %H:%M:%S.%f'), ) ], total = 56, diff --git a/test/test_problem.py b/test/test_problem.py index 5863a07..938b9db 100644 --- a/test/test_problem.py +++ b/test/test_problem.py @@ -40,6 +40,7 @@ def make_instance(self, include_optional) -> Problem: status = 56, code = '', detail = '', + diagnostics = { }, correlation_id = '' ) else: