upstash / qstash-py

Python SDK for Upstash QStash
https://docs.upstash.com/qstash
MIT License
7 stars 1 forks source link

Typing Examples #15

Open pedroimpulcetto opened 2 months ago

pedroimpulcetto commented 2 months ago

Proposal

Hey there, do we want to use type hints in rows for types?

Example:

from upstash_qstash import Client
from qstash_tokens import QSTASH_TOKEN
from upstash_qstash.schedules import CreateScheduleRequest

client = Client(QSTASH_TOKEN)
schedules = client.schedules()

params: CreateScheduleRequest = {
            "cron": "* * * * *",
            "destination": "https://py-qstash-testing.requestcatcher.com",
            "body": {"hello": "world"},
            "headers": {
                "content-type": "application/json",  # This is the default, but you can override it
            },
        }
res = schedules.create(params)

So, by doing that params: CreateScheduleRequest we can give a really good experience to the user and he can make sure is passing the right params to the method. Also, he can have a quick check with the VSCode autocomplete feature.

Screenshot 2024-05-03 at 4 49 20 PM

And see if some key is optional or required as well.

Screenshot 2024-05-03 at 4 53 48 PM


If we want to do it, I can work on that 😄

MeshanKhosla commented 2 months ago

What would this change from the existing request dictionary? https://github.com/upstash/qstash-python/blob/80a1f2ff2ddea7f421fd1870f36c683de94ae1ee/upstash_qstash/schedules.py#L25

pedroimpulcetto commented 2 months ago

We may need to make some small changes from the Optional type to use NotRequired. - Take a look at the Typed Dict reference

And also, it would be nice to set up MyPy to have a proper check. Using "all" sort of checker.

After that, we can change the examples and docs to show explicitly to the user which are the parameter types, like the example above.

params: CreateScheduleRequest = { ...
pedroimpulcetto commented 2 months ago

mypy

it would be nice to have all sorts of checkers in mypy

mypy.ini

[mypy]
; Ensure full coverage
disallow_untyped_calls = True
disallow_untyped_defs = True
disallow_incomplete_defs = True
disallow_untyped_decorators = True
check_untyped_defs = True

; Restrict dynamic typing
disallow_any_generics = True
disallow_subclassing_any = True
warn_return_any = True

; Know exactly what you're doing
warn_redundant_casts = True
warn_unused_ignores = True
warn_unused_configs = True
warn_unreachable = True
show_error_codes = True

; Explicit is better than implicit
no_implicit_optional = True

Screenshot 2024-05-06 at 10 14 03 AM

with that, we are going to have ~168 issues.

but definitely, it can be done progressively, incrementing each checker at a time

pedroimpulcetto commented 1 month ago

adding:

fixing all these types of issues we can mark the package as "typed" using the py. typed file to follow PEP-561 to allow MyPy to check the package as a third part in other projects.