Pylance-release: Support Tqdm

Created on 13 Aug 2020  路  12Comments  路  Source: microsoft/pylance-release

Hi,

Tqdm is a popular library that provides easy-to-use progress bars.

It is currently not working with Pylance (I generated stubs as pylance suggests, but they don't seem to help).

It would be great if it worked!

needs stub

All 12 comments

We should be able to work with any library (but potentially some things within may not work). Can you provide some examples of what you think isn't working when using the library? Is it not resolving? Are some things missing? Are some of the types wrong? What's not working about it?

Sure, sorry, I was very unspecific.

Tqdm is typically used to wrap iterables in for-loops like this:

from tqdm import tqdm

for i in tqdm(range(20)):
  print (i)

It then outputs a nice progress bar when running the script, without changing anything to the logic of the code.

Currently, Pylance shows an error saying Type of "i" is unknown Pylance (reportUnknownVariableType). The function tqdm(iterable) returns an iterable of the same type as the one that was passed in, so here i should be of type int.

There's some more advanced usecases, but I'd guess that 99% of tqdm use is for simple uses like this - so just adding good stubs for the tqdm function should be a good starting point.

It sounds like you would be better off sticking with "basic" type checking mode. The reportUnknownVariableType diagnostic rule is enabled only in "strict" mode. For strict mode, you will need high-quality and complete type stubs for all libraries that you are using. Such type stubs don't exist yet for many libraries.

As you noticed, Pylance provides a feature for creating a "first draft" of type stubs for a library, but you will need to do significant work to fill in remaining type information. For example, the __iter__ method in the tqdm class has no return type annotation, so you would need to manually provide that type annotation.

@erictraut, sure, this wasn't a bug report - I selected "feature request" when creating this issue but it doesn't seem like that is visible anywhere.

If requests for stubs for specific libraries are discouraged here, then I won't post any more. Maybe consider making it clear at issue creation time that this isn't the place to request (better) stubs?

The templates largely exist to allow forms with varying levels of info, but don't apply labels because we want to triage requests and label them appropriately. E.g., if something is requested as a feature, but we know it should work, then we know it's a bug and need to handle it as such.

We can modify our template to note that this isn't the place to ask for specific stubs.

We briefly talked about this, and we don't want to explicitly discourage reporting like this as it's useful feedback for what's missing. But, upstream stubs are definitely going to be the preferred method.

Note that there's already an issue on the tqdm repo (https://github.com/tqdm/tqdm/issues/260) for creating type stubs; it seems like there would be support for a PR for this but there hasn't been anybody who has wanted to actually make the stub files.

We had actually looked into stubbing tqdm ourselves, and found that it was largely just that one function, yes. You'd need to decide if that's truly the entire API that tqdm offers, as the stub defines the API of the module it describes, and omitting something means we're no longer going to show it.

Note that you don't want to call it T, as the name implies that it is exported from the stub, when the T doesn't "really" exist in the real code. So you'd want to write:

from typing import Any, Iterable, Iterator, TypeVar
_T = TypeVar("_T")
def tqdm(iterable: Iterable[_T], *args: Any, **kwargs: Any) -> Iterator[_T]: ...

Something I missed; the parameter names used in the real code should match the stub, as I can write tqdm(iterable=[]) and it work in the stub but not in the real code; you'll want to make sure that lines up if possible.

You'd also need to verify that Iterable is the right Protocol to use; if the underlying code really does require Iterator you don't want to type it too loosely. Returning Iterator makes sense.

Right; is it really a valid stub though? The actual function is tqdm.tqdm.__init__.

Probably not, I commented back on the upstream issue if you'd prefer there: https://github.com/tqdm/tqdm/issues/260#issuecomment-680264808

Was this page helpful?
0 / 5 - 0 ratings

Related issues

flaree picture flaree  路  4Comments

PedroMDuarte picture PedroMDuarte  路  5Comments

ciaranjudge picture ciaranjudge  路  3Comments

tweakimp picture tweakimp  路  3Comments

martinjohndyer picture martinjohndyer  路  4Comments