python: Fix 3.11 lint errors

This corrects lint errors that get reported on Python 3.11 but not
Python 3.8.

Unify pw_protobuf and pw_protobuf_compiler dependency versions.

Change-Id: I06cafae6692c8bf2fa878d4873c6ccd4e294c50c
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/153270
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com>
Commit-Queue: Anthony DiGirolamo <tonymd@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
diff --git a/pw_build/py/pw_build/project_builder_context.py b/pw_build/py/pw_build/project_builder_context.py
index f459423..4e68260 100644
--- a/pw_build/py/pw_build/project_builder_context.py
+++ b/pw_build/py/pw_build/project_builder_context.py
@@ -221,7 +221,7 @@
     def clear_progress_scrollback(self) -> None:
         if not self.progress_bar:
             return
-        self.progress_bar._app_loop.call_soon_threadsafe(  # pylint: disable=protected-access
+        self.progress_bar._app_loop.call_soon_threadsafe(  # type: ignore # pylint: disable=all
             self.progress_bar.app.renderer.clear
         )
 
diff --git a/pw_env_setup/py/pw_env_setup/python_packages.py b/pw_env_setup/py/pw_env_setup/python_packages.py
index 34cd043..96e69f0 100644
--- a/pw_env_setup/py/pw_env_setup/python_packages.py
+++ b/pw_env_setup/py/pw_env_setup/python_packages.py
@@ -33,7 +33,7 @@
         if isinstance(pkg, pkg_resources.DistInfoDistribution)  # type: ignore
         # This will skip packages with local versions.
         #   For example text after a plus sign: 1.2.3+dev456
-        and not pkg.parsed_version.local
+        and not pkg.parsed_version.local  # type: ignore
         # These are always installed by default in:
         #   pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
         and pkg.key not in ['pip', 'setuptools', 'wheel']
diff --git a/pw_protobuf/py/setup.cfg b/pw_protobuf/py/setup.cfg
index 915967b..209a533 100644
--- a/pw_protobuf/py/setup.cfg
+++ b/pw_protobuf/py/setup.cfg
@@ -25,6 +25,7 @@
     # protoc 3.17 requires a protobuf version >= 3.20.1 and <= 3.20.3
     # https://developers.google.com/protocol-buffers/docs/news/2022-05-06#python-updates
     # Match all 3.20.* versions:
+    # This is also specified in //pw_protobuf_compiler/py/setup.cfg
     protobuf~=3.20.1
     googleapis-common-protos>=1.56.2
     graphlib-backport;python_version<'3.9'
diff --git a/pw_protobuf_compiler/py/setup.cfg b/pw_protobuf_compiler/py/setup.cfg
index 8e3a6ec..11bc544 100644
--- a/pw_protobuf_compiler/py/setup.cfg
+++ b/pw_protobuf_compiler/py/setup.cfg
@@ -23,12 +23,13 @@
 zip_safe = False
 install_requires =
     # NOTE: protobuf needs to stay in sync with mypy-protobuf
-    # Currently using mypy protobuf 3.20.1 and mypy-protobuf 3.3.0 (see
+    # Currently using mypy protobuf 3.20.3 and mypy-protobuf 3.3.0 (see
     # constraint.list). These requirements should stay as >= the lowest version
     # we support.
-    mypy-protobuf>=3.2.0
-    protobuf>=3.20.1
-    types-protobuf>=3.19.22
+    mypy-protobuf>=3.2.0,<3.4.0
+    # This is also specified in //pw_protobuf/py/setup.cfg
+    protobuf~=3.20.1
+    types-protobuf>=3.19.22,<4.0.0
 
 [options.package_data]
 pw_protobuf_compiler = py.typed
diff --git a/pw_tokenizer/py/pw_tokenizer/detokenize.py b/pw_tokenizer/py/pw_tokenizer/detokenize.py
index 3aa7a3a..34f3a31 100755
--- a/pw_tokenizer/py/pw_tokenizer/detokenize.py
+++ b/pw_tokenizer/py/pw_tokenizer/detokenize.py
@@ -73,7 +73,7 @@
 BASE64_PREFIX = encode.BASE64_PREFIX.encode()
 DEFAULT_RECURSION = 9
 
-_RawIO = Union[io.RawIOBase, BinaryIO]
+_RawIo = Union[io.RawIOBase, BinaryIO]
 
 
 class DetokenizedString:
@@ -266,7 +266,7 @@
 
     def detokenize_base64_live(
         self,
-        input_file: _RawIO,
+        input_file: _RawIo,
         output: BinaryIO,
         prefix: Union[str, bytes] = BASE64_PREFIX,
         recursion: int = DEFAULT_RECURSION,
@@ -430,14 +430,14 @@
 
         self.data = bytearray()
 
-    def _read_next(self, fd: _RawIO) -> Tuple[bytes, int]:
+    def _read_next(self, fd: _RawIo) -> Tuple[bytes, int]:
         """Returns the next character and its index."""
         char = fd.read(1) or b''
         index = len(self.data)
         self.data += char
         return char, index
 
-    def read_messages(self, binary_fd: _RawIO) -> Iterator[Tuple[bool, bytes]]:
+    def read_messages(self, binary_fd: _RawIo) -> Iterator[Tuple[bool, bytes]]:
         """Parses prefixed messages; yields (is_message, contents) chunks."""
         message_start = None
 
@@ -464,7 +464,7 @@
                 yield False, char
 
     def transform(
-        self, binary_fd: _RawIO, transform: Callable[[bytes], bytes]
+        self, binary_fd: _RawIo, transform: Callable[[bytes], bytes]
     ) -> Iterator[bytes]:
         """Yields the file with a transformation applied to the messages."""
         for is_message, chunk in self.read_messages(binary_fd):