Repository: cherrypy/cheroot (language: python)

Issue:
Add type hints
❓ **I'm submitting a ...**
- [ ] 🐞 bug report
- [X] 🐣 feature request
- [ ] ❓ question about the decisions made in the repository

🐣 **Describe the solution you'd like**
It would be great to see the python 3.5+ type hints in the repository, especially for the ``Server`` api.

📋 **Describe alternatives you've considered**
Adding type stubs to typeshed (https://github.com/python/typeshed/tree/master/stubs).
If you think this makes more sense, that's possible. But I first wanted to ask here.



Discussion / hints:
I'd love to see type hints here in Cheroot and in CherryPy. The next major release is supposed to be dropping py2 so it's possible to use native syntax. OTOH, we could also try pyi files or comment-based hints for something to be available in the 8.x stream. PR is welcome :)
@webknjaz Let me try to add some more context and ideas
- type comments: very limited syntax but python 2 compatible. I guess it's not worth the effort due the deprecation of python 2
- pyi files: would then be part of typeshed I guess? However, I prefer native support, because you don't forget to adapt the types when you code. In addition, mypy can then also help you during development.

I'm happy to file a PR adding mypy and some utility stuff. I can also try to add some types by my own but I guess help of the actual core developers will be needed. In addition it should be decided, if you would like to type your whole codebase or only the public API. 

That's btw just my view, so please feel free to add yours 😄 
> - type comments: very limited syntax but python 2 compatible. I guess it's not worth the effort due the deprecation of python 2

There's more to it. We were thinking about keeping the 8.x for bugfixes. This means that we'd need to backport things from the newer versions. Active use of the newer syntax would mean the need to manually resolve conflicts, which adds to the maintainance burden. OTOH if the code base is similar enough, `git cherry-pick` will be able to apply patches cleanly, meaning that we could just rely on the backporting bot to do this.
So from this perspective, it's totally worth the effort. This is the main reason I proposed this.

> - pyi files: would then be part of typeshed I guess? However, I prefer native support, because you don't forget to adapt the types when you code. In addition, mypy can then also help you during development.

No, pyi files can also live in the project next to their counterparts.

> I'm happy to file a PR adding mypy and some utility stuff. I can also try to add some types by my own but I guess help of the actual core developers will be needed. In addition it should be decided, if you would like to type your whole codebase or only the public API. 

You can count on me for reviews. Also, the mypy integration should go to the pre-commit.com config FYI.

Oh, and a bonus though: it'd be interesting to also use all of the other type checkers that exist, at least in the CI. Because the users or Pyro or other stuff would get different results compared to the mypy users and we need to be compliant with all of these.
Sorry for the late reply. I agree with you, pyi files seem to be the best solution. If it's fine for you, I'll try to add some base hints for e.g. the ``Server`` and then let's see
Sounds good. Note that I'm on vacation and may be unable to review for a week or two.

Fix patch:
diff --git a/cheroot/_compat.pyi b/cheroot/_compat.pyi
new file mode 100644
index 0000000000..8726446150
--- /dev/null
+++ b/cheroot/_compat.pyi
@@ -0,0 +1,25 @@
+from typing import Any, ContextManager, Optional, Type, Union
+
+def suppress(*exceptions: Type[BaseException]) -> ContextManager[None]: ...
+
+selectors: Any
+
+IS_ABOVE_OPENSSL10: Optional[bool]
+IS_CI: bool
+IS_GITHUB_ACTIONS_WORKFLOW: bool
+IS_PYPY: bool
+SYS_PLATFORM: str
+IS_WINDOWS: bool
+IS_LINUX: bool
+IS_MACOS: bool
+PLATFORM_ARCH: str
+IS_PPC: bool
+
+def ntob(n: str, encoding: str = ...) -> bytes: ...
+def ntou(n: str, encoding: str = ...) -> str: ...
+def bton(b: bytes, encoding: str = ...) -> str: ...
+def assert_native(n: str) -> None: ...
+
+memoryview: Any
+
+def extract_bytes(mv: Union[memoryview, bytes]) -> bytes: ...
diff --git a/mypy.ini b/mypy.ini
index 2e0be78a1c..24b4ac8611 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -6,4 +6,4 @@ warn_no_return = true
 warn_redundant_casts = true
 warn_unused_configs = true
 ignore_missing_imports = true
-exclude = cheroot/test|cheroot/_compat
+exclude = cheroot/test


Test patch:
diff --git a/stubtest_allowlist.txt b/stubtest_allowlist.txt
index d628fb2620..b5f551d89f 100644
--- a/stubtest_allowlist.txt
+++ b/stubtest_allowlist.txt
@@ -38,3 +38,6 @@ cheroot.ssl.pyopenssl.SSLConnection.write
 # false positives (https://github.com/python/mypy/issues/11843)
 cheroot.connections.IS_WINDOWS
 cheroot.ssl.builtin.IS_ABOVE_OPENSSL10
+
+# suppress is both a function and class
+cheroot._compat.suppress