#type-hinting
1 messages · Page 50 of 1
hmm
i think mypy flags some similar cases without generica
oh, you're right ```py
from typing import overload
@overload
def foo(x: str) -> str: ...
@overload
def foo(x: object) -> int: ...
> Overload 1 for "foo" overlaps overload 2 and returns an incompatible type (pyright)
so the bug is that this definition is even allowed to exist. I think that makes sense
Sometimes it makes sense though, e.g.: ```py
@overload
def foo(x: str) -> list[str]: ...
@overload
def foo(x: object) -> list[object]: ...
Hey yall, I'm not sure I understand the use case for the new sentinel built-in? Is it a cleaner way of doing things instead of | None for example?
You'd use it in cases where you need some special value but can't use None (for example, because None is itself a valid value)
There are a number of use cases in the standard library, e.g. functools.Placeholder, typing.NoDefault, dataclasses.KW_ONLY
Could someone help me type the following?
from abc import ABC, abstractmethod
from typing import Literal
XGRID_AXES = Literal["X", "Y", "Z"]
UXGRID_AXES = Literal["FACE", "DEPTH"]
class BaseGrid(ABC):
@property
@abstractmethod
def axes(self) -> list[str]:
...
@abstractmethod
def get_axis_dim(self, axis: str) -> int:
...
class XGrid(BaseGrid):
@property
def axes(self) -> list[XGRID_AXES]:
...
def get_axis_dim(self, axis: XGRID_AXES) -> int:
...
class UxGrid(BaseGrid):
@property
def axes(self) -> list[UXGRID_AXES]:
...
def get_axis_dim(self, axis: UXGRID_AXES) -> int:
...
gives me a bunch of errors like
t.py:20: error: Signature of "axes" incompatible with supertype "BaseGrid" [override]
t.py:20: note: Superclass:
t.py:20: note: list[str]
t.py:20: note: Subclass:
t.py:20: note: list[Literal['X', 'Y', 'Z']]
I like the specific typehints on UxGrid and XGrid since its useful for devs. Is the only way to fix this to remove those typehints and broaden to str?
variance strikes again
list[str] is a stricter requirement than "all elements are str", its also "this list allows arbitrary strings being appended to it". so like, if grid: BaseGrid, i should be able to grid.axes.append("hello")
and because class XGrid(BaseGrid), when grid: XGrid, this should also work, but when you said its -> list[XGRID_AXES], now you're overriding it with saying i cant append hello to it, only X Y Z, so the subclass is incompatible with the base class (thats where the signature incompatible with supertype comes from)
if you dont want axes to be mutable, typehint it as collections.abc.Sequence[str] rather than list[str], Sequence is covariant in its type parameter as its only used in outputs, so since XGRID_AXES is a subtype of str, Sequence[XGRID_AXES] will be a subtype of Sequence[str]
tbh this seems like Grid[Axis: str] with BaseGrid = Grid[str], XGrid = Grid[XGRID_AXES], UxGrid = Grid[UNXGRID_AXES]
not sure why you defined them as separate classes
This is really helpful, thank you!
I significantly trimmed down the example - the original code is here https://github.com/Parcels-code/Parcels/blob/main/src/parcels/_core/basegrid.py
@restive rapids I was thinking about variance tutorials again and maybe it's time to invent an analogy. Like the burrito for monads. I know it doesn't really work for monads. But I have a good feeling for variance. What real world things would be:
- Generic in some other real world thing
- Have different variance?
Does the Python discord have a reading list btw? I would love to learn about type theory. I'm not sure if a Python oriented book is the best way to go given it was kinda bolted onto the language after the fact. Anyone have book recs? A quick reddit search leads me to "Types and Programming Languages" - keen to know what people think
it would essentially need to tie into some consumer vs producer thing, i think
inputs outputs
a generic animal vet can accept a cat and a dog because cat and dog are animals
but a cat vet cant accept a dog
because dog is not cat
a profession dealing with accepting patients is contravariant over the patient type
Does anyone has the hackmd from the typing summit?
How would you type hint an empty list the correct way? On stackoverflow I found list[Never] (from the typing module), but can I use this?
why does the typehint need to represent that its empty?
I have a function that uses list comprehension on a iterable but if the iterable is empty the returning list will be empty too
and why cant you just typehint it as list[T] where T is the normal element type? [] is a valid list[int]
list[Never] is basically useless for the caller, they wont be able to use this list. you cant assign list[Never] to list[T] unless T=Never
(list is invariant)
Is there any reason to declare a Literal as a type expression? (type L = Literal[...] vs L = Literal[...])
type statements are new in 3.12 and they're lazily evaluated. So it might be slightly better for performance (import time) and cannot cause issues due to ordering, e.g.: ```py
DarkColors = Literal[Color.black, Color.deep_blue] # error: Color not defined
class Color(Enum):
...
also just consistency, it's strange to have half of your type aliases be `type` statements, and half as normal assignments.
alright
There's https://github.com/Instagram/MonkeyType, but I never tried it myself
There's also autotype which will do all the simple easy to determine type hints
Write me a code to make call of duty
Write me a code to make call of duty
Fahh
What the fuck?
Average typing experience, trying to code a normal parser combinator, accidentally makes a safe transmute function by combing two ty bugs. This has not been my week for typing.
maybe use a more mature type checker 😉
(which has a different set of bugs, but at least no TODOs)
pyrefly recently released a 1.0 version apparently
all the bugs are "as designed" in other typecheckers
Funny thing about that, I also run BasedPyright, and while writing a different parser combinator found a crash .-.
Does it crash on normal pyright as well?
Sadly no, it was basedpyright exclusive
did you file a github issue?
Yep, already fixed
I recently found a bug that's present in all four type checkers and I'm procrastinating on reporting it. Maybe someone else wants to do it
I haven’t found one on all four yet (unless you include unsupported narrowing), but I have reported 3 that were shared between mypy and ty
4, huh? i suppose that answers the question about any opinions you may have on zuban
Zuban doesn't have an online playground, so I haven't tested on it 🙂
It’s in there
I still have to install something to run it on my computer
(Though I also rarely use it since web is easier)
do i recall as well that you once hosted a pyright playground?
yes
https://github.com/DetachHead/basedpyright/issues/1710 if you’re interested
(I think it costed me a total of $0)
I feel like the common thread here for me is that parsers are hard (the allure is irresistible)
is this supposed to be a jupyter replacement?
no, it doesnt run your code, only typechecks it with various typecheckers
its like, say, https://pyrefly.org/sandbox/ but for all typecheckers at once, so you can easily write something and typecheck it against everything at once, to find bugs/differences between typecheckers
Ah
Woohoo, new channel :)
@acoustic thicket Your channel is born
proceeds to delete all messages so this is first
Best type hinting tool to use?
Hey. Dont take my idea xP
Depends on what you mean by "tool". E.g. for generating typehints or validating them
I use mypy to validate type hints - pretty great
Some Links
Typing Overview: https://typing.readthedocs.io/en/latest/
Typing Module: https://docs.python.org/3/library/typing.html
Mypy: https://mypy.readthedocs.io/en/stable/getting_started.html
Pyright: https://github.com/microsoft/pyright
Pydantic: https://pypi.org/project/pydantic/
PEP 483 -- The Theory of Type Hints: https://www.python.org/dev/peps/pep-0483/
PEP 484 -- Type Hints: https://www.python.org/dev/peps/pep-0484/
PEP 585 -- Type Hinting Generics In Standard Collections: https://www.python.org/dev/peps/pep-0585/
PEP 613 -- Explicit Type Aliases: https://www.python.org/dev/peps/pep-0613/
might be more apt ones out there 
:)
@rustic gull I'll steal your links
noooo i lost first
i like the sound of this
import typing
boom solved this crisis
Intro
Type hints allow you to specify the types you're dealing with:
def add(x: int, y: int) -> str:
return f"{x} + {y} = {x+y}"
If you're totally new, check out these tutorials:
https://realpython.com/python-type-checking
https://decorator-factory.github.io/typing-tips/tutorials/main/0-start-here/
pretty sure you shouldnt install that anymore
yeah i guess its useless
.format() instead of f-strings?
NOTE: in Python 3.5 and later, the typing module lives in the stdlib, and installing this package has NO EFFECT, because stdlib takes higher precedence than the installation directory.
damn man
i use %
It's in the pypi page
but... why?
Also, these mypy settings for a VSCode settings.json is what I use, some might find it handy: ```json
{
"python.linting.enabled": true,
"python.linting.mypyEnabled": true,
"python.linting.mypyArgs": [
"--strict"
]
}
because why not
because f strings exist 
yup
so amazing
what else would it be 🤔
NaN
NaN is part of the IEEE-754 floating point standard.
A not a number is a number 
that's javascript
typeof(NaN) -> number
type hinting 🤔
thinting for short :P
type hinting is literally just
def func(arg1: int, arg2: str, arg3: lemons keyboard) -> None:
pass
thin minting
>>> isinstance(float('nan'), numbers.Number)
True```
Programming is never supposed to make sense
NaN is just a bit of a misnomer
omg its lemon's keyboard
(!+[]+[]+![]) in javascript is "truefalse"
it's more like "numeric error"
hi
whats that
even though this channel is brand new, please keep the discussion on topic -- about type hinting
also what's mypy
yessir
so
def main() -> None: ...
def main() -> typing.Union[None]: ...
which one is better
Check the pinned messages
mypy is a static type checker for python
-> None is preferred
yo what this is sick
typing.Union[None] is None
like typing makes it None
i know
but it's called typing so you gotta love more typing
typing.Optional[typing.Union[None]] this is for people that loves typing
im reading mypy docs and what is a dynamically and dstatically typed function
anyways is typehinting possible in lambdas
yes
you can't type hint lambda arguments, no
If you're totally new to this, I'd suggest reading the articles in the first pin
ah ok
foo: Callable[[int, str], float] = lambda x, y: 1.0
ooo nice
oh so its assigning x and y to be int and str and 1.0 to be float
i guess #internals-and-peps was getting too filled with type theory discussions
interesting
enforcing function and data structures contracts for one
It documents your code, it gives better autocompletion in editors, and it allows you to find some bugs before you run the code
ahh ok
type hints on their own don't do absolutely anything at runtime
they dont slow ur code down?
barely
they don't do anything at all
unless the module is inspecting your functions and definitions and automatically converting them
they dont really if you use future annotations
is it possible to autocomplete type hints? (so formatting it like you can with black formatter)
jelle is working on this i think
...but you can
a) check them statically with mypy or pyright
b) inspect them at runtime, which is what libraries like pydantic and dataclass_factory do
from __future__ import annotations?
yes
I'm a little confused on the black mention 
how does that get rid of the runtime cost?
yk how black formatter can format your code for u
that but type hints
:P i think u should know u do stuff with black dont u
it makes all the type hints strings at runtime
o ur a maintainer
Black can format type hints, what's the problem?
doesn't that still have a cost?
it's a nanocost
thats why i said dont really
type hinting
hype tinting
yeah, but it's still the same without from __future__ import annotations?
comments also have a cost - files with comments take longer to type - but you don't really notice it
no cause the annotations are strings
if a type is already inferred by your static analysis tool, you probably don't need it to be auto-filled
it can?
thinting and htinting 🤔
Yes, type hints are normal Python code after all
how can u enable it
i don't understaand how that reduces the cost
No special DSL
oohhh
black doesn't autocomplete anything
oh ok
type hints are so op they can make undefined variables
not really
can u automatically have type hints on save is what i mean
cause when you do list[str] or similar you are calling a function and returning a types.GenericAlias
sorry i had a very stupid comparison 🤦
i see
you can declare variables with typehints
Editors will show you the types of things if they know them. Why do you want them to be placed in the code? That would be very noisy.
oh but then what were u talking about that should be placed into code?
Use type hints in function signatures to tell people what functions take and return.
def format_number_sum(x: int, y: int) -> str:
return "{} + {} = {}".format(x, y, x + y)
oh
It's mostly a tool for formal documentation
can you have something automatically do that
You can't automatically infer argument types
you can type hint variables too but you should only if the data type is complicated enough where it's non obvious to either you the human or your static analyser
oh wait i dont make any docs so would that be useless for me
that makes sense now, thanks
dataclasses have entered the chat.
it's possible in some cases, but most of the time no
If you don't write any documentation at all, your code will be unusable after a few months. If you're working with a team - weeks
from __future__ import annotations
@lambda x: x()
class __annotations__:
def __setitem__(self, k, v):
globals()[k] = v()
var: list
how to declare undefined variables
Well sometimes when im making __init__ VSCode makes it def __init__() -> None:
hmm?
monkey type can add type hints based on what a function gets at runtime
That sounds like a snippet not autocompletation
oh it is
I am extremely a beginner so I am sorry if this is super basic but what is type hinting? What would you use it for?
i mean i just make code like games or tictactoe, not stuff that others can use (as of now- i dont think im experienced enough, nor do i have any original ideas)
📌 :P
and go to the first link unlike me i went to mypy and instantly got confused :\
Type hinting acts like machine verified API documentation - when reading the code you can skip a bunch of the "what is this code supposed to do in the first place" stage
It can also help prevent bugs.
now the machine verified bit requires a type checker like mypy or pyright
If you make very small programs - 200-400 lines - it doesn't really matter - just use good function names.
In bigger projects, documentation is essential so that people can easily navigate the code.
README is part of documentation, yes
def println(*args: str, l:bool = True) -> None:
"""
This program will print a line in the stdout (Standard Output Stream) stream and do a flush.
It can be disabled by using the key word argument `l`, if l set to False, it will NOT flush nor start
a new line.
"""
stdout = __import__('sys').stdout
if not type(l) == bool:
raise Exception("read the typehints my guy")
if l:
stdout.write(str(*args))
stdout.write('\n')
stdout.flush()
else:
stdout.write(str(*args))
return
*args should be str
so:
- i cannot have something automatically do the type hints for me
- type hints is mostly a tool for formal documentation
- i dont know anything about type hints
In newer versions of python you can use list
k
why __import__
because i need the code to run slower and each time it's called it'll import it
i would just do a local import, but you really should be using a global import anyways
can you add https://typing.readthedocs.io/en/latest/ to this?
also i thought documentations r like markdown files, not Python files. How can you type hint markdown files :\
type hints are specific to Python code
Documentation is everything besides the code that explains it. Documentation can be standalone (like in a separate markdown/rst file) or embedded (like docstrings, comments and type hints)
you could also argue that function/class/variable/module names also act as micro-documentation
And just for a real life example (pulled from psf/black):
def main(
ctx: click.Context,
code: Optional[str],
line_length: int,
target_version: List[TargetVersion],
check: bool,
diff: bool,
color: bool,
fast: bool,
pyi: bool,
ipynb: bool,
skip_string_normalization: bool,
skip_magic_trailing_comma: bool,
experimental_string_processing: bool,
quiet: bool,
verbose: bool,
required_version: str,
include: Pattern,
exclude: Optional[Pattern],
extend_exclude: Optional[Pattern],
force_exclude: Optional[Pattern],
stdin_filename: Optional[str],
src: Tuple[str, ...],
config: Optional[str],
) -> None:
... I would not want to try and remember what types all of these parameters should be
oh my
now to be fair, the variable names makes it easier on their own, but the types makes it unambiguous
If you have a procedure with ten parameters, you probably missed some.
- Alan Perlis
This is a main function using click so 🤷
I'm just surprised that code is optional in a code formatter.
click is cool btw, want to talk about that in a different channel? Since I'm not sure what the advantage of click is over argparse
it's for the --code option which is different from src aka the files and directories passed
I've never used argparse so no thank you
what would it do?
No? since functions will always return something
do the same as -> None
Actually false
void = None
!d typing.NoReturn
typing.NoReturn```
Special type indicating that a function never returns. For example:
```py
from typing import NoReturn
def stop() -> NoReturn:
raise RuntimeError('no way')
``` New in version 3.5.4.
New in version 3.6.2.
NoReturn is different
thats different
well OK that's for erroring / exiting functions .
If you really want to play the words lawyering game, you could argue that I meant that if a function is returning (not exiting or erroring!) it will return something
Not that a function will always return.
What would a function that only has say, a print function, return?
sure, done
if you really really want to play the words lawyering game, you said "functions will always return something"
Woooo type annotations
hi Stelercus
Hi
@trim tangle hello friend
hello
@rustic gull also https://pypi.org/project/typing-extensions/
although maybe not necessary
wasn't that literally the point of my statement?
anyway let's move on, I shouldn't be derailing a brand new channel 😅
def f():
while True:
pass
i wasn't saying it was true, i was just pointing out something he said
I'm confused but OK
Another cool use of type hinting is transcompilation
I plead the 505
mypyc (which is built on top of mypy) will use the type hints in your code to generate Python C extensions for sometimes massive performance wins
Well strict mypy but yes
yeah
if it doesnt segfault yes
lmao
or crash at runtime with a RuntimeError("hit apparently unreachable block") 😉
i wrote a logging statement like that
if you see this, its time to look for a different program. The core of this one is entirely broken
i deleted it because it was logging into my console too much ;-;
Prepare for wall of text 
Big PSA about uppercase vs lowercase hints for things like List, Tuple, and Dict:
In Python 3.9 and later you can use lowercase list with no imports to type hint things:
def printlist(lst: list[int]):
print(lst)
printlist([1, 2, 3]) # -> [1, 2, 3]
But in Python 3.8 and earlier you'll get errors like TypeError: 'type' object is not subscriptable and need to use uppercase List with from typing import List:
from typing import List
def printlist(lst: List[int]):
print(lst)
However, such usage is deprecated (see https://docs.python.org/3/library/typing.html#typing.List) so it's not ideal.
So alternatively, you can use lowercase list with from __future__ import annotations, but only in Python 3.7 and beyond:
from __future__ import annotations
def printlist(lst: list[int]):
print(lst)
For Python 3.5 and 3.6, use the uppercase List method. (Type hinting was introduced in 3.5.)
A backport library might also be an option: https://pypi.org/project/typing-extensions/
In a pinch you can put quotes around a hint like 'list[int]' but that is usually for forward references (https://www.python.org/dev/peps/pep-0484/#forward-references).
Check out https://pypi.org/project/flake8-pep585/ for a package that helps you avoid deprecated types.
Any of the above methods will work for 3.9 and beyond.
Lots of people still use old versions of Python (see https://w3techs.com/technologies/details/pl-python/3 and https://dev.to/hugovk/python-version-share-over-time-6-1jb8) so choose your type hints carefully if you are making something other people will use!
I put it in there 
when is the Union version of this text wall coming?
| is in 3.10
the Rust or operator
| for dicts is pretty nice
If this has any inaccuracies or anything tell me and I'll fix them 
i think a link to pep 585 might be welcome in this
cause that has a list of all of the things that you can use this on
I put 585 in here, hope that suits
There's probably other peps to add 
cool thanks
yay type hinting 
Type hinting plus static type checker like mypy is awesome
Worth mentioning, you can make an alias for a long type hint in the same way as defining a variable, like PathLike here: ```py
import os
from typing import Union, Any
PathLike = Union[str, bytes, os.PathLike[Any]]
def printfile(path: PathLike):
with open(path) as file:
print(file.read())
!pep 613
Playground/"fiddle" web app for Mypy: https://mypy-play.net. It's very helpful to post a Mypy-Play link when asking questions, so we can see both your code and the Mypy output in one place.
@trim tangle can you pin that? ☝️
message 57,895
Time to talk about professional and extremely complex hinting.
Whoever can find the longest type hint in production code gets a (virtual) cookie
🍪
that won't come to my house
you can use ...
To specify a variable-length tuple of homogeneous type, use literal ellipsis, e.g. Tuple[int, ...]. A plain Tuple is equivalent to Tuple[Any, ...], and in turn to tuple.
https://docs.python.org/3/library/typing.html#typing.Tuple
Oh does that actually work for a single type
I just stopped using tuples when I needed to type hint the code

I wrote one similar to
Congrats! You've apparently found some way to break not only this program, but also the logic of Python itself. So unless I (the developer) made some super silly mistake, pat yourself on the back a couple times and head over to the Python Forums! ;)
Can we pin it
that is pinned
I wanted to recommend one too 
this is my first message in here
ok
Ok guys
I have a dict like this
Config = Dict[str, List[Union[one, two, three]]]
From this i need some relevant key-value pairs that are Union[one, two] and i need to extend them into a list
I guess i can provide a full example
def flatten(sections: Config) -> List[Union[Aliased, Unaliased]]:
all_cols: List[Union[Aliased, Unaliased]] = []
for k, col in sections.items():
if k in [relevant cols]:
all_cols.extend(col)
return all_cols
The problem is that col is List[Union[aliased, unaliased, else]]
Which is more general i guess
Thatn the hint for all_cols
Only manually
@granite plover Did you mean if col in [relevant cols]:?
I'm not sure type checkers understand in checks
I don't think they can narrow it down unless you use Literal though
hmmmmm I'm not sure how the code was supposed to work
Is col guaranteed to be a list[Union[Aliased, Unaliased]], after the if k in [relevant cols] check?
If so, just assert the type.
assert isinstance(col, list[Union[Aliased, Unaliased]])
I think 🤔
relevant columns is a list of strs, im checking if the dict has these sections as keys
Instead of the whole try except
that won't work, but cast will work
Union[] is a very weird construct so that won't work.
Oh right
that won't work because list[...] isn't checkable
I'm not sure I understand your question actually @granite plover
You have a dict, and you want to extract a subset of the key-value pairs, for all of which the value has type list[Union[Aliased, Unaliased]]? And you want to then concatenate these lists together?
But the dict also contains values which are lists that might contain some other type, which you're not interested in?
The dict is for configuration so not all of the values are the same type
Theres three types in the dict, theyre all tuples of different structures
I want a subset
But i keep getting an error from mypy
Im extending a list hinted as List[Union[one, two]] with something that is List[Union[one, two, three]]
And thats giving me incompatibility errors
See from this, all_cols is the subset list i want
but col, the list im extending onto all_cols is a more general type
Oh right. Well obviously you can't add a three to a list of ones and twos. But you're sure that the values you're going to add to all_cols are in fact ones and twos?
Yes
So you need to communicate this to the type checker?
yes basically
not sure how to tell mypy that im only ever getting one and two in this list
@trim tangle Would something like this work? (I'm figuring this out as I go along tbh) ```py
for val in col:
assert isinstance(val, (Aliased, Unaliased))
all_cols.append(col)
Or would typing.cast be appropriate to use here?
yep, that should work
error: Parameterized generics cannot be used with class or instance checks
lemme look up typing.cast
Oh right. So then it looks like you want to do ```py
for val in col:
val = cast(val, Union[Aliased, Unaliased])
all_cols.append(col)
assert isinstance(val, (Aliased, Unaliased)) should work
@granite plover you're trying to do isinstance(something, list[something_else])
or Aliased/Unaliased is a parametrized generic
in that case yeah, you'll have to use cast
man, typing is hard
How about using a TypedDict for the config?
i'll look it up
ultimately this isnt that important right now, but i should sort it out
i moved stuff around to make it easier for mypy to understand what i want
everything checks out now, thanks peeps
why does is doesn't work with built-in types when making it Generic (list, dict, etc)? This works tho for typing module.
import typing
a = typing.List[str]
b = typing.List[str]
print(a is b)
>>> True
c = list[str]
d = list[str]
print(c is d)
>>> False
The typing module is written in Python and does a bunch of checks, as well as caching the objects it produces. But the builtin version is instead written in C and is a bit simpler.
oh, so builtin type when making it Generic is not comparable with is? Means that it is stored in a different memory location?
I have a discord command that has this in
@commands.command()
async def my_command(self, ctx, *, user_input: Optional[str] = None) -> None:
if user_input is None:
return await error(ctx, "No item given.")
if user_input.startswith("e "):
user_input = "extra"+user_input.removeprefix("e ")
But the problem is, mypy complains that "None" has no .startswith(), since it's Optional, what should I do in this situation?
I'm also getting a similar problem
Item "None" of "Optional[str]" has no attribute "lower"
@primal sun I don't get this error:
https://mypy-play.net/?mypy=latest&python=3.10&gist=30b1d73ab6561cbdfe128cf6faf4dfb0
can you show more code perhaps?
@trim tangle I think this should be good?
Another thing I'm not sure about is this:
https://mypy-play.net/?mypy=latest&python=3.10&gist=5c3b08b7e5018d61cad3ed64e09df256
Do I only ever type hint it in the first case it appears, even if it never runs?
why do you want to declare it?
I mean, why do you want to type hint it?
a = "b"
if a == "b":
my_number = 5
else:
my_number = 6
Am I stupid to be type hinting everything?
You shouldn't type hint everything - when you do an assignment, the type checker usually infers the type for you.
Hmmmm
I guess I've been doing things wrong then, oops
So is it wrong to type hint something if it's being assigned to that type?
e.g.
a: int = int("7")
Any ideas on this?
It's not 'wrong', it just clutters the code
it's pretty clear both to programmers and to tools that it's an int
You need to use typing.get_origin() and typing.get_args() and compare
Yes that is extremely unnecessary haha
in where exactly?
!d typing.get_origin
typing.get_origin(tp)```
Provide basic introspection for generic types and special typing forms.
For a typing object of the form `X[Y, Z, ...]` these functions return `X` and `(Y, Z, ...)`. If `X` is a generic alias for a builtin or [`collections`](https://docs.python.org/3.10/library/collections.html#module-collections "collections: Container datatypes") class, it gets normalized to the original class. If `X` is a union or [`Literal`](https://docs.python.org/3.10/library/typing.html#typing.Literal "typing.Literal") contained in another generic type, the order of `(Y, Z, ...)` may be different from the order of the original arguments `[Y, Z, ...]` due to type caching. For unsupported objects return `None` and `()` correspondingly. Examples:
```py
assert get_origin(Dict[str, int]) is dict
assert get_args(Dict[int, str]) == (int, str)
assert get_origin(Union[int, str]) is Union
assert get_args(Union[int, str]) == (int, str)
``` New in version 3.8.
wow
!e ```python
import typing
print(typing.get_origin(typing.Annotated[str, int]))
print(typing.get_args(typing.Annotated[str, int]))
@blazing nest :white_check_mark: Your eval job has completed with return code 0.
001 | <class 'typing.Annotated'>
002 | (<class 'str'>, <class 'int'>)
So from that you get the actual class used, and the arguments in it.
alright
, but whats the reason normal is doesn't work?
Hey new channel
Hmm, where should I use them then?
I kinda assumed you'd take an approach like Java where everything has a type
is there an API to check the compatibility of a type ?
Ah sorry for the delay, is checks memory location. So you're asking is this the same object (not if they're equal)
When it is not given, all functions should have them for all parameters and return types. For classes you want all attributes to be typed as well.
Variables can then be inferred from that. If I have a function that returns an integer and assign this to a variable, then I know the variable is an int.
So just parameters and return types, as well as classes? Seems like not a lot but sounds good
wdym?
it's new, created yesterday
most big changes happen on sundays because that's when we have staff meetings
!e ```py
test1 = [2]
test2 = [2]
test3 = test1
print(test1 == test2)
print(test1 is test2)
print(test1 is test3)```
@rich shell :white_check_mark: Your eval job has completed with return code 0.
001 | True
002 | False
003 | True
I mean like if I have List[...] and want to see if it's compatible with Sequence[...]
i figured out how to parse a file with mypy.parse, from inside python, but the various type checks mypy.subtypes.is_equivalent(left, right) for example) always return True if I pass types from the parsed module
maybe that's just not possible but I was just looking to see if there was any way to get more than a printout of errors (like the mypy command) from it
That sounds incredibly unnecessary
List is a subclass of sequence
So you can just check args
So this is a fun one, never had this warning before, any suggestions on what a fix would be, or what it means in general? ```py
@dataclass
class PingConfig:
ping_string: str = "@here"
wait_duration: int = 5 * 60
ignored_categories: t.Optional[list[int]] = None
...
class PingDelay(commands.Cog):
def init(self):
...
self.config = t.Optional[PingConfig] = None
The t.Optional[PingConfig] typehint gives the pylance error Generic class type cannot be assigned
The only reason i want to do this is because the PingConfig is populated in a coro after init, so I just wanted to highlight that this instance var exists when initialising
@void ibex are you sure you don't want self.config: t.Optional[PingConfig]? i'm confused
Personally I wouldn't assign this as None so you don't have to unwrap it every time you access and use it
how would y'all go about type-hinting a method that returns all objects in a list that match a given type?
def get_objects(self, obj_type) -> list[obj_type]:
output = []
for item in self.some_list:
if isinstance(item, obj_type):
output.append(item)
return output
``` or is that even possible?
I would use TypeVar here, it is basically a unknown type; together with Type ```python
from typing import TypeVar, Type
T = TypeVar("T")
def get_objects(self, obj_type: Type[T]) -> list[T]:
output = []
for item in self.some_list:
if isinstance(item, obj_type):
output.append(item)
return output```
https://docs.python.org/3/library/typing.html#typing.TypeVar
https://docs.python.org/3/library/typing.html#typing.Type
^
just type[T] would also work in 3.9+
I don't currently thing Type[T] works with type checkers, but yeah that is how I would do it
ooh! TypeVar is a new one for me, thanks!
I am pretty sure it does? ```py
from typing import TypeVar, Type
T = TypeVar("T")
def foo(a: Type[T]) -> T: ...
class Bar: ...
reveal_type(foo(Bar))and mypy gives us the result
tmp.py:13: note: Revealed type is 'tmp.Bar*'
They must have fixed it
I remember in the typing summit someone wanted to introduce what is basically this but everyone unanimously agreed that this should already be type-able
interesting
Lemme find it I might be missing something
https://youtu.be/ld9rwCvGdhc at 46:13
Greetings
Type Syntax Simplifications (Maggie Moss) 0:06
Validating JSON with TypedDict, trycast, and TypeForm (David Foster) 29:45
Type Variables for All (Pradeep Kumar Srinivasan) 54:20
Static Python: Types in Bytecode Compilation & Runtime (Carl Meyer) 1:25:16
Incremental Check in Pyre (Jia Chen) 1:50:55
Scaling Typeshed to 1000 Package...
Oh I think that's slightly different
well that is interesting
okay so I did some testing ```python
from typing import *
T = TypeVar("T")
def foo(a: Type[T]) -> T: ...
class Bar: ...
class Baz: ...
def fsfsdfs(x: Type[Union[Bar, Baz]]) -> None:
reveal_type(foo(x))
``` mypy says builtins.object* while pyright says Bar | Baz (which is clearly what it is )
so is this what they were talking about you think? @soft matrix
I guess I wont be using mypy anymore then 🙃
I just don't use a type checker :^)
😮
I am currently in a really annoying situation,
I either use a async lib with no type hinting, or a sync one with.
ofc I wanna go async, but the lack of type hints are really annoying me
pyright can generate stubs
Or you can use monkey type to type hint all the functions you care about
yhe that is a good idea, will look into that
@boreal ingot what libs btw
pymongo (sync) and motor (async)
it does, but it still has its own types
well these stubs are not the most usefull ones I have seen (just generated them) xD
that would be wonderful 😄
I use it basically all over my current project (discord bot)
postgres tho
mongo was just easier to get started with
and I cant really switch now, since another developer on my team (tbh we are 2 people) is already using that db in "our" 2 other parts of this project
Is this a good way to fetch the return value for a function? Or is there a better way?
from typing import Any, Callable, TypeVar
R = TypeVar("R")
def cast_input(
func: Callable[[Any], R],
err_text: str = "Not valid!",
input_text: str = "> "
) -> R:
while True:
try:
return func(input(input_text))
except ValueError:
print(err_text)
I think that is the best way,
also side note, you can use [str] instead of [Any]
Oh yeah its the input.
I just quickly put something in there to test the TypeVar as i havent used that before
Thanks
Makes for a fun way to make any type without having to copy paste:
int_input = partial(cast_input, int, "Not a valid whole number!")
float_input = partial(cast_input, float, "Not a valid real number!")
that is cool idea!
Whats a good way to check types of partially applied functions lol
As the signature that ipython shows is:
int_input(input_text: str = '> ') -> ~R
I guess its not a problem so to say. But it would be nicer if there existed a way to "parse" out the ~R as the function for the return value is applied.
But i think im asking a lot from the functools.partial doing that.
you could make it a nested function, like create_cast_input or something like that
no it should be Any you can pass anything to input
Yeah my editor is not very happy with the casting from R. Saying R@cast_input is not int :P
Because of a object* not being int which i find odd and likely a vital hint to whats wrong
the function is taking the return of input, which is always str
something like ```py
from typing import Any, Callable, TypeVar
R = TypeVar("R")
def cast_input(
func: Callable[[str], R],
err_text: str = "Not valid!",
) -> Callable[[str], R]:
def inner(input_text: str) -> R:
while True:
try:
return func(input(input_text))
except ValueError:
print(err_text)
return inner```
Still the same issue, but now its not "object*" but rather "object"
Is the error when trying to use it the partial functions to add data to a dataclass that has int and float types respectively.
hmmm, what is your code?
Lines that mess it up is 72-74
I can make a simpler example if this one is too hard to read
okay, so yhe partial is not to nice with type hints, what is the error with the nesting funcs approach (sorry my code above is weirdly indented, discord :/ )
Dammit, i had a feeling it would be partial
my guess is that the only type info it can keep when using partial is the return type, which is basically Any because it has no context
you could use some cast, but tbh that feels like a bit to much repetition
I wonder whether you could implement partial using paramspec and (reverse?) concatenate
Yeah. It doesnt seem like partial has any nice way of type support :/
Ended up just making a one line function with the types set rather than trying to use the dynamic one:
def int_input(input_text: str = "> ") -> int:
return cast_input(int, err_text="Not a valid whole number!", input_text=input_text)
!pep 561
what does the py.typed file mean?
Partial isn't typeable currently, pep 612 was maybe gonna fix this but I think they didn't want to bother implementing that
It means that static type checkers should read the project's source for type hints.
Without it static type checker will look for 3rd party stubs
!e
a = "hi"
b = "hi"
print(a is b)
```why does `is` work with strings?
@wicked scarab :white_check_mark: Your eval job has completed with return code 0.
True
and also @blazing nest ^^
because strings, integers and floats are special types
oooh
i dont know how exactly that works but a string with the same value will always have the same id if you compare them
is there any documentation of special types?
!e ```py
test1 = "test"
test2 = "test"
print(f"{id(test1)} {id(test2)}")
@rich shell :white_check_mark: Your eval job has completed with return code 0.
139784128270192 139784128270192
its not really relevant for the most time
== is more than enough for most needs
yeah True, just wondering..
or rather the "secret sauce" if you wanna call it that is that int, float and string types are not mutable
which means that each time you change them you create a new object
unlike a list
hmm, oh. So immutable types makes a new object in different memory location everytime?
@rich shell :white_check_mark: Your eval job has completed with return code 0.
001 | 140098835175728
002 | 140098835175856
mutable types have the same memory space since you only mutate them
!e py test = [] print(id(test)) test = [] print(id(test))
@rich shell :white_check_mark: Your eval job has completed with return code 0.
001 | 139773859148160
002 | 139773859319552
this will also create a new object, though
!e
a = [1,2,3]
print(id(a))
a[0] = 4
print(id(a))
@wicked scarab :white_check_mark: Your eval job has completed with return code 0.
001 | 140433855390080
002 | 140433855390080
okay cool
when wont it create a new object then?
like this one
everytime you do {} or [] which are shorthands for dict() and list() respectively a new object is created
or set
if you do test = [] the test variable will now refer to that object
true
Expanded info:
{} is both for dict or set, its overloaded.
dictionary: {x: y}
set: {x, y}
hmm
creates a new object: set, dict, list
wont creates new object: str, int, float, complex, bool
is this correct?
!e print(type({}))
@little hare :white_check_mark: Your eval job has completed with return code 0.
<class 'dict'>
ok
they will create a new object if it doesnt exit yet
yeah I mean if it exists already
but yes more or less thats how it goes
ah, mutable vs immutable
jup
which means that all 'hi' are actually the same string?
if it wasn't out of scope at a different point ofc
like uh
there are ways to make a custom class behave the same but i really dont know much about that though
!e ```py
a = 'hi'
b = 'hi'
print(a is b)
@little hare :white_check_mark: Your eval job has completed with return code 0.
True
if you compare two strings with the same value they will always be the same object
at least during normal operation
@little hare :white_check_mark: Your eval job has completed with return code 0.
001 | -4016080006415762537
002 | -4016080006415762537
@rich shell :white_check_mark: Your eval job has completed with return code 0.
[<function getregentry at 0x7fc5ebfbd5e0>, <codecs.CodecInfo object for encoding utf-8 at 0x7fc5ebfa9be0>, {'name': 'utf-8', 'encode': <built-in function utf_8_encode>, 'decode': <function decode at 0x7fc5ebfbd550>, 'incrementalencoder': <class 'encodings.utf_8.IncrementalEncoder'>, 'incrementaldecoder': <class 'encodings.utf_8.IncrementalDecoder'>, 'streamwriter': <class 'encodings.utf_8.StreamWriter'>, 'streamreader': <class 'encodings.utf_8.StreamReader'>}, {'utf_8': <codecs.CodecInfo object for encoding utf-8 at 0x7fc5ebfa9be0>}, {'utf_8': <codecs.CodecInfo object for encoding utf-8 at 0x7fc5ebfa9be0>}, ModuleSpec(name='_signal', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), {'name': '_signal', 'loader': <class '_frozen_importlib.BuiltinImporter'>, 'origin': 'built-in', 'loader_state': None, 'submodule_search_locations': None, '_set_fileattr': False, '_cached': None, '_initializing': False}, <module '_signal' (built-in)>, <built-in function default_int_han
... (truncated - too long)
Full output: too long to upload
@rich shell :white_check_mark: Your eval job has completed with return code 0.
3823
new channel?
thats not actually correct
Right. I think if they are both literals it's correct because the strings get interned, but strings created at runtime won't be the same.
hmm ye if they are literals and in compile time, they will be ig
^
If I want to hint that something is a Type of one of two forward references
is it
Type['A | B'] or Type['A'] | Type['B']
I believe mypy treats those as equivalent
Danke
How does subclassing generics behave?
What do I need to do "to satisfy it"? For example my parent class has the type variable T and I want to continue using this.
inherit from Parent[T]
you dont need to reinsert Generic[T] if that was also what you were wondering
theres a lot of that in typeshed which idu
I have to remind Sebastian every so often that it's redundant 🙂
has that always been in pep 484?
Wait now I am confused, so where is the variable?
Parent[T]
So I just give it a new variable ah?
I think so
oh cool
Can Protocol take a generic param like class Foo(Protocol[T]) : def foo(self, t: T): ...
I'm trying this out but it doesn't work. But if I try Generic[T] it works. But aiui I need to use Protocol since I'm defining a protocol not a Generic type
that should work what error are you getting?
are you getting error: Invariant type variable "T" used in protocol where contravariant one is expected?
P = ParamSpec('P')
class Hider(Generic[P]):
hidden: Callable[P, None]
def __init__(self, value: Callable[P, None]) -> None:
self.callback = value
@property
def value(self) -> Callable[P, None]:
return self.hidden
@value.setter
def value(self, function: Callable[P, None]) -> None:
self.hidden = function
O = ParamSpec('O')
class Subclass(Hider[O]):
def is_set(self) -> None:
print('The value is set:', self.value) # Cannot access member "value" for type "Subclass[O@Subclass]"
I have simplified my code to this, could this be a PyRight bug?
MyPy straight up doesn't support ParamSpec yet
That seems like a bug to me
The thing is, this works when I remove the [O] (but it is needed for the real functionality I have)
Report it to pyright, Eric Traut will probably fix it immediately 🙂
Hahaha true
yes!!
TypeVar('T', contravariant=True) ?
yep
ok because the error wrapped i misread it as 'where covariant expected' and tried covariant = True which didnt work
Hello All,
I wanted to share another uni-model approach I have been working on to address the issue of type-hinted db model management, access, migrations, and caching. Much like sqlmodel, there is only a single model to manage( which happens to be pydantic) but with further abstractions to try and make model creation & relationships a bit easier. Happy to hear your thoughts, I hope this makes your lives a little easier 🙂
what is the typehint for any iterable or any generator?
generator?
@upper tapir @rustic gull typing.Iterable and typing.Generator are deprecated now, you can (and eventually will be forced to) use collections.abc.Iterable and collections.abc.Generator
most of the time you can/should just use Iterable for generators, unless you want to support "push"-mode with .send
oh
they changed it when they added support for [] to all classes in 3.9
is it only for these two from typing?
no, a lot of the things in typing were aliases for things in collections.abc, those are all deprecated now
Iterable, Sequence, Mapping, etc.
whatever is _alias, i shud not use?
same with typing.Tuple, typing.List, typing.Dict , you should use tuple, list, and dict now. unless you need to support python 3.8 specifically
ooh
yeah, anything that is an alias for something in collections.abc
i assume they won't actually remove it until 3.8 is EOL which is not for a long time
so is it normal just like this?
from collections.abc import Iterable
def test(inpt: Iterable):
...
i see
Does anybody know a PyRight CI? Like Github Action?
If I remember correctly they're made in JavaScript/TypeScript and so is PyRight, so I would expect there to be one rather simply
yes
Public announcement: ParamSpec from typing_extensions does not work with Generics!
Could you report a bug for that to python/typing?
typing_extensions/README.rst line 70
Certain types have incorrect runtime behavior due to limitations of older```
It is documented there
I really want to see if I can hack it. What would be the downside of having it be a subclass of TypeVar for example 🤔
Because that's the condition it fails to pass
ParamSpec fails the isinstance(x, TypeVar)
Hm I think we considered that, check the PR where we added ParamSpec to typing_extensions
I saw the stuff about that couldn't you just add a metaclass that overwrites instance check?
Yeah, I ran into the error and had to go. Now I got some time over on my phone so I'll definitely read up on that.
For the list stuff and then have it inherit TypeVar
oh yeah, I think the problem was that we had to make it inherit from list for other reasons, and we couldn't double-inherit from TypeVar and list
It was so it was valid as the first arg to Callable wasn't it?
yes
But I don't think you can use a metaclass on X to make isinstance(X, list) true
Oh right yeah
It might be possible with doing something sketchy with __class__ but that seemed too risky
actually didn't we fix much of this in https://github.com/python/typing/pull/817/files ?
It may actually be supported it was some bug on my end? https://github.com/python/typing/pull/817
Yeah LOL
Hahaha
we did end up going with the __class__ hack
🚨 Crisis averted 🚨
ummm
class this(typing.TypeVar, _root=True):
__class__ = list
isinstance(this("t"), typing.TypeVar)
Out[10]: True
isinstance(this("t"), list)
Out[11]: True
```seems to work on 3.9.3
That's what we ended up doing: https://github.com/python/typing/blob/master/typing_extensions/src_py3/typing_extensions.py#L2286
typing_extensions/src_py3/typing_extensions.py line 2286
class ParamSpec(list):```
Wait so it's not an issue
Oh the instance checks weren't passing for me cause I'm on 3.10.0
Wait doesn't it alias on versions where it exists?
Like an ```python
try:
from typing import ParamSpec
except ImportError:
class ParamSpec(list):
...
typing_extensions/src_py3/typing_extensions.py lines 2281 to 2286
if hasattr(typing, 'ParamSpec'):
ParamSpec = typing.ParamSpec
else:
# Inherits from list as a workaround for Callable checks in Python < 3.9.2.
class ParamSpec(list):```
And the sneaky __class__ hack: https://github.com/python/typing/blob/master/typing_extensions/src_py3/typing_extensions.py#L2333-L2334
typing_extensions/src_py3/typing_extensions.py lines 2333 to 2334
# Trick Generic __parameters__.
__class__ = TypeVar```

Finally?
well, the main word is 'considering'
Hah, yeah
after this, fix the lambda syntax to not use that horrible keyword and use \
we had a meeting with folks from all the major type checkers about better callable syntax recently. Everyone is supportive, just needs to have a PEP written for it and the SC needs to accept it
that would be cool
btw, will typing have a type for a function (not just any callable?)
it seems to cause some issues because functions are descriptors
mypy treats Callable attributes weirdly, and pyright apparently doesn't let you make method decorators that produce methods
No plans to address that part yet
What type annotation should one use for *args and **kwargs?
the common type of all args or kwargs that can be passed
e.g. if your function accepts any number of ints, write *args: int
Have you decided to adopt this channel?
I don't know what adopting means
But I saw it got created and figured I could help 🙂
When a domain expert frequents and positively contributes to a channel related to their domain 🙂
or a Union, I suppose?
sure, if all of the args could be of multiple types
there's currently no way to say that a specific kwarg should be of a specific type, but there's talk of using TypedDict for that
oh and ParamSpec already works
the roles should be reversed, the "virgin" side lists all the things you can't do easily with static types and no side effects, and the "chad" side would be a horrible perl one-liner
You can probably encode Perl inside Agda, at type level
if TypedDict was to be used, how would the syntax look?
because **kwargs: SomeTypedDict means that each kwarg is SomeTypedDict
would something like **kwargs: KwargsDescription[SomeTypedDict] be used?
TypeScript hints ...args as an array
e.g. here ts type ExtraArgs = [number, number, number] | [string] const f = (a: Thing, ...args: ExtraArgs) => { ... } f takes either Thing, number, number, number or Thing, string
oh that is really interesting
I guess in python to get that you might be able to use @overload
in Python it would be useful to do this with **kwargs, where e.g. 10 different functions take the same kwargs
there are two options:
- repeat the same arguments over and over
- just specify
**kwargs: Any
both options are bad
now there's ParamSpec, maybe it will solve some cases, but I"m not sure how
or when sub classing where it is much more convenient to take __init__(some_new_thing, *args, **kwargs) instead of listing everything the parent class takes
yeah
so something along the lines of ```py
P = ParamSpec("P", bound=Parent.init)
class Child(Parent):
def init(some_new_thing: int, *args: P.args, **kwargs: P.kwargs) -> None:
super().init(*args, **kwargs)```
depending on how it is decided that bound should work
well, this won't work because of self
Right, but something along these lines would be nice
You would need new syntax
Like keyed arguments for __*item__ calls? 
wat
the PEP to have keyed arguments for __getitem__, __setitem__ __class_getitem__, etc was rejected and I'm still upset about it.
Yes, that's the problem. The ideas are I think to write it as Expand[SomeTypedDict] (where Expand is a new special form from typing) or **kwargs: **SomeTypedDict, which would require new syntax
like x[1, foo='bar']?
https://www.python.org/dev/peps/pep-0646/ proposes this for *args only, I don't think the **kwargs variiant has made it to a PEP yet
Interesting, not sure which I like more, I guess ** makes the most sense
yes. don't rub it in 
i like
i assume the custom syntax would be some special annotation
def f(**kwargs: Kwargs[MyTypedDict])
from typing import Generic, TypeVar
from typing_extensions import ParamSpec
P = ParamSpec('P')
RT = TypeVar('RT')
class Testing(Generic[P, RT]):
"""I don't get why this fails."""
...
TypeError: Parameters to Generic[...] must all be type variables
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_6092/958801032.py in <module>
7
8
----> 9 class Testing(Generic[P, RT]):
10 """I don't get why this fails."""
11 ...
~\AppData\Local\Programs\Python\Python39\lib\typing.py in inner(*args, **kwds)
266 except TypeError:
267 pass # All real errors (not unhashable args) are raised below.
--> 268 return func(*args, **kwds)
269 return inner
270
~\AppData\Local\Programs\Python\Python39\lib\typing.py in __class_getitem__(cls, params)
978 # Generic and Protocol can only be subscripted with unique type variables.
979 if not all(isinstance(p, TypeVar) for p in params):
--> 980 raise TypeError(
981 f"Parameters to {cls.__name__}[...] must all be type variables")
982 if len(set(params)) != len(params):
TypeError: Parameters to Generic[...] must all be type variables
Any idea what might've changed between 3.9.5 and 3.9.6 to affect this?
Because it doesn't fail on @rough sluice's eval, and it is on 3.9.6 when I am on 3.9.5
Aahhh, 3.9.5 is literally the only version this doesn't work on haha. (I use Windows and use the py command to run the same code on 3.6.8 as well as 3.5.4)
are you sure you're running the same version of typing-extensions? there aren't any relevant changes in typing.py between 3.9.5 and 3.9.6
Yeah, I ran pip install -U typing_extensios (for each version)
paramspec seems kinda broken and unsupported right now
It's not unsupported at runtime. If something is broken for you, please report a bug. Mypy doesn't have real support for it yet, though (Pyright does).
noted. is the above a bug? #type-hinting message
Yes, that is expected to work
https://github.com/python/typing/issues/899, thanks for reporting this
How wil I typehint a parameter which will take in any iterable containing integers?
Iterable[int]
thanks
is there some way to tell mypy that a certain class is expected to implement a certain Protocol, and should be type-checked to that effect?
e.g. i want to have mypy enforce that A and B implement HasFoo:
from __future__ import annotations
from typing import Protocol, TypeVar
from _magic_ import implements_protocol
class HasFoo(Protocol):
def foo(self) -> int: ...
@implements_protocol(HasFoo)
class A:
def foo(self) -> int:
return 5
@implements_protocol(HasFoo)
class B:
def quack(self) -> float:
return -3.3
is there no equivalent of @implements() supported by mypy? if not, how would one go about writing a plugin for something like this?
I need help writing a set of Websockets
this channel is about type hinting and static type checking. consider #web-development, #networks, or a help channel, #❓|how-to-get-help
@fierce ridge yes, I was redirected here lol
this is what i have
connected: set((str, Websocket)) = set()
set[str | Websocket]
if you're in python < 3.10, you need from __future__ import annotations to get the | syntax. otherwise you can do from typing import Union and then set[Union[str, Websocket]]
and in python < 3.9 you need to do from typing import Set and Set[Union[str, Websocket]]
I need to use a for loop to predict the auc score for all my column values do let me know how can I do that
I have used list1 as my target value and the others I need column wise but the compiler is throwing an error
list1 = newdata['diagnosis']
for i in range(len(columns)):
auc = roc_auc_score(list1, newdata.columns[i])
print(auc)
ah [] @fierce ridge thanks
I think | won't work before 3.10 at all
well, it will break if you'll try to evaluate the annotation
i thought so too, but it does, only if you use the future import, and only in annotations
yeah exactly
there is no "compiler" as such. i think you were misdirected, this probably belongs in #data-science-and-ml. however please include the actual error when asking questions like this, otherwise nobody can help.
Yup just need help with the for loop since I want to select column by column in my dataset but newdata.columns[i]) this doesnt seem to work
ask in #data-science-and-ml , i will answer there
There's no decorator for it. You can write something like if TYPE_CHECKING: _a: HasFoo = B() and mypy will error if it doesn't match the protocol
Or set[tuple[str, WebSocket]], not sure what the OP meant here
ah, interesting. it'd be nice if i could declare to mypy that "B and all subclasses of B must implement HasFoo
is that doable with a plugin?
Honestly I don't know much about plugins, never written one. Seems likely to be possible though
i'll have to look into it then. i know of some packages that implement plugins, e.g. Returns
!pypi returns
How do I use generics with unions?
Both of these classes are generics that take two arguments: Command = Union[SlashCommand, ContextMenuCommand]
I want to do Command[P, RT]
I can just do Command = Union[SlashCommand[P, RT], ContextMenuCommand[P, RT]] apparently
I did get a very long issue now that I don't even know where to start though: ```
Argument of type "SlashCommand[P@command, RT@command] | MessageCommand | UserCommand" cannot be assigned to parameter "command" of type "Command[Unknown, Unknown]" in function "register_command"
Type "SlashCommand[P@command, RT@command] | MessageCommand | UserCommand" cannot be assigned to type "Command[Unknown, Unknown]"
Type "SlashCommand[P@command, RT@command]" cannot be assigned to type "Command[Unknown, Unknown]"
TypeVar "P@SlashCommand" is invariant
Type "P@command" cannot be assigned to type "P@Command"
"SlashCommand[P@command, RT@command]" is incompatible with "ContextMenuCommand[P@Command, RT@Command]"
The issue comes from this code: ```py
def command(
self,
type: Union[CommandType, Callback[P, RT]] = CommandType.chat_input,
*,
name: str = MISSING,
description: str = MISSING
) -> Union[Command[P, RT], Callable[[Callback[P, RT]], Command[P, RT]]]:
def decorator(func: Callback[P, RT]) -> Command[P, RT]:
if type is CommandType.chat_input:
command = SlashCommand(func, name=name, description=description)
elif type is CommandType.message:
command = MessageCommand(func, name=name)
elif type is CommandType.user:
command = UserCommand(func, name=name)
else:
raise ValueError("Unknown value of 'type':", type)
self.register_command(command) # ERROR HERE
return command
if callable(type):
return decorator(type)
return decorator
P is ParamSpec and RT is a TypeVar
And register_command just looks like this: ```python
def register_command(self, command: Command) -> None:
"""Register a command handler to be called."""
self.commands[command.name] = command
hah, nobody uses them really. except in enum, and it's really awkward there.
pyright error messages are really nasty
Why are basically "stateful" variants invariant with the "unknown" ones?
maybe it's a variance issue?
Can you show more definitions?
@blazing nest Where do you get this error?
It highlights command inside of self.register_command()
Does changing Command to Command[Any, Any] work?
The type of command just before it is Type of "command" is "SlashCommand[P@command, RT@command] | MessageCommand | UserCommand"
I got an idea, I can change Command to be Union[SlashCommand[P, RT], MessageCommand[P, RT], UserCommand[P, RT]]. I guess I was being lazy and using MessageCommand and UserCommand's parent type
Stolen from TypeScript 🙂 ||just like everything else||
I see the issue now I think, when I tried to do above I get "Expected no type arguments" because I had class MessageCommand(ContextMenuCommand): (without the variables)
Aaah, no?
What even is this haha: ```
Argument of type "SlashCommand[P@command, RT@command] | MessageCommand[P@command, RT@command] | UserCommand[P@command, RT@command]" cannot be assigned to parameter "command" of type "Command[Unknown, Unknown]" in function "register_command"
Type "SlashCommand[P@command, RT@command] | MessageCommand[P@command, RT@command] | UserCommand[P@command, RT@command]" cannot be assigned to type "Command[Unknown, Unknown]"
Type "SlashCommand[P@command, RT@command]" cannot be assigned to type "Command[Unknown, Unknown]"
TypeVar "P@SlashCommand" is invariant
Type "P@command" cannot be assigned to type "P@Command"
"SlashCommand[P@command, RT@command]" is incompatible with "MessageCommand[P@Command, RT@Command]"
"SlashCommand[P@command, RT@command]" is incompatible with "UserCommand[P@Command, RT@Command]"
Type "MessageCommand[P@command, RT@command]" cannot be assigned to type "Command[Unknown, Unknown]"
"MessageCommand[P@command, RT@command]" is incompatible with "SlashCommand[P@Command, RT@Command]"
can you perhaps upload this on github so that I can look at the error locally?
does pyright already implement variance of ParamSpecs?
I hope so? 🤞
i thought the variance for that was left for a future pep
I don't know how erictraut keeps up with the amount of new features and bug fixes
Since ParameterSpecification is just a juiced up type variable, it makes sense to try and re-use existing logic for TypeVar as much as possible (especially if later PEPs make use of the bounds and variance arguments that PEP 612 reserves)
Maybe that is the case?
This is from an old issue though: https://github.com/python/mypy/issues/8645
its in the pep i thought
eric's inhuman in the best way
I already had this in-dev branch for moving changes between my laptop and computer. I just pushed my changes I made today: https://github.com/Bluenix2/wumpy/tree/progress
You'll find it under wumpy/interactions/commands/registrar.py
what is the @ in that output @blazing nest @trim tangle ?
its the name of the function/class that type var is used in
it's pyright's syntax for specifying in which context to take the type var from
ah, interesting
Since I can re-use type variables in different classes and they don't mean the same thing
Yeah exactly haha
It's like the same type.. and if you add [P, RT] to the argument then the error is just delayed to the insertion into the dict.
This is super weird too haha: ```
Type "P@command" cannot be assigned to type "P@Command"
I assume the former is referencing the variable?
It's really odd, try removing the [P, RT] inside of the union. But now it fails at runtime
TypeError: typing.Union[wumpy.interactions.commands.slash.SlashCommand, wumpy.interactions.commands.context.MessageCommand, wumpy.interactions.commands.context.UserCommand] is not a generic class
c:\Users\%username%\Projects\wumpy\wumpy\interactions\commands\registrar.py in CommandRegistrar()
110 name: str = MISSING,
111 description: str = MISSING
--> 112 ) -> Union[Command[P, RT], Callable[[Callback[P, RT]], Command[P, RT]]]:
113 """Register and create a new application command through a decorator.
114
you cant subscript a Union
what happens if you expand it to what it would be if you could subscript a union?
You can subscript a Union if any of the members is subscriptable
i couldnt get it to work and afaict all of those should be subscriptable
class G(typing.Generic[typing.T]):
...
class H(typing.Generic[typing.T]):
...
typing.Union[G, H][int]
Traceback (most recent call last):
...
"/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/typing.py", line 292, in inner
def decorator(func):
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/typing.py", line 989, in __getitem__
super().__init__(origin, inst=inst, name=name)
File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/typing.py", line 211, in _check_generic
tvars.extend([t for t in t.__parameters__ if t not in tvars])
TypeError: typing.Union[__main__.G, __main__.H] is not a generic class```
am i missing something
doesnt work with types.UnionType either
(G | H)[int]
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'types.Union' object is not subscriptable
G is equivalent to G[Any]. Try G[T]
What are the other static type checkers out there?
Except from PyRight and Mypy
I can't remember the rest, I want to see what other type checkers think about my issue above.
pytype and pyre are the other big(ish) two
Ah, I'll give those a try
Does anyone know if there are known issues with flake8/mypy and forward referencing? Long story short: I'm passing an Optional['logging.Logger'] argument to my function. The logger gets defined elsewhere, so I use a forward reference, but mypy and flake8 won't leave me alone 
Should be fine but you do need to import logging
Possibly within if TYPE_CHECKING
Was hoping there'd be a prettier solution than TYPE_CHECKING, but alas.
Restructure your code so you don't have circular dependencies 😄

well sometimes circular dependencies (when it comes to typing) are hard to avoid.
an example I can think of is having some object that stores a reference to its "parent".
like a discord bot, where client.py will need to import channel.py to use Channel, and Channel needs to contain a reference to a Client to be able to do stuff like channel.send().
at runtime Client is not needed in channel.py directly, but it is needed for proper type-hinting
Yes, it's hard. You could get around it by defining a Protocol for the interface that Channel needs on Client, then using that as a type. But that doesn't necessarily make your code easier to understand.
exactly, (tbh in this case you could have a seperate api.py that client.py uses at runetime, and channel.py for type-hinting)
it'd be kind of nice if you could do this:
MagicNumber = '6'
MagicNumberString = AliasedLiteral[MagicNumber]
which would be equivalent to
MagicNumber = '6'
MagicNumberString = Literal['6']
When using a Literal for a method argument, is the method call supposed to throw an exception if the given value for that argument is not one of the defined values?
from typing import Literal
def test(arg: Literal["yes", "no", "maybe so"]):
return True
test("check this out")
Because this works, as in I still get the return value of True even though the arg was not in the list of literals
@tawny flame Type hints don't do anything at runtime.
They exists purely for documentation, type checkers (like mypy and pyright), and inspection via the_function.__annotations__
Ah I see
So the better way to force a check at runtime would be to do something like this:
def test(arg: Literal["yes", "no", "maybe so"]):
args_literal = ["yes", "no", "maybe so"]
if arg in args_literal:
return True
raise ValueError('"{}" is not a valid arg value.'.format(arg))
print(test("check this out"))
which correctly has an error in pyright and throws the ValueError exception at runtime
the way type checking works is that you have to "prove" to the compiler that the type is a certain thing
theoretically something like this would be valid:
valid_args = ["yes", "no", "maybe so"]
ValidArg = Literal["yes", "no", "maybe so"]
def _test_impl(arg: ValidArg) -> str:
...
def test_safe(arg: str) -> str:
if arg in valid_args:
return _test_impl(arg)
else:
raise ValueError()
but in practice the type checker isn't smart enough to understand this kind of thing without PEP 647 "type guards" https://www.python.org/dev/peps/pep-0647/
an example that does actually work is this:
def _test_impl(arg: Path):
...
def test_safe(arg: str | Path):
if isinstance(arg, Path):
return _test_impl(arg)
else:
raise ValueError()
because mypy has hard-coded behavior to understand isinstance
oh very interesting, never head of type guards, sounds really useful
yeah it basically lets you avoid having to write a mypy plugin for custom type refining behavior
every day that passes I just cant wait for 3.10 and all the cool new typing stuff
typeguards are available in typing-extensions and are supported by mypy .910 afaik
oh nice!
from typing import Literal, TypeGuard
valid_args = {"yes", "no", "maybe so"}
ValidArg = Literal["yes", "no", "maybe so"]
def is_valid_arg(arg: str) -> TypeGuard[ValidArg]:
return arg in valid_args
def _test_impl(arg: ValidArg) -> str:
...
# Does typecheck
def test_safe_1(arg: str) -> str:
if is_valid_arg(arg):
return _test_impl(arg)
else:
raise ValueError()
# Does not typecheck
def test_safe_2(arg: str) -> str:
if arg in valid_args:
return _test_impl(arg)
else:
raise ValueError()
I dont have any places I have use for them atm, but I am just loving the concept already 😄
statically checking if something is a positive integer for example
ohhh, OHHH oooooooooooooooooooooooooooooooo
now we are talking
On a different note, is there a guide/tutorial explaining the use of Generics & TypeVars? I don't really understand why/when to use something like _T = TypeVar("_T") and then have Generics[_T] somewhere later in code
Tutorials I came across just assume you know what they're saying regarding those topics
tbh I feel like I will go SUPER overboard with this xD
tbh, i think the best tutorial might be spending some time with a statically-typed language that supports generics
if i find one that's python-oriented i'll let you know
the general idea is that a TypeVar is a placeholder in a type signature
I come from a C++ background but we glossed over templates in uni
well i don't know much of anything about C++ so i'm no good there 😆
tldr: if you have def foo(x: T) -> T for some T = TypeVar('T'), it means that T can be any type, as long as both Ts are the same type
If you've ever used list<int> or similar it's basically like that
yeah, list would be a "generic"
so you can write functions like this:
from collections.abc import Callable, Iterable
from typing import TypeVar
A = TypeVar('A')
B = TypeVar('B')
def maplist(f: Callable[[A], B], data: Iterable[A]) -> List[B]:
return [f(elem) for elem in data]
A and B are both "any type", but all appearances of A have to be the same type, and all appearances of B have to be the same type
it's the same idea as regular variables in programming
if you write a program (x + y) / x, it doesn't matter what x and y are, as long as both appearances of x refer to the same thing
you can also control the behavior of type variables with some precision, e.g. setting an "upper bound", restricting them to a specific list of valid types, or controlling their "variance"
on "variance", see
https://blog.daftcode.pl/covariance-contravariance-and-invariance-the-ultimate-python-guide-8fabc0c24278
https://stackoverflow.com/q/61568462/2954547
Which generic would I use to designate something that contains other things, but is not necessarily iterable
Collection?
Collection is still iterable IIRC
Container
What do you mean by "contains"?
Actually collection should work since it inherits from Iterable, Sized, and Container
here is a nice list over what different abstract types implement, https://docs.python.org/3/library/collections.abc.html
I'm gonna play around with an @overload decorator, which means creating a FunctionGroup class
The FunctionGroup will contain functions of course, but its not exactly iterable (not by its core nature — it always could be iterable though)
Sounds like you should just use FunctionGroup as an annotation?
?
are you making a container for functions?
Yeah
Just toying around, but, I'd imagine the first @overload on a function with the name somefunction would return a function group. Every subsequent @overload on a function with that name would be added to that function group
I know I'm slipping hairs—I'll just use Iterable for now
Are you implementing a type checker?
@typing.overload doesn't really work like you describe (it doesn't do anything at runtime)
No, a decorator, to actually implement overloading
Just for kicks, mind you, just to see
if you want a sort of runtime overload you might be able to use functools.singledispatch
It shouldn't be too hard to rig up, assuming pattern matching works the I think it works
Just need to PM *args and **kwargs, and somehow map their patterns to the functions contained in the function group. I'm sure its all crossed our minds at some point
what wud be the typehint for a function returning either a str or raises an exception? i thought of Union[str, NoReturn] or Optional[str] or something else
the first one looks stupid to me btw
but if an exception occurred there wont be any return
Why do you want to specify the exception?
i dont, i was just curious
Java has a thing called "checked exceptions" where you can specify the exceptions thrown, and AFAICT people had a lot of pain with it
i see
Literal[1, 2, 3, 4, 5, 6, 7, 8, 9, ..., 18446744073709551615, ...] :>
returning str | NoReturn is equivalent to returning str because the function can't return a value of type NoReturn
For the most part, NoReturn is only useful to show static analyzers that a function will never return
hmm fine, ty
@bleak wind
fwiw most docstring styles specify a way of mentioning the exceptions that can be raised, such as:
def f():
"""
blah blah
:raises Exception: explain when Exception is raised
"""
...
yeah
Nim has (optional) checked exceptions
It's a great feature because it's opt-in
At least as far as I know from my beginner level usage so far, it will only check exceptions if you annotate a function with the raises pragma
But python doesn't distinguish between raising an exception and looping forever, which really are two different effects
I'd love RunsForever/Diverges and Raises, both of which are subclasses of NoReturn
The problem with raising annotations in python is that damn near everything can raise an exception
And there isn't a good way to prove statically to a type checker that you know an exception will not be raised
I had that problem in Nim as well with fmt strings, where even though I as a human knew statically that it would not raise, the compiler did not
it would also make the type checkers for Python even more complex
Annoying to have the type checker complain "Ahhh this can raise a Value error" when you know that it won't unless something has gone terribly wrong
wont_raise(ValueError, foo)(1, 2)
Are python type checkers significantly more complicated than other type checkers?
How are exceptions like SystemExit or KeyboardInterrupt handled if you were to typehint exceptions?
or I guess any exception as there is a func for raising an exception in a thread in the c api
So for example List from typing is just for type hinting right? It doesnt do anything other than that?
yep
Current Python hinting, though, covers most of the functionality of typing.List I believe
yeah, in 3.9+ it's not needed
Oh then i can safely omit it in my dict to object implementation, thnx
type hints are good though, you should have them
No i mean im using em but my implentation is a bit different its similar to golang's json unmarshal u use structs and structs can have values and values can be other structs
So in python most basic implementation of dict to object would create instances of the same class but my implementation allows different classes being assigned to different values just like go so i have to check if like my value is from the typing module and it has a class as the input and if i have anything to map to that class...
A bit complicated
That's a great question
For that matter if I don't know how Nim handles it
Maybe there is a certain category of "i/o errors" that aren't checked because they can happen literally anywhere by design
fix error mentioned this before, but java has this thing where you put throws Error if your method can throw
Yeah that's what I'm talking about, "checked exceptions"
I would think that mypy could make a concession to practicality and allow certain exceptions to remain unchecked by default, like SystemExit, unless you use a pragma or config option
!e I would think type checkers would only care about subclasses of Exception so would ignore those py print(issubclass(SystemExit, Exception)) print(issubclass(SystemExit, BaseException))
@boreal ingot :white_check_mark: Your eval job has completed with return code 0.
001 | False
002 | True
also imo they should ignore TypeError as in theory it is their job to catch that error before runtime (meaning a function should not raise it if it type checks)
and imo I would trust my users to actually respect my type-hints


