From 17c943e9147ac180ff17fc2fb54ce2a5ed9d8d7f Mon Sep 17 00:00:00 2001 From: Tim Camise Date: Fri, 6 Sep 2024 11:28:02 -0700 Subject: [PATCH] Python sdk maintenance (#569) * Update dependencies * Update bleak * Update Wifi Windows driver for Hero 13 --- .../sdk_wireless_camera_control/docs/api.rst | 6 + .../sdk_wireless_camera_control/docs/conf.py | 92 +- .../sdk_wireless_camera_control/noxfile.py | 6 +- .../open_gopro/api/api.py | 24 +- .../open_gopro/api/ble_commands.py | 127 +- .../open_gopro/api/builders.py | 177 +-- .../open_gopro/api/http_commands.py | 103 +- .../open_gopro/api/params.py | 15 + .../open_gopro/api/parsers.py | 40 +- .../open_gopro/ble/adapters/bleak_wrapper.py | 19 +- .../open_gopro/ble/client.py | 39 +- .../open_gopro/ble/controller.py | 23 +- .../open_gopro/ble/services.py | 55 +- .../open_gopro/communicator_interface.py | 102 +- .../open_gopro/constants.py | 2 +- .../open_gopro/demos/gui/components/util.py | 10 +- .../open_gopro/demos/video.py | 12 +- .../open_gopro/enum.py | 2 +- .../open_gopro/exceptions.py | 4 +- .../open_gopro/gopro_base.py | 38 +- .../open_gopro/gopro_wired.py | 24 +- .../open_gopro/gopro_wireless.py | 43 +- .../open_gopro/logger.py | 18 +- .../open_gopro/models/media_list.py | 10 +- .../open_gopro/models/response.py | 29 +- .../open_gopro/parser_interface.py | 43 +- .../open_gopro/types.py | 31 +- .../open_gopro/util.py | 6 +- .../open_gopro/wifi/adapters/wireless.py | 57 +- .../open_gopro/wifi/client.py | 15 +- .../open_gopro/wifi/controller.py | 24 +- .../open_gopro/wifi/mdns_scanner.py | 6 +- .../sdk_wireless_camera_control/poetry.lock | 1058 +++++++++-------- .../pyproject.toml | 29 +- .../tests/conftest.py | 15 +- .../tests/unit/test_wireless_gopro.py | 7 +- 36 files changed, 1220 insertions(+), 1091 deletions(-) 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..08a28c9b 100644 --- a/demos/python/sdk_wireless_camera_control/docs/conf.py +++ b/demos/python/sdk_wireless_camera_control/docs/conf.py @@ -6,6 +6,10 @@ from open_gopro import WirelessGoPro +from sphinx.ext.intersphinx import missing_reference + +import open_gopro.models + gopro = WirelessGoPro(enable_wifi=False) project = "Open GoPro Python SDK" @@ -23,8 +27,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 = { @@ -36,9 +40,12 @@ autodoc_default_options = { "members": True, } -# https://autodoc-pydantic.readthedocs.io/en/stable/users/installation.html#configuration -autodoc_pydantic_model_show_json = True +# https://autodoc-pydantic.readthedocs.io/en/stable/users/configuration.html +autodoc_pydantic_model_show_json = False 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 +58,79 @@ 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", + # TODO there must be a better way of doing this... + "Params.Toggle": "open_gopro.api.params.Toggle", + "Params.CameraControl": "open_gopro.api.params.CameraControl", + "Params.WebcamProtocol": "open_gopro.api.params.WebcamProtocol", + "Params.WebcamResolution": "open_gopro.api.params.WebcamResolution", + "Params.WebcamFOV": "open_gopro.api.params.WebcamFOV", +} + +# 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"), + # TODO need to fix these + ("py:class", "Path"), + ("py:class", "JsonDict"), + ("py:class", "ValueType"), ] nitpick_ignore_regex = [ - (r"py:class", r".*proto\..+"), # TODO how should / can we handle protobuf documenting? + (r"py:class", r".*proto\..+"), (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:class", r".*DisconnectHandlerType"), + (r"py:obj", r".*CommunicatorType"), + (r"py:class", r".*QueryParserType"), + (r"py:class", r".*ValueType"), + (r"py:obj", r".*communicator_interface.MessageType"), + (r"py:class", r".*dataclasses.*"), ] -# 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("Error") + 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/noxfile.py b/demos/python/sdk_wireless_camera_control/noxfile.py index 082f2694..e908e20e 100644 --- a/demos/python/sdk_wireless_camera_control/noxfile.py +++ b/demos/python/sdk_wireless_camera_control/noxfile.py @@ -62,10 +62,10 @@ def tests(session) -> None: @session(python=SUPPORTED_VERSIONS[-1]) def docstrings(session) -> None: """Validate docstrings.""" - session.install("darglint") + session.install("pydoclint") session.install("pydocstyle[toml]") session.run("pydocstyle", "open_gopro") - session.run("darglint", "open_gopro") + session.run("pydoclint", "open_gopro") @session(python=SUPPORTED_VERSIONS[-1]) @@ -78,7 +78,7 @@ def docs(session) -> None: "sphinx-rtd-theme", "sphinxcontrib-napoleon", "autodoc-pydantic", - "darglint", + "pydoclint", ) session.run("sphinx-build", "-W", "docs", "docs/build") # Clean up for Jekyll consumption diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/api.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/api.py index 563ee681..bf0a9de4 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/api.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/api.py @@ -3,6 +3,8 @@ """Implementation of Open GoPro API version 2.0""" +from __future__ import annotations + from typing import Final from open_gopro.communicator_interface import GoProHttp, GoProWirelessInterface @@ -12,16 +14,15 @@ class WirelessApi: - """Implementation of Open GoPro API version 2.0 for Wireless interface (Wifi and BLE)""" + """Implementation of Open GoPro API version 2.0 for Wireless interface (Wifi and BLE) + + Args: + communicator (GoProWirelessInterface): used to communicate via BLE and Wifi + """ version: Final = "2.0" def __init__(self, communicator: GoProWirelessInterface) -> None: - """Constructor - - Args: - communicator (GoProWirelessInterface): used to communicate via BLE and Wifi - """ self._communicator = communicator self.ble_command = BleCommands(communicator) self.ble_setting = BleSettings(communicator) @@ -32,16 +33,15 @@ def __init__(self, communicator: GoProWirelessInterface) -> None: class WiredApi: - """Implementation of Open GoPro API version 2.0 for Wired interface (USB)""" + """Implementation of Open GoPro API version 2.0 for Wired interface (USB) + + Args: + communicator (GoProHttp): used to communicate via BLE and Wifi + """ version: Final = "2.0" def __init__(self, communicator: GoProHttp) -> None: - """Constructor - - Args: - communicator (GoProHttp): used to communicate via BLE and Wifi - """ self._communicator = communicator self.http_command = HttpCommands(communicator) self.http_setting = HttpSettings(communicator) 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 b9cbc9cc..55709526 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 @@ -86,10 +86,10 @@ async def set_shutter(self, *, shutter: Params.Toggle) -> GoProResp[None]: """Set the Shutter to start / stop encoding Args: - shutter (open_gopro.api.params.Toggle): on or off + shutter (Params.Toggle): on or off Returns: - GoProResp: status of command + GoProResp[None]: status of command """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.TAG_HILIGHT) @@ -97,7 +97,7 @@ async def tag_hilight(self) -> GoProResp[None]: """Tag a highlight during encoding Returns: - GoProResp: status of command + GoProResp[None]: status of command """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.POWER_DOWN) @@ -105,7 +105,7 @@ async def power_down(self) -> GoProResp[None]: """Power Down the camera Returns: - GoProResp: status of command + GoProResp[None]: status of command """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.SLEEP) @@ -113,7 +113,7 @@ async def sleep(self) -> GoProResp[None]: """Put the camera in standby Returns: - GoProResp: status of command + GoProResp[None]: status of command """ @ble_write_command( @@ -145,7 +145,7 @@ async def get_hardware_info(self) -> GoProResp[CameraInfo]: """Get the model number, board, type, firmware version, serial number, and AP info Returns: - GoProResp: response as JSON + GoProResp[CameraInfo]: response as JSON """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.SET_WIFI, Int8ub) @@ -156,7 +156,7 @@ async def enable_wifi_ap(self, *, enable: bool) -> GoProResp[None]: enable (bool): True to enable, False to disable Returns: - GoProResp: response as JSON + GoProResp[None]: response as JSON """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.LOAD_PRESET_GROUP, Int16ub) @@ -166,10 +166,10 @@ async def load_preset_group(self, *, group: proto.EnumPresetGroup.ValueType) -> Once complete, the most recently used preset in this group will be active. Args: - group (open_gopro.api.proto.EnumPresetGroup): preset group to load + group (proto.EnumPresetGroup.ValueType): preset group to load Returns: - GoProResp: response as JSON + GoProResp[None]: response as JSON """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.LOAD_PRESET, Int32ub) @@ -182,7 +182,7 @@ async def load_preset(self, *, preset: int) -> GoProResp[None]: preset (int): preset ID to load Returns: - GoProResp: command status + GoProResp[None]: command status """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.SET_THIRD_PARTY_CLIENT_INFO) @@ -190,7 +190,7 @@ async def set_third_party_client_info(self) -> GoProResp[None]: """Flag as third party app Returns: - GoProResp: command status + GoProResp[None]: command status """ @ble_write_command( @@ -207,7 +207,7 @@ async def get_open_gopro_api_version(self) -> GoProResp[str]: """Get Open GoPro API Version Returns: - GoProResp: response as JSON + GoProResp[str]: response as JSON """ @ble_write_command( @@ -219,7 +219,7 @@ async def get_camera_statuses(self) -> GoProResp[CameraState]: """Get all of the camera's statuses Returns: - GoProResp: response as JSON + GoProResp[CameraState]: response as JSON """ @ble_write_command( @@ -231,7 +231,7 @@ async def get_camera_settings(self) -> GoProResp[CameraState]: """Get all of the camera's settings Returns: - GoProResp: response as JSON + GoProResp[CameraState]: response as JSON """ @ble_write_command( @@ -243,7 +243,7 @@ async def get_camera_capabilities(self) -> GoProResp[CameraState]: """Get the current capabilities of each camera setting Returns: - GoProResp: response as JSON + GoProResp[CameraState]: response as JSON """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.SET_DATE_TIME, param_builder=ByteParserBuilders.DateTime()) @@ -254,7 +254,7 @@ async def set_date_time(self, *, date_time: datetime.datetime) -> GoProResp[None date_time (datetime.datetime): Date and time to set (Timezone will be ignored) Returns: - GoProResp: command status + GoProResp[None]: command status """ @ble_write_command( @@ -269,7 +269,7 @@ async def get_date_time(self) -> GoProResp[datetime.datetime]: """Get the camera's date and time (non timezone / DST version) Returns: - GoProResp: response as JSON + GoProResp[datetime.datetime]: response as JSON """ @ble_write_command(GoProUUIDs.CQ_COMMAND, CmdId.SET_DATE_TIME_DST, param_builder=ByteParserBuilders.DateTime()) @@ -284,7 +284,7 @@ async def set_date_time_tz_dst( is_dst (bool): is daylight savings time? Returns: - GoProResp: command status + GoProResp[None]: command status """ @ble_write_command( @@ -299,7 +299,7 @@ async def get_date_time_tz_dst(self) -> GoProResp[TzDstDateTime]: """Get the camera's date and time with timezone / DST Returns: - GoProResp: response as JSON + GoProResp[TzDstDateTime]: response as JSON """ ###################################################################################################### @@ -317,7 +317,7 @@ async def get_wifi_ssid(self) -> GoProResp[str]: """Get the Wifi SSID. Returns: - GoProResp: command status and SSID + GoProResp[str]: command status and SSID """ @ble_read_command( @@ -331,7 +331,7 @@ async def get_wifi_password(self) -> GoProResp[str]: """Get the Wifi password. Returns: - GoProResp: command status and password + GoProResp[str]: command status and password """ ###################################################################################################### @@ -344,14 +344,14 @@ 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: command status and current value of all statuses + GoProResp[None]: command status and current value of all statuses """ @ble_register_command( @@ -360,14 +360,14 @@ 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: command status + GoProResp[None]: command status """ @ble_register_command( @@ -376,14 +376,14 @@ 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: command status and current value of all settings + GoProResp[None]: command status and current value of all settings """ @ble_register_command( @@ -392,14 +392,14 @@ 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: command status + GoProResp[None]: command status """ @ble_register_command( @@ -408,14 +408,14 @@ 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: command status and current value of all capabilities + GoProResp[None]: command status and current value of all capabilities """ @ble_register_command( @@ -424,14 +424,14 @@ 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: command status + GoProResp[None]: command status """ ###################################################################################################### @@ -452,10 +452,10 @@ async def set_camera_control( """Tell the camera that the app (i.e. External Control) wishes to claim control of the camera. Args: - camera_control_status (open_gopro.api.proto.EnumCameraControlStatus): Desired camera control. + camera_control_status (proto.EnumCameraControlStatus.ValueType): Desired camera control. Returns: - GoProResp: command status of request + GoProResp[None]: command status of request """ @ble_proto_command( @@ -470,10 +470,10 @@ async def set_turbo_mode(self, *, mode: Params.Toggle) -> GoProResp[None]: """Enable / disable turbo mode. Args: - mode (open_gopro.api.params.Toggle): True to enable, False to disable. + mode (Params.Toggle): True to enable, False to disable. Returns: - GoProResp: command status of request + GoProResp[None]: command status of request """ return {"active": mode} # type: ignore @@ -498,13 +498,13 @@ async def get_preset_status( sent asynchronously as :py:attr:`open_gopro.constants.ActionId.PRESET_MODIFIED_NOTIFICATION` Args: - register (list[open_gopro.api.proto.EnumRegisterPresetStatus], Optional): Types of preset modified + register (list[proto.EnumRegisterPresetStatus.ValueType] | None): Types of preset modified updates to register for. Defaults to None. - unregister (list[open_gopro.api.proto.EnumRegisterPresetStatus], Optional): Types of preset modified + unregister (list[proto.EnumRegisterPresetStatus.ValueType] | None): Types of preset modified updates to unregister for. Defaults to None. Returns: - GoProResp: JSON data describing all currently available presets + GoProResp[proto.NotifyPresetStatus]: JSON data describing all currently available presets """ return { # type: ignore "register_preset_status": register or [], @@ -579,7 +579,7 @@ async def scan_wifi_networks(self) -> GoProResp[proto.ResponseStartScanning]: """Scan for Wifi networks Returns: - GoProResp: Command status of request + GoProResp[proto.ResponseStartScanning]: Command status of request """ @ble_proto_command( @@ -601,7 +601,7 @@ async def get_ap_entries( max_entries (int): Used for paging. Value must be < NotifStartScanning.total_entries. Defaults to 100. Returns: - GoProResp: result of scan with entries for WiFi networks + GoProResp[proto.ResponseGetApEntries]: result of scan with entries for WiFi networks """ return {"scan_id": scan_id, "start_index": start_index, "max_entries": max_entries} # type: ignore @@ -623,7 +623,7 @@ async def request_wifi_connect(self, *, ssid: str) -> GoProResp[proto.ResponseCo ssid (str): SSID to connect to Returns: - GoProResp: Command status of request + GoProResp[proto.ResponseConnect]: Command status of request """ @ble_proto_command( @@ -645,7 +645,7 @@ async def request_wifi_connect_new(self, *, ssid: str, password: str) -> GoProRe password (str): password of WiFi network Returns: - GoProResp: Command status of request + GoProResp[proto.ResponseConnectNew]: Command status of request """ @ble_proto_command( @@ -674,12 +674,12 @@ async def set_livestream_mode( minimum_bitrate (int): Desired minimum streaming bitrate (>= 800) maximum_bitrate (int): Desired maximum streaming bitrate (<= 8000) starting_bitrate (int): Initial streaming bitrate (honored if 800 <= value <= 8000) - window_size (open_gopro.api.proto.EnumWindowSize | None): Streaming video resolution. Defaults to None (use camera default). - lens (open_gopro.api.proto.EnumLens): Streaming Field of View. Defaults to None (use camera default). + window_size (proto.EnumWindowSize.ValueType | None): Streaming video resolution. Defaults to None (use camera default). + lens (proto.EnumLens.ValueType | None): Streaming Field of View. Defaults to None (use camera default). certs (list[Path] | None): list of certificates to use. Defaults to None. Returns: - GoProResp: command status of request + GoProResp[None]: command status of request """ d = { "url": url, @@ -720,13 +720,13 @@ async def register_livestream_status( """Register / unregister to receive asynchronous livestream statuses Args: - register (Optional[list[open_gopro.api.proto.EnumRegisterLiveStreamStatus]]): Statuses to register + register (list[proto.EnumRegisterLiveStreamStatus.ValueType] | None): Statuses to register for. Defaults to None (don't register for any). - unregister (Optional[list[open_gopro.api.proto.EnumRegisterLiveStreamStatus]]): Statues to + unregister (list[proto.EnumRegisterLiveStreamStatus.ValueType] | None): Statuses to unregister for. Defaults to None (don't unregister for any). Returns: - GoProResp: current livestream status + GoProResp[proto.NotifyLiveStreamStatus]: current livestream status """ return {"register_live_stream_status": register or [], "unregister_live_stream_status": unregister or []} # type: ignore @@ -742,7 +742,7 @@ async def release_network(self) -> GoProResp[None]: """Disconnect the camera Wifi network in STA mode so that it returns to AP mode. Returns: - GoProResp: status of release request + GoProResp[None]: status of release request """ @ble_proto_command( @@ -825,7 +825,7 @@ async def cohn_set_setting(self, *, mode: Params.Toggle) -> GoProResp[None]: """Set a COHN specific setting. Args: - mode (open_gopro.api.params.Toggle): should camera auto connect to home network? + mode (Params.Toggle): should camera auto connect to home network? Returns: GoProResp[None]: status of set @@ -841,7 +841,6 @@ class BleSettings(BleMessages[BleSetting.BleSettingMessageBase]): Args: communicator (GoProBle): Adapter to read / write settings - params: (type[Params]): the set of parameters to use to build the settings """ def __init__(self, communicator: GoProBle): @@ -1082,6 +1081,11 @@ def __init__(self, communicator: GoProBle): ) """File type of photo output""" + self.video_duration: BleSetting[Params.VideoDuration] = BleSetting[Params.VideoDuration]( + communicator, SettingId.VIDEO_DURATION, Params.VideoDuration + ) + """If set, a video will automatically be stopped after recording for this long.""" + super().__init__(communicator) @@ -1125,7 +1129,6 @@ class BleStatuses(BleMessages[BleStatus.BleStatusMessageBase]): Args: communicator (GoProBle): Adapter to read / write settings - params: (type[Params]): the set of parameters to use to build the statuses """ def __init__(self, communicator: GoProBle) -> None: 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 4df7263c..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__) @@ -54,15 +54,14 @@ class BleReadCommand(BleMessage): - """A BLE command that reads data from a BleUUID""" + """A BLE command that reads data from a BleUUID - def __init__(self, uuid: BleUUID, parser: Parser) -> None: - """Constructor + Args: + uuid (BleUUID): BleUUID to read from + parser (Parser): the parser that will parse the received bytestream into a JSON dict + """ - Args: - uuid (BleUUID): BleUUID to read from - parser (Parser): the parser that will parse the received bytestream into a JSON dict - """ + def __init__(self, uuid: BleUUID, parser: Parser) -> None: super().__init__(uuid=uuid, parser=parser, identifier=uuid) def _build_data(self, **kwargs: Any) -> bytearray: @@ -72,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 @@ -124,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 @@ -142,6 +141,13 @@ class RegisterUnregisterAll(BleWriteCommand): This will loop over all of the elements (i.e. settings / statuses found from the element_set entry of the producer tuple parameter) and individually register / unregister (depending on the action parameter) each element in the set + + Args: + uuid (BleUUID): UUID to write to + cmd (CmdId): Command ID that is being sent + update_set (type[SettingId] | type[StatusId]): what are registering / unregistering for? + action (Action): whether to register or unregister + parser (Parser | None): Optional response parser. Defaults to None. """ class Action(enum.Enum): @@ -158,22 +164,25 @@ def __init__( action: Action, parser: Parser | None = None, ) -> None: - """Constructor - - Args: - uuid (BleUUID): UUID to write to - cmd (CmdId): Command ID that is being sent - update_set (type[SettingId] | type[StatusId]): what are registering / unregistering for? - action (Action): whether to register or unregister - parser (Optional[BytesParser], optional): Optional response parser. Defaults to None. - """ self.action = action self.update_set = update_set super().__init__(uuid=uuid, cmd=cmd, parser=parser) class BleProtoCommand(BleMessage): - """A BLE command that is sent and received as using the Protobuf protocol""" + """A BLE command that is sent and received as using the Protobuf protocol + + Args: + uuid (BleUUID): BleUUID to write to + 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[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. + """ def __init__( self, @@ -181,25 +190,11 @@ 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: - """Constructor - - Args: - uuid (BleUUID): BleUUID to write to - 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 - parser (Optional[BytesParser], optional): Optional response parser. Defaults to None. - additional_matching_ids (Optional[set[Union[ActionId, CmdId]]], optional): 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. - """ p = parser or Parser() p.byte_json_adapter = ByteParserBuilders.Protobuf(response_proto) super().__init__(uuid=uuid, parser=p, identifier=response_action_id) @@ -242,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 @@ -314,8 +309,8 @@ def ble_register_command( uuid (BleUUID): UUID to write to cmd (CmdId): Command ID that is being sent update_set (type[SettingId] | type[StatusId]): set of ID's being registered for - action (Action): whether to register or unregister - parser (Parser, optional): Optional response parser. Defaults to None. + action (RegisterUnregisterAll.Action): whether to register or unregister + parser (Parser | None): Optional response parser. Defaults to None. Returns: Callable: Generated method to perform command @@ -334,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: @@ -346,12 +341,11 @@ 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 - parser (Parser | None, optional): Response parser to transform received Protobuf bytes. Defaults to None. - additional_matching_ids (Optional[set[Union[ActionId, CmdId]]], optional): 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. + 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. Returns: Callable: Generated method to perform command @@ -401,6 +395,9 @@ def __call__(self, **kwargs: Any) -> bytearray: # noqa: D102 class BleSettingFacade(Generic[ValueType]): """Wrapper around BleSetting since a BleSetting's message definition changes based on how it is being operated on. + Raises: + TypeError: Parser builder is not a valid type + Args: communicator (GoProBle): BLE communicator that will operate on this object. identifier (SettingId): Setting Identifier @@ -416,12 +413,16 @@ class BleSettingMessageBase(BleMessage): Args: uuid (BleUUID): UUID to access this setting. identifier (SettingId | QueryCmdId): How responses to operations on this message will be identified. - setting_id: (SettingId): Setting identifier. May match identifier in some cases. + setting_id (SettingId): Setting identifier. May match identifier in some cases. builder (BuilderProtocol): Build request bytes from the current message. """ def __init__( - self, uuid: BleUUID, identifier: SettingId | QueryCmdId, setting_id: SettingId, builder: BuilderProtocol + self, + uuid: BleUUID, + identifier: SettingId | QueryCmdId, + setting_id: SettingId, + builder: BuilderProtocol, ) -> None: self._build = builder self._setting_id = setting_id @@ -430,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): @@ -469,7 +470,7 @@ async def set(self, value: ValueType) -> GoProResp[None]: value (ValueType): The argument to use to set the setting value. Returns: - GoProResp: Status of set + GoProResp[None]: Status of set """ def _build_data(**kwargs: Any) -> bytearray: @@ -494,7 +495,7 @@ async def get_value(self) -> GoProResp[ValueType]: """Get the settings value. Returns: - GoProResp: settings value + GoProResp[ValueType]: settings value """ message = BleSettingFacade.BleSettingMessageBase( BleSettingFacade.READER_UUID, @@ -509,6 +510,9 @@ async def get_name(self) -> GoProResp[str]: Raises: NotImplementedError: This isn't implemented on the camera + + Returns: + GoProResp[str]: setting name as string """ raise NotImplementedError("Not implemented on camera!") @@ -516,7 +520,7 @@ async def get_capabilities_values(self) -> GoProResp[list[ValueType]]: """Get currently supported settings capabilities values. Returns: - GoProResp: settings capabilities values + GoProResp[list[ValueType]]: settings capabilities values """ message = BleSettingFacade.BleSettingMessageBase( BleSettingFacade.READER_UUID, @@ -531,17 +535,20 @@ async def get_capabilities_names(self) -> GoProResp[list[str]]: Raises: NotImplementedError: This isn't implemented on the camera + + Returns: + GoProResp[list[str]]: list of capability names as strings """ 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: Current value of respective setting ID + GoProResp[None]: Current value of respective setting ID """ message = BleSettingFacade.BleSettingMessageBase( BleSettingFacade.READER_UUID, @@ -553,14 +560,14 @@ 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: Status of unregister + GoProResp[None]: Status of unregister """ message = BleSettingFacade.BleSettingMessageBase( BleSettingFacade.READER_UUID, @@ -572,14 +579,14 @@ 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: Current capabilities of respective setting ID + GoProResp[None]: Current capabilities of respective setting ID """ message = BleSettingFacade.BleSettingMessageBase( BleSettingFacade.READER_UUID, @@ -591,14 +598,14 @@ 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: Status of unregister + GoProResp[None]: Status of unregister """ message = BleSettingFacade.BleSettingMessageBase( BleSettingFacade.READER_UUID, @@ -652,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) @@ -679,7 +686,7 @@ async def get_value(self) -> GoProResp[ValueType]: """Get the current value of a status. Returns: - GoProResp: current status value + GoProResp[ValueType]: current status value """ message = BleStatusFacade.BleStatusMessageBase( BleStatusFacade.UUID, @@ -689,14 +696,14 @@ 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: current status value + GoProResp[ValueType]: current status value """ message = BleStatusFacade.BleStatusMessageBase( BleStatusFacade.UUID, @@ -708,14 +715,14 @@ 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: + 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: Status of unregister + GoProResp[None]: Status of unregister """ message = BleStatusFacade.BleStatusMessageBase( BleStatusFacade.UUID, @@ -756,8 +763,8 @@ def http_get_json_command( endpoint (str): base 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. - parser (Parser | None, optional): Parser to handle received JSON. Defaults to None. - identifier (types.IdType | None): explicit message identifier. If None, will be generated from endpoint. + parser (Parser | None): Parser to handle received JSON. Defaults to None. + identifier (str | None): explicit message identifier. If None, will be generated from endpoint. rules (MessageRules): rules this Message must obey. Defaults to MessageRules(). Returns: @@ -788,8 +795,8 @@ def http_get_binary_command( endpoint (str): base 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. - parser (Parser | None, optional): Parser to handle received JSON. Defaults to None. - identifier (types.IdType | None): explicit message identifier. If None, will be generated from endpoint. + parser (Parser | None): Parser to handle received JSON. Defaults to None. + identifier (str | None): explicit message identifier. If None, will be generated from endpoint. rules (MessageRules): rules this Message must obey. Defaults to MessageRules(). Returns: @@ -827,8 +834,8 @@ def http_put_json_command( 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, optional): Arguments to be added to the body JSON. Defaults to None. - parser (Parser | None, optional): Parser to handle received JSON. Defaults to None. - identifier (types.IdType | None): explicit message identifier. If None, will be generated from endpoint. + parser (Parser | None): Parser to handle received JSON. Defaults to None. + identifier (str | None): explicit message identifier. If None, will be generated from endpoint. rules (MessageRules): rules this Message must obey. Defaults to MessageRules(). Returns: @@ -866,7 +873,7 @@ def build_url(self, **kwargs: Any) -> str: """Build the endpoint from the current arguments Args: - kwargs (Any): run-time arguments + **kwargs (Any): run-time arguments Returns: str: built URL 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 28fa2ec2..bfbd940e 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 @@ -104,7 +105,7 @@ async def update_custom_preset( `proto.EnumPresetTitle.PRESET_TITLE_USER_DEFINED_CUSTOM_NAME`. Defaults to None. Returns: - GoProResp: command status + GoProResp[None]: command status """ @http_get_json_command(endpoint="gopro/camera/digital_zoom", arguments=["percent"]) @@ -115,7 +116,7 @@ async def set_digital_zoom(self, *, percent: int) -> GoProResp[None]: percent (int): Desired zoom as a percentage Returns: - GoProResp: command status + GoProResp[None]: command status """ @http_get_json_command( @@ -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: status and settings as JSON + GoProResp[CameraState]: status and settings as JSON """ @http_get_json_command( @@ -137,7 +138,7 @@ async def get_camera_info(self) -> GoProResp[CameraInfo]: """Get general information about the camera such as firmware version Returns: - GoProResp: status and settings as JSON + GoProResp[CameraInfo]: status and settings as JSON """ @http_get_json_command(endpoint="gopro/camera/keep_alive") @@ -145,7 +146,7 @@ async def set_keep_alive(self) -> GoProResp[None]: """Send the keep alive signal to maintain the connection. Returns: - GoProResp: command status + GoProResp[None]: command status """ @http_get_json_command( @@ -160,7 +161,7 @@ async def get_media_metadata(self, *, path: str) -> GoProResp[MediaMetadata]: path (str): Path on camera of media file to get metadata for Returns: - GoProResp: Media metadata JSON structure + GoProResp[MediaMetadata]: Media metadata JSON structure """ @http_get_json_command( @@ -171,7 +172,7 @@ async def get_media_list(self) -> GoProResp[MediaList]: """Get a list of media on the camera. Returns: - GoProResp: Media list JSON structure + GoProResp[MediaList]: Media list JSON structure """ @http_get_json_command(endpoint="gopro/media/turbo_transfer", arguments=["p"]) @@ -179,10 +180,10 @@ async def set_turbo_mode(self, *, mode: Params.Toggle) -> GoProResp[None]: """Enable or disable Turbo transfer mode. Args: - mode (open_gopro.api.params.Toggle): enable / disable turbo mode + mode (Params.Toggle): enable / disable turbo mode Returns: - GoProResp: Status + GoProResp[None]: Status """ return {"p": mode} # type: ignore @@ -194,16 +195,16 @@ async def get_open_gopro_api_version(self) -> GoProResp[str]: """Get Open GoPro API version Returns: - GoProResp: Open GoPro Version + GoProResp[str]: Open GoPro Version """ # 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: 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"]) @@ -216,7 +217,7 @@ async def load_preset(self, *, preset: int) -> GoProResp[None]: preset (int): preset to load Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"id": preset} # type: ignore @@ -227,10 +228,10 @@ async def load_preset_group(self, *, group: proto.EnumPresetGroup.ValueType) -> The most recently used Preset in this group will be set. Args: - group (open_gopro.proto.EnumPresetGroup): desired Preset Group + group (proto.EnumPresetGroup.ValueType): desired Preset Group Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"id": group} # type: ignore @@ -241,11 +242,12 @@ async def set_preview_stream(self, *, mode: Params.Toggle, port: int | None = No """Start or stop the preview stream Args: - mode (open_gopro.api.params.Toggle): enable to start or disable to stop - port (int): Port to use for Preview Stream. Defaults to 8554 if None. Only relevant when starting the stream. + mode (Params.Toggle): enable to start or disable to stop + port (int | None): Port to use for Preview Stream. Defaults to 8554 if None. + Only relevant when starting the stream. Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"mode": "start" if mode is Params.Toggle.ENABLE else "stop", "port": port} # type: ignore @@ -254,7 +256,7 @@ async def set_third_party_client_info(self) -> GoProResp[None]: """Flag as third party app Returns: - GoProResp: command status + GoProResp[None]: command status """ @http_get_json_command( @@ -269,10 +271,10 @@ async def set_shutter(self, *, shutter: Params.Toggle) -> GoProResp[None]: """Set the shutter on or off Args: - shutter (open_gopro.api.params.Toggle): on or off (i.e. start or stop encoding) + shutter (Params.Toggle): on or off (i.e. start or stop encoding) Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"mode": "start" if shutter is Params.Toggle.ENABLE else "stop"} # type: ignore @@ -281,10 +283,10 @@ async def set_camera_control(self, *, mode: Params.CameraControl) -> GoProResp[N """Configure global behaviors by setting camera control (to i.e. Idle, External) Args: - mode (open_gopro.api.params.CameraControl): desired camera control value + mode (Params.CameraControl): desired camera control value Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"p": mode} # type: ignore @@ -304,7 +306,7 @@ async def set_date_time( is_dst (bool): is daylight savings time?. Defaults to False. Returns: - GoProResp: command status + GoProResp[None]: command status """ return { # type: ignore "date": f"{date_time.year}_{date_time.month}_{date_time.day}", @@ -318,7 +320,7 @@ async def get_date_time(self) -> GoProResp[datetime.datetime]: """Get the date and time of the camera (Non timezone / DST aware) Returns: - GoProResp: current date and time on camera + GoProResp[datetime.datetime]: current date and time on camera """ @http_get_json_command(endpoint="gopro/webcam/version") @@ -326,7 +328,7 @@ async def get_webcam_version(self) -> GoProResp[str]: """Get the version of the webcam implementation Returns: - GoProResp: version + GoProResp[str]: version """ @http_get_json_command( @@ -346,7 +348,7 @@ async def add_file_hilight( offset (int | None): offset in ms from start of media Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"path": file, "ms": offset or None} # type: ignore @@ -367,7 +369,7 @@ async def remove_file_hilight( offset (int | None): offset in ms from start of media Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"path": file, "ms": offset} # type: ignore @@ -380,7 +382,7 @@ async def webcam_exit(self) -> GoProResp[WebcamResponse]: """Exit the webcam. Returns: - GoProResp: command status + GoProResp[WebcamResponse]: command status """ @http_get_json_command( @@ -392,7 +394,7 @@ async def webcam_preview(self) -> GoProResp[WebcamResponse]: """Start the webcam preview. Returns: - GoProResp: command status + GoProResp[WebcamResponse]: command status """ @http_get_json_command( @@ -412,16 +414,14 @@ async def webcam_start( """Start the webcam. Args: - resolution (Optional[open_gopro.api.params.WebcamResolution]): resolution to use. If not set, - camera default will be used. - fov (Optional[open_gopro.api.params.WebcamFOV]): field of view to use. If not set, camera - default will be used. - port (Optional[int]): port to use for streaming. If not set, camera default of 8554 will be used. - protocol (Optional[open_gopro.api.params.WebcamProtocol]): streaming protocol to use. If not set, camera - default of TS will be used. + resolution (Params.WebcamResolution | None): resolution to use. If not set, camera default will be used. + fov (Params.WebcamFOV | None): field of view to use. If not set, camera default will be used. + port (int | None): port to use for streaming. If not set, camera default of 8554 will be used. + protocol (Params.WebcamProtocol | None): streaming protocol to use. If not set, camera default of TS will + be used. Returns: - GoProResp: command status + GoProResp[WebcamResponse]: command status """ return {"res": resolution, "fov": fov, "port": port, "protocol": protocol} # type: ignore @@ -434,7 +434,7 @@ async def webcam_stop(self) -> GoProResp[WebcamResponse]: """Stop the webcam. Returns: - GoProResp: command status + GoProResp[WebcamResponse]: command status """ @http_get_json_command( @@ -446,7 +446,7 @@ async def webcam_status(self) -> GoProResp[WebcamResponse]: """Get the current status of the webcam Returns: - GoProResp: command status including the webcam status + GoProResp[WebcamResponse]: command status including the webcam status """ @http_get_json_command( @@ -457,10 +457,10 @@ async def wired_usb_control(self, *, control: Params.Toggle) -> GoProResp[None]: """Enable / disable wired usb control Args: - control (params.Toggle): enable or disable + control (Params.Toggle): enable or disable Returns: - GoProResp: command status + GoProResp[None]: command status """ return {"p": control} # type: ignore @@ -475,7 +475,7 @@ async def get_gpmf_data(self, *, camera_file: str, local_file: Path | None = Non local_file (Path | None): Location on computer to write output. Defaults to None. Returns: - Path: Path to local_file that output was written to + GoProResp[Path]: Path to local_file that output was written to """ @http_get_binary_command(endpoint="gopro/media/screennail", arguments=["path"]) @@ -489,7 +489,7 @@ async def get_screennail__call__(self, *, camera_file: str, local_file: Path | N local_file (Path | None): Location on computer to write output. Defaults to None. Returns: - Path: Path to local_file that output was written to + GoProResp[Path]: Path to local_file that output was written to """ @http_get_binary_command(endpoint="gopro/media/thumbnail", arguments=["path"]) @@ -503,7 +503,7 @@ async def get_thumbnail(self, *, camera_file: str, local_file: Path | None = Non local_file (Path | None): Location on computer to write output. Defaults to None. Returns: - Path: Path to local_file that output was written to + GoProResp[Path]: Path to local_file that output was written to """ @http_get_binary_command(endpoint="gopro/media/telemetry", arguments=["path"]) @@ -517,7 +517,7 @@ async def get_telemetry(self, *, camera_file: str, local_file: Path | None = Non local_file (Path | None): Location on computer to write output. Defaults to None. Returns: - Path: Path to local_file that output was written to + GoProResp[Path]: Path to local_file that output was written to """ @http_get_binary_command(endpoint="videos/DCIM", components=["path"], identifier="Download File") @@ -531,7 +531,7 @@ async def download_file(self, *, camera_file: str, local_file: Path | None = Non local_file (Path | None): Location on computer to write output. Defaults to None. Returns: - Path: Path to local_file that output was written to + GoProResp[Path]: Path to local_file that output was written to """ @@ -733,4 +733,9 @@ def __init__(self, communicator: GoProHttp): ) """File type of photo output""" + self.video_duration: HttpSetting[Params.VideoDuration] = HttpSetting[Params.VideoDuration]( + communicator, SettingId.VIDEO_DURATION + ) + """If set, a video will automatically be stopped after recording for this long.""" + super().__init__(communicator) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py b/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py index e2715b6f..2fcd2594 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/api/params.py @@ -419,6 +419,7 @@ class PhotoDuration(GoProIntEnum): MIN_15 = 5 MIN_30 = 6 HOUR_1 = 7 + HOUR_2 = 8 HOUR_3 = 9 @@ -434,3 +435,17 @@ class PresetGroup(GoProIntEnum): VIDEO = 1000 PHOTO = 1001 TIMELAPSE = 1002 + + +class VideoDuration(GoProIntEnum): + DUR_15_SECONDS = 1 + DUR_30_SECONDS = 2 + DUR_1_MINUTE = 3 + DUR_5_MINUTES = 4 + DUR_15_MINUTES = 5 + DUR_30_MINUTES = 6 + DUR_1_HOUR = 7 + DUR_2_HOURS = 8 + DUR_3_HOURS = 9 + DUR_5_SECONDS = 10 + DUR_NO_LIMIT = 100 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 d165c032..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 (dict): 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[[dict], dict]): 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 (dict): 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 (dict): input dict to parse + data (JsonDict): input dict to parse Returns: - dict: 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 @@ -179,7 +179,7 @@ class GoProEnum(BytesParserBuilder): """Parse into a GoProEnum Args: - target (type[GoProEnum]): enum type to parse into + target (type[GoProIntEnum]): enum type to parse into """ def __init__(self, target: type[GoProIntEnum]) -> None: @@ -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/adapters/bleak_wrapper.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py index cbfe3b3a..81b128eb 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/adapters/bleak_wrapper.py @@ -3,6 +3,8 @@ """Manage a Bluetooth connection using bleak.""" +from __future__ import annotations + import asyncio import logging import platform @@ -62,16 +64,15 @@ def uuid2bleak_string(uuid: BleUUID) -> str: class BleakWrapperController(BLEController[BleakDevice, bleak.BleakClient], Singleton): - """Wrapper around bleak to manage a Bluetooth connection.""" + """Wrapper around bleak to manage a Bluetooth connection. - def __init__(self, exception_handler: Optional[Callable] = None) -> None: - """Constructor + Note, this is a singleton. - Note, this is a singleton. + Args: + exception_handler (Callable | None): Used to catch asyncio exceptions from other tasks. Defaults to None. + """ - Args: - exception_handler (Callable, Optional): Used to catch asyncio exceptions from other tasks. Defaults to None. - """ + def __init__(self, exception_handler: Callable | None = None) -> None: BLEController.__init__(self, exception_handler) async def read(self, handle: bleak.BleakClient, uuid: BleUUID) -> bytearray: @@ -326,7 +327,7 @@ def bleak_notification_cb_adapter(characteristic: BleakGATTCharacteristic, data: await handle.start_notify(char, bleak_notification_cb_adapter) logger.info("Done enabling notifications") - async def discover_chars(self, handle: bleak.BleakClient, uuids: Optional[type[UUIDs]] = None) -> GattDB: + async def discover_chars(self, handle: bleak.BleakClient, uuids: type[UUIDs] | None = None) -> GattDB: """Discover all characteristics for a connected handle. By default, the BLE controller only knows Spec-Defined BleUUID's so any additional BleUUID's should @@ -334,7 +335,7 @@ async def discover_chars(self, handle: bleak.BleakClient, uuids: Optional[type[U Args: handle (bleak.BleakClient): BLE handle to discover for - uuids (type[UUIDs], Optional): Additional BleUUID information to use when building the + uuids (type[UUIDs] | None): Additional BleUUID information to use when building the Gatt Database. Defaults to None. Returns: diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/client.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/client.py index 32ea82b8..895ef9d5 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/client.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/client.py @@ -3,10 +3,12 @@ """Generic BLE Client definition that is composed of a BLE Controller.""" +from __future__ import annotations + import logging import re from pathlib import Path -from typing import Generic, Optional, Pattern, Union +from typing import Generic, Optional, Pattern from open_gopro.ble import BleUUID from open_gopro.exceptions import ConnectFailed, FailedToFindDevice @@ -24,31 +26,30 @@ class BleClient(Generic[BleHandle, BleDevice]): - """A BLE device that is to be connected to.""" + """A BLE device that is to be connected to. + + Args: + controller (BLEController): controller implementation to use for this client + disconnected_cb (DisconnectHandlerType): disconnected callback + notification_cb (NotiHandlerType): notification callback + target (tuple[Pattern | BleDevice, list[BleUUID] | None]): Tuple of: + (device, service_uuids) where device is the BLE device (or regex) to connect to and + service_uuids is a list of service uuid's to filter for + uuids (type[UUIDs] | None): Additional UUIDs that will be used when discovering characteristic. + Defaults to None in which case any unknown UUIDs will be set to "unknown". + + Raises: + ValueError: Must pass a valid target + """ def __init__( self, controller: BLEController, disconnected_cb: DisconnectHandlerType, notification_cb: NotiHandlerType, - target: tuple[Union[Pattern, BleDevice], Optional[list[BleUUID]]], - uuids: Optional[type[UUIDs]] = None, + target: tuple[Pattern | BleDevice, list[BleUUID] | None], + uuids: type[UUIDs] | None = None, ) -> None: - """Constructor - - Args: - controller (BLEController): controller implementation to use for this client - disconnected_cb (DisconnectHandlerType): disconnected callback - notification_cb (NotiHandlerType): notification callback - target (tuple[Union[Pattern, BleDevice], Optional[list[BleUUID]]]): Tuple - of (device, service_uuids) where device is the BLE device (or regex) to connect to and - service_uuids is a list of service uuid's to filter for - uuids (type[UUIDs], Optional): Additional UUIDs that will be used when discovering characteristic. - Defaults to None in which case any unknown UUIDs will be set to "unknown". - - Raises: - ValueError: Must pass a valid target - """ if target is None: raise ValueError("Target can not be None!") if isinstance(target[0], str): diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/ble/controller.py b/demos/python/sdk_wireless_camera_control/open_gopro/ble/controller.py index 328ae4b5..91e37b39 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/ble/controller.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/ble/controller.py @@ -3,6 +3,8 @@ """BLE Controller Interface Definition.""" +from __future__ import annotations + import logging from abc import ABC, abstractmethod from typing import Callable, Generic, Optional, Pattern, TypeVar @@ -34,7 +36,6 @@ async def read(self, handle: BleHandle, uuid: BleUUID) -> bytes: Returns: bytes: response """ - raise NotImplementedError @abstractmethod async def write(self, handle: BleHandle, uuid: BleUUID, data: bytes) -> None: @@ -44,25 +45,20 @@ async def write(self, handle: BleHandle, uuid: BleUUID, data: bytes) -> None: handle (BleHandle): handle to pair to uuid (BleUUID): BleUUID to write to data (bytes): bytestream to write - - Returns: - bytes: response """ - raise NotImplementedError @abstractmethod - async def scan(self, token: Pattern, timeout: int = 5, service_uuids: Optional[list[BleUUID]] = None) -> BleDevice: + async def scan(self, token: Pattern, timeout: int = 5, service_uuids: list[BleUUID] | None = None) -> BleDevice: """Scan BLE device with a regex in it's device name. Args: token (Pattern): Regex to scan for timeout (int): Time to scan (in seconds) before considering scanning as failed. Defaults to 5. - service_uuids (list[BleUUID], Optional): The list of BleUUID's to filter on. Defaults to None. + service_uuids (list[BleUUID] | None): The list of BleUUID's to filter on. Defaults to None. Returns: BleDevice: discovered device (shall not be multiple devices) """ - raise NotImplementedError @abstractmethod async def connect(self, disconnect_cb: DisconnectHandlerType, device: BleDevice, timeout: int = 15) -> BleHandle: @@ -76,7 +72,6 @@ async def connect(self, disconnect_cb: DisconnectHandlerType, device: BleDevice, Returns: BleHandle: handle that has been connected to """ - raise NotImplementedError @abstractmethod async def pair(self, handle: BleHandle) -> None: @@ -85,7 +80,6 @@ async def pair(self, handle: BleHandle) -> None: Args: handle (BleHandle): handle to pair to """ - raise NotImplementedError @abstractmethod async def enable_notifications(self, handle: BleHandle, handler: NotiHandlerType) -> None: @@ -98,10 +92,9 @@ async def enable_notifications(self, handle: BleHandle, handler: NotiHandlerType handle (BleHandle): handle to enable notifications on handler (NotiHandlerType): notification handler """ - raise NotImplementedError @abstractmethod - async def discover_chars(self, handle: BleHandle, uuids: Optional[type[UUIDs]] = None) -> GattDB: + async def discover_chars(self, handle: BleHandle, uuids: type[UUIDs] | None = None) -> GattDB: """Discover all characteristics for a connected handle. By default, the BLE controller only knows Spec-Defined BleUUID's so any additional BleUUID's should @@ -109,13 +102,12 @@ async def discover_chars(self, handle: BleHandle, uuids: Optional[type[UUIDs]] = Args: handle (BleHandle): BLE handle to discover for - uuids (type[UUIDs], Optional): Additional BleUUID information to use when building the - Gatt Database. Defaults to None. + uuids (type[UUIDs] | None): Additional BleUUID information to use when building the Gatt Database. + Defaults to None. Returns: GattDB: Gatt Database """ - raise NotImplementedError @abstractmethod async def disconnect(self, handle: BleHandle) -> None: @@ -124,4 +116,3 @@ async def disconnect(self, handle: BleHandle) -> None: Args: handle (BleHandle): handle to disconnect from """ - raise NotImplementedError 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 8d9289a9..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 @@ -63,6 +63,18 @@ class BleUUID(uuid.UUID): """An extension of the standard UUID to associate a string name with the UUID and allow 8-bit UUID input Can only be initialized with one of [hex, bytes, bytes_le, int] + + Args: + name (str): human readable name + format (BleUUID.Format): 16 or 128 bit format. Defaults to BleUUID.Format.BIT_128. + hex (str | None): build from hex string. Defaults to None. + bytes (bytes | None): build from big-endian bytes. Defaults to None. + bytes_le (bytes | None): build from little-endian bytes. Defaults to None. + int (int | None): build from int. Defaults to None. + + Raises: + ValueError: Attempt to initialize with more than one option + ValueError: Badly formed input """ class Format(IntEnum): @@ -76,25 +88,11 @@ def __init__( self, name: str, format: BleUUID.Format = Format.BIT_128, - hex: Optional[str] = None, - bytes: Optional[bytes] = None, - bytes_le: Optional[bytes] = None, - int: Optional[int] = None, + hex: str | None = None, + bytes: bytes | None = None, + bytes_le: bytes | None = None, + int: int | None = None, ) -> None: - """Constructor - - Args: - name (str): human readable name - format (BleUUID.Format, Optional): 16 or 128 bit format. Defaults to BleUUID.Format.BIT_128. - hex (str, Optional): build from hex string. Defaults to None. - bytes (bytes, Optional): build from big-endian bytes. Defaults to None. - bytes_le (bytes, Optional): build from little-endian bytes. Defaults to None. - int (int, Optional): build from int. Defaults to None. - - Raises: - ValueError: Attempt to initialize with more than one option - ValueError: Badly formed input - """ self.name: str if format is BleUUID.Format.BIT_16: if [hex, bytes, bytes_le, int].count(None) != 3: @@ -166,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] = {} @@ -373,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() @@ -388,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() @@ -531,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 1daff778..91fbd39f 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 @@ -11,12 +11,11 @@ import re from abc import ABC, abstractmethod from pathlib import Path -from typing import Any, Generator, Generic, Pattern, Protocol, TypeVar +from typing import Any, Generic, Iterator, Pattern, Protocol, TypeVar from urllib.parse import urlencode 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__) @@ -45,8 +45,9 @@ class MessageRules: """Message Rules Manager Args: - fastpass_analyzer (Analyzer): used to check if message is fastpass. Defaults to always_false. - wait_for_encoding_analyer (Analyzer): Used to check if message should wait for encoding. Defaults to always_false. + fastpass_analyzer (Analyzer): Analyzer to decide if the message is fastpass. Defaults to always_false. + wait_for_encoding_analyzer (Analyzer): Analyzer to decide if the message should wait for encoding. + Defaults to always_false. """ class Analyzer(Protocol): @@ -56,7 +57,7 @@ def __call__(self, **kwargs: Any) -> bool: """Analyze the current inputs to see if the rule should be applied Args: - kwargs (Any): input arguments + **kwargs (Any): input arguments Returns: bool: Should the rule be applied? @@ -75,7 +76,7 @@ def is_fastpass(self, **kwargs: Any) -> bool: """Is this command fastpass? Args: - kwargs (Any) : Arguments passed into the message + **kwargs (Any) : Arguments passed into the message Returns: bool: result of rule check @@ -86,7 +87,7 @@ def should_wait_for_encoding_start(self, **kwargs: Any) -> bool: """Should this message wait for encoding to start? Args: - kwargs (Any) : Arguments passed into the message + **kwargs (Any) : Arguments passed into the message Returns: bool: result of rule check @@ -103,25 +104,23 @@ 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 """ - raise NotImplementedError @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). """ - raise NotImplementedError class GoProHttp(BaseGoProCommunicator): @@ -137,7 +136,7 @@ async def _get_json( message (HttpMessage): operation description timeout (int): time (in seconds) to wait to receive response before returning error. Defaults to 0. rules (MessageRules | None): message rules that this operation will obey. Defaults to MessageRules(). - kwargs (Any) : any run-time arguments to apply to the operation + **kwargs (Any) : any run-time arguments to apply to the operation Returns: GoProResp: response parsed from received JSON @@ -153,7 +152,7 @@ async def _get_stream( message (HttpMessage): operation description timeout (int): time (in seconds) to wait to receive response before returning error. Defaults to 0. rules (MessageRules | None): message rules that this operation will obey. Defaults to MessageRules(). - kwargs (Any) : any run-time arguments to apply to the operation + **kwargs (Any) : any run-time arguments to apply to the operation Returns: GoProResp: response wrapper around downloaded binary @@ -169,7 +168,7 @@ async def _put_json( message (HttpMessage): operation description timeout (int): time (in seconds) to wait to receive response before returning error. Defaults to 0. rules (MessageRules | None): message rules that this operation will obey. Defaults to MessageRules(). - kwargs (Any) : any run-time arguments to apply to the operation + **kwargs (Any) : any run-time arguments to apply to the operation Returns: GoProResp: response parsed from received JSON @@ -239,7 +238,7 @@ async def _send_ble_message( Args: message (BleMessage): BLE operation description rules (MessageRules): message rules that this operation will obey. Defaults to MessageRules(). - kwargs (Any) : any run-time arguments to apply to the operation + **kwargs (Any) : any run-time arguments to apply to the operation Returns: GoProResp: response parsed from accumulated BLE notifications @@ -254,7 +253,7 @@ async def _read_ble_characteristic( Args: message (BleMessage): BLE operation description rules (MessageRules): message rules that this operation will obey. Defaults to MessageRules(). - kwargs (Any) : any run-time arguments to apply to the operation + **kwargs (Any) : any run-time arguments to apply to the operation Returns: GoProResp: response parsed from bytes read from characteristic @@ -262,7 +261,7 @@ async def _read_ble_characteristic( # TODO this should be somewhere else @classmethod - def _fragment(cls, data: bytes) -> Generator[bytes, None, None]: + def _fragment(cls, data: bytes) -> Iterator[bytes]: """Fragment data in to MAX_BLE_PKT_LEN length packets Args: @@ -272,7 +271,7 @@ def _fragment(cls, data: bytes) -> Generator[bytes, None, None]: ValueError: data is too long Yields: - Generator[bytes, None, None]: Generator of packets as bytes + bytes: packet as bytes """ MAX_BLE_PKT_LEN = 20 @@ -313,7 +312,7 @@ def _fragment(cls, data: bytes) -> Generator[bytes, None, None]: bytes_remaining = MAX_BLE_PKT_LEN - len(packet) current, data = (data[:bytes_remaining], data[bytes_remaining:]) packet.extend(current) - yield packet + yield bytes(packet) class GoProWiredInterface(BaseGoProCommunicator): @@ -324,6 +323,13 @@ class GoProWirelessInterface(GoProBle, GoProWifi, Generic[BleDevice, BleHandle]) """The top-level interface for a Wireless Open GoPro controller This always supports BLE and can optionally support Wifi + + Args: + ble_controller (BLEController): BLE controller instance + wifi_controller (WifiController | None): Wifi controller instance + disconnected_cb (DisconnectHandlerType): callback for BLE disconnects + notification_cb (NotiHandlerType): callback for BLE received notifications + target (Pattern | BleDevice): BLE device to search for """ def __init__( @@ -334,15 +340,6 @@ def __init__( notification_cb: NotiHandlerType, target: Pattern | BleDevice, ) -> None: - """Constructor - - Args: - ble_controller (BLEController): BLE controller instance - wifi_controller (Optional[WifiController]): Wifi controller instance - disconnected_cb (DisconnectHandlerType): callback for BLE disconnects - notification_cb (NotiHandlerType): callback for BLE received notifications - target (Pattern | BleDevice): BLE device to search for - """ # Initialize GoPro Communication Client GoProBle.__init__(self, ble_controller, disconnected_cb, notification_cb, target) if wifi_controller: @@ -363,37 +360,37 @@ 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 """ - raise NotImplementedError class BleMessage(Message): """The base class for all BLE messages to store common info Args: - communicator (GoProBle): BLE client to read / write - uuid (BleUUID): BleUUID to read / write to + uuid (BleUUID): BLE client to read / write + 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) @@ -408,7 +405,7 @@ def _build_data(self, **kwargs: Any) -> bytearray: """Build the raw write request from operation description and run-time arguments Args: - kwargs (Any) : run-time arguments + **kwargs (Any) : run-time arguments Returns: bytearray: raw bytes request @@ -420,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. @@ -432,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, @@ -455,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, @@ -464,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()} @@ -519,6 +516,7 @@ def build_url(self, **kwargs: Any) -> str: MessageType = TypeVar("MessageType", bound=Message) + CommunicatorType = TypeVar("CommunicatorType", bound=BaseGoProCommunicator) @@ -529,24 +527,22 @@ class Messages(ABC, dict, Generic[MessageType, CommunicatorType]): Instance attributes that are an instance (or subclass) of Message are automatically accumulated during instantiation + + Args: + communicator (CommunicatorType): communicator that will send messages """ def __init__(self, communicator: CommunicatorType) -> None: - """Constructor - - Args: - communicator (CommunicatorType): communicator that will send messages - """ 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 # Append any automatically discovered methods (i.e. for commands) for name, method in inspect.getmembers(self, predicate=inspect.ismethod): if not name.startswith("_"): - message_map[name.replace("_", " ").title()] = method # type: ignore + message_map[name.replace("_", " ").title()] = method dict.__init__(self, message_map) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/constants.py b/demos/python/sdk_wireless_camera_control/open_gopro/constants.py index 46b0f811..29353eb5 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/constants.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/constants.py @@ -225,7 +225,7 @@ class SettingId(GoProIntEnum): INTERNAL_153 = 153 INTERNAL_154 = 154 INTERNAL_155 = 155 - INTERNAL_156 = 156 + VIDEO_DURATION = 156 INTERNAL_157 = 157 INTERNAL_158 = 158 INTERNAL_159 = 159 diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/components/util.py b/demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/components/util.py index cc184e86..efe5044a 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/components/util.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/demos/gui/components/util.py @@ -29,15 +29,13 @@ class BufferlessVideoCapture(threading.Thread): """Buffer-less video capture to only display the most recent frame Open a video source to display it, and block until the user stops it by sending 'q' + + Args: + source (str): video source to display + printer (Callable): used to display output message. Defaults to print. """ def __init__(self, source: str, printer: Callable = print) -> None: - """Constructor - - Args: - source (str): video source to display - printer (Callable): used to display output message. Defaults to print. - """ self.printer = printer self.printer("Starting viewer...") self.cap = cv2.VideoCapture(source + "?overrun_nonfatal=1&fifo_size=50000000", cv2.CAP_FFMPEG) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py b/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py index ef80585b..04372092 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/demos/video.py @@ -33,9 +33,11 @@ async def main(args: argparse.Namespace) -> None: media_set_before = set((await gopro.http_command.get_media_list()).data.files) # Take a video console.print("Capturing a video...") + # assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.ENABLE)).ok + # await asyncio.sleep(args.record_time) + # assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.DISABLE)).ok + assert await gopro.http_setting.video_duration.set(Params.VideoDuration.DUR_15_SECONDS) assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.ENABLE)).ok - await asyncio.sleep(args.record_time) - assert (await gopro.http_command.set_shutter(shutter=Params.Toggle.DISABLE)).ok # Get the media list after media_set_after = set((await gopro.http_command.get_media_list()).data.files) @@ -56,11 +58,7 @@ async def main(args: argparse.Namespace) -> None: def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Connect to a GoPro camera, take a video, then download it.") - parser.add_argument( - "record_time", - type=float, - help="How long to record for", - ) + parser.add_argument("-r", "--record_time", type=float, help="How long to record for", default=2.0) parser.add_argument( "-o", "--output", diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/enum.py b/demos/python/sdk_wireless_camera_control/open_gopro/enum.py index 487ab45d..a537ace4 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/enum.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/enum.py @@ -133,7 +133,7 @@ def enum_factory(proto_enum: ProtobufDescriptor) -> type[GoProIntEnum]: proto_enum (ProtobufDescriptor): input protobuf enum descriptor Returns: - GoProEnum: generated GoProEnum + type[GoProIntEnum]: generated GoProEnum """ keys = proto_enum.values_by_name.keys() values = list(proto_enum.values_by_number.keys()) diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/exceptions.py b/demos/python/sdk_wireless_camera_control/open_gopro/exceptions.py index e8c0580a..1ce8bcc1 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/exceptions.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/exceptions.py @@ -3,6 +3,8 @@ """Exceptions that pertain to Gopro-level functionality.""" +from __future__ import annotations + from typing import Callable @@ -50,8 +52,8 @@ class ConnectFailed(GoProError): Args: connection (str): type of connection that failed + timeout (float): the timeout used for each attempt retries (int): how many retries were attempted - timeout (int): the timeout used for each attempt """ def __init__(self, connection: str, timeout: float, retries: int): 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 4e814f4e..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__) @@ -64,7 +64,7 @@ def catch_thread_exception(wrapped: Callable, instance: GoProBase, args: Any, kw kwargs (Any): keyword args Returns: - Optional[Callable]: forwarded return of wrapped method or None if exception occurs + Callable | None: forwarded return of wrapped method or None if exception occurs """ try: return wrapped(*args, **kwargs) @@ -77,7 +77,7 @@ def ensure_opened(interface: tuple[GoProMessageInterface]) -> Callable: """Raise exception if relevant interface is not currently opened Args: - interface (Interface): wireless interface to verify + interface (tuple[GoProMessageInterface]): wireless interface to verify Returns: Callable: Direct pass-through of callable after verification @@ -135,12 +135,10 @@ async def open(self, timeout: int = 10, retries: int = 5) -> None: timeout (int): time before considering connection a failure. Defaults to 10. retries (int): number of connection retries. Defaults to 5. """ - raise NotImplementedError @abstractmethod async def close(self) -> None: """Gracefully close the GoPro Client connection""" - raise NotImplementedError @property @abstractmethod @@ -150,7 +148,6 @@ async def is_ready(self) -> bool: Returns: bool: yes if ready, no otherwise """ - raise NotImplementedError @property @abstractmethod @@ -160,7 +157,6 @@ def identifier(self) -> str: Returns: str: identifier """ - raise NotImplementedError @property def version(self) -> str: @@ -181,7 +177,6 @@ def http_command(self) -> HttpCommands: Returns: HttpCommands: the commands """ - raise NotImplementedError @property @abstractmethod @@ -191,7 +186,6 @@ def http_setting(self) -> HttpSettings: Returns: HttpSettings: the settings """ - raise NotImplementedError @property @abstractmethod @@ -201,7 +195,6 @@ def ble_command(self) -> BleCommands: Returns: BleCommands: the commands """ - raise NotImplementedError @property @abstractmethod @@ -211,7 +204,6 @@ def ble_setting(self) -> BleSettings: Returns: BleSettings: the settings """ - raise NotImplementedError @property @abstractmethod @@ -221,7 +213,6 @@ def ble_status(self) -> BleStatuses: Returns: BleStatuses: the statuses """ - raise NotImplementedError @property @abstractmethod @@ -231,7 +222,6 @@ def is_open(self) -> bool: Returns: bool: True if yes, False if no """ - raise NotImplementedError @property @abstractmethod @@ -241,7 +231,6 @@ def is_ble_connected(self) -> bool: Returns: bool: True if yes, False if no """ - raise NotImplementedError @property @abstractmethod @@ -251,7 +240,6 @@ def is_http_connected(self) -> bool: Returns: bool: True if yes, False if no """ - raise NotImplementedError @abstractmethod async def configure_cohn(self, timeout: int = 60) -> bool: @@ -266,7 +254,6 @@ async def configure_cohn(self, timeout: int = 60) -> bool: Returns: bool: True if success, False otherwise """ - raise NotImplementedError @property @abstractmethod @@ -278,7 +265,6 @@ async def is_cohn_provisioned(self) -> bool: Returns: bool: True if COHN is provisioned, False otherwise """ - raise NotImplementedError ########################################################################################################## # End Public API @@ -294,20 +280,20 @@ async def _enforce_message_rules( wrapped (Callable): operation to enforce message (Message): message passed to operation rules (MessageRules): rules to enforce - kwargs (Any) : arguments passed to operation + **kwargs (Any) : arguments passed to operation Returns: 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 (Dict): 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): @@ -333,7 +319,6 @@ def _base_url(self) -> str: Returns: str: base endpoint with URL from serial number """ - raise NotImplementedError @property @abstractmethod @@ -341,16 +326,15 @@ def _api(self) -> ApiType: """Unique identifier for the connected GoPro Client Returns: - str: identifier + ApiType: identifier """ - raise NotImplementedError @staticmethod def _ensure_opened(interface: tuple[GoProMessageInterface]) -> Callable: """Raise exception if relevant interface is not currently opened Args: - interface (Interface): wireless interface to verify + interface (tuple[GoProMessageInterface]): wireless interface to verify Returns: Callable: Direct pass-through of callable after verification @@ -362,11 +346,11 @@ def _catch_thread_exception(*args: Any, **kwargs: Any) -> Callable | None: """Catch any exceptions from this method and pass them to the exception handler identifier by thread name Args: - args (Any): positional args - kwargs (Any): keyword args + *args (Any): positional args + **kwargs (Any): keyword args Returns: - Optional[Callable]: forwarded return of wrapped method or None if exception occurs + Callable | None: forwarded return of wrapped method or None if exception occurs """ return catch_thread_exception(*args, **kwargs) 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 e0370991..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__) @@ -57,9 +57,9 @@ class WiredGoPro(GoProBase[WiredApi], GoProWiredInterface): >>> # Send some messages now Args: - serial (Optional[str]): (at least) last 3 digits of GoPro Serial number. If not set, first GoPro + serial (str | None): (at least) last 3 digits of GoPro Serial number. If not set, first GoPro discovered from mDNS will be used. Defaults to None - kwargs (Any): additional keyword arguments to pass to base class + **kwargs (Any): additional keyword arguments to pass to base class """ _BASE_IP: Final[str] = "172.2{}.1{}{}.51" @@ -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,13 +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 (dict[Union[StatusId, SettingId], Any]): 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 315f9d08..e4402b98 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 @@ -91,14 +92,14 @@ class WirelessGoPro(GoProBase[WirelessApi], GoProWirelessInterface): >>> # Send some messages now Args: - target (Pattern, Optional): A regex to search for the target GoPro's name. For example, "GoPro 0456"). + target (Pattern | None): A regex to search for the target GoPro's name. For example, "GoPro 0456"). Defaults to None (i.e. connect to first discovered GoPro) - wifi_interface (str, Optional): Set to specify the wifi interface the local machine will use to connect + wifi_interface (str | None): Set to specify the wifi interface the local machine will use to connect to the GoPro. If None (or not set), first discovered interface will be used. - sudo_password (str, Optional): User password for sudo. If not passed, you will be prompted if a password + sudo_password (str | None): User password for sudo. If not passed, you will be prompted if a password is needed which should only happen on Nix systems. enable_wifi (bool): Optionally do not enable Wifi if set to False. Defaults to True. - kwargs (Dict): additional parameters for internal use / testing + **kwargs (Any): additional parameters for internal use / testing # noqa: DAR401 @@ -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 @@ -260,7 +261,7 @@ def http_setting(self) -> HttpSettings: """ return self._api.http_setting - async def open(self, timeout: int = 10, retries: int = 5) -> None: + async def open(self, timeout: int = 15, retries: int = 5) -> None: """Perform all initialization commands for ble and wifi For BLE: scan and find device, establish connection, discover characteristics, configure queries @@ -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 @@ -774,12 +775,12 @@ async def _put_json(self, message: HttpMessage, *args: Any, **kwargs: Any) -> Go return await super()._put_json(*args, message=message, **kwargs) @GoProBase._ensure_opened((GoProMessageInterface.BLE,)) - async def _open_wifi(self, timeout: int = 10, retries: int = 5) -> None: + async def _open_wifi(self, timeout: int = 30, retries: int = 5) -> None: """Connect to a GoPro device via Wifi. Args: - timeout (int): Time before considering establishment failed. Defaults to 15 seconds. - retries (int): How many tries to reconnect after failures. Defaults to 10. + timeout (int): Time before considering establishment failed. Defaults to 10 seconds. + retries (int): How many tries to reconnect after failures. Defaults to 5. Raises: ConnectFailed: Was not able to establish the Wifi Connection diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/logger.py b/demos/python/sdk_wireless_camera_control/open_gopro/logger.py index 4762238f..9750fa2a 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/logger.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/logger.py @@ -19,9 +19,8 @@ class Logger: Args: logger (logging.Logger): input logger that will be modified and then returned - output (Path, Optional): Path of log file for file stream handler. If not set, will not log to file. - modules (dict[str, int], Optional): Optional override of modules / levels. Will be merged into default - modules. + output (Path | None): Path of log file for file stream handler. If not set, will not log to file. + modules (list[str] | None): Optional override of modules / levels. Will be merged into default modules. """ _instances: dict[type[Logger], Logger] = {} @@ -37,7 +36,7 @@ def __new__(cls, *_: Any) -> Any: # noqa https://github.com/PyCQA/pydocstyle/is def __init__( self, - logger: Any, + logger: logging.Logger, output: Path | None = None, modules: list[str] | None = None, ) -> None: @@ -205,17 +204,18 @@ def build_log_rx_str(stringable: Any, asynchronous: bool = False) -> str: def setup_logging( - base: logging.Logger | str, output: Path | None = None, modules: list[str] | None = None + base: logging.Logger | str, + output: Path | None = None, + modules: list[str] | None = None, ) -> logging.Logger: """Configure the GoPro modules for logging and get a logger that can be used by the application This can only be called once and should be done at the top level of the application. Args: - base (Union[logging.Logger, str]): Name of application (i.e. __name__) or preconfigured logger to use as base - output (Path, Optional): Path of log file for file stream handler. If not set, will not log to file. - modules (dict[str, int], Optional): Optional override of modules / levels. Will be merged into default - modules. + base (logging.Logger | str): Name of application (i.e. __name__) or preconfigured logger to use as base + output (Path | None): Path of log file for file stream handler. If not set, will not log to file. + modules (list[str] | None): Optional override of modules / levels. Will be merged into default modules. Raises: TypeError: Base logger is not of correct type 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 4a20ff5b..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()) @@ -184,16 +184,15 @@ def __init__(self) -> None: self._parser: Parser | None = None @abstractmethod - def build(self) -> GoProResp: + def build(self) -> GoProResp[T]: """Build a response Returns: - GoProResp: built response + GoProResp[T]: built response """ - raise NotImplementedError -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. @@ -203,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 @@ -290,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__() @@ -305,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: @@ -313,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] @@ -467,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 ebaad7f7..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__) @@ -39,14 +39,13 @@ def transform(self, data: T) -> T: Returns: T: transformed data """ - raise NotImplementedError class BytesTransformer(BaseTransformer[bytes]): """Bytes to Bytes transformer interface""" -class JsonTransformer(BaseTransformer[types.JsonDict]): +class JsonTransformer(BaseTransformer[JsonDict]): """Json to json transformer interface""" @@ -71,10 +70,9 @@ def parse(self, data: T) -> T_co: # pylint: disable=method-hidden Returns: T_co: parsed output """ - raise NotImplementedError -class JsonParser(BaseParser[types.JsonDict, T_co]): +class JsonParser(BaseParser[JsonDict, T_co]): """Json to Target Type Parser Interface""" @@ -92,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: @@ -110,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 @@ -122,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: @@ -176,7 +174,6 @@ def parse(self, data: bytes) -> T_co: Returns: T_co: parsed output """ - raise NotImplementedError @abstractmethod def build(self, obj: Any) -> bytes: @@ -199,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: @@ -212,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 @@ -233,10 +230,10 @@ 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 (Union[SettingId, StatusId]): identifier to find container for + identifier (ResponseType): identifier to find container for Returns: - Callable: container if found else None + Callable | None: container if found else None """ try: parser_builder = cast(BytesParserBuilder, cls._global_parsers[identifier].byte_json_adapter) @@ -245,15 +242,15 @@ 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: - Optional[Parser]: parser if found, else None + Parser | None: parser if found, else None """ return cls._global_parsers.get(identifier) 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..5eb8918e 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/types.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/types.py @@ -7,8 +7,13 @@ from typing import Any, Callable, Coroutine, Union +try: + from typing import TypeAlias +except ImportError: + from typing_extensions import TypeAlias + 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 +26,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/open_gopro/util.py b/demos/python/sdk_wireless_camera_control/open_gopro/util.py index 059a4f10..ecee2cb0 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/util.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/util.py @@ -33,13 +33,13 @@ def __new__(cls, *_: Any) -> Any: # noqa https://github.com/PyCQA/pydocstyle/is return cls._instances[cls] -def map_keys(obj: Any, key: str, func: Callable[[Any], Any]) -> None: +def map_keys(obj: Any, key: str, func: Callable) -> None: """Map all matching keys (deeply searched) using the input function Args: obj (Any): object to modify in place key (str): key to search for to modify - func (Callable[[Any], Any]): mapping function + func (Callable): mapping function """ if isinstance(obj, dict): for k in obj.keys(): @@ -265,7 +265,7 @@ def add_cli_args_and_parse( wifi (bool): Add WiFi args?. Defaults to True. Returns: - argparse.ArgumentParser: modified argument parser + argparse.Namespace: modified argument parser """ # Common args parser.add_argument("--log", type=Path, help="Location to store detailed log", default="gopro_demo.log") diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/adapters/wireless.py b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/adapters/wireless.py index 71cb3c1c..43eb6909 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/adapters/wireless.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/adapters/wireless.py @@ -70,21 +70,17 @@ class WifiCli(WifiController): If interface is not specified (i.e. it is None), we will attempt to automatically discover a suitable interface - """ - - def __init__(self, interface: Optional[str] = None, password: Optional[str] = None) -> None: - """Constructor - Args: - interface (str, Optional): Interface. Defaults to None. - password (str, Optional): User Password for sudo. Defaults to None. + This will raise a RunTimeError if either: + - The system is using any language other then en_US + - We weren't able to find a suitable driver or auto-detect an interface after detecting driver - #noqa: DAR402 + Args: + interface (str | None): Interface. Defaults to None. + password (str | None): User Password for sudo. Defaults to None. + """ - Raises: - RuntimeError: The system is using any language other then en_US - RuntimeError: We weren't able to find a suitable driver or auto-detect an interface after detecting driver - """ + def __init__(self, interface: str | None = None, password: str | None = None) -> None: # noqa: DOC502 ensure_us_english() WifiController.__init__(self, interface, password) @@ -914,23 +910,26 @@ def connect(self, ssid: str, password: str, timeout: float = 15) -> bool: raise RuntimeError(response) os.remove(filename) - # Try to connect - response = cmd(f'netsh wlan connect ssid="{ssid}" name="{ssid}" interface="{self.interface}"') - if "was completed successfully" not in response: - raise RuntimeError(response) - # Wait for connection to establish - DELAY = 1 - while (current := self.current()) != (ssid, SsidState.CONNECTED): - logger.debug(f"Waiting {DELAY} second for Wi-Fi connection to establish...") - time.sleep(DELAY) - timeout -= DELAY - if timeout <= 0 or current[1] is SsidState.DISCONNECTED: - return False - - logger.info("Wifi connection established!") - self.ssid = ssid + for _ in range(5): + # Try to connect + response = cmd(f'netsh wlan connect ssid="{ssid}" name="{ssid}" interface="{self.interface}"') + if "was completed successfully" not in response: + raise RuntimeError(response) + # Wait for connection to establish + DELAY = 1 + while current := self.current(): + if current == (ssid, SsidState.CONNECTED): + logger.info("Wifi connection established!") + self.ssid = ssid + return True + logger.debug(f"Waiting {DELAY} second for Wi-Fi connection to establish...") + time.sleep(DELAY) + timeout -= DELAY + if timeout <= 0 or current[1] is SsidState.DISCONNECTED: + logger.debug("Wifi driver detected disconnect. Attempting retry...") + break - return True + return False def disconnect(self) -> bool: """Terminate the Wifi connection. @@ -1025,7 +1024,7 @@ def is_on(self) -> bool: return True def power(self, power: bool) -> bool: - """Enable or disbale the Wifi controller + """Enable or disable the Wifi controller Args: power (bool): True to enable, False to Disable diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/client.py b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/client.py index 0cdb821b..5fbdb1e1 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/client.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/client.py @@ -3,6 +3,8 @@ """Open GoPro WiFi Client Implementation""" +from __future__ import annotations + import logging from typing import Optional @@ -14,16 +16,15 @@ class WifiClient: - """A Wifi client that is composed of, among other things, a Wifi interface""" + """A Wifi client that is composed of, among other things, a Wifi interface - def __init__(self, controller: WifiController) -> None: - """Constructor + The interface is generic and can be set with the 'controller' argument - The interface is generic and can be set with the 'controller' argument + Args: + controller (WifiController): controller implementation to use for this client + """ - Args: - controller (WifiController): controller implementation to use for this client - """ + def __init__(self, controller: WifiController) -> None: self._controller = controller self.ssid: Optional[str] self.password: Optional[str] diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/controller.py b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/controller.py index fd1ca6bb..afe14cfa 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/controller.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/controller.py @@ -3,6 +3,8 @@ """Wifi Controller Interface Definition.""" +from __future__ import annotations + import logging from abc import ABC, abstractmethod from enum import IntEnum, auto @@ -22,15 +24,14 @@ class SsidState(IntEnum): class WifiController(ABC): - """Interface definition for a Wifi driver to be used by GoPro.""" + """Interface definition for a Wifi driver to be used by GoPro. - def __init__(self, interface: Optional[str] = None, password: Optional[str] = None) -> None: - """Constructor + Args: + interface (str | None): Wifi interface to use. Defaults to None (auto-detect). + password (str | None): user password to use for sudo. Defaults to None. + """ - Args: - interface (str, Optional): Wifi interface to use. Defaults to None (auto-detect). - password (str, Optional): user password to use for sudo. Defaults to None. - """ + def __init__(self, interface: str | None = None, password: str | None = None) -> None: self._target_interface = interface self._interface: str self._password = password @@ -47,7 +48,6 @@ def connect(self, ssid: str, password: str, timeout: float = 15) -> bool: Returns: bool: True if successful, False otherwise """ - raise NotImplementedError @abstractmethod def disconnect(self) -> bool: @@ -56,7 +56,6 @@ def disconnect(self) -> bool: Returns: bool: True if successful, False otherwise """ - raise NotImplementedError @abstractmethod def current(self) -> tuple[Optional[str], SsidState]: @@ -66,7 +65,6 @@ def current(self) -> tuple[Optional[str], SsidState]: tuple[Optional[str], SsidState]: Tuple of SSID str and state. If SSID is None, there is no current connection. """ - raise NotImplementedError @abstractmethod def available_interfaces(self) -> list[str]: @@ -75,7 +73,6 @@ def available_interfaces(self) -> list[str]: Returns: list[str]: list of interfaces """ - raise NotImplementedError @property def interface(self) -> str: @@ -126,8 +123,10 @@ def power(self, power: bool) -> bool: Args: power (bool): Enable if True. Disable if False. + + Returns: + bool: was the power request successful? """ - raise NotImplementedError @property @abstractmethod @@ -137,7 +136,6 @@ def is_on(self) -> bool: Returns: bool: True if yes. False if no. """ - raise NotImplementedError @property def sudo(self) -> str: diff --git a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/mdns_scanner.py b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/mdns_scanner.py index aee49e8c..c0f810ea 100644 --- a/demos/python/sdk_wireless_camera_control/open_gopro/wifi/mdns_scanner.py +++ b/demos/python/sdk_wireless_camera_control/open_gopro/wifi/mdns_scanner.py @@ -3,6 +3,8 @@ """MDNS utility functions""" +from __future__ import annotations + import asyncio import logging from typing import Any @@ -27,7 +29,7 @@ def add_service(self, zc: zeroconf.Zeroconf, type_: str, name: str) -> None: """Callback called by ServiceBrowser when a new service is discovered Args: - zc (Zeroconf): instantiated zeroconf object that owns the search + zc (zeroconf.Zeroconf): instantiated zeroconf object that owns the search type_ (str): name of mDNS service that search is occurring on name (str): discovered device """ @@ -83,6 +85,6 @@ async def get_all_services() -> list[str]: """Get all service names Returns: - tuple[str, ...]: tuple of service names + list[str]: list of service names """ return list(await zeroconf.asyncio.AsyncZeroconfServiceTypes.async_find()) diff --git a/demos/python/sdk_wireless_camera_control/poetry.lock b/demos/python/sdk_wireless_camera_control/poetry.lock index 602535c8..1b9d9336 100644 --- a/demos/python/sdk_wireless_camera_control/poetry.lock +++ b/demos/python/sdk_wireless_camera_control/poetry.lock @@ -14,35 +14,30 @@ files = [ [[package]] name = "annotated-types" -version = "0.6.0" +version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [[package]] name = "astroid" -version = "2.15.8" +version = "3.2.4" 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.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, + {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, ] [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" @@ -82,14 +77,14 @@ type-checking = ["mypy (>=1.9,<2.0)", "types-docutils (>=0.20,<0.21)", "typing-e [[package]] name = "babel" -version = "2.15.0" +version = "2.16.0" description = "Internationalization utilities" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, - {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, ] [package.extras] @@ -133,23 +128,23 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bleak" -version = "0.21.1" +version = "0.22.2" description = "Bluetooth Low Energy platform Agnostic Klient" category = "main" optional = false -python-versions = ">=3.8,<3.13" +python-versions = "<3.13,>=3.8" files = [ - {file = "bleak-0.21.1-py3-none-any.whl", hash = "sha256:ccec260a0f5ec02dd133d68b0351c0151b2ecf3ddd0bcabc4c04a1cdd7f33256"}, - {file = "bleak-0.21.1.tar.gz", hash = "sha256:ec4a1a2772fb315b992cbaa1153070c7e26968a52b0e2727035f443a1af5c18f"}, + {file = "bleak-0.22.2-py3-none-any.whl", hash = "sha256:8395c9e096f28e0ba1f3e6a8619fa21c327c484f720b7af3ea578d04f498a458"}, + {file = "bleak-0.22.2.tar.gz", hash = "sha256:09010c0f4bd843e7dcaa1652e1bfb2450ce690da08d4c6163f0723aaa986e9fe"}, ] [package.dependencies] async-timeout = {version = ">=3.0.0,<5", markers = "python_version < \"3.11\""} bleak-winrt = {version = ">=1.2.0,<2.0.0", markers = "platform_system == \"Windows\" and python_version < \"3.12\""} dbus-fast = {version = ">=1.83.0,<3", markers = "platform_system == \"Linux\""} -pyobjc-core = {version = ">=9.2,<10.0", markers = "platform_system == \"Darwin\""} -pyobjc-framework-CoreBluetooth = {version = ">=9.2,<10.0", markers = "platform_system == \"Darwin\""} -pyobjc-framework-libdispatch = {version = ">=9.2,<10.0", markers = "platform_system == \"Darwin\""} +pyobjc-core = {version = ">=10.0,<11.0", markers = "platform_system == \"Darwin\""} +pyobjc-framework-CoreBluetooth = {version = ">=10.0,<11.0", markers = "platform_system == \"Darwin\""} +pyobjc-framework-libdispatch = {version = ">=10.0,<11.0", markers = "platform_system == \"Darwin\""} typing-extensions = {version = ">=4.7.0", markers = "python_version < \"3.12\""} [[package]] @@ -175,14 +170,14 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] @@ -425,73 +420,60 @@ toml = ["tomli"] [[package]] name = "coverage-badge" -version = "1.1.0" +version = "1.1.2" description = "Generate coverage badges for Coverage.py." category = "dev" optional = false python-versions = "*" files = [ - {file = "coverage-badge-1.1.0.tar.gz", hash = "sha256:c824a106503e981c02821e7d32f008fb3984b2338aa8c3800ec9357e33345b78"}, - {file = "coverage_badge-1.1.0-py2.py3-none-any.whl", hash = "sha256:e365d56e5202e923d1b237f82defd628a02d1d645a147f867ac85c58c81d7997"}, + {file = "coverage_badge-1.1.2-py2.py3-none-any.whl", hash = "sha256:d8413ce51c91043a1692b943616b450868cbeeb0ea6a0c54a32f8318c9c96ff7"}, + {file = "coverage_badge-1.1.2.tar.gz", hash = "sha256:fe7ed58a3b72dad85a553b64a99e963dea3847dcd0b8ddd2b38a00333618642c"}, ] [package.dependencies] coverage = "*" - -[[package]] -name = "darglint" -version = "1.8.1" -description = "A utility for ensuring Google-style docstrings stay up to date with the source code." -category = "dev" -optional = false -python-versions = ">=3.6,<4.0" -files = [ - {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, - {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, -] +setuptools = "*" [[package]] name = "dbus-fast" -version = "2.21.2" +version = "2.24.0" description = "A faster version of dbus-next" category = "main" optional = false -python-versions = "<4.0,>=3.7" +python-versions = "<4.0,>=3.8" files = [ - {file = "dbus_fast-2.21.2-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b5f79edcb0dd48e98b1a1e3e4a655fd0ecc2ba72275f9e8379e8655b4411edcc"}, - {file = "dbus_fast-2.21.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40aa9068759bbf7e062f074c965b391b95f18f897cc9be6eb906ee48a6f77724"}, - {file = "dbus_fast-2.21.2-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:d2406b838ccbda9bd49dda4a7620ce228da306cd8f9a3f8c9f42b2d792a491fb"}, - {file = "dbus_fast-2.21.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ed431895630135da9cec736326304f0833ac31919043efdbecf8f6c7bed40d05"}, - {file = "dbus_fast-2.21.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:90f09498ac91f0e6ddc7fa569e851a2b258a70917cd07ae8412ad5725ef1d411"}, - {file = "dbus_fast-2.21.2-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b17f1eafeaa825e8933a5394157db9e0a24e65eac188a244dbbbc01dc23fde7a"}, - {file = "dbus_fast-2.21.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9f4191f7108f9433e5c017915e60ec57231aaf58c82fde6e20bd497998ebc97"}, - {file = "dbus_fast-2.21.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3b96a645cbd035f47f3b934130cd0ae977c043480ad7fe9838f78fdcb480c189"}, - {file = "dbus_fast-2.21.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bc696304ce0f5da374ddfb3e83273e9d89602a8f20e7fab57b079378f2cb5789"}, - {file = "dbus_fast-2.21.2-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b5e2015a385f0b364eff1827b151313429d3148d2718d679bec8a9c67b78721a"}, - {file = "dbus_fast-2.21.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32efcbe276a4fdf6946450c512355e7ae22836cf3595d48c59330687cda52117"}, - {file = "dbus_fast-2.21.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:601c3c8796e7edd23bce0432e44ca8f0b85c48a17ab5258f57cd8fe815f9c07a"}, - {file = "dbus_fast-2.21.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:194899057b8382c1902c32e1a565a2d47bcc99e06aafe9d660348394532a4bf6"}, - {file = "dbus_fast-2.21.2-cp37-cp37m-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:81ac390d4e26711b3ac46b3dd81a29bcbc1eddd4a408b336c67f0c94eb6d7ff0"}, - {file = "dbus_fast-2.21.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f056f2bfee24e87a4184202d3b108a56176344303bb1278988f13f5e90777da"}, - {file = "dbus_fast-2.21.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9ba884d102e069e105f22986fccf1d21776e6ced11f4b75aeddcc37e728a80fd"}, - {file = "dbus_fast-2.21.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:60d989030403cc1611105bec6a90df22967e523ae28486dee5f9bd644e37f797"}, - {file = "dbus_fast-2.21.2-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:aabe539f0e9961a1beb6e8c0078112a1a60de18958335678edb3f26021951ff9"}, - {file = "dbus_fast-2.21.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6edec4f92d32b9a288b38457a114086a0d5f5fdec9c3e9b7ff6052fd45963c1d"}, - {file = "dbus_fast-2.21.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37e6f717dedc299fc15ab8f5ec5b180725d2b896ba1aaef07c1921df0b7113a0"}, - {file = "dbus_fast-2.21.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eade5ed18327bf306b75e525ded98c08921e1b21d42e715b7f0a1371a7669168"}, - {file = "dbus_fast-2.21.2-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:2fd1be6967a92957f517dbd3755ee7cddc128ec840af2ef4ad6fb023a0dac74d"}, - {file = "dbus_fast-2.21.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5db0737471e60228c1a6aabecbf883c972f0b9e50bf7fc0878a8b35ebdf1d1e"}, - {file = "dbus_fast-2.21.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6c6f1fda6f318061a023d6da96ee50ad2d30c04557012a60a0f1abd39c2a8704"}, - {file = "dbus_fast-2.21.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0b78f2116fb745a7623c8e18d9c435bfe4732e4f9284a923c4b9a44ef68ae2d4"}, - {file = "dbus_fast-2.21.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:886ce5750d4e64636bd933f22513e9ba06b7ee9650f28699c553c162b52db666"}, - {file = "dbus_fast-2.21.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3159f1cecd4b86f565c01da787ad6eaa57e8ba210d355836fa849e4c0b1ee57"}, - {file = "dbus_fast-2.21.2-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:51279b69ac6b872208f3aa1b00b910dd9ef9c3d625b79eb378405dbd72a29cab"}, - {file = "dbus_fast-2.21.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29f07ef89e35b93afa87dea86abec2aff68802572944485250f50def15dc5ef8"}, - {file = "dbus_fast-2.21.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:38138fc5a24797cc443c6894d25497271ccf3399c8aa8cdba228a7bdda2d2921"}, - {file = "dbus_fast-2.21.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afde99d085a330e8aed59535d808636f1f563cb08d12900d0e415508e6270a1d"}, - {file = "dbus_fast-2.21.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c2bb0fd813bf3cafc6796d86d42cc8a9d37c2633d973dd963c3ad4c080d7061d"}, - {file = "dbus_fast-2.21.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:044eec5d0668d3229480094f5b2aefafb336afa6976d686bd0cd8770eee1bb2c"}, - {file = "dbus_fast-2.21.2.tar.gz", hash = "sha256:8645187b2e86c5141217adcb462d6dbecd37fb2ab8705f66b3773a66206ef83d"}, + {file = "dbus_fast-2.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0f69c272ef1376b5f3a8c899b6aa34d72a568935f90ac269abdf4a74241b57b"}, + {file = "dbus_fast-2.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:014441b49e250f5709b9e43dbdd3fee680edf2d2b50d934ef6ffe1814d16457d"}, + {file = "dbus_fast-2.24.0-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:1516eef9726da1de870adaad690ed4b2dc45d2c7e3926e07abb3ac5309fd04e2"}, + {file = "dbus_fast-2.24.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:aaf255b28b18c1b3caef03a1e3c66716ed23a4fc3e153ccdc8a0558c1078b257"}, + {file = "dbus_fast-2.24.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:884b09ee6034fae49dde65fd2d2575d1876ff96e893a877778be86417922f139"}, + {file = "dbus_fast-2.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87ed7661e38457789c8d7f10b067c83267b0610c0de39896bec2ff083a2e0047"}, + {file = "dbus_fast-2.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddb5116858e01dcad2326f0519bb805c71da93e0c47ad8a0cfa3730b72de9a79"}, + {file = "dbus_fast-2.24.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7be081fd6c1a78fd12a98c6ee47fc2d7437e85f800b037cde189beabf5067a71"}, + {file = "dbus_fast-2.24.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3acc7893804d1ca9d438df9742e08b45a9f6e70924e2f706378742f766570191"}, + {file = "dbus_fast-2.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1bc8a95cc83556b0e12469ad7c14830419ab3a8bdb1f6ff2a0844c3d0558740"}, + {file = "dbus_fast-2.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e19be18299601f04510bac045172aee53fc04f027f58ee5ade960ef58f8bd716"}, + {file = "dbus_fast-2.24.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f7f45957f3f705d52b586677a44e16a7338e7ac72d616a06048a73755e11553"}, + {file = "dbus_fast-2.24.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aec31051f632898b12f4ad0841fc89b32ef7918ee0590a7ff31c729660bc4262"}, + {file = "dbus_fast-2.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d14686d9709924888735c88f941c7c4fba95672abd658c050ba6dfd21ce3ea92"}, + {file = "dbus_fast-2.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3697fbf642ea0d36cd8907e6b5a28c336b45e08710e42d96f32a0e881ed3111c"}, + {file = "dbus_fast-2.24.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:11f69848d86d5f68e4efcf7e40d1c2f1de912b5d8ca0a76ebe4e20e68e6603f8"}, + {file = "dbus_fast-2.24.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:58d5d630c165148c76daef056a5443daacf9c0eabcc28e67d5e9951d5a1a7504"}, + {file = "dbus_fast-2.24.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aac69b8e0b3f3b918e06a3448c2b40c8868bddfa715dfaf7f5bbde4d76783f6"}, + {file = "dbus_fast-2.24.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90ce8cc1f99da1fac661fda7ae76afc3373d1afb709a8f1c525ddd38c63f7c4c"}, + {file = "dbus_fast-2.24.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:81621cbd5a172cdfe3649032405e5bfeeb8dafef114bbc48949563d56a082a8b"}, + {file = "dbus_fast-2.24.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:fcd754fd6cca77fb73815f7ca4d8ae14b72aacdfb027359adfb9ab03e21615ab"}, + {file = "dbus_fast-2.24.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84ac47e47ee88f80e28004722b3a0398777309c47cb0cd502e8db6afdd836fa6"}, + {file = "dbus_fast-2.24.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4065c11993e70c0cae849b2045862b6f221f3d81074488b22257aa898b04c803"}, + {file = "dbus_fast-2.24.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c291dbbd3920f4ff4a3051e82d107489cabdb5725c57638b379db74b631b016d"}, + {file = "dbus_fast-2.24.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:637fa5db4c6c0916cd9b08ba31a59688bd61ff5f796c20ab6801eefb1d9ac712"}, + {file = "dbus_fast-2.24.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48869b2eafdcb62d0344e1ed93c97e4a55e981c399dfd9feb3874ebd461feba7"}, + {file = "dbus_fast-2.24.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a2290482d5b5723d0008ba422c0270d6ba7ca28440acfc5bcb96b4da28a21b7"}, + {file = "dbus_fast-2.24.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:415c5e0673d219cd2254c3d261ca90f4fe0ebc618ab9735b994365387d83f94c"}, + {file = "dbus_fast-2.24.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e33f70bf79fe431d7914981ef7792041306675877611c898a1da3a87089fc2de"}, + {file = "dbus_fast-2.24.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10c8046391cce8e04f5c6be328743d32614c8c3b59ed2878f7b1edc55ac1c473"}, + {file = "dbus_fast-2.24.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux_2_5_x86_64.manylinux1_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a04269b8301944b320a40b08909db26d719d35f5ed5d2f05947436428a1bab99"}, + {file = "dbus_fast-2.24.0.tar.gz", hash = "sha256:72b59c51e882300fd7f6d5bec8fb84ae8dea58040ade1d15c62c7fd9fa546f35"}, ] [[package]] @@ -510,28 +492,40 @@ files = [ graph = ["objgraph (>=1.7.2)"] profile = ["gprof2dot (>=2022.7.29)"] +[[package]] +name = "docstring-parser-fork" +version = "0.0.9" +description = "Parse Python docstrings in reST, Google and Numpydoc format" +category = "dev" +optional = false +python-versions = "<4.0,>=3.7" +files = [ + {file = "docstring_parser_fork-0.0.9-py3-none-any.whl", hash = "sha256:0be85ad00cb25bf5beeb673e46e777facf0f47552fa3a7570d120ef7e3374401"}, + {file = "docstring_parser_fork-0.0.9.tar.gz", hash = "sha256:95b23cc5092af85080c716a6da68360f5ae4fcffa75f4a3aca5e539783cbcc3d"}, +] + [[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]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -539,14 +533,14 @@ test = ["pytest (>=6)"] [[package]] name = "idna" -version = "3.7" +version = "3.8" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] [[package]] @@ -575,23 +569,23 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.1.0" +version = "8.4.0" description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, + {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, + {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "iniconfig" @@ -638,53 +632,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" @@ -769,45 +716,45 @@ files = [ [[package]] name = "mypy" -version = "1.10.0" +version = "1.11.2" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da1cbf08fb3b851ab3b9523a884c232774008267b1f83371ace57f412fe308c2"}, - {file = "mypy-1.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:12b6bfc1b1a66095ab413160a6e520e1dc076a28f3e22f7fb25ba3b000b4ef99"}, - {file = "mypy-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e36fb078cce9904c7989b9693e41cb9711e0600139ce3970c6ef814b6ebc2b2"}, - {file = "mypy-1.10.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2b0695d605ddcd3eb2f736cd8b4e388288c21e7de85001e9f85df9187f2b50f9"}, - {file = "mypy-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd777b780312ddb135bceb9bc8722a73ec95e042f911cc279e2ec3c667076051"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3be66771aa5c97602f382230165b856c231d1277c511c9a8dd058be4784472e1"}, - {file = "mypy-1.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8b2cbaca148d0754a54d44121b5825ae71868c7592a53b7292eeb0f3fdae95ee"}, - {file = "mypy-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ec404a7cbe9fc0e92cb0e67f55ce0c025014e26d33e54d9e506a0f2d07fe5de"}, - {file = "mypy-1.10.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e22e1527dc3d4aa94311d246b59e47f6455b8729f4968765ac1eacf9a4760bc7"}, - {file = "mypy-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:a87dbfa85971e8d59c9cc1fcf534efe664d8949e4c0b6b44e8ca548e746a8d53"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a781f6ad4bab20eef8b65174a57e5203f4be627b46291f4589879bf4e257b97b"}, - {file = "mypy-1.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b808e12113505b97d9023b0b5e0c0705a90571c6feefc6f215c1df9381256e30"}, - {file = "mypy-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f55583b12156c399dce2df7d16f8a5095291354f1e839c252ec6c0611e86e2e"}, - {file = "mypy-1.10.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4cf18f9d0efa1b16478c4c129eabec36148032575391095f73cae2e722fcf9d5"}, - {file = "mypy-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:bc6ac273b23c6b82da3bb25f4136c4fd42665f17f2cd850771cb600bdd2ebeda"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9fd50226364cd2737351c79807775136b0abe084433b55b2e29181a4c3c878c0"}, - {file = "mypy-1.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f90cff89eea89273727d8783fef5d4a934be2fdca11b47def50cf5d311aff727"}, - {file = "mypy-1.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fcfc70599efde5c67862a07a1aaf50e55bce629ace26bb19dc17cece5dd31ca4"}, - {file = "mypy-1.10.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:075cbf81f3e134eadaf247de187bd604748171d6b79736fa9b6c9685b4083061"}, - {file = "mypy-1.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:3f298531bca95ff615b6e9f2fc0333aae27fa48052903a0ac90215021cdcfa4f"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fa7ef5244615a2523b56c034becde4e9e3f9b034854c93639adb667ec9ec2976"}, - {file = "mypy-1.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3236a4c8f535a0631f85f5fcdffba71c7feeef76a6002fcba7c1a8e57c8be1ec"}, - {file = "mypy-1.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a2b5cdbb5dd35aa08ea9114436e0d79aceb2f38e32c21684dcf8e24e1e92821"}, - {file = "mypy-1.10.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92f93b21c0fe73dc00abf91022234c79d793318b8a96faac147cd579c1671746"}, - {file = "mypy-1.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:28d0e038361b45f099cc086d9dd99c15ff14d0188f44ac883010e172ce86c38a"}, - {file = "mypy-1.10.0-py3-none-any.whl", hash = "sha256:f8c083976eb530019175aabadb60921e73b4f45736760826aa1689dda8208aee"}, - {file = "mypy-1.10.0.tar.gz", hash = "sha256:3d087fcbec056c4ee34974da493a826ce316947485cef3901f511848e687c131"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d42a6dd818ffce7be66cce644f1dff482f1d97c53ca70908dff0b9ddc120b77a"}, + {file = "mypy-1.11.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:801780c56d1cdb896eacd5619a83e427ce436d86a3bdf9112527f24a66618fef"}, + {file = "mypy-1.11.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41ea707d036a5307ac674ea172875f40c9d55c5394f888b168033177fce47383"}, + {file = "mypy-1.11.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6e658bd2d20565ea86da7d91331b0eed6d2eee22dc031579e6297f3e12c758c8"}, + {file = "mypy-1.11.2-cp310-cp310-win_amd64.whl", hash = "sha256:478db5f5036817fe45adb7332d927daa62417159d49783041338921dcf646fc7"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75746e06d5fa1e91bfd5432448d00d34593b52e7e91a187d981d08d1f33d4385"}, + {file = "mypy-1.11.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a976775ab2256aadc6add633d44f100a2517d2388906ec4f13231fafbb0eccca"}, + {file = "mypy-1.11.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cd953f221ac1379050a8a646585a29574488974f79d8082cedef62744f0a0104"}, + {file = "mypy-1.11.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:57555a7715c0a34421013144a33d280e73c08df70f3a18a552938587ce9274f4"}, + {file = "mypy-1.11.2-cp311-cp311-win_amd64.whl", hash = "sha256:36383a4fcbad95f2657642a07ba22ff797de26277158f1cc7bd234821468b1b6"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e8960dbbbf36906c5c0b7f4fbf2f0c7ffb20f4898e6a879fcf56a41a08b0d318"}, + {file = "mypy-1.11.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:06d26c277962f3fb50e13044674aa10553981ae514288cb7d0a738f495550b36"}, + {file = "mypy-1.11.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e7184632d89d677973a14d00ae4d03214c8bc301ceefcdaf5c474866814c987"}, + {file = "mypy-1.11.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3a66169b92452f72117e2da3a576087025449018afc2d8e9bfe5ffab865709ca"}, + {file = "mypy-1.11.2-cp312-cp312-win_amd64.whl", hash = "sha256:969ea3ef09617aff826885a22ece0ddef69d95852cdad2f60c8bb06bf1f71f70"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:37c7fa6121c1cdfcaac97ce3d3b5588e847aa79b580c1e922bb5d5d2902df19b"}, + {file = "mypy-1.11.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4a8a53bc3ffbd161b5b2a4fff2f0f1e23a33b0168f1c0778ec70e1a3d66deb86"}, + {file = "mypy-1.11.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ff93107f01968ed834f4256bc1fc4475e2fecf6c661260066a985b52741ddce"}, + {file = "mypy-1.11.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:edb91dded4df17eae4537668b23f0ff6baf3707683734b6a818d5b9d0c0c31a1"}, + {file = "mypy-1.11.2-cp38-cp38-win_amd64.whl", hash = "sha256:ee23de8530d99b6db0573c4ef4bd8f39a2a6f9b60655bf7a1357e585a3486f2b"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:801ca29f43d5acce85f8e999b1e431fb479cb02d0e11deb7d2abb56bdaf24fd6"}, + {file = "mypy-1.11.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af8d155170fcf87a2afb55b35dc1a0ac21df4431e7d96717621962e4b9192e70"}, + {file = "mypy-1.11.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7821776e5c4286b6a13138cc935e2e9b6fde05e081bdebf5cdb2bb97c9df81d"}, + {file = "mypy-1.11.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:539c570477a96a4e6fb718b8d5c3e0c0eba1f485df13f86d2970c91f0673148d"}, + {file = "mypy-1.11.2-cp39-cp39-win_amd64.whl", hash = "sha256:3f14cd3d386ac4d05c5a39a51b84387403dadbd936e17cb35882134d4f8f0d24"}, + {file = "mypy-1.11.2-py3-none-any.whl", hash = "sha256:b499bc07dbdcd3de92b0a8b29fdf592c111276f6a12fe29c30f6c417dd546d12"}, + {file = "mypy-1.11.2.tar.gz", hash = "sha256:7f9993ad3e0ffdc95c2a14b66dee63729f021968bff8ad911867579c65d13a79"}, ] [package.dependencies] mypy-extensions = ">=1.0.0" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.1.0" +typing-extensions = ">=4.6.0" [package.extras] dmypy = ["psutil (>=4.0)"] @@ -829,65 +776,137 @@ files = [ [[package]] name = "numpy" -version = "1.26.4" +version = "2.0.2" description = "Fundamental package for array computing in Python" category = "main" optional = true python-versions = ">=3.9" files = [ - {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, - {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, - {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, - {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, - {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, - {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, - {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, - {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, - {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, - {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, - {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b"}, + {file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd"}, + {file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318"}, + {file = "numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8"}, + {file = "numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326"}, + {file = "numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97"}, + {file = "numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a"}, + {file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669"}, + {file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951"}, + {file = "numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9"}, + {file = "numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15"}, + {file = "numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4"}, + {file = "numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c"}, + {file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692"}, + {file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a"}, + {file = "numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c"}, + {file = "numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded"}, + {file = "numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5"}, + {file = "numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729"}, + {file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1"}, + {file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd"}, + {file = "numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d"}, + {file = "numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d"}, + {file = "numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa"}, + {file = "numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385"}, + {file = "numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78"}, +] + +[[package]] +name = "numpy" +version = "2.1.1" +description = "Fundamental package for array computing in Python" +category = "main" +optional = true +python-versions = ">=3.10" +files = [ + {file = "numpy-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8a0e34993b510fc19b9a2ce7f31cb8e94ecf6e924a40c0c9dd4f62d0aac47d9"}, + {file = "numpy-2.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7dd86dfaf7c900c0bbdcb8b16e2f6ddf1eb1fe39c6c8cca6e94844ed3152a8fd"}, + {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:5889dd24f03ca5a5b1e8a90a33b5a0846d8977565e4ae003a63d22ecddf6782f"}, + {file = "numpy-2.1.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:59ca673ad11d4b84ceb385290ed0ebe60266e356641428c845b39cd9df6713ab"}, + {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13ce49a34c44b6de5241f0b38b07e44c1b2dcacd9e36c30f9c2fcb1bb5135db7"}, + {file = "numpy-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913cc1d311060b1d409e609947fa1b9753701dac96e6581b58afc36b7ee35af6"}, + {file = "numpy-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:caf5d284ddea7462c32b8d4a6b8af030b6c9fd5332afb70e7414d7fdded4bfd0"}, + {file = "numpy-2.1.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:57eb525e7c2a8fdee02d731f647146ff54ea8c973364f3b850069ffb42799647"}, + {file = "numpy-2.1.1-cp310-cp310-win32.whl", hash = "sha256:9a8e06c7a980869ea67bbf551283bbed2856915f0a792dc32dd0f9dd2fb56728"}, + {file = "numpy-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:d10c39947a2d351d6d466b4ae83dad4c37cd6c3cdd6d5d0fa797da56f710a6ae"}, + {file = "numpy-2.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0d07841fd284718feffe7dd17a63a2e6c78679b2d386d3e82f44f0108c905550"}, + {file = "numpy-2.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b5613cfeb1adfe791e8e681128f5f49f22f3fcaa942255a6124d58ca59d9528f"}, + {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:0b8cc2715a84b7c3b161f9ebbd942740aaed913584cae9cdc7f8ad5ad41943d0"}, + {file = "numpy-2.1.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b49742cdb85f1f81e4dc1b39dcf328244f4d8d1ded95dea725b316bd2cf18c95"}, + {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d5f8a8e3bc87334f025194c6193e408903d21ebaeb10952264943a985066ca"}, + {file = "numpy-2.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d51fc141ddbe3f919e91a096ec739f49d686df8af254b2053ba21a910ae518bf"}, + {file = "numpy-2.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:98ce7fb5b8063cfdd86596b9c762bf2b5e35a2cdd7e967494ab78a1fa7f8b86e"}, + {file = "numpy-2.1.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:24c2ad697bd8593887b019817ddd9974a7f429c14a5469d7fad413f28340a6d2"}, + {file = "numpy-2.1.1-cp311-cp311-win32.whl", hash = "sha256:397bc5ce62d3fb73f304bec332171535c187e0643e176a6e9421a6e3eacef06d"}, + {file = "numpy-2.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:ae8ce252404cdd4de56dcfce8b11eac3c594a9c16c231d081fb705cf23bd4d9e"}, + {file = "numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e"}, + {file = "numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe"}, + {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f"}, + {file = "numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521"}, + {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b"}, + {file = "numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201"}, + {file = "numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a"}, + {file = "numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313"}, + {file = "numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed"}, + {file = "numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270"}, + {file = "numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5"}, + {file = "numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5"}, + {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136"}, + {file = "numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0"}, + {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb"}, + {file = "numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df"}, + {file = "numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78"}, + {file = "numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556"}, + {file = "numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b"}, + {file = "numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0"}, + {file = "numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553"}, + {file = "numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480"}, + {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f"}, + {file = "numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468"}, + {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef"}, + {file = "numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f"}, + {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c"}, + {file = "numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec"}, + {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7be6a07520b88214ea85d8ac8b7d6d8a1839b0b5cb87412ac9f49fa934eb15d5"}, + {file = "numpy-2.1.1-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:52ac2e48f5ad847cd43c4755520a2317f3380213493b9d8a4c5e37f3b87df504"}, + {file = "numpy-2.1.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a95ca3560a6058d6ea91d4629a83a897ee27c00630aed9d933dff191f170cd"}, + {file = "numpy-2.1.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:99f4a9ee60eed1385a86e82288971a51e71df052ed0b2900ed30bc840c0f2e39"}, + {file = "numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd"}, ] [[package]] name = "opencv-python" -version = "4.9.0.80" +version = "4.10.0.84" description = "Wrapper package for OpenCV python bindings." category = "main" optional = true python-versions = ">=3.6" files = [ - {file = "opencv-python-4.9.0.80.tar.gz", hash = "sha256:1a9f0e6267de3a1a1db0c54213d022c7c8b5b9ca4b580e80bdc58516c922c9e1"}, - {file = "opencv_python-4.9.0.80-cp37-abi3-macosx_10_16_x86_64.whl", hash = "sha256:7e5f7aa4486651a6ebfa8ed4b594b65bd2d2f41beeb4241a3e4b1b85acbbbadb"}, - {file = "opencv_python-4.9.0.80-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:71dfb9555ccccdd77305fc3dcca5897fbf0cf28b297c51ee55e079c065d812a3"}, - {file = "opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b34a52e9da36dda8c151c6394aed602e4b17fa041df0b9f5b93ae10b0fcca2a"}, - {file = "opencv_python-4.9.0.80-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4088cab82b66a3b37ffc452976b14a3c599269c247895ae9ceb4066d8188a57"}, - {file = "opencv_python-4.9.0.80-cp37-abi3-win32.whl", hash = "sha256:dcf000c36dd1651118a2462257e3a9e76db789a78432e1f303c7bac54f63ef6c"}, - {file = "opencv_python-4.9.0.80-cp37-abi3-win_amd64.whl", hash = "sha256:3f16f08e02b2a2da44259c7cc712e779eff1dd8b55fdb0323e8cab09548086c0"}, + {file = "opencv-python-4.10.0.84.tar.gz", hash = "sha256:72d234e4582e9658ffea8e9cae5b63d488ad06994ef12d81dc303b17472f3526"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:fc182f8f4cda51b45f01c64e4cbedfc2f00aff799debebc305d8d0210c43f251"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-macosx_12_0_x86_64.whl", hash = "sha256:71e575744f1d23f79741450254660442785f45a0797212852ee5199ef12eed98"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09a332b50488e2dda866a6c5573ee192fe3583239fb26ff2f7f9ceb0bc119ea6"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ace140fc6d647fbe1c692bcb2abce768973491222c067c131d80957c595b71f"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-win32.whl", hash = "sha256:2db02bb7e50b703f0a2d50c50ced72e95c574e1e5a0bb35a8a86d0b35c98c236"}, + {file = "opencv_python-4.10.0.84-cp37-abi3-win_amd64.whl", hash = "sha256:32dbbd94c26f611dc5cc6979e6b7aa1f55a64d6b463cc1dcd3c95505a63e48fe"}, ] [package.dependencies] @@ -895,10 +914,10 @@ numpy = [ {version = ">=1.21.0", markers = "python_version <= \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""}, {version = ">=1.21.2", markers = "python_version >= \"3.10\""}, {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\""}, + {version = ">=1.23.5", markers = "python_version >= \"3.11\""}, {version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\""}, {version = ">=1.17.0", markers = "python_version >= \"3.7\""}, {version = ">=1.17.3", markers = "python_version >= \"3.8\""}, - {version = ">=1.23.5", markers = "python_version >= \"3.11\""}, ] [[package]] @@ -1037,14 +1056,14 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "4.2.1" +version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, - {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] [package.extras] @@ -1070,14 +1089,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "poethepoet" -version = "0.26.1" +version = "0.28.0" description = "A task runner that works well with poetry." category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "poethepoet-0.26.1-py3-none-any.whl", hash = "sha256:aa43b443fec5d17d7e76771cccd484e5285805301721a74f059c483ad3276edd"}, - {file = "poethepoet-0.26.1.tar.gz", hash = "sha256:aaad8541f6072617a60bcff2562d00779b58b353bd0f1847b06d8d0f2b6dc192"}, + {file = "poethepoet-0.28.0-py3-none-any.whl", hash = "sha256:db6946ff39a1244235950cd720ee7182107f64126d3dcc64c9a996cc4d755404"}, + {file = "poethepoet-0.28.0.tar.gz", hash = "sha256:5dc3ee036ab0c93e918b5caed628274618b07d788e5cff6c4ae480913cbe009c"}, ] [package.dependencies] @@ -1145,111 +1164,122 @@ files = [ [[package]] name = "pydantic" -version = "2.7.1" +version = "2.9.0" description = "Data validation using Python type hints" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, - {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, + {file = "pydantic-2.9.0-py3-none-any.whl", hash = "sha256:f66a7073abd93214a20c5f7b32d56843137a7a2e70d02111f3be287035c45370"}, + {file = "pydantic-2.9.0.tar.gz", hash = "sha256:c7a8a9fdf7d100afa49647eae340e2d23efa382466a8d177efcd1381e9be5598"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.18.2" -typing-extensions = ">=4.6.1" +pydantic-core = "2.23.2" +typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} +tzdata = {version = "*", markers = "python_version >= \"3.9\""} [package.extras] email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.2" +version = "2.23.2" description = "Core functionality for Pydantic validation and serialization" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, - {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, - {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, - {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, - {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, - {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, - {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, - {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, - {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, - {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, - {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, - {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, - {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, - {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, - {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, - {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, - {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, - {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, - {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, - {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, - {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, - {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, - {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, - {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, - {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, - {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, - {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, - {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, - {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, - {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, - {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, - {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, - {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, + {file = "pydantic_core-2.23.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7d0324a35ab436c9d768753cbc3c47a865a2cbc0757066cb864747baa61f6ece"}, + {file = "pydantic_core-2.23.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:276ae78153a94b664e700ac362587c73b84399bd1145e135287513442e7dfbc7"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:964c7aa318da542cdcc60d4a648377ffe1a2ef0eb1e996026c7f74507b720a78"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1cf842265a3a820ebc6388b963ead065f5ce8f2068ac4e1c713ef77a67b71f7c"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae90b9e50fe1bd115b24785e962b51130340408156d34d67b5f8f3fa6540938e"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ae65fdfb8a841556b52935dfd4c3f79132dc5253b12c0061b96415208f4d622"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c8aa40f6ca803f95b1c1c5aeaee6237b9e879e4dfb46ad713229a63651a95fb"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c53100c8ee5a1e102766abde2158077d8c374bee0639201f11d3032e3555dfbc"}, + {file = "pydantic_core-2.23.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6b9dd6aa03c812017411734e496c44fef29b43dba1e3dd1fa7361bbacfc1354"}, + {file = "pydantic_core-2.23.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b18cf68255a476b927910c6873d9ed00da692bb293c5b10b282bd48a0afe3ae2"}, + {file = "pydantic_core-2.23.2-cp310-none-win32.whl", hash = "sha256:e460475719721d59cd54a350c1f71c797c763212c836bf48585478c5514d2854"}, + {file = "pydantic_core-2.23.2-cp310-none-win_amd64.whl", hash = "sha256:5f3cf3721eaf8741cffaf092487f1ca80831202ce91672776b02b875580e174a"}, + {file = "pydantic_core-2.23.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7ce8e26b86a91e305858e018afc7a6e932f17428b1eaa60154bd1f7ee888b5f8"}, + {file = "pydantic_core-2.23.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e9b24cca4037a561422bf5dc52b38d390fb61f7bfff64053ce1b72f6938e6b2"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753294d42fb072aa1775bfe1a2ba1012427376718fa4c72de52005a3d2a22178"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:257d6a410a0d8aeb50b4283dea39bb79b14303e0fab0f2b9d617701331ed1515"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8319e0bd6a7b45ad76166cc3d5d6a36c97d0c82a196f478c3ee5346566eebfd"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a05c0240f6c711eb381ac392de987ee974fa9336071fb697768dfdb151345ce"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d5b0ff3218858859910295df6953d7bafac3a48d5cd18f4e3ed9999efd2245f"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:96ef39add33ff58cd4c112cbac076726b96b98bb8f1e7f7595288dcfb2f10b57"}, + {file = "pydantic_core-2.23.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0102e49ac7d2df3379ef8d658d3bc59d3d769b0bdb17da189b75efa861fc07b4"}, + {file = "pydantic_core-2.23.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a6612c2a844043e4d10a8324c54cdff0042c558eef30bd705770793d70b224aa"}, + {file = "pydantic_core-2.23.2-cp311-none-win32.whl", hash = "sha256:caffda619099cfd4f63d48462f6aadbecee3ad9603b4b88b60cb821c1b258576"}, + {file = "pydantic_core-2.23.2-cp311-none-win_amd64.whl", hash = "sha256:6f80fba4af0cb1d2344869d56430e304a51396b70d46b91a55ed4959993c0589"}, + {file = "pydantic_core-2.23.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c83c64d05ffbbe12d4e8498ab72bdb05bcc1026340a4a597dc647a13c1605ec"}, + {file = "pydantic_core-2.23.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6294907eaaccf71c076abdd1c7954e272efa39bb043161b4b8aa1cd76a16ce43"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a801c5e1e13272e0909c520708122496647d1279d252c9e6e07dac216accc41"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cc0c316fba3ce72ac3ab7902a888b9dc4979162d320823679da270c2d9ad0cad"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b06c5d4e8701ac2ba99a2ef835e4e1b187d41095a9c619c5b185c9068ed2a49"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82764c0bd697159fe9947ad59b6db6d7329e88505c8f98990eb07e84cc0a5d81"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b1a195efd347ede8bcf723e932300292eb13a9d2a3c1f84eb8f37cbbc905b7f"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7efb12e5071ad8d5b547487bdad489fbd4a5a35a0fc36a1941517a6ad7f23e0"}, + {file = "pydantic_core-2.23.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5dd0ec5f514ed40e49bf961d49cf1bc2c72e9b50f29a163b2cc9030c6742aa73"}, + {file = "pydantic_core-2.23.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:820f6ee5c06bc868335e3b6e42d7ef41f50dfb3ea32fbd523ab679d10d8741c0"}, + {file = "pydantic_core-2.23.2-cp312-none-win32.whl", hash = "sha256:3713dc093d5048bfaedbba7a8dbc53e74c44a140d45ede020dc347dda18daf3f"}, + {file = "pydantic_core-2.23.2-cp312-none-win_amd64.whl", hash = "sha256:e1895e949f8849bc2757c0dbac28422a04be031204df46a56ab34bcf98507342"}, + {file = "pydantic_core-2.23.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:da43cbe593e3c87d07108d0ebd73771dc414488f1f91ed2e204b0370b94b37ac"}, + {file = "pydantic_core-2.23.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:64d094ea1aa97c6ded4748d40886076a931a8bf6f61b6e43e4a1041769c39dd2"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:084414ffe9a85a52940b49631321d636dadf3576c30259607b75516d131fecd0"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043ef8469f72609c4c3a5e06a07a1f713d53df4d53112c6d49207c0bd3c3bd9b"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3649bd3ae6a8ebea7dc381afb7f3c6db237fc7cebd05c8ac36ca8a4187b03b30"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6db09153d8438425e98cdc9a289c5fade04a5d2128faff8f227c459da21b9703"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5668b3173bb0b2e65020b60d83f5910a7224027232c9f5dc05a71a1deac9f960"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c7b81beaf7c7ebde978377dc53679c6cba0e946426fc7ade54251dfe24a7604"}, + {file = "pydantic_core-2.23.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ae579143826c6f05a361d9546446c432a165ecf1c0b720bbfd81152645cb897d"}, + {file = "pydantic_core-2.23.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:19f1352fe4b248cae22a89268720fc74e83f008057a652894f08fa931e77dced"}, + {file = "pydantic_core-2.23.2-cp313-none-win32.whl", hash = "sha256:e1a79ad49f346aa1a2921f31e8dbbab4d64484823e813a002679eaa46cba39e1"}, + {file = "pydantic_core-2.23.2-cp313-none-win_amd64.whl", hash = "sha256:582871902e1902b3c8e9b2c347f32a792a07094110c1bca6c2ea89b90150caac"}, + {file = "pydantic_core-2.23.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:743e5811b0c377eb830150d675b0847a74a44d4ad5ab8845923d5b3a756d8100"}, + {file = "pydantic_core-2.23.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6650a7bbe17a2717167e3e23c186849bae5cef35d38949549f1c116031b2b3aa"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56e6a12ec8d7679f41b3750ffa426d22b44ef97be226a9bab00a03365f217b2b"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810ca06cca91de9107718dc83d9ac4d2e86efd6c02cba49a190abcaf33fb0472"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:785e7f517ebb9890813d31cb5d328fa5eda825bb205065cde760b3150e4de1f7"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ef71ec876fcc4d3bbf2ae81961959e8d62f8d74a83d116668409c224012e3af"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d50ac34835c6a4a0d456b5db559b82047403c4317b3bc73b3455fefdbdc54b0a"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16b25a4a120a2bb7dab51b81e3d9f3cde4f9a4456566c403ed29ac81bf49744f"}, + {file = "pydantic_core-2.23.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:41ae8537ad371ec018e3c5da0eb3f3e40ee1011eb9be1da7f965357c4623c501"}, + {file = "pydantic_core-2.23.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07049ec9306ec64e955b2e7c40c8d77dd78ea89adb97a2013d0b6e055c5ee4c5"}, + {file = "pydantic_core-2.23.2-cp38-none-win32.whl", hash = "sha256:086c5db95157dc84c63ff9d96ebb8856f47ce113c86b61065a066f8efbe80acf"}, + {file = "pydantic_core-2.23.2-cp38-none-win_amd64.whl", hash = "sha256:67b6655311b00581914aba481729971b88bb8bc7996206590700a3ac85e457b8"}, + {file = "pydantic_core-2.23.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:358331e21a897151e54d58e08d0219acf98ebb14c567267a87e971f3d2a3be59"}, + {file = "pydantic_core-2.23.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c4d9f15ffe68bcd3898b0ad7233af01b15c57d91cd1667f8d868e0eacbfe3f87"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0123655fedacf035ab10c23450163c2f65a4174f2bb034b188240a6cf06bb123"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e6e3ccebdbd6e53474b0bb7ab8b88e83c0cfe91484b25e058e581348ee5a01a5"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc535cb898ef88333cf317777ecdfe0faac1c2a3187ef7eb061b6f7ecf7e6bae"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aab9e522efff3993a9e98ab14263d4e20211e62da088298089a03056980a3e69"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05b366fb8fe3d8683b11ac35fa08947d7b92be78ec64e3277d03bd7f9b7cda79"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7568f682c06f10f30ef643a1e8eec4afeecdafde5c4af1b574c6df079e96f96c"}, + {file = "pydantic_core-2.23.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cdd02a08205dc90238669f082747612cb3c82bd2c717adc60f9b9ecadb540f80"}, + {file = "pydantic_core-2.23.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a2ab4f410f4b886de53b6bddf5dd6f337915a29dd9f22f20f3099659536b2f6"}, + {file = "pydantic_core-2.23.2-cp39-none-win32.whl", hash = "sha256:0448b81c3dfcde439551bb04a9f41d7627f676b12701865c8a2574bcea034437"}, + {file = "pydantic_core-2.23.2-cp39-none-win_amd64.whl", hash = "sha256:4cebb9794f67266d65e7e4cbe5dcf063e29fc7b81c79dc9475bd476d9534150e"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e758d271ed0286d146cf7c04c539a5169a888dd0b57026be621547e756af55bc"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f477d26183e94eaafc60b983ab25af2a809a1b48ce4debb57b343f671b7a90b6"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da3131ef2b940b99106f29dfbc30d9505643f766704e14c5d5e504e6a480c35e"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329a721253c7e4cbd7aad4a377745fbcc0607f9d72a3cc2102dd40519be75ed2"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7706e15cdbf42f8fab1e6425247dfa98f4a6f8c63746c995d6a2017f78e619ae"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e64ffaf8f6e17ca15eb48344d86a7a741454526f3a3fa56bc493ad9d7ec63936"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dd59638025160056687d598b054b64a79183f8065eae0d3f5ca523cde9943940"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:12625e69b1199e94b0ae1c9a95d000484ce9f0182f9965a26572f054b1537e44"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d813fd871b3d5c3005157622ee102e8908ad6011ec915a18bd8fde673c4360e"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1eb37f7d6a8001c0f86dc8ff2ee8d08291a536d76e49e78cda8587bb54d8b329"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ce7eaf9a98680b4312b7cebcdd9352531c43db00fca586115845df388f3c465"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f087879f1ffde024dd2788a30d55acd67959dcf6c431e9d3682d1c491a0eb474"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ce883906810b4c3bd90e0ada1f9e808d9ecf1c5f0b60c6b8831d6100bcc7dd6"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a8031074a397a5925d06b590121f8339d34a5a74cfe6970f8a1124eb8b83f4ac"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23af245b8f2f4ee9e2c99cb3f93d0e22fb5c16df3f2f643f5a8da5caff12a653"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c57e493a0faea1e4c38f860d6862ba6832723396c884fbf938ff5e9b224200e2"}, + {file = "pydantic_core-2.23.2.tar.gz", hash = "sha256:95d6bf449a1ac81de562d65d180af5d8c19672793c81877a2eda8fde5d08f2fd"}, ] [package.dependencies] @@ -1257,24 +1287,45 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-settings" -version = "2.2.1" +version = "2.4.0" description = "Settings management using Pydantic" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.2.1-py3-none-any.whl", hash = "sha256:0235391d26db4d2190cb9b31051c4b46882d28a51533f97440867f012d4da091"}, - {file = "pydantic_settings-2.2.1.tar.gz", hash = "sha256:00b9f6a5e95553590434c0fa01ead0b216c3e10bc54ae02e37f359948643c5ed"}, + {file = "pydantic_settings-2.4.0-py3-none-any.whl", hash = "sha256:bb6849dc067f1687574c12a639e231f3a6feeed0a12d710c1382045c5db1c315"}, + {file = "pydantic_settings-2.4.0.tar.gz", hash = "sha256:ed81c3a0f46392b4d7c0a565c05884e6e54b3456e6f0fe4d8814981172dc9a88"}, ] [package.dependencies] -pydantic = ">=2.3.0" +pydantic = ">=2.7.0" python-dotenv = ">=0.21.0" [package.extras] +azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] toml = ["tomli (>=2.0.1)"] yaml = ["pyyaml (>=6.0.1)"] +[[package]] +name = "pydoclint" +version = "0.4.2" +description = "A Python docstring linter that checks arguments, returns, yields, and raises sections" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydoclint-0.4.2-py2.py3-none-any.whl", hash = "sha256:1941ba8d47b021939e47f6b79b77513449ef0565330b836173df9d6cf1606045"}, + {file = "pydoclint-0.4.2.tar.gz", hash = "sha256:559060dc1a91240ac1e28be570b3563ae66f292c7dd7124f4d4eab1483416a41"}, +] + +[package.dependencies] +click = ">=8.1.0" +docstring-parser-fork = ">=0.0.5" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +flake8 = ["flake8 (>=4)"] + [[package]] name = "pydocstyle" version = "6.3.0" @@ -1311,24 +1362,24 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pylint" -version = "2.17.7" +version = "3.2.7" 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.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, + {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, ] [package.dependencies] -astroid = ">=2.15.8,<=2.17.0-dev0" +astroid = ">=3.2.4,<=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\""} @@ -1341,92 +1392,94 @@ testutils = ["gitpython (>3)"] [[package]] name = "pyobjc-core" -version = "9.2" +version = "10.3.1" description = "Python<->ObjC Interoperability Module" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyobjc-core-9.2.tar.gz", hash = "sha256:d734b9291fec91ff4e3ae38b9c6839debf02b79c07314476e87da8e90b2c68c3"}, - {file = "pyobjc_core-9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fa674a39949f5cde8e5c7bbcd24496446bfc67592b028aedbec7f81dc5fc4daa"}, - {file = "pyobjc_core-9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bbc8de304ee322a1ee530b4d2daca135a49b4a49aa3cedc6b2c26c43885f4842"}, - {file = "pyobjc_core-9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0fa950f092673883b8bd28bc18397415cabb457bf410920762109b411789ade9"}, - {file = "pyobjc_core-9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:586e4cae966282eaa61b21cae66ccdcee9d69c036979def26eebdc08ddebe20f"}, - {file = "pyobjc_core-9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41189c2c680931c0395a55691763c481fc681f454f21bb4f1644f98c24a45954"}, - {file = "pyobjc_core-9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:2d23ee539f2ba5e9f5653d75a13f575c7e36586fc0086792739e69e4c2617eda"}, - {file = "pyobjc_core-9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b9809cf96678797acb72a758f34932fe8e2602d5ab7abec15c5ac68ddb481720"}, + {file = "pyobjc_core-10.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ea46d2cda17921e417085ac6286d43ae448113158afcf39e0abe484c58fb3d78"}, + {file = "pyobjc_core-10.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:899d3c84d2933d292c808f385dc881a140cf08632907845043a333a9d7c899f9"}, + {file = "pyobjc_core-10.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6ff5823d13d0a534cdc17fa4ad47cf5bee4846ce0fd27fc40012e12b46db571b"}, + {file = "pyobjc_core-10.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2581e8e68885bcb0e11ec619e81ef28e08ee3fac4de20d8cc83bc5af5bcf4a90"}, + {file = "pyobjc_core-10.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ea98d4c2ec39ca29e62e0327db21418696161fb138ee6278daf2acbedf7ce504"}, + {file = "pyobjc_core-10.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:4c179c26ee2123d0aabffb9dbc60324b62b6f8614fb2c2328b09386ef59ef6d8"}, + {file = "pyobjc_core-10.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cb901fce65c9be420c40d8a6ee6fff5ff27c6945f44fd7191989b982baa66dea"}, + {file = "pyobjc_core-10.3.1.tar.gz", hash = "sha256:b204a80ccc070f9ab3f8af423a3a25a6fd787e228508d00c4c30f8ac538ba720"}, ] [[package]] name = "pyobjc-framework-cocoa" -version = "9.2" +version = "10.3.1" description = "Wrappers for the Cocoa frameworks on macOS" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyobjc-framework-Cocoa-9.2.tar.gz", hash = "sha256:efd78080872d8c8de6c2b97e0e4eac99d6203a5d1637aa135d071d464eb2db53"}, - {file = "pyobjc_framework_Cocoa-9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9e02d8a7cc4eb7685377c50ba4f17345701acf4c05b1e7480d421bff9e2f62a4"}, - {file = "pyobjc_framework_Cocoa-9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3b1e6287b3149e4c6679cdbccd8e9ef6557a4e492a892e80a77df143f40026d2"}, - {file = "pyobjc_framework_Cocoa-9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:312977ce2e3989073c6b324c69ba24283de206fe7acd6dbbbaf3e29238a22537"}, - {file = "pyobjc_framework_Cocoa-9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aae7841cf40c26dd915f4dd828f91c6616e6b7998630b72e704750c09e00f334"}, - {file = "pyobjc_framework_Cocoa-9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:739a421e14382a46cbeb9a883f192dceff368ad28ec34d895c48c0ad34cf2c1d"}, - {file = "pyobjc_framework_Cocoa-9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:32d9ac1033fac1b821ddee8c68f972a7074ad8c50bec0bea9a719034c1c2fb94"}, - {file = "pyobjc_framework_Cocoa-9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b236bb965e41aeb2e215d4e98a5a230d4b63252c6d26e00924ea2e69540a59d6"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4cb4f8491ab4d9b59f5187e42383f819f7a46306a4fa25b84f126776305291d1"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5f31021f4f8fdf873b57a97ee1f3c1620dbe285e0b4eaed73dd0005eb72fd773"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11b4e0bad4bbb44a4edda128612f03cdeab38644bbf174de0c13129715497296"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:de5e62e5ccf2871a94acf3bf79646b20ea893cc9db78afa8d1fe1b0d0f7cbdb0"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c5af24610ab639bd1f521ce4500484b40787f898f691b7a23da3339e6bc8b90"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:a7151186bb7805deea434fae9a4423335e6371d105f29e73cc2036c6779a9dbc"}, + {file = "pyobjc_framework_Cocoa-10.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:743d2a1ac08027fd09eab65814c79002a1d0421d7c0074ffd1217b6560889744"}, + {file = "pyobjc_framework_cocoa-10.3.1.tar.gz", hash = "sha256:1cf20714daaa986b488fb62d69713049f635c9d41a60c8da97d835710445281a"}, ] [package.dependencies] -pyobjc-core = ">=9.2" +pyobjc-core = ">=10.3.1" [[package]] name = "pyobjc-framework-corebluetooth" -version = "9.2" +version = "10.3.1" description = "Wrappers for the framework CoreBluetooth on macOS" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyobjc-framework-CoreBluetooth-9.2.tar.gz", hash = "sha256:cb2481b1dfe211ae9ce55f36537dc8155dbf0dc8ff26e0bc2e13f7afb0a291d1"}, - {file = "pyobjc_framework_CoreBluetooth-9.2-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:53d888742119d0f0c725d0b0c2389f68e8f21f0cba6d6aec288c53260a0196b6"}, - {file = "pyobjc_framework_CoreBluetooth-9.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:179532882126526e38fe716a50fb0ee8f440e0b838d290252c515e622b5d0e49"}, - {file = "pyobjc_framework_CoreBluetooth-9.2-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:256a5031ea9d8a7406541fa1b0dfac549b1de93deae8284605f9355b13fb58be"}, + {file = "pyobjc_framework_CoreBluetooth-10.3.1-cp36-abi3-macosx_10_13_universal2.whl", hash = "sha256:c89ee6fba0ed359c46b4908a7d01f88f133be025bd534cbbf4fb9c183e62fc97"}, + {file = "pyobjc_framework_CoreBluetooth-10.3.1-cp36-abi3-macosx_10_9_universal2.whl", hash = "sha256:2f261a386aa6906f9d4601d35ff71a13315dbca1a0698bf1f1ecfe3971de4648"}, + {file = "pyobjc_framework_CoreBluetooth-10.3.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:5211df0da2e8be511d9a54a48505dd7af0c4d04546fe2027dd723801d633c6ba"}, + {file = "pyobjc_framework_CoreBluetooth-10.3.1-cp36-abi3-macosx_11_0_universal2.whl", hash = "sha256:b8becd4e406be289a2d423611d3ad40730532a1f6728effb2200e68c9c04c3e8"}, + {file = "pyobjc_framework_corebluetooth-10.3.1.tar.gz", hash = "sha256:dc5d326ab5541b8b68e7e920aa8363851e779cb8c33842f6cfeef4674cc62f94"}, ] [package.dependencies] -pyobjc-core = ">=9.2" -pyobjc-framework-Cocoa = ">=9.2" +pyobjc-core = ">=10.3.1" +pyobjc-framework-Cocoa = ">=10.3.1" [[package]] name = "pyobjc-framework-libdispatch" -version = "9.2" +version = "10.3.1" description = "Wrappers for libdispatch on macOS" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pyobjc-framework-libdispatch-9.2.tar.gz", hash = "sha256:542e7f7c2b041939db5ed6f3119c1d67d73ec14a996278b92485f8513039c168"}, - {file = "pyobjc_framework_libdispatch-9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88d4091d4bcb5702783d6e86b4107db973425a17d1de491543f56bd348909b60"}, - {file = "pyobjc_framework_libdispatch-9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1a67b007113328538b57893cc7829a722270764cdbeae6d5e1460a1d911314df"}, - {file = "pyobjc_framework_libdispatch-9.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:6fccea1a57436cf1ac50d9ebc6e3e725bcf77f829ba6b118e62e6ed7866d359d"}, - {file = "pyobjc_framework_libdispatch-9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6eba747b7ad91b0463265a7aee59235bb051fb97687f35ca2233690369b5e4e4"}, - {file = "pyobjc_framework_libdispatch-9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2e835495860d04f63c2d2f73ae3dd79da4222864c107096dc0f99e8382700026"}, - {file = "pyobjc_framework_libdispatch-9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1b107e5c3580b09553030961ea6b17abad4a5132101eab1af3ad2cb36d0f08bb"}, - {file = "pyobjc_framework_libdispatch-9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:83cdb672acf722717b5ecf004768f215f02ac02d7f7f2a9703da6e921ab02222"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5543aea8acd53fb02bcf962b003a2a9c2bdacf28dc290c31a3d2de7543ef8392"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3e0db3138aae333f0b87b42586bc016430a76638af169aab9cef6afee4e5f887"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b209dbc9338cd87e053ede4d782b8c445bcc0b9a3d0365a6ffa1f9cd5143c301"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a74e62314376dc2d34bc5d4a86cedaf5795786178ebccd0553c58e8fa73400a3"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8e8fb27ac86d48605eb2107ac408ed8de281751df81f5430fe66c8228d7626b8"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:0a7a19afef70c98b3b527fb2c9adb025444bcb50f65c8d7b949f1efb51bde577"}, + {file = "pyobjc_framework_libdispatch-10.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:109044cddecb3332cbb75f14819cd01b98aacfefe91204c776b491eccc58a112"}, + {file = "pyobjc_framework_libdispatch-10.3.1.tar.gz", hash = "sha256:f5c3475498cb32f54d75e21952670e4a32c8517fb2db2e90869f634edc942446"}, ] [package.dependencies] -pyobjc-core = ">=9.2" +pyobjc-core = ">=10.3.1" +pyobjc-framework-Cocoa = ">=10.3.1" [[package]] name = "pyparsing" -version = "3.1.2" +version = "3.1.4" description = "pyparsing module - Classes and methods to define and execute parsing grammars" category = "main" optional = false python-versions = ">=3.6.8" files = [ - {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, - {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, + {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, + {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, ] [package.extras] @@ -1571,14 +1624,14 @@ files = [ [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1628,6 +1681,27 @@ pygments = ">=2.6.0,<3.0.0" [package.extras] jupyter = ["ipywidgets (>=7.5.1,<8.0.0)"] +[[package]] +name = "setuptools" +version = "74.1.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-74.1.2-py3-none-any.whl", hash = "sha256:5f4c08aa4d3ebcb57a50c33b1b07e94315d7fc7230f7115e47fc99776c8ce308"}, + {file = "setuptools-74.1.2.tar.gz", hash = "sha256:95b40ed940a1c67eb70fc099094bd6e99c6ee7c23aa2306f4d2697ba7916f9c6"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.5.2)"] +core = ["importlib-metadata (>=6)", "importlib-resources (>=5.10.2)", "jaraco.text (>=3.7)", "more-itertools (>=8.8)", "packaging (>=24)", "platformdirs (>=2.6.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.11.0,<1.12.0)", "pytest-mypy"] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -1642,55 +1716,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] @@ -1698,52 +1773,52 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] [[package]] name = "sphinxcontrib-applehelp" -version = "1.0.8" +version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" category = "dev" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_applehelp-1.0.8-py3-none-any.whl", hash = "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4"}, - {file = "sphinxcontrib_applehelp-1.0.8.tar.gz", hash = "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619"}, + {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, + {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-devhelp" -version = "1.0.6" +version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" category = "dev" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_devhelp-1.0.6-py3-none-any.whl", hash = "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f"}, - {file = "sphinxcontrib_devhelp-1.0.6.tar.gz", hash = "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3"}, + {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, + {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.5" +version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" category = "dev" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"}, - {file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"}, + {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, + {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] test = ["html5lib", "pytest"] @@ -1779,53 +1854,38 @@ test = ["flake8", "mypy", "pytest"] [[package]] name = "sphinxcontrib-qthelp" -version = "1.0.7" +version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" category = "dev" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"}, - {file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"}, + {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, + {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] standalone = ["Sphinx (>=5)"] -test = ["pytest"] +test = ["defusedxml (>=0.7.1)", "pytest"] [[package]] name = "sphinxcontrib-serializinghtml" -version = "1.1.10" +version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" category = "dev" optional = false python-versions = ">=3.9" files = [ - {file = "sphinxcontrib_serializinghtml-1.1.10-py3-none-any.whl", hash = "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7"}, - {file = "sphinxcontrib_serializinghtml-1.1.10.tar.gz", hash = "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f"}, + {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, + {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, ] [package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] +lint = ["mypy", "ruff (==0.5.5)", "types-docutils"] 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" @@ -1840,14 +1900,14 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.5" +version = "0.13.2" description = "Style preserving TOML library" category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"}, - {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"}, + {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, + {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, ] [[package]] @@ -1863,14 +1923,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]] @@ -1887,14 +1947,14 @@ files = [ [[package]] name = "types-requests" -version = "2.31.0.20240406" +version = "2.32.0.20240905" description = "Typing stubs for requests" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "types-requests-2.31.0.20240406.tar.gz", hash = "sha256:4428df33c5503945c74b3f42e82b181e86ec7b724620419a2966e2de604ce1a1"}, - {file = "types_requests-2.31.0.20240406-py3-none-any.whl", hash = "sha256:6216cdac377c6b9a040ac1c0404f7284bd13199c0e1bb235f4324627e8898cf5"}, + {file = "types-requests-2.32.0.20240905.tar.gz", hash = "sha256:e97fd015a5ed982c9ddcd14cc4afba9d111e0e06b797c8f776d14602735e9bd6"}, + {file = "types_requests-2.32.0.20240905-py3-none-any.whl", hash = "sha256:f46ecb55f5e1a37a58be684cf3f013f166da27552732ef2469a0cc8e62a72881"}, ] [package.dependencies] @@ -1917,14 +1977,14 @@ types-pytz = "*" [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] @@ -1959,14 +2019,14 @@ devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3) [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -2057,63 +2117,79 @@ files = [ [[package]] name = "zeroconf" -version = "0.132.2" +version = "0.133.0" description = "A pure python implementation of multicast DNS service discovery" category = "main" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "zeroconf-0.132.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:31c8406f62251aa62f5b67d865007ffd1dd929eae9027166ffa6bccca69253bd"}, - {file = "zeroconf-0.132.2-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:d4bc5e43d02e0848c3174914595dfcebed9b74e65cbdfb1011c5082db7916605"}, - {file = "zeroconf-0.132.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59953e8445e69e5fee53381c437d3494f7fac8d7b51f0169d59b69eba8f95063"}, - {file = "zeroconf-0.132.2-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:ddae9592604fe04ec065cc53a321844c3592c812988346136d8ee548127f3d12"}, - {file = "zeroconf-0.132.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b20036ab22df2fb663f797b110fa82d4798084fcc56c8a264af50989581062be"}, - {file = "zeroconf-0.132.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:82678a77e471dd3b0ad5ed47a4a42474af3150819718eff7e36dca32ae591949"}, - {file = "zeroconf-0.132.2-cp310-cp310-win32.whl", hash = "sha256:390feb3e7fccdffbf66c9bcd895b1db92e501aa2789d6a8b44e6e027ab80ec14"}, - {file = "zeroconf-0.132.2-cp310-cp310-win_amd64.whl", hash = "sha256:779d81aac693e57090343ce5b18f477fec993f969aa87660a33e7ce81880ccdf"}, - {file = "zeroconf-0.132.2-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:76d12185c335c14b04b8706b4dd0badc16f4185caeb635419c84e575cef7c980"}, - {file = "zeroconf-0.132.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:700bae69eb7c45037deef4a729586f32205d391de38802e2ab89151a7a87d1fc"}, - {file = "zeroconf-0.132.2-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:9d364a929121df5b96af53ac62abdd61fa3a931e74c7a4c80204c961c01a8667"}, - {file = "zeroconf-0.132.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e2c398679c863e810a9af2c5d14542a32d438e3bf5ba0b9d8e119326c33303"}, - {file = "zeroconf-0.132.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:28b1721617ddc9bf3d2ba3e2b96234f7539e1dbdcacaf6e94ec31ff7b5ebe620"}, - {file = "zeroconf-0.132.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f2b26c23efeded0e7fcfd0fb4d638ec4a83d120e1d455267d353090e36479528"}, - {file = "zeroconf-0.132.2-cp311-cp311-win32.whl", hash = "sha256:4754dfba1af63545dfd0ab26c834c907e1dd3f94c8ee190c3041a6444313aaed"}, - {file = "zeroconf-0.132.2-cp311-cp311-win_amd64.whl", hash = "sha256:db8607a32347da1fd4519cfea441d8b36b44df0c53198ae0471c76fc932a86e0"}, - {file = "zeroconf-0.132.2-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:5354c1cf83d36b2d03ee5774923d30fe838f9371963b42ca46ecba45d3507ff4"}, - {file = "zeroconf-0.132.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48275e3db89a8d90ff983c3f7b0c6eee2ede3c4e5e75eaf2aa571ea8cb956d95"}, - {file = "zeroconf-0.132.2-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:3eb0e57654e139c3ef5b6421053236be4a0add9f0301b01545b11a0552c7c123"}, - {file = "zeroconf-0.132.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dd7143dfc37a20f7d1ccf32f916ac78c11d3c8bae61438ee06376b1bc535fc"}, - {file = "zeroconf-0.132.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f9a28b0416a36ec32273ee1ac80cc72ff9b06d1cb15a9481dcd5c92bd2bc8f03"}, - {file = "zeroconf-0.132.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:06203c23a82b69aca9e961da675600dff19026bb22b5d042f18f9e0ff1139ed3"}, - {file = "zeroconf-0.132.2-cp312-cp312-win32.whl", hash = "sha256:5c8c2eeb838538fffaa421f9b3f9c671778886595b5aa0d4ef4d000531e721d2"}, - {file = "zeroconf-0.132.2-cp312-cp312-win_amd64.whl", hash = "sha256:a37fe4f302edb8d931a4c386d0944f996e3f54717495636113880c4492ab479f"}, - {file = "zeroconf-0.132.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:6732b224be7e69f7c77798e50205f8e92646ab59724151d66d8dc97f92e99a77"}, - {file = "zeroconf-0.132.2-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:3ad2fe0cbfebe20612c9a5390075a2b3a258a78928f5b7b5163be1699cc528f0"}, - {file = "zeroconf-0.132.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56146e66774c30e238088f67be47740ffd4f669c08e76f2e470bd611d7bdae46"}, - {file = "zeroconf-0.132.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4dd7d8fdee36cc6bde0bcb08b79375009de7a76d935d1401b6ae4b62505b9ee0"}, - {file = "zeroconf-0.132.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a49b13ec79edff347b1e7af65f5843719ca151ef071ac6b2ff564bb69d164331"}, - {file = "zeroconf-0.132.2-cp38-cp38-win32.whl", hash = "sha256:ca46637fcc0386fdbe6bde447184ed981499c8c1b5b5fcaa0f35c3b15528162a"}, - {file = "zeroconf-0.132.2-cp38-cp38-win_amd64.whl", hash = "sha256:f56ec955f43f944985f857c9d23030362df52e14a7c53c64bf8b29cfadebd601"}, - {file = "zeroconf-0.132.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:5586bc773d6cee4f9a14692f5e6bc6387ddb54b2bfae0db01c0695aac20c420a"}, - {file = "zeroconf-0.132.2-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1f09b692219abf9b1ca28364d6f4eb283a4c676e30c905933d1694cbd321bc4b"}, - {file = "zeroconf-0.132.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1031c7c5f8516108e7c24190179e6a522183de218a954681a341ee818f8079a"}, - {file = "zeroconf-0.132.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:87b6e92a869932f4aac3076816a1b987c581b01e49a08e495bef7165be049dfd"}, - {file = "zeroconf-0.132.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:13beed15eed7e569fd56dbe16c7cb758f81c661d53ec253fbf9cfe7a20e28b7c"}, - {file = "zeroconf-0.132.2-cp39-cp39-win32.whl", hash = "sha256:4e83e18722d0bdc2e603f7ca104adf276d5728a664b9e94c99e2d8c02001429c"}, - {file = "zeroconf-0.132.2-cp39-cp39-win_amd64.whl", hash = "sha256:a2fa3a89f6a0cf03a56141dad158634a009a22fbe645c7c01e85edc12a0a239f"}, - {file = "zeroconf-0.132.2-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:1a95025f0949ed0e873e141d482fbbefa223ef90646443e4a1d6d47f50eb89d7"}, - {file = "zeroconf-0.132.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1c932b15848ae6b8e4b2b50c65368e396d000fea95acd473611693dbe5a00096"}, - {file = "zeroconf-0.132.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c295b424a271ce5022da83a1274b4cd0f696c5b8e0c190e6a28efde8b36e82d"}, - {file = "zeroconf-0.132.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c50ee0df6b0b06f1dad6261670b5be53c909b9a2b1985bcf65ea5b0d766fd10e"}, - {file = "zeroconf-0.132.2-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5b6cfc2b62e6282eabbcb6c7223b0a8c05ed3a326e7b467d06b85a3eeda1bfc8"}, - {file = "zeroconf-0.132.2-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:d6c05af8b49c442422ce49565ab41a094b23e0f5692abe1533428cbe35a78f8e"}, - {file = "zeroconf-0.132.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0d2ffc4bafbcc4152067bfbc1a67074d23e6100e356424bd985ca8067a2bfd"}, - {file = "zeroconf-0.132.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b60b260c70bb77d7f3b666bdd2a2a74cead5e36814f8b4295778bcdd08f65c7e"}, - {file = "zeroconf-0.132.2-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:9228c512334905338f65825102e47778e5ce034bb4249c3deb22991826ed061f"}, - {file = "zeroconf-0.132.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:e36f50a963d149bb7152543db9bdbd73f7997e66b57b7956fc17751f55e59625"}, - {file = "zeroconf-0.132.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bd0cd9435dced8c31491b3ed7c15707acedd11f00451f7fbb57ba3868dd5724"}, - {file = "zeroconf-0.132.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d80bde641349198c8c17684692a8cc40a36a93c0cebd8f1d7c42db7ceeaa17be"}, - {file = "zeroconf-0.132.2.tar.gz", hash = "sha256:9ad8bc6e3f168fe8c164634c762d3265c775643defff10e26273623a12d73ae1"}, + {file = "zeroconf-0.133.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:6a0239bc2fd440264b97d3d00120060676493b17591700c50a6d00fd8dbf6e10"}, + {file = "zeroconf-0.133.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:7fce1bdd16530d7de7d1197fd4f6f2150b552c3b2ef947d08dbb7476fa3506dc"}, + {file = "zeroconf-0.133.0-cp310-cp310-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:aa2d29c6c743db3d5056c9c016914fa561099669f44cda441d1081f274be6de2"}, + {file = "zeroconf-0.133.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:073028e09fee39c74c342f6367a7c9c34eb7c26a03c9d93b366b5e2f7b04ea6c"}, + {file = "zeroconf-0.133.0-cp310-cp310-manylinux_2_31_x86_64.whl", hash = "sha256:36acdee76831aedf40d9ae09e57b8b3d9fc452ff17bb98f9d22a163dfa704200"}, + {file = "zeroconf-0.133.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fe71c44532af06b09a2cacb91447f86e701702817d245553d41bfbdca908550f"}, + {file = "zeroconf-0.133.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5d120222d363cf3a9fcc0fedaf734571e99e73531559af3c3186aa6794aa7570"}, + {file = "zeroconf-0.133.0-cp310-cp310-win32.whl", hash = "sha256:f34423bea75d770631b708ee2868d31ed44e3f7aca395dc14c66118b2bf15e34"}, + {file = "zeroconf-0.133.0-cp310-cp310-win_amd64.whl", hash = "sha256:685e90d64ec1471b32495b94000657fb1ac3495df2571237a0bb45c0ce6b1829"}, + {file = "zeroconf-0.133.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:beec5ec1faf6cc014fc74e1fd8608ac5fa4b36422dea9e5e4246db3c39021c6d"}, + {file = "zeroconf-0.133.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:4ff13025b6aaa476a84c009ad9f23e960f375d4b8ed0ffb57d657dc10135da34"}, + {file = "zeroconf-0.133.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4563dccc320d36bbb41764624f32077b26f65088234a934678c20351a2a9637c"}, + {file = "zeroconf-0.133.0-cp311-cp311-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:b11099f1c60c34086abcd2bd61359008be71cfb69e69074d76f05f413294ff3e"}, + {file = "zeroconf-0.133.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78025ae5caed6ee1606a47b3493c58db7b30038d5a2e5572f409d088f9c1e7e2"}, + {file = "zeroconf-0.133.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ff4b603e7243049e9e7b34b1a8479091d98e576d334199b1db5ff3b6777b700b"}, + {file = "zeroconf-0.133.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1298d845163952fe3692cb3e5febaa278427ccab00df4a2c92b83ef5219dd013"}, + {file = "zeroconf-0.133.0-cp311-cp311-win32.whl", hash = "sha256:0dc54a1b4f284687f33175f9fda7a639ae2db8630bb70426997a34931bfeae0d"}, + {file = "zeroconf-0.133.0-cp311-cp311-win_amd64.whl", hash = "sha256:038530c8215d36a4a45e6a98382f00b30af2833b007865494fee46a208cd5bf2"}, + {file = "zeroconf-0.133.0-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:e8a57617ac9b973d64f2dadbc53beeb1c1d81403435ca7a0619e01a9d4f83e28"}, + {file = "zeroconf-0.133.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:92c05af80c764a4380651c0c2947720ee5a3c4ada3529c54d3acfa5a25c54812"}, + {file = "zeroconf-0.133.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0ef28cb0253c39faa98d8b265516bd3ee0fb6621298b878a678a85198c95639"}, + {file = "zeroconf-0.133.0-cp312-cp312-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:1b243754410f693542d0d7dce0ec8731f189cf76d883c82fe614c4255f92a12f"}, + {file = "zeroconf-0.133.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83421aab6ef36c97215135594b52d82913f3a573ceb89cead010fee2c8d1f04e"}, + {file = "zeroconf-0.133.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fb52f31874af53b029b1ba0a98a9cdcd7b80be554bc6ae8de3fc0c73b67d3972"}, + {file = "zeroconf-0.133.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e921bce78935676f8a693bd5c361d25db378d3122b5fe8f41f3ae0d7ad1eff9b"}, + {file = "zeroconf-0.133.0-cp312-cp312-win32.whl", hash = "sha256:befcb059885ae152bedad34a56ca9e2aa48724ac1c366af01417d9830eb2d2fe"}, + {file = "zeroconf-0.133.0-cp312-cp312-win_amd64.whl", hash = "sha256:686626df48798926c9ad229675cc737eba680913a7b9225fb88e8ce224c766a4"}, + {file = "zeroconf-0.133.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:0bd29d2c269d9bf8e3c4b9debbb68ffbe14ecbc6e072c9ff3cae21694660e83d"}, + {file = "zeroconf-0.133.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:a9f001b896c190d75c01ea7042e1add4d3c271fb4e634db32fb623cd4c52dc6e"}, + {file = "zeroconf-0.133.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcb526a07ecd26630c8a6a3a0c4ab79d2892400840b9aa8af7b2dbf6252cada6"}, + {file = "zeroconf-0.133.0-cp313-cp313-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:811fb55e5b5a643556242ecbf26d6fd317a1b0517af6a09f8215cfa3b1676f4f"}, + {file = "zeroconf-0.133.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7705f9b678cd33f8c3f9bfe59e25ddff090d0c91ea00b7133d25116304fb613"}, + {file = "zeroconf-0.133.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:02b14e9b3f6c432475ec85e2fa54b9b1161d400d455f245160ace8a08f83086e"}, + {file = "zeroconf-0.133.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a912515d3025140f7e3a6bcfd7fbb25477d531e216abcd662089dbfef0f6bdd1"}, + {file = "zeroconf-0.133.0-cp313-cp313-win32.whl", hash = "sha256:ce00adb90ace385560705c61afb4f510c22c5db2a937eaf2af1f0d55a91551ac"}, + {file = "zeroconf-0.133.0-cp313-cp313-win_amd64.whl", hash = "sha256:127326682a358fd91b9ac8e02c050aabd6bd191b71247c5f014c8dfd1e4fb9dc"}, + {file = "zeroconf-0.133.0-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:c49eb0f4d0c3da762147234537ce0c48cea68848e0d7c55cfd9aeaf8d2c19623"}, + {file = "zeroconf-0.133.0-cp38-cp38-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:19de0328ad3ca1629b670f9d3354088045c6c934572470178be2b193da0fbdcd"}, + {file = "zeroconf-0.133.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecd3957d61e9a44d630cb54ca0e62902326154e53a8846f85739d07667765148"}, + {file = "zeroconf-0.133.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:3caaa3e1dd600594b175f37408e8bb5812729045c45235008775d3703268602b"}, + {file = "zeroconf-0.133.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:b8182255b49fff1a5ffd454f4b21b4d5bda9903f08b01b75e0f95d51cab6eba1"}, + {file = "zeroconf-0.133.0-cp38-cp38-win32.whl", hash = "sha256:576ad6c32b6e747f493021c02daf823367261f4b7d3391fef6c7e6936606821b"}, + {file = "zeroconf-0.133.0-cp38-cp38-win_amd64.whl", hash = "sha256:2c90092c8727ef29a57c59f6db1309d7e3de49879c21c1d67e03ff8ee8048973"}, + {file = "zeroconf-0.133.0-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:2594802113aed1fc7d5c3fb3fb92fa48c04b78a8ea24f68cb29030bd7dc62dc5"}, + {file = "zeroconf-0.133.0-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:97d2fea9a70d3df918d6c6d38a3739254f6d093254d70ffdbf73f435e9ef65ba"}, + {file = "zeroconf-0.133.0-cp39-cp39-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:6d57052ac4eb28d0f8a63ce7adcf176e1db527ee383991f536aa4fa95b5f6066"}, + {file = "zeroconf-0.133.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b720ae968872f7ecc15bde1de0efd2b3657240f7842c349ba19c44210d5314d7"}, + {file = "zeroconf-0.133.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c9f3ac428aa2f56c7d57149f3009d97071ef055680af9b113dab21e536ee8b69"}, + {file = "zeroconf-0.133.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a0e9fe6439cb45d4e00b451ff1384a86be37f8d81f32a2d6de0b911a0948de36"}, + {file = "zeroconf-0.133.0-cp39-cp39-win32.whl", hash = "sha256:4a5c8b46084d7543ff671ff498a4e033eefd811608b3a5c341c09d061f825a77"}, + {file = "zeroconf-0.133.0-cp39-cp39-win_amd64.whl", hash = "sha256:5fb19173d8f41305d2f784ed1d262cb5e1fd994decaa89ede092cd10b4cd65c0"}, + {file = "zeroconf-0.133.0-pp310-pypy310_pp73-macosx_12_0_x86_64.whl", hash = "sha256:fdfa54b134b053a0700623fe064b207eab2534f29f6d9c21a6374f02a6918bc0"}, + {file = "zeroconf-0.133.0-pp310-pypy310_pp73-macosx_14_0_arm64.whl", hash = "sha256:5cba6264e7dc40d5fe39f4513f4bbc6bda38232c15bca433b5608e67b33d5918"}, + {file = "zeroconf-0.133.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:55826ca3b76f24cf1a5d9f520abea28059a921c636e473f06cc090179c4e748d"}, + {file = "zeroconf-0.133.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38e847572ee08b0f3ad92a26a102e9c457ce6f51b2c89eb1db5ac12a440db631"}, + {file = "zeroconf-0.133.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:35c8a6c2547c6905ee283d22d35ee72dce60ad02d6f5c19b93bef5b8f14f3004"}, + {file = "zeroconf-0.133.0-pp38-pypy38_pp73-macosx_12_0_x86_64.whl", hash = "sha256:dccec0292f88307a7f150656ecdc6bb11569d2142b5a4c35f361ff706a7e707f"}, + {file = "zeroconf-0.133.0-pp38-pypy38_pp73-macosx_14_0_arm64.whl", hash = "sha256:eff1ae3ae62b12134aafbd7b5b6f15aca6c1e7f1413777bd89468823f2f58be2"}, + {file = "zeroconf-0.133.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:c1699707618349d788bfa1017195fbec11a0604b2d043bb0cd6e80e7aaa1794b"}, + {file = "zeroconf-0.133.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29e5d7352c015ade5a0c56dfb665280ec501f59c27f4391055e9378209a66fd1"}, + {file = "zeroconf-0.133.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f2871c4d8bb38c6f809ea7aa06678a2e1e94712b494ba74490287fe06b313516"}, + {file = "zeroconf-0.133.0-pp39-pypy39_pp73-macosx_12_0_x86_64.whl", hash = "sha256:73625ad082e5fa3f106d6114cc0162107f8c4018f155711ed334e242a53260dd"}, + {file = "zeroconf-0.133.0-pp39-pypy39_pp73-macosx_14_0_arm64.whl", hash = "sha256:9ef7672413f3c037971541ae8be7b1cf015fabf98a2fdb34be3c6109705f9e41"}, + {file = "zeroconf-0.133.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux_2_5_i686.manylinux1_i686.manylinux2014_i686.whl", hash = "sha256:cd4eb5ea118994ffd61f39e9fff917797ad6a5a83493703c7e85bb5ca8de237b"}, + {file = "zeroconf-0.133.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:951cd26ed47d768bfba070a2da91c814f95b6962fe681595f062dd6470999e01"}, + {file = "zeroconf-0.133.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:561ae1de25ef27ec36062b9943036668c7a095884dad1309080015004bd0e54a"}, + {file = "zeroconf-0.133.0.tar.gz", hash = "sha256:0bd9dec747284c55a58e98733b90ce0c4434f0e24a4f46cf7c22341f80aab212"}, ] [package.dependencies] @@ -2122,19 +2198,23 @@ ifaddr = ">=0.1.7" [[package]] name = "zipp" -version = "3.18.1" +version = "3.20.1" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, - {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, + {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, + {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] [extras] gui = ["opencv-python", "Pillow"] @@ -2142,4 +2222,4 @@ gui = ["opencv-python", "Pillow"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "f2e9d2dd78a4da02ab1f6e1f1f0c487756c9cf1332e08c0a33ae2e3ea58966cf" +content-hash = "4277cfc55ba0b2b9e1154293534cfdb84f3734a7faa1be5eb1a6023728104f83" diff --git a/demos/python/sdk_wireless_camera_control/pyproject.toml b/demos/python/sdk_wireless_camera_control/pyproject.toml index 50faa767..42e3755b 100644 --- a/demos/python/sdk_wireless_camera_control/pyproject.toml +++ b/demos/python/sdk_wireless_camera_control/pyproject.toml @@ -38,7 +38,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry.dependencies] python = ">=3.9,<3.12" -bleak = "=0.21.1" +bleak = "=0.22.2" construct = "^2" wrapt = "^1" requests = "^2" @@ -52,11 +52,13 @@ opencv-python = { version = "^4", optional = true } Pillow = {version= "^9", optional = true} pytz = "*" tzlocal = "*" +typing-extensions = "^4" [tool.poetry.extras] gui = ["opencv-python", "pillow"] [tool.poetry.group.dev.dependencies] +pydoclint = "^0.4.1" pydocstyle = { extras = ["toml"], version = "^6" } pytest = "^7" pytest-cov = "^3" @@ -65,23 +67,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" -coverage-badge = "=1.1.0" -darglint = "^1" +sphinx = "^7" +sphinx-rtd-theme = "^2" +coverage-badge = "^1" 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" @@ -115,16 +115,16 @@ help = "Perform all static code analysis" cmd = "pydocstyle --config pyproject.toml -v open_gopro" help = "check docstrings style" -[tool.poe.tasks._darglint] -cmd = "darglint -v 2 open_gopro" +[tool.poe.tasks._doclint] +cmd = "pydoclint open_gopro" help = "validate docstrings" [tool.poe.tasks.docstrings] -sequence = ["_pydocstyle", "_darglint"] +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] @@ -264,3 +264,8 @@ match-dir = '(?!.*demos).*' [tool.isort] profile = "black" + +[tool.pydoclint] +style = 'google' +exclude = 'schemas/' +require-return-section-when-returning-nothing = false \ No newline at end of file diff --git a/demos/python/sdk_wireless_camera_control/tests/conftest.py b/demos/python/sdk_wireless_camera_control/tests/conftest.py index 36105af0..cb0dd3af 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 CameraState, UpdateCb, UpdateType 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..88e4ca32 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 @@ -16,8 +16,9 @@ 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 open_gopro.types import UpdateType 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)