#3725 Python typing stubs baseline
Closed by tkopecek. Opened by tkopecek.
tkopecek/koji issue3708  into  master

Download 3725.patch

Related: https://pagure.io/koji/issue/3708

@mikem @cobrien I've used koji-smoky-dingo as a baseline, reused types directly in stub files, so they don't interfere with the code. If you think it is okish, I'll update also packaging. It seems that normal practice is really to install it to site-packages alongside with .py files.

Btw, main usecase is writing koji scripts. So, ClientSession "bundles" signatures for API calls as in koji-smoky-dingo.

If you're going to distribute, you may also want to add the py.typed file to the distribution to let consumers of the package have their mypy also honor the stubs

https://peps.python.org/pep-0561/#packaging-type-information

Something else I noticed which you may need to update: the ClientSession.getTaskInfo will need to be modified from what's in this PR.

reference:
https://github.com/obriencj/koji-smoky-dingo/blob/master/stubs/koji/init.pyi#L459

Something else I noticed which you may need to update: the ClientSession.getTaskInfo will need to be modified from what's in this PR.

It is now corresponding to real API - it is doing more than what is in docstring :-( I'll file separate PR to update that API doc.

PR #3726

I mean to say that the behavior isn't represented correctly when using Union[int,List[int]] as the argument type. typing offers an overload decorator which says essentially "when called with these argument types, you get this result type; when called with these different argument types, you get this different result type" which is how getTaskInfo truly behaves

That's why there are two definitions for getTaskInfo in the KSD variation of the .pyi. mypy verification gets quite unhappy when using the union form instead of the overload form

https://docs.python.org/3/library/typing.html#typing.overload

Ah, nice - I wasn't aware of this.

1 new commit added

  • overload getTaskInfo

rebased onto ca97aa9eae5b4bc8e3c9feb78383e19688938e63

Since the .typi files were accidentally included in the 1.33 wheel on PyPI, I got a chance to Beta test them. Looking forward to having this officially!

Hit a few problems though:

  • ClientSession.listBuilds() returns _BuildInfos which is Collection[_BuildInfo], Collection only has __contains__, __iter__, __len__, but my code did something vaguely similar to build = session.listBuilds(..., 'queryOpts': {'order': '-completion_ts'})[0]. IMO, all list returns should be List[type] (general principle to take generic types, return concrete types.)

  • But on other side, it's a problem that chainMaven takes Collection[_BuildInfos], since xmlrpmc wants specifically a list to marshal. (Not a problem I hit in practice, just looking how BuildInfos is used.)

  • koji.PathInfo.build/rpm are specified as taking _BuildInfo, _RpmInfo, but it can be useful to do .e.g: koji.PathInfo.build({"name": .., "version": ..., "release": ...) without doing a server roundtrip to get all the fields. To get more type safety than a dict, could do class _NVRInfo(TypedDict) with just name/version/release, and make build() take that. With both pyright and mpypy, you'd be able to pass a _BuildInfo into the function since it has a superset of the fields.

  • BaseTaskHandler.run_callbacks() is specified with *args: list, **kwargs: dict, but that means that non-kwarg arguments all have list values, and the kwargs dict arguments (https://peps.python.org/pep-0484/#arbitrary-argument-lists-and-default-argument-values)
    What was meant was probably: *args: Any, **kwargs: Any

  • BaseTaskHandler.__init__ has options: dict, but options is not a dict, it's optparse.Values.

  • koji.DEP_* and koji.RPMSENSE_* constants are missing. (And other constants. To declare a constant in a stub, it is sufficent to do CONSTANT: int)

rebased onto 20f3b10e2154a9ebf115d4b98987da65866d70cb

Thanks! Added some updates (+rebase).

rebased onto 1ccb7fa2708b3fb9bb05a507beee7aabcd87ca23

1 new commit added

  • remove unused import

Not sure what should be the best python 3.x version to stuck with.

rebased onto ef29ebccce737a3d9198ea9a2bf2ef5cad23b9f0

rebased onto 89bfce95e6e4099bfd32530d5559c91cbcca8663

rebased onto e83eb0de546f0a6e49cf930d98e590761bc312d4

I've moved it to https://github.com/tkopecek/koji-stubs for now. It is just a copy of files - needs packaging, etc.

Pull-Request has been closed by tkopecek

Metadata