#type-hinting

1 messages ยท Page 52 of 1

blazing nest
#

Because fn is Callable[..., T]. MyPy can't figure out that ...

soft matrix
#

You can totally do this with ParamSpec and pyright

little hare
#

but pyright isn't written in python ๐Ÿฅฒ

blazing nest
#

Also kind of suprised it even works at all, I thought type checkers didn't check for that type of dynamicness inside of function bodies?

nocturne snow
#

hmmm

#
FuncT = TypeVar('FuncT', bound=Callable[..., T])
class gevent_coroutine(Generic[FuncT]):
    def __init__(self, fn: FuncT):
        self.__call__ = fn
#

this carries the type across but it also breaks uh

#

like handling the self/cls argument

blazing nest
nocturne snow
#

fails in both orders

blazing nest
#

Ah no, just tried it. MyPy doesn't care

soft matrix
#

why are you using gevent in the first place :)?

nocturne snow
#

this codebase is old

blazing nest
# nocturne snow fails in both orders

At runtime if @gevent_coroutine was innermost then you would need to supply the cls argument when running. Because before it has been wrapped in a classmethod you are intercepting the function afaik.

nocturne snow
#

it works with staticmethod

#

doesn't work with classmethod

blazing nest
#

Yeah, when you have staticmethod you don't have any argument so it plays nicely

dire bobcat
#

a channel for typehinting lol

blazing nest
#

Yeah? And?

narrow goblet
#

how do i type hint a fixed size list?

#

like Tuple[int, int] but i want list instead of tuple: List[int, int] does not work

slender glen
#

The whole point of lists is to be dynamically sized. If you need a fixed sized list, then use a tuple instead

narrow goblet
#

you're right, however i can't assign tuple item, so it's not exactly what i need. but i think it's okay to recreate the tuple instead of assigning it's item, since i have only 2 item inside it

blazing nest
#

!e ```python
from sys import getsizeof

print(getsizeof(list()))
print(getsizeof(tuple()))

rough sluiceBOT
#

@blazing nest :white_check_mark: Your eval job has completed with return code 0.

001 | 56
002 | 40
blazing nest
#

Tuples are also smaller ๐Ÿ˜‰

brazen horizon
#

How can I type hint an argument that has to be an int that is more than or equals to 10?

oblique urchin
brazen horizon
#

๐Ÿ˜ฆ

fierce ridge
#

you can do it with TypeGuard!

#

(kinda)

#

unfortunately i'm not aware of any way to make this parameterizable, e.g. you can't have class IntegerAtLeast[10] or class IntegerAtLeast[Literal[10]], because you aren't allowed to write class IntegerAtLeast(int, Generic[I]) such that I is Literal[<any integer>]

trim tangle
# trim tangle You can't

btw, did y'all know that asyncio.gather returns a list even though the type hint says it returns a tuple?

#

Typing hacks, volume 3

fierce ridge
#

...why does it do that

trim tangle
fierce ridge
#

is it like map where they try to capture the heterogeneity by overloading 1, 2, 3, etc. until they give up around 5?

trim tangle
#

Yep

fierce ridge
#

alas

oblique urchin
#

hey I thought we went up to like 8

fierce ridge
#

(jk)

oblique urchin
rough sluiceBOT
#

stdlib/builtins.pyi line 1084

class map(Iterator[_S], Generic[_S]):```
oblique urchin
fierce ridge
#

probably not explicitly, but i bet someone out there somewhere has done some trickery with *-unpacking that results in such a thing

oblique urchin
#

For zip maybe, but map? In any case that wouldn't match an explicit overload with 32 args anyway

fierce ridge
#

true

#

unless it was a length-32 tuple where the length was known statically somehow ๐Ÿ˜›

soft matrix
#

isnt typing gather one of the reason guido wants pep 646?

oblique urchin
#

I think map and zip are more of a motivation. gather() would still not work because we don't have a way to type heterogeneous lists

fierce ridge
#

what if Tuple had a generalization to "fixed-size heterogenous sequences"

blazing nest
#

!pep 646

rough sluiceBOT
#
**PEP 646 - Variadic Generics**
Status

Draft

Python-Version

3.10

Created

16-Sep-2020

Type

Standards Track

blazing nest
#

Ah right, I see

#

Tuple, Literal basically gets special behaviour no one else does

trim tangle
#

Hmmmm well now it should be ```py
typing_hack_volumes: Literal[2] = 9 # type: ignore

HACK

trim tangle
# fierce ridge alas

we should make are-we-typescript-yet.com and cache NO with a TTL of like a decade
for legal reasons this is a joke

rustic gull
#

Why doesn't this work?

_F = TypeVar("_F", bound=Callable[..., Any])
oblique urchin
rustic gull
old hull
#

is there a compiler that optimises based off of hinting or am i tripping

soft matrix
#

cython or mypyc are your best options if you want to compile stuff based off of annotations

fierce ridge
trim tangle
fierce ridge
trim tangle
#

ah

#

yeah

#

I meant that as a comment about typescript having this nice feature

#

random thought: what if the typing module wasn't in the stdlib?

#

type checkers are (somewhat) incompatible anyway

#

so mypy could make its own type language that's convenient to implement, pyright would make one etc.

#

just like in JS there were flow and typescript and something else

brisk hedge
#

Sounds like pretty nasty fragmentation

trim tangle
#

in the end the JS community converged on one option

#

which won because of the free market competition

fierce ridge
#

there's no reason a type checker couldn't write their own typing alternative or their own typing-extensions that is only supported by that type checker

#

i think having it in the stdlib makes a lot of sense

#

imagine if flow and typescript could use the same core system of basic types

#

flow would probably still be in use today if you could write code that ran under both systems

soft matrix
oblique urchin
#

Yes, there's nothing stopping type checkers from implementing their own extensions

#

And we already have typing-extensions where we can put things without being bound to the stdlib release cycle

pale otter
#

I feel stupid for asking, but is using __future__ to use the | (PEP604) in type hinting a legit method?

from __future__ import annotations

@dataclass
class Puppy:

  breed: str | None
  adoption_date: datetime.date

...
#

i'm not on 3.10 yet and using the method shown above doesn't give me any errors/warnings on my IDE, but i'm curious on whether there's a better way

soft matrix
#

yeah

#

not really no

#

depends on if you only support 3.7+

pale otter
soft matrix
#

if you you dont have future annotations you need to use a forward reference and quote the "str | None" part

soft matrix
#

dw about forward references then

pale otter
#

yippee! thanks wavey

trim tangle
#

it's fine as long as you don't evaluate the annotations at runtime

pale otter
#

are you referring to PEP563?

brisk hedge
#

Oh wait dataclass types aren't collected at runtime

soft matrix
#

like dont run

#

!d typing.get_type_hints

rough sluiceBOT
#

typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)```
Return a dictionary containing type hints for a function, method, module or class object.

This is often the same as `obj.__annotations__`. In addition, forward references encoded as string literals are handled by evaluating them in `globals` and `locals` namespaces. If necessary, `Optional[t]` is added for function and method annotations if a default value equal to `None` is set. For a class `C`, return a dictionary constructed by merging all the `__annotations__` along `C.__mro__` in reverse order.

The function recursively replaces all `Annotated[T, ...]` with `T`, unless `include_extras` is set to `True` (see [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated "typing.Annotated") for more information). For example:
soft matrix
#

on your Pet class

pale otter
#

ah

#

that makes sense

blazing nest
#

I actually prefer explicit forward references

#

It makes it clear that "this will be defined in the future" or that "I am not actually importing this".

pale otter
unreal bolt
#

Making the annotations strings can get annoying sometimes

trim tangle
#

I searched far and wide, but couldn't find how to get a mypy.types.ProperType representing int... Should be easy, right?

#

Found it, ctx.api.named_type

fierce ridge
oblique urchin
rustic gull
#

Is there a way to enable all mypy checks instead of having something like this in the pyproject.toml pithink toml [tool.mypy] check_untyped_defs = true disallow_any_generics = true ignore_missing_imports = true no_implicit_optional = true no_implicit_reexport = true show_error_codes = true strict_equality = true warn_redundant_casts = true warn_return_any = true warn_unreachable = true warn_unused_configs = true

leaden oak
#

strict = true maybe?

#

although it turns on some other checks that can be annoying to say the least ...

fierce ridge
#

I usually do strict = true and show_error_codes = true

spare mauve
#

worth noting __future__.annotations breaks pydantic too

pliant horizon
#

Aside from not using it

blazing nest
#

There is none lmao

#

If you're using __future__.annotations because of a circular import, then there is no fix other than a restructuring of the project.

pliant horizon
trim tangle
#

well, that will just fail at runtime

#

pydantic has to evaluate the actual expressions in the annotations

#

so if you want to use pydantic, just do Dict[str, str] (or maybe use Mapping[str, str] if you don't actually need a dict)

pliant horizon
#

From pydantic devs side

blazing nest
#

I mean they're trying to of course, but you literally need to eval() code

pliant horizon
#

Like fix the conflict between eval() and __future__.annotations

#

So lemme get this straight

#

from __future__ import annotations fails when using pydantic?

soft matrix
#

The import doesn't fail

#

It's just using it makes pydantic break

pliant horizon
#

In 3.8+

soft matrix
#

You need to be on 3.9+

#

For that to atleast come close to working

pliant horizon
#

Why

#

dict[str, str] works with that import on 3.8+

#

right?

soft matrix
#

Pydantic will evaluate the annotations at runtime

#

And that doesn't work at runtime on 3.8

pliant horizon
#

I'm pretty sure from __future__ import annotations converts that dict[str, str] to an understandable for 3.8+ code

trim tangle
#

@pliant horizon all from __future__ import annotations does is defer the evaluation of annotations

#

It doesn't automatically transform dict[str, str] into Dict[str, str] or anything like that.

pliant horizon
#

Is there any method not to use deprecated code for a 3.8+ compatible project?

trim tangle
#

I don't think so, just use Dict

pliant horizon
blazing nest
#

Not in 3.8

soft matrix
#

You can do some gross compatibility stuff

blazing nest
#

Use Dict until it is removed. When it is, drop support for 3.8 and use dict

pliant horizon
soft matrix
#

Like if sys.version_info > (3, 8):
Dict = dict
else: from typing import Dict

#

Probably yes

blazing nest
blazing nest
trim tangle
#

And at that point, 3.8 will be deprecated

pliant horizon
#

So just use deprecated code until 3.8 bites the dust then

trim tangle
#

Yes

blazing nest
soft matrix
#

I think most a lot of libraries have switched to 3.9+ already haven't they?

#

Atleast numpy and astropy are

pliant horizon
blazing nest
soft matrix
#

I'm personally concerned with making people have to stick on a version I think having to support older versions of python just ends up being a pain

#

If people don't want to update they just shouldn't use whatever I'm writing

trim tangle
pliant horizon
#

Like is it that hard

trim tangle
#

for beginners and people who aren't professional programmers it might be hard

pliant horizon
#

I already ditched 3.9 and using 3.10

blazing nest
pliant horizon
trim tangle
pliant horizon
green gale
green gale
blazing nest
blazing nest
trim tangle
#

I've seen how people struggle with installing Python on windows

pliant horizon
#

So @green gale @trim tangle if you were me
Would you make a huge discord API wrapper 3.8+ or 3.9+?

green gale
#

3.9+

trim tangle
#

but yeah, most people will be fine with 3.9

pliant horizon
#

So just use 3.9 code then?

trim tangle
#

If all you need is nicer type annotations I'd stick with 3.8

pliant horizon
#

Apparently from __future__ import annotations works

#

With 3.8+ and list

trim tangle
#

if you don't need to inspect the annotations, then yes, that will work

#

I'm actually not sure how often you really need dict[K, V] and list[T] and not Mapping[K, V]/MutableMapping[K, V] and Sequence[T]/MutableSequence[T]/Iterable[T].

blazing nest
#

Look, the type is a string

trim tangle
#

define 'work'

#

if you need the annotation for static analysis purposes, it does work

soft matrix
pliant horizon
trim tangle
#

so when you drop support for 3.8 you'll have to import them from collections.abc

pliant horizon
#

Which begs the question

#

Should I even support 3.8 now?

trim tangle
#
  • it will be there until 2025
  • upgrading is not that hard
  • many people still use 3.8
pliant horizon
#

Third one is a concern

trim tangle
#

over time they'll stop using 3.8

pliant horizon
#

OK fair

soft matrix
#

You can look at the numbers yourself and decide if they are worth it

#

They are on pypi somewhere

blazing nest
#

Important to know is that the numbers are heavilty affected by CI

pliant horizon
#

It just annoys me how people still use 2.7

#

Like come on

#

It's dead

#

Move on

trim tangle
#

yeah, just fork the CAD program you're using and update it to 3.10 ๐Ÿ™‚

pliant horizon
runic tapir
#

On large codebases that have barely been touched in a decade and that were written by someone else, it absolutely is

#

And without any test suite, of course.

spare mauve
#

voila, no more deprecated code ๐Ÿ˜…

pliant horizon
#

iirc

rustic gull
#

what's the difference between collections.abc and typing

trim tangle
#

so now the Mapping in typing is deprecated because we don't need two different things for the same annotation

rustic gull
#

i see

#

so i should use collections.abc instead of typing pithink

trim tangle
rustic gull
#

so then why are stuff getting deprecated from typingpithink

trim tangle
#

Now you can do list[int] so typing.List doesn't serve any purpose

rustic gull
#

i really liked Dict and List instead of dict and list ngl ๐Ÿ˜”

pliant horizon
trim tangle
#

!e

from __future__ import annotations

def f(x: 1 + "2"):
    ...
rough sluiceBOT
#

@trim tangle :warning: Your eval job has completed with return code 0.

[No output]
pliant horizon
trim tangle
#

wdym?

#

why?

pliant horizon
# trim tangle wdym?

I shouldn't use them because then the user can insert a str instead of the typehint

#

That what you mean?

trim tangle
rough sluiceBOT
#

@trim tangle :white_check_mark: Your eval job has completed with return code 0.

{'x': <class 'int'>, 'return': <class 'list'>}
void panther
#

it only applies in the file the import is in, the lib's users won't be influenced by it (and can't influence your lib).
The only case when you'd care about it is if you inspect annotations at runtime

trim tangle
#

!e
But here they are strings:

from __future__ import annotations

def f(x: int) -> list:
    ...

print(f.__annotations__)
rough sluiceBOT
#

@trim tangle :white_check_mark: Your eval job has completed with return code 0.

{'x': 'int', 'return': 'list'}
pliant horizon
rough sluiceBOT
#

@pliant horizon :warning: Your eval job has completed with return code 0.

[No output]
pliant horizon
#

No errors

#

Despite it being a string passed into list[int]

void panther
#

there won't be any errors even without the future import, python doesn't enforce types through typehints

pliant horizon
void panther
#

Documentation and static checkers

pliant horizon
void panther
#

No, you'd have to use some 3rd party lib that inspects annotations at runtime, but that often ends up conflicting with the syntax of typehints to be functional

pliant horizon
void panther
#

you don't

#

document what it accepts and your job is done there

pliant horizon
#

That lowkey sucks

#

ngl

trim tangle
#

Annotations were originally meant for many purposes, not just type-checking. There are tools that enforce the types at runtime, but the whole point of static typing is that type errors are caught before runtime.

#

@pliant horizon There are tools like beartype that do runtime checking. But you fundamentally can't check some things at runtime.

#

For example, how do you know if a function conforms to Callable[[int], str]?

void panther
#

checking at runtime would do unnecessary checks 99% of the time as they'll only happen during development

trim tangle
#

that is also true, although I guess you could have some debug flag

pliant horizon
void panther
#

c++ also doesn't do it at runtime

trim tangle
#

C++ doesn't do that when the program runs. It does that during compilation.

#

That's what type checkers, such as mypy and pyright, do in Python.

pliant horizon
#

Like something that does it during interpertation

trim tangle
trim tangle
#

I don't know, haven't used them

trim tangle
pliant horizon
#

I want the app to raise error if someone's messing up

trim tangle
#

then I guess you can try beartype and share how it goes ๐Ÿ™‚

#

Some things you won't really be able to automate to be nice.

#

but most you probably can

pliant horizon
trim tangle
#

well, from the perspective of the library user

soft matrix
#

really it depends as with all things

#

it will hurt performance for everyone so that some people dont mess up

pliant horizon
#

I see

#

I'll just rely on Pydantic's model validations ig

leaden oak
#

hello! Due to Python runtime requirements I have had to reimplement contextlib.nullcontext. Functionally I know what I am doing, but in terms of typing I haven't used TypeVar before. I wanted to check that I was using it in the right way (before it gets stuck in my memory):

import contextlib
from typing import Iterator, TypeVar

T = TypeVar("T")

@contextlib.contextmanager
def nullcontext(enter_result: T) -> Iterator[T]:
    yield enter_result

with nullcontext(123) as value:
    print(value)
soft matrix
#

yeah thats correct

leaden oak
#

thank you!

leaden oak
pastel egret
#

For that definition, note that typing self is a special case, here it's used in the overload to indicate the generic value with different init arguments.

leaden oak
#

Is it possible to narrow the type of TypedDict field when subclassing? For context I'm trying to use the following:

class FileResult(TypedDict):
    type: Literal["nothing-changed", "reformatted", "failed"]
    src: str

class NothingChangedResult(FileResult):
    type: Literal["nothing-changed"]

class ReformattedResult(FileResult):
    type: Literal["reformatted"]
    dst: str

class FailedResult(FileResult):
    type: Literal["failed"]
    error: str
    message: str

but mypy isn't too happy about it

diff_shades/results.py:23: error: Overwriting TypedDict field "type" while extending  [misc]
diff_shades/results.py:27: error: Overwriting TypedDict field "type" while extending  [misc]
diff_shades/results.py:32: error: Overwriting TypedDict field "type" while extending  [misc]
pastel egret
#

What you could do is move the parent type to another subclass - maybe UnknownResult, and cast/maybe use TypeGuard.

soft matrix
#

Can you not just make the literal on the FileResult and instead just make it str?

leaden oak
soft matrix
#

Can you just # type: ignore?

leaden oak
#

unless I'm totally misreading your suggestion ^^

soft matrix
#

No that's what I meant

leaden oak
#

Hmm I guess I could try that, I'm just worried that since it's erroring on that, it won't narrow the type when I do:

result: FileResult
if result["type"] == "reformatted":
    reveal_type(result)  # ReformattedResult

although now I come to think about it, this might not be supported anyway

soft matrix
#

That doesn't work no

leaden oak
#

ah ok

pastel egret
#

What you need is typing.TypeGuard.

spare mauve
frank glade
#

i wished typeguard worked, it seemed really cool at first

spare mauve
#

typeguard has an easy import hook, beartype doesn't :\

frank glade
#

but the tracebacks are unwieldy

leaden oak
#

I'll think it over with the ideas and thoughts suggested, thanks!

pastel egret
#

Indeed. Otherwise you could cast it.

frank glade
#

if you have more complex stuff, consider icontract in addition

rustic gull
spare mauve
#

was __class_getitem__ added specifically to support type hints?

upbeat wadi
fierce ridge
#

(i suggested TypedDict(frozen=True) as possible syntax)

trim tangle
#

yep

#
class FooBar(TypedDict):
    x: Literal["foo", "bar"]

class Bar(FooBar):
    x: Literal["bar"]

def f(d: FooBar):
    d["x"] = "foo"

d: Bar = ...
f(d)  # oops
vapid quarry
#

Is it right to type annotate return as following:

def do_something() -> Union[Tuple[str, str], None]:
  """
  Returns a Tuple or None
  """
#

or we could also do following using Optional, and not explicitly mention None:

def do_something() -> Optional[Tuple[str, str]]:
  """
  Returns a Tuple or None
  """
leaden oak
#

!d typing.Optional

rough sluiceBOT
#

typing.Optional```
Optional type.

`Optional[X]` is equivalent to `X | None` (or `Union[X, None]`).

Note that this is not the same concept as an optional argument, which is one that has a default. An optional argument with a default does not require the `Optional` qualifier on its type annotation just because it is optional. For example:

```py
def foo(arg: int = 0) -> None:
    ...
```  On the other hand, if an explicit value of `None` is allowed, the use of `Optional` is appropriate, whether the argument is optional or not. For example...
trim tangle
#

yep

vapid quarry
#

ok thank you (:

pastel egret
#

typing.Union[X, None] actually returns typing.Optional[X].

leaden oak
#

!eval

import typing

X = typing.TypeVar("X")
huh = typing.Union[None, X]
print(huh)
rough sluiceBOT
#

@leaden oak :white_check_mark: Your eval job has completed with return code 0.

typing.Optional[~X]
pastel egret
#

Looking at the current implementation, actually Optional returns Union[x, None] and then Union's repr code special-case shows Optional.

#

X | None stays like that however.

#

In any case all three syntaxes are entirely equivalent.

blazing nest
leaden oak
#

I feel like I am managing to get the typing wrong every time I'm using a feature I haven't used before

@overload
def filter_results(
    file_results: Dict[str, FileResult], type: ResultTypes
) -> Dict[str, FileResult]:
    ...

@overload
def filter_results(
    file_results: List[FileResult], type: ResultTypes
) -> List[FileResult]:
    ...

def filter_results(file_results, type):
    reveal_type(file_results)
    if isinstance(file_results, list):
        return [result for result in file_results if result.type == type]
    else:
        return {file: result for file, result in file_results if results.type == type}

what did I do wrong here ๐Ÿ˜ฆ

pastel egret
#

Well, you are supposed to annotate the last version too, but this annotation is to specify what the implementation receives and returns - so Union[Dict[...], List[...]]

leaden oak
pastel egret
#

The type checker checks all the overloads are compatible with the implementation signature.

leaden oak
#

or is that only for stub files?

pastel egret
#

In stubs you have no implementation.

blazing nest
oblique urchin
#

Though you should indeed annotate the implementation

leaden oak
pastel egret
#

Yep, since it's unannotated the type checker ignores the content.

leaden oak
pastel egret
#

That example should probably be:

def utf8(value: Union[bytes, Unicode, None]) -> Optional[bytes]:
blazing nest
pastel egret
#

Yep.

leaden oak
#

got it, thanks!

grave fjord
#

That's a weird example could be better as:

@overload
def utf8(value: None) -> None:
    pass
@overload
def utf8(value: bytes | unicode) -> bytes:
    pass
def utf8(value: bytes | unicode | None) -> bytes | None:
    <actual implementation>
#

The typechecker should tell you if overloads are redundant and fold them into a union

fierce ridge
#

i wish you didn't have to write out the union'ed types in the implementation

grave fjord
#

Mixing def and match together would be cool

fierce ridge
#

definitely. or at least generalize the match destructuring syntax to = and function signatures

#

hm... not sure about the syntax.

def distance(p1 : Point(x1, y1), p2 : Point(x2, y2)) -> float:
    ...
upbeat wadi
#

why is subprocess.Popen subscriptable? what is the passed type for?

oblique urchin
upbeat wadi
#

nevermind

#

thanks

leaden fog
#

guys, how can I write this typescript generic statement in python?

export type Options<K, V, C = K> {}
``` can I do typevar = typevar in python?
oblique urchin
leaden fog
oblique urchin
#

There's an open issue for it in python/typing

#

If somebody advocates for it and pushes a PEP through, it'll probably be received positively

leaden fog
#
KT = TypeVar("KT")
VT = TypeVar("VT")
CT = TypeVar("CT")

class SomeClass(Generic[KT, VT, CT]):
    def some_func(self, arg: KT) -> CT:
        """this func might be overridden to return something, but returns the same arg by default."""
        return arg
```here, mypy throws an error:

Incompatible return value type (got "KT", expected "CT")

#

@oblique urchin do bounds have to do anything wth this?

oblique urchin
leaden fog
oblique urchin
leaden fog
rough sluiceBOT
#

src/index.js line 17

export type Options<K, V, C = K> = {```
pastel egret
#

You could make some_func abstract, then put this some_func implementation in a subclass, which is defined like this:

class DefaultSomeClass(Generic[KT, VT], SomeClass[KT, VT, KT]):
    ...
trim tangle
#

Or just make a type alias

#
WithDefault = Options[K, V, K]
fierce ridge
#

seems like kind of a niche use case for adding new syntax, but i can see why that'd be nice. i wish you could properly inherit from protocols instead of having to mess with ABCs

topaz dove
drowsy plinth
#

lemon_pensive wow this channel seems to have masters of python in it

pliant prism
#

while not GolfScore.isdigit() or int(GolfScore)< 18 or int(GolfScore) > 150:
AttributeError: 'int' object has no attribute 'isdigit'

#

Does anyone know what this error mean?

drowsy plinth
#

what does Generic[KT, VT] mean

trim tangle
#

@pliant prism This doesn't have anything to do with type hints. If you have a general question, see #โ“๏ฝœhow-to-get-help and claim a help channel.

#

@drowsy plinth What parts of type hinting are you already familiar with?

drowsy plinth
#
class Person:
    def __init__(self,name:str,age:int,gpa:union[int,float],courses:list):
#

that is as far as i know

trim tangle
#

Generic is how you let a type have type parameters, like list or dict.

drowsy plinth
#

there is alot for me to learn

blazing nest
#

In the code you listed, it has allowed union[int,float] to have parameters

#

(but union is a bit special)

trim tangle
#

Union is a special form, it's different

drowsy plinth
#

is not union become switched to | in patch 3.10?

blazing nest
#

It did yeah

#

But it's the same thing

drowsy plinth
#

is there any decorators or magic methods i should search to learn more how to use

#

i know ```py
@staticmethod
@classmethod
@overload < notmuch about

trim tangle
#

This is the minimal example of a generic type:

from typing import Generic, TypeVar

T = TypeVar("T")

class Box(Generic[T]):
    def __init__(self, initial_value: T):
        self._value = initial_value

    def set(self, value: T) -> None:
        self._value = value

    def get(self) -> T:
        return self._value


def increment_box(box: Box[int]) -> None:
    x = box.get()
    box.set(x + 1)


box = Box(41)
box.increment_box()

You can hover over different variables in your IDE to see what type everything is

drowsy plinth
#

okay thank you

trim tangle
#

It doesn't impact the runtime in any way, it's just a type hinting thing

drowsy plinth
#

yea like comments etc..

#

docstrings comments and type hints are cool

trim tangle
#

well, mypy doesn't tell you when your comment is outdated ๐Ÿ™‚

drowsy plinth
#

what does the -> None: mean?

trim tangle
#

it means that the function returns None

drowsy plinth
#

ah its a type hint thing

trim tangle
#

yes

drowsy plinth
#

it's basicaly a method to set or increment

#

yes i understand now

#

how do you inherent a private instance attribute from a class to another tho

blazing nest
#

There's nothing private in Python

#

You can still access it using box._value

drowsy plinth
#

woow

drowsy plinth
grave fjord
blazing nest
#

In reference to modules?

#

When talking about attributes then name mangling is probably the most closest to being private because of the pain necessary to access it.

#

Just not re-exporting and adding a leading _ is scary enough for modules though yeah

grave fjord
#

I mean the mypy feature

dim flume
#

Where else can I find type hints other than typing and abc (Abstract Base Classes)

oblique urchin
dim flume
oblique urchin
#

The runtime typing code is generally permissive in what it allows so that future enhancements to the type system are easier

leaden oak
dim flume
#

Oh, I'm currently on 3.9.7

leaden oak
#

eh, there's typeguard that is only present in typing since 3.10 for one

#

not sure how useful that'd be for you, but typing_extensions does still have recent additions

vivid sphinx
#

Can someone help me Im trying to make the user input choose what multiples they want to know

trim tangle
gray wadi
#

When I try to assign a dict value using
self.relationship_id = inRelationship["relationship_id"]
and self.relationship_id is defined as
relationship_id: str
I get an incompatable error Incompatible types in assignment (expression has type "Union[str, Optional[List[PropertyModel]]]", variable has type "str")
My dict has either key value pairs with both values being of type str, or an optional key, value pair that could be a list.

#

I'm using mypy in vs code

#

I understood Union to be for when there could be two options, and my Union has str as a type.

#

What am I missing

gray wadi
#

I ended up having to put an if isinstance statement to check it was str for it to work

dim flume
#

I wonder what generics in Python are used for

#

Also confused what are overloads in Python

acoustic thicket
#

in case y was other, x's type would become incorrect

gray wadi
#

I get you

#

x could be none

grave fjord
#

functors?

blazing nest
trim tangle
#

!pep 649

rough sluiceBOT
#
**PEP 649 - Deferred Evaluation Of Annotations Using Descriptors**
Status

Draft

Created

11-Jan-2021

Type

Standards Track

soft matrix
#

what would be the best way to implement deferred evaluation of subscriptions to types in mypy?

#

cause i was using api.type to get the current type thats being analysed but when subscripting a generic the subscription is understandably called before the type that i want info (the full name) about is created

gray wadi
#

Is it possible to specify the keys in a dict like in Typescript e.g.
Interface DataInterface { myData: str; }

oblique urchin
fierce ridge
#

is there some way to write a typevar such that it resolves to a union?

a : List[T]
b : List[T]

in this example, i expect that a and b might be heterogenous (and could contain anything), but i want a and b to contain the same mix of things

#

actual use case:

@contextmanager
def multicontext(
    *unnamed_contexts: ContextManager[_T], **named_contexts: ContextManager[_T]
) -> Generator[Dict[str | int, _T], None, None]:
    """Enter multiple contexts in a single `with` statement."""
    contexts: Dict[str | int, ContextManager[_T]] = {
        # Unnamed contexts are numbered sequentially: `{0: ctx1, 1: ctx2, ...}`
        **dict(enumerate(unnamed_contexts)),
        # Named contexts are used as-is
        **named_contexts,
    }
    with ExitStack() as stack:
        yield {
            label: stack.enter_context(context) for label, context in contexts.items()
        }
#

i want the _T to be "whatever the user provided", even if that's several different types

spare mauve
#

any idea what could be happening here?

#

something with pydantic? it is running on python 3.8

#

maybe the bad line is actually in the ??? which is not very helpful....

oblique urchin
spare mauve
#

does this not work on 3.8?

#

I guess with Dict it might?

oblique urchin
#

yes, you need Dict or 3.9

#

PEP 585 added support for dict[str, str] but that's only in 3.9

spare mauve
#

thanks, that helps a lot ๐Ÿฅณ

#

maybe it's easier to just stop supporting 3.8

grave fjord
#

You can use from __future__ import annotations or "dict[str, str]"

blazing nest
fierce ridge
blazing nest
#

Wait so you want Union[int, str] and Union[str, int, float] to be correct?

brisk hedge
#

Maybe with a TypeVarTuple, I'm pretty sure you can stick those into Union (if your type checker supports a drafted feature)

#

Union[Unpack[Ts]] in theory

#

Union[*Ts] if optimistic for the future

fierce ridge
brisk hedge
#

Now, keep in mind that you can't really tell whether the user intended the type to be T | U or to be V (common parent of T & U)

fierce ridge
#

in this case I can't assume that the types in the union have a common parent, other than objectof course

brisk hedge
#

Can the amount of union objects be pretty much unlimited?

#

(I say just use object)

fierce ridge
#

ideally I would like to be able to statically map keyword arguments to keys in the result, if they are known statically, but that seems like too much to ask for

blazing nest
fierce ridge
#

Oh that's valid?

#

I never even thought to try that

brisk hedge
fierce ridge
#

(i know that none of this is currently supported)

oblique urchin
oblique urchin
#

huh mypy does accept it

blazing nest
#

This is a union of boxes:

#

Which creates this new box

#

No?

oblique urchin
blazing nest
#

Huh? Wouldn't it become Union[Any, ...] (even though that's not accepted syntax)

#

Ah, you have to be explicit with your Union[Any] typing

oblique urchin
blazing nest
oblique urchin
#

Union[Any] is just Any; it lets you pass a non-union type if you use that as a bound

blazing nest
#

Hmm, you right

#

Also I realize now that when I changed some stuff and ran it that didn't change the gist so I just pasted the same gist 2 times

oblique urchin
wide radish
#

how can i make type a type hinting like that

class EstimatedDiameterDetails(TypedDict):
    estimated_diameter_max: float
    estimated_diameter_min: float

class EstimatedDiameter(TypedDict):
    kilometers: EstimatedDiameterDetails
    meters: EstimatedDiameterDetails
    miles: EstimatedDiameterDetails
    feet: EstimatedDiameterDetails

class Asteroid(TypedDict):
    links: Dict[str, str]
    id: str
    neo_reference_id: str
    name: str
    nasa_jpl_url: str
    absolute_magnitude_h: float
    estimated_diameter: EstimatedDiameter
    is_potentially_hazardous_asteroid: bool

a: Asteroid
a["estimated_diameter"]["make something that makes autocomplete match 'kilometers', 'meters', etc"]
oblique urchin
#

If i recall correctly pyright (vscode's default for python) recently made an improvement for TypedDict key autocompletion

trim tangle
#

yep, pyright does that

wide radish
#

yeah, pyright did this for me

#

autocomplete is working now, at least when you try to create a dict

#

to access too, probably

#

ty

trim tangle
#

pyright has most of its stuff stolen from TypeScript, as the author says

#

so yeah

wide radish
#

in a class that inherits TypedDict, how can i say that a key can exist or not? like, supposing something like this:

class Book(TypedDict):
    next_page: int # next page may dont exist, considering you're in the last page
    previous_page: int # same thing for previous page
#

how can i say that these keys may not exist?

oblique urchin
brisk hedge
#

class Book(TypedDict, total=False)

#

Keep in mind this will make all of the keys optional

oblique urchin
#

Oh right, you can actually do that for the whole TypedDict

#

And with inheritance you can make some keys required and others not required

wide radish
brisk hedge
#

So if you need a mix of optional & required keys, you have to make a total=False class and subclass it with a normal TypedDict

#

It's kind of a gross code pattern but whatever

soft matrix
#

im pretty sure pyright already has support for 655

oblique urchin
soft matrix
#

yeah

#

it can even be imported (not at run time from typing exts)

oblique urchin
#

Oh interesting, I guess they put it in their private copy of typeshed

soft matrix
#

must have

rough sluiceBOT
#

packages/pyright-internal/typeshed-fallback/stdlib/typing_extensions.pyi line 125

Required: _SpecialForm = ...```
brisk hedge
#

I mean I usually import from typing_extensions in a TYPE_CHECKING block regardless

tawny flame
#

So I'm adding type hinting to a function where an argument expects a list that contains at least one element, and the elements in it can only be specific values like so:

def foo(args = ["one", "two"]):
    # do things with args

How would I go about type hinting this list of literals where not all elements need to be present?

oblique urchin
#

And invariance may make such a type a pain to use

tawny flame
#

Wouldn't that expect a list with explicitly those two elements, rather than one or the other or both?
And I'm willing to just have that length check in inside the function itself

#

Would it be something dumb like List[Optional[Literal["one"]], Optional[Literal["two"]]]

trim tangle
#

I don't quite get it

#

List[Literal["one", "two"]] would allow [], ["one"], ["two"], ["two", "two", "one", "two"], ["one", "one"] etc.

tawny flame
#

Let me expand the available values for the args argument

def foo(args: list = ["one", "two", "three"]):
    if len(args) == 0:
        raise IndexError("List has no elements")
    if "one" in args:
        # do specific action
    if "two" in args:
        # different action
tawny flame
#

Just wanting to make sure that only specific elements can exist in this list

trim tangle
#

@tawny flame you could accept a set

tawny flame
#

That could also work
So args: set[Literal["one", "two"]] would do it?

trim tangle
#

yep

#

or use enum.IntFlag ```py
class Args(IntFlag):
ONE = 1
TWO = 2
THREE = 4

#

you'll be able to do Args.ONE | Args.THREE and such

#

so illegal arguments will never pass type checking

#

(which is sort of the holy grail of static typing)

rustic gull
#

may I ask why pyright is a bit wonky here?

soft matrix
#

It's probably not re exported

#

You'll need to change the import of cvtColor to an import as

rustic gull
#

ah

soft matrix
#

Or you need a py.typed

rustic gull
#

ic

#

how come

#

import cv2 as cv2 fixes the issues

soft matrix
#

Oh I meant in cv2/init.py

rustic gull
#

moment

#

i kinda don't wanna edit the lib ๐Ÿฅด

soft matrix
#

And you need py.types files so type checkers know your code is typed

rustic gull
#

okie

#

i have a py.typed

#

so

trim tangle
#

new Pyright update improves type narrowing with generics ```py
from typing import Sequence, Union, List

def f(x: Union[List[int], Sequence[str]]):
if isinstance(x, list):
reveal_type(x)
else:
reveal_type(x)

pyright gives the types `list[int] | list[str]` and `Sequence[str]`
whereas mypy gives the types `list[int] | list[Any]` and `Sequence[str]`
chrome hinge
#

ah, 7 hours ago, presumably the 1.1.181 release. Time to update, nice.

trim tangle
#

yeah, release

#

if pyright ever gets some sort of plugin system, it's probably going to be a better choice for production than mypy

agile cliff
#
import math

#****************************AR*EA*****************************#
b = input("Base Here: ")
h = input("Altezza Here: ")
#****************************AR*EA*****************************#
#**************************PERI*M*ETRO************************#
h2 = math.pow(h)
b2 = math.pow(b)

t = b2 + h2
t2 = math.sqrt(t)
t3 = b * h
#**************************PERI*M*ETRO************************#
#****************************TOT*ALE**************************#
print(str("Area: "+ t3))
print(str("Perimetro: "+ t2))
#****************************TOT*ALE**************************#
#

whats wrong with this code "/

#

:/

#

it has errors i tried to fix

trim tangle
#

@agile cliff Is this somehow related to type hinting?

azure niche
#

How do I do type hinting

#

do I just install the package

trim tangle
#

@azure niche You don't need any special package for type-hinting. But if you want static analysis, you'll need a tool like mypy or pyright.

#

Alternatively, you can install the tool into your editor. What editor are you using?

azure niche
#

vsc

#

Although Im trying to type hint here, but it seems to error

#

Snake is a class defined below

#

I love how you have a SQL db icon as your head

trim tangle
#

@azure niche It will fail at runtime. You need to do snake: "Snake" if you want a forward reference

#

btw, did you set "Pylance > type checking" to basic in the settings?

azure niche
#

nope

trim tangle
#

you should, otherwise it doesn't report most type errors

azure niche
#

ok

#

thanks

twin arrow
#

Would var: list[int] mean that it is a list that is filled with ints

rustic gull
#

Yes

twin arrow
#

guessed it :0

trim tangle
#

[1, 2, 3] is ok, [] is ok, [True] is ok

twin arrow
#

cool

#

but then something like ["a", 1, 2, 3] wont be ok

trim tangle
#

yes

rustic gull
#

well i need ti make this to itn

#

its a loop that makes string as output

#

and i need number of that output

trim tangle
rustic gull
#

like this is a simple question, i dont want to bother the help channels

trim tangle
#

The topical channels each have their own topic. For example, this channel is about type hinting - discussions about type hints go here. But not questions about networking or graphics.

rustic gull
#

i know that dont worry

leaden oak
#

Converting between the basic types is usually out of type-hinting's realm as it focuses specifically on type annotations and the ecosystem around it (unless you're talking about how to convert types in a type-safe manner)

spare mauve
#

like def func(x: "List[MyType]"=8): didn't work iirc

#

I believe I had to use

def func(x: typing.ForwardRef("List[MyType]")=6):
solid light
#

Maybe List["MyType"]?

spare mauve
solid light
#

Yeah

#

You only put the forward reference bit in quotes ig

#

No need to put List in quotes since that's in the scope

#

Also 3.9 you can do list[x] instead of typing.List[x] so if you're 3.9+ I'd change that

spare mauve
#

ah, I wish I knew what I had been doing to get some error

#

that works tho, ty

oblique urchin
little hare
#

!d typing.get_type_hints

rough sluiceBOT
#

typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)```
Return a dictionary containing type hints for a function, method, module or class object.

This is often the same as `obj.__annotations__`. In addition, forward references encoded as string literals are handled by evaluating them in `globals` and `locals` namespaces. If necessary, `Optional[t]` is added for function and method annotations if a default value equal to `None` is set. For a class `C`, return a dictionary constructed by merging all the `__annotations__` along `C.__mro__` in reverse order.

The function recursively replaces all `Annotated[T, ...]` with `T`, unless `include_extras` is set to `True` (see [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated "typing.Annotated") for more information). For example:
little hare
#

ahhhhhhh i need to use globals and locals

#

OH.

#

Note
get_type_hints() does not work with imported type aliases that include forward references. Enabling postponed evaluation of annotations (PEP 563) may remove the need for most forward references.

blazing nest
little hare
grave fjord
#

it makes them ForwardRef objects though right?

pastel egret
#

No, just strings.

undone carbon
#

r there any modules which could help to perform type checking within code??

#

like

#

smth like tiz

#
def func(arg: int): if type(arg) != int: raise NotImplementedError()
#

but it's goin to take a lot of effort

#

r there any modules?

pastel egret
#

There's beartype and pydantic which both provide decorators for automatically doing that to functions.

undone carbon
#

wow

#

k

#

thx

undone carbon
pastel egret
#

Not yet, since the @overload decorator right now causes all the overloads to be discarded. But there's a solution planned.

undone carbon
#

i wonder how u always hv the names of the modules needed for a certain purpose n all the stack n github links lmao ๐Ÿ˜

#

thx a lot

undone carbon
#

umm...

#

@pastel egret can ya summarise the whole thing

#

it's a bit way too long...

pastel egret
#

Add a replacement @beartype.overload decorator you use instead, which does store off the overloads for use, and is still treated correctly by static type checkers.

undone carbon
undone carbon
pastel egret
#

It's not implemented yet.

undone carbon
#

huh

undone carbon
#

is it like tat??

#

ps i m still not quite familar with overload

pastel egret
#

Yeah.

undone carbon
#

oh

#

ok

#

thx

soft matrix
#

this doesnt look like a case for overloads

#

you should probably be using a type var with constraints

undone carbon
# pastel egret Yeah.
Traceback (most recent call last):
  File "c:/Users/babario/OneDrive/Desktop/Projects/test.py", line 4, in <module>
    @beartype.overload
AttributeError: 'function' object has no attribute 'overload'
undone carbon
#

it's for beartype

pastel egret
#

As I said it's not implemented yet so it wouldn't work...

undone carbon
#

oh

#

sad

#

tat's real sadddddddd

#

bruhh

soft matrix
#
T = TypeVar("T", int, str)
@beartype
def func(arg: T) -> T:
   # actual impl
#

this should work for now

undone carbon
#

oh

#

k

#

thx

undone carbon
#

oh

#

i see

#

ya right

#

k

#

understood alr

#

could i possibly change the error msg in beartype tho?

#

@pastel egret

#

@soft matrix

soft matrix
#

the error when you fail to pass a type check?

undone carbon
#

@soft matrix

soft matrix
#

idk how youd do it apart from add another decorator to catch the error as the function is called

#

ive never actually worked with beartype

undone carbon
#

oh

soft matrix
#

have you never written a decorator?

undone carbon
#

umm

#

i just heard bout it

#

not really

#

familar with it

soft matrix
#

!tag decorators

rough sluiceBOT
#

Decorators

A decorator is a function that modifies another function.

Consider the following example of a timer decorator:

>>> import time
>>> def timer(f):
...     def inner(*args, **kwargs):
...         start = time.time()
...         result = f(*args, **kwargs)
...         print('Time elapsed:', time.time() - start)
...         return result
...     return inner
...
>>> @timer
... def slow(delay=1):
...     time.sleep(delay)
...     return 'Finished!'
...
>>> print(slow())
Time elapsed: 1.0011568069458008
Finished!
>>> print(slow(3))
Time elapsed: 3.000307321548462
Finished!

More information:
โ€ข Corey Schafer's video on decorators
โ€ข Real python article

undone carbon
#

wait just a min

#

ya k

#

understood

#

at least the basics

#

@soft matrix

pastel egret
undone carbon
#

ok...

soft matrix
#

i think they want to make the error clearer

undone carbon
#

ya

soft matrix
#

but idk what the error actually looks like

undone carbon
#

huh

#

tiz is the original error

beartype.roar.BeartypeCallHintPepParamException: @beartyped func() parameter arg="1.0" violates type hint ~A, as "1.0" not int or str.```
soft matrix
#

oh i dont think theres an issue there

#

that makes sense to me

undone carbon
#

haha

#

k

soft matrix
#

im assuming you passed a float there not a str

undone carbon
#

ya

solid light
#

If you really want to change it I guess except beartype.roar.BeartypeCallHintPepParamException: then raise your own error @undone carbon

undone carbon
#

oh

#

right

solid light
#

But yeah, I'd say that error is fine myself

undone carbon
#

thx

solid light
#

๐Ÿ‘

spare mauve
#

its really annoting because it's a long warning that takes about half a page of output

#

can't be avoided afaik and it always showsit

#

it's just complaining if you use List instead of list ๐Ÿ˜’

soft matrix
#

most things now complain about that

spare mauve
#

seems unhelpful :p

pastel egret
spare mauve
#

that's correct

#

that's why it's annoying the name of the warning changed

#

from Deprecation to Deprecated or vise-versa

#

but its not a showstopper of course

wraith linden
#

Hello. I'm a bit stuck on something and wondering if someone could help me out.

I'm writing an event bus system, and more specifically the function used to subscribe to receive notifications of certain events. I have a base event type: py class Event(ABC): ... And the subscribe function will look something like this: py def subscribe( event_type: ..., callback: Callable[[...], None] ) -> None: ... I'm just not sure what to put in place of the two ...s to make this function generic. The event_type should be a type, specifically a subtype of Event. The callback should accept an object of this type (or a subtype) as its first and only argument.

oblique urchin
#

and then def subscribe(event_type: Type[Event], callback: Callable[[Event], None]) -> None: ...

trim tangle
wraith linden
oblique urchin
trim tangle
trim tangle
#

do you know if I can somehow pull this?

oblique urchin
#

Normally they're pretty quick at updating though, kind of surprised this change isn't in yet

trim tangle
#

I assume it was sunday yesterday ๐Ÿ™‚

oblique urchin
#

Sounds like it should be in pyright 1.1.181

trim tangle
#

oh, I'm using pylance

#

maybe it lags

#

yeah, I'm a dummy

#

pyright 1.181 doesn't show any errors

undone carbon
#

i just realized beartype doesn't support custom classes ๐Ÿ˜ฉ

pastel egret
#

In what way?

undone carbon
#

oh

#

like tiz

undone carbon
# pastel egret In what way?

beartype.roar.BeartypeDecorWrappeeException: <class '__main__.Label'> unsupported, as classes currently unsupported by @beartype.

pastel egret
#

Ahh. You can't yet directly decorate classes, but you can decorate the methods I think.

undone carbon
#

oh

#

i see

#

sad

undone carbon
pastel egret
#

It's new yes.

undone carbon
#

oh

#

tat explains

undone carbon
#

any thing in typing module tat says like Something[int, str] means int or str or None?

pastel egret
#

You want typing.Union, or in 3.9+ int | str | None.

undone carbon
#

oh

#

okay

#

thx

acoustic thicket
undone carbon
#

ya

#

it's too

acoustic thicket
#

with the future import it works in 3.9 too, ig

undone carbon
#

i m using 3.8 ๐Ÿ˜†

undone carbon
pastel egret
#

Use Union[int, str, None].

undone carbon
#

ya

#

ok

#

thx

crimson raft
#

is this general discussion or am i allowed to ask for help with some mypy errors i'm stuck with

crimson raft
#

i can't for the life of me figure out why mypy suddenly doesn't like me importing this:

from types import UnionType```
tells me `Module "types" has no attribute "UnionType"; maybe "FunctionType"?`
it was introduced in 3.10, i've ensured i'm using 3.10, even added `--python-version=3.10` in the mypy linting arguments in vscode
as well as type hinting with `OptionalStr = str | None` (tells me `OptionalStr is not a valid type` when i type hint one of my function params with it)
#

i've literally had no problem with these two for the past few days, but tonight i have no idea what i did for mypy to start throwing me these errors

undone carbon
#

i m not exactly sure

#

but try

#
from types import Union```
#

@crimson raft

crimson raft
#

i can import union just fine, i need UnionType

#

later in my code i check function annotations programmatically and i need to match UnionTypes to go through each type inside of it

#

since str | None for example produces a UnionType

#

(taking annotations from func.__annotations__)

undone carbon
#

i m pretty sure it's Union not UnionType but tiz guy can help @pastel egret ig

crimson raft
#
def foo(x: str | int):
    pass


print(type(foo.__annotations__["x"])) # <class 'types.UnionType'>
undone carbon
#

@crimson raft does tiz help?

crimson raft
#

no, the issue isn't the functionality part of my code

#

it's mypy throwing an error saying UnionType doesn't exist when i'm using 3.10 and types.UnionType exists

#

there's also this, which mypy tells me OptionalString is not a valid type
def help(self, cmd_name: OptionalString = None) -> None:
OptionalString = str | None

undone carbon
#

i guess u could use a help channel, discussion channels normally take longer for some1 2 ans

crimson raft
#

yeah i did earlier and got not response lel

#

i'm fine waiting here if more people who know about type checking look in here rather than help channels

undone carbon
#

just ask gain n try rephrasing your question

crimson raft
#

i could workaround and go back to typing.Union for both of my errors and check the underlying type of that but it's not really what i'd like to do

#

since i had this working perfectly fine for 2-3 days until tonight for some odd reason

#

changed nothing about the typing, mypy just started complaining although i'm definitely using 3.10 & mypy is installed under 3.10

pastel egret
#

Sounds like it could be a mypy or typeshed bug.

undone carbon
#

lol u r finally here

pastel egret
rough sluiceBOT
#

stdlib/types.pyi line 395

class UnionType:```
undone carbon
#

@crimson raft

crimson raft
#

well i don't know what to do with that information lol

#

sure it's defined, and it was defined for the past 2 days for me monkaHmm

pastel egret
#

Either the copy of typeshed bundled in mypy is missing it, perhaps mypy is failing to handle sys.version_info >= (3, 10), or there's something else. Did you update mypy or something?

crimson raft
#

i did not

#

but i've reinstalled it in case it was some bug

#

is there any way i can debug the sys version for mypy?

#
OptionalString = str | None

def foo(x: OptionalString = None) -> None:
    pass```
cause this is an example of my other issue
#

this should be a valid type alias in 3.10

#

but it gives me:

#

uh, i guess installing the latest git version of mypy seemed to solve it?

#

awkward.

undone carbon
#

just ping him

crimson raft
#

no need now, i've solved it

#

๐Ÿ‘

#

thanks for trying though

undone carbon
#

lol

#

i m bad

#

just trying to help

crimson raft
#

ye i appreciate it

#

i'm still confused why it randomly broke...

#

but whatever

undone carbon
#

why does mypy gimme tiz error List or tuple expected as variable arguments? @pastel egret

pastel egret
#

For what line of code?

undone carbon
#

like

#
def foo(layout: Any, widget: Any, coords=Optional[Tuple[int, int]]) -> None:
    layout.addWidget(widget, *coords)
#

smth like tat

#

not really sure how to shorten @pastel egret

#

nvm

#

solved it maself

blazing nest
#

At least how I've done it Infernum

#

Didn't know they added UnionType though, that's interesting

soft matrix
#

I'm pretty sure mypy doesn't support type aliases using the new syntax yet

wicked scarab
#

hey, just wondering, whats the difference between func.__annotations__ and typing.get_type_hints(func)?

brisk hedge
#

!d typing.get_type_hints

rough sluiceBOT
#

typing.get_type_hints(obj, globalns=None, localns=None, include_extras=False)```
Return a dictionary containing type hints for a function, method, module or class object.

This is often the same as `obj.__annotations__`. In addition, forward references encoded as string literals are handled by evaluating them in `globals` and `locals` namespaces. If necessary, `Optional[t]` is added for function and method annotations if a default value equal to `None` is set. For a class `C`, return a dictionary constructed by merging all the `__annotations__` along `C.__mro__` in reverse order.

The function recursively replaces all `Annotated[T, ...]` with `T`, unless `include_extras` is set to `True` (see [`Annotated`](https://docs.python.org/3/library/typing.html#typing.Annotated "typing.Annotated") for more information). For example:
blazing nest
#

This only works correctly on 3.10 afaik

#

It doesn't evaluate on any other version

#

Also personally the Annotated[T, ...] is a deal-breaker for me

soft matrix
#

Just use typing extensions

oblique urchin
oblique urchin
soft matrix
#

the recommended way to get annotations going forward is to use inspect.get_annotations cause it isn't as opinionated as get_type_hints

crimson raft
#
    SQLResult = tuple
    SQLResults = list[SQLResult]

    def execute(
        self, query: str, *args, fetch_all: bool = True
    ) -> SQLResults | SQLResult:
        with self.connection as cursor:
            result: Cursor = cursor.execute(query, args)
            if fetch_all:
                return result.fetchall()
            return result.fetchone()

     def get_rows_by_table_name(self, table_name: str) -> SQLResults:
        return self.execute(f"SELECT * FROM {table_name}") # Incompatible return value type (got "Union[List[Tuple[Any, ...]], Tuple[Any, ...]]", expected "List[Tuple[Any, ...]]")```
am i doing something wrong here? thought i was able to do this
soft matrix
crimson raft
#

ah really it doesn't infer that i'm inherently passing True ?

soft matrix
#

well ok you could use overloads to make this work

#
    @overload
    def execute(
        self, query: str, *args, fetch_all: Literal[True] = ...
    ) -> SQLResults: ...

    @overload
    def execute(
        self, query: str, *args, fetch_all: Literal[False] = ...
    ) -> SQLResult: ...

    def execute(
        self, query: str, *args, fetch_all: bool = True
    ) -> SQLResults | SQLResult:
        with self.connection as cursor:
            result: Cursor = cursor.execute(query, args)
            if fetch_all:
                return result.fetchall()
            return result.fetchone()
#

notice how the return type changes based on the literal value of fetch_all

#

!d typing.overload

rough sluiceBOT
#

@typing.overload```
The `@overload` decorator allows describing functions and methods that support multiple different combinations of argument types. A series of `@overload`-decorated definitions must be followed by exactly one non-`@overload`-decorated definition (for the same function/method). The `@overload`-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-`@overload`-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling a `@overload`-decorated function directly will raise [`NotImplementedError`](https://docs.python.org/3/library/exceptions.html#NotImplementedError "NotImplementedError"). An example of overload that gives a more precise type than can be expressed using a union or a type variable:
crimson raft
#

TIL

#

ty!

hallow flint
rustic gull
#

any way I could write this better? Union[Gallery, List[Gallery], Shelf]

fierce ridge
#

i think Union[Gallery, List[Gallery]] is an anti-pattern in a lot of cases

soft matrix
tranquil turtle
#

how to use variadic tuples?
i have this code:

T = TypeVar('T')

class DataClass(Generic[T]):
    def read(self, buf: Buffer) -> T: pass
    def write(self, buf: Buffer, obj: T) -> None: pass

class Sequence(DataClass[tuple[T, ...]]): # what to write here?
    def __init__(self, *dclss: DataClass[T]) -> None: pass # what to write here: `*dclss: ???`
    def read(self, buf: Buffer) -> tuple[T, ...]: pass
    def write(self, buf: Buffer, obj: tuple[T, ...]) -> None: pass

s = Sequence( # mypy error: Cannot infer type argument 1 of "Sequence"
    DataClass[int](),
    DataClass[str](),
    DataClass[bytes](),
)

# I expects:
s: Sequence[tuple[int, str, bytes]]
s.read(...) # -> tuple[int, str, bytes]
x: tuple[int, str, bytes] = (0, '', b'')
s.write(..., x)

# I got:
reveal_type(s) # Sequence[Any]
reveal_type(s.read(...)) # tuple[Any]


# this is ok:
s2 = Sequence(
    DataClass[int](), # same types
    DataClass[int](),
    DataClass[int](),
)
reveal_type(s2) # Sequence[int]
reveal_type(s2.read(...)) # tuple[int]

I dont know how to use variadic tuples such as (int, str, bytes) so that mypy doesnt go crazy

soft matrix
#

there currently isnt a way to do variadics this should be solved by

#

!pep 646

rough sluiceBOT
#
**PEP 646 - Variadic Generics**
Status

Draft

Python-Version

3.10

Created

16-Sep-2020

Type

Standards Track

tranquil turtle
#

ok, thanks :(

trim tangle
#

@tranquil turtle pyright supports variadics from typing_extensions

#

afaict

tranquil turtle
#

does mypy supports it?

soft matrix
#

no

#

considering this pep hasnt even been expected i think that makes sense

rustic gull
#

bad practice?

#

or common mistake?

fierce ridge
rustic gull
#

what should I use then?

fierce ridge
#

it depends - why do you want to support both cases?

#

most of the time, the List[Foo] version is just a list comprehension over a list of Foos

#

if nothing else, it's probably a better idea to have Sequence[Foo] (from collections.abc), which allows the user to pass in a tuple, ordereddict, numpy array, whatever

rustic gull
#

so I'm better off just typehinting it as a list

fierce ridge
#

why is that?

rustic gull
#

or prolly I misunderstood

fierce ridge
#

it really depends on the specifics of your application

#

but it's rare that your code requires a list specifically

#

often you just need an Iterable

rustic gull
#

aj

#

ah

#

I get it now

fierce ridge
#

if you explain what the function does and why you wanted Foo | list[Foo], maybe i can give more specific advice

rustic gull
#

no no you are completely right

#

thanks

dim flume
#

What's the difference between this and singledispatch from functools

pastel egret
#

singledispatch operates at runtime, overload doesn't actually change how your function behaves - it's used to tell a type checker how it does behave (using if isinstance(...) or something), so it can follow along.

undone carbon
#

as stated over here

#

i will hv to drop <3.9

#

or remove the error:

BeartypeDecorHintPep585DeprecationWarning: PEP 484 type hint typing.Tuple[int, int] deprecated by PEP 585 scheduled for removal in the first Python version released after October 5th, 2025. To resolve this, either drop Python < 3.9 support and globally replace this hint by the equivalent PEP 585 type hint (e.g., "typing.List[int]" by "list[int]")
#

by doin these

#

Hide warnings. The middle-finger way is to just squelch all deprecation warnings with an ignore warning filter targeting the BeartypeDecorHintPep484DeprecationWarning category. On the one hand, this will still fail in 2025 or 2026 with fiery explosions and thus only constitutes a temporary workaround at best. On the other hand, this has the obvious advantage of preserving Python < 3.9 support with minimal to no refactoring costs. The two ways to do this have differing tradeoffs depending on who you want to suffer most โ€“ your developers or your userbase:

# Do it globally for everyone, whether they want you to or not!
# This is the "Make Users Suffer" option.
from beartype.roar import BeartypeDecorHintPep484DeprecationWarning
from warnings import filterwarnings
filterwarnings("ignore", category=BeartypeDecorHintPep484DeprecationWarning)
...

# Do it locally only for you! (Hope you like increasing your
# indentation level in every single codebase module.)
# This is the "Make Yourself Suffer" option.
from beartype.roar import BeartypeDecorHintPep484DeprecationWarning
from warnings import catch_warnings, filterwarnings
with catch_warnings():
    filterwarnings("ignore", category=BeartypeDecorHintPep484DeprecationWarning)
    ...
#

umm

#

can someone explain to me?

#

i honestly dun understand wat is happening

undone carbon
#

oh

#

i think i solved it

#

just use tuple[int, int] instead of Tuple[int, int] ig

mossy leaf
#

How can I check if an object matches a type?

solid light
mossy leaf
#

Like ```py

check_type(typing.List[int], [1])
True
check_type(typing.List[int], ["foo"])
False```

solid light
#

!e py print(isinstance([1], list[int]))

rough sluiceBOT
#

@solid light :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | TypeError: isinstance() argument 2 cannot be a parameterized generic
solid light
#

Hmm, not sure

blazing nest
blazing nest
undone carbon
#

ya

#

the error only occured in 3.9

pastel egret
soft matrix
#

they used to but i dont think they liked the runtime complexity for it

trim tangle
#

Also, you can't really check if an object is List[int]. What if you save it and someone adds a string to it later?

soft matrix
#

copy it :^)

brisk hedge
#

Check if an object is Callable[Ps, T] by simply making a new copy of the universe and applying any side-effects to that universe

blazing nest
#

I have a TypeVar that looks like this: ```python
C = TypeVar('C', bound='Callable[[Event], Coroutine]')

But I need `Callable[[EventSubclass], Coroutine]` to be able to be passed here
#

The issue is that if I make it covariant my decorator that takes this callable and returns it again doesn't work

#

If I make it contravariant then I can't return it

fierce ridge
#

can you make the Event be the typevar?

#
E = TypeVar('E', bound='Event')
C = TypeVar('C', bound=Callable[[E], Coroutine])

idk if this works

#

also what exactly does the decorator return? maybe you want to have it return a concrete type anyway

blazing nest
fierce ridge
#

ah ok, that's what i was wondering

blazing nest
fierce ridge
#

heck

#

i guess use a Protocol

#

or wait that's the same issue

soft matrix
#

i tried that and it didnt work

acoustic thicket
#

is it common to reuse the same TypeVar in unrelated function definitions?

oblique urchin
acoustic thicket
#

๐Ÿ‘

#

i was going to make a separate typevar for each function, heh

acoustic thicket
#

oh god

fierce ridge
trim tangle
#

I don't know other languages that require declaring typevars like that

fierce ridge
#

i agree that TypeVar is not ideal

trim tangle
#

okay, I admit - in this case I'm just lazy ๐Ÿ˜„

oblique urchin
#

But it's pretty easy (one line) to just declare it when you need it. Having lots of obscure names like RX3 in your interface is going to be confusing for users

trim tangle
#

I guess

#

well, the chance that someone will actually use that library is very low

soft matrix
#

def func[T <= SupportsAbs](x: T) -> int: ... when?

oblique urchin
#

when you write a PEP ๐Ÿ˜„

soft matrix
#

i should put this on typing sig

#

good idea

oblique urchin
#

Pradeep had a slide proposing this at the typing summit earlier this year. I think everyone involved in typing will think it's an improvement, but somebody actually needs to push it through.

soft matrix
#

yeah wasnt that with <T> though?

oblique urchin
#

Also, it will require new syntax, so it may be hard sell to the steering councl

oblique urchin
soft matrix
#

i think [] would make more sense

#

i might rewatch the summit tho

oblique urchin
#

it's also easier to extend to selecting an overload at runtime

#

like you could write func[float](2.0) but func<float>(2.0) would be backward incompatible

trim tangle
#

yeah, rn it would mean (func < float) and (float > 2.0)

soft matrix
#

neither are syntax errors though so thats atleast good

trim tangle
#

how do you make the second one work, though?

oblique urchin
#

the angle brackets one? that would require some really weird __lt__ implementation

trim tangle
#

yeah

oblique urchin
#

or a parser hack

trim tangle
#

I'm not sure you can make it threadsafe, generator-safe etc.

soft matrix
#
In [1]: 2<1>2
Out[1]: False```
#

or just turn on barry_as_FLUFL

trim tangle
#

I'm actually not sure how to make typevars on the fly and maintain type annotations being available at runtime...

#

and also not make it ugly

soft matrix
#

literally just got to this part in the summit

oblique urchin
#

def foo(x: list[T := TypeVar("T")]) -> T: would work today ๐Ÿ˜„

#

though I think there was talk of disallowing walrus in type annotations

soft matrix
#
class Base[T]:
    ...

class Child[T, S](Base[T]):
    ...
```this is kinda gross with the subclass
#

anyways ill put this on the long list of peps that will never happen

trim tangle
#

"in Python 3.28 we decided to take the Go path and removed all generics!"

subtle creek
dapper yew
#

Is there a way to typehint type aliases? e.g., we have a lot of stuff like this for some business logic (to help with knowing what values exactly are being passed around where):

# I really want this docstring to show up when someone hovers over the below type alias
SomeBusinessLogicType = float