Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best Practices document #851

Open
Tracked by #845
srittau opened this issue Aug 24, 2021 · 3 comments
Open
Tracked by #845

Best Practices document #851

srittau opened this issue Aug 24, 2021 · 3 comments
Labels
topic: documentation Documentation-related issues and PRs

Comments

@srittau
Copy link
Collaborator

srittau commented Aug 24, 2021

  • Built-in generics
  • New union syntax
  • No union return types, use Any or T | Any
  • Discuss Any vs object
  • Callbacks: Use return type object instead of None or Any if the returned value is ignored

Please add anything you think the document should contain.

@hmc-cs-mdrissi
Copy link

What knowledge should the document assume and what are prerequisite documents to read? The typing tutorial + type stub tutorial? If yes then I think this is blocked by those two documents being created first just to build on them.

One practice common in my team is if python 3.7+ is fine (most of our code) then use from future import annotations and feel free to use features in newer version. We're currently on 3.7 and about to migrate to 3.8 before being stuck there for a couple months until 1 dependency updates. If you are in 3.6 you can still use string annotations for new syntax.

Another one is prefer TypedDict over dicts. Sometimes we do need a mapping[str, str] and don't know much about input argument, but a lot of times we do know the structure of dict. I often see people new to types used dict when a specific typeddict is actual expectation. Similarly NamedTuple > namedtuple. Most of the time where mapping is correct its utility functions while main business/api logic has more knowledge of the dict. If you are indexing elements by specific values like d['foo'] then mapping can probably be typeddict instead.

Unsure if this goes in tutorial or best practices, method compatibility check (liskov substituation) is an important one I occasionally see broken. One common reason I see it broken is from superclass really being generic on a type but not stating it.

Include partial/py.typed for any libraries you make. Avoid relying on implicit imports. Specifically the section on what symbols are publicly exported from a module here. Some libraries I use heavily ignore this rule which leads to some type checker confusion. The from x import A as A syntax is one that's pretty uncommon that I usually need to explain.

May fit better in a different doc, but one practice that's helped a lot in improving type coverage of our codebase is adding a CI check that runs type checkers twice on changed files and requires the error count to go down by 5 on every PR compared to master. It's pretty difficult for 1/2 people to add types to large codebase so making a CI rule that pushes in that direction has helped a lot. Any type checker is fine for this and I currently run 2 in CI. Simpler check of requiring 0 type errors would have been unfeasible when a lot files had 100+ type errors (mostly missing types).

There's also question of how to handle recent pep type features that are not supported by all type checkers yet. My current practice is to allow them if some checker handles it and type ignore as needed for other checker (recursive types being one). That's very debatable practice though and it may be better for a best practices doc to avoid type features missing support in a popular checker.

@srittau
Copy link
Collaborator Author

srittau commented Sep 27, 2021

We should include a section about I/O types:

  • Use protocols if possible for argument types.
  • Use concrete types for return types. Ideally, these derive from typing.IO.
  • Use typing.IO, not io.IOBase.

Came up in python/typeshed#6067.

@srittau
Copy link
Collaborator Author

srittau commented May 21, 2022

Another best practice: Use from __future__ import annotations. (Which of course @hmc-cs-mdrissi already mentioned and I overlooked.)

srittau added a commit to srittau/typing that referenced this issue May 21, 2022
Move all "style guide" items over that apply to both stubs as well as
implementation. The items are reordered and the "Types" section was
split, but the text itself is unchanged.

Part of python#851
hauntsaninja pushed a commit that referenced this issue May 21, 2022
Move all "style guide" items over that apply to both stubs as well as
implementation. The items are reordered and the "Types" section was
split, but the text itself is unchanged.

Part of #851
srittau added a commit to srittau/typing that referenced this issue May 25, 2022
JelleZijlstra added a commit that referenced this issue Jun 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: documentation Documentation-related issues and PRs
Projects
None yet
Development

No branches or pull requests

2 participants