diff --git a/demos/python/sdk_wireless_camera_control/docs/api.rst b/demos/python/sdk_wireless_camera_control/docs/api.rst index cd685526..95b0bd35 100644 --- a/demos/python/sdk_wireless_camera_control/docs/api.rst +++ b/demos/python/sdk_wireless_camera_control/docs/api.rst @@ -76,6 +76,8 @@ These should not be imported directly and instead should be accessed using the r Base Types ---------- +.. automodule:: open_gopro.types + GoPro Enum ^^^^^^^^^^ @@ -173,6 +175,8 @@ These are the various models that are returned in responses, used in commands, e from open_gopro.models import *** +.. autopydantic_model:: open_gopro.models.media_list.MediaPath + .. autopydantic_model:: open_gopro.models.media_list.MediaMetadata .. autopydantic_model:: open_gopro.models.media_list.PhotoMetadata @@ -221,6 +225,8 @@ Exceptions Common Interface ================ +.. automodule:: open_gopro.parser_interface + .. autoclass:: open_gopro.gopro_base.GoProBase .. autoclass:: open_gopro.communicator_interface.GoProBle diff --git a/demos/python/sdk_wireless_camera_control/docs/conf.py b/demos/python/sdk_wireless_camera_control/docs/conf.py index 206edc0b..ce104d99 100644 --- a/demos/python/sdk_wireless_camera_control/docs/conf.py +++ b/demos/python/sdk_wireless_camera_control/docs/conf.py @@ -6,6 +6,11 @@ from open_gopro import WirelessGoPro +from sphinx.ext.intersphinx import missing_reference + +import open_gopro +import open_gopro.models + gopro = WirelessGoPro(enable_wifi=False) project = "Open GoPro Python SDK" @@ -23,8 +28,8 @@ "sphinx.ext.autosectionlabel", "sphinx.ext.graphviz", "sphinx.ext.inheritance_diagram", - # "sphinxemoji.sphinxemoji", # https://github.com/sphinx-contrib/emojicodes/issues/42 "sphinxcontrib.autodoc_pydantic", + "sphinx.ext.intersphinx", ] html_theme = "sphinx_rtd_theme" html_context = { @@ -39,6 +44,9 @@ # https://autodoc-pydantic.readthedocs.io/en/stable/users/installation.html#configuration autodoc_pydantic_model_show_json = True autodoc_pydantic_settings_show_json = False +intersphinx_mapping = { + "python": ("https://docs.python.org/3", None), +} # The version info for the project you're documenting, acts as replacement # for |version| and |release|, also used in various other places throughout @@ -51,52 +59,72 @@ nitpicky = True +TYPE_ALIASES = { + "CameraState": "open_gopro.types.CameraState", + "UpdateCb": "open_gopro.types.UpdateCb", + "UpdateType": "open_gopro.types.UpdateType", + "JsonDict": "open_gopro.JsonDict", + "ResponseType": "open_gopro.types.ResponseType", + "Protobuf": "open_gopro.types.Protobuf", + "IdType": "open_gopro.types.IdType", +} + +# This is very broken. +# https://github.com/sphinx-doc/sphinx/issues/10455 +# https://github.com/sphinx-doc/sphinx/issues/10785 # autodoc_type_aliases = { -# "IdType": "open_gopro.interface.IdType", -# "CommunicatorType": "open_gopro.interface.CommunicatorType", -# "ParserType": "open_gopro.interface.ParserType", -# "DisconnectHandlerType": "open_gopro.ble.controller.DisconnectHandlerType", -# "NotiHandlerType": "open_gopro.ble.controller.NotiHandlerType", -# "ValueType": "open_gopro.api.builders.ValueType", -# "BleDevice": "open_gopro.ble.controller.BleDevice", -# "BleHandle": "open_gopro.ble.controller.BleHandle", -# "CmdType": "open_gopro.constants.CmdType", -# "ResponseType": "open_gopro.constants.ResponseType", +# "CameraState": "open_gopro.types.CameraState", +# "Path": "pathlib.Path", # } nitpick_ignore = [ ("py:class", "T"), ("py:class", "T_co"), ("py:class", "ExceptionHandler"), - ("py:class", "datetime.datetime"), - ("py:class", "open_gopro.models.parsers.Parser"), ("py:class", "abc.ABC"), - ("py:class", "collections.abc.Iterable"), ] nitpick_ignore_regex = [ (r"py:class", r".*proto\..+"), # TODO how should / can we handle protobuf documenting? (r"py:class", r".*_pb2\..+"), - (r"py:class", r".+Type"), - (r"py:obj", r".+Type"), - (r"py:class", r".*Path"), - (r"py:class", r".*InitVar"), - (r"py:class", r".*UpdateCb"), - (r"py:class", r".*JsonDict"), - (r"py:class", r".*BleDevice"), - (r"py:class", r".*BleHandle"), - (r"py:class", r".*Parser"), - (r"py:class", r".*Builder"), (r".*", r".*construct.*"), - (r".*", r".*response.T*"), + # Generic Types that are pointless to document + (r"py:class", r".*\.T"), + (r"py:class", r".*\.T_co"), + (r"py:class", r".*BleHandle"), + (r"py:class", r".*BleDevice"), + (r"py:class", r".*CommunicatorType"), + (r"py:class", r".*NotiHandlerType"), + (r"py:obj", r".*CommunicatorType"), + (r"py:obj", r".*MessageType"), ] -# This is the expected signature of the handler for this event, cf doc def autodoc_skip_member_handler(app, what, name, *_): for skip in ("internal", "deprecated"): if skip in name.lower(): return name +def resolve_type_aliases(app, env, node, contnode): + """Resolve :class: references to our type aliases as :attr: instead.""" + try: + if node["refdomain"] == "py" and (target := TYPE_ALIASES.get(node["reftarget"])): + print(f"updating {node['reftarget']}") + return app.env.get_domain("py").resolve_any_xref( + env, + node["refdoc"], + app.builder, + target, + node, + contnode, + )[ + 0 + ][1] + except IndexError: + print("uhoh") + return None + + def setup(app): app.connect("autodoc-skip-member", autodoc_skip_member_handler) + app.connect("missing-reference", resolve_type_aliases) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py index 3dd8d643..71551e4d 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/ble_commands.py @@ -27,7 +27,7 @@ this, ) -from open_gopro import proto, types +from open_gopro import proto from open_gopro.api.builders import BleAsyncResponse from open_gopro.api.builders import BleSettingFacade as BleSetting from open_gopro.api.builders import BleStatusFacade as BleStatus @@ -56,7 +56,7 @@ from open_gopro.models import CameraInfo, TzDstDateTime from open_gopro.models.response import GlobalParsers, GoProResp from open_gopro.parser_interface import Parser -from open_gopro.types import CameraState +from open_gopro.types import CameraState, UpdateCb from . import params as Params @@ -344,11 +344,11 @@ async def get_wifi_password(self) -> GoProResp[str]: update_set=StatusId, action=RegisterUnregisterAll.Action.REGISTER, ) - async def register_for_all_statuses(self, callback: types.UpdateCb) -> GoProResp[None]: + async def register_for_all_statuses(self, callback: UpdateCb) -> GoProResp[None]: """Register push notifications for all statuses Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: command status and current value of all statuses @@ -360,11 +360,11 @@ async def register_for_all_statuses(self, callback: types.UpdateCb) -> GoProResp update_set=StatusId, action=RegisterUnregisterAll.Action.UNREGISTER, ) - async def unregister_for_all_statuses(self, callback: types.UpdateCb) -> GoProResp[None]: + async def unregister_for_all_statuses(self, callback: UpdateCb) -> GoProResp[None]: """Unregister push notifications for all statuses Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: command status @@ -376,11 +376,11 @@ async def unregister_for_all_statuses(self, callback: types.UpdateCb) -> GoProRe update_set=SettingId, action=RegisterUnregisterAll.Action.REGISTER, ) - async def register_for_all_settings(self, callback: types.UpdateCb) -> GoProResp[None]: + async def register_for_all_settings(self, callback: UpdateCb) -> GoProResp[None]: """Register push notifications for all settings Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: command status and current value of all settings @@ -392,11 +392,11 @@ async def register_for_all_settings(self, callback: types.UpdateCb) -> GoProResp update_set=SettingId, action=RegisterUnregisterAll.Action.UNREGISTER, ) - async def unregister_for_all_settings(self, callback: types.UpdateCb) -> GoProResp[None]: + async def unregister_for_all_settings(self, callback: UpdateCb) -> GoProResp[None]: """Unregister push notifications for all settings Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: command status @@ -408,11 +408,11 @@ async def unregister_for_all_settings(self, callback: types.UpdateCb) -> GoProRe update_set=SettingId, action=RegisterUnregisterAll.Action.REGISTER, ) - async def register_for_all_capabilities(self, callback: types.UpdateCb) -> GoProResp[None]: + async def register_for_all_capabilities(self, callback: UpdateCb) -> GoProResp[None]: """Register push notifications for all capabilities Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: command status and current value of all capabilities @@ -424,11 +424,11 @@ async def register_for_all_capabilities(self, callback: types.UpdateCb) -> GoPro update_set=SettingId, action=RegisterUnregisterAll.Action.UNREGISTER, ) - async def unregister_for_all_capabilities(self, callback: types.UpdateCb) -> GoProResp[None]: + async def unregister_for_all_capabilities(self, callback: UpdateCb) -> GoProResp[None]: """Unregister push notifications for all capabilities Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: command status diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/builders.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/builders.py index 453b4442..d50a344c 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/builders.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/builders.py @@ -15,7 +15,6 @@ import construct import wrapt -from open_gopro import types from open_gopro.api.parsers import ByteParserBuilders from open_gopro.ble import BleUUID from open_gopro.communicator_interface import ( @@ -40,6 +39,7 @@ from open_gopro.logger import Logger from open_gopro.models.response import GlobalParsers, GoProResp from open_gopro.parser_interface import BytesBuilder, BytesParserBuilder, Parser +from open_gopro.types import CameraState, JsonDict, Protobuf, UpdateCb logger = logging.getLogger(__name__) @@ -71,14 +71,14 @@ def _build_data(self, **kwargs: Any) -> bytearray: def __str__(self) -> str: return f"Read {self._uuid.name.lower().replace('_', ' ').title()}" - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: """Return the attributes of the command as a dict Args: **kwargs (Any): additional entries for the dict Returns: - types.JsonDict: command as dict + JsonDict: command as dict """ return {"id": self._uuid, **self._base_dict} | kwargs @@ -123,14 +123,14 @@ def _build_data(self, **kwargs: Any) -> bytearray: def __str__(self) -> str: return self.cmd.name.lower().replace("_", " ").removeprefix("cmdid").title() - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: """Return the attributes of the command as a dict Args: **kwargs (Any): additional entries for the dict Returns: - types.JsonDict: command as dict + JsonDict: command as dict """ return {"id": self.cmd, **self._base_dict} | kwargs @@ -177,8 +177,8 @@ class BleProtoCommand(BleMessage): feature_id (FeatureId): Feature ID that is being executed action_id (ActionId): protobuf specific action ID that is being executed response_action_id (ActionId): the action ID that will be in the response to this command - request_proto (type[types.Protobuf]): the action ID that will be in the response - response_proto (type[types.Protobuf]): protobuf used to parse received bytestream + request_proto (type[Protobuf]): the action ID that will be in the response + response_proto (type[Protobuf]): protobuf used to parse received bytestream parser (Parser | None): Optional response parser. Defaults to None. additional_matching_ids (set[ActionId | CmdId] | None): Other action ID's to share this parser. This is used, for example, if a notification shares the same ID as the synchronous response. Defaults to None. Defaults to None. @@ -190,8 +190,8 @@ def __init__( feature_id: FeatureId, action_id: ActionId, response_action_id: ActionId, - request_proto: type[types.Protobuf], - response_proto: type[types.Protobuf], + request_proto: type[Protobuf], + response_proto: type[Protobuf], parser: Parser | None, additional_matching_ids: set[ActionId | CmdId] | None = None, ) -> None: @@ -237,14 +237,14 @@ def _build_data(self, **kwargs: Any) -> bytearray: def __str__(self) -> str: return self.action_id.name.lower().replace("_", " ").removeprefix("actionid").title() - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: """Return the attributes of the command as a dict Args: **kwargs (Any): additional entries for the dict Returns: - types.JsonDict: command as dict + JsonDict: command as dict """ return {"id": self.action_id, "feature_id": self.feature_id, **self._base_dict} | kwargs @@ -329,8 +329,8 @@ def ble_proto_command( feature_id: FeatureId, action_id: ActionId, response_action_id: ActionId, - request_proto: type[types.Protobuf], - response_proto: type[types.Protobuf], + request_proto: type[Protobuf], + response_proto: type[Protobuf], parser: Parser | None = None, additional_matching_ids: set[ActionId | CmdId] | None = None, ) -> Callable: @@ -341,8 +341,8 @@ def ble_proto_command( feature_id (FeatureId): Feature ID that is being executed action_id (ActionId): protobuf specific action ID that is being executed response_action_id (ActionId): the action ID that will be in the response to this command - request_proto (type[types.Protobuf]): the action ID that will be in the response - response_proto (type[types.Protobuf]): protobuf used to parse received bytestream + request_proto (type[Protobuf]): the action ID that will be in the response + response_proto (type[Protobuf]): protobuf used to parse received bytestream parser (Parser | None): Response parser to transform received Protobuf bytes. Defaults to None. additional_matching_ids (set[ActionId | CmdId] | None): Other action ID's to share this parser. This is used, for example, if a notification shares the same ID as the synchronous response. Defaults to None. @@ -431,13 +431,13 @@ def __init__( def _build_data(self, **kwargs: Any) -> bytearray: return self._build(**kwargs) - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: d = {"id": self._identifier, "setting_id": self._setting_id, **self._base_dict} | kwargs return d def __init__(self, communicator: GoProBle, identifier: SettingId, parser_builder: QueryParserType) -> None: # TODO abstract this - parser = Parser[types.CameraState]() + parser = Parser[CameraState]() if isinstance(parser_builder, construct.Construct): parser.byte_json_adapter = ByteParserBuilders.Construct(parser_builder) elif isinstance(parser_builder, BytesParserBuilder): @@ -541,11 +541,11 @@ async def get_capabilities_names(self) -> GoProResp[list[str]]: """ raise NotImplementedError("Not implemented on camera!") - async def register_value_update(self, callback: types.UpdateCb) -> GoProResp[None]: + async def register_value_update(self, callback: UpdateCb) -> GoProResp[None]: """Register for asynchronous notifications when a given setting ID's value updates. Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: Current value of respective setting ID @@ -560,11 +560,11 @@ async def register_value_update(self, callback: types.UpdateCb) -> GoProResp[Non self._communicator.register_update(callback, self._identifier) return response - async def unregister_value_update(self, callback: types.UpdateCb) -> GoProResp[None]: + async def unregister_value_update(self, callback: UpdateCb) -> GoProResp[None]: """Stop receiving notifications when a given setting ID's value updates. Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: Status of unregister @@ -579,11 +579,11 @@ async def unregister_value_update(self, callback: types.UpdateCb) -> GoProResp[N self._communicator.unregister_update(callback, self._identifier) return response - async def register_capability_update(self, callback: types.UpdateCb) -> GoProResp[None]: + async def register_capability_update(self, callback: UpdateCb) -> GoProResp[None]: """Register for asynchronous notifications when a given setting ID's capabilities update. Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: Current capabilities of respective setting ID @@ -598,11 +598,11 @@ async def register_capability_update(self, callback: types.UpdateCb) -> GoProRes self._communicator.unregister_update(callback, self._identifier) return response - async def unregister_capability_update(self, callback: types.UpdateCb) -> GoProResp[None]: + async def unregister_capability_update(self, callback: UpdateCb) -> GoProResp[None]: """Stop receiving notifications when a given setting ID's capabilities change. Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: Status of unregister @@ -659,12 +659,12 @@ def __init__( def _build_data(self, **kwargs: Any) -> bytearray: return self._build(self, **kwargs) - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: return {"id": self._identifier, "status_id": self._status_id, **self._base_dict} | kwargs def __init__(self, communicator: GoProBle, identifier: StatusId, parser: QueryParserType) -> None: # TODO abstract this - parser_builder = Parser[types.CameraState]() + parser_builder = Parser[CameraState]() # Is it a protobuf enum? if isinstance(parser, construct.Construct): parser_builder.byte_json_adapter = ByteParserBuilders.Construct(parser) @@ -696,11 +696,11 @@ async def get_value(self) -> GoProResp[ValueType]: ) return await self._communicator._send_ble_message(message) - async def register_value_update(self, callback: types.UpdateCb) -> GoProResp[ValueType]: + async def register_value_update(self, callback: UpdateCb) -> GoProResp[ValueType]: """Register for asynchronous notifications when a status changes. Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[ValueType]: current status value @@ -715,11 +715,11 @@ async def register_value_update(self, callback: types.UpdateCb) -> GoProResp[Val self._communicator.register_update(callback, self._identifier) return response - async def unregister_value_update(self, callback: types.UpdateCb) -> GoProResp[None]: + async def unregister_value_update(self, callback: UpdateCb) -> GoProResp[None]: """Stop receiving notifications when status changes. Args: - callback (types.UpdateCb): callback to be notified with + callback (UpdateCb): callback to be notified with Returns: GoProResp[None]: Status of unregister diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py index 2bb21f4f..af577f84 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/http_commands.py @@ -11,7 +11,7 @@ import logging from pathlib import Path -from open_gopro import proto, types +from open_gopro import proto from open_gopro.api.builders import ( HttpSetting, http_get_binary_command, @@ -30,6 +30,7 @@ from open_gopro.models.general import WebcamResponse from open_gopro.models.response import GoProResp from open_gopro.parser_interface import Parser +from open_gopro.types import CameraState, JsonDict from . import params as Params @@ -123,11 +124,11 @@ async def set_digital_zoom(self, *, percent: int) -> GoProResp[None]: parser=Parser(json_parser=JsonParsers.CameraStateParser()), rules=MessageRules(fastpass_analyzer=MessageRules.always_true), ) - async def get_camera_state(self) -> GoProResp[types.CameraState]: + async def get_camera_state(self) -> GoProResp[CameraState]: """Get all camera statuses and settings Returns: - GoProResp[types.CameraState]: status and settings as JSON + GoProResp[CameraState]: status and settings as JSON """ @http_get_json_command( @@ -199,11 +200,11 @@ async def get_open_gopro_api_version(self) -> GoProResp[str]: # TODO make pydantic model of preset status @http_get_json_command(endpoint="gopro/camera/presets/get") - async def get_preset_status(self) -> GoProResp[types.JsonDict]: + async def get_preset_status(self) -> GoProResp[JsonDict]: """Get status of current presets Returns: - GoProResp[types.JsonDict]: JSON describing currently available presets and preset groups + GoProResp[JsonDict]: JSON describing currently available presets and preset groups """ @http_get_json_command(endpoint="gopro/camera/presets/load", arguments=["id"]) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/parsers.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/parsers.py index 00c31f6b..ca17770c 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/parsers.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/parsers.py @@ -15,7 +15,6 @@ from google.protobuf.json_format import MessageToDict as ProtobufToDict from pydantic import BaseModel -from open_gopro import types from open_gopro.constants import SettingId, StatusId from open_gopro.enum import GoProIntEnum, enum_factory from open_gopro.parser_interface import ( @@ -26,6 +25,7 @@ JsonParser, JsonTransformer, ) +from open_gopro.types import CameraState, JsonDict, Protobuf, ResponseType from open_gopro.util import map_keys, pretty_print logger = logging.getLogger(__name__) @@ -49,11 +49,11 @@ class PydanticAdapter(JsonParser[BaseModel]): def __init__(self, model: type[BaseModel]) -> None: self.model = model - def parse(self, data: types.JsonDict) -> BaseModel: + def parse(self, data: JsonDict) -> BaseModel: """Parse json dict into model Args: - data (types.JsonDict): data to parse + data (JsonDict): data to parse Returns: BaseModel: parsed model @@ -64,17 +64,17 @@ class LambdaParser(JsonParser[T]): """Helper class to allow parser definition using a lambda Args: - parser (Callable[[types.JsonDict], T]): lambda to parse input + parser (Callable[[JsonDict], T]): lambda to parse input """ - def __init__(self, parser: Callable[[types.JsonDict], T]) -> None: + def __init__(self, parser: Callable[[JsonDict], T]) -> None: self._parser = parser - def parse(self, data: types.JsonDict) -> T: + def parse(self, data: JsonDict) -> T: """Use stored lambda parse for parsing Args: - data (types.JsonDict): input dict to parse + data (JsonDict): input dict to parse Returns: T: parsed output @@ -84,20 +84,20 @@ def parse(self, data: types.JsonDict) -> T: class CameraStateParser(JsonParser): """Parse integer numbers into Enums""" - def parse(self, data: types.JsonDict) -> types.CameraState: + def parse(self, data: JsonDict) -> CameraState: """Parse dict of integer values into human readable (i.e. enum'ed) setting / status map Args: - data (types.JsonDict): input dict to parse + data (JsonDict): input dict to parse Returns: - types.CameraState: output human readable dict + CameraState: output human readable dict """ parsed: dict = {} # Parse status and settings values into nice human readable things for name, id_map in [("status", StatusId), ("settings", SettingId)]: for k, v in data[name].items(): - identifier = cast(types.ResponseType, id_map(int(k))) + identifier = cast(ResponseType, id_map(int(k))) try: if not (parser_builder := GlobalParsers.get_query_container(identifier)): parsed[identifier] = v @@ -123,14 +123,14 @@ def __init__(self, key: str, func: Callable) -> None: self.func = func super().__init__() - def transform(self, data: types.JsonDict) -> types.JsonDict: + def transform(self, data: JsonDict) -> JsonDict: """Transform json, mapping keys Args: - data (types.JsonDict): json data to transform + data (JsonDict): json data to transform Returns: - types.JsonDict: transformed json data + JsonDict: transformed json data """ map_keys(data, self.key, self.func) return data @@ -215,10 +215,10 @@ class Protobuf(BytesParser): using the protobuf definition Args: - proto (type[types.Protobuf]): protobuf definition to parse (a proxy) into + proto (type[Protobuf]): protobuf definition to parse (a proxy) into """ - def __init__(self, proto: type[types.Protobuf]) -> None: + def __init__(self, proto: type[Protobuf]) -> None: class ProtobufByteParser(BytesParser[dict]): """Parse bytes into a dict using the protobuf""" @@ -226,7 +226,7 @@ class ProtobufByteParser(BytesParser[dict]): # pylint: disable=not-callable def parse(self, data: bytes) -> Any: - response: types.Protobuf = self.protobuf().FromString(bytes(data)) + response: Protobuf = self.protobuf().FromString(bytes(data)) # TODO can translate from Protobuf enums without relying on Protobuf internal implementation? # Monkey patch the field-to-json function to use our enum translation @@ -235,9 +235,7 @@ def parse(self, data: bytes) -> Any: if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_ENUM else original_field_to_json(self, field, value) ) - as_dict = ProtobufToDict( - response, including_default_value_fields=False, preserving_proto_field_name=True - ) + as_dict = ProtobufToDict(response, preserving_proto_field_name=True) # For any unset fields, use None for key in response.DESCRIPTOR.fields_by_name: if key not in as_dict: diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/services.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/services.py index 904a7812..63a2616a 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/services.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/services.py @@ -164,19 +164,19 @@ class Characteristic: handle (int) : the handle of the attribute table that the characteristic resides at uuid (BleUUID) : the BleUUID of the characteristic props (CharProps) : the characteristic's properties (READ, WRITE, NOTIFY, etc) - value (bytes) : the current byte stream value of the characteristic value - init_descriptors (Optional[list[Descriptor]]) : Descriptors known at initialization (can also be + value (bytes | None) : the current byte stream value of the characteristic value + init_descriptors (list[Descriptor] | None) : Descriptors known at initialization (can also be set later using the descriptors property) - descriptor_handle (Optional[int]) : handle of this characteristic's declaration descriptor. If not + descriptor_handle (int | None) : handle of this characteristic's declaration descriptor. If not passed, defaults to handle + 1 """ handle: int uuid: BleUUID props: CharProps - value: Optional[bytes] = None - init_descriptors: InitVar[Optional[list[Descriptor]]] = None - descriptor_handle: Optional[int] = None + value: bytes | None = None + init_descriptors: InitVar[list[Descriptor] | None] = None + descriptor_handle: int | None = None def __post_init__(self, init_descriptors: Optional[list[Descriptor]]) -> None: self._descriptors: dict[BleUUID, Descriptor] = {} @@ -371,8 +371,7 @@ def keys(self) -> Generator[BleUUID, None, None]: # noqa: D102 def iter_keys(): for service in self._db.services.values(): - for ble_uuid in service.characteristics.keys(): - yield ble_uuid + yield from service.characteristics.keys() return iter_keys() @@ -386,8 +385,7 @@ def values(self) -> Generator[Characteristic, None, None]: # noqa: D102 def iter_values(): for service in self._db.services.values(): - for char in service.characteristics.values(): - yield char + yield from service.characteristics.values() return iter_values() @@ -529,8 +527,7 @@ def __contains__(cls, key: Union[uuid.UUID, int, str]) -> bool: @no_type_check def __iter__(cls): - for item in cls._int2uuid.items(): - yield item + yield from cls._int2uuid.items() @dataclass(frozen=True) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/communicator_interface.py b/demos/python/sdk_wireless_camera_control/open_gopro/communicator_interface.py index 251cf0fe..ae67d446 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/communicator_interface.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/communicator_interface.py @@ -16,7 +16,6 @@ from construct import Bit, BitsInteger, BitStruct, Const, Construct, Padding -from open_gopro import types from open_gopro.ble import ( BleClient, BLEController, @@ -36,6 +35,7 @@ JsonTransformer, Parser, ) +from open_gopro.types import IdType, JsonDict, UpdateCb, UpdateType from open_gopro.wifi import WifiClient, WifiController logger = logging.getLogger(__name__) @@ -104,21 +104,21 @@ class BaseGoProCommunicator(ABC): """Common Communicator interface""" @abstractmethod - def register_update(self, callback: types.UpdateCb, update: types.UpdateType) -> None: + def register_update(self, callback: UpdateCb, update: UpdateType) -> None: """Register for callbacks when an update occurs Args: - callback (types.UpdateCb): callback to be notified in - update (types.UpdateType): update to register for + callback (UpdateCb): callback to be notified in + update (UpdateType): update to register for """ @abstractmethod - def unregister_update(self, callback: types.UpdateCb, update: types.UpdateType | None = None) -> None: + def unregister_update(self, callback: UpdateCb, update: UpdateType | None = None) -> None: """Unregister for asynchronous update(s) Args: - callback (types.UpdateCb): callback to stop receiving update(s) on - update (types.UpdateType | None): updates to unsubscribe for. Defaults to None (all + callback (UpdateCb): callback to stop receiving update(s) on + update (UpdateType | None): updates to unsubscribe for. Defaults to None (all updates that use this callback will be unsubscribed). """ @@ -360,21 +360,21 @@ class Message(ABC): def __init__( self, - identifier: types.IdType, + identifier: IdType, parser: Parser | None = None, ) -> None: - self._identifier: types.IdType = identifier + self._identifier: IdType = identifier self._parser = parser @abstractmethod - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: """Return the attributes of the message as a dict Args: **kwargs (Any): additional entries for the dict Returns: - types.JsonDict: message as dict + JsonDict: message as dict """ @@ -383,14 +383,14 @@ class BleMessage(Message): Args: uuid (BleUUID): BLE client to read / write - identifier (types.IdType): BleUUID to read / write to + identifier (IdType): BleUUID to read / write to parser (Parser | None): parser to interpret message """ def __init__( self, uuid: BleUUID, - identifier: types.IdType, + identifier: IdType, parser: Parser | None, ) -> None: Message.__init__(self, identifier, parser) @@ -417,7 +417,7 @@ class HttpMessage(Message): Args: endpoint (str): base endpoint - identifier (types.IdType | None): explicit message identifier. If None, will be generated from endpoint. + identifier (IdType | None): explicit message identifier. If None, will be generated from endpoint. components (list[str] | None): Additional path components (i.e. endpoint/{COMPONENT}). Defaults to None. arguments (list[str] | None): Any arguments to be appended after endpoint (i.e. endpoint?{ARGUMENT}). Defaults to None. body_args (list[str] | None): Arguments to be added to the body JSON. Defaults to None. @@ -429,7 +429,7 @@ class HttpMessage(Message): def __init__( self, endpoint: str, - identifier: types.IdType | None, + identifier: IdType | None, components: list[str] | None = None, arguments: list[str] | None = None, body_args: list[str] | None = None, @@ -452,7 +452,7 @@ def __init__( self._body_args = body_args or [] self._certificate = certificate Message.__init__(self, identifier, parser) - self._base_dict: types.JsonDict = { + self._base_dict: JsonDict = { "id": self._identifier, "protocol": GoProResp.Protocol.HTTP, "endpoint": self._endpoint, @@ -461,14 +461,14 @@ def __init__( def __str__(self) -> str: return str(self._identifier).title() - def _as_dict(self, **kwargs: Any) -> types.JsonDict: + def _as_dict(self, **kwargs: Any) -> JsonDict: """Return the attributes of the message as a dict Args: **kwargs (Any): additional entries for the dict Returns: - types.JsonDict: message as dict + JsonDict: message as dict """ # If any kwargs keys were to conflict with base dict, append underscore return self._base_dict | {f"{'_' if k in ['id', 'protocol'] else ''}{k}": v for k, v in kwargs.items()} @@ -516,8 +516,8 @@ def build_url(self, **kwargs: Any) -> str: MessageType = TypeVar("MessageType", bound=Message) -CommunicatorType = TypeVar("CommunicatorType", bound=BaseGoProCommunicator) +CommunicatorType = TypeVar("CommunicatorType", bound=BaseGoProCommunicator) class Messages(ABC, dict, Generic[MessageType, CommunicatorType]): """Base class for setting and status containers @@ -534,7 +534,7 @@ class Messages(ABC, dict, Generic[MessageType, CommunicatorType]): def __init__(self, communicator: CommunicatorType) -> None: self._communicator = communicator # Append any automatically discovered instance attributes (i.e. for settings and statuses) - message_map: dict[types.IdType, MessageType] = {} + message_map: dict[IdType, MessageType] = {} for message in self.__dict__.values(): if hasattr(message, "_identifier"): message_map[message._identifier] = message diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/gopro_base.py b/demos/python/sdk_wireless_camera_control/open_gopro/gopro_base.py index 9a888aa1..cdc1cfdc 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/gopro_base.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/gopro_base.py @@ -18,7 +18,6 @@ import wrapt import open_gopro.exceptions as GpException -from open_gopro import types from open_gopro.api import ( BleCommands, BleSettings, @@ -37,6 +36,7 @@ from open_gopro.constants import ErrorCode from open_gopro.logger import Logger from open_gopro.models.response import GoProResp, RequestsHttpRespBuilderDirector +from open_gopro.types import JsonDict from open_gopro.util import pretty_print logger = logging.getLogger(__name__) @@ -286,14 +286,14 @@ async def _enforce_message_rules( GoProResp: Operation response """ - def _handle_exception(self, source: Any, context: types.JsonDict) -> None: + def _handle_exception(self, source: Any, context: JsonDict) -> None: """Gather exceptions from module threads and send through callback if registered. Note that this function signature matches asyncio's exception callback requirement. Args: source (Any): Where did the exception come from? - context (types.JsonDict): Access exception via context["exception"] + context (JsonDict): Access exception via context["exception"] """ # context["message"] will always be there; but context["exception"] may not if exception := context.get("exception", False): diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wired.py b/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wired.py index 486f4558..a090f105 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wired.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wired.py @@ -11,7 +11,6 @@ import open_gopro.exceptions as GpException import open_gopro.wifi.mdns_scanner # Imported this way for pytest monkeypatching -from open_gopro import types from open_gopro.api import ( BleCommands, BleSettings, @@ -25,6 +24,7 @@ from open_gopro.constants import StatusId from open_gopro.gopro_base import GoProBase from open_gopro.models import GoProResp +from open_gopro.types import CameraState, UpdateCb, UpdateType logger = logging.getLogger(__name__) @@ -226,24 +226,24 @@ def is_http_connected(self) -> bool: """ return self.is_open - def register_update(self, callback: types.UpdateCb, update: types.UpdateType) -> None: + def register_update(self, callback: UpdateCb, update: UpdateType) -> None: """Register for callbacks when an update occurs Args: - callback (types.UpdateCb): callback to be notified in - update (types.UpdateType): update to register for + callback (UpdateCb): callback to be notified in + update (UpdateType): update to register for Raises: NotImplementedError: not yet possible """ raise NotImplementedError - def unregister_update(self, callback: types.UpdateCb, update: types.UpdateType | None = None) -> None: + def unregister_update(self, callback: UpdateCb, update: UpdateType | None = None) -> None: """Unregister for asynchronous update(s) Args: - callback (types.UpdateCb): callback to stop receiving update(s) on - update (types.UpdateType | None): updates to unsubscribe for. Defaults to None (all + callback (UpdateCb): callback to stop receiving update(s) on + update (UpdateType | None): updates to unsubscribe for. Defaults to None (all updates that use this callback will be unsubscribed). Raises: @@ -309,11 +309,11 @@ async def _enforce_message_rules( await self._wait_for_state({StatusId.ENCODING: True}) return response - async def _wait_for_state(self, check: types.CameraState) -> None: + async def _wait_for_state(self, check: CameraState) -> None: """Poll the current state until a variable amount of states are all equal to desired values Args: - check (types.CameraState): dict{setting / status: value} of settings / statuses and values to wait for + check (CameraState): dict{setting / status: value} of settings / statuses and values to wait for """ while True: state = (await self.http_command.get_camera_state()).data diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wireless.py b/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wireless.py index 88a1967c..ba2923b4 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wireless.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/gopro_wireless.py @@ -14,7 +14,7 @@ from typing import Any, Callable, Final, Pattern import open_gopro.exceptions as GpException -from open_gopro import proto, types +from open_gopro import proto from open_gopro.api import ( BleCommands, BleSettings, @@ -41,6 +41,7 @@ from open_gopro.logger import Logger from open_gopro.models.general import CohnInfo from open_gopro.models.response import BleRespBuilder, GoProResp +from open_gopro.types import ResponseType, UpdateCb, UpdateType from open_gopro.util import SnapshotQueue, get_current_dst_aware_time, pretty_print from open_gopro.wifi import WifiCli @@ -153,11 +154,11 @@ def __init__( # can only be one active response per BleUUID self._active_builders: dict[BleUUID, BleRespBuilder] = {} # Responses that we are waiting for. - self._sync_resp_wait_q: SnapshotQueue[types.ResponseType] = SnapshotQueue() + self._sync_resp_wait_q: SnapshotQueue[ResponseType] = SnapshotQueue() # Synchronous response that has been parsed and are ready for their sender to receive as the response. self._sync_resp_ready_q: SnapshotQueue[GoProResp] = SnapshotQueue() - self._listeners: dict[types.UpdateType, set[types.UpdateCb]] = defaultdict(set) + self._listeners: dict[UpdateType, set[UpdateCb]] = defaultdict(set) # TO be set up when opening in async context self._loop: asyncio.AbstractEventLoop @@ -329,21 +330,21 @@ async def close(self) -> None: await self._close_ble() self._open = False - def register_update(self, callback: types.UpdateCb, update: types.UpdateType) -> None: + def register_update(self, callback: UpdateCb, update: UpdateType) -> None: """Register for callbacks when an update occurs Args: - callback (types.UpdateCb): callback to be notified in - update (types.UpdateType): update to register for + callback (UpdateCb): callback to be notified in + update (UpdateType): update to register for """ self._listeners[update].add(callback) - def unregister_update(self, callback: types.UpdateCb, update: types.UpdateType | None = None) -> None: + def unregister_update(self, callback: UpdateCb, update: UpdateType | None = None) -> None: """Unregister for asynchronous update(s) Args: - callback (types.UpdateCb): callback to stop receiving update(s) on - update (types.UpdateType | None): updates to unsubscribe for. Defaults to None (all + callback (UpdateCb): callback to stop receiving update(s) on + update (UpdateType | None): updates to unsubscribe for. Defaults to None (all updates that use this callback will be unsubscribed). """ if update: @@ -554,11 +555,11 @@ async def _enforce_message_rules( self._encoding_started.clear() return response - async def _notify_listeners(self, update: types.UpdateType, value: Any) -> None: + async def _notify_listeners(self, update: UpdateType, value: Any) -> None: """Notify all registered listeners of this update Args: - update (types.UpdateType): update to notify + update (UpdateType): update to notify value (Any): value to notify """ for listener in self._listeners.get(update, []): @@ -589,7 +590,7 @@ async def _open_ble(self, timeout: int = 10, retries: int = 5) -> None: await self._update_internal_state(StatusId.SYSTEM_BUSY, busy) logger.info("BLE is ready!") - async def _update_internal_state(self, update: types.UpdateType, value: int) -> None: + async def _update_internal_state(self, update: UpdateType, value: int) -> None: """Update the internal state based on a status update. # Note!!! This needs to be reentrant-safe @@ -597,7 +598,7 @@ async def _update_internal_state(self, update: types.UpdateType, value: int) -> Used to update encoding and / or busy status Args: - update (types.UpdateType): type of update (status ID) + update (UpdateType): type of update (status ID) value (int): updated value """ # Cancel any currently pending state update tasks diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/models/media_list.py b/demos/python/sdk_wireless_camera_control/open_gopro/models/media_list.py index 3077b226..04bd2f02 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/models/media_list.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/models/media_list.py @@ -10,8 +10,8 @@ from pydantic import Field, PrivateAttr, validator -from open_gopro import types from open_gopro.models.bases import CustomBaseModel +from open_gopro.types import JsonDict ############################################################################################################## # Generic @@ -64,11 +64,11 @@ class MediaMetadata(ABC, CustomBaseModel): lens_projection: Optional[str] = Field(alias="prjn", default=None) #: Lens projection @classmethod - def from_json(cls, json_str: types.JsonDict) -> MediaMetadata: + def from_json(cls, json_str: JsonDict) -> MediaMetadata: """Build a metadata object given JSON input Args: - json_str (types.JsonDict): raw JSON + json_str (JsonDict): raw JSON Returns: MediaMetadata: parsed metadata @@ -144,13 +144,13 @@ class MediaFileSystem(CustomBaseModel): @validator("file_system", pre=True, each_item=True) @classmethod - def identify_item(cls, item: types.JsonDict) -> MediaItem: + def identify_item(cls, item: JsonDict) -> MediaItem: """Extent item into GroupedMediaItem if it such an item A group item is identified by the presence of a "g" field Args: - item (types.JsonDict): input JSON + item (JsonDict): input JSON Returns: MediaItem: parsed media item diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/models/response.py b/demos/python/sdk_wireless_camera_control/open_gopro/models/response.py index a257404c..6d0c5cc4 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/models/response.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/models/response.py @@ -14,7 +14,6 @@ import requests -from open_gopro import types from open_gopro.api.parsers import JsonParsers from open_gopro.ble import BleUUID from open_gopro.constants import ( @@ -31,6 +30,7 @@ from open_gopro.exceptions import ResponseParseError from open_gopro.parser_interface import GlobalParsers, Parser from open_gopro.proto import EnumResultGeneric +from open_gopro.types import CameraState, JsonDict, ResponseType from open_gopro.util import pretty_print logger = logging.getLogger(__name__) @@ -92,7 +92,7 @@ class GoProResp(Generic[T]): protocol (GoProResp.Protocol): protocol response was received on status (ErrorCode): status of response data (T): parsed response data - identifier (types.ResponseType): response identifier, the type of which will vary depending on the response + identifier (ResponseType): response identifier, the type of which will vary depending on the response """ class Protocol(enum.Enum): @@ -104,7 +104,7 @@ class Protocol(enum.Enum): protocol: GoProResp.Protocol status: ErrorCode data: T - identifier: types.ResponseType + identifier: ResponseType def _as_dict(self) -> dict: """Represent the response as dictionary, merging it's data and meta information @@ -126,7 +126,7 @@ def __eq__(self, obj: object) -> bool: return self.identifier == obj if isinstance(obj, GoProResp): return self.identifier == obj.identifier - raise TypeError("Equal can only compare GoProResp and types.ResponseType") + raise TypeError("Equal can only compare GoProResp and ResponseType") def __str__(self) -> str: return pretty_print(self._as_dict()) @@ -192,7 +192,7 @@ def build(self) -> GoProResp[T]: """ -class HttpRespBuilder(RespBuilder[types.JsonDict]): +class HttpRespBuilder(RespBuilder[JsonDict]): """HTTP Response Builder This is not intended to be fool proof to use as the user must understand which fields are needed. @@ -202,13 +202,13 @@ class HttpRespBuilder(RespBuilder[types.JsonDict]): def __init__(self) -> None: super().__init__() self._endpoint: str - self._response: types.JsonDict + self._response: JsonDict - def set_response(self, response: types.JsonDict) -> None: + def set_response(self, response: JsonDict) -> None: """Store the JSON data. This is mandatory. Args: - response (types.JsonDict): json data_ + response (JsonDict): json data_ """ self._response = response @@ -289,7 +289,7 @@ class BleRespBuilder(RespBuilder[bytearray]): def __init__(self) -> None: self._bytes_remaining = 0 self._uuid: BleUUID - self._identifier: types.ResponseType + self._identifier: ResponseType self._feature_id: FeatureId | None = None self._action_id: ActionId | None = None super().__init__() @@ -304,7 +304,7 @@ def is_response_protobuf(self) -> bool: return isinstance(self._identifier, (ActionId, FeatureId)) @classmethod - def get_response_identifier(cls, uuid: BleUUID, packet: bytearray) -> types.ResponseType: + def get_response_identifier(cls, uuid: BleUUID, packet: bytearray) -> ResponseType: """Get the identifier based on what is currently known about the packet Args: @@ -312,7 +312,7 @@ def get_response_identifier(cls, uuid: BleUUID, packet: bytearray) -> types.Resp packet (bytearray): raw bytes contained in packet Returns: - types.ResponseType: identifier of this response + ResponseType: identifier of this response """ # If it's a protobuf command identifier = packet[0] @@ -466,7 +466,7 @@ def build(self) -> GoProResp: # Query (setting get value, status get value, etc.) if query_type: - camera_state: types.CameraState = defaultdict(list) + camera_state: CameraState = defaultdict(list) self._status = ErrorCode(buf[0]) buf = buf[1:] # Parse all parameters diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/parser_interface.py b/demos/python/sdk_wireless_camera_control/open_gopro/parser_interface.py index 0f901ebc..bca1ef07 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/parser_interface.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/parser_interface.py @@ -10,8 +10,8 @@ from collections import defaultdict from typing import Any, Callable, ClassVar, Generic, Protocol, TypeVar, cast -from open_gopro import types from open_gopro.constants import ActionId, FeatureId +from open_gopro.types import JsonDict, ResponseType logger = logging.getLogger(__name__) @@ -45,7 +45,7 @@ class BytesTransformer(BaseTransformer[bytes]): """Bytes to Bytes transformer interface""" -class JsonTransformer(BaseTransformer[types.JsonDict]): +class JsonTransformer(BaseTransformer[JsonDict]): """Json to json transformer interface""" @@ -72,7 +72,7 @@ def parse(self, data: T) -> T_co: # pylint: disable=method-hidden """ -class JsonParser(BaseParser[types.JsonDict, T_co]): +class JsonParser(BaseParser[JsonDict, T_co]): """Json to Target Type Parser Interface""" @@ -90,16 +90,16 @@ class Parser(ABC, Generic[T]): 4. One JSON parser (json -> Any) Args: - byte_transformers (list[BytesTransformer] | None, optional): bytes --> bytes. Defaults to None. - byte_json_adapter (BytesParser[types.JsonDict] | None, optional): bytes --> json. Defaults to None. - json_transformers (list[JsonTransformer] | None, optional): json --> json. Defaults to None. - json_parser (JsonParser[T] | None, optional): json --> T. Defaults to None. + byte_transformers (list[BytesTransformer] | None): bytes --> bytes. Defaults to None. + byte_json_adapter (BytesParser[JsonDict] | None): bytes --> json. Defaults to None. + json_transformers (list[JsonTransformer] | None): json --> json. Defaults to None. + json_parser (JsonParser[T] | None): json --> T. Defaults to None. """ def __init__( self, byte_transformers: list[BytesTransformer] | None = None, - byte_json_adapter: BytesParser[types.JsonDict] | None = None, + byte_json_adapter: BytesParser[JsonDict] | None = None, json_transformers: list[JsonTransformer] | None = None, json_parser: JsonParser[T] | None = None, ) -> None: @@ -108,11 +108,11 @@ def __init__( self.json_transformers = json_transformers or [] self.json_parser = json_parser - def parse(self, data: bytes | bytearray | types.JsonDict) -> T: + def parse(self, data: bytes | bytearray | JsonDict) -> T: """Perform the parsing using the stored transformers and parsers Args: - data (bytes | bytearray | types.JsonDict): input bytes or json to parse + data (bytes | bytearray | JsonDict): input bytes or json to parse Raises: RuntimeError: attempted to parse bytes when a byte-json adapter does not exist @@ -120,7 +120,7 @@ def parse(self, data: bytes | bytearray | types.JsonDict) -> T: Returns: T: final parsed output """ - parsed_json: types.JsonDict + parsed_json: JsonDict if isinstance(data, (bytes, bytearray)): data = bytes(data) if not self.byte_json_adapter: @@ -196,7 +196,7 @@ class GlobalParsers: """ _feature_action_id_map: ClassVar[dict[FeatureId, list[ActionId]]] = defaultdict(list) - _global_parsers: ClassVar[dict[types.ResponseType, Parser]] = {} + _global_parsers: ClassVar[dict[ResponseType, Parser]] = {} @classmethod def add_feature_action_id_mapping(cls, feature_id: FeatureId, action_id: ActionId) -> None: @@ -209,17 +209,17 @@ def add_feature_action_id_mapping(cls, feature_id: FeatureId, action_id: ActionI cls._feature_action_id_map[feature_id].append(action_id) @classmethod - def add(cls, identifier: types.ResponseType, parser: Parser) -> None: + def add(cls, identifier: ResponseType, parser: Parser) -> None: """Add a global parser that can be accessed by this class's class methods Args: - identifier (types.ResponseType): identifier to add parser for + identifier (ResponseType): identifier to add parser for parser (Parser): parser to add """ cls._global_parsers[identifier] = parser @classmethod - def get_query_container(cls, identifier: types.ResponseType) -> Callable | None: + def get_query_container(cls, identifier: ResponseType) -> Callable | None: """Attempt to get a callable that will translate an input value to the ID-appropriate value. For example, _get_query_container(SettingId.RESOLUTION) will return @@ -230,7 +230,7 @@ def get_query_container(cls, identifier: types.ResponseType) -> Callable | None: Note! Not all ID's are currently parsed so None will be returned if the container does not exist Args: - identifier (types.ResponseType): identifier to find container for + identifier (ResponseType): identifier to find container for Returns: Callable | None: container if found else None @@ -242,13 +242,13 @@ def get_query_container(cls, identifier: types.ResponseType) -> Callable | None: return None @classmethod - def get_parser(cls, identifier: types.ResponseType) -> Parser | None: + def get_parser(cls, identifier: ResponseType) -> Parser | None: """Get a globally defined parser for the given ID. Currently, only BLE uses globally defined parsers Args: - identifier (types.ResponseType): ID to get parser for + identifier (ResponseType): ID to get parser for Returns: Parser | None: parser if found, else None diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/types.py b/demos/python/sdk_wireless_camera_control/open_gopro/types.py index 97df1aae..56b3ae5d 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/types.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/types.py @@ -5,10 +5,10 @@ from __future__ import annotations -from typing import Any, Callable, Coroutine, Union +from typing import Any, Callable, Coroutine, TypeAlias, Union import construct -from google.protobuf.message import Message as Protobuf # pylint: disable=unused-import +from google.protobuf.message import Message from open_gopro.constants import ( ActionId, @@ -21,20 +21,28 @@ # Note! We need to use Union here for Python 3.9 support -ProducerType = tuple[QueryCmdId, Union[SettingId, StatusId]] +Protobuf: TypeAlias = Message + +ProducerType: TypeAlias = tuple[QueryCmdId, Union[SettingId, StatusId]] """Types that can be registered for.""" -CmdType = Union[CmdId, QueryCmdId, ActionId] +CmdType: TypeAlias = Union[CmdId, QueryCmdId, ActionId] """Types that identify a command.""" -ResponseType = Union[CmdType, StatusId, SettingId, BleUUID, str, construct.Enum] +ResponseType: TypeAlias = Union[CmdType, StatusId, SettingId, BleUUID, str, construct.Enum] """Types that are used to identify a response.""" -CameraState = dict[Union[SettingId, StatusId], Any] +CameraState: TypeAlias = dict[Union[SettingId, StatusId], Any] +"""Status / setting id-to-value mappings""" + +JsonDict: TypeAlias = dict[str, Any] +"""Generic JSON dictionary""" -JsonDict = dict[str, Any] +UpdateType: TypeAlias = Union[SettingId, StatusId, ActionId] +"""Identifier Type of an asynchronous update""" -UpdateType = Union[SettingId, StatusId, ActionId] -UpdateCb = Callable[[UpdateType, Any], Coroutine[Any, Any, None]] +UpdateCb: TypeAlias = Callable[[UpdateType, Any], Coroutine[Any, Any, None]] +"""Callback definition for update handlers""" -IdType = Union[SettingId, StatusId, ActionId, CmdId, BleUUID, str] +IdType: TypeAlias = Union[SettingId, StatusId, ActionId, CmdId, BleUUID, str] +"""Message Identifier Type""" diff --git a/demos/python/sdk_wireless_camera_control/poetry.lock b/demos/python/sdk_wireless_camera_control/poetry.lock index c6bde7cb..9e48c581 100644 --- a/demos/python/sdk_wireless_camera_control/poetry.lock +++ b/demos/python/sdk_wireless_camera_control/poetry.lock @@ -26,23 +26,18 @@ files = [ [[package]] name = "astroid" -version = "2.15.8" +version = "3.2.3" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false -python-versions = ">=3.7.2" +python-versions = ">=3.8.0" files = [ - {file = "astroid-2.15.8-py3-none-any.whl", hash = "sha256:1aa149fc5c6589e3d0ece885b4491acd80af4f087baafa3fb5203b113e68cd3c"}, - {file = "astroid-2.15.8.tar.gz", hash = "sha256:6c107453dffee9055899705de3c9ead36e74119cee151e5a9aaf7f0b0e020a6a"}, + {file = "astroid-3.2.3-py3-none-any.whl", hash = "sha256:3eae9ea67c11c858cdd2c91337d2e816bd019ac897ca07d7b346ac10105fceb3"}, + {file = "astroid-3.2.3.tar.gz", hash = "sha256:7099b5a60985529d8d46858befa103b82d0d05a5a5e8b816b5303ed96075e1d9"}, ] [package.dependencies] -lazy-object-proxy = ">=1.4.0" typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} -wrapt = [ - {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, - {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, -] [[package]] name = "async-timeout" @@ -506,14 +501,14 @@ files = [ [[package]] name = "docutils" -version = "0.18.1" +version = "0.20.1" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, ] [[package]] @@ -632,53 +627,6 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] -[[package]] -name = "lazy-object-proxy" -version = "1.10.0" -description = "A fast and thorough lazy object proxy." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "lazy-object-proxy-1.10.0.tar.gz", hash = "sha256:78247b6d45f43a52ef35c25b5581459e85117225408a4128a3daf8bf9648ac69"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:855e068b0358ab916454464a884779c7ffa312b8925c6f7401e952dcf3b89977"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab7004cf2e59f7c2e4345604a3e6ea0d92ac44e1c2375527d56492014e690c3"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0d2fc424e54c70c4bc06787e4072c4f3b1aa2f897dfdc34ce1013cf3ceef05"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e2adb09778797da09d2b5ebdbceebf7dd32e2c96f79da9052b2e87b6ea495895"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1f711e2c6dcd4edd372cf5dec5c5a30d23bba06ee012093267b3376c079ec83"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-win32.whl", hash = "sha256:76a095cfe6045c7d0ca77db9934e8f7b71b14645f0094ffcd842349ada5c5fb9"}, - {file = "lazy_object_proxy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:b4f87d4ed9064b2628da63830986c3d2dca7501e6018347798313fcf028e2fd4"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fec03caabbc6b59ea4a638bee5fce7117be8e99a4103d9d5ad77f15d6f81020c"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02c83f957782cbbe8136bee26416686a6ae998c7b6191711a04da776dc9e47d4"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009e6bb1f1935a62889ddc8541514b6a9e1fcf302667dcb049a0be5c8f613e56"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75fc59fc450050b1b3c203c35020bc41bd2695ed692a392924c6ce180c6f1dc9"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:782e2c9b2aab1708ffb07d4bf377d12901d7a1d99e5e410d648d892f8967ab1f"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-win32.whl", hash = "sha256:edb45bb8278574710e68a6b021599a10ce730d156e5b254941754a9cc0b17d03"}, - {file = "lazy_object_proxy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:e271058822765ad5e3bca7f05f2ace0de58a3f4e62045a8c90a0dfd2f8ad8cc6"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e98c8af98d5707dcdecc9ab0863c0ea6e88545d42ca7c3feffb6b4d1e370c7ba"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:952c81d415b9b80ea261d2372d2a4a2332a3890c2b83e0535f263ddfe43f0d43"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80b39d3a151309efc8cc48675918891b865bdf742a8616a337cb0090791a0de9"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e221060b701e2aa2ea991542900dd13907a5c90fa80e199dbf5a03359019e7a3"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92f09ff65ecff3108e56526f9e2481b8116c0b9e1425325e13245abfd79bdb1b"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-win32.whl", hash = "sha256:3ad54b9ddbe20ae9f7c1b29e52f123120772b06dbb18ec6be9101369d63a4074"}, - {file = "lazy_object_proxy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:127a789c75151db6af398b8972178afe6bda7d6f68730c057fbbc2e96b08d282"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4ed0518a14dd26092614412936920ad081a424bdcb54cc13349a8e2c6d106a"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ad9e6ed739285919aa9661a5bbed0aaf410aa60231373c5579c6b4801bd883c"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc0a92c02fa1ca1e84fc60fa258458e5bf89d90a1ddaeb8ed9cc3147f417255"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0aefc7591920bbd360d57ea03c995cebc204b424524a5bd78406f6e1b8b2a5d8"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5faf03a7d8942bb4476e3b62fd0f4cf94eaf4618e304a19865abf89a35c0bbee"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-win32.whl", hash = "sha256:e333e2324307a7b5d86adfa835bb500ee70bfcd1447384a822e96495796b0ca4"}, - {file = "lazy_object_proxy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:cb73507defd385b7705c599a94474b1d5222a508e502553ef94114a143ec6696"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:366c32fe5355ef5fc8a232c5436f4cc66e9d3e8967c01fb2e6302fd6627e3d94"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2297f08f08a2bb0d32a4265e98a006643cd7233fb7983032bd61ac7a02956b3b"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18dd842b49456aaa9a7cf535b04ca4571a302ff72ed8740d06b5adcd41fe0757"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:217138197c170a2a74ca0e05bddcd5f1796c735c37d0eee33e43259b192aa424"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a3a87cf1e133e5b1994144c12ca4aa3d9698517fe1e2ca82977781b16955658"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-win32.whl", hash = "sha256:30b339b2a743c5288405aa79a69e706a06e02958eab31859f7f3c04980853b70"}, - {file = "lazy_object_proxy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:a899b10e17743683b293a729d3a11f2f399e8a90c73b089e29f5d0fe3509f0dd"}, - {file = "lazy_object_proxy-1.10.0-pp310.pp311.pp312.pp38.pp39-none-any.whl", hash = "sha256:80fa48bd89c8f2f456fc0765c11c23bf5af827febacd2f523ca5bc1893fcc09d"}, -] - [[package]] name = "markupsafe" version = "2.1.5" @@ -1344,24 +1292,24 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "2.17.7" +version = "3.2.5" description = "python code static checker" category = "dev" optional = false -python-versions = ">=3.7.2" +python-versions = ">=3.8.0" files = [ - {file = "pylint-2.17.7-py3-none-any.whl", hash = "sha256:27a8d4c7ddc8c2f8c18aa0050148f89ffc09838142193fdbe98f172781a3ff87"}, - {file = "pylint-2.17.7.tar.gz", hash = "sha256:f4fcac7ae74cfe36bc8451e931d8438e4a476c20314b1101c458ad0f05191fad"}, + {file = "pylint-3.2.5-py3-none-any.whl", hash = "sha256:32cd6c042b5004b8e857d727708720c54a676d1e22917cf1a2df9b4d4868abd6"}, + {file = "pylint-3.2.5.tar.gz", hash = "sha256:e9b7171e242dcc6ebd0aaa7540481d1a72860748a0a7816b8fe6cf6c80a6fe7e"}, ] [package.dependencies] -astroid = ">=2.15.8,<=2.17.0-dev0" +astroid = ">=3.2.2,<=3.3.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, ] -isort = ">=4.2.5,<6" +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" mccabe = ">=0.6,<0.8" platformdirs = ">=2.2.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} @@ -1675,55 +1623,56 @@ files = [ [[package]] name = "sphinx" -version = "5.3.0" +version = "7.3.7" description = "Python documentation generator" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"}, - {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"}, + {file = "sphinx-7.3.7-py3-none-any.whl", hash = "sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3"}, + {file = "sphinx-7.3.7.tar.gz", hash = "sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc"}, ] [package.dependencies] -alabaster = ">=0.7,<0.8" +alabaster = ">=0.7.14,<0.8.0" babel = ">=2.9" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.14,<0.20" +docutils = ">=0.18.1,<0.22" imagesize = ">=1.3" importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} Jinja2 = ">=3.0" packaging = ">=21.0" -Pygments = ">=2.12" -requests = ">=2.5.0" +Pygments = ">=2.14" +requests = ">=2.25.0" snowballstemmer = ">=2.0" sphinxcontrib-applehelp = "*" sphinxcontrib-devhelp = "*" sphinxcontrib-htmlhelp = ">=2.0.0" sphinxcontrib-jsmath = "*" sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" +sphinxcontrib-serializinghtml = ">=1.1.9" +tomli = {version = ">=2", markers = "python_version < \"3.11\""} [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] +lint = ["flake8 (>=3.5.0)", "importlib_metadata", "mypy (==1.9.0)", "pytest (>=6.0)", "ruff (==0.3.7)", "sphinx-lint", "tomli", "types-docutils", "types-requests"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=6.0)", "setuptools (>=67.0)"] [[package]] name = "sphinx-rtd-theme" -version = "1.3.0" +version = "2.0.0" description = "Read the Docs theme for Sphinx" category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.6" files = [ - {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"}, - {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"}, + {file = "sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586"}, + {file = "sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b"}, ] [package.dependencies] -docutils = "<0.19" -sphinx = ">=1.6,<8" +docutils = "<0.21" +sphinx = ">=5,<8" sphinxcontrib-jquery = ">=4,<5" [package.extras] @@ -1844,21 +1793,6 @@ lint = ["docutils-stubs", "flake8", "mypy"] standalone = ["Sphinx (>=5)"] test = ["pytest"] -[[package]] -name = "sphinxemoji" -version = "0.3.1" -description = "An extension to use emoji codes in your Sphinx documentation" -category = "dev" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxemoji-0.3.1-py3-none-any.whl", hash = "sha256:dae483695f8d1e90a28a6e9bbccc08d256202afcc1d0fbd33b51b3b4352d439e"}, - {file = "sphinxemoji-0.3.1.tar.gz", hash = "sha256:23ecff1f1e765393e49083b45386b7da81ced97c9a18a1dfd191460a97da3b11"}, -] - -[package.dependencies] -sphinx = ">=5.0" - [[package]] name = "tomli" version = "2.0.1" @@ -1896,14 +1830,14 @@ files = [ [[package]] name = "types-protobuf" -version = "4.25.0.20240417" +version = "5.27.0.20240626" description = "Typing stubs for protobuf" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "types-protobuf-4.25.0.20240417.tar.gz", hash = "sha256:c34eff17b9b3a0adb6830622f0f302484e4c089f533a46e3f147568313544352"}, - {file = "types_protobuf-4.25.0.20240417-py3-none-any.whl", hash = "sha256:e9b613227c2127e3d4881d75d93c93b4d6fd97b5f6a099a0b654a05351c8685d"}, + {file = "types-protobuf-5.27.0.20240626.tar.gz", hash = "sha256:683ba14043bade6785e3f937a7498f243b37881a91ac8d81b9202ecf8b191e9c"}, + {file = "types_protobuf-5.27.0.20240626-py3-none-any.whl", hash = "sha256:688e8f7e8d9295db26bc560df01fb731b27a25b77cbe4c1ce945647f7024f5c1"}, ] [[package]] @@ -2175,4 +2109,4 @@ gui = ["opencv-python", "Pillow"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "bebc0b2adc82298289a353e0d112b3e2aaf8c72814504ef4f860c09ca03ccda0" +content-hash = "af275fed865b75c561af3ca6e34cc50dcd8e78d8d00011b2d91a2bd0029bf26d" diff --git a/demos/python/sdk_wireless_camera_control/pyproject.toml b/demos/python/sdk_wireless_camera_control/pyproject.toml index c7d4b6ac..0370b36c 100644 --- a/demos/python/sdk_wireless_camera_control/pyproject.toml +++ b/demos/python/sdk_wireless_camera_control/pyproject.toml @@ -66,22 +66,21 @@ pytest-html = "^3" coverage = { extras = ["toml"], version = "^6" } requests-mock = "^1" black = "*" -pylint = "^2" +pylint = "*" mypy = "*" types-requests = "*" types-attrs = "*" types-pytz = "*" types-tzlocal = "*" construct-typing = "*" -sphinx = "^5" -sphinx-rtd-theme = "^1" -sphinxemoji = "^0" +sphinx = "^7" +sphinx-rtd-theme = "^2" coverage-badge = "=1.1.0" poethepoet = "^0" autodoc-pydantic = "^2" pytest-timeout = "^2" isort = "*" -types-protobuf = "^4" +types-protobuf = "*" [tool.poe.tasks.tests] cmd = "pytest tests/unit --cov-fail-under=70" @@ -124,7 +123,7 @@ sequence = ["_pydocstyle", "_doclint"] help = "Analyze docstrings for consistency and errors" [tool.poe.tasks.sphinx] -cmd = "sphinx-build -W --keep-going -a -E -b html docs docs/build" +cmd = "sphinx-build -W --keep-going -a -n -E -b html docs docs/build" help = "Build sphinx documentation." [tool.poe.tasks._coverage] diff --git a/demos/python/sdk_wireless_camera_control/tests/conftest.py b/demos/python/sdk_wireless_camera_control/tests/conftest.py index 36105af0..4d801179 100644 --- a/demos/python/sdk_wireless_camera_control/tests/conftest.py +++ b/demos/python/sdk_wireless_camera_control/tests/conftest.py @@ -12,7 +12,7 @@ import pytest -from open_gopro import WiredGoPro, WirelessGoPro, types +from open_gopro import WiredGoPro, WirelessGoPro from open_gopro.api import ( BleCommands, BleSettings, @@ -49,6 +49,7 @@ from open_gopro.gopro_base import GoProBase from open_gopro.logger import set_logging_level, setup_logging from open_gopro.models.response import GoProResp +from open_gopro.types import UpdateCb, UpdateType, CameraState from open_gopro.wifi import SsidState, WifiClient, WifiController from tests import mock_good_response, versions @@ -221,10 +222,10 @@ def __init__(self, test_version: str) -> None: super().__init__(MockBleController(), disconnection_handler, notification_handler, re.compile("target")) self._api = api_versions[test_version](self) - def register_update(self, callback: types.UpdateCb, update: types.UpdateType) -> None: + def register_update(self, callback: UpdateCb, update: UpdateType) -> None: return - def unregister_update(self, callback: types.UpdateCb, update: types.UpdateType = None) -> None: + def unregister_update(self, callback: UpdateCb, update: UpdateType = None) -> None: return async def _send_ble_message( @@ -323,10 +324,10 @@ async def _put_json( async def _stream_to_file(self, url: str, file: Path): return url, file - def register_update(self, callback: types.UpdateCb, update: types.UpdateType) -> None: + def register_update(self, callback: UpdateCb, update: UpdateType) -> None: return - def unregister_update(self, callback: types.UpdateCb, update: types.UpdateType = None) -> None: + def unregister_update(self, callback: UpdateCb, update: UpdateType = None) -> None: return @property @@ -364,12 +365,12 @@ def __init__(self, test_version: str) -> None: self.http_command.wired_usb_control = self._mock_wired_usb_control self.http_command.get_open_gopro_api_version = self._mock_get_version self.http_command.get_camera_state = self._mock_get_state - self.state_response: types.CameraState = {} + self.state_response: CameraState = {} async def _mock_get_state(self, *args, **kwargs): return DataPatch(self.state_response) - def set_state_response(self, response: types.CameraState): + def set_state_response(self, response: CameraState): self.state_response = response async def _mock_wired_usb_control(self, *args, **kwargs): diff --git a/demos/python/sdk_wireless_camera_control/tests/unit/test_wireless_gopro.py b/demos/python/sdk_wireless_camera_control/tests/unit/test_wireless_gopro.py index 36230d83..9b7d4edc 100644 --- a/demos/python/sdk_wireless_camera_control/tests/unit/test_wireless_gopro.py +++ b/demos/python/sdk_wireless_camera_control/tests/unit/test_wireless_gopro.py @@ -13,10 +13,11 @@ import requests import requests_mock +from open_gopro.types import UpdateType from open_gopro.communicator_interface import HttpMessage from open_gopro.constants import ErrorCode, QueryCmdId, SettingId, StatusId from open_gopro.exceptions import GoProNotOpened, ResponseTimeout -from open_gopro.gopro_wireless import Params, WirelessGoPro, types +from open_gopro.gopro_wireless import Params, WirelessGoPro from open_gopro.models.response import GlobalParsers, GoProResp from tests import mock_good_response @@ -128,7 +129,7 @@ async def test_get_update(mock_wireless_gopro_basic: WirelessGoPro): mock_wireless_gopro_basic._loop = asyncio.get_running_loop() event = asyncio.Event() - async def receive_encoding_status(id: types.UpdateType, value: bool): + async def receive_encoding_status(id: UpdateType, value: bool): event.set() mock_wireless_gopro_basic.register_update(receive_encoding_status, StatusId.ENCODING) @@ -200,7 +201,7 @@ async def test_get_update_unregister_all(mock_wireless_gopro_basic: WirelessGoPr event = asyncio.Event() mock_wireless_gopro_basic._loop = asyncio.get_running_loop() - async def receive_encoding_status(id: types.UpdateType, value: bool): + async def receive_encoding_status(id: UpdateType, value: bool): event.set() mock_wireless_gopro_basic.register_update(receive_encoding_status, StatusId.ENCODING)