diff --git a/codegen/layouts/partials/resource-dataclass.hbs b/codegen/layouts/partials/resource-dataclass.hbs index 8a923753..c0297ba0 100644 --- a/codegen/layouts/partials/resource-dataclass.hbs +++ b/codegen/layouts/partials/resource-dataclass.hbs @@ -15,8 +15,11 @@ {{../memberIndent}}{{pythonIdentifier name}}: {{type}} {{/each}} +{{memberIndent}}# The payload is decoded JSON, so every value read out of it is untyped. +{{memberIndent}}# Typing d as Any keeps that at this boundary instead of casting each +{{memberIndent}}# read, and the dataclass fields carry the real types. {{memberIndent}}@classmethod -{{memberIndent}}def from_dict(cls, d: Dict[str, Any]): +{{memberIndent}}def from_dict(cls, d: Any): {{#unless properties}} {{memberIndent}} # This shape documents no properties, so there is nothing to read. {{memberIndent}} # pylint: disable=unused-argument diff --git a/codegen/layouts/partials/route-method.hbs b/codegen/layouts/partials/route-method.hbs index c009161a..d5549441 100644 --- a/codegen/layouts/partials/route-method.hbs +++ b/codegen/layouts/partials/route-method.hbs @@ -1,6 +1,6 @@ def {{> method-signature}}: """{{> method-docstring}}""" - json_payload = {} + json_payload: Dict[str, Any] = {} {{#each params}} if {{name}} is not None: diff --git a/codegen/lib/layouts/resources.ts b/codegen/lib/layouts/resources.ts index 0463f8de..fc4d6397 100644 --- a/codegen/lib/layouts/resources.ts +++ b/codegen/lib/layouts/resources.ts @@ -6,7 +6,10 @@ import type { Blueprint, Property } from '@seamapi/blueprint' import { pascalCase, snakeCase } from 'change-case' import { convertCustomResourceName } from '../custom-resource-name-conversions.js' -import { mapPropertyToPythonType } from '../python-type.js' +import { + mapPropertyToPythonType, + mapRequiredPropertyToPythonType, +} from '../python-type.js' export interface ResourceLayoutContext extends ResourceClassLayoutContext { moduleName: string @@ -144,6 +147,9 @@ const mergeOccurrences = (occurrences: Property[], path: string): Property => { return { ...first, ...docs } } +const withOptionality = (property: Property, isOptional: boolean): Property => + isOptional ? { ...property, isOptional: true } : property + const mergePropertyLists = ( propertyLists: Property[][], path = '', @@ -161,7 +167,13 @@ const mergePropertyLists = ( } return [...occurrences.entries()].map(([name, group]) => - mergeOccurrences(group, path === '' ? name : `${path}.${name}`), + // A property only some variants carry is absent whenever the merged + // dataclass holds one of the variants that omits it, so it is optional on + // the merged shape no matter how each variant declares it. + withOptionality( + mergeOccurrences(group, path === '' ? name : `${path}.${name}`), + group.length < propertyLists.length, + ), ) } @@ -249,7 +261,17 @@ const buildClass = ( ) } - const type = mapPropertyToPythonType(property, nestedClassName) + const isObject = nestedClassName != null && property.format === 'object' + // A nested object is read as None whenever the payload omits it, and the + // schema is not a reliable guide to when that happens: an action attempt + // documents both error and result as required, yet a pending one carries + // neither. Constructing them unconditionally would fail on those payloads, + // so from_dict keeps its None fallback and the field stays Optional. + const type = mapPropertyToPythonType(property, nestedClassName, isObject) + const requiredType = mapRequiredPropertyToPythonType( + property, + nestedClassName, + ) return { name: property.name, description: property.description, @@ -259,8 +281,8 @@ const buildClass = ( // Nested classes are attributes of the class that owns them, so // from_dict reaches them through cls rather than a qualified path. nestedClassName: nestedClassName ?? '', - isDictParam: type.startsWith('Dict'), - isObject: nestedClassName != null && property.format === 'object', + isDictParam: requiredType.startsWith('Dict'), + isObject, isObjectList: nestedClassName != null && property.format === 'list', } }) diff --git a/codegen/lib/python-type.ts b/codegen/lib/python-type.ts index feed09b5..fadcd5d7 100644 --- a/codegen/lib/python-type.ts +++ b/codegen/lib/python-type.ts @@ -21,9 +21,25 @@ export const mapParameterToPythonType = (parameter: Parameter): string => { return mapScalarFormatToPythonType(parameter.format) } +// from_dict reads every property with dict.get, so a property the API may omit +// or send as null arrives as None. Declaring those fields Optional keeps the +// dataclass honest about what a caller can actually find on it. export const mapPropertyToPythonType = ( property: Property, nestedClassName?: string, + isOptional = false, +): string => { + const type = mapRequiredPropertyToPythonType(property, nestedClassName) + return isOptional || property.isOptional || property.isNullable + ? `Optional[${type}]` + : type +} + +// The type a property has before optionality is taken into account. Callers +// that match on the shape of the type, rather than render it, want this one. +export const mapRequiredPropertyToPythonType = ( + property: Property, + nestedClassName?: string, ): string => { if (property.format === 'list') { return `List[${ diff --git a/justfile b/justfile index a34cc4d5..ed397262 100644 --- a/justfile +++ b/justfile @@ -11,7 +11,7 @@ default: build uv run pylint ./seam ./test uv run black --check . uv run rstcheck README.rst - uv run mypy seam/resources --disable-error-code=arg-type --disable-error-code=import-not-found + uv run mypy seam test @test: uv run pytest --cov=./seam diff --git a/seam/__init__.py b/seam/__init__.py index 6e62d98d..de402cd8 100644 --- a/seam/__init__.py +++ b/seam/__init__.py @@ -1,5 +1,4 @@ # flake8: noqa -# type: ignore from .seam import Seam from .seam_without_workspace import SeamWithoutWorkspace diff --git a/seam/auth.py b/seam/auth.py index 3b30c071..6b8c09af 100644 --- a/seam/auth.py +++ b/seam/auth.py @@ -43,15 +43,18 @@ def get_auth_headers( api_key=api_key, personal_access_token=personal_access_token, ): - return get_auth_headers_for_api_key(api_key) + # The guard returns True only for a non-None api_key, which is not + # something the type checker can see through the call. + return get_auth_headers_for_api_key(api_key) # type: ignore[arg-type] if is_seam_options_with_personal_access_token( personal_access_token=personal_access_token, api_key=api_key, workspace_id=workspace_id, ): + # Likewise, the guard raises unless both of these are set. return get_auth_headers_for_personal_access_token( - personal_access_token, workspace_id + personal_access_token, workspace_id # type: ignore[arg-type] ) raise SeamInvalidOptionsError( diff --git a/seam/client.py b/seam/client.py index 9dc3ea44..e637020b 100644 --- a/seam/client.py +++ b/seam/client.py @@ -40,7 +40,7 @@ def _handle_response(self, response: requests.Response): raise NotImplementedError @abc.abstractmethod - def _handle_error_response(self, response: requests.Response): + def _handle_error_response(self, response: requests.Response, status_code: int): raise NotImplementedError @@ -74,7 +74,19 @@ def __init__( headers = {**auth_headers, **custom_headers, **SDK_HEADERS} self.headers.update(headers) - def request(self, method, url, *args, **kwargs): + # request returns the decoded body rather than the Response that + # niquests.Session promises, so the verb helpers routed through it have to + # say so too. Without these overrides callers see the inherited Response + # type and indexing the returned payload does not type check. + def get(self, url, **kwargs) -> Any: + return self.request("GET", url, **kwargs) + + # data and json are named rather than collected into *args because + # Session.request takes params in the position Session.post gives data. + def post(self, url, data=None, json=None, **kwargs) -> Any: + return self.request("POST", url, data=data, json=json, **kwargs) + + def request(self, method, url, *args, **kwargs) -> Any: url = urljoin(self.base_url, url) if kwargs.get("timeout", NIQUESTS_TIMEOUT_DEFAULT) == NIQUESTS_TIMEOUT_DEFAULT: @@ -85,16 +97,22 @@ def request(self, method, url, *args, **kwargs): return self._handle_response(response) def _handle_response(self, response: requests.Response): - if not 200 <= response.status_code < 300: - self._handle_error_response(response) + # niquests types status_code as optional because a Response exists + # before it has one. Anything reaching here has been received, so a + # missing status is an error the SDK cannot classify itself. + status_code = response.status_code + + if status_code is None: + response.raise_for_status() + elif not 200 <= status_code < 300: + self._handle_error_response(response, status_code) if "application/json" in response.headers.get("content-type", ""): return response.json() return response.text - def _handle_error_response(self, response: requests.Response): - status_code = response.status_code + def _handle_error_response(self, response: requests.Response, status_code: int): request_id = response.headers.get("seam-request-id") if status_code == 401: diff --git a/seam/exceptions.py b/seam/exceptions.py index 73fc3210..9a8367b7 100644 --- a/seam/exceptions.py +++ b/seam/exceptions.py @@ -1,4 +1,4 @@ -from typing import Any, Dict +from typing import Any, Dict, Optional from .resources import ActionAttempt @@ -15,20 +15,24 @@ class SeamHttpApiError(Exception): :vartype code: str :ivar status_code: The HTTP status code of the error response :vartype status_code: int - :ivar request_id: The unique identifier for the API request - :vartype request_id: str + :ivar request_id: The unique identifier for the API request, when the + response carried one + :vartype request_id: Optional[str] :ivar data: Additional error data, if provided by the API :vartype data: Dict[str, Any] """ - def __init__(self, error: Dict[str, Any], status_code: int, request_id: str): + def __init__( + self, error: Dict[str, Any], status_code: int, request_id: Optional[str] + ): """ :param error: Dictionary containing error details from the API response :type error: Dict[str, Any] :param status_code: HTTP status code of the error response :type status_code: int - :param request_id: Unique identifier for the API request - :type request_id: str + :param request_id: Unique identifier for the API request, when the + response carried one + :type request_id: Optional[str] """ super().__init__(error.get("message")) @@ -45,10 +49,11 @@ class SeamHttpUnauthorizedError(SeamHttpApiError): This exception is a specific type of SeamHttpApiError for 401 Unauthorized errors. """ - def __init__(self, request_id: str): + def __init__(self, request_id: Optional[str]): """ - :param request_id: Unique identifier for the API request - :type request_id: str + :param request_id: Unique identifier for the API request, when the + response carried one + :type request_id: Optional[str] """ super().__init__( @@ -66,14 +71,17 @@ class SeamHttpInvalidInputError(SeamHttpApiError): :vartype code: str """ - def __init__(self, error: Dict[str, Any], status_code: int, request_id: str): + def __init__( + self, error: Dict[str, Any], status_code: int, request_id: Optional[str] + ): """ :param error: Dictionary containing error details from the API response :type error: Dict[str, Any] :param status_code: HTTP status code of the error response :type status_code: int - :param request_id: Unique identifier for the API request - :type request_id: str + :param request_id: Unique identifier for the API request, when the + response carried one + :type request_id: Optional[str] """ super().__init__(error, status_code, request_id) @@ -120,9 +128,17 @@ def __init__(self, action_attempt: ActionAttempt): :type action_attempt: ActionAttempt """ - super().__init__(action_attempt.error.message, action_attempt) + # A failed action attempt carries an error, but reading through it + # unguarded would raise AttributeError over the actual failure if one + # ever arrives without it. + error = action_attempt.error + + super().__init__( + error.message if error is not None else "Action attempt failed", + action_attempt, + ) self.name = self.__class__.__name__ - self.code = action_attempt.error.type + self.code = error.type if error is not None else "unknown_error" class SeamActionAttemptTimeoutError(SeamActionAttemptError): @@ -136,12 +152,12 @@ class SeamActionAttemptTimeoutError(SeamActionAttemptError): :vartype name: str """ - def __init__(self, action_attempt: ActionAttempt, timeout: str): + def __init__(self, action_attempt: ActionAttempt, timeout: float): """ :param action_attempt: The ActionAttempt object associated with this error :type action_attempt: ActionAttempt :param timeout: The timeout duration in seconds - :type timeout: str + :type timeout: float """ message = f"Timed out waiting for action attempt after {timeout}s" diff --git a/seam/modules/action_attempts.py b/seam/modules/action_attempts.py index 7d48243c..d764d3cb 100644 --- a/seam/modules/action_attempts.py +++ b/seam/modules/action_attempts.py @@ -21,8 +21,8 @@ def poll_until_ready( client: SeamHttpClient, *, action_attempt_id: str, - timeout: Optional[float] = TIMEOUT, - polling_interval: Optional[float] = POLLING_INTERVAL, + timeout: float = TIMEOUT, + polling_interval: float = POLLING_INTERVAL, ) -> ActionAttempt: time_waiting = 0.0 diff --git a/seam/paginator.py b/seam/paginator.py index fedb86d9..119173ca 100644 --- a/seam/paginator.py +++ b/seam/paginator.py @@ -1,6 +1,6 @@ -from typing import Callable, Dict, Any, Tuple, Generator, List +from typing import Callable, Dict, Any, Optional, Tuple, Generator, List, Union from .client import SeamHttpClient -from niquests import Response, JSONDecodeError +from niquests import PreparedRequest, Response, JSONDecodeError from .pagination import Pagination @@ -17,7 +17,7 @@ def __init__( self, client: SeamHttpClient, request: Callable, - params: Dict[str, Any] = None, + params: Optional[Dict[str, Any]] = None, ): """ Initializes the Paginator. @@ -74,7 +74,7 @@ def flatten_to_list(self) -> List[Any]: if current_items: all_items.extend(current_items) - while pagination.has_next_page: + while pagination and pagination.has_next_page and pagination.next_page_cursor: current_items, pagination = self.next_page(pagination.next_page_cursor) if current_items: all_items.extend(current_items) @@ -92,8 +92,13 @@ def flatten(self) -> Generator[Any, None, None]: if current_items: yield from current_items - def _cache_pagination(self, response: Response, page_key: str) -> None: + def _cache_pagination( + self, response: Union[PreparedRequest, Response], page_key: str + ) -> None: """Extracts pagination dict from response, creates Pagination object, and caches it.""" + if not isinstance(response, Response): + return + try: response_json = response.json() pagination = response_json.get("pagination", {}) diff --git a/seam/resources/access_code.py b/seam/resources/access_code.py index 00fc66a5..7cb5baba 100644 --- a/seam/resources/access_code.py +++ b/seam/resources/access_code.py @@ -86,17 +86,20 @@ class DormakabaOracodeMetadata(ResourceMapping): :ivar user_level_name: Dormakaba Oracode user level name associated with this access code. """ - is_cancellable: bool - is_early_checkin_able: bool - is_extendable: bool - is_overridable: bool - site_name: str - stay_id: float - user_level_id: str - user_level_name: str - + is_cancellable: Optional[bool] + is_early_checkin_able: Optional[bool] + is_extendable: Optional[bool] + is_overridable: Optional[bool] + site_name: Optional[str] + stay_id: Optional[float] + user_level_id: Optional[str] + user_level_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( is_cancellable=d.get("is_cancellable", None), is_early_checkin_able=d.get("is_early_checkin_able", None), @@ -146,31 +149,37 @@ class ModifiedFields(ResourceMapping): :ivar to: The new value of the field.""" field: str - from_: str - to: str + from_: Optional[str] + to: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( field=d.get("field", None), from_=d.get("from", None), to=d.get("to", None), ) - created_at: str + created_at: Optional[str] error_code: str - is_access_code_error: bool + is_access_code_error: Optional[bool] message: str - managed_access_code_id: str - unmanaged_access_code_id: str - change_type: str - modified_fields: List[ModifiedFields] - is_connected_account_error: bool - is_device_error: bool - is_bridge_error: bool - + managed_access_code_id: Optional[str] + unmanaged_access_code_id: Optional[str] + change_type: Optional[str] + modified_fields: Optional[List[ModifiedFields]] + is_connected_account_error: Optional[bool] + is_device_error: Optional[bool] + is_bridge_error: Optional[bool] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -216,13 +225,16 @@ class From(ResourceMapping): :ivar starts_at: Previous start time for the access code.""" - code: str - name: str - ends_at: str - starts_at: str + code: Optional[str] + name: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( code=d.get("code", None), name=d.get("name", None), @@ -242,13 +254,16 @@ class To(ResourceMapping): :ivar starts_at: New start time for the access code.""" - code: str - name: str - ends_at: str - starts_at: str + code: Optional[str] + name: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( code=d.get("code", None), name=d.get("name", None), @@ -259,12 +274,15 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str message: str mutation_code: str - scheduled_at: str - from_: From - to: To + scheduled_at: Optional[str] + from_: Optional[From] + to: Optional[To] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -304,25 +322,31 @@ class ModifiedFields(ResourceMapping): :ivar to: The new value of the field.""" field: str - from_: str - to: str + from_: Optional[str] + to: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( field=d.get("field", None), from_=d.get("from", None), to=d.get("to", None), ) - created_at: str + created_at: Optional[str] message: str warning_code: str - change_type: str - modified_fields: List[ModifiedFields] + change_type: Optional[str] + modified_fields: Optional[List[ModifiedFields]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -335,32 +359,35 @@ def from_dict(cls, d: Dict[str, Any]): ) access_code_id: str - code: str - common_code_key: str + code: Optional[str] + common_code_key: Optional[str] created_at: str device_id: str - dormakaba_oracode_metadata: DormakabaOracodeMetadata - ends_at: str + dormakaba_oracode_metadata: Optional[DormakabaOracodeMetadata] + ends_at: Optional[str] errors: List[Errors] - is_backup: bool + is_backup: Optional[bool] is_backup_access_code_available: bool is_external_modification_allowed: bool is_managed: bool is_offline_access_code: bool is_one_time_use: bool - is_scheduled_on_device: bool - is_waiting_for_code_assignment: bool - name: str + is_scheduled_on_device: Optional[bool] + is_waiting_for_code_assignment: Optional[bool] + name: Optional[str] pending_mutations: List[PendingMutations] - pulled_backup_access_code_id: str - starts_at: str + pulled_backup_access_code_id: Optional[str] + starts_at: Optional[str] status: str type: str warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_code_id=d.get("access_code_id", None), code=d.get("code", None), diff --git a/seam/resources/access_grant.py b/seam/resources/access_grant.py index 77550335..4eac1e84 100644 --- a/seam/resources/access_grant.py +++ b/seam/resources/access_grant.py @@ -64,10 +64,13 @@ class Errors(ResourceMapping): created_at: str error_code: str message: str - missing_device_ids: List[str] + missing_device_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -101,12 +104,15 @@ class From(ResourceMapping): :ivar starts_at: Previous start time for access.""" - device_ids: List[str] - ends_at: str - starts_at: str + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_ids=d.get("device_ids", None), ends_at=d.get("ends_at", None), @@ -125,13 +131,16 @@ class To(ResourceMapping): :ivar starts_at: New start time for access.""" - common_code_key: str - device_ids: List[str] - ends_at: str - starts_at: str + common_code_key: Optional[str] + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( common_code_key=d.get("common_code_key", None), device_ids=d.get("device_ids", None), @@ -140,14 +149,17 @@ def from_dict(cls, d: Dict[str, Any]): ) created_at: str - from_: From + from_: Optional[From] message: str mutation_code: str - to: To - access_method_ids: List[str] + to: Optional[To] + access_method_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), from_=( @@ -178,15 +190,18 @@ class RequestedAccessMethods(ResourceMapping): :ivar mode: Access method mode. Supported values: ``code``, ``card``, ``mobile_key``, ``cloud_key``. """ - code: str + code: Optional[str] created_access_method_ids: List[str] created_at: str display_name: str - instant_key_max_use_count: int + instant_key_max_use_count: Optional[int] mode: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( code=d.get("code", None), created_access_method_ids=d.get("created_access_method_ids", None), @@ -233,8 +248,11 @@ class FailedDevices(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), error_code=d.get("error_code", None), @@ -244,15 +262,18 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str message: str warning_code: str - failed_devices: List[FailedDevices] - access_method_ids: List[str] - device_id: str - new_code: str - original_code: str - reason: str - + failed_devices: Optional[List[FailedDevices]] + access_method_ids: Optional[List[str]] + device_id: Optional[str] + new_code: Optional[str] + original_code: Optional[str] + reason: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -269,28 +290,31 @@ def from_dict(cls, d: Dict[str, Any]): ) access_grant_id: str - access_grant_key: str + access_grant_key: Optional[str] access_method_ids: List[str] - client_session_token: str + client_session_token: Optional[str] created_at: str - customization_profile_id: str + customization_profile_id: Optional[str] display_name: str - ends_at: str + ends_at: Optional[str] errors: List[Errors] - instant_key_url: str + instant_key_url: Optional[str] location_ids: List[str] - name: str + name: Optional[str] pending_mutations: List[PendingMutations] requested_access_methods: List[RequestedAccessMethods] - reservation_key: str + reservation_key: Optional[str] space_ids: List[str] starts_at: str user_identity_id: str warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_grant_id=d.get("access_grant_id", None), access_grant_key=d.get("access_grant_key", None), diff --git a/seam/resources/access_method.py b/seam/resources/access_method.py index f8d11823..595d6611 100644 --- a/seam/resources/access_method.py +++ b/seam/resources/access_method.py @@ -59,8 +59,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -91,12 +94,15 @@ class From(ResourceMapping): :ivar starts_at: Previous start time for access.""" - device_ids: List[str] - ends_at: str - starts_at: str + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_ids=d.get("device_ids", None), ends_at=d.get("ends_at", None), @@ -113,12 +119,15 @@ class To(ResourceMapping): :ivar starts_at: New start time for access.""" - device_ids: List[str] - ends_at: str - starts_at: str + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_ids=d.get("device_ids", None), ends_at=d.get("ends_at", None), @@ -126,13 +135,16 @@ def from_dict(cls, d: Dict[str, Any]): ) created_at: str - from_: From + from_: Optional[From] message: str mutation_code: str - to: To + to: Optional[To] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), from_=( @@ -161,10 +173,13 @@ class Warnings(ResourceMapping): created_at: str message: str warning_code: str - original_access_method_id: str + original_access_method_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -173,26 +188,29 @@ def from_dict(cls, d: Dict[str, Any]): ) access_method_id: str - client_session_token: str - code: str + client_session_token: Optional[str] + code: Optional[str] created_at: str - customization_profile_id: str + customization_profile_id: Optional[str] display_name: str errors: List[Errors] - instant_key_url: str - is_assignment_required: bool - is_encoding_required: bool + instant_key_url: Optional[str] + is_assignment_required: Optional[bool] + is_encoding_required: Optional[bool] is_issued: bool - is_ready_for_assignment: bool - is_ready_for_encoding: bool - issued_at: str + is_ready_for_assignment: Optional[bool] + is_ready_for_encoding: Optional[bool] + issued_at: Optional[str] mode: str pending_mutations: List[PendingMutations] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_method_id=d.get("access_method_id", None), client_session_token=d.get("client_session_token", None), diff --git a/seam/resources/acs_access_group.py b/seam/resources/acs_access_group.py index 24692f63..ca19719f 100644 --- a/seam/resources/acs_access_group.py +++ b/seam/resources/acs_access_group.py @@ -53,11 +53,14 @@ class AccessSchedule(ResourceMapping): :ivar starts_at: Date and time at which the user's access starts, in `ISO 8601 `_ format. """ - ends_at: str + ends_at: Optional[str] starts_at: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( ends_at=d.get("ends_at", None), starts_at=d.get("starts_at", None), @@ -78,8 +81,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -119,14 +125,17 @@ class From(ResourceMapping): :ivar acs_entrance_id: Old entrance ID.""" - name: str - ends_at: str - starts_at: str - acs_user_id: str - acs_entrance_id: str + name: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + acs_user_id: Optional[str] + acs_entrance_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( name=d.get("name", None), ends_at=d.get("ends_at", None), @@ -149,14 +158,17 @@ class To(ResourceMapping): :ivar acs_entrance_id: New entrance ID.""" - name: str - ends_at: str - starts_at: str - acs_user_id: str - acs_entrance_id: str + name: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + acs_user_id: Optional[str] + acs_entrance_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( name=d.get("name", None), ends_at=d.get("ends_at", None), @@ -168,13 +180,16 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str message: str mutation_code: str - from_: From - to: To - acs_user_id: str - variant: str - + from_: Optional[From] + to: Optional[To] + acs_user_id: Optional[str] + variant: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -204,8 +219,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -214,7 +232,7 @@ def from_dict(cls, d: Dict[str, Any]): access_group_type: str access_group_type_display_name: str - access_schedule: AccessSchedule + access_schedule: Optional[AccessSchedule] acs_access_group_id: str acs_system_id: str connected_account_id: str @@ -229,8 +247,11 @@ def from_dict(cls, d: Dict[str, Any]): warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_group_type=d.get("access_group_type", None), access_group_type_display_name=d.get( diff --git a/seam/resources/acs_credential.py b/seam/resources/acs_credential.py index 561bded7..a33ca7b1 100644 --- a/seam/resources/acs_credential.py +++ b/seam/resources/acs_credential.py @@ -88,15 +88,18 @@ class AssaAbloyVostioMetadata(ResourceMapping): :ivar override_guest_acs_entrance_ids: IDs of the guest entrances to override in the Vostio access system. """ - auto_join: bool - door_names: List[str] - endpoint_id: str - key_id: str - key_issuing_request_id: str - override_guest_acs_entrance_ids: List[str] - + auto_join: Optional[bool] + door_names: Optional[List[str]] + endpoint_id: Optional[str] + key_id: Optional[str] + key_issuing_request_id: Optional[str] + override_guest_acs_entrance_ids: Optional[List[str]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_join=d.get("auto_join", None), door_names=d.get("door_names", None), @@ -122,8 +125,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -151,17 +157,20 @@ class VisionlineMetadata(ResourceMapping): :ivar joiner_acs_credential_ids: IDs of the credentials to which you want to join. """ - auto_join: bool - card_function_type: str - card_id: str - common_acs_entrance_ids: List[str] - credential_id: str - guest_acs_entrance_ids: List[str] - is_valid: bool - joiner_acs_credential_ids: List[str] - + auto_join: Optional[bool] + card_function_type: Optional[str] + card_id: Optional[str] + common_acs_entrance_ids: Optional[List[str]] + credential_id: Optional[str] + guest_acs_entrance_ids: Optional[List[str]] + is_valid: Optional[bool] + joiner_acs_credential_ids: Optional[List[str]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_join=d.get("auto_join", None), card_function_type=d.get("card_function_type", None), @@ -188,8 +197,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -198,35 +210,38 @@ def from_dict(cls, d: Dict[str, Any]): access_method: str acs_credential_id: str - acs_credential_pool_id: str + acs_credential_pool_id: Optional[str] acs_system_id: str - acs_user_id: str - assa_abloy_vostio_metadata: AssaAbloyVostioMetadata - card_number: str - code: str + acs_user_id: Optional[str] + assa_abloy_vostio_metadata: Optional[AssaAbloyVostioMetadata] + card_number: Optional[str] + code: Optional[str] connected_account_id: str created_at: str display_name: str - ends_at: str + ends_at: Optional[str] errors: List[Errors] - external_type: str - external_type_display_name: str - is_issued: bool - is_latest_desired_state_synced_with_provider: bool + external_type: Optional[str] + external_type_display_name: Optional[str] + is_issued: Optional[bool] + is_latest_desired_state_synced_with_provider: Optional[bool] is_managed: bool - is_multi_phone_sync_credential: bool - is_one_time_use: bool - issued_at: str - latest_desired_state_synced_with_provider_at: str - parent_acs_credential_id: str - starts_at: str - user_identity_id: str - visionline_metadata: VisionlineMetadata + is_multi_phone_sync_credential: Optional[bool] + is_one_time_use: Optional[bool] + issued_at: Optional[str] + latest_desired_state_synced_with_provider_at: Optional[str] + parent_acs_credential_id: Optional[str] + starts_at: Optional[str] + user_identity_id: Optional[str] + visionline_metadata: Optional[VisionlineMetadata] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_method=d.get("access_method", None), acs_credential_id=d.get("acs_credential_id", None), diff --git a/seam/resources/acs_encoder.py b/seam/resources/acs_encoder.py index 88bc5a75..b048ad95 100644 --- a/seam/resources/acs_encoder.py +++ b/seam/resources/acs_encoder.py @@ -51,8 +51,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -67,8 +70,11 @@ def from_dict(cls, d: Dict[str, Any]): errors: List[Errors] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_encoder_id=d.get("acs_encoder_id", None), acs_system_id=d.get("acs_system_id", None), diff --git a/seam/resources/acs_entrance.py b/seam/resources/acs_entrance.py index d3c40fee..6c5ccb71 100644 --- a/seam/resources/acs_entrance.py +++ b/seam/resources/acs_entrance.py @@ -81,23 +81,29 @@ class Actions(ResourceMapping): :ivar name: Name of the gadget action.""" - id: str - name: str + id: Optional[str] + name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( id=d.get("id", None), name=d.get("name", None), ) - actions: List[Actions] - gadget_id: str - site_id: str - site_name: str + actions: Optional[List[Actions]] + gadget_id: Optional[str] + site_id: Optional[str] + site_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( actions=[cls.Actions.from_dict(i) for i in d.get("actions") or []], gadget_id=d.get("gadget_id", None), @@ -120,14 +126,17 @@ class AssaAbloyVostioMetadata(ResourceMapping): :ivar stand_open: Indicates whether keys are allowed to set the door in stand open mode in the Vostio access system. """ - door_name: str - door_number: float - door_type: str - pms_id: str - stand_open: bool + door_name: Optional[str] + door_number: Optional[float] + door_type: Optional[str] + pms_id: Optional[str] + stand_open: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( door_name=d.get("door_name", None), door_number=d.get("door_number", None), @@ -154,16 +163,19 @@ class AvigilonAltaMetadata(ResourceMapping): :ivar zone_name: Zone name for an Avigilon Alta system.""" - entry_name: str - entry_relays_total_count: float - org_name: str - site_id: float - site_name: str - zone_id: float - zone_name: str - + entry_name: Optional[str] + entry_relays_total_count: Optional[float] + org_name: Optional[str] + site_id: Optional[float] + site_name: Optional[str] + zone_id: Optional[float] + zone_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( entry_name=d.get("entry_name", None), entry_relays_total_count=d.get("entry_relays_total_count", None), @@ -184,12 +196,15 @@ class BrivoMetadata(ResourceMapping): :ivar site_name: Name of the site that the access point belongs to.""" - access_point_id: str - site_id: float - site_name: str + access_point_id: Optional[str] + site_id: Optional[float] + site_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_point_id=d.get("access_point_id", None), site_id=d.get("site_id", None), @@ -203,10 +218,13 @@ class DormakabaAmbianceMetadata(ResourceMapping): :ivar access_point_name: Name of the access point in the dormakaba Ambiance access system. """ - access_point_name: str + access_point_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_point_name=d.get("access_point_name", None), ) @@ -218,10 +236,13 @@ class DormakabaCommunityMetadata(ResourceMapping): :ivar access_point_profile: Type of access point profile in the dormakaba Community access system. """ - access_point_profile: str + access_point_profile: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_point_profile=d.get("access_point_profile", None), ) @@ -241,8 +262,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -259,12 +283,15 @@ class HotekMetadata(ResourceMapping): :ivar room_number: Room number of the entrance.""" - common_area_name: str - common_area_number: str - room_number: str + common_area_name: Optional[str] + common_area_number: Optional[str] + room_number: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( common_area_name=d.get("common_area_name", None), common_area_number=d.get("common_area_number", None), @@ -283,13 +310,16 @@ class LatchMetadata(ResourceMapping): :ivar is_connected: Indicates whether the entrance is connected.""" - accessibility_type: str - door_name: str - door_type: str - is_connected: bool + accessibility_type: Optional[str] + door_name: Optional[str] + door_type: Optional[str] + is_connected: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accessibility_type=d.get("accessibility_type", None), door_name=d.get("door_name", None), @@ -317,17 +347,20 @@ class SaltoKsMetadata(ResourceMapping): :ivar privacy_mode: Indicates whether privacy mode is enabled for the lock.""" - battery_level: str - door_name: str - intrusion_alarm: bool - left_open_alarm: bool - lock_type: str - locked_state: str - online: bool - privacy_mode: bool - + battery_level: Optional[str] + door_name: Optional[str] + intrusion_alarm: Optional[bool] + left_open_alarm: Optional[bool] + lock_type: Optional[str] + locked_state: Optional[str] + online: Optional[bool] + privacy_mode: Optional[bool] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( battery_level=d.get("battery_level", None), door_name=d.get("door_name", None), @@ -355,15 +388,18 @@ class SaltoSpaceMetadata(ResourceMapping): :ivar room_name: Name of the room in the Salto Space access system.""" - audit_on_keys: bool - door_description: str - door_id: str - door_name: str - room_description: str - room_name: str + audit_on_keys: Optional[bool] + door_description: Optional[str] + door_id: Optional[str] + door_name: Optional[str] + room_description: Optional[str] + room_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( audit_on_keys=d.get("audit_on_keys", None), door_description=d.get("door_description", None), @@ -392,11 +428,14 @@ class Profiles(ResourceMapping): :ivar visionline_door_profile_type: Door profile type in the Visionline access system. """ - visionline_door_profile_id: str - visionline_door_profile_type: str + visionline_door_profile_id: Optional[str] + visionline_door_profile_type: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( visionline_door_profile_id=d.get( "visionline_door_profile_id", None @@ -406,12 +445,15 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - door_category: str - door_name: str - profiles: List[Profiles] + door_category: Optional[str] + door_name: Optional[str] + profiles: Optional[List[Profiles]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( door_category=d.get("door_category", None), door_name=d.get("door_name", None), @@ -433,8 +475,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -443,32 +488,35 @@ def from_dict(cls, d: Dict[str, Any]): acs_entrance_id: str acs_system_id: str - akiles_metadata: AkilesMetadata - assa_abloy_vostio_metadata: AssaAbloyVostioMetadata - avigilon_alta_metadata: AvigilonAltaMetadata - brivo_metadata: BrivoMetadata - can_belong_to_reservation: bool - can_unlock_with_card: bool - can_unlock_with_cloud_key: bool - can_unlock_with_code: bool - can_unlock_with_mobile_key: bool + akiles_metadata: Optional[AkilesMetadata] + assa_abloy_vostio_metadata: Optional[AssaAbloyVostioMetadata] + avigilon_alta_metadata: Optional[AvigilonAltaMetadata] + brivo_metadata: Optional[BrivoMetadata] + can_belong_to_reservation: Optional[bool] + can_unlock_with_card: Optional[bool] + can_unlock_with_cloud_key: Optional[bool] + can_unlock_with_code: Optional[bool] + can_unlock_with_mobile_key: Optional[bool] connected_account_id: str created_at: str display_name: str - dormakaba_ambiance_metadata: DormakabaAmbianceMetadata - dormakaba_community_metadata: DormakabaCommunityMetadata + dormakaba_ambiance_metadata: Optional[DormakabaAmbianceMetadata] + dormakaba_community_metadata: Optional[DormakabaCommunityMetadata] errors: List[Errors] - hotek_metadata: HotekMetadata - is_locked: bool - latch_metadata: LatchMetadata - salto_ks_metadata: SaltoKsMetadata - salto_space_metadata: SaltoSpaceMetadata + hotek_metadata: Optional[HotekMetadata] + is_locked: Optional[bool] + latch_metadata: Optional[LatchMetadata] + salto_ks_metadata: Optional[SaltoKsMetadata] + salto_space_metadata: Optional[SaltoSpaceMetadata] space_ids: List[str] - visionline_metadata: VisionlineMetadata + visionline_metadata: Optional[VisionlineMetadata] warnings: List[Warnings] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_entrance_id=d.get("acs_entrance_id", None), acs_system_id=d.get("acs_system_id", None), diff --git a/seam/resources/acs_system.py b/seam/resources/acs_system.py index 933eaecd..3c1ebf54 100644 --- a/seam/resources/acs_system.py +++ b/seam/resources/acs_system.py @@ -69,10 +69,13 @@ class Errors(ResourceMapping): created_at: str error_code: str message: str - is_bridge_error: bool + is_bridge_error: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -87,10 +90,13 @@ class Location(ResourceMapping): :ivar time_zone: Time zone in which the `access control system `_ is located. """ - time_zone: str + time_zone: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( time_zone=d.get("time_zone", None), ) @@ -106,12 +112,15 @@ class VisionlineMetadata(ResourceMapping): :ivar system_id: Unique ID assigned by the ASSA ABLOY licensing team that identifies each hotel in your credential manager. """ - lan_address: str - mobile_access_uuid: str - system_id: str + lan_address: Optional[str] + mobile_access_uuid: Optional[str] + system_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( lan_address=d.get("lan_address", None), mobile_access_uuid=d.get("mobile_access_uuid", None), @@ -133,10 +142,13 @@ class Warnings(ResourceMapping): created_at: str message: str warning_code: str - misconfigured_acs_entrance_ids: List[str] + misconfigured_acs_entrance_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -146,29 +158,32 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - acs_access_group_count: float + acs_access_group_count: Optional[float] acs_system_id: str - acs_user_count: float + acs_user_count: Optional[float] connected_account_id: str connected_account_ids: List[str] created_at: str - default_credential_manager_acs_system_id: str + default_credential_manager_acs_system_id: Optional[str] errors: List[Errors] - external_type: str - external_type_display_name: str + external_type: Optional[str] + external_type_display_name: Optional[str] image_alt_text: str image_url: str is_credential_manager: bool - location: Location + location: Optional[Location] name: str - system_type: str - system_type_display_name: str - visionline_metadata: VisionlineMetadata + system_type: Optional[str] + system_type_display_name: Optional[str] + visionline_metadata: Optional[VisionlineMetadata] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_access_group_count=d.get("acs_access_group_count", None), acs_system_id=d.get("acs_system_id", None), diff --git a/seam/resources/acs_user.py b/seam/resources/acs_user.py index faef5196..18ce9aa2 100644 --- a/seam/resources/acs_user.py +++ b/seam/resources/acs_user.py @@ -72,11 +72,14 @@ class AccessSchedule(ResourceMapping): :ivar starts_at: Date and time at which the user's access starts, in `ISO 8601 `_ format. """ - ends_at: str + ends_at: Optional[str] starts_at: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( ends_at=d.get("ends_at", None), starts_at=d.get("starts_at", None), @@ -97,8 +100,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -146,17 +152,20 @@ class From(ResourceMapping): :ivar acs_credential_id: Previous credential ID.""" - email_address: str - full_name: str - phone_number: str - ends_at: str - starts_at: str - is_suspended: bool - acs_access_group_id: str - acs_credential_id: str - + email_address: Optional[str] + full_name: Optional[str] + phone_number: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + is_suspended: Optional[bool] + acs_access_group_id: Optional[str] + acs_credential_id: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( email_address=d.get("email_address", None), full_name=d.get("full_name", None), @@ -188,17 +197,20 @@ class To(ResourceMapping): :ivar acs_credential_id: New credential ID.""" - email_address: str - full_name: str - phone_number: str - ends_at: str - starts_at: str - is_suspended: bool - acs_access_group_id: str - acs_credential_id: str - + email_address: Optional[str] + full_name: Optional[str] + phone_number: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + is_suspended: Optional[bool] + acs_access_group_id: Optional[str] + acs_credential_id: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( email_address=d.get("email_address", None), full_name=d.get("full_name", None), @@ -213,14 +225,17 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str message: str mutation_code: str - scheduled_at: str - from_: From - to: To - acs_access_group_id: str - variant: str - + scheduled_at: Optional[str] + from_: Optional[From] + to: Optional[To] + acs_access_group_id: Optional[str] + variant: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -243,10 +258,13 @@ class SaltoKsMetadata(ResourceMapping): :ivar is_subscribed: Indicates whether the user holds an active subscription slot on the Salto KS site. Only subscribed users can unlock doors and count against the site's user-subscription limit. A user may not be subscribed because their access schedule has not started or has ended, the site has reached its subscription limit, or they were manually unsubscribed. This is distinct from ``is_suspended``, which reflects whether the user has been explicitly blocked. """ - is_subscribed: bool + is_subscribed: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( is_subscribed=d.get("is_subscribed", None), ) @@ -259,11 +277,14 @@ class SaltoSpaceMetadata(ResourceMapping): :ivar user_id: User ID in the Salto Space access system.""" - audit_openings: bool - user_id: str + audit_openings: Optional[bool] + user_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( audit_openings=d.get("audit_openings", None), user_id=d.get("user_id", None), @@ -283,42 +304,48 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), warning_code=d.get("warning_code", None), ) - access_schedule: AccessSchedule + access_schedule: Optional[AccessSchedule] acs_system_id: str acs_user_id: str connected_account_id: str created_at: str display_name: str - email: str - email_address: str + email: Optional[str] + email_address: Optional[str] errors: List[Errors] - external_type: str - external_type_display_name: str - full_name: str - hid_acs_system_id: str + external_type: Optional[str] + external_type_display_name: Optional[str] + full_name: Optional[str] + hid_acs_system_id: Optional[str] is_managed: bool - is_suspended: bool - pending_mutations: List[PendingMutations] - phone_number: str - salto_ks_metadata: SaltoKsMetadata - salto_space_metadata: SaltoSpaceMetadata - user_identity_email_address: str - user_identity_full_name: str - user_identity_id: str - user_identity_phone_number: str + is_suspended: Optional[bool] + pending_mutations: Optional[List[PendingMutations]] + phone_number: Optional[str] + salto_ks_metadata: Optional[SaltoKsMetadata] + salto_space_metadata: Optional[SaltoSpaceMetadata] + user_identity_email_address: Optional[str] + user_identity_full_name: Optional[str] + user_identity_id: Optional[str] + user_identity_phone_number: Optional[str] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_schedule=( cls.AccessSchedule.from_dict(d.get("access_schedule")) diff --git a/seam/resources/action_attempt.py b/seam/resources/action_attempt.py index 21e4a97a..a9bb54b3 100644 --- a/seam/resources/action_attempt.py +++ b/seam/resources/action_attempt.py @@ -29,8 +29,11 @@ class Error(ResourceMapping): message: str type: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( message=d.get("message", None), type=d.get("type", None), @@ -169,21 +172,24 @@ class VisionlineMetadata(ResourceMapping): :ivar pending_auto_update: Indicates whether the card associated with the `credential `_ is pending auto-update. """ - cancelled: bool - card_format: str - card_holder: str - card_id: str - common_acs_entrance_ids: List[str] - discarded: bool - expired: bool - guest_acs_entrance_ids: List[str] - number_of_issued_cards: float - overridden: bool - overwritten: bool - pending_auto_update: bool - + cancelled: Optional[bool] + card_format: Optional[str] + card_holder: Optional[str] + card_id: Optional[str] + common_acs_entrance_ids: Optional[List[str]] + discarded: Optional[bool] + expired: Optional[bool] + guest_acs_entrance_ids: Optional[List[str]] + number_of_issued_cards: Optional[float] + overridden: Optional[bool] + overwritten: Optional[bool] + pending_auto_update: Optional[bool] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( cancelled=d.get("cancelled", None), card_format=d.get("card_format", None), @@ -199,15 +205,18 @@ def from_dict(cls, d: Dict[str, Any]): pending_auto_update=d.get("pending_auto_update", None), ) - card_number: str - created_at: str - ends_at: str - is_issued: bool - starts_at: str - visionline_metadata: VisionlineMetadata + card_number: Optional[str] + created_at: Optional[str] + ends_at: Optional[str] + is_issued: Optional[bool] + starts_at: Optional[str] + visionline_metadata: Optional[VisionlineMetadata] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( card_number=d.get("card_number", None), created_at=d.get("created_at", None), @@ -299,15 +308,18 @@ class AssaAbloyVostioMetadata(ResourceMapping): :ivar override_guest_acs_entrance_ids: IDs of the guest entrances to override in the Vostio access system. """ - auto_join: bool - door_names: List[str] - endpoint_id: str - key_id: str - key_issuing_request_id: str - override_guest_acs_entrance_ids: List[str] + auto_join: Optional[bool] + door_names: Optional[List[str]] + endpoint_id: Optional[str] + key_id: Optional[str] + key_issuing_request_id: Optional[str] + override_guest_acs_entrance_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_join=d.get("auto_join", None), door_names=d.get("door_names", None), @@ -333,8 +345,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -362,17 +377,20 @@ class VisionlineMetadata(ResourceMapping): :ivar joiner_acs_credential_ids: IDs of the credentials to which you want to join. """ - auto_join: bool - card_function_type: str - card_id: str - common_acs_entrance_ids: List[str] - credential_id: str - guest_acs_entrance_ids: List[str] - is_valid: bool - joiner_acs_credential_ids: List[str] - + auto_join: Optional[bool] + card_function_type: Optional[str] + card_id: Optional[str] + common_acs_entrance_ids: Optional[List[str]] + credential_id: Optional[str] + guest_acs_entrance_ids: Optional[List[str]] + is_valid: Optional[bool] + joiner_acs_credential_ids: Optional[List[str]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_join=d.get("auto_join", None), card_function_type=d.get("card_function_type", None), @@ -401,8 +419,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -411,35 +432,38 @@ def from_dict(cls, d: Dict[str, Any]): access_method: str acs_credential_id: str - acs_credential_pool_id: str + acs_credential_pool_id: Optional[str] acs_system_id: str - acs_user_id: str - assa_abloy_vostio_metadata: AssaAbloyVostioMetadata - card_number: str - code: str + acs_user_id: Optional[str] + assa_abloy_vostio_metadata: Optional[AssaAbloyVostioMetadata] + card_number: Optional[str] + code: Optional[str] connected_account_id: str created_at: str display_name: str - ends_at: str + ends_at: Optional[str] errors: List[Errors] - external_type: str - external_type_display_name: str - is_issued: bool - is_latest_desired_state_synced_with_provider: bool + external_type: Optional[str] + external_type_display_name: Optional[str] + is_issued: Optional[bool] + is_latest_desired_state_synced_with_provider: Optional[bool] is_managed: bool - is_multi_phone_sync_credential: bool - is_one_time_use: bool - issued_at: str - latest_desired_state_synced_with_provider_at: str - parent_acs_credential_id: str - starts_at: str - user_identity_id: str - visionline_metadata: VisionlineMetadata + is_multi_phone_sync_credential: Optional[bool] + is_one_time_use: Optional[bool] + issued_at: Optional[str] + latest_desired_state_synced_with_provider_at: Optional[str] + parent_acs_credential_id: Optional[str] + starts_at: Optional[str] + user_identity_id: Optional[str] + visionline_metadata: Optional[VisionlineMetadata] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_method=d.get("access_method", None), acs_credential_id=d.get("acs_credential_id", None), @@ -507,13 +531,16 @@ class Warnings(ResourceMapping): """ warning_code: str - warning_message: str - created_at: str - message: str - original_access_method_id: str - + warning_message: Optional[str] + created_at: Optional[str] + message: Optional[str] + original_access_method_id: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( warning_code=d.get("warning_code", None), warning_message=d.get("warning_message", None), @@ -539,15 +566,18 @@ class AssaAbloyVostioMetadata(ResourceMapping): :ivar override_guest_acs_entrance_ids: IDs of the guest entrances to override in the Vostio access system. """ - auto_join: bool - door_names: List[str] - endpoint_id: str - key_id: str - key_issuing_request_id: str - override_guest_acs_entrance_ids: List[str] + auto_join: Optional[bool] + door_names: Optional[List[str]] + endpoint_id: Optional[str] + key_id: Optional[str] + key_issuing_request_id: Optional[str] + override_guest_acs_entrance_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_join=d.get("auto_join", None), door_names=d.get("door_names", None), @@ -574,8 +604,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -603,17 +636,20 @@ class VisionlineMetadata(ResourceMapping): :ivar joiner_acs_credential_ids: IDs of the credentials to which you want to join. """ - auto_join: bool - card_function_type: str - card_id: str - common_acs_entrance_ids: List[str] - credential_id: str - guest_acs_entrance_ids: List[str] - is_valid: bool - joiner_acs_credential_ids: List[str] - + auto_join: Optional[bool] + card_function_type: Optional[str] + card_id: Optional[str] + common_acs_entrance_ids: Optional[List[str]] + credential_id: Optional[str] + guest_acs_entrance_ids: Optional[List[str]] + is_valid: Optional[bool] + joiner_acs_credential_ids: Optional[List[str]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_join=d.get("auto_join", None), card_function_type=d.get("card_function_type", None), @@ -647,11 +683,14 @@ class From(ResourceMapping): :ivar starts_at: Previous start time for access.""" - ends_at: str - starts_at: str + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( ends_at=d.get("ends_at", None), starts_at=d.get("starts_at", None), @@ -665,24 +704,30 @@ class To(ResourceMapping): :ivar starts_at: New start time for access.""" - ends_at: str - starts_at: str + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( ends_at=d.get("ends_at", None), starts_at=d.get("starts_at", None), ) created_at: str - from_: From + from_: Optional[From] message: str mutation_code: str - to: To + to: Optional[To] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), from_=( @@ -699,50 +744,53 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - was_confirmed_by_device: bool - acs_credential_on_encoder: AcsCredentialOnEncoder - acs_credential_on_seam: AcsCredentialOnSeam - warnings: List[Warnings] - access_method: str - acs_credential_id: str - acs_credential_pool_id: str - acs_system_id: str - acs_user_id: str - assa_abloy_vostio_metadata: AssaAbloyVostioMetadata - card_number: str - code: str - connected_account_id: str - created_at: str - display_name: str - ends_at: str - errors: List[Errors] - external_type: str - external_type_display_name: str - is_issued: bool - is_latest_desired_state_synced_with_provider: bool - is_managed: bool - is_multi_phone_sync_credential: bool - is_one_time_use: bool - issued_at: str - latest_desired_state_synced_with_provider_at: str - parent_acs_credential_id: str - starts_at: str - user_identity_id: str - visionline_metadata: VisionlineMetadata - workspace_id: str - access_method_id: str - client_session_token: str - customization_profile_id: str - instant_key_url: str - is_assignment_required: bool - is_encoding_required: bool - is_ready_for_assignment: bool - is_ready_for_encoding: bool - mode: str - pending_mutations: List[PendingMutations] - + was_confirmed_by_device: Optional[bool] + acs_credential_on_encoder: Optional[AcsCredentialOnEncoder] + acs_credential_on_seam: Optional[AcsCredentialOnSeam] + warnings: Optional[List[Warnings]] + access_method: Optional[str] + acs_credential_id: Optional[str] + acs_credential_pool_id: Optional[str] + acs_system_id: Optional[str] + acs_user_id: Optional[str] + assa_abloy_vostio_metadata: Optional[AssaAbloyVostioMetadata] + card_number: Optional[str] + code: Optional[str] + connected_account_id: Optional[str] + created_at: Optional[str] + display_name: Optional[str] + ends_at: Optional[str] + errors: Optional[List[Errors]] + external_type: Optional[str] + external_type_display_name: Optional[str] + is_issued: Optional[bool] + is_latest_desired_state_synced_with_provider: Optional[bool] + is_managed: Optional[bool] + is_multi_phone_sync_credential: Optional[bool] + is_one_time_use: Optional[bool] + issued_at: Optional[str] + latest_desired_state_synced_with_provider_at: Optional[str] + parent_acs_credential_id: Optional[str] + starts_at: Optional[str] + user_identity_id: Optional[str] + visionline_metadata: Optional[VisionlineMetadata] + workspace_id: Optional[str] + access_method_id: Optional[str] + client_session_token: Optional[str] + customization_profile_id: Optional[str] + instant_key_url: Optional[str] + is_assignment_required: Optional[bool] + is_encoding_required: Optional[bool] + is_ready_for_assignment: Optional[bool] + is_ready_for_encoding: Optional[bool] + mode: Optional[str] + pending_mutations: Optional[List[PendingMutations]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( was_confirmed_by_device=d.get("was_confirmed_by_device", None), acs_credential_on_encoder=( @@ -818,12 +866,15 @@ def from_dict(cls, d: Dict[str, Any]): action_attempt_id: str action_type: str - error: Error - result: Result + error: Optional[Error] + result: Optional[Result] status: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( action_attempt_id=d.get("action_attempt_id", None), action_type=d.get("action_type", None), diff --git a/seam/resources/batch.py b/seam/resources/batch.py index 1313eb3e..6e4c2e2b 100644 --- a/seam/resources/batch.py +++ b/seam/resources/batch.py @@ -134,33 +134,36 @@ class Batch: :ivar workspaces: Represents a Seam `workspace `_. A workspace is a top-level entity that encompasses all other resources below it, such as devices, connected accounts, and Connect Webviews. Seam provides two types of workspaces. A `sandbox workspace `_ is a special type of workspace designed for testing code. Sandbox workspaces offer test device accounts and virtual devices that you can connect and control. This ability to work with virtual devices is quite handy because it removes the need to own physical devices from multiple brands. To connect real devices and systems to Seam, use a `production workspace `_. """ - access_codes: List[Dict[str, Any]] - access_grants: List[Dict[str, Any]] - access_methods: List[Dict[str, Any]] - acs_access_groups: List[Dict[str, Any]] - acs_credentials: List[Dict[str, Any]] - acs_encoders: List[Dict[str, Any]] - acs_entrances: List[Dict[str, Any]] - acs_systems: List[Dict[str, Any]] - acs_users: List[Dict[str, Any]] - action_attempts: List[Dict[str, Any]] - client_sessions: List[Dict[str, Any]] - connect_webviews: List[Dict[str, Any]] - connected_accounts: List[Dict[str, Any]] - devices: List[Dict[str, Any]] - events: List[Dict[str, Any]] - instant_keys: List[Dict[str, Any]] - noise_thresholds: List[Dict[str, Any]] - spaces: List[Dict[str, Any]] - thermostat_daily_programs: List[Dict[str, Any]] - thermostat_schedules: List[Dict[str, Any]] - unmanaged_access_codes: List[Dict[str, Any]] - unmanaged_devices: List[Dict[str, Any]] - user_identities: List[Dict[str, Any]] - workspaces: List[Dict[str, Any]] - + access_codes: Optional[List[Dict[str, Any]]] + access_grants: Optional[List[Dict[str, Any]]] + access_methods: Optional[List[Dict[str, Any]]] + acs_access_groups: Optional[List[Dict[str, Any]]] + acs_credentials: Optional[List[Dict[str, Any]]] + acs_encoders: Optional[List[Dict[str, Any]]] + acs_entrances: Optional[List[Dict[str, Any]]] + acs_systems: Optional[List[Dict[str, Any]]] + acs_users: Optional[List[Dict[str, Any]]] + action_attempts: Optional[List[Dict[str, Any]]] + client_sessions: Optional[List[Dict[str, Any]]] + connect_webviews: Optional[List[Dict[str, Any]]] + connected_accounts: Optional[List[Dict[str, Any]]] + devices: Optional[List[Dict[str, Any]]] + events: Optional[List[Dict[str, Any]]] + instant_keys: Optional[List[Dict[str, Any]]] + noise_thresholds: Optional[List[Dict[str, Any]]] + spaces: Optional[List[Dict[str, Any]]] + thermostat_daily_programs: Optional[List[Dict[str, Any]]] + thermostat_schedules: Optional[List[Dict[str, Any]]] + unmanaged_access_codes: Optional[List[Dict[str, Any]]] + unmanaged_devices: Optional[List[Dict[str, Any]]] + user_identities: Optional[List[Dict[str, Any]]] + workspaces: Optional[List[Dict[str, Any]]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_codes=d.get("access_codes", None), access_grants=d.get("access_grants", None), diff --git a/seam/resources/client_session.py b/seam/resources/client_session.py index fb289c16..38456094 100644 --- a/seam/resources/client_session.py +++ b/seam/resources/client_session.py @@ -44,17 +44,20 @@ class ClientSession: connect_webview_ids: List[str] connected_account_ids: List[str] created_at: str - customer_key: str + customer_key: Optional[str] device_count: float expires_at: str token: str - user_identifier_key: str - user_identity_id: str + user_identifier_key: Optional[str] + user_identity_id: Optional[str] user_identity_ids: List[str] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( client_session_id=d.get("client_session_id", None), connect_webview_ids=d.get("connect_webview_ids", None), diff --git a/seam/resources/connect_webview.py b/seam/resources/connect_webview.py index fc948390..77d06b1d 100644 --- a/seam/resources/connect_webview.py +++ b/seam/resources/connect_webview.py @@ -59,25 +59,28 @@ class ConnectWebview: accepted_capabilities: List[str] accepted_providers: List[str] any_provider_allowed: bool - authorized_at: str + authorized_at: Optional[str] automatically_manage_new_devices: bool connect_webview_id: str - connected_account_id: str + connected_account_id: Optional[str] created_at: str custom_metadata: Dict[str, Any] - custom_redirect_failure_url: str - custom_redirect_url: str - customer_key: str + custom_redirect_failure_url: Optional[str] + custom_redirect_url: Optional[str] + customer_key: Optional[str] device_selection_mode: str login_successful: bool - selected_provider: str + selected_provider: Optional[str] status: str url: str wait_for_device_creation: bool workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accepted_capabilities=d.get("accepted_capabilities", None), accepted_providers=d.get("accepted_providers", None), diff --git a/seam/resources/connected_account.py b/seam/resources/connected_account.py index 9cceb75d..a7277447 100644 --- a/seam/resources/connected_account.py +++ b/seam/resources/connected_account.py @@ -81,13 +81,16 @@ class Sites(ResourceMapping): :ivar subscribed_site_user_count: Count of subscribed site users for a Salto site associated with the connected account that has an error. """ - site_id: str - site_name: str - site_user_subscription_limit: int - subscribed_site_user_count: int - + site_id: Optional[str] + site_name: Optional[str] + site_user_subscription_limit: Optional[int] + subscribed_site_user_count: Optional[int] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( site_id=d.get("site_id", None), site_name=d.get("site_name", None), @@ -99,23 +102,29 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - sites: List[Sites] + sites: Optional[List[Sites]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( sites=[cls.Sites.from_dict(i) for i in d.get("sites") or []], ) created_at: str error_code: str - is_bridge_error: bool - is_connected_account_error: bool + is_bridge_error: Optional[bool] + is_connected_account_error: Optional[bool] message: str - salto_ks_metadata: SaltoKsMetadata + salto_ks_metadata: Optional[SaltoKsMetadata] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -144,14 +153,17 @@ class UserIdentifier(ResourceMapping): :ivar username: Username of the user identifier associated with the connected account. """ - api_url: str - email: str - exclusive: bool - phone: str - username: str + api_url: Optional[str] + email: Optional[str] + exclusive: Optional[bool] + phone: Optional[str] + username: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( api_url=d.get("api_url", None), email=d.get("email", None), @@ -193,13 +205,16 @@ class Sites(ResourceMapping): :ivar subscribed_site_user_count: Count of subscribed site users for a Salto site associated with the connected account that has a warning. """ - site_id: str - site_name: str - site_user_subscription_limit: int - subscribed_site_user_count: int + site_id: Optional[str] + site_name: Optional[str] + site_user_subscription_limit: Optional[int] + subscribed_site_user_count: Optional[int] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( site_id=d.get("site_id", None), site_name=d.get("site_name", None), @@ -211,10 +226,13 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - sites: List[Sites] + sites: Optional[List[Sites]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( sites=[cls.Sites.from_dict(i) for i in d.get("sites") or []], ) @@ -222,10 +240,13 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str message: str warning_code: str - salto_ks_metadata: SaltoKsMetadata + salto_ks_metadata: Optional[SaltoKsMetadata] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -238,26 +259,29 @@ def from_dict(cls, d: Dict[str, Any]): ) accepted_capabilities: List[str] - account_type: str + account_type: Optional[str] account_type_display_name: str automatically_manage_new_devices: bool connected_account_id: str - created_at: str + created_at: Optional[str] custom_metadata: Dict[str, Any] - customer_key: str - default_checkin_time: str - default_checkout_time: str + customer_key: Optional[str] + default_checkin_time: Optional[str] + default_checkout_time: Optional[str] display_name: str errors: List[Errors] - ical_feed_origin: str - ical_url: str - image_url: str - time_zone: str - user_identifier: UserIdentifier + ical_feed_origin: Optional[str] + ical_url: Optional[str] + image_url: Optional[str] + time_zone: Optional[str] + user_identifier: Optional[UserIdentifier] warnings: List[Warnings] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accepted_capabilities=d.get("accepted_capabilities", None), account_type=d.get("account_type", None), diff --git a/seam/resources/customer_portal.py b/seam/resources/customer_portal.py index 120cbc7a..fa9a7f82 100644 --- a/seam/resources/customer_portal.py +++ b/seam/resources/customer_portal.py @@ -28,8 +28,11 @@ class CustomerPortal: url: str workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), customer_key=d.get("customer_key", None), diff --git a/seam/resources/device.py b/seam/resources/device.py index 8d86fe69..65c2a775 100644 --- a/seam/resources/device.py +++ b/seam/resources/device.py @@ -95,11 +95,14 @@ class DeviceManufacturer(ResourceMapping): """ display_name: str - image_url: str + image_url: Optional[str] manufacturer: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( display_name=d.get("display_name", None), image_url=d.get("image_url", None), @@ -121,11 +124,14 @@ class DeviceProvider(ResourceMapping): device_provider_name: str display_name: str - image_url: str + image_url: Optional[str] provider_category: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_provider_name=d.get("device_provider_name", None), display_name=d.get("display_name", None), @@ -152,13 +158,16 @@ class Errors(ResourceMapping): created_at: str error_code: str - is_connected_account_error: bool - is_device_error: bool + is_connected_account_error: Optional[bool] + is_device_error: Optional[bool] message: str - is_bridge_error: bool + is_bridge_error: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -179,12 +188,15 @@ class Location(ResourceMapping): :ivar timezone: Deprecated: Use ``time_zone`` instead. Time zone of the device location. """ - location_name: str - time_zone: str - timezone: str + location_name: Optional[str] + time_zone: Optional[str] + timezone: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( location_name=d.get("location_name", None), time_zone=d.get("time_zone", None), @@ -421,17 +433,23 @@ class Battery(ResourceMapping): level: float + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( level=d.get("level", None), ) - battery: Battery + battery: Optional[Battery] is_connected: bool + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( battery=( cls.Battery.from_dict(d.get("battery")) @@ -450,8 +468,11 @@ class Appearance(ResourceMapping): name: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( name=d.get("name", None), ) @@ -468,8 +489,11 @@ class Battery(ResourceMapping): level: float status: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( level=d.get("level", None), status=d.get("status", None), @@ -494,16 +518,19 @@ class Model(ResourceMapping): :ivar online_access_codes_supported: Deprecated: use device.can_program_online_access_codes. """ - accessory_keypad_supported: bool - can_connect_accessory_keypad: bool + accessory_keypad_supported: Optional[bool] + can_connect_accessory_keypad: Optional[bool] display_name: str - has_built_in_keypad: bool + has_built_in_keypad: Optional[bool] manufacturer_display_name: str - offline_access_codes_supported: bool - online_access_codes_supported: bool + offline_access_codes_supported: Optional[bool] + online_access_codes_supported: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accessory_keypad_supported=d.get( "accessory_keypad_supported", None @@ -539,21 +566,27 @@ class Endpoints(ResourceMapping): :ivar is_active: Indicated whether the endpoint is active.""" - endpoint_id: str - is_active: bool + endpoint_id: Optional[str] + is_active: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( endpoint_id=d.get("endpoint_id", None), is_active=d.get("is_active", None), ) - endpoints: List[Endpoints] - has_active_endpoint: bool + endpoints: Optional[List[Endpoints]] + has_active_endpoint: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( endpoints=[ cls.Endpoints.from_dict(i) for i in d.get("endpoints") or [] @@ -568,10 +601,13 @@ class SaltoSpaceCredentialServiceMetadata(ResourceMapping): :ivar has_active_phone: Indicates whether the credential service has an active associated phone. """ - has_active_phone: bool + has_active_phone: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( has_active_phone=d.get("has_active_phone", None), ) @@ -588,13 +624,16 @@ class AkilesMetadata(ResourceMapping): :ivar product_name: Product name for an Akiles device.""" - _member_group_id: str - gadget_id: str - gadget_name: str - product_name: str + _member_group_id: Optional[str] + gadget_id: Optional[str] + gadget_name: Optional[str] + product_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( _member_group_id=d.get("_member_group_id", None), gadget_id=d.get("gadget_id", None), @@ -622,17 +661,20 @@ class AqaraMetadata(ResourceMapping): :ivar time_zone: Time zone reported for an Aqara device (e.g. GMT-07:00).""" - device_name: str - did: str - firmware_version: str - model: str - model_type: float - parent_did: str - position_id: str - time_zone: str - + device_name: Optional[str] + did: Optional[str] + firmware_version: Optional[str] + model: Optional[str] + model_type: Optional[float] + parent_did: Optional[str] + position_id: Optional[str] + time_zone: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_name=d.get("device_name", None), did=d.get("did", None), @@ -650,10 +692,13 @@ class AssaAbloyVostioMetadata(ResourceMapping): :ivar encoder_name: Encoder name for an ASSA ABLOY Vostio system.""" - encoder_name: str + encoder_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( encoder_name=d.get("encoder_name", None), ) @@ -676,16 +721,19 @@ class AugustMetadata(ResourceMapping): :ivar model: Model for an August device.""" - has_keypad: bool - house_id: str - house_name: str - keypad_battery_level: str - lock_id: str - lock_name: str - model: str - + has_keypad: Optional[bool] + house_id: Optional[str] + house_name: Optional[str] + keypad_battery_level: Optional[str] + lock_id: Optional[str] + lock_name: Optional[str] + model: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( has_keypad=d.get("has_keypad", None), house_id=d.get("house_id", None), @@ -714,16 +762,19 @@ class AvigilonAltaMetadata(ResourceMapping): :ivar zone_name: Zone name for an Avigilon Alta system.""" - entry_name: str - entry_relays_total_count: float - org_name: str - site_id: float - site_name: str - zone_id: float - zone_name: str - + entry_name: Optional[str] + entry_relays_total_count: Optional[float] + org_name: Optional[str] + site_id: Optional[float] + site_name: Optional[str] + zone_id: Optional[float] + zone_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( entry_name=d.get("entry_name", None), entry_relays_total_count=d.get("entry_relays_total_count", None), @@ -742,11 +793,14 @@ class BrivoMetadata(ResourceMapping): :ivar device_name: Device name for a Brivo device.""" - activation_enabled: bool - device_name: str + activation_enabled: Optional[bool] + device_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( activation_enabled=d.get("activation_enabled", None), device_name=d.get("device_name", None), @@ -762,12 +816,15 @@ class ControlbywebMetadata(ResourceMapping): :ivar relay_name: Relay name for a ControlByWeb device.""" - device_id: str - device_name: str - relay_name: str + device_id: Optional[str] + device_name: Optional[str] + relay_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -798,8 +855,11 @@ class DormakabaOracodeMetadata(ResourceMapping): class DeviceId(ResourceMapping): """Device ID for a dormakaba Oracode device.""" + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): # This shape documents no properties, so there is nothing to read. # pylint: disable=unused-argument return cls() @@ -828,19 +888,22 @@ class PredefinedTimeSlots(ResourceMapping): :ivar prefix: Prefix for a time slot for a dormakaba Oracode device.""" - check_in_time: str - check_out_time: str - dormakaba_oracode_user_level_id: str - dormakaba_oracode_user_level_prefix: float - is_24_hour: bool - is_biweekly_mode: bool - is_master: bool - is_one_shot: bool - name: str - prefix: float - + check_in_time: Optional[str] + check_out_time: Optional[str] + dormakaba_oracode_user_level_id: Optional[str] + dormakaba_oracode_user_level_prefix: Optional[float] + is_24_hour: Optional[bool] + is_biweekly_mode: Optional[bool] + is_master: Optional[bool] + is_one_shot: Optional[bool] + name: Optional[str] + prefix: Optional[float] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( check_in_time=d.get("check_in_time", None), check_out_time=d.get("check_out_time", None), @@ -858,17 +921,20 @@ def from_dict(cls, d: Dict[str, Any]): prefix=d.get("prefix", None), ) - device_id: DeviceId - door_id: float - door_is_wireless: bool - door_name: str - iana_timezone: str - predefined_time_slots: List[PredefinedTimeSlots] - site_id: float - site_name: str - + device_id: Optional[DeviceId] + door_id: Optional[float] + door_is_wireless: Optional[bool] + door_name: Optional[str] + iana_timezone: Optional[str] + predefined_time_slots: Optional[List[PredefinedTimeSlots]] + site_id: Optional[float] + site_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=( cls.DeviceId.from_dict(d.get("device_id")) @@ -895,11 +961,14 @@ class EcobeeMetadata(ResourceMapping): :ivar ecobee_device_id: Device ID for an ecobee device.""" - device_name: str - ecobee_device_id: str + device_name: Optional[str] + ecobee_device_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_name=d.get("device_name", None), ecobee_device_id=d.get("ecobee_device_id", None), @@ -916,12 +985,15 @@ class FourSuitesMetadata(ResourceMapping): :ivar reclose_delay_in_seconds: Reclose delay, in seconds, for a 4SUITES device. """ - device_id: float - device_name: str - reclose_delay_in_seconds: float + device_id: Optional[float] + device_name: Optional[str] + reclose_delay_in_seconds: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -936,11 +1008,14 @@ class GenieMetadata(ResourceMapping): :ivar door_name: Door name for a Genie device.""" - device_name: str - door_name: str + device_name: Optional[str] + door_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_name=d.get("device_name", None), door_name=d.get("door_name", None), @@ -955,11 +1030,14 @@ class HoneywellResideoMetadata(ResourceMapping): :ivar honeywell_resideo_device_id: Device ID for a Honeywell Resideo device. """ - device_name: str - honeywell_resideo_device_id: str + device_name: Optional[str] + honeywell_resideo_device_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_name=d.get("device_name", None), honeywell_resideo_device_id=d.get( @@ -977,12 +1055,15 @@ class IglooMetadata(ResourceMapping): :ivar model: Model for an igloo device.""" - bridge_id: str - device_id: str - model: str + bridge_id: Optional[str] + device_id: Optional[str] + model: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( bridge_id=d.get("bridge_id", None), device_id=d.get("device_id", None), @@ -1005,15 +1086,18 @@ class IgloohomeMetadata(ResourceMapping): :ivar keypad_id: Keypad ID for an igloohome device.""" - bridge_id: str - bridge_name: str - device_id: str - device_name: str - is_accessory_keypad_linked_to_bridge: bool - keypad_id: str + bridge_id: Optional[str] + bridge_name: Optional[str] + device_id: Optional[str] + device_name: Optional[str] + is_accessory_keypad_linked_to_bridge: Optional[bool] + keypad_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( bridge_id=d.get("bridge_id", None), bridge_name=d.get("bridge_name", None), @@ -1071,30 +1155,33 @@ class KeynestMetadata(ResourceMapping): :ivar subscription_plan: Subscription plan for a KeyNest device.""" - address: str - current_or_last_store_id: float - current_status: str - current_user_company: str - current_user_email: str - current_user_name: str - current_user_phone_number: str - default_office_id: float - device_name: str - fob_id: float - handover_method: str - has_photo: bool - is_quadient_locker: bool - key_id: str - key_notes: str - keynest_app_user: str - last_movement: str - property_id: str - property_postcode: str - status_type: str - subscription_plan: str - + address: Optional[str] + current_or_last_store_id: Optional[float] + current_status: Optional[str] + current_user_company: Optional[str] + current_user_email: Optional[str] + current_user_name: Optional[str] + current_user_phone_number: Optional[str] + default_office_id: Optional[float] + device_name: Optional[str] + fob_id: Optional[float] + handover_method: Optional[str] + has_photo: Optional[bool] + is_quadient_locker: Optional[bool] + key_id: Optional[str] + key_notes: Optional[str] + keynest_app_user: Optional[str] + last_movement: Optional[str] + property_id: Optional[str] + property_postcode: Optional[str] + status_type: Optional[str] + subscription_plan: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( address=d.get("address", None), current_or_last_store_id=d.get("current_or_last_store_id", None), @@ -1131,13 +1218,16 @@ class KisiMetadata(ResourceMapping): :ivar place_name: Place name for a Kisi device.""" - description: str - lock_id: float - lock_name: str - place_name: str + description: Optional[str] + lock_id: Optional[float] + lock_name: Optional[str] + place_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( description=d.get("description", None), lock_id=d.get("lock_id", None), @@ -1164,16 +1254,19 @@ class KorelockMetadata(ResourceMapping): :ivar wifi_signal_strength: WiFi signal strength (0-1) for a Korelock device. """ - device_id: str - device_name: str - firmware_version: str - location_id: str - model_code: str - serial_number: str - wifi_signal_strength: float - + device_id: Optional[str] + device_name: Optional[str] + firmware_version: Optional[str] + location_id: Optional[str] + model_code: Optional[str] + serial_number: Optional[str] + wifi_signal_strength: Optional[float] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1194,12 +1287,15 @@ class KwiksetMetadata(ResourceMapping): :ivar model_number: Model number for a Kwikset device.""" - device_id: str - device_name: str - model_number: str + device_id: Optional[str] + device_name: Optional[str] + model_number: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1216,12 +1312,15 @@ class LocklyMetadata(ResourceMapping): :ivar model: Model for a Lockly device.""" - device_id: str - device_name: str - model: str + device_id: Optional[str] + device_name: Optional[str] + model: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1261,11 +1360,14 @@ class AccelerometerZ(ResourceMapping): :ivar value: Value of latest accelerometer Z-axis reading for a Minut device. """ - time: str - value: float + time: Optional[str] + value: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( time=d.get("time", None), value=d.get("value", None), @@ -1279,11 +1381,14 @@ class Humidity(ResourceMapping): :ivar value: Value of latest humidity reading for a Minut device.""" - time: str - value: float + time: Optional[str] + value: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( time=d.get("time", None), value=d.get("value", None), @@ -1297,11 +1402,14 @@ class Pressure(ResourceMapping): :ivar value: Value of latest pressure reading for a Minut device.""" - time: str - value: float + time: Optional[str] + value: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( time=d.get("time", None), value=d.get("value", None), @@ -1315,11 +1423,14 @@ class Sound(ResourceMapping): :ivar value: Value of latest sound reading for a Minut device.""" - time: str - value: float + time: Optional[str] + value: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( time=d.get("time", None), value=d.get("value", None), @@ -1334,24 +1445,30 @@ class Temperature(ResourceMapping): :ivar value: Value of latest temperature reading for a Minut device. """ - time: str - value: float + time: Optional[str] + value: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( time=d.get("time", None), value=d.get("value", None), ) - accelerometer_z: AccelerometerZ - humidity: Humidity - pressure: Pressure - sound: Sound - temperature: Temperature + accelerometer_z: Optional[AccelerometerZ] + humidity: Optional[Humidity] + pressure: Optional[Pressure] + sound: Optional[Sound] + temperature: Optional[Temperature] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accelerometer_z=( cls.AccelerometerZ.from_dict(d.get("accelerometer_z")) @@ -1380,12 +1497,15 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - device_id: str - device_name: str - latest_sensor_values: LatestSensorValues + device_id: Optional[str] + device_name: Optional[str] + latest_sensor_values: Optional[LatestSensorValues] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1408,13 +1528,16 @@ class NestMetadata(ResourceMapping): :ivar nest_device_id: Device ID for a Google Nest device.""" - device_custom_name: str - device_name: str - display_name: str - nest_device_id: str + device_custom_name: Optional[str] + device_name: Optional[str] + display_name: Optional[str] + nest_device_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_custom_name=d.get("device_custom_name", None), device_name=d.get("device_name", None), @@ -1437,14 +1560,17 @@ class NoiseawareMetadata(ResourceMapping): :ivar noise_level_nrs: Noise level, expressed as a Noise Risk Score (NRS), for a NoiseAware device. """ - device_id: str - device_model: str - device_name: str - noise_level_decibel: float - noise_level_nrs: float + device_id: Optional[str] + device_model: Optional[str] + device_name: Optional[str] + noise_level_decibel: Optional[float] + noise_level_nrs: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_model=d.get("device_model", None), @@ -1468,14 +1594,17 @@ class NukiMetadata(ResourceMapping): :ivar keypad_paired: Indicates whether the keypad is paired for a Nuki device. """ - device_id: str - device_name: str - keypad_2_paired: bool - keypad_battery_critical: bool - keypad_paired: bool + device_id: Optional[str] + device_name: Optional[str] + keypad_2_paired: Optional[bool] + keypad_battery_critical: Optional[bool] + keypad_paired: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1503,16 +1632,19 @@ class OmnitecMetadata(ResourceMapping): :ivar timezone_raw_offset_ms: Static UTC offset of the Omnitec lock in milliseconds. Does not account for DST. """ - has_gateway: bool - lock_alias: str - lock_id: float - lock_mac: str - lock_name: str - time_zone: str - timezone_raw_offset_ms: float - + has_gateway: Optional[bool] + lock_alias: Optional[str] + lock_id: Optional[float] + lock_mac: Optional[str] + lock_name: Optional[str] + time_zone: Optional[str] + timezone_raw_offset_ms: Optional[float] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( has_gateway=d.get("has_gateway", None), lock_alias=d.get("lock_alias", None), @@ -1531,11 +1663,14 @@ class RingMetadata(ResourceMapping): :ivar device_name: Device name for a Ring device.""" - device_id: str - device_name: str + device_id: Optional[str] + device_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1564,18 +1699,21 @@ class SaltoKsMetadata(ResourceMapping): :ivar site_name: Site name for the Salto KS site to which the device belongs. """ - battery_level: str - customer_reference: str - has_custom_pin_subscription: bool - lock_id: str - lock_type: str - locked_state: str - model: str - site_id: str - site_name: str - + battery_level: Optional[str] + customer_reference: Optional[str] + has_custom_pin_subscription: Optional[bool] + lock_id: Optional[str] + lock_type: Optional[str] + locked_state: Optional[str] + model: Optional[str] + site_id: Optional[str] + site_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( battery_level=d.get("battery_level", None), customer_reference=d.get("customer_reference", None), @@ -1611,17 +1749,20 @@ class SaltoMetadata(ResourceMapping): :ivar site_name: Site name for the Salto KS site to which the device belongs. """ - battery_level: str - customer_reference: str - lock_id: str - lock_type: str - locked_state: str - model: str - site_id: str - site_name: str - + battery_level: Optional[str] + customer_reference: Optional[str] + lock_id: Optional[str] + lock_type: Optional[str] + locked_state: Optional[str] + model: Optional[str] + site_id: Optional[str] + site_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( battery_level=d.get("battery_level", None), customer_reference=d.get("customer_reference", None), @@ -1643,12 +1784,15 @@ class SchlageMetadata(ResourceMapping): :ivar model: Model for a Schlage device.""" - device_id: str - device_name: str - model: str + device_id: Optional[str] + device_name: Optional[str] + model: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1665,12 +1809,15 @@ class SeamBridgeMetadata(ResourceMapping): :ivar unlock_method: Unlock method for Seam Bridge.""" - device_num: float - name: str - unlock_method: str + device_num: Optional[float] + name: Optional[str] + unlock_method: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_num=d.get("device_num", None), name=d.get("name", None), @@ -1689,13 +1836,16 @@ class SensiMetadata(ResourceMapping): :ivar product_type: Product type for a Sensi device.""" - device_id: str - device_name: str - dual_setpoints_not_supported: bool - product_type: str + device_id: Optional[str] + device_name: Optional[str] + dual_setpoints_not_supported: Optional[bool] + product_type: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1717,13 +1867,16 @@ class SmartthingsMetadata(ResourceMapping): :ivar model: Model for a SmartThings device.""" - device_id: str - device_name: str - location_id: str - model: str + device_id: Optional[str] + device_name: Optional[str] + location_id: Optional[str] + model: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1739,11 +1892,14 @@ class TadoMetadata(ResourceMapping): :ivar serial_no: Serial number for a tado° device.""" - device_type: str - serial_no: str + device_type: Optional[str] + serial_no: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_type=d.get("device_type", None), serial_no=d.get("serial_no", None), @@ -1767,16 +1923,19 @@ class TedeeMetadata(ResourceMapping): :ivar serial_number: Serial number for a Tedee device.""" - bridge_id: float - bridge_name: str - device_id: float - device_model: str - device_name: str - keypad_id: float - serial_number: str - + bridge_id: Optional[float] + bridge_name: Optional[str] + device_id: Optional[float] + device_model: Optional[str] + device_name: Optional[str] + keypad_id: Optional[float] + serial_number: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( bridge_id=d.get("bridge_id", None), bridge_name=d.get("bridge_name", None), @@ -1823,16 +1982,19 @@ class Features(ResourceMapping): :ivar wifi: Indicates whether a TTLock device supports Wi-Fi.""" - auto_lock_time_config: bool - incomplete_keyboard_passcode: bool - lock_command: bool - passcode: bool - passcode_management: bool - unlock_via_gateway: bool - wifi: bool - + auto_lock_time_config: Optional[bool] + incomplete_keyboard_passcode: Optional[bool] + lock_command: Optional[bool] + passcode: Optional[bool] + passcode_management: Optional[bool] + unlock_via_gateway: Optional[bool] + wifi: Optional[bool] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( auto_lock_time_config=d.get("auto_lock_time_config", None), incomplete_keyboard_passcode=d.get( @@ -1854,26 +2016,32 @@ class WirelessKeypads(ResourceMapping): :ivar wireless_keypad_name: Name for a wireless keypad for a TTLock device. """ - wireless_keypad_id: float - wireless_keypad_name: str + wireless_keypad_id: Optional[float] + wireless_keypad_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( wireless_keypad_id=d.get("wireless_keypad_id", None), wireless_keypad_name=d.get("wireless_keypad_name", None), ) - feature_value: str - features: Features - has_gateway: bool - lock_alias: str - lock_id: float - timezone_raw_offset_ms: float - wireless_keypads: List[WirelessKeypads] - + feature_value: Optional[str] + features: Optional[Features] + has_gateway: Optional[bool] + lock_alias: Optional[str] + lock_id: Optional[float] + timezone_raw_offset_ms: Optional[float] + wireless_keypads: Optional[List[WirelessKeypads]] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( feature_value=d.get("feature_value", None), features=( @@ -1899,11 +2067,14 @@ class TwoNMetadata(ResourceMapping): :ivar device_name: Device name for a 2N device.""" - device_id: float - device_name: str + device_id: Optional[float] + device_name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1921,13 +2092,16 @@ class UltraloqMetadata(ResourceMapping): :ivar time_zone: IANA timezone for the Ultraloq device.""" - device_id: str - device_name: str - device_type: str - time_zone: str + device_id: Optional[str] + device_name: Optional[str] + device_type: Optional[str] + time_zone: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_name=d.get("device_name", None), @@ -1941,10 +2115,13 @@ class VisionlineMetadata(ResourceMapping): :ivar encoder_id: Encoder ID for an ASSA ABLOY Visionline system.""" - encoder_id: str + encoder_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( encoder_id=d.get("encoder_id", None), ) @@ -1969,17 +2146,20 @@ class WyzeMetadata(ResourceMapping): :ivar product_type: Product type for a Wyze device.""" - device_id: str - device_info_model: str - device_name: str - keypad_uuid: str - locker_status_hardlock: float - product_model: str - product_name: str - product_type: str - + device_id: Optional[str] + device_info_model: Optional[str] + device_name: Optional[str] + keypad_uuid: Optional[str] + locker_status_hardlock: Optional[float] + product_model: Optional[str] + product_name: Optional[str] + product_type: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), device_info_model=d.get("device_info_model", None), @@ -2002,11 +2182,14 @@ class CodeConstraints(ResourceMapping): :ivar min_length: Minimum name length constraint for access codes.""" constraint_type: str - max_length: float - min_length: float + max_length: Optional[float] + min_length: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( constraint_type=d.get("constraint_type", None), max_length=d.get("max_length", None), @@ -2021,8 +2204,11 @@ class KeypadBattery(ResourceMapping): level: float + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( level=d.get("level", None), ) @@ -2063,8 +2249,11 @@ class TimePairs(ResourceMapping): end_time: str start_time: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( display_name=d.get("display_name", None), end_time=d.get("end_time", None), @@ -2072,16 +2261,19 @@ def from_dict(cls, d: Dict[str, Any]): ) display_name: str - end_date_recurrence_rule: str - matching_start_end_time: bool - max_duration: str - min_duration: str - start_date_recurrence_rule: str - time_pairs: List[TimePairs] - time_zone: str - + end_date_recurrence_rule: Optional[str] + matching_start_end_time: Optional[bool] + max_duration: Optional[str] + min_duration: Optional[str] + start_date_recurrence_rule: Optional[str] + time_pairs: Optional[List[TimePairs]] + time_zone: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( display_name=d.get("display_name", None), end_date_recurrence_rule=d.get("end_date_recurrence_rule", None), @@ -2133,8 +2325,11 @@ class TimePairs(ResourceMapping): end_time: str start_time: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( display_name=d.get("display_name", None), end_time=d.get("end_time", None), @@ -2142,16 +2337,19 @@ def from_dict(cls, d: Dict[str, Any]): ) display_name: str - end_date_recurrence_rule: str - matching_start_end_time: bool - max_duration: str - min_duration: str - start_date_recurrence_rule: str - time_pairs: List[TimePairs] - time_zone: str - + end_date_recurrence_rule: Optional[str] + matching_start_end_time: Optional[bool] + max_duration: Optional[str] + min_duration: Optional[str] + start_date_recurrence_rule: Optional[str] + time_pairs: Optional[List[TimePairs]] + time_zone: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( display_name=d.get("display_name", None), end_date_recurrence_rule=d.get("end_date_recurrence_rule", None), @@ -2209,8 +2407,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -2222,15 +2423,18 @@ def from_dict(cls, d: Dict[str, Any]): device_id: str ends_at: str errors: List[Errors] - is_override_allowed: bool - max_override_period_minutes: int - name: str + is_override_allowed: Optional[bool] + max_override_period_minutes: Optional[int] + name: Optional[str] starts_at: str thermostat_schedule_id: str workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_preset_key=d.get("climate_preset_key", None), created_at=d.get("created_at", None), @@ -2293,12 +2497,15 @@ class EcobeeMetadata(ResourceMapping): :ivar owner: Indicates whether the climate preset is owned by the user or the system. """ - climate_ref: str - is_optimized: bool - owner: str + climate_ref: Optional[str] + is_optimized: Optional[bool] + owner: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_ref=d.get("climate_ref", None), is_optimized=d.get("is_optimized", None), @@ -2309,20 +2516,23 @@ def from_dict(cls, d: Dict[str, Any]): can_edit: bool can_use_with_thermostat_daily_programs: bool climate_preset_key: str - climate_preset_mode: str - cooling_set_point_celsius: float - cooling_set_point_fahrenheit: float + climate_preset_mode: Optional[str] + cooling_set_point_celsius: Optional[float] + cooling_set_point_fahrenheit: Optional[float] display_name: str - ecobee_metadata: EcobeeMetadata - fan_mode_setting: str - heating_set_point_celsius: float - heating_set_point_fahrenheit: float - hvac_mode_setting: str + ecobee_metadata: Optional[EcobeeMetadata] + fan_mode_setting: Optional[str] + heating_set_point_celsius: Optional[float] + heating_set_point_fahrenheit: Optional[float] + hvac_mode_setting: Optional[str] manual_override_allowed: bool - name: str + name: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( can_delete=d.get("can_delete", None), can_edit=d.get("can_edit", None), @@ -2397,36 +2607,42 @@ class EcobeeMetadata(ResourceMapping): :ivar owner: Indicates whether the climate preset is owned by the user or the system. """ - climate_ref: str - is_optimized: bool - owner: str + climate_ref: Optional[str] + is_optimized: Optional[bool] + owner: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_ref=d.get("climate_ref", None), is_optimized=d.get("is_optimized", None), owner=d.get("owner", None), ) - can_delete: bool - can_edit: bool - can_use_with_thermostat_daily_programs: bool - climate_preset_key: str - climate_preset_mode: str - cooling_set_point_celsius: float - cooling_set_point_fahrenheit: float - display_name: str - ecobee_metadata: EcobeeMetadata - fan_mode_setting: str - heating_set_point_celsius: float - heating_set_point_fahrenheit: float - hvac_mode_setting: str - manual_override_allowed: bool - name: str - + can_delete: Optional[bool] + can_edit: Optional[bool] + can_use_with_thermostat_daily_programs: Optional[bool] + climate_preset_key: Optional[str] + climate_preset_mode: Optional[str] + cooling_set_point_celsius: Optional[float] + cooling_set_point_fahrenheit: Optional[float] + display_name: Optional[str] + ecobee_metadata: Optional[EcobeeMetadata] + fan_mode_setting: Optional[str] + heating_set_point_celsius: Optional[float] + heating_set_point_fahrenheit: Optional[float] + hvac_mode_setting: Optional[str] + manual_override_allowed: Optional[bool] + name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( can_delete=d.get("can_delete", None), can_edit=d.get("can_edit", None), @@ -2501,36 +2717,42 @@ class EcobeeMetadata(ResourceMapping): :ivar owner: Indicates whether the climate preset is owned by the user or the system. """ - climate_ref: str - is_optimized: bool - owner: str + climate_ref: Optional[str] + is_optimized: Optional[bool] + owner: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_ref=d.get("climate_ref", None), is_optimized=d.get("is_optimized", None), owner=d.get("owner", None), ) - can_delete: bool - can_edit: bool - can_use_with_thermostat_daily_programs: bool - climate_preset_key: str - climate_preset_mode: str - cooling_set_point_celsius: float - cooling_set_point_fahrenheit: float - display_name: str - ecobee_metadata: EcobeeMetadata - fan_mode_setting: str - heating_set_point_celsius: float - heating_set_point_fahrenheit: float - hvac_mode_setting: str - manual_override_allowed: bool - name: str - + can_delete: Optional[bool] + can_edit: Optional[bool] + can_use_with_thermostat_daily_programs: Optional[bool] + climate_preset_key: Optional[str] + climate_preset_mode: Optional[str] + cooling_set_point_celsius: Optional[float] + cooling_set_point_fahrenheit: Optional[float] + display_name: Optional[str] + ecobee_metadata: Optional[EcobeeMetadata] + fan_mode_setting: Optional[str] + heating_set_point_celsius: Optional[float] + heating_set_point_fahrenheit: Optional[float] + hvac_mode_setting: Optional[str] + manual_override_allowed: Optional[bool] + name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( can_delete=d.get("can_delete", None), can_edit=d.get("can_edit", None), @@ -2572,13 +2794,16 @@ class TemperatureThreshold(ResourceMapping): :ivar upper_limit_fahrenheit: Upper limit in °F within the current `temperature threshold `_ set for the thermostat. """ - lower_limit_celsius: float - lower_limit_fahrenheit: float - upper_limit_celsius: float - upper_limit_fahrenheit: float + lower_limit_celsius: Optional[float] + lower_limit_fahrenheit: Optional[float] + upper_limit_celsius: Optional[float] + upper_limit_fahrenheit: Optional[float] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( lower_limit_celsius=d.get("lower_limit_celsius", None), lower_limit_fahrenheit=d.get("lower_limit_fahrenheit", None), @@ -2615,8 +2840,11 @@ class Periods(ResourceMapping): climate_preset_key: str starts_at_time: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_preset_key=d.get("climate_preset_key", None), starts_at_time=d.get("starts_at_time", None), @@ -2624,13 +2852,16 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str device_id: str - name: str + name: Optional[str] periods: List[Periods] thermostat_daily_program_id: str workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), device_id=d.get("device_id", None), @@ -2664,16 +2895,19 @@ class ThermostatWeeklyProgram(ResourceMapping): """ created_at: str - friday_program_id: str - monday_program_id: str - saturday_program_id: str - sunday_program_id: str - thursday_program_id: str - tuesday_program_id: str - wednesday_program_id: str - + friday_program_id: Optional[str] + monday_program_id: Optional[str] + saturday_program_id: Optional[str] + sunday_program_id: Optional[str] + thursday_program_id: Optional[str] + tuesday_program_id: Optional[str] + wednesday_program_id: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), friday_program_id=d.get("friday_program_id", None), @@ -2685,113 +2919,120 @@ def from_dict(cls, d: Dict[str, Any]): wednesday_program_id=d.get("wednesday_program_id", None), ) - accessory_keypad: AccessoryKeypad - appearance: Appearance - battery: Battery - battery_level: float - currently_triggering_noise_threshold_ids: List[str] - has_direct_power: bool - image_alt_text: str - image_url: str - manufacturer: str - model: Model + accessory_keypad: Optional[AccessoryKeypad] + appearance: Optional[Appearance] + battery: Optional[Battery] + battery_level: Optional[float] + currently_triggering_noise_threshold_ids: Optional[List[str]] + has_direct_power: Optional[bool] + image_alt_text: Optional[str] + image_url: Optional[str] + manufacturer: Optional[str] + model: Optional[Model] name: str - noise_level_decibels: float - offline_access_codes_enabled: bool + noise_level_decibels: Optional[float] + offline_access_codes_enabled: Optional[bool] online: bool - online_access_codes_enabled: bool - serial_number: str - supports_accessory_keypad: bool - supports_offline_access_codes: bool - assa_abloy_credential_service_metadata: AssaAbloyCredentialServiceMetadata - salto_space_credential_service_metadata: SaltoSpaceCredentialServiceMetadata - akiles_metadata: AkilesMetadata - aqara_metadata: AqaraMetadata - assa_abloy_vostio_metadata: AssaAbloyVostioMetadata - august_metadata: AugustMetadata - avigilon_alta_metadata: AvigilonAltaMetadata - brivo_metadata: BrivoMetadata - controlbyweb_metadata: ControlbywebMetadata - dormakaba_oracode_metadata: DormakabaOracodeMetadata - ecobee_metadata: EcobeeMetadata - four_suites_metadata: FourSuitesMetadata - genie_metadata: GenieMetadata - honeywell_resideo_metadata: HoneywellResideoMetadata - igloo_metadata: IglooMetadata - igloohome_metadata: IgloohomeMetadata - keynest_metadata: KeynestMetadata - kisi_metadata: KisiMetadata - korelock_metadata: KorelockMetadata - kwikset_metadata: KwiksetMetadata - lockly_metadata: LocklyMetadata - minut_metadata: MinutMetadata - nest_metadata: NestMetadata - noiseaware_metadata: NoiseawareMetadata - nuki_metadata: NukiMetadata - omnitec_metadata: OmnitecMetadata - ring_metadata: RingMetadata - salto_ks_metadata: SaltoKsMetadata - salto_metadata: SaltoMetadata - schlage_metadata: SchlageMetadata - seam_bridge_metadata: SeamBridgeMetadata - sensi_metadata: SensiMetadata - smartthings_metadata: SmartthingsMetadata - tado_metadata: TadoMetadata - tedee_metadata: TedeeMetadata - ttlock_metadata: TtlockMetadata - two_n_metadata: TwoNMetadata - ultraloq_metadata: UltraloqMetadata - visionline_metadata: VisionlineMetadata - wyze_metadata: WyzeMetadata - auto_lock_delay_seconds: float - auto_lock_enabled: bool - backup_access_code_pool_enabled: bool - code_constraints: List[CodeConstraints] - door_open: bool - has_native_entry_events: bool - keypad_battery: KeypadBattery - locked: bool - max_active_codes_supported: float - offline_time_frame_options: List[OfflineTimeFrameOptions] - online_time_frame_options: List[OnlineTimeFrameOptions] - supported_code_lengths: List[float] - supports_backup_access_code_pool: bool - active_thermostat_schedule: ActiveThermostatSchedule - active_thermostat_schedule_id: str - available_climate_preset_modes: List[str] - available_climate_presets: List[AvailableClimatePresets] - available_fan_mode_settings: List[str] - available_hvac_mode_settings: List[str] - current_climate_setting: CurrentClimateSetting - default_climate_setting: DefaultClimateSetting - fallback_climate_preset_key: str - fan_mode_setting: str - is_cooling: bool - is_fan_running: bool - is_heating: bool - is_temporary_manual_override_active: bool - max_cooling_set_point_celsius: float - max_cooling_set_point_fahrenheit: float - max_heating_set_point_celsius: float - max_heating_set_point_fahrenheit: float - max_thermostat_daily_program_periods_per_day: float - max_unique_climate_presets_per_thermostat_weekly_program: float - min_cooling_set_point_celsius: float - min_cooling_set_point_fahrenheit: float - min_heating_cooling_delta_celsius: float - min_heating_cooling_delta_fahrenheit: float - min_heating_set_point_celsius: float - min_heating_set_point_fahrenheit: float - relative_humidity: float - temperature_celsius: float - temperature_fahrenheit: float - temperature_threshold: TemperatureThreshold - thermostat_daily_program_period_precision_minutes: float - thermostat_daily_programs: List[ThermostatDailyPrograms] - thermostat_weekly_program: ThermostatWeeklyProgram - + online_access_codes_enabled: Optional[bool] + serial_number: Optional[str] + supports_accessory_keypad: Optional[bool] + supports_offline_access_codes: Optional[bool] + assa_abloy_credential_service_metadata: Optional[ + AssaAbloyCredentialServiceMetadata + ] + salto_space_credential_service_metadata: Optional[ + SaltoSpaceCredentialServiceMetadata + ] + akiles_metadata: Optional[AkilesMetadata] + aqara_metadata: Optional[AqaraMetadata] + assa_abloy_vostio_metadata: Optional[AssaAbloyVostioMetadata] + august_metadata: Optional[AugustMetadata] + avigilon_alta_metadata: Optional[AvigilonAltaMetadata] + brivo_metadata: Optional[BrivoMetadata] + controlbyweb_metadata: Optional[ControlbywebMetadata] + dormakaba_oracode_metadata: Optional[DormakabaOracodeMetadata] + ecobee_metadata: Optional[EcobeeMetadata] + four_suites_metadata: Optional[FourSuitesMetadata] + genie_metadata: Optional[GenieMetadata] + honeywell_resideo_metadata: Optional[HoneywellResideoMetadata] + igloo_metadata: Optional[IglooMetadata] + igloohome_metadata: Optional[IgloohomeMetadata] + keynest_metadata: Optional[KeynestMetadata] + kisi_metadata: Optional[KisiMetadata] + korelock_metadata: Optional[KorelockMetadata] + kwikset_metadata: Optional[KwiksetMetadata] + lockly_metadata: Optional[LocklyMetadata] + minut_metadata: Optional[MinutMetadata] + nest_metadata: Optional[NestMetadata] + noiseaware_metadata: Optional[NoiseawareMetadata] + nuki_metadata: Optional[NukiMetadata] + omnitec_metadata: Optional[OmnitecMetadata] + ring_metadata: Optional[RingMetadata] + salto_ks_metadata: Optional[SaltoKsMetadata] + salto_metadata: Optional[SaltoMetadata] + schlage_metadata: Optional[SchlageMetadata] + seam_bridge_metadata: Optional[SeamBridgeMetadata] + sensi_metadata: Optional[SensiMetadata] + smartthings_metadata: Optional[SmartthingsMetadata] + tado_metadata: Optional[TadoMetadata] + tedee_metadata: Optional[TedeeMetadata] + ttlock_metadata: Optional[TtlockMetadata] + two_n_metadata: Optional[TwoNMetadata] + ultraloq_metadata: Optional[UltraloqMetadata] + visionline_metadata: Optional[VisionlineMetadata] + wyze_metadata: Optional[WyzeMetadata] + auto_lock_delay_seconds: Optional[float] + auto_lock_enabled: Optional[bool] + backup_access_code_pool_enabled: Optional[bool] + code_constraints: Optional[List[CodeConstraints]] + door_open: Optional[bool] + has_native_entry_events: Optional[bool] + keypad_battery: Optional[KeypadBattery] + locked: Optional[bool] + max_active_codes_supported: Optional[float] + offline_time_frame_options: Optional[List[OfflineTimeFrameOptions]] + online_time_frame_options: Optional[List[OnlineTimeFrameOptions]] + supported_code_lengths: Optional[List[float]] + supports_backup_access_code_pool: Optional[bool] + active_thermostat_schedule: Optional[ActiveThermostatSchedule] + active_thermostat_schedule_id: Optional[str] + available_climate_preset_modes: Optional[List[str]] + available_climate_presets: Optional[List[AvailableClimatePresets]] + available_fan_mode_settings: Optional[List[str]] + available_hvac_mode_settings: Optional[List[str]] + current_climate_setting: Optional[CurrentClimateSetting] + default_climate_setting: Optional[DefaultClimateSetting] + fallback_climate_preset_key: Optional[str] + fan_mode_setting: Optional[str] + is_cooling: Optional[bool] + is_fan_running: Optional[bool] + is_heating: Optional[bool] + is_temporary_manual_override_active: Optional[bool] + max_cooling_set_point_celsius: Optional[float] + max_cooling_set_point_fahrenheit: Optional[float] + max_heating_set_point_celsius: Optional[float] + max_heating_set_point_fahrenheit: Optional[float] + max_thermostat_daily_program_periods_per_day: Optional[float] + max_unique_climate_presets_per_thermostat_weekly_program: Optional[float] + min_cooling_set_point_celsius: Optional[float] + min_cooling_set_point_fahrenheit: Optional[float] + min_heating_cooling_delta_celsius: Optional[float] + min_heating_cooling_delta_fahrenheit: Optional[float] + min_heating_set_point_celsius: Optional[float] + min_heating_set_point_fahrenheit: Optional[float] + relative_humidity: Optional[float] + temperature_celsius: Optional[float] + temperature_fahrenheit: Optional[float] + temperature_threshold: Optional[TemperatureThreshold] + thermostat_daily_program_period_precision_minutes: Optional[float] + thermostat_daily_programs: Optional[List[ThermostatDailyPrograms]] + thermostat_weekly_program: Optional[ThermostatWeeklyProgram] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accessory_keypad=( cls.AccessoryKeypad.from_dict(d.get("accessory_keypad")) @@ -3194,11 +3435,14 @@ class Warnings(ResourceMapping): created_at: str message: str warning_code: str - active_access_code_count: int - max_active_access_code_count: int + active_access_code_count: Optional[int] + max_active_access_code_count: Optional[int] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -3209,46 +3453,49 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - can_configure_auto_lock: bool - can_hvac_cool: bool - can_hvac_heat: bool - can_hvac_heat_cool: bool - can_program_offline_access_codes: bool - can_program_online_access_codes: bool - can_program_thermostat_programs_as_different_each_day: bool - can_program_thermostat_programs_as_same_each_day: bool - can_program_thermostat_programs_as_weekday_weekend: bool - can_remotely_lock: bool - can_remotely_unlock: bool - can_run_thermostat_programs: bool - can_simulate_connection: bool - can_simulate_disconnection: bool - can_simulate_hub_connection: bool - can_simulate_hub_disconnection: bool - can_simulate_paid_subscription: bool - can_simulate_removal: bool - can_turn_off_hvac: bool - can_unlock_with_code: bool + can_configure_auto_lock: Optional[bool] + can_hvac_cool: Optional[bool] + can_hvac_heat: Optional[bool] + can_hvac_heat_cool: Optional[bool] + can_program_offline_access_codes: Optional[bool] + can_program_online_access_codes: Optional[bool] + can_program_thermostat_programs_as_different_each_day: Optional[bool] + can_program_thermostat_programs_as_same_each_day: Optional[bool] + can_program_thermostat_programs_as_weekday_weekend: Optional[bool] + can_remotely_lock: Optional[bool] + can_remotely_unlock: Optional[bool] + can_run_thermostat_programs: Optional[bool] + can_simulate_connection: Optional[bool] + can_simulate_disconnection: Optional[bool] + can_simulate_hub_connection: Optional[bool] + can_simulate_hub_disconnection: Optional[bool] + can_simulate_paid_subscription: Optional[bool] + can_simulate_removal: Optional[bool] + can_turn_off_hvac: Optional[bool] + can_unlock_with_code: Optional[bool] capabilities_supported: List[str] connected_account_id: str created_at: str custom_metadata: Dict[str, Any] device_id: str - device_manufacturer: DeviceManufacturer - device_provider: DeviceProvider + device_manufacturer: Optional[DeviceManufacturer] + device_provider: Optional[DeviceProvider] device_type: str display_name: str errors: List[Errors] is_managed: bool - location: Location - nickname: str - properties: Properties + location: Optional[Location] + nickname: Optional[str] + properties: Optional[Properties] space_ids: List[str] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( can_configure_auto_lock=d.get("can_configure_auto_lock", None), can_hvac_cool=d.get("can_hvac_cool", None), diff --git a/seam/resources/device_provider.py b/seam/resources/device_provider.py index 2b498134..6bd6a2e7 100644 --- a/seam/resources/device_provider.py +++ b/seam/resources/device_provider.py @@ -57,33 +57,36 @@ class DeviceProvider: :ivar provider_categories: List of provider categories to which the device provider belongs, such as ``stable``, ``consumer_smartlocks``, ``thermostats``, and so on. """ - can_configure_auto_lock: bool - can_hvac_cool: bool - can_hvac_heat: bool - can_hvac_heat_cool: bool - can_program_offline_access_codes: bool - can_program_online_access_codes: bool - can_program_thermostat_programs_as_different_each_day: bool - can_program_thermostat_programs_as_same_each_day: bool - can_program_thermostat_programs_as_weekday_weekend: bool - can_remotely_lock: bool - can_remotely_unlock: bool - can_run_thermostat_programs: bool - can_simulate_connection: bool - can_simulate_disconnection: bool - can_simulate_hub_connection: bool - can_simulate_hub_disconnection: bool - can_simulate_paid_subscription: bool - can_simulate_removal: bool - can_turn_off_hvac: bool - can_unlock_with_code: bool + can_configure_auto_lock: Optional[bool] + can_hvac_cool: Optional[bool] + can_hvac_heat: Optional[bool] + can_hvac_heat_cool: Optional[bool] + can_program_offline_access_codes: Optional[bool] + can_program_online_access_codes: Optional[bool] + can_program_thermostat_programs_as_different_each_day: Optional[bool] + can_program_thermostat_programs_as_same_each_day: Optional[bool] + can_program_thermostat_programs_as_weekday_weekend: Optional[bool] + can_remotely_lock: Optional[bool] + can_remotely_unlock: Optional[bool] + can_run_thermostat_programs: Optional[bool] + can_simulate_connection: Optional[bool] + can_simulate_disconnection: Optional[bool] + can_simulate_hub_connection: Optional[bool] + can_simulate_hub_disconnection: Optional[bool] + can_simulate_paid_subscription: Optional[bool] + can_simulate_removal: Optional[bool] + can_turn_off_hvac: Optional[bool] + can_unlock_with_code: Optional[bool] device_provider_name: str display_name: str image_url: str provider_categories: List[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( can_configure_auto_lock=d.get("can_configure_auto_lock", None), can_hvac_cool=d.get("can_hvac_cool", None), diff --git a/seam/resources/instant_key.py b/seam/resources/instant_key.py index 39a98211..b7c32d1c 100644 --- a/seam/resources/instant_key.py +++ b/seam/resources/instant_key.py @@ -38,12 +38,15 @@ class Customization(ResourceMapping): :ivar secondary_color: Secondary color used in the Instant Key UI.""" - logo_url: str - primary_color: str - secondary_color: str + logo_url: Optional[str] + primary_color: Optional[str] + secondary_color: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( logo_url=d.get("logo_url", None), primary_color=d.get("primary_color", None), @@ -52,16 +55,19 @@ def from_dict(cls, d: Dict[str, Any]): client_session_id: str created_at: str - customization: Customization - customization_profile_id: str + customization: Optional[Customization] + customization_profile_id: Optional[str] expires_at: str instant_key_id: str instant_key_url: str user_identity_id: str workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( client_session_id=d.get("client_session_id", None), created_at=d.get("created_at", None), diff --git a/seam/resources/noise_threshold.py b/seam/resources/noise_threshold.py index e0eee750..d8179713 100644 --- a/seam/resources/noise_threshold.py +++ b/seam/resources/noise_threshold.py @@ -28,11 +28,14 @@ class NoiseThreshold: name: str noise_threshold_decibels: float noise_threshold_id: str - noise_threshold_nrs: float + noise_threshold_nrs: Optional[float] starts_daily_at: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), ends_daily_at=d.get("ends_daily_at", None), diff --git a/seam/resources/pagination.py b/seam/resources/pagination.py index a2180092..53949210 100644 --- a/seam/resources/pagination.py +++ b/seam/resources/pagination.py @@ -15,11 +15,14 @@ class Pagination: :ivar next_page_url: URL to get the next page of results.""" has_next_page: bool - next_page_cursor: str - next_page_url: str + next_page_cursor: Optional[str] + next_page_url: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( has_next_page=d.get("has_next_page", None), next_page_cursor=d.get("next_page_cursor", None), diff --git a/seam/resources/phone.py b/seam/resources/phone.py index c7ed93c2..2c69f137 100644 --- a/seam/resources/phone.py +++ b/seam/resources/phone.py @@ -42,8 +42,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -76,21 +79,27 @@ class Endpoints(ResourceMapping): :ivar is_active: Indicated whether the endpoint is active.""" - endpoint_id: str - is_active: bool + endpoint_id: Optional[str] + is_active: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( endpoint_id=d.get("endpoint_id", None), is_active=d.get("is_active", None), ) - endpoints: List[Endpoints] - has_active_endpoint: bool + endpoints: Optional[List[Endpoints]] + has_active_endpoint: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( endpoints=[ cls.Endpoints.from_dict(i) for i in d.get("endpoints") or [] @@ -105,19 +114,29 @@ class SaltoSpaceCredentialServiceMetadata(ResourceMapping): :ivar has_active_phone: Indicates whether the credential service has an active associated phone. """ - has_active_phone: bool + has_active_phone: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( has_active_phone=d.get("has_active_phone", None), ) - assa_abloy_credential_service_metadata: AssaAbloyCredentialServiceMetadata - salto_space_credential_service_metadata: SaltoSpaceCredentialServiceMetadata + assa_abloy_credential_service_metadata: Optional[ + AssaAbloyCredentialServiceMetadata + ] + salto_space_credential_service_metadata: Optional[ + SaltoSpaceCredentialServiceMetadata + ] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( assa_abloy_credential_service_metadata=( cls.AssaAbloyCredentialServiceMetadata.from_dict( @@ -149,8 +168,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -163,13 +185,16 @@ def from_dict(cls, d: Dict[str, Any]): device_type: str display_name: str errors: List[Errors] - nickname: str - properties: Properties + nickname: Optional[str] + properties: Optional[Properties] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), custom_metadata=DeepAttrDict(d.get("custom_metadata", None)), diff --git a/seam/resources/seam_event.py b/seam/resources/seam_event.py index 28a57f65..68fe4395 100644 --- a/seam/resources/seam_event.py +++ b/seam/resources/seam_event.py @@ -200,12 +200,15 @@ class ChangedProperties(ResourceMapping): :ivar to: New value of the property, or null if cleared.""" - from_: str + from_: Optional[str] property: str - to: str + to: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( from_=d.get("from", None), property=d.get("property", None), @@ -224,13 +227,16 @@ class From(ResourceMapping): :ivar starts_at: Previous start time.""" - name: str - code: str - ends_at: str - starts_at: str + name: Optional[str] + code: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( name=d.get("name", None), code=d.get("code", None), @@ -250,13 +256,16 @@ class To(ResourceMapping): :ivar starts_at: New start time.""" - name: str - code: str - ends_at: str - starts_at: str + name: Optional[str] + code: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( name=d.get("name", None), code=d.get("code", None), @@ -275,12 +284,15 @@ class RequestedMutations(ResourceMapping): :ivar to: New property values after the requested change. Keys depend on the mutation type. Absent for non-property mutations like ``deleting``. """ - from_: Dict[str, Any] + from_: Optional[Dict[str, Any]] mutation_code: str - to: Dict[str, Any] + to: Optional[Dict[str, Any]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( from_=DeepAttrDict(d.get("from", None)), mutation_code=d.get("mutation_code", None), @@ -302,8 +314,11 @@ class AccessCodeErrors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -325,8 +340,11 @@ class AccessCodeWarnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -348,8 +366,11 @@ class ConnectedAccountErrors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -371,8 +392,11 @@ class ConnectedAccountWarnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -394,8 +418,11 @@ class DeviceErrors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -417,8 +444,11 @@ class DeviceWarnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -440,8 +470,11 @@ class AcsSystemErrors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -463,8 +496,11 @@ class AcsSystemWarnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -483,107 +519,113 @@ class Reason(ResourceMapping): message: str reason_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( message=d.get("message", None), reason_code=d.get("reason_code", None), ) - access_code_id: str - connected_account_custom_metadata: Dict[str, Any] - connected_account_id: str + access_code_id: Optional[str] + connected_account_custom_metadata: Optional[Dict[str, Any]] + connected_account_id: Optional[str] created_at: str - device_custom_metadata: Dict[str, Any] - device_id: str - event_description: str + device_custom_metadata: Optional[Dict[str, Any]] + device_id: Optional[str] + event_description: Optional[str] event_id: str event_type: str occurred_at: str workspace_id: str - change_reason: str - changed_properties: List[ChangedProperties] - description: str - from_: From - to: To - requested_mutations: List[RequestedMutations] - code: str - access_code_errors: List[AccessCodeErrors] - access_code_warnings: List[AccessCodeWarnings] - connected_account_errors: List[ConnectedAccountErrors] - connected_account_warnings: List[ConnectedAccountWarnings] - device_errors: List[DeviceErrors] - device_warnings: List[DeviceWarnings] - backup_access_code_id: str - access_grant_id: str - acs_entrance_id: str - access_grant_key: str - ends_at: str - starts_at: str - error_message: str - missing_device_ids: List[str] - access_grant_ids: List[str] - access_grant_keys: List[str] - access_method_id: str - is_backup_code: bool - acs_system_id: str - acs_system_errors: List[AcsSystemErrors] - acs_system_warnings: List[AcsSystemWarnings] - acs_credential_id: str - acs_user_id: str - acs_encoder_id: str - acs_access_group_id: str - client_session_id: str - connect_webview_id: str - customer_key: str - connected_account_type: str - action_attempt_id: str - action_type: str - status: str - error_code: str - battery_level: float - battery_status: str - device_name: str - minut_metadata: Dict[str, Any] - noise_level_decibels: float - noise_level_nrs: float - noise_threshold_id: str - noise_threshold_name: str - noiseaware_metadata: Dict[str, Any] - access_code_is_managed: bool - is_via_bluetooth: bool - is_via_nfc: bool - method: str - user_identity_id: str - reason: Reason - climate_preset_key: str - is_fallback_climate_preset: bool - thermostat_schedule_id: str - cooling_set_point_celsius: float - cooling_set_point_fahrenheit: float - fan_mode_setting: str - heating_set_point_celsius: float - heating_set_point_fahrenheit: float - hvac_mode_setting: str - lower_limit_celsius: float - lower_limit_fahrenheit: float - temperature_celsius: float - temperature_fahrenheit: float - upper_limit_celsius: float - upper_limit_fahrenheit: float - desired_temperature_celsius: float - desired_temperature_fahrenheit: float - activation_reason: str - image_url: str - motion_sub_type: str - video_url: str - acs_entrance_ids: List[str] - device_ids: List[str] - space_id: str - space_key: str - + change_reason: Optional[str] + changed_properties: Optional[List[ChangedProperties]] + description: Optional[str] + from_: Optional[From] + to: Optional[To] + requested_mutations: Optional[List[RequestedMutations]] + code: Optional[str] + access_code_errors: Optional[List[AccessCodeErrors]] + access_code_warnings: Optional[List[AccessCodeWarnings]] + connected_account_errors: Optional[List[ConnectedAccountErrors]] + connected_account_warnings: Optional[List[ConnectedAccountWarnings]] + device_errors: Optional[List[DeviceErrors]] + device_warnings: Optional[List[DeviceWarnings]] + backup_access_code_id: Optional[str] + access_grant_id: Optional[str] + acs_entrance_id: Optional[str] + access_grant_key: Optional[str] + ends_at: Optional[str] + starts_at: Optional[str] + error_message: Optional[str] + missing_device_ids: Optional[List[str]] + access_grant_ids: Optional[List[str]] + access_grant_keys: Optional[List[str]] + access_method_id: Optional[str] + is_backup_code: Optional[bool] + acs_system_id: Optional[str] + acs_system_errors: Optional[List[AcsSystemErrors]] + acs_system_warnings: Optional[List[AcsSystemWarnings]] + acs_credential_id: Optional[str] + acs_user_id: Optional[str] + acs_encoder_id: Optional[str] + acs_access_group_id: Optional[str] + client_session_id: Optional[str] + connect_webview_id: Optional[str] + customer_key: Optional[str] + connected_account_type: Optional[str] + action_attempt_id: Optional[str] + action_type: Optional[str] + status: Optional[str] + error_code: Optional[str] + battery_level: Optional[float] + battery_status: Optional[str] + device_name: Optional[str] + minut_metadata: Optional[Dict[str, Any]] + noise_level_decibels: Optional[float] + noise_level_nrs: Optional[float] + noise_threshold_id: Optional[str] + noise_threshold_name: Optional[str] + noiseaware_metadata: Optional[Dict[str, Any]] + access_code_is_managed: Optional[bool] + is_via_bluetooth: Optional[bool] + is_via_nfc: Optional[bool] + method: Optional[str] + user_identity_id: Optional[str] + reason: Optional[Reason] + climate_preset_key: Optional[str] + is_fallback_climate_preset: Optional[bool] + thermostat_schedule_id: Optional[str] + cooling_set_point_celsius: Optional[float] + cooling_set_point_fahrenheit: Optional[float] + fan_mode_setting: Optional[str] + heating_set_point_celsius: Optional[float] + heating_set_point_fahrenheit: Optional[float] + hvac_mode_setting: Optional[str] + lower_limit_celsius: Optional[float] + lower_limit_fahrenheit: Optional[float] + temperature_celsius: Optional[float] + temperature_fahrenheit: Optional[float] + upper_limit_celsius: Optional[float] + upper_limit_fahrenheit: Optional[float] + desired_temperature_celsius: Optional[float] + desired_temperature_fahrenheit: Optional[float] + activation_reason: Optional[str] + image_url: Optional[str] + motion_sub_type: Optional[str] + video_url: Optional[str] + acs_entrance_ids: Optional[List[str]] + device_ids: Optional[List[str]] + space_id: Optional[str] + space_key: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_code_id=d.get("access_code_id", None), connected_account_custom_metadata=DeepAttrDict( diff --git a/seam/resources/space.py b/seam/resources/space.py index 2712f62b..629fb423 100644 --- a/seam/resources/space.py +++ b/seam/resources/space.py @@ -42,13 +42,16 @@ class CustomerData(ResourceMapping): :ivar time_zone: IANA time zone for the space, e.g. America/Los_Angeles.""" - address: str - default_checkin_time: str - default_checkout_time: str - time_zone: str - + address: Optional[str] + default_checkin_time: Optional[str] + default_checkout_time: Optional[str] + time_zone: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( address=d.get("address", None), default_checkin_time=d.get("default_checkin_time", None), @@ -67,8 +70,11 @@ class Geolocation(ResourceMapping): latitude: float longitude: float + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( latitude=d.get("latitude", None), longitude=d.get("longitude", None), @@ -76,18 +82,21 @@ def from_dict(cls, d: Dict[str, Any]): acs_entrance_count: float created_at: str - customer_data: CustomerData - customer_key: str + customer_data: Optional[CustomerData] + customer_key: Optional[str] device_count: float display_name: str - geolocation: Geolocation + geolocation: Optional[Geolocation] name: str space_id: str - space_key: str + space_key: Optional[str] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_entrance_count=d.get("acs_entrance_count", None), created_at=d.get("created_at", None), diff --git a/seam/resources/thermostat_daily_program.py b/seam/resources/thermostat_daily_program.py index 3876b0d6..e6710a01 100644 --- a/seam/resources/thermostat_daily_program.py +++ b/seam/resources/thermostat_daily_program.py @@ -33,8 +33,11 @@ class Periods(ResourceMapping): climate_preset_key: str starts_at_time: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_preset_key=d.get("climate_preset_key", None), starts_at_time=d.get("starts_at_time", None), @@ -42,13 +45,16 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str device_id: str - name: str + name: Optional[str] periods: List[Periods] thermostat_daily_program_id: str workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), device_id=d.get("device_id", None), diff --git a/seam/resources/thermostat_schedule.py b/seam/resources/thermostat_schedule.py index 4bb71bc9..b51d1dd8 100644 --- a/seam/resources/thermostat_schedule.py +++ b/seam/resources/thermostat_schedule.py @@ -45,8 +45,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -58,15 +61,18 @@ def from_dict(cls, d: Dict[str, Any]): device_id: str ends_at: str errors: List[Errors] - is_override_allowed: bool - max_override_period_minutes: int - name: str + is_override_allowed: Optional[bool] + max_override_period_minutes: Optional[int] + name: Optional[str] starts_at: str thermostat_schedule_id: str workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( climate_preset_key=d.get("climate_preset_key", None), created_at=d.get("created_at", None), diff --git a/seam/resources/unmanaged_access_code.py b/seam/resources/unmanaged_access_code.py index faecc79e..0d39e68d 100644 --- a/seam/resources/unmanaged_access_code.py +++ b/seam/resources/unmanaged_access_code.py @@ -72,17 +72,20 @@ class DormakabaOracodeMetadata(ResourceMapping): :ivar user_level_name: Dormakaba Oracode user level name associated with this access code. """ - is_cancellable: bool - is_early_checkin_able: bool - is_extendable: bool - is_overridable: bool - site_name: str - stay_id: float - user_level_id: str - user_level_name: str - + is_cancellable: Optional[bool] + is_early_checkin_able: Optional[bool] + is_extendable: Optional[bool] + is_overridable: Optional[bool] + site_name: Optional[str] + stay_id: Optional[float] + user_level_id: Optional[str] + user_level_name: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( is_cancellable=d.get("is_cancellable", None), is_early_checkin_able=d.get("is_early_checkin_able", None), @@ -132,31 +135,37 @@ class ModifiedFields(ResourceMapping): :ivar to: The new value of the field.""" field: str - from_: str - to: str + from_: Optional[str] + to: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( field=d.get("field", None), from_=d.get("from", None), to=d.get("to", None), ) - created_at: str + created_at: Optional[str] error_code: str - is_access_code_error: bool + is_access_code_error: Optional[bool] message: str - managed_access_code_id: str - unmanaged_access_code_id: str - change_type: str - modified_fields: List[ModifiedFields] - is_connected_account_error: bool - is_device_error: bool - is_bridge_error: bool - + managed_access_code_id: Optional[str] + unmanaged_access_code_id: Optional[str] + change_type: Optional[str] + modified_fields: Optional[List[ModifiedFields]] + is_connected_account_error: Optional[bool] + is_device_error: Optional[bool] + is_bridge_error: Optional[bool] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -200,25 +209,31 @@ class ModifiedFields(ResourceMapping): :ivar to: The new value of the field.""" field: str - from_: str - to: str + from_: Optional[str] + to: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( field=d.get("field", None), from_=d.get("from", None), to=d.get("to", None), ) - created_at: str + created_at: Optional[str] message: str warning_code: str - change_type: str - modified_fields: List[ModifiedFields] + change_type: Optional[str] + modified_fields: Optional[List[ModifiedFields]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -231,24 +246,27 @@ def from_dict(cls, d: Dict[str, Any]): ) access_code_id: str - cannot_be_managed: bool - cannot_delete_unmanaged_access_code: bool - code: str + cannot_be_managed: Optional[bool] + cannot_delete_unmanaged_access_code: Optional[bool] + code: Optional[str] created_at: str device_id: str - dormakaba_oracode_metadata: DormakabaOracodeMetadata - ends_at: str + dormakaba_oracode_metadata: Optional[DormakabaOracodeMetadata] + ends_at: Optional[str] errors: List[Errors] is_managed: bool - name: str - starts_at: str + name: Optional[str] + starts_at: Optional[str] status: str type: str warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_code_id=d.get("access_code_id", None), cannot_be_managed=d.get("cannot_be_managed", None), diff --git a/seam/resources/unmanaged_access_grant.py b/seam/resources/unmanaged_access_grant.py index 9b2c3f30..354a3d37 100644 --- a/seam/resources/unmanaged_access_grant.py +++ b/seam/resources/unmanaged_access_grant.py @@ -56,10 +56,13 @@ class Errors(ResourceMapping): created_at: str error_code: str message: str - missing_device_ids: List[str] + missing_device_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -93,12 +96,15 @@ class From(ResourceMapping): :ivar starts_at: Previous start time for access.""" - device_ids: List[str] - ends_at: str - starts_at: str + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_ids=d.get("device_ids", None), ends_at=d.get("ends_at", None), @@ -117,13 +123,16 @@ class To(ResourceMapping): :ivar starts_at: New start time for access.""" - common_code_key: str - device_ids: List[str] - ends_at: str - starts_at: str + common_code_key: Optional[str] + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( common_code_key=d.get("common_code_key", None), device_ids=d.get("device_ids", None), @@ -132,14 +141,17 @@ def from_dict(cls, d: Dict[str, Any]): ) created_at: str - from_: From + from_: Optional[From] message: str mutation_code: str - to: To - access_method_ids: List[str] + to: Optional[To] + access_method_ids: Optional[List[str]] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), from_=( @@ -170,15 +182,18 @@ class RequestedAccessMethods(ResourceMapping): :ivar mode: Access method mode. Supported values: ``code``, ``card``, ``mobile_key``, ``cloud_key``. """ - code: str + code: Optional[str] created_access_method_ids: List[str] created_at: str display_name: str - instant_key_max_use_count: int + instant_key_max_use_count: Optional[int] mode: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( code=d.get("code", None), created_access_method_ids=d.get("created_access_method_ids", None), @@ -225,8 +240,11 @@ class FailedDevices(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_id=d.get("device_id", None), error_code=d.get("error_code", None), @@ -236,15 +254,18 @@ def from_dict(cls, d: Dict[str, Any]): created_at: str message: str warning_code: str - failed_devices: List[FailedDevices] - access_method_ids: List[str] - device_id: str - new_code: str - original_code: str - reason: str - + failed_devices: Optional[List[FailedDevices]] + access_method_ids: Optional[List[str]] + device_id: Optional[str] + new_code: Optional[str] + original_code: Optional[str] + reason: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -264,21 +285,24 @@ def from_dict(cls, d: Dict[str, Any]): access_method_ids: List[str] created_at: str display_name: str - ends_at: str + ends_at: Optional[str] errors: List[Errors] location_ids: List[str] - name: str + name: Optional[str] pending_mutations: List[PendingMutations] requested_access_methods: List[RequestedAccessMethods] - reservation_key: str + reservation_key: Optional[str] space_ids: List[str] starts_at: str - user_identity_id: str + user_identity_id: Optional[str] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_grant_id=d.get("access_grant_id", None), access_method_ids=d.get("access_method_ids", None), diff --git a/seam/resources/unmanaged_access_method.py b/seam/resources/unmanaged_access_method.py index edd18201..0183e341 100644 --- a/seam/resources/unmanaged_access_method.py +++ b/seam/resources/unmanaged_access_method.py @@ -53,8 +53,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -85,12 +88,15 @@ class From(ResourceMapping): :ivar starts_at: Previous start time for access.""" - device_ids: List[str] - ends_at: str - starts_at: str + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_ids=d.get("device_ids", None), ends_at=d.get("ends_at", None), @@ -107,12 +113,15 @@ class To(ResourceMapping): :ivar starts_at: New start time for access.""" - device_ids: List[str] - ends_at: str - starts_at: str + device_ids: Optional[List[str]] + ends_at: Optional[str] + starts_at: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( device_ids=d.get("device_ids", None), ends_at=d.get("ends_at", None), @@ -120,13 +129,16 @@ def from_dict(cls, d: Dict[str, Any]): ) created_at: str - from_: From + from_: Optional[From] message: str mutation_code: str - to: To + to: Optional[To] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), from_=( @@ -155,10 +167,13 @@ class Warnings(ResourceMapping): created_at: str message: str warning_code: str - original_access_method_id: str + original_access_method_id: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -167,23 +182,26 @@ def from_dict(cls, d: Dict[str, Any]): ) access_method_id: str - code: str + code: Optional[str] created_at: str display_name: str errors: List[Errors] - is_assignment_required: bool - is_encoding_required: bool + is_assignment_required: Optional[bool] + is_encoding_required: Optional[bool] is_issued: bool - is_ready_for_assignment: bool - is_ready_for_encoding: bool - issued_at: str + is_ready_for_assignment: Optional[bool] + is_ready_for_encoding: Optional[bool] + issued_at: Optional[str] mode: str pending_mutations: List[PendingMutations] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( access_method_id=d.get("access_method_id", None), code=d.get("code", None), diff --git a/seam/resources/unmanaged_device.py b/seam/resources/unmanaged_device.py index 34d4eff7..273abc48 100644 --- a/seam/resources/unmanaged_device.py +++ b/seam/resources/unmanaged_device.py @@ -92,13 +92,16 @@ class Errors(ResourceMapping): created_at: str error_code: str - is_connected_account_error: bool - is_device_error: bool + is_connected_account_error: Optional[bool] + is_device_error: Optional[bool] message: str - is_bridge_error: bool + is_bridge_error: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), error_code=d.get("error_code", None), @@ -119,12 +122,15 @@ class Location(ResourceMapping): :ivar timezone: Deprecated: Use ``time_zone`` instead. Time zone of the device location. """ - location_name: str - time_zone: str - timezone: str + location_name: Optional[str] + time_zone: Optional[str] + timezone: Optional[str] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( location_name=d.get("location_name", None), time_zone=d.get("time_zone", None), @@ -175,17 +181,23 @@ class Battery(ResourceMapping): level: float + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( level=d.get("level", None), ) - battery: Battery + battery: Optional[Battery] is_connected: bool + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( battery=( cls.Battery.from_dict(d.get("battery")) @@ -207,8 +219,11 @@ class Battery(ResourceMapping): level: float status: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( level=d.get("level", None), status=d.get("status", None), @@ -233,16 +248,19 @@ class Model(ResourceMapping): :ivar online_access_codes_supported: Deprecated: use device.can_program_online_access_codes. """ - accessory_keypad_supported: bool - can_connect_accessory_keypad: bool + accessory_keypad_supported: Optional[bool] + can_connect_accessory_keypad: Optional[bool] display_name: str - has_built_in_keypad: bool + has_built_in_keypad: Optional[bool] manufacturer_display_name: str - offline_access_codes_supported: bool - online_access_codes_supported: bool + offline_access_codes_supported: Optional[bool] + online_access_codes_supported: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accessory_keypad_supported=d.get( "accessory_keypad_supported", None @@ -261,20 +279,23 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - accessory_keypad: AccessoryKeypad - battery: Battery - battery_level: float - image_alt_text: str - image_url: str - manufacturer: str - model: Model + accessory_keypad: Optional[AccessoryKeypad] + battery: Optional[Battery] + battery_level: Optional[float] + image_alt_text: Optional[str] + image_url: Optional[str] + manufacturer: Optional[str] + model: Optional[Model] name: str - offline_access_codes_enabled: bool + offline_access_codes_enabled: Optional[bool] online: bool - online_access_codes_enabled: bool + online_access_codes_enabled: Optional[bool] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( accessory_keypad=( cls.AccessoryKeypad.from_dict(d.get("accessory_keypad")) @@ -321,11 +342,14 @@ class Warnings(ResourceMapping): created_at: str message: str warning_code: str - active_access_code_count: int - max_active_access_code_count: int + active_access_code_count: Optional[int] + max_active_access_code_count: Optional[int] + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -336,26 +360,26 @@ def from_dict(cls, d: Dict[str, Any]): ), ) - can_configure_auto_lock: bool - can_hvac_cool: bool - can_hvac_heat: bool - can_hvac_heat_cool: bool - can_program_offline_access_codes: bool - can_program_online_access_codes: bool - can_program_thermostat_programs_as_different_each_day: bool - can_program_thermostat_programs_as_same_each_day: bool - can_program_thermostat_programs_as_weekday_weekend: bool - can_remotely_lock: bool - can_remotely_unlock: bool - can_run_thermostat_programs: bool - can_simulate_connection: bool - can_simulate_disconnection: bool - can_simulate_hub_connection: bool - can_simulate_hub_disconnection: bool - can_simulate_paid_subscription: bool - can_simulate_removal: bool - can_turn_off_hvac: bool - can_unlock_with_code: bool + can_configure_auto_lock: Optional[bool] + can_hvac_cool: Optional[bool] + can_hvac_heat: Optional[bool] + can_hvac_heat_cool: Optional[bool] + can_program_offline_access_codes: Optional[bool] + can_program_online_access_codes: Optional[bool] + can_program_thermostat_programs_as_different_each_day: Optional[bool] + can_program_thermostat_programs_as_same_each_day: Optional[bool] + can_program_thermostat_programs_as_weekday_weekend: Optional[bool] + can_remotely_lock: Optional[bool] + can_remotely_unlock: Optional[bool] + can_run_thermostat_programs: Optional[bool] + can_simulate_connection: Optional[bool] + can_simulate_disconnection: Optional[bool] + can_simulate_hub_connection: Optional[bool] + can_simulate_hub_disconnection: Optional[bool] + can_simulate_paid_subscription: Optional[bool] + can_simulate_removal: Optional[bool] + can_turn_off_hvac: Optional[bool] + can_unlock_with_code: Optional[bool] capabilities_supported: List[str] connected_account_id: str created_at: str @@ -364,13 +388,16 @@ def from_dict(cls, d: Dict[str, Any]): device_type: str errors: List[Errors] is_managed: bool - location: Location - properties: Properties + location: Optional[Location] + properties: Optional[Properties] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( can_configure_auto_lock=d.get("can_configure_auto_lock", None), can_hvac_cool=d.get("can_hvac_cool", None), diff --git a/seam/resources/unmanaged_user_identity.py b/seam/resources/unmanaged_user_identity.py index 307cc2ea..2831e4c6 100644 --- a/seam/resources/unmanaged_user_identity.py +++ b/seam/resources/unmanaged_user_identity.py @@ -49,8 +49,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_system_id=d.get("acs_system_id", None), acs_user_id=d.get("acs_user_id", None), @@ -74,8 +77,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -85,16 +91,19 @@ def from_dict(cls, d: Dict[str, Any]): acs_user_ids: List[str] created_at: str display_name: str - email_address: str + email_address: Optional[str] errors: List[Errors] - full_name: str - phone_number: str + full_name: Optional[str] + phone_number: Optional[str] user_identity_id: str warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_user_ids=d.get("acs_user_ids", None), created_at=d.get("created_at", None), diff --git a/seam/resources/user_identity.py b/seam/resources/user_identity.py index d1693265..8d9e5751 100644 --- a/seam/resources/user_identity.py +++ b/seam/resources/user_identity.py @@ -51,8 +51,11 @@ class Errors(ResourceMapping): error_code: str message: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_system_id=d.get("acs_system_id", None), acs_user_id=d.get("acs_user_id", None), @@ -76,8 +79,11 @@ class Warnings(ResourceMapping): message: str warning_code: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( created_at=d.get("created_at", None), message=d.get("message", None), @@ -87,17 +93,20 @@ def from_dict(cls, d: Dict[str, Any]): acs_user_ids: List[str] created_at: str display_name: str - email_address: str + email_address: Optional[str] errors: List[Errors] - full_name: str - phone_number: str + full_name: Optional[str] + phone_number: Optional[str] user_identity_id: str - user_identity_key: str + user_identity_key: Optional[str] warnings: List[Warnings] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( acs_user_ids=d.get("acs_user_ids", None), created_at=d.get("created_at", None), diff --git a/seam/resources/webhook.py b/seam/resources/webhook.py index fba1c282..75353745 100644 --- a/seam/resources/webhook.py +++ b/seam/resources/webhook.py @@ -16,13 +16,16 @@ class Webhook: :ivar webhook_id: ID of the webhook.""" - event_types: List[str] - secret: str + event_types: Optional[List[str]] + secret: Optional[str] url: str webhook_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( event_types=d.get("event_types", None), secret=d.get("secret", None), diff --git a/seam/resources/workspace.py b/seam/resources/workspace.py index 2c89663c..06c9eb1b 100644 --- a/seam/resources/workspace.py +++ b/seam/resources/workspace.py @@ -43,14 +43,17 @@ class ConnectWebviewCustomization(ResourceMapping): :ivar success_message: Success message for `Connect Webviews `_ in the workspace. See also `Customize the Look and Feel of Your Connect Webviews `_. """ - inviter_logo_url: str - logo_shape: str - primary_button_color: str - primary_button_text_color: str - success_message: str - + inviter_logo_url: Optional[str] + logo_shape: Optional[str] + primary_button_color: Optional[str] + primary_button_text_color: Optional[str] + success_message: Optional[str] + + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( inviter_logo_url=d.get("inviter_logo_url", None), logo_shape=d.get("logo_shape", None), @@ -60,18 +63,21 @@ def from_dict(cls, d: Dict[str, Any]): ) company_name: str - connect_partner_name: str - connect_webview_customization: ConnectWebviewCustomization + connect_partner_name: Optional[str] + connect_webview_customization: Optional[ConnectWebviewCustomization] is_publishable_key_auth_enabled: bool is_sandbox: bool is_suspended: bool name: str - organization_id: str - publishable_key: str + organization_id: Optional[str] + publishable_key: Optional[str] workspace_id: str + # The payload is decoded JSON, so every value read out of it is untyped. + # Typing d as Any keeps that at this boundary instead of casting each + # read, and the dataclass fields carry the real types. @classmethod - def from_dict(cls, d: Dict[str, Any]): + def from_dict(cls, d: Any): return cls( company_name=d.get("company_name", None), connect_partner_name=d.get("connect_partner_name", None), diff --git a/seam/routes/access_codes.py b/seam/routes/access_codes.py index e6929152..ddccd477 100644 --- a/seam/routes/access_codes.py +++ b/seam/routes/access_codes.py @@ -445,7 +445,7 @@ def create( :param use_offline_access_code: Deprecated: Use ``is_offline_access_code`` instead. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -545,7 +545,7 @@ def create_multiple( :param use_backup_access_code_pool: Indicates whether to use a `backup access code pool `_ provided by Seam. If ``true``, you can use ```/access_codes/pull_backup_access_code`` `_. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_ids is not None: json_payload["device_ids"] = device_ids @@ -587,7 +587,7 @@ def delete(self, *, access_code_id: str, device_id: Optional[str] = None) -> Non :param device_id: ID of the device for which you want to delete the access code. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -604,7 +604,7 @@ def generate_code(self, *, device_id: str) -> AccessCode: :param device_id: ID of the device for which you want to generate a code. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -631,7 +631,7 @@ def get( :param device_id: ID of the device containing the access code that you want to get. You must specify either ``access_code_id`` or both ``device_id`` and ``code``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -683,7 +683,7 @@ def list( :param user_identifier_key: Your user ID for the user by which to filter access codes. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_ids is not None: json_payload["access_code_ids"] = access_code_ids @@ -724,7 +724,7 @@ def pull_backup_access_code(self, *, access_code_id: str) -> AccessCode: :param access_code_id: ID of the access code for which you want to pull a backup access code. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -755,7 +755,7 @@ def report_device_constraints( :param supported_code_lengths: Array of supported code lengths as integers between 4 and 20, inclusive. You can specify either ``supported_code_lengths`` or ``min_code_length``/``max_code_length``. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -838,7 +838,7 @@ def update( :param use_offline_access_code: Deprecated: Use ``is_offline_access_code`` instead. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -911,7 +911,7 @@ def update_multiple( :param starts_at: Date and time at which the validity of the new access code starts, in `ISO 8601 `_ format. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if common_code_key is not None: json_payload["common_code_key"] = common_code_key diff --git a/seam/routes/access_codes_simulate.py b/seam/routes/access_codes_simulate.py index 048c13fb..3b0b0064 100644 --- a/seam/routes/access_codes_simulate.py +++ b/seam/routes/access_codes_simulate.py @@ -39,7 +39,7 @@ def create_unmanaged_access_code( :param name: Name of the simulated unmanaged access code. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if code is not None: json_payload["code"] = code diff --git a/seam/routes/access_codes_unmanaged.py b/seam/routes/access_codes_unmanaged.py index da1b17f1..e0dd0612 100644 --- a/seam/routes/access_codes_unmanaged.py +++ b/seam/routes/access_codes_unmanaged.py @@ -137,7 +137,7 @@ def convert_to_managed( :param is_external_modification_allowed: Indicates whether `external modification `_ of the access code is allowed. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -161,7 +161,7 @@ def delete(self, *, access_code_id: str) -> None: :param access_code_id: ID of the unmanaged access code that you want to delete. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -188,7 +188,7 @@ def get( :param device_id: ID of the device containing the unmanaged access code that you want to get. You must specify either ``access_code_id`` or both ``device_id`` and ``code``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -223,7 +223,7 @@ def list( :param user_identifier_key: Your user ID for the user by which to filter unmanaged access codes. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -261,7 +261,7 @@ def update( :param is_external_modification_allowed: Indicates whether `external modification `_ of the code is allowed. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id diff --git a/seam/routes/access_grants.py b/seam/routes/access_grants.py index e9550c33..8865a7fa 100644 --- a/seam/routes/access_grants.py +++ b/seam/routes/access_grants.py @@ -264,7 +264,7 @@ def create( :param starts_at: Date and time at which the validity of the new grant starts, in `ISO 8601 `_ format. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if requested_access_methods is not None: json_payload["requested_access_methods"] = requested_access_methods @@ -305,7 +305,7 @@ def delete(self, *, access_grant_id: str) -> None: """Delete an Access Grant. :param access_grant_id: ID of Access Grant to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id @@ -327,7 +327,7 @@ def get( :param access_grant_key: Unique key of Access Grant to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id @@ -357,7 +357,7 @@ def get_related( :param include: :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_ids is not None: json_payload["access_grant_ids"] = access_grant_ids @@ -418,7 +418,7 @@ def list( :param user_identity_id: ID of user identity by which you want to filter the list of Access Grants. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -461,7 +461,7 @@ def request_access_methods( :param requested_access_methods: Array of requested access methods to add to the access grant. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id @@ -495,7 +495,7 @@ def update( :param starts_at: Date and time at which the validity of the grant starts, in `ISO 8601 `_ format. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id diff --git a/seam/routes/access_grants_unmanaged.py b/seam/routes/access_grants_unmanaged.py index 2dd8b80d..ffa6796b 100644 --- a/seam/routes/access_grants_unmanaged.py +++ b/seam/routes/access_grants_unmanaged.py @@ -77,7 +77,7 @@ def get(self, *, access_grant_id: str) -> UnmanagedAccessGrant: :param access_grant_id: ID of unmanaged Access Grant to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id @@ -111,7 +111,7 @@ def list( :param user_identity_id: ID of user identity by which you want to filter the list of unmanaged Access Grants. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_id is not None: json_payload["acs_entrance_id"] = acs_entrance_id @@ -149,7 +149,7 @@ def update( :param access_grant_key: Unique key for the access grant. If not provided, the existing key will be preserved. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id diff --git a/seam/routes/access_methods.py b/seam/routes/access_methods.py index c92c2d10..87c94a57 100644 --- a/seam/routes/access_methods.py +++ b/seam/routes/access_methods.py @@ -180,7 +180,7 @@ def assign_card( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id @@ -216,7 +216,7 @@ def delete( :param reservation_key: Reservation key of the access grant whose access methods should be deleted. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id @@ -245,7 +245,7 @@ def encode( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id @@ -272,7 +272,7 @@ def get(self, *, access_method_id: str) -> AccessMethod: :param access_method_id: ID of access method to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id @@ -297,7 +297,7 @@ def get_related( :param include: :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_ids is not None: json_payload["access_method_ids"] = access_method_ids @@ -341,7 +341,7 @@ def list( :param space_id: ID of the space by which to filter the returned access methods. Must be combined with ``access_grant_id``, ``access_grant_key``, or ``acs_entrance_id``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id @@ -380,7 +380,7 @@ def unlock_door( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id diff --git a/seam/routes/access_methods_unmanaged.py b/seam/routes/access_methods_unmanaged.py index a2783641..bd1e1584 100644 --- a/seam/routes/access_methods_unmanaged.py +++ b/seam/routes/access_methods_unmanaged.py @@ -49,7 +49,7 @@ def get(self, *, access_method_id: str) -> UnmanagedAccessMethod: :param access_method_id: ID of unmanaged access method to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id @@ -77,7 +77,7 @@ def list( :param space_id: ID of the space for which you want to retrieve all unmanaged access methods. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_id is not None: json_payload["access_grant_id"] = access_grant_id diff --git a/seam/routes/acs_access_groups.py b/seam/routes/acs_access_groups.py index 606ffa8d..743ae2a3 100644 --- a/seam/routes/acs_access_groups.py +++ b/seam/routes/acs_access_groups.py @@ -121,7 +121,7 @@ def add_user( :param user_identity_id: ID of the desired user identity that you want to add to an access group. You can only provide one of acs_user_id or user_identity_id. If the ACS system contains an ACS user with the same ``email_address`` or ``phone_number`` as the user identity that you specify, they are linked, and the access group membership belongs to the ACS user. If the ACS system does not have a corresponding ACS user, one is created. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -138,7 +138,7 @@ def delete(self, *, acs_access_group_id: str) -> None: """Deletes a specified `access group `_. :param acs_access_group_id: ID of the access group that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -153,7 +153,7 @@ def get(self, *, acs_access_group_id: str) -> AcsAccessGroup: :param acs_access_group_id: ID of the access group that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -181,7 +181,7 @@ def list( :param user_identity_id: ID of the user identity for which you want to retrieve all access groups. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -204,7 +204,7 @@ def list_accessible_entrances( :param acs_access_group_id: ID of the access group for which you want to retrieve all accessible entrances. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -221,7 +221,7 @@ def list_users(self, *, acs_access_group_id: str) -> List[AcsUser]: :param acs_access_group_id: ID of the access group for which you want to retrieve all access system users. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -245,7 +245,7 @@ def remove_user( :param user_identity_id: ID of the user identity associated with the user that you want to remove from an access group. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id diff --git a/seam/routes/acs_credentials.py b/seam/routes/acs_credentials.py index cc2910bf..2ad19891 100644 --- a/seam/routes/acs_credentials.py +++ b/seam/routes/acs_credentials.py @@ -189,7 +189,7 @@ def assign( :param user_identity_id: ID of the user identity to whom you want to assign a credential. You can only provide one of acs_user_id or user_identity_id. If the ACS system contains an ACS user with the same ``email_address`` or ``phone_number`` as the user identity that you specify, they are linked, and the credential belongs to the ACS user. If the ACS system does not have a corresponding ACS user, one is created. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id @@ -248,7 +248,7 @@ def create( :param visionline_metadata: Visionline-specific metadata for the new credential. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method is not None: json_payload["access_method"] = access_method @@ -289,7 +289,7 @@ def delete(self, *, acs_credential_id: str) -> None: """Deletes a specified `credential `_. :param acs_credential_id: ID of the credential that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id @@ -304,7 +304,7 @@ def get(self, *, acs_credential_id: str) -> AcsCredential: :param acs_credential_id: ID of the credential that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id @@ -344,7 +344,7 @@ def list( :param search: String for which to search. Filters returned credentials to include all records that satisfy a partial match using ``display_name``, ``code``, ``card_number``, ``acs_user_id`` or ``acs_credential_id``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_user_id is not None: json_payload["acs_user_id"] = acs_user_id @@ -375,7 +375,7 @@ def list_accessible_entrances(self, *, acs_credential_id: str) -> List[AcsEntran :param acs_credential_id: ID of the credential for which you want to retrieve all entrances to which the credential grants access. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id @@ -401,7 +401,7 @@ def unassign( :param user_identity_id: ID of the user identity from which you want to unassign a credential. You can only provide one of acs_user_id or user_identity_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id @@ -429,7 +429,7 @@ def update( :param ends_at: Replacement date and time at which the validity of the credential ends, in `ISO 8601 `_ format. Must be a time in the future and after the ``starts_at`` value that you set when creating the credential. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id diff --git a/seam/routes/acs_encoders.py b/seam/routes/acs_encoders.py index 3bd18abb..1ecc91ce 100644 --- a/seam/routes/acs_encoders.py +++ b/seam/routes/acs_encoders.py @@ -143,7 +143,7 @@ def encode_credential( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id @@ -172,7 +172,7 @@ def get(self, *, acs_encoder_id: str) -> AcsEncoder: :param acs_encoder_id: ID of the encoder that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id @@ -203,7 +203,7 @@ def list( :param page_cursor: Identifies the specific page of results to return, obtained from the previous page's ``next_page_cursor``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -236,7 +236,7 @@ def scan_credential( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id @@ -279,7 +279,7 @@ def scan_to_assign_credential( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id diff --git a/seam/routes/acs_encoders_simulate.py b/seam/routes/acs_encoders_simulate.py index e9c5653a..02553872 100644 --- a/seam/routes/acs_encoders_simulate.py +++ b/seam/routes/acs_encoders_simulate.py @@ -89,7 +89,7 @@ def next_credential_encode_will_fail( :param acs_credential_id: ID of the ``acs_credential`` that will fail to be encoded onto a card in the next request. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id @@ -112,7 +112,7 @@ def next_credential_encode_will_succeed( :param acs_encoder_id: ID of the ``acs_encoder`` that will be used in the next request to encode the ``acs_credential``. :param scenario: Scenario to simulate.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id @@ -140,7 +140,7 @@ def next_credential_scan_will_fail( :param error_code: :param acs_credential_id_on_seam:""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id @@ -169,7 +169,7 @@ def next_credential_scan_will_succeed( :param acs_credential_id_on_seam: ID of the Seam ``acs_credential`` that matches the ``acs_credential`` on the encoder in this simulation. :param scenario: Scenario to simulate.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_encoder_id is not None: json_payload["acs_encoder_id"] = acs_encoder_id diff --git a/seam/routes/acs_entrances.py b/seam/routes/acs_entrances.py index 30d38cf2..71b462ba 100644 --- a/seam/routes/acs_entrances.py +++ b/seam/routes/acs_entrances.py @@ -121,7 +121,7 @@ def get(self, *, acs_entrance_id: str) -> AcsEntrance: :param acs_entrance_id: ID of the entrance that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_id is not None: json_payload["acs_entrance_id"] = acs_entrance_id @@ -145,7 +145,7 @@ def grant_access( :param user_identity_id: ID of the user identity to whom you want to grant access to an entrance. You can only provide one of acs_user_id or user_identity_id. If the ACS system contains an ACS user with the same ``email_address`` or ``phone_number`` as the user identity that you specify, they are linked, and the access group membership belongs to the ACS user. If the ACS system does not have a corresponding ACS user, one is created. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_id is not None: json_payload["acs_entrance_id"] = acs_entrance_id @@ -198,7 +198,7 @@ def list( :param space_id: ID of the space for which you want to list entrances. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_method_id is not None: json_payload["access_method_id"] = access_method_id @@ -237,7 +237,7 @@ def list_credentials_with_access( :param include_if: Conditions that credentials must meet to be included in the returned list. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_id is not None: json_payload["acs_entrance_id"] = acs_entrance_id @@ -266,7 +266,7 @@ def unlock( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id diff --git a/seam/routes/acs_systems.py b/seam/routes/acs_systems.py index 4e582c1d..144a0c86 100644 --- a/seam/routes/acs_systems.py +++ b/seam/routes/acs_systems.py @@ -78,7 +78,7 @@ def get(self, *, acs_system_id: str) -> AcsSystem: :param acs_system_id: ID of the access system that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -105,7 +105,7 @@ def list( :param search: String for which to search. Filters returned access systems to include all records that satisfy a partial match using ``name`` or ``acs_system_id``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id @@ -128,7 +128,7 @@ def list_compatible_credential_manager_acs_systems( :param acs_system_id: ID of the access system for which you want to retrieve all compatible credential manager systems. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -154,7 +154,7 @@ def report_devices( :param acs_encoders: Array of ACS encoders to report :param acs_entrances: Array of ACS entrances to report""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id diff --git a/seam/routes/acs_users.py b/seam/routes/acs_users.py index e5567333..7f57044e 100644 --- a/seam/routes/acs_users.py +++ b/seam/routes/acs_users.py @@ -265,7 +265,7 @@ def add_to_access_group( :param acs_user_id: ID of the access system user that you want to add to an access group. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -307,7 +307,7 @@ def create( :param user_identity_id: ID of the user identity with which you want to associate the new access system user. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -345,7 +345,7 @@ def delete( :param user_identity_id: ID of the user identity that you want to delete. You must provide either acs_user_id or user_identity_id. If you provide user_identity_id, you must also provide acs_system_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -374,7 +374,7 @@ def get( :param user_identity_id: ID of the user identity that you want to get. You can only provide acs_user_id or user_identity_id. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_user_id is not None: json_payload["acs_user_id"] = acs_user_id @@ -418,7 +418,7 @@ def list( :param user_identity_phone_number: Phone number of the user identity for which you want to retrieve all access system users, in `E.164 format `_ (for example, ``+15555550100``). :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -457,7 +457,7 @@ def list_accessible_entrances( :param user_identity_id: ID of the user identity for whom you want to list accessible entrances. You can only provide acs_user_id or user_identity_id. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -487,7 +487,7 @@ def remove_from_access_group( :param user_identity_id: ID of the user identity that you want to remove from an access group. You can only provide acs_user_id or user_identity_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_access_group_id is not None: json_payload["acs_access_group_id"] = acs_access_group_id @@ -515,7 +515,7 @@ def revoke_access_to_all_entrances( :param user_identity_id: ID of the user identity for whom you want to revoke access. You can only provide acs_user_id or user_identity_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -543,7 +543,7 @@ def suspend( :param user_identity_id: ID of the user identity that you want to suspend. You can only provide acs_user_id or the combination of acs_system_id and user_identity_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -571,7 +571,7 @@ def unsuspend( :param user_identity_id: ID of the user identity that you want to unsuspend. You can only provide acs_user_id or the combination of acs_system_id and user_identity_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_id is not None: json_payload["acs_system_id"] = acs_system_id @@ -617,7 +617,7 @@ def update( :param user_identity_id: ID of the user identity that you want to update. You can only provide acs_user_id or user_identity_id. If you provide user_identity_id, you must also provide acs_system_id. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if access_schedule is not None: json_payload["access_schedule"] = access_schedule diff --git a/seam/routes/action_attempts.py b/seam/routes/action_attempts.py index f1291ddf..310ff7ca 100644 --- a/seam/routes/action_attempts.py +++ b/seam/routes/action_attempts.py @@ -64,7 +64,7 @@ def get( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if action_attempt_id is not None: json_payload["action_attempt_id"] = action_attempt_id @@ -102,7 +102,7 @@ def list( :param page_cursor: Identifies the specific page of results to return, obtained from the previous page's ``next_page_cursor``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if action_attempt_ids is not None: json_payload["action_attempt_ids"] = action_attempt_ids diff --git a/seam/routes/client_sessions.py b/seam/routes/client_sessions.py index 5e318cc1..80ab10f6 100644 --- a/seam/routes/client_sessions.py +++ b/seam/routes/client_sessions.py @@ -189,7 +189,7 @@ def create( :param user_identity_ids: Deprecated: Use ``user_identity_id`` instead. IDs of the `user identities `_ that you want to associate with the client session. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_ids is not None: json_payload["connect_webview_ids"] = connect_webview_ids @@ -216,7 +216,7 @@ def delete(self, *, client_session_id: str) -> None: """Deletes a `client session `_. :param client_session_id: ID of the client session that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if client_session_id is not None: json_payload["client_session_id"] = client_session_id @@ -238,7 +238,7 @@ def get( :param user_identifier_key: User identifier key associated with the client session that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if client_session_id is not None: json_payload["client_session_id"] = client_session_id @@ -274,7 +274,7 @@ def get_or_create( :param user_identity_ids: Deprecated: Use ``user_identity_id``. IDs of the `user identities `_ that you want to associate with the client session. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_ids is not None: json_payload["connect_webview_ids"] = connect_webview_ids @@ -317,7 +317,7 @@ def grant_access( :param user_identity_ids: Deprecated: Use ``user_identity_id``. IDs of the `user identities `_ that you want to associate with the client session. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if client_session_id is not None: json_payload["client_session_id"] = client_session_id @@ -358,7 +358,7 @@ def list( :param without_user_identifier_key: Indicates whether to retrieve only client sessions without associated user identifier keys. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if client_session_id is not None: json_payload["client_session_id"] = client_session_id @@ -381,7 +381,7 @@ def revoke(self, *, client_session_id: str) -> None: Note that `deleting a client session `_ is a separate action. :param client_session_id: ID of the client session that you want to revoke.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if client_session_id is not None: json_payload["client_session_id"] = client_session_id diff --git a/seam/routes/connect_webviews.py b/seam/routes/connect_webviews.py index 44cd32ad..bb9a7ca6 100644 --- a/seam/routes/connect_webviews.py +++ b/seam/routes/connect_webviews.py @@ -149,7 +149,7 @@ def create( :param wait_for_device_creation: Indicates whether Seam should finish syncing all devices in a newly-connected account before completing the associated Connect Webview. See also: `Customize the Behavior Settings of Your Connect Webviews `_. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if accepted_capabilities is not None: json_payload["accepted_capabilities"] = accepted_capabilities @@ -184,7 +184,7 @@ def delete(self, *, connect_webview_id: str) -> None: You do not need to delete a Connect Webview once a user completes it. Instead, you can simply ignore completed Connect Webviews. :param connect_webview_id: ID of the Connect Webview that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id @@ -201,7 +201,7 @@ def get(self, *, connect_webview_id: str) -> ConnectWebview: :param connect_webview_id: ID of the Connect Webview that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id @@ -235,7 +235,7 @@ def list( :param user_identifier_key: Your user ID for the user by which you want to filter Connect Webviews. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if custom_metadata_has is not None: json_payload["custom_metadata_has"] = custom_metadata_has diff --git a/seam/routes/connected_accounts.py b/seam/routes/connected_accounts.py index fbd82829..16e9eafc 100644 --- a/seam/routes/connected_accounts.py +++ b/seam/routes/connected_accounts.py @@ -126,7 +126,7 @@ def delete(self, *, connected_account_id: str) -> None: :param connected_account_id: ID of the connected account that you want to delete. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id @@ -145,7 +145,7 @@ def get( :param email: Email address associated with the connected account that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id @@ -184,7 +184,7 @@ def list( :param user_identifier_key: Your user ID for the user by which you want to filter connected accounts. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if custom_metadata_has is not None: json_payload["custom_metadata_has"] = custom_metadata_has @@ -210,7 +210,7 @@ def sync(self, *, connected_account_id: str) -> None: :param connected_account_id: ID of the connected account that you want to sync. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id @@ -243,7 +243,7 @@ def update( :param display_name: Human-readable name for the connected account, shown in the dashboard. For example, ``Booking from Airbnb House 1``. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id diff --git a/seam/routes/connected_accounts_simulate.py b/seam/routes/connected_accounts_simulate.py index 3766b03b..a53f14d6 100644 --- a/seam/routes/connected_accounts_simulate.py +++ b/seam/routes/connected_accounts_simulate.py @@ -24,7 +24,7 @@ def disconnect(self, *, connected_account_id: str) -> None: :param connected_account_id: ID of the connected account you want to simulate as disconnected. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id diff --git a/seam/routes/customers.py b/seam/routes/customers.py index 26ddfa92..dc465914 100644 --- a/seam/routes/customers.py +++ b/seam/routes/customers.py @@ -229,7 +229,7 @@ def create_portal( :param customer_data: :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if customer_resources_filters is not None: json_payload["customer_resources_filters"] = customer_resources_filters @@ -321,7 +321,7 @@ def delete_data( :param user_identity_keys: List of user identity keys to delete. :param user_keys: List of user keys to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_grant_keys is not None: json_payload["access_grant_keys"] = access_grant_keys @@ -431,7 +431,7 @@ def push_data( :param user_identities: List of user identities. :param users: List of users.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if customer_key is not None: json_payload["customer_key"] = customer_key diff --git a/seam/routes/devices.py b/seam/routes/devices.py index fcec08c9..f11e77f0 100644 --- a/seam/routes/devices.py +++ b/seam/routes/devices.py @@ -169,7 +169,7 @@ def get( :param name: Name of the device that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -235,7 +235,7 @@ def list( :param user_identifier_key: Your own internal user ID for the user for which you want to list devices. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id @@ -286,7 +286,7 @@ def list_device_providers( :param provider_category: Category for which you want to list providers. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if provider_category is not None: json_payload["provider_category"] = provider_category @@ -299,7 +299,7 @@ def report_provider_metadata(self, *, devices: List[Dict[str, Any]]) -> None: """Updates provider-specific metadata for devices. :param devices: Array of devices with provider metadata to update""" - json_payload = {} + json_payload: Dict[str, Any] = {} if devices is not None: json_payload["devices"] = devices @@ -333,7 +333,7 @@ def update( :param name: Name for the device. :param properties:""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/devices_simulate.py b/seam/routes/devices_simulate.py index 2ebaa239..29a49bc3 100644 --- a/seam/routes/devices_simulate.py +++ b/seam/routes/devices_simulate.py @@ -72,7 +72,7 @@ def connect(self, *, device_id: str) -> None: :param device_id: ID of the device that you want to simulate connecting to Seam. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -88,7 +88,7 @@ def connect_to_hub(self, *, device_id: str) -> None: This will clear the ``hub_disconnected`` error on the device. :param device_id: ID of the device whose hub you want to reconnect.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -102,7 +102,7 @@ def disconnect(self, *, device_id: str) -> None: :param device_id: ID of the device that you want to simulate disconnecting from Seam. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -119,7 +119,7 @@ def disconnect_from_hub(self, *, device_id: str) -> None: IglooHome bridge offline in sandbox. :param device_id: ID of the device whose hub you want to disconnect.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -136,7 +136,7 @@ def paid_subscription(self, *, device_id: str, is_expired: bool) -> None: :param device_id: :param is_expired:""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -152,7 +152,7 @@ def remove(self, *, device_id: str) -> None: :param device_id: ID of the device that you want to simulate removing from Seam. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/devices_unmanaged.py b/seam/routes/devices_unmanaged.py index 8da04525..d7c6e9c1 100644 --- a/seam/routes/devices_unmanaged.py +++ b/seam/routes/devices_unmanaged.py @@ -123,7 +123,7 @@ def get( :param name: Name of the unmanaged device that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -191,7 +191,7 @@ def list( :param user_identifier_key: Your own internal user ID for the user for which you want to list devices. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id @@ -247,7 +247,7 @@ def update( :param is_managed: Indicates whether the device is managed. Set this parameter to ``true`` to convert an unmanaged device to managed. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/events.py b/seam/routes/events.py index eb624c73..639fbb7b 100644 --- a/seam/routes/events.py +++ b/seam/routes/events.py @@ -141,7 +141,7 @@ def get( :param event_type: Type of the event that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if event_id is not None: json_payload["event_id"] = event_id @@ -245,7 +245,7 @@ def list( :param user_identity_id: ID of the user identity for which you want to list events. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if access_code_id is not None: json_payload["access_code_id"] = access_code_id diff --git a/seam/routes/instant_keys.py b/seam/routes/instant_keys.py index d9af3a77..bf3ab433 100644 --- a/seam/routes/instant_keys.py +++ b/seam/routes/instant_keys.py @@ -48,7 +48,7 @@ def delete(self, *, instant_key_id: str) -> None: """Deletes a specified `Instant Key `_. :param instant_key_id: ID of the Instant Key that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if instant_key_id is not None: json_payload["instant_key_id"] = instant_key_id @@ -70,7 +70,7 @@ def get( :param instant_key_url: URL of the instant key to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if instant_key_id is not None: json_payload["instant_key_id"] = instant_key_id @@ -87,7 +87,7 @@ def list(self, *, user_identity_id: Optional[str] = None) -> List[InstantKey]: :param user_identity_id: ID of the user identity by which you want to filter the list of Instant Keys. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id diff --git a/seam/routes/locks.py b/seam/routes/locks.py index e1f168a5..effc53d1 100644 --- a/seam/routes/locks.py +++ b/seam/routes/locks.py @@ -171,7 +171,7 @@ def configure_auto_lock( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if auto_lock_enabled is not None: json_payload["auto_lock_enabled"] = auto_lock_enabled @@ -207,7 +207,7 @@ def get( .. deprecated:: Use ``/devices/get`` instead.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -273,7 +273,7 @@ def list( :param user_identifier_key: Your own internal user ID for the user for which you want to list devices. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id @@ -325,7 +325,7 @@ def lock_door( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -357,7 +357,7 @@ def unlock_door( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/locks_simulate.py b/seam/routes/locks_simulate.py index 66fde77e..d53fe3e0 100644 --- a/seam/routes/locks_simulate.py +++ b/seam/routes/locks_simulate.py @@ -64,7 +64,7 @@ def keypad_code_entry( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if code is not None: json_payload["code"] = code @@ -98,7 +98,7 @@ def manual_lock_via_keypad( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/noise_sensors.py b/seam/routes/noise_sensors.py index 7c2b517b..598ce75e 100644 --- a/seam/routes/noise_sensors.py +++ b/seam/routes/noise_sensors.py @@ -152,7 +152,7 @@ def list( :param user_identifier_key: Your own internal user ID for the user for which you want to list devices. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id diff --git a/seam/routes/noise_sensors_noise_thresholds.py b/seam/routes/noise_sensors_noise_thresholds.py index 5b62e1ce..80d5e996 100644 --- a/seam/routes/noise_sensors_noise_thresholds.py +++ b/seam/routes/noise_sensors_noise_thresholds.py @@ -122,7 +122,7 @@ def create( :param noise_threshold_nrs: Noise level in Noiseaware Noise Risk Score (NRS) for the new noise threshold. This parameter is only relevant for `Noiseaware sensors `_. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -149,7 +149,7 @@ def delete(self, *, device_id: str, noise_threshold_id: str) -> None: :param device_id: ID of the device that contains the noise threshold that you want to delete. :param noise_threshold_id: ID of the noise threshold that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -166,7 +166,7 @@ def get(self, *, noise_threshold_id: str) -> NoiseThreshold: :param noise_threshold_id: ID of the noise threshold that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if noise_threshold_id is not None: json_payload["noise_threshold_id"] = noise_threshold_id @@ -181,7 +181,7 @@ def list(self, *, device_id: str) -> List[NoiseThreshold]: :param device_id: ID of the device for which you want to list noise thresholds. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -219,7 +219,7 @@ def update( :param starts_daily_at: Time at which the noise threshold should become active daily. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/noise_sensors_simulate.py b/seam/routes/noise_sensors_simulate.py index 1ce320f2..445ae5ca 100644 --- a/seam/routes/noise_sensors_simulate.py +++ b/seam/routes/noise_sensors_simulate.py @@ -24,7 +24,7 @@ def trigger_noise_threshold(self, *, device_id: str) -> None: :param device_id: ID of the device for which you want to simulate the triggering of a noise threshold. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/phones.py b/seam/routes/phones.py index 1ea284cc..cc39e6d5 100644 --- a/seam/routes/phones.py +++ b/seam/routes/phones.py @@ -59,7 +59,7 @@ def deactivate(self, *, device_id: str) -> None: """Deactivates a phone, which is useful, for example, if a user has lost their phone. For more information, see `App User Lost Phone Process `_. :param device_id: Device ID of the phone that you want to deactivate.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -74,7 +74,7 @@ def get(self, *, device_id: str) -> Phone: :param device_id: Device ID of the phone that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -96,7 +96,7 @@ def list( :param owner_user_identity_id: ID of the user identity that represents the owner by which you want to filter the list of returned phones. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_credential_id is not None: json_payload["acs_credential_id"] = acs_credential_id diff --git a/seam/routes/phones_simulate.py b/seam/routes/phones_simulate.py index b11b693a..a1b7af2f 100644 --- a/seam/routes/phones_simulate.py +++ b/seam/routes/phones_simulate.py @@ -53,7 +53,7 @@ def create_sandbox_phone( :param phone_metadata: Metadata that you want to associate with the simulated phone. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id diff --git a/seam/routes/spaces.py b/seam/routes/spaces.py index 1add7f83..34e6f995 100644 --- a/seam/routes/spaces.py +++ b/seam/routes/spaces.py @@ -206,7 +206,7 @@ def add_acs_entrances(self, *, acs_entrance_ids: List[str], space_id: str) -> No :param acs_entrance_ids: IDs of the entrances that you want to add to the space. :param space_id: ID of the space to which you want to add entrances.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_ids is not None: json_payload["acs_entrance_ids"] = acs_entrance_ids @@ -226,7 +226,7 @@ def add_connected_account( :param space_id: ID of the space to which you want to add the connected account. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id @@ -243,7 +243,7 @@ def add_devices(self, *, device_ids: List[str], space_id: str) -> None: :param device_ids: IDs of the devices that you want to add to the space. :param space_id: ID of the space to which you want to add devices.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_ids is not None: json_payload["device_ids"] = device_ids @@ -282,7 +282,7 @@ def create( :param space_key: Unique key for the space within the workspace. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if name is not None: json_payload["name"] = name @@ -307,7 +307,7 @@ def delete(self, *, space_id: str) -> None: """Deletes a space. :param space_id: ID of the space that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if space_id is not None: json_payload["space_id"] = space_id @@ -326,7 +326,7 @@ def get( :param space_key: Unique key of the space that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if space_id is not None: json_payload["space_id"] = space_id @@ -356,7 +356,7 @@ def get_related( :param space_keys: Keys of the spaces that you want to get along with their related resources. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if exclude is not None: json_payload["exclude"] = exclude @@ -393,7 +393,7 @@ def list( :param space_key: Filter spaces by space_key. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if customer_key is not None: json_payload["customer_key"] = customer_key @@ -418,7 +418,7 @@ def remove_acs_entrances( :param acs_entrance_ids: IDs of the entrances that you want to remove from the space. :param space_id: ID of the space from which you want to remove entrances.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_ids is not None: json_payload["acs_entrance_ids"] = acs_entrance_ids @@ -438,7 +438,7 @@ def remove_connected_account( :param space_id: ID of the space from which you want to remove the connected account. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connected_account_id is not None: json_payload["connected_account_id"] = connected_account_id @@ -455,7 +455,7 @@ def remove_devices(self, *, device_ids: List[str], space_id: str) -> None: :param device_ids: IDs of the devices that you want to remove from the space. :param space_id: ID of the space from which you want to remove devices.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_ids is not None: json_payload["device_ids"] = device_ids @@ -491,7 +491,7 @@ def update( :param space_key: Unique key of the space that you want to update. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_entrance_ids is not None: json_payload["acs_entrance_ids"] = acs_entrance_ids diff --git a/seam/routes/thermostats.py b/seam/routes/thermostats.py index 2008310d..338fcfd0 100644 --- a/seam/routes/thermostats.py +++ b/seam/routes/thermostats.py @@ -458,7 +458,7 @@ def activate_climate_preset( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if climate_preset_key is not None: json_payload["climate_preset_key"] = climate_preset_key @@ -500,7 +500,7 @@ def cool( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -565,7 +565,7 @@ def create_climate_preset( :param name: User-friendly name to identify the `climate preset `_. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if climate_preset_key is not None: json_payload["climate_preset_key"] = climate_preset_key @@ -603,7 +603,7 @@ def delete_climate_preset(self, *, climate_preset_key: str, device_id: str) -> N :param device_id: ID of the thermostat device for which you want to delete a climate preset. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if climate_preset_key is not None: json_payload["climate_preset_key"] = climate_preset_key @@ -633,7 +633,7 @@ def heat( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -681,7 +681,7 @@ def heat_cool( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -763,7 +763,7 @@ def list( :param user_identifier_key: Your own internal user ID for the user for which you want to list devices. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_webview_id is not None: json_payload["connect_webview_id"] = connect_webview_id @@ -815,7 +815,7 @@ def off( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -843,7 +843,7 @@ def set_fallback_climate_preset( :param device_id: ID of the thermostat device for which you want to set the fallback climate preset. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if climate_preset_key is not None: json_payload["climate_preset_key"] = climate_preset_key @@ -873,7 +873,7 @@ def set_fan_mode( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -924,7 +924,7 @@ def set_hvac_mode( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -974,7 +974,7 @@ def set_temperature_threshold( :param upper_limit_fahrenheit: Upper temperature limit in in °C. Seam alerts you if the reported temperature is higher than this value. You can specify either ``upper_limit`` but not both. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -1033,7 +1033,7 @@ def update_climate_preset( :param name: User-friendly name to identify the `climate preset `_. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if climate_preset_key is not None: json_payload["climate_preset_key"] = climate_preset_key @@ -1098,7 +1098,7 @@ def update_weekly_program( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/thermostats_daily_programs.py b/seam/routes/thermostats_daily_programs.py index 5ce877ae..d1662efe 100644 --- a/seam/routes/thermostats_daily_programs.py +++ b/seam/routes/thermostats_daily_programs.py @@ -70,7 +70,7 @@ def create( :param periods: Array of thermostat daily program periods. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -88,7 +88,7 @@ def delete(self, *, thermostat_daily_program_id: str) -> None: :param thermostat_daily_program_id: ID of the thermostat daily program that you want to delete. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if thermostat_daily_program_id is not None: json_payload["thermostat_daily_program_id"] = thermostat_daily_program_id @@ -116,7 +116,7 @@ def update( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if name is not None: json_payload["name"] = name diff --git a/seam/routes/thermostats_schedules.py b/seam/routes/thermostats_schedules.py index 6acd9c91..3b6d2340 100644 --- a/seam/routes/thermostats_schedules.py +++ b/seam/routes/thermostats_schedules.py @@ -131,7 +131,7 @@ def create( :param name: Name of the thermostat schedule. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if climate_preset_key is not None: json_payload["climate_preset_key"] = climate_preset_key @@ -157,7 +157,7 @@ def delete(self, *, thermostat_schedule_id: str) -> None: :param thermostat_schedule_id: ID of the thermostat schedule that you want to delete. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if thermostat_schedule_id is not None: json_payload["thermostat_schedule_id"] = thermostat_schedule_id @@ -172,7 +172,7 @@ def get(self, *, thermostat_schedule_id: str) -> ThermostatSchedule: :param thermostat_schedule_id: ID of the thermostat schedule that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if thermostat_schedule_id is not None: json_payload["thermostat_schedule_id"] = thermostat_schedule_id @@ -191,7 +191,7 @@ def list( :param user_identifier_key: User identifier key by which to filter the list of returned thermostat schedules. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -231,7 +231,7 @@ def update( :param starts_at: Date and time at which the thermostat schedule starts, in `ISO 8601 `_ format. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if thermostat_schedule_id is not None: json_payload["thermostat_schedule_id"] = thermostat_schedule_id diff --git a/seam/routes/thermostats_simulate.py b/seam/routes/thermostats_simulate.py index ae488ec5..8695b23f 100644 --- a/seam/routes/thermostats_simulate.py +++ b/seam/routes/thermostats_simulate.py @@ -80,7 +80,7 @@ def hvac_mode_adjusted( :param heating_set_point_fahrenheit: Heating `set point `_ in °F that you want to simulate. You must set ``heating_set_point_fahrenheit`` or ``heating_set_point_celsius``. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -114,7 +114,7 @@ def temperature_reached( :param temperature_fahrenheit: Temperature in °F that you want simulate the thermostat reaching. You must set ``temperature_fahrenheit`` or ``temperature_celsius``. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id diff --git a/seam/routes/user_identities.py b/seam/routes/user_identities.py index f6d140bc..948620fe 100644 --- a/seam/routes/user_identities.py +++ b/seam/routes/user_identities.py @@ -258,7 +258,7 @@ def add_acs_user( :param user_identity_key: Key of the user identity to which you want to add an access system user. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_user_id is not None: json_payload["acs_user_id"] = acs_user_id @@ -293,7 +293,7 @@ def create( :param user_identity_key: Unique key for the new user identity. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_system_ids is not None: json_payload["acs_system_ids"] = acs_system_ids @@ -314,7 +314,7 @@ def delete(self, *, user_identity_id: str) -> None: """Deletes a specified `user identity `_. This deletes the user identity and all associated resources, including any `credentials `_, `acs users `_ and `client sessions `_. :param user_identity_id: ID of the user identity that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -339,7 +339,7 @@ def generate_instant_key( :param max_use_count: Maximum number of times the instant key can be used. Default: 1. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -367,7 +367,7 @@ def get( :param user_identity_key: :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -385,7 +385,7 @@ def grant_access_to_device(self, *, device_id: str, user_identity_id: str) -> No :param user_identity_id: ID of the user identity that you want to grant access to a device. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -421,7 +421,7 @@ def list( :param user_identity_ids: Array of user identity IDs by which to filter the list of user identities. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if created_before is not None: json_payload["created_before"] = created_before @@ -448,7 +448,7 @@ def list_accessible_devices(self, *, user_identity_id: str) -> List[Device]: :param user_identity_id: ID of the user identity for which you want to retrieve all accessible devices. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -465,7 +465,7 @@ def list_accessible_entrances(self, *, user_identity_id: str) -> List[AcsEntranc :param user_identity_id: ID of the user identity for which you want to retrieve all accessible entrances. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -482,7 +482,7 @@ def list_acs_systems(self, *, user_identity_id: str) -> List[AcsSystem]: :param user_identity_id: ID of the user identity for which you want to retrieve all access systems. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -497,7 +497,7 @@ def list_acs_users(self, *, user_identity_id: str) -> List[AcsUser]: :param user_identity_id: ID of the user identity for which you want to retrieve all access system users. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -513,7 +513,7 @@ def remove_acs_user(self, *, acs_user_id: str, user_identity_id: str) -> None: :param user_identity_id: ID of the user identity from which you want to remove an access system user. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if acs_user_id is not None: json_payload["acs_user_id"] = acs_user_id @@ -531,7 +531,7 @@ def revoke_access_to_device(self, *, device_id: str, user_identity_id: str) -> N :param user_identity_id: ID of the user identity from which you want to revoke access to a device. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if device_id is not None: json_payload["device_id"] = device_id @@ -562,7 +562,7 @@ def update( :param phone_number: Unique phone number for the user identity. :param user_identity_key: Unique key for the user identity.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id diff --git a/seam/routes/user_identities_unmanaged.py b/seam/routes/user_identities_unmanaged.py index c5109c2c..f4de6364 100644 --- a/seam/routes/user_identities_unmanaged.py +++ b/seam/routes/user_identities_unmanaged.py @@ -69,7 +69,7 @@ def get(self, *, user_identity_id: str) -> UnmanagedUserIdentity: :param user_identity_id: ID of the unmanaged user identity that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if user_identity_id is not None: json_payload["user_identity_id"] = user_identity_id @@ -97,7 +97,7 @@ def list( :param search: String for which to search. Filters returned unmanaged user identities to include all records that satisfy a partial match using ``full_name``, ``phone_number``, ``email_address``, ``user_identity_id`` or ``acs_system_id``. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if created_before is not None: json_payload["created_before"] = created_before @@ -131,7 +131,7 @@ def update( :param user_identity_key: Unique key for the user identity. If not provided, the existing key will be preserved. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if is_managed is not None: json_payload["is_managed"] = is_managed diff --git a/seam/routes/webhooks.py b/seam/routes/webhooks.py index 444bed45..b82cd1fa 100644 --- a/seam/routes/webhooks.py +++ b/seam/routes/webhooks.py @@ -63,7 +63,7 @@ def create(self, *, url: str, event_types: Optional[List[str]] = None) -> Webhoo :param event_types: Types of events that you want the new webhook to receive. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if url is not None: json_payload["url"] = url @@ -78,7 +78,7 @@ def delete(self, *, webhook_id: str) -> None: """Deletes a specified `webhook `_. :param webhook_id: ID of the webhook that you want to delete.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if webhook_id is not None: json_payload["webhook_id"] = webhook_id @@ -93,7 +93,7 @@ def get(self, *, webhook_id: str) -> Webhook: :param webhook_id: ID of the webhook that you want to get. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if webhook_id is not None: json_payload["webhook_id"] = webhook_id @@ -106,7 +106,7 @@ def list(self) -> List[Webhook]: """Returns a list of all `webhooks `_. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} res = self.client.post("/webhooks/list", json=json_payload) @@ -118,7 +118,7 @@ def update(self, *, event_types: List[str], webhook_id: str) -> None: :param event_types: Types of events that you want the webhook to receive. :param webhook_id: ID of the webhook that you want to update.""" - json_payload = {} + json_payload: Dict[str, Any] = {} if event_types is not None: json_payload["event_types"] = event_types diff --git a/seam/routes/workspaces.py b/seam/routes/workspaces.py index d223c346..4dd397d2 100644 --- a/seam/routes/workspaces.py +++ b/seam/routes/workspaces.py @@ -142,7 +142,7 @@ def create( :param webview_success_message: Deprecated: Use ``connect_webview_customization.webview_success_message`` instead. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} if name is not None: json_payload["name"] = name @@ -177,7 +177,7 @@ def get(self) -> Workspace: """Returns the `workspace `_ associated with the authentication value. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} res = self.client.post("/workspaces/get", json=json_payload) @@ -187,7 +187,7 @@ def list(self) -> List[Workspace]: """Returns a list of `workspaces `_ associated with the authentication value. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} res = self.client.post("/workspaces/list", json=json_payload) @@ -201,7 +201,7 @@ def reset_sandbox( :param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish. :returns: OK""" - json_payload = {} + json_payload: Dict[str, Any] = {} res = self.client.post("/workspaces/reset_sandbox", json=json_payload) @@ -241,7 +241,7 @@ def update( :param organization_id: ID of the organization to assign the workspace to. The authenticated user must be the owner of the workspace and an admin of the target organization. """ - json_payload = {} + json_payload: Dict[str, Any] = {} if connect_partner_name is not None: json_payload["connect_partner_name"] = connect_partner_name diff --git a/seam/seam.py b/seam/seam.py index 97442403..f552e36c 100644 --- a/seam/seam.py +++ b/seam/seam.py @@ -104,7 +104,10 @@ def __init__( niquests_options=niquests_options, ) - Routes.__init__(self, client=self.client, defaults=self.defaults) + # Seam and Routes are siblings under AbstractRoutes rather than parent + # and child, so borrowing this initializer to attach the route + # namespaces passes a self the signature does not admit. + Routes.__init__(self, client=self.client, defaults=self.defaults) # type: ignore[arg-type] def create_paginator( self, request: Callable, params: Optional[Dict[str, Any]] = None, / diff --git a/test/paginator_test.py b/test/paginator_test.py index 800cf78e..65af163b 100644 --- a/test/paginator_test.py +++ b/test/paginator_test.py @@ -14,7 +14,7 @@ def test_paginator_next_page_requires_a_cursor(seam: Seam): paginator = seam.create_paginator(seam.connected_accounts.list, {"limit": 2}) with pytest.raises(ValueError, match=r"next_page_cursor"): - paginator.next_page(None) + paginator.next_page(None) # type: ignore[arg-type] with pytest.raises(ValueError, match=r"next_page_cursor"): paginator.next_page("") @@ -24,8 +24,12 @@ def test_paginator_last_page_has_no_next_page(seam: Seam): paginator = seam.create_paginator(seam.connected_accounts.list, {"limit": 2}) _, first_pagination = paginator.first_page() + assert first_pagination is not None + assert first_pagination.next_page_cursor is not None + _, next_pagination = paginator.next_page(first_pagination.next_page_cursor) + assert next_pagination is not None assert next_pagination.has_next_page is False assert next_pagination.next_page_cursor is None @@ -47,7 +51,9 @@ def test_paginator_next_page(seam: Seam): first_page_accounts, first_pagination = paginator.first_page() assert len(first_page_accounts) == 2 + assert first_pagination is not None assert first_pagination.has_next_page is True + assert first_pagination.next_page_cursor is not None next_page_accounts, _ = paginator.next_page(first_pagination.next_page_cursor)