python: Use future annotations

Change-Id: I1922aa9b5f4059de369714ba2f857e0fc4fdaaba
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/198570
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Pigweed-Auto-Submit: Rob Mohr <mohrr@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
diff --git a/pw_build/py/pw_build/build_recipe.py b/pw_build/py/pw_build/build_recipe.py
index 8c7cd96..75983b2 100644
--- a/pw_build/py/pw_build/build_recipe.py
+++ b/pw_build/py/pw_build/build_recipe.py
@@ -216,7 +216,7 @@
 class BuildRecipeStatus:
     """Stores the status of a build recipe."""
 
-    recipe: 'BuildRecipe'
+    recipe: BuildRecipe
     current_step: str = ''
     percent: float = 0.0
     error_count: int = 0
diff --git a/pw_build/py/pw_build/project_builder.py b/pw_build/py/pw_build/project_builder.py
index 43d1176..0bca7b5 100644
--- a/pw_build/py/pw_build/project_builder.py
+++ b/pw_build/py/pw_build/project_builder.py
@@ -37,6 +37,8 @@
   --build-system-command outbazel 'bazel test'
 """
 
+from __future__ import annotations
+
 import argparse
 import concurrent.futures
 import os
@@ -347,7 +349,7 @@
 
 def log_build_recipe_start(
     index_message: str,
-    project_builder: 'ProjectBuilder',
+    project_builder: ProjectBuilder,
     cfg: BuildRecipe,
     logger: logging.Logger = _LOG,
 ) -> None:
@@ -386,7 +388,7 @@
 
 def log_build_recipe_finish(
     index_message: str,
-    project_builder: 'ProjectBuilder',
+    project_builder: ProjectBuilder,
     cfg: BuildRecipe,
     logger: logging.Logger = _LOG,
 ) -> None:
diff --git a/pw_cli/py/pw_cli/process.py b/pw_cli/py/pw_cli/process.py
index 882db4a..a211d90 100644
--- a/pw_cli/py/pw_cli/process.py
+++ b/pw_cli/py/pw_cli/process.py
@@ -13,6 +13,8 @@
 # the License.
 """Module for running subprocesses from pw and capturing their output."""
 
+from __future__ import annotations
+
 import asyncio
 import logging
 import os
@@ -44,7 +46,7 @@
 
     def __init__(
         self,
-        process: 'asyncio.subprocess.Process',
+        process: asyncio.subprocess.Process,
         output: bytes | IO[bytes],
     ):
         assert process.returncode is not None
@@ -93,7 +95,7 @@
 
 
 async def _kill_process_and_children(
-    process: 'asyncio.subprocess.Process',
+    process: asyncio.subprocess.Process,
 ) -> None:
     """Kills child processes of a process with PID `pid`."""
     # Look up child processes before sending the kill signal to the parent,
diff --git a/pw_console/py/pw_console/console_app.py b/pw_console/py/pw_console/console_app.py
index 9058a0a..8e4cfed 100644
--- a/pw_console/py/pw_console/console_app.py
+++ b/pw_console/py/pw_console/console_app.py
@@ -117,7 +117,7 @@
 
 def _add_log_handler_to_pane(
     logger: str | logging.Logger,
-    pane: 'LogPane',
+    pane: LogPane,
     level_name: str | None = None,
 ) -> None:
     """A log pane handler for a given logger instance."""
diff --git a/pw_console/py/pw_console/help_window.py b/pw_console/py/pw_console/help_window.py
index 291368d..742bc2b 100644
--- a/pw_console/py/pw_console/help_window.py
+++ b/pw_console/py/pw_console/help_window.py
@@ -13,6 +13,8 @@
 # the License.
 """Help window container class."""
 
+from __future__ import annotations
+
 import functools
 import importlib.resources
 import inspect
@@ -99,14 +101,14 @@
 
     def __init__(
         self,
-        application: 'ConsoleApp',
+        application: ConsoleApp,
         preamble: str = '',
         additional_help_text: str = '',
         title: str = '',
         disable_ctrl_c: bool = False,
     ) -> None:
         # Dict containing key = section title and value = list of key bindings.
-        self.application: 'ConsoleApp' = application
+        self.application: ConsoleApp = application
         self.show_window: bool = False
         self.help_text_sections: dict[str, dict] = {}
         self._pane_title: str = title
diff --git a/pw_console/py/pw_console/log_view.py b/pw_console/py/pw_console/log_view.py
index 601ee6a..60a347d 100644
--- a/pw_console/py/pw_console/log_view.py
+++ b/pw_console/py/pw_console/log_view.py
@@ -65,8 +65,8 @@
 
     def __init__(
         self,
-        log_pane: 'LogPane',
-        application: 'ConsoleApp',
+        log_pane: LogPane,
+        application: ConsoleApp,
         log_store: LogStore | None = None,
     ):
         # Parent LogPane reference. Updated by calling `set_log_pane()`.
@@ -112,9 +112,9 @@
 
         # Filter
         self.filtering_on: bool = False
-        self.filters: 'collections.OrderedDict[str, LogFilter]' = (
-            collections.OrderedDict()
-        )
+        self.filters: collections.OrderedDict[
+            str, LogFilter
+        ] = collections.OrderedDict()
         self.filtered_logs: collections.deque = collections.deque()
         self.filter_existing_logs_task: asyncio.Task | None = None
 
@@ -471,9 +471,9 @@
             return
         self.clear_search()
         self.filtering_on = False
-        self.filters: 'collections.OrderedDict[str, re.Pattern]' = (
-            collections.OrderedDict()
-        )
+        self.filters: collections.OrderedDict[
+            str, re.Pattern
+        ] = collections.OrderedDict()
         self.filtered_logs.clear()
         # Reset scrollback start
         self._scrollback_start_index = 0
diff --git a/pw_console/py/pw_console/plugins/clock_pane.py b/pw_console/py/pw_console/plugins/clock_pane.py
index 397c7c3..aa4a769 100644
--- a/pw_console/py/pw_console/plugins/clock_pane.py
+++ b/pw_console/py/pw_console/plugins/clock_pane.py
@@ -14,6 +14,8 @@
 """Example Plugin that displays some dynamic content (a clock) and examples of
 text formatting."""
 
+from __future__ import annotations
+
 from datetime import datetime
 
 from prompt_toolkit.filters import Condition, has_focus
@@ -42,7 +44,7 @@
     handling keybindings if in focus, and mouse input.
     """
 
-    def __init__(self, clock_pane: 'ClockPane', *args, **kwargs) -> None:
+    def __init__(self, clock_pane: ClockPane, *args, **kwargs) -> None:
         self.clock_pane = clock_pane
 
         # Set some custom key bindings to toggle the view mode and wrap lines.
diff --git a/pw_console/py/pw_console/plugins/twenty48_pane.py b/pw_console/py/pw_console/plugins/twenty48_pane.py
index d1e9dfe..282425a 100644
--- a/pw_console/py/pw_console/plugins/twenty48_pane.py
+++ b/pw_console/py/pw_console/plugins/twenty48_pane.py
@@ -283,7 +283,7 @@
     handling keybindings if in focus, and mouse input.
     """
 
-    def __init__(self, twenty48_pane: 'Twenty48Pane', *args, **kwargs) -> None:
+    def __init__(self, twenty48_pane: Twenty48Pane, *args, **kwargs) -> None:
         self.twenty48_pane = twenty48_pane
         self.game = self.twenty48_pane.game
 
diff --git a/pw_console/py/pw_console/progress_bar/progress_bar_impl.py b/pw_console/py/pw_console/progress_bar/progress_bar_impl.py
index 1a4ca26..b5eb0a5 100644
--- a/pw_console/py/pw_console/progress_bar/progress_bar_impl.py
+++ b/pw_console/py/pw_console/progress_bar/progress_bar_impl.py
@@ -54,7 +54,7 @@
     def format(
         self,
         progress_bar: ProgressBar,
-        progress: 'ProgressBarCounter[object]',
+        progress: ProgressBarCounter[object],
         width: int,
     ) -> AnyFormattedText:
         formatted_text = super().format(progress_bar, progress, width)
@@ -67,7 +67,7 @@
     def format(
         self,
         progress_bar: ProgressBar,
-        progress: 'ProgressBarCounter[object]',
+        progress: ProgressBarCounter[object],
         width: int,
     ) -> AnyFormattedText:
         formatted_text = super().format(progress_bar, progress, width)
@@ -80,7 +80,7 @@
     def format(
         self,
         progress_bar: ProgressBar,
-        progress: 'ProgressBarCounter[object]',
+        progress: ProgressBarCounter[object],
         width: int,
     ) -> AnyFormattedText:
         formatted_text = super().format(progress_bar, progress, width)
diff --git a/pw_console/py/pw_console/repl_pane.py b/pw_console/py/pw_console/repl_pane.py
index 0619d6d..eb47c5e 100644
--- a/pw_console/py/pw_console/repl_pane.py
+++ b/pw_console/py/pw_console/repl_pane.py
@@ -13,6 +13,8 @@
 # the License.
 """ReplPane class."""
 
+from __future__ import annotations
+
 import asyncio
 import concurrent
 import functools
@@ -102,7 +104,7 @@
     # pylint: disable=too-many-instance-attributes,too-many-public-methods
     def __init__(
         self,
-        application: 'ConsoleApp',
+        application: ConsoleApp,
         python_repl: PwPtPythonRepl,
         pane_title: str = 'Python Repl',
         startup_message: str | None = None,
diff --git a/pw_console/py/pw_console/widgets/window_pane.py b/pw_console/py/pw_console/widgets/window_pane.py
index e8b9fff..c71aa64 100644
--- a/pw_console/py/pw_console/widgets/window_pane.py
+++ b/pw_console/py/pw_console/widgets/window_pane.py
@@ -13,6 +13,8 @@
 # the License.
 """Window pane base class."""
 
+from __future__ import annotations
+
 from abc import ABC
 from typing import Callable, TYPE_CHECKING
 import functools
@@ -80,7 +82,7 @@
     # pylint: disable=too-many-instance-attributes
     def __init__(
         self,
-        application: 'ConsoleApp | Any' = None,
+        application: ConsoleApp | Any = None,
         pane_title: str = 'Window',
         height: AnyDimension | None = None,
         width: AnyDimension | None = None,
diff --git a/pw_hdlc/py/decode_test.py b/pw_hdlc/py/decode_test.py
index 0d64095..8ec3e03 100755
--- a/pw_hdlc/py/decode_test.py
+++ b/pw_hdlc/py/decode_test.py
@@ -14,6 +14,8 @@
 # the License.
 """Contains the Python decoder tests and generates C++ decoder tests."""
 
+from __future__ import annotations
+
 import queue
 from typing import Iterator, NamedTuple
 import unittest
@@ -686,7 +688,7 @@
     def test_emits_data_if_timeout_expires(self) -> None:
         frame_start = b'~this looks like a real frame'
 
-        non_frame_data: 'queue.Queue[bytes]' = queue.Queue()
+        non_frame_data: queue.Queue[bytes] = queue.Queue()
         decoder = FrameAndNonFrameDecoder(non_frame_data.put, timeout_s=0.001)
 
         self.assertEqual([], list(decoder.process(frame_start)))
diff --git a/pw_hdlc/py/pw_hdlc/rpc.py b/pw_hdlc/py/pw_hdlc/rpc.py
index c47571e..6f2c535 100644
--- a/pw_hdlc/py/pw_hdlc/rpc.py
+++ b/pw_hdlc/py/pw_hdlc/rpc.py
@@ -581,7 +581,7 @@
 
         self.server = SocketSubprocess(server_command, port)
 
-        self._bytes_queue: 'queue.SimpleQueue[bytes]' = queue.SimpleQueue()
+        self._bytes_queue: queue.SimpleQueue[bytes] = queue.SimpleQueue()
         self._read_thread = threading.Thread(target=self._read_from_socket)
         self._read_thread.start()
 
diff --git a/pw_ide/py/pw_ide/cpp.py b/pw_ide/py/pw_ide/cpp.py
index 8ad7dd4..6942e63 100644
--- a/pw_ide/py/pw_ide/cpp.py
+++ b/pw_ide/py/pw_ide/cpp.py
@@ -1083,7 +1083,7 @@
 
     @classmethod
     def merge(
-        cls, *db_sets: 'CppCompilationDatabasesMap'
+        cls, *db_sets: CppCompilationDatabasesMap
     ) -> CppCompilationDatabasesMap:
         """Merge several sets of processed compilation databases.
 
diff --git a/pw_module/py/pw_module/create.py b/pw_module/py/pw_module/create.py
index d6b03e2..df626b4 100644
--- a/pw_module/py/pw_module/create.py
+++ b/pw_module/py/pw_module/create.py
@@ -90,7 +90,7 @@
     class _IndentationContext:
         """Context that increases the output's indentation when it is active."""
 
-        def __init__(self, output: '_OutputFile', width: int):
+        def __init__(self, output: _OutputFile, width: int):
             self._output = output
             self._width: int = width
 
@@ -251,7 +251,7 @@
     def _write_cc_target(
         self,
         file: _OutputFile,
-        target: '_BuildFile.CcTarget',
+        target: _BuildFile.CcTarget,
     ) -> None:
         """Defines a C++ library target within the build file."""
 
@@ -259,7 +259,7 @@
     def _write_cc_test(
         self,
         file: _OutputFile,
-        target: '_BuildFile.CcTarget',
+        target: _BuildFile.CcTarget,
     ) -> None:
         """Defines a C++ unit test target within the build file."""
 
@@ -362,7 +362,7 @@
     def _write_cc_test(
         self,
         file: _OutputFile,
-        target: '_BuildFile.CcTarget',
+        target: _BuildFile.CcTarget,
     ) -> None:
         _GnBuildFile._target(
             file,
@@ -533,7 +533,7 @@
     def _write_cc_test(
         self,
         file: _OutputFile,
-        target: '_BuildFile.CcTarget',
+        target: _BuildFile.CcTarget,
     ) -> None:
         _BazelBuildFile._target(
             file,
@@ -622,7 +622,7 @@
     def _write_cc_test(
         self,
         file: _OutputFile,
-        target: '_BuildFile.CcTarget',
+        target: _BuildFile.CcTarget,
     ) -> None:
         _CmakeBuildFile._target(
             file,
diff --git a/pw_protobuf/py/pw_protobuf/output_file.py b/pw_protobuf/py/pw_protobuf/output_file.py
index 7e493d4..bf39c64 100644
--- a/pw_protobuf/py/pw_protobuf/output_file.py
+++ b/pw_protobuf/py/pw_protobuf/output_file.py
@@ -70,7 +70,7 @@
     class _IndentationContext:
         """Context that increases the output's indentation when it is active."""
 
-        def __init__(self, output: 'OutputFile', amount: int):
+        def __init__(self, output: OutputFile, amount: int):
             self._output = output
             self._amount: int = amount
 
diff --git a/pw_rpc/py/pw_rpc/callback_client/impl.py b/pw_rpc/py/pw_rpc/callback_client/impl.py
index 9c3743c..0e2ff1b 100644
--- a/pw_rpc/py/pw_rpc/callback_client/impl.py
+++ b/pw_rpc/py/pw_rpc/callback_client/impl.py
@@ -13,6 +13,8 @@
 # the License.
 """The callback-based pw_rpc client implementation."""
 
+from __future__ import annotations
+
 import inspect
 import logging
 import textwrap
@@ -59,7 +61,7 @@
 
     def __init__(
         self,
-        client_impl: 'Impl',
+        client_impl: Impl,
         rpcs: PendingRpcs,
         channel: Channel,
         method: Method,
diff --git a/pw_rpc/py/pw_rpc/client.py b/pw_rpc/py/pw_rpc/client.py
index 3d32c89..8cbe52d 100644
--- a/pw_rpc/py/pw_rpc/client.py
+++ b/pw_rpc/py/pw_rpc/client.py
@@ -400,7 +400,7 @@
     invoked directly (e.g. rpc(field1=123, field2=b'456')).
     """
 
-    client: 'Client'
+    client: Client
     channel: Channel
     rpcs: Services
 
diff --git a/pw_rpc/py/pw_rpc/descriptors.py b/pw_rpc/py/pw_rpc/descriptors.py
index 5e15600..e901283 100644
--- a/pw_rpc/py/pw_rpc/descriptors.py
+++ b/pw_rpc/py/pw_rpc/descriptors.py
@@ -112,7 +112,7 @@
 
     _descriptor: ServiceDescriptor
     id: int
-    methods: 'Methods'
+    methods: Methods
 
     @property
     def name(self):
diff --git a/pw_transfer/integration_test/test_fixture.py b/pw_transfer/integration_test/test_fixture.py
index 14c529f..6578923 100644
--- a/pw_transfer/integration_test/test_fixture.py
+++ b/pw_transfer/integration_test/test_fixture.py
@@ -14,6 +14,8 @@
 # the License.
 """Test fixture for pw_transfer integration tests."""
 
+from __future__ import annotations
+
 import argparse
 import asyncio
 from dataclasses import dataclass
@@ -349,7 +351,7 @@
 
 class BasicTransfer(NamedTuple):
     id: int
-    type: 'config_pb2.TransferAction.TransferType.ValueType'
+    type: config_pb2.TransferAction.TransferType.ValueType
     data: bytes