#type-hinting

1 messages Β· Page 55 of 1

undone carbon
#

p.s. if the arg is a list or tuple, i would use it in the map func, which mypy doesnt seem to like

acoustic thicket
#

int | list | tuple seems like a weird combination

#

what does arg represent in your actual code?

undone carbon
#

just an example

undone carbon
acoustic thicket
#

not sure what the convention is, but a TypeGuard could work

def is_iterable(x) -> TypeGuard[Iterable]:
  try:
    iter(x)
    return True
  except TypeError:
    return False

def func(arg: Union[int, list, tuple]):
  if is_iterable(arg):
    ...
  else:
    ...
undone carbon
#

okayy thx

undone carbon
acoustic thicket
#

typing

#

oh also its 3.10+

undone carbon
#

is it?

#

bruh

#

tat's sad

pastel egret
#

You can get it on earlier versions via typing_extensions on PyPI.

undone carbon
#

right

#

it worked! thx a lot

undone carbon
#

nvm, i just needa update it breh

undone carbon
#
from typing import Union

def func(arg: Union[int, float, str, bool]):
    ...

def foo(arg: Union[int, float, str, bool, list, tuple]):
    if type(arg) not in [list, tuple]:  # <- NEED HELP!!!
        func(arg)

how should i avoid tiz error mypy gives me??

Argument 1 to "func" has incompatible type "Union[int, float, str, bool, List[Any], Tuple[Any, ...]]"; expected "Union[int, float, str, bool]"
buoyant swift
#

mypy doesn't understand that check, use isinstance

undone carbon
#

okayy lemme try

undone carbon
buoyant swift
#

!d isinstance

rough sluiceBOT
#

isinstance(object, classinfo)```
Return `True` if the *object* argument is an instance of the *classinfo* argument, or of a (direct, indirect, or [virtual](https://docs.python.org/3/glossary.html#term-abstract-base-class)) subclass thereof. If *object* is not an object of the given type, the function always returns `False`. If *classinfo* is a tuple of type objects (or recursively, other such tuples) or a [Union Type](https://docs.python.org/3/library/stdtypes.html#types-union) of multiple types, return `True` if *object* is an instance of any of the types. If *classinfo* is not a type or tuple of types and such tuples, a [`TypeError`](https://docs.python.org/3/library/exceptions.html#TypeError "TypeError") exception is raised.

Changed in version 3.10: *classinfo* can be a [Union Type](https://docs.python.org/3/library/stdtypes.html#types-union).
buoyant swift
#

I've got school, sorry

undone carbon
#

okay πŸ™ƒ np

trim tangle
#

So mypy is correct here

undone carbon
#

huh?

undone carbon
trim tangle
undone carbon
#

so?

#

@trim tangle

blazing nest
undone carbon
#

i think so wait a min

undone carbon
buoyant swift
#

should be not ...

lapis copper
#

I'm looking forward to research the subject of type hinting, in the purpose of presenting the subject to a class. Eventually the purpose is to bring myself and the class I'll be presenting to a level of which a high level of understanding regarding type hinting in terms of:
- being familiar with the typing module
- being familiar with python's built-in features
- knowing when to use it and how to use it properly
- getting to know many other modules and features according to the subject
- also proper structural coding according to certain PEP rules

I'd love to know if you guys have any recommendations for any sources, ideas, subjects, modules and so on. And how deep should I be going into this subject? Thanks in advance

oblique urchin
lapis copper
#

that's great to know, thanks a lot

#

this source is great, it talks about many things I wanted to discuss and I honestly happened to use many of them

#

didn't try flake8 but did use black

oblique urchin
#

As for how deep to go, that's up to you. If this is meant to be introductory, I think answering the questions in your above message is going to be a great start, but you can go much deeper into particular subjects if you want to.

lapis copper
#

absolutely

#

wait so what exactly is static typing? I mean, is there dynamic typing?

oblique urchin
#

In the context of Python type checking, static typing means you use an external tool that you run on your code and that finds type errors. Dynamic typing means checking for bad types when you actually run your code.

lapis copper
#

right

grave fjord
#

also proper structural coding according to certain PEP rules

Is a bit vague imho

buoyant swift
#

!pep 484

rough sluiceBOT
#
**PEP 484 - Type Hints**
Status

Provisional

Python-Version

3.5

Created

29-Sep-2014

Type

Standards Track

buoyant swift
#

and this

oblique urchin
buoyant swift
#

awwww 🐈

trim tangle
#

that's one big catamorphism

rustic gull
#

Hey hi henlo everyone, would anybody have a couple spare minutes to help me with a specific idea/issue that I encountered, around which I struggle to wrap my head around?
Is there any way to call a function from an annotation on the argument that it annotates?
Let's say I have:

def a_function(str: swapcase):
  return str.swapcase()

I do realise the example is kinda stupid, but I hope it conveys what I'm trying to achieve!

oblique urchin
rustic gull
oblique urchin
#

Ah I see, you'd probably want to write a decorator doing that?

#

It would be hard to make this work with a static type checker though

misty hearth
soft matrix
#

are you looking for a

#

!d typing.Protocol

rough sluiceBOT
#

class typing.Protocol(Generic)```
Base class for protocol classes. Protocol classes are defined like this:

```py
class Proto(Protocol):
    def meth(self) -> int:
        ...
```  Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing), for example...
brisk hedge
#

Yeah, class CanSwapCase(typing.Protocol): ... or similar

#

For this I don't see the benefit of anything more than str but of course I don't know the context

tulip hearth
#

Is it possible to do something like this

def my_func(arg_a) -> arg_a:
   return arg_a

Like is it possible that return annotations can be function arguments?

oblique urchin
soft matrix
#

!d typing.TypeVar

rough sluiceBOT
#

class typing.TypeVar```
Type variable.

Usage:

```py
T = TypeVar('T')  # Can be anything
A = TypeVar('A', str, bytes)  # Must be str or bytes
```  Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions. See [`Generic`](https://docs.python.org/3/library/typing.html#typing.Generic "typing.Generic") for more information on generic types. Generic functions work as follows...
tulip hearth
#

Interesting, this can help me in something else i am working on thnx

grave fjord
#

Might be nice to be able to do stuff like:

def foo(v: typing.T < str) -> typing.T: ...

pastel egret
#

That exists, TypeVar('T', bound=str) - if you mean T must be a str or subclass.

grave fjord
#

Sure but without having to add an extra line

pastel egret
#

Yeah it's very awkward having to construct the vars, not really an easy way to get around that.

undone carbon
rustic gull
#

is there a lower bound type hint?

buoyant swift
#

what is that?

buoyant swift
#

idts

pastel egret
#

What you do is do TypeVar('T', contravariant=True) to make it contravariant like that.

#

Then it accepts the subscripted type or any parent types.

#

Callable return types are contravariant for example.

acoustic thicket
#

return types or parameter types?

pastel egret
#

Which way around should it be?

#

Actually it doesn't mention it in docs.

rustic gull
#

i think its covariant in the return type and contravariant in the parameters but im not sure

oblique urchin
#

that's right

acoustic thicket
#

yeah

acoustic thicket
hallow flint
tulip hearth
#

Is it possible to pass in a string in my custom Generic type
without forward referencing it Field[str, "abc"], here "abc" is considered as forward annotation is there a way i can prevent that

tulip hearth
#

That helps

lapis copper
fading knoll
#

I dont know if this is the right channel, if not please send the right one.
But how do I run a python file through a variable

ex:

myfilename = "test"

import (myfilename).py

(I heard doing this will run the file i want, im doing this to get the newest version of a file then run it) anyone know how?

#

I gtg, so please ping me the answer and ill check tomorrow, please and thanks

acoustic thicket
brazen jolt
#

Is it possible to typehint a tuple of n string elements where n is taken as a function argument?

def foo(x: Any, n: int) -> Tuple[str, ...]:
    return (x, ) * n
trim tangle
#

Why? You can get n as len(tupel)

brazen trellis
#

yall know if its possible to allow multiple types w pydantic? either string or bool

little hare
#

union?

brazen trellis
#

Ayee

#

Ty

little vigil
#

Can you check if a variable exists without getting a KeyError?

entry['author'] will sometime result in a KeyError ,
because when the field is empty, the variable will not be created (from module side).

My workaround right now:

except: entry['author'] = ""```
#

Sorry if this is the wrong channel for this

ashen wave
#

dict.get(key, default_val)

#

will return default_val if the key is not present, otherwise returns the val that corresponds to key

#

to check if key is in entry:

if key in entry:
  print("Found!")
little vigil
oblique urchin
#

use Generic[T], not Generic(T)

rustic gull
#

πŸ€¦β€β™‚οΈ thank you

honest dawn
#

hi

torpid yarrow
#

posted this here a couple times, but typing is great totallyFine py def foo(bar: Union[Iterable[Union[str, int, float]], Callable[["Context"], Union[Iterable[Union[str, int, float]], Coroutine[Any, Any, Iterable[Union[str, int, float]]]]], Coroutine[Any, Any, Iterable[Union[str, int, float]]]]) -> Callable[["Context"], Coroutine[Any, Any, Iterable[Union[str, int, float]]]]: async def baz(): ... return baz Is Coroutine[Any,Any,X] or Awaitable[X] more correct here? (For typing an async function)

Also, if I want [1,2,3] or ["1", "2", "3"] but not [1, "2", 3], is Iterable[Union[str, int, float]] ok or should I use Union[Iterable[str], Iterable[int], Iterable[float]]?

trim tangle
#
  1. It's more concise
  2. It lets you return a different Awaitable in the future (that's weird, but it could happen I guess)
#

Also... do you know about type aliases?

torpid yarrow
#

Yep I use them

trim tangle
torpid yarrow
trim tangle
#

Also @torpid yarrow, I would strongly suggest configuring your editor/CI to reject values: Values = None. It should be values: Optional[Values] = None

soft matrix
#

Pycharm doesn't have an option for this I'm pretty sure

#

It just treats that as Optional

trim tangle
#

that's weird

#

I don't think it has the same behaviour in mypy in pyright

torpid yarrow
torpid yarrow
#

Wondering if I should use Coroutine to maintain consistency

oblique urchin
#

Eric made noises recently about flipping the default

#

And mypy has had an issue for a long time about flipping the default but it tends to move at a more glacial pace

trim tangle
#

so it's actually optional but it shows as non-optional??

#

is this a bug?

oblique urchin
trim tangle
#

pylance bug to be specific, not pyright

oblique urchin
#

Wouldn't it get the type to display from pyright?

trim tangle
#

I opened a bug on pylance

#

my bets are on Eric closing it with as designed

little hare
#

how do you do that

trim tangle
oblique urchin
#

type checkers will recognize that and print the inferred type of x

#

at least mypy, pyright, and pyanalyze do; I think it's not formally standardized

trim tangle
#

yeah

little hare
#

so you have to remove it if not type checking?

oblique urchin
#

yes it will throw an error at runtime because the function doesn't exist

#

there's been some talk about providing a runtime implementation

soft matrix
#

do you know if guidos gotten anywhere with that jelle?

oblique urchin
#

I don't think anything has happened. Probably it needs someone to actually push it through.

rustic gull
oblique urchin
rustic gull
#

so it should be JSON = Union[Dict[str, Any], List[Any], int, str, float, bool, None]

soft matrix
#

you shouldnt really use this cause it just makes thing a pain

#

if there was an AnyOf class it would be much better over the Union

rustic gull
#

What's the difference?

soft matrix
#

AnyOf is theoretically any of the types used to subscript and there shouldnt be any type checking for alternatives in the subscription, however, Union checks all of the items are correctly narrowed

leaden oak
#

So a bounded Any in a way?

soft matrix
#

if you use pycharm or maybe pytype Union is what AnyOf should be

trim tangle
#

not sure I'd like such AnyOf over Any or object

soft matrix
#

the main proposed use is for language servers/suggestions

trim tangle
soft matrix
pastel egret
# torpid yarrow Wondering if I should use Coroutine to maintain consistency

Coroutine is specifically what an async def function returns (or an exact replica), it requires send(), throw(), and close() methods in addition to __await__(). Awaitable on the other hand is just anything that can be awaited, which is more lenient if that's all you require. It's similar to the difference between Iterator and Generator,

trim tangle
#

not the function itself

pastel egret
#

I meant that yeah.

trim tangle
#

the python docs use these interchangeably which adds to confusion πŸ˜”

pastel egret
#

It is a bit confusing, a coroutine function returns a coroutine object, while the function is just the regular types.FunctionType...

#

Generators are sometimes specified as "generator-iterators", doesn't really work for coroutines though - "coroutine-awaitable"?

trim tangle
leaden oak
#
@overload
def filter_results(
    file_results: Dict[str, FileResult], type: Literal["reformatted"]
) -> Dict[str, ReformattedResult]:
    ...


@overload
def filter_results(
    file_results: Dict[str, FileResult], type: Literal["failed"]
) -> Dict[str, FailedResult]:
    ...


@overload
def filter_results(
    file_results: Dict[str, FileResult], type: Literal["nothing-changed"]
) -> Dict[str, NothingChangedResult]:
    ...


def filter_results(file_results: Dict[str, FileResult], type: str) -> Dict[str, FileResult]:
    return {
        file: result for file, result in file_results.items() if result.type == type
    }

I guess Literal["nothing-changed"] isn't a subtype of str hence why mypy doesn't like the function implementation.

leaden oak
#
src/diff_shades/analysis.py:149: error: Overloaded function implementation cannot produce return type of signature 1  [misc]
src/diff_shades/analysis.py:149: error: Overloaded function implementation cannot produce return type of signature 2  [misc]
src/diff_shades/analysis.py:149: error: Overloaded function implementation cannot produce return type of signature 3  [misc]
trim tangle
#

@leaden oak What is FileResult?

#

and what if you change Dict to Mapping?

leaden oak
#
@dataclasses.dataclass(frozen=True, init=False)
class FileResult:
    type: ResultTypes
    src: str


@dataclasses.dataclass(frozen=True)
class NothingChangedResult(FileResult):
    type: Literal["nothing-changed"] = field(default="nothing-changed", init=False)


@dataclasses.dataclass(frozen=True)
class ReformattedResult(FileResult):
    type: Literal["reformatted"] = field(default="reformatted", init=False)
    dst: str


@dataclasses.dataclass(frozen=True)
class FailedResult(FileResult):
    type: Literal["failed"] = field(default="failed", init=False)
    error: str
    message: str
#

Oh is this related to mutable containers again?

#

contra vs co varience or whatever the terms are

trim tangle
# leaden oak ```python @dataclasses.dataclass(frozen=True, init=False) class FileResult: ...

Why not ```py

@dataclasses.dataclass(frozen=True)
class NothingChangedResult:
type: Literal["nothing-changed"] = field(default="nothing-changed", init=False)

@dataclasses.dataclass(frozen=True)
class ReformattedResult:
type: Literal["reformatted"] = field(default="reformatted", init=False)
dst: str

@dataclasses.dataclass(frozen=True)
class FailedResult:
type: Literal["failed"] = field(default="failed", init=False)
error: str
message: str

FileResult = Union[NothingChangedResult, ReformattedResult, FailedResult]

#

and why do you need the type field?

leaden oak
#

honestly not sure, I've been just treating these dataclasses like dictionaries

trim tangle
#
@dataclasses.dataclass(frozen=True)
class NothingChangedResult:
    src: str


@dataclasses.dataclass(frozen=True)
class ReformattedResult:
    src: str
    dst: str


@dataclasses.dataclass(frozen=True)
class FailedResult:
    src: str
    error: str
    message: str

FileResult = Union[NothingChangedResult, ReformattedResult, FailedResult]
``` and then use `isinstance`
leaden oak
#

Technically you're missing the always present src attribute

trim tangle
leaden oak
#

There's probably a better way of handling this.

trim tangle
#

so I'd just pick a field during the [de]serialization

#

although it might be pretty inconvenient

#

depends on how you're doing it

leaden oak
#

Yeah that's pretty much the main reason why I did it that way, just treating 'em like dictionaries

#

I'll look into moving the type field somewhere else if possible.

hasty hull
#

Still got some kinks that need to be ironed out

torpid yarrow
soft matrix
#

you technically should be as lenient as possible when it comes to type hints

#

its also shorter to use Awaitable[Return] than Coroutine[Any, Any, Return] (although you obviously can use type aliases)

void panther
#

If you do not need what Coroutine provides to keep it functional, using a broader type will keep your api more open to changes

hasty hull
#

Does anyone know if there is anything I can do about this mypy performance issue

#

Creating generic classes causes mypy to take 34 minutes to check the code

#

instead of the previous 8

little hare
#

in a row

hasty hull
#

Okay there's no need to judge my actions workflows lol

#

I wrote then ages ago and had no idea what I was doing

little hare
#

nah i just want to make it the best possible

hasty hull
#

Also it is caching two different things

little hare
#

tldr I had a very stressful moment with workflows earlier

hasty hull
#

What happened?

little hare
#

tldr mrabarnett/mrab-regex#445

mighty lindenBOT
little hare
#

the title should explain it all

hasty hull
#

Oof

rustic gull
#

i was also wondering about that, do pyre or others have faster initial startup time than mypy

soft matrix
#

pyre should be pretty fast as its in not python πŸ˜‰

trim tangle
#

pyright seems faster than mypy

#

(also not in Python πŸ˜‰)

hallow flint
#

technically, mypy isn't in python either

oblique urchin
leaden oak
#

at what point does mypy take longer than pre-release-automation black?

#

to be fair mypy does wayy more testing than we do

oblique urchin
#

black's longest gap was 10 months, mypy is only at 5

leaden oak
#

Feels way longer than that .. not sure what to make of that

oblique urchin
#

I think the June releases already didn't include everything that was on master at the time

leaden oak
#

Yeah and it appears 0.920 will be similar

oblique urchin
#

yes it was branched months ago

undone carbon
#

is it possible to type hint like tiz?

class MyClass:
    def __init__(self, arg: MyClass): ...
solid light
undone carbon
#

n then?

solid light
#

Nothing

#

That's it

undone carbon
#

oh

#

well thx

solid light
#

__future__ is basically features that have already been coded, just not officially added yet (for one reason or another)

solid light
undone carbon
#

@solid light well than is vscode (pylance to be specific) giving me an error normal?

#

ig so...

undone carbon
#

@pastel egret can you help? πŸ˜…

pastel egret
#

Well, what's the error?

undone carbon
solid light
#

Show ur full code

undone carbon
#

huh

#

tat's the code

solid light
#

Well that doesn't have the import so it can't be everything

undone carbon
#

@pastel egret does mypy work with __future__ annotations then?

pastel egret
#

It should accept it yes.

undone carbon
#

okay thx

#

eh

undone carbon
#
@beartype
class MyClass:
    def __init__(self, arg: MyClass): ...
pastel egret
#

Beartype currently can't annotate classes themselves, you need to use it individually on all the functions.

undone carbon
#

oh silly me

#

yep it worked fine

#

thx

hasty hull
#

I've also had to disable multiple features from being generated when using mypy because they either cause nypy to take an unreasonable amount of time to type check or to straight up crash

undone carbon
#

breh i found the error

#
class MyClass:
    @beartype
    def __init__(self, arg: Union[str, MyClass]): ...
#

beartype will give tiz loooooong error but i think the main error is tiz:

#

beartype.roar.BeartypeDecorHintPep563Exception: @beartyped MyClass.__init__() parameter "arg" PEP 563-postponed type hint 'Union[str, MyClass]' syntactically invalid (i.e., "name 'MyClass' is not defined") under:

#

@pastel egret sry for the ping

pastel egret
#

Then why did you ping me?

undone carbon
#

lmao

pastel egret
#

And that is correct since it isn't yet defined when you execute the decorator.

hasty hull
undone carbon
#

oh

#

ok it worked thx

indigo locust
#

If I have a generic object which also inherits from a base

#
class Attribute(Generic[T_Typehint], Object):
    ...
#

Like that?

upbeat wadi
#

Other way around

#

The Generic should be last

#

(I'm not fully sure if it matters but I believe it does)

soft matrix
#

it doesnt

upbeat wadi
#

Ah okay

last pulsar
#

is there a way to say to a class that it must have properties with certain instances of classes? something like

class Foo:
    pass

class Bar:
    pass

class NotAllowed:
    pass

class Test:
    foo = Foo()
    bar = Bar()
    not_allowed = NotAllowed() # make this class accept only properties that are instances                                   of Foo and Bar
tranquil turtle
#

you cannot

#

it is impossible in python

#

classes have other properties, such as __doc__ and __class__, with certain types

#

you cannot say that all properties have some type, because it isnt true

pastel egret
#

Well you can't type hint it, but you can override __setattr__, and error out if the value isn't one of those.

tranquil turtle
#

you can typehint some properties:

class Foo:
    pass

class Bar:
    pass

class NotAllowed:
    pass

Foo_or_Bar = Foo | Bar # Union[Foo, Bar]

class Test:
    foo: Foo_or_Bar = Foo()
    bar: Foo_or_Bar = Bar()
    not_allowed: Foo_or_Bar = NotAllowed() # there should be an error

test = Test()
test.foo = 1 # error
test.foo = Bar() # ok
tranquil turtle
#

(sorry for my language)

last pulsar
#

i see

upbeat wadi
#

the first parameter isn't being concatenated because the function takes self as a parameter, which makes it appear as a MethodOfClass

#

having to rely on the parameter name to check if it's a method of a class isn't great, but i'm not sure how else to do it

pastel egret
#

What you probably need to do is make alru_cache a descriptor. The reason you can't find another way to check is that functions defined in and out of a class is exactly the same, the difference is when accessing the attribute.

upbeat wadi
#

I'll try that thanks

upbeat wadi
pastel egret
#

Couldn’t you define __call__()?

upbeat wadi
pastel egret
#

I mean if that's called, it's a regular function. If __get__ is called, it is accessed from a class or instance.

upbeat wadi
pure sonnet
#

what do decorators return?

#
def timed(ndigits: int= 5):
    def real_timed(func):
        def wrap(*args, **kwargs):
            time_start = time.time()
            return_val = func(*args, **kwargs)
            time_end   = time.time()
            print(f"[*] {func.__name__} took: { round(time_end - time_start, ndigits) }")
            return return_val
        return wrap
    return real_timed
grave fjord
pure sonnet
#

how do i specify that in a return type

#

-> object?

#

or -> class

#

or

pure sonnet
#

-> callable

pastel egret
#

You'll want a TypeVar or ParamSpec so the original function's signature is preserved.

grave fjord
#

Fortunately it's a signature preserving decorator so you don't need ParamSpec

#

Because mypy doesn't support ParamSpec yet q.q

fierce ridge
#

wait, mypy infers *args, **kwargs for decorators?

#

i had no idea

#

oh, it doesn't, they use cast() in the example

#

also --strict doesnt let you get away with those untyped varargs

rustic gull
#

Mypy just complained with this Argument 1 to "open" has incompatible type; expected "Union[Union[str, bytes, PathLike[str], PathLike[bytes]], int]" [arg-type]

#

I get the string/path ones but why is int a valid type for open lemon_thinking

pastel egret
#

If you have a file descriptor, you can use that to re-open that same handle.

tranquil turtle
#

mypy bug?

trim tangle
tranquil turtle
#

just to check mypy behavior xD

#

it isnt a very useful case

#

also pylint gives me interesting warning on third line:
pylint: warning W0238 - Unused private member 'X1.__m(self)' (unused-private-member)
πŸ€”

grave fjord
#

Yeah mypy should read that as _X1__m

trim tangle
#

Well this is at least a confusing error message

#

Which is as a bug in my books

tulip hearth
#

how would i declare Generic[T] so that it takes undefined amount of types, mypy is just expects 1 type argument, but n given

pastel egret
#

It's not currently possible.

#

!pep 646

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

Draft

Python-Version

3.10

Created

16-Sep-2020

Type

Standards Track

pastel egret
#

The Steering Council has basically accepted this, there's just one edge case to sort out.

tulip hearth
#

ohh

grave fjord
opaque root
#

Quick question, is there a way to typehint a weakref set?
For the sake of autocompletion I could just use x: t.Set[XYZ] = weakref.WeakSet(), but that's a wrong typehint of course, especially because the WeakSet doesn't inherit from set

void panther
#

you should be able to use weakref.ref as the generic argument if I understood correctly

opaque root
#
>>> x: WeakSet[Something] = WeakSet()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable

The problem is the type is unusable in a hint
Some quick searching has led me to a stackoverflow thread that shows a need to inherit from typing.Generic for this hint to work, but how would you do that for an already existing class?

soft matrix
#

you need put it in quotes

#

or update your version of python to 3.9+

#

x: "WeakSet[Something]" = WeakSet()

#

or use future.annotations

opaque root
#

Such a simple fix, that's done it, thanks πŸ˜„

trim tangle
#

||/hj||

grave fjord
#

TIL

#

Thing is I need the zope and Django and sqlalchemy plugins

trim tangle
grave fjord
#

Dang

trim tangle
#

Unless I figure out how to read its code πŸ‘€

#

And hack it in

grave fjord
#

Unless Django switches to typing.Annotated from model.Field

#

Maybe macros?

little hare
#

typehints are so weird because they can be so easily abused lol

#

an example they provide:

@bot.command()
async def clean(ctx, *, content: commands.clean_content(use_nicknames=False)):
    await ctx.send(content)
void panther
#

that's not really a typehint but a plain annotation

little hare
#

...

#

right

#

type hints are annotations

#

but then what exactly is the difference?

dim trail
#

PSA: callback protocols (Protocol subclass with a dunder call) require you to also use the same name, not just the same type (at least when checked by pyright)

i just spent multiple hours before i realised the reason pyright was throwing a error was not because of the type, but because of the argument name.

void panther
little hare
#

ahhh

#

that makes me wonder

#

is there a way to duplicate them?

#

use both the annotation for arbitrary metadata, and a typehint?

void panther
#

typing.Annotated was recently added for that

little hare
#

ah, okay

blazing nest
little hare
#

protocol?

dim trail
#

Protocols allow a more powerful way of defining types that typecheckers can check against. Generally, if you just want to typehint "any class that has a .open method with these arguments" you would make a protocol.

Callback Protocols are done by defining a __call__ in the Protocol, which makes them a Callable. its a more powerfull way to typehint a callable than typing.Callable

#

i think they're called callback protocols because thats their main usecase.

little hare
#

interesting, is there a way to check a class implements said protocol?

dim trail
#

yes, you can decorate the protocol with @runtime_checkable to make it work in issubclass

dim trail
rough sluiceBOT
#

@dim trail :white_check_mark: Your eval job has completed with return code 0.

True
dim trail
#

but the more common usecase is for a static typechecker such as mypy or pyright

spare mauve
#

though afaik the door is still open for other applications of annotations

#

but I've not actually seen one as of yet

blazing nest
#

I'd say that what FastAPI is doing can be somewhat categorized there

dim trail
#

with typehinting being a very nice tool in a lot of cases, im not sure i would actually want many other things using the annotations, as that would lock me out of using type-hints

void panther
#

that's what Annotated aimed to solve, but last time I checked the common runtime users of annotations didn't support it

hasty hull
#

pydantic supports it

soft matrix
#

Annotated could have been made a lot more powerful by the kwarg getitem pep that was denied

tulip hearth
#

so i have

T = TypeVar("T")
O = TypeVar("O")


class AttributeMeta(type):
    def __getitem__(self, params: Tuple[List[T], dict]) -> T:
        # Implementation skipped


class Attribute(Generic[T, O], metaclass=AttributeMeta):
    pass

val: Attribute[[int], {"name":"value"}]

This works but type checkers aren't happy with it, so is there a way to like indicate it to type checkers like mypy that this is valid?

oblique urchin
tulip hearth
#

it convers the list of T into a union of them and the dict is converted to a named tuple and then it returns typing.Annotated with the union and the named tuple

indigo locust
#

Hey my dudes

#

Question about singletons

#
class Singleton(type):

    def __call__(singleton: Singleton, *positional: Any, **encyclopedic: Any) -> T_Singleton:
        ...
#

With a singleton, the 'self' arg in the call method is an instance of singleton, right?

#

And, its a class. What comes out of the call method is an instance of that

#

How do I hint that properly?

grave fjord
indigo locust
#

H11?

grave fjord
#

they do this:

from typing import TypeVar, Type, Tuple, Any, Dict

_T_Sentinel = TypeVar("_T_Sentinel", bound="Sentinel")


class Sentinel(type):
    def __new__(
        cls: Type[_T_Sentinel],
        name: str,
        bases: Tuple[type, ...],
        namespace: Dict[str, Any],
        **kwds: Any
    ) -> _T_Sentinel:
        assert bases == (Sentinel, )
        v = super().__new__(cls, name, bases, namespace, **kwds)
        v.__class__ = v  # type: ignore
        return v

    def __repr__(self) -> str:
        return self.__name__


class CLIENT(Sentinel, metaclass=Sentinel):
    pass
#

I'm not sure if __call__ is the right method - isn't it __new__ on type?

#

h11 has a special requirement that type(CLIENT) is CLIENT

indigo locust
#

I figured it'd have something to do with binding a typevar. I thought that that just set a lower threshold for the inheritance chain. So it would, for example, prevent object from matching

grave fjord
#

so you don't need quite that much magic

#

tbh I'd probably just use an enum on a fresh project

indigo locust
#

I couldn't get a quick explanation on what 'bound' does could I? I've searched for one in the past but I've never found a direct answer

blazing nest
indigo locust
#

Yeah

hasty hull
#

Bound adds a type restriction, otherwise anything can be passed

#

So if you do bound='Sentinel' then only an instance of sentinel or an instance of a subclass of sentinel can be passed

indigo locust
#

So with this, _T_Sentinel represents the instance, while Type[_T_Sentinel] represents it's class. And _T_Sentinel is bound to the class of the class 😐

#

Metaclasses are always hard to follow, but that doesn't seem right to me

hasty hull
#

Yeah that's right, it's so that the methods propagate for subclasses

blazing nest
#

_T_Sentinel is the class, Type[_T_Sentinel] is the metaclass

terse sky
#

you wrote the same thing twice?

indigo locust
#

I thought I was hallucinating XD

terse sky
#

it's a bit unusual to make something both a base and a metaclass for clients

#

if you're going to do that then you may as well just provide a stub base class, with the metaclass in question, and then clients just inherit from that

#

and don't have to repeat themselves

#

Either that or don't combine the functionality

#

I'm not totally sure I understood the original problem.

indigo locust
#

I'm just wondering what the right way to hint the return of the meta's __call__ method is

terse sky
#

so Singleton is a meta class?

indigo locust
#

yeah

terse sky
#

it would need to be generic, I'd assume

hasty hull
#

I don't really understand the problem but shouldn't it be _T_Sentinel?

terse sky
#

I highly recommend avoiding this problem by avoiding singletons, which are an anti-pattern anyway πŸ˜›

#

btw, generic metaclasses are not supported, unfortunately, so making this work in the ideal may not be possible

#

at least not in mypy, not sure if you're planning to use a different type checker

leaden oak
#
from typing import Sequence, Type, TypeVar

T = TypeVar("T", bound=Type)

def my_filter(items: Sequence[object], cls: T) -> Sequence[T]:
    return [v for v in items if isinstance(v, cls)]

some_stuff = [1, "a", 2.2, (1, 2)]
integers = my_filter(some_stuff, int)
reveal_type(integers)
test.py:6: error: List comprehension has incompatible type List[object]; expected List[T]  [misc]
test.py:10: note: Revealed type is "typing.Sequence[Overload(def (x: Union[builtins.str, builtins.bytes, typing.SupportsInt, typing_extensions.SupportsIndex, builtins._SupportsTrunc] =) -> builtins.int*, def (x: Union[builtins.str, builtins.bytes], base: builtins.int) -> builtins.int*)]"

Did I misuse TypeVar here? or is mypy just not smart enough to use that isinstance to do type narrowing?

#

!d typing.TypeVar

rough sluiceBOT
#

class typing.TypeVar```
Type variable.

Usage:

```py
T = TypeVar('T')  # Can be anything
A = TypeVar('A', str, bytes)  # Must be str or bytes
```  Type variables exist primarily for the benefit of static type checkers. They serve as the parameters for generic types as well as for generic function definitions. See [`Generic`](https://docs.python.org/3/library/typing.html#typing.Generic "typing.Generic") for more information on generic types. Generic functions work as follows...
leaden oak
#

Alright, cool, I totally misunderstood what bound=... does.

pastel egret
#

You used it correctly for cls, if you're wanting to pass a subclass of type/Type which you are.

#

But you can't then do the reverse of Type to get the sequence subscript.

#

What you want is for T to represent the instances, not the type itself:

T = TypeVar("T")

def my_filter(items: Sequence[object], cls: Type[T]) -> Sequence[T]:
    return [v for v in items if isinstance(v, cls)]
leaden oak
#

Ah, that makes way more sense.

leaden oak
#

Thank you!

pastel egret
#

No problem.

#

You might want to make items just Iterable[object], since that's all you require.

leaden oak
#

yeah I would but that was just a toy example from having simplified a bit more complicated bit of code :)

pastel egret
#

Ah sure!

trim tangle
#
def aaa() -> callable:
    ...

bbb = aaa()

reveal_type(bbb)
#

This shows Any -> bool on pyright...

#

Interesting

brisk hedge
#

Huh, that should fail

trim tangle
#

That's a really confusing behaviour, that should give a warning on hover instead of literally the type of callable

#

I'll report this is l when I get home

#

Or well, anyone can report

trim tangle
native burrow
#

huh

minor reef
tranquil turtle
#

class X(Generic[A, B]):
    _dict: dict[A, B]
    _pair: X[B, A]

    def method(self) -> None:
        pair = self._pair

        reveal_type(self) # X[A, B]
        reveal_type(self._dict) # dict[A, B]
        reveal_type(pair) # X[B, A]
        reveal_type(pair._dict) # dict[A, B] WTF???

```pyright is shit
mypy is better
blazing nest
#

What's wrong?

#

I literally cannot tell what's bad with your "wtf" comment

blazing nest
#

That's all working as expected, is the issue that there's no initializer?

#

You basically have a recursive type there with self._pair πŸ€·β€β™‚οΈ

tranquil turtle
#

mypy works fine in this case

blazing nest
#

What you have to the left is that a representation or exactly what it outputted?

tranquil turtle
#

comments - pyright output

hasty hull
#

Pyright shows dict[A, B] because A and B are scoped to the X context not the child context

tranquil turtle
#

first three cases are ok, fourth is not ok

blazing nest
#

Because I would bet that A, B is referring to self._pair's A and B generics, (which are defined as B and A of the "parent" X).

hasty hull
#

^

blazing nest
#

What happens if you make the types concrete?

hasty hull
#

pyright actually shows: dict[A@X, B@X]

blazing nest
#

As in, do it on an instance where the generics have been filled in.

tranquil turtle
#

this fixes the issue:
def method(self: X[A, B]) -> None:

hasty hull
#

There is no issue, pyright shows dict[A, B] because those are the types in that context

blazing nest
#

I am on my phone but can you show this code? ```python
instance: X[int, str]

reveal_type(instance)
reveal_type(instance._dict)
reveal_type(instance._pair)
reveal_type(instance._pair._dict)

#

Show what PyRight outputs

tranquil turtle
#

outside the method all works fine

tranquil turtle
hasty hull
blazing nest
#

I assume this is your argument though? That you want the behaviour of MyPy.

tranquil turtle
#

yea, mypy works fine without explicit typing self in method

hasty hull
#

The actual resolved types are correct, it's just the representation of them thats different

blazing nest
tranquil turtle
hasty hull
#

What are the error messages?

blazing nest
#

That could be a bug then, open an issue and it'll be fixed in a few days - compared to MyPy hehe πŸ˜‰

hasty hull
#

Okay, nevermind that does look like an actual bug

blazing nest
#

Yeah but I didn't want their mind to explode hearing that πŸ˜‚

#

For the record I think MyPy is good but I am just giving it shit because Denball here is super confident about how shit Pyright is

hasty hull
fierce ridge
#

is the pyright dev some a full time MS employee who only works on pyright?

hasty hull
#

I think so

fierce ridge
#

makes sense

hasty hull
#

yeah it's insane how fast he fixes bugs

tranquil turtle
tranquil turtle
tranquil turtle
#
from __future__ import annotations

from typing import TypeVar, Generic
from typing_extensions import (
    Self,
    TypeVarTuple,
    Unpack,
)

T = TypeVar('T')
TT = TypeVarTuple('TT')

# this works:
def f(*args: Unpack[TT]) -> tuple[Unpack[TT]]:
    return args

reveal_type(f(1, '', [])) # -> tuple[int, str, list]
reveal_type(f()) # -> tuple[()]

class X(Generic[T]): pass

# this is not working:
#            vvvvvvvvvvvvv  what to write here?
def g(*args: Unpack[X[TT]]) -> tuple[Unpack[TT]]:
    # i tried:
    # Unpack[X[TT]]
    # X[Unpack[TT]]
    # X[TT]
    # Unpack[X[Unpack[TT]]]
    return tuple[Unpack[TT]]()

# i want:
reveal_type(g(X[int](), X[str](), X[list]())) # -> tuple[int, str, list]
#

this is related question

tranquil turtle
#

maybe something like this?```py
XTT = tuple(X[T] for T in TT)
def g(*args: Unpack[XTT]) -> tuple[Unpack[TT]]: ...

fierce ridge
#

@tranquil turtle tuple[T, ...] is a variadic but homogeneous tuple

tranquil turtle
#

i know

#

i want variadic tuple with all items wrapped with X[...]

#

example: g(X[int], X[str], X[list]) -> tuple[int, str, list]
i want to do this generic

#

before i uses this:
def g(*args: X[Any]) -> tuple[Any, ...]:

#

but this is bad for obvious reasons

fierce ridge
#

you can't do that unfortunately

#

the best you can do is a union

tranquil turtle
tranquil turtle
fierce ridge
#

unless i misunderstand your intentions

#

i'd argue that perhaps this is a confusing interface anyway and maybe should be written another way

tranquil turtle
fierce ridge
#

did you use from __future__ import annotations?

#

also not all types are callable like that

rustic gull
#

(i did not)

fierce ridge
rustic gull
#

it still raises the same error

tranquil turtle
hasty hull
#

Mypy thinks that key is a string, thats why the error is raised

#

e.g. this works:

def foo(post: Post) -> None:
    key: Literal['w'] = 'w'
    print(post[key])
#

but this doesn't:

def foo(post: Post) -> None:
    key: str = 'w'
    print(post[key])
rustic gull
#

oh i didnt read it close enough right, it says 'string literal'

#

thank you

hasty hull
#

happy to help, you can just ignore the error in this context as you know that you're right

tranquil turtle
fierce ridge
#

at least, i couldn't get them to work that way

trim tangle
#

this is literally me every day

fierce ridge
#

there's no reason it shouldn't be possible though right?

trim tangle
#

hmm depends on what exactly you want

#

maybe I misunderstand

fierce ridge
#

https://mypy-play.net/?mypy=latest&python=3.10&flags=strict&gist=02b581a4d8df54dcbe7d2d43108c9b2a

from typing import Generic, TypeVar

T = TypeVar('T')

class X(Generic[T]):
    value: T
    def __init__(self, value: T):
        self.value = value

def f(*args: X[T]) -> tuple[T, ...]:
    return tuple(arg.value for arg in args)

args = f(X(1), X('hi'))

reveal_type(args)
main.py:13: error: Cannot infer type argument 1 of "f"
main.py:15: note: Revealed type is "builtins.tuple[Any]"
Found 1 error in 1 file (checked 1 source file)
#

i want this to infer that T is int | str

trim tangle
#

@fierce ridge

#

πŸ™‚

fierce ridge
#
reveal_type((X(1), X('hi')))
main.py:13: note: Revealed type is "Tuple[__main__.X[builtins.int*], __main__.X[builtins.str*]]"
trim tangle
#

I actually thought you wanted it to infer tuple[int, str], hence the typescript reference

#

so it's mypy's fault I guess?

fierce ridge
#

well that'd be even better

trim tangle
#

oh wait

fierce ridge
#

so pyright seems to do the right thing

little hare
#

definitely dawn and aboo

trim tangle
#

well, Rust is very different from Python

#

unlike TS

trim tangle
#
from typing import Generic, TypeVar, Union

T = TypeVar('T')

class X(Generic[T]):
    value: T
    def __init__(self, value: T):
        self.value = value

def f(*args: X[T]) -> tuple[T, ...]:
    return tuple(arg.value for arg in args)

arg1: X[Union[int, str]] = X(42)
arg2: X[Union[int, str]] = X("hi")
args = f(arg1, arg2)


reveal_type(args)
fierce ridge
#

yeah, but ew

trim tangle
#

πŸ˜„

#

yeah I'm half trolling

fierce ridge
#

might as well do f(cast(X[int | str], X(1)), cast(X[int | str], X("hi")))

trim tangle
#

lmao

#

Firstly, this shouldn't be an error. It should do what pyright does -- infer d's type as dict[str, Unknown]
Secondly, I'm not calling the update method for goodness sake!

#

I got really confused by this today

#

And if you enable the strictDictionaryInference option in pyright, d is inferred as dict[str, object | float]

fierce ridge
#

update? what?

#

did they implement d = {**x, **y} as d.update(x).update(y)??

trim tangle
#

is mypy just a big hack?

#

you know, like cloc is one 11000-line Perl script

little hare
trim tangle
#

why are type checkers so buggy and weird? πŸ€”

trim tangle
#

hey, what is this shiny new thing

grave fjord
#

Everyone is making their own hype checker

trim tangle
#

time to make my own

grave fjord
#

#hype-tinting

undone carbon
#

lmaoo

spare mauve
#

is there a non-deprecated way to write

typing.Callable[..., typing.Any]
``` ?
grave fjord
#

I tend to use Protocol if I need a fancy callable

class SupportsCall(typing.Protocol):
    def __call__(self, *args: object, **kwargs: object) -> typing.Any: ...
spare mauve
#

I didn't think so, @vagrant dagger , but beartype was complaining about it.. I got past it by dropping the annotation

spare mauve
grave fjord
#

Can beartype check callable return types like that?

#

There's no way of knowing what a Callable will return until you call it

spare mauve
#

hmm ...

void panther
grave fjord
#

Huh til typing.Callable is deprecated

grave fjord
#

!e

import typing
import collections.abc

collections.abc.Callable[[], 2]
print("why is it that collections.abc.Callable[[], 2] works")
typing.Callable[[], 2]
print("but typing.Callable[[], 2] fails?")
rough sluiceBOT
#

@grave fjord :x: Your eval job has completed with return code 1.

001 | why is it that collections.abc.Callable[[], 2] works
002 | Traceback (most recent call last):
003 |   File "<string>", line 6, in <module>
004 |   File "/usr/local/lib/python3.10/typing.py", line 1182, in __getitem__
005 |     return self.__getitem_inner__(params)
006 |   File "/usr/local/lib/python3.10/typing.py", line 309, in inner
007 |     return func(*args, **kwds)
008 |   File "/usr/local/lib/python3.10/typing.py", line 1188, in __getitem_inner__
009 |     result = _type_check(result, msg)
010 |   File "/usr/local/lib/python3.10/typing.py", line 173, in _type_check
011 |     raise TypeError(f"{msg} Got {arg!r:.100}.")
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/uhanenolus.txt?noredirect

void panther
#

!e list[0]

rough sluiceBOT
#

@void panther :warning: Your eval job has completed with return code 0.

[No output]
grave fjord
#

!e

import collections.abc
collections.abc.Callable[2, 2]
rough sluiceBOT
#

@grave fjord :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 2, in <module>
003 |   File "/usr/local/lib/python3.10/_collections_abc.py", line 436, in __new__
004 |     raise TypeError(f"Expected a list of types, an ellipsis, "
005 | TypeError: Expected a list of types, an ellipsis, ParamSpec, or Concatenate. Got 2
grave fjord
little hare
#

what is Protocols?

grave fjord
#

what do you mean by nested return?

grave fjord
#

create a mypy play?

little hare
void panther
grave fjord
void panther
#

Why did they decide to draw the line there but don't validate further like the typing version

little hare
#

so what exactly does the protocol mean, and how is it used?

little hare
#

huh

#

so what do the [] mean on classes?

grave fjord
#

although there's a bunch of other places where [] means something slightly different eg v: Final[int] = 2

#

do you want to return [] instead?

#

!e

contiguousVals = []
min(contiguousVals) + max(contiguousVals)

but then you get this at runtime

rough sluiceBOT
#

@grave fjord :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 2, in <module>
003 | ValueError: min() arg is an empty sequence
grave fjord
#

is it possible to not have any contiguousVals at runtime?

#

ah right but mypy doesn't know that

#

so you need to prove you handle the case or use an assert contiguousVals is not None or something to flatten the Optional

spare mauve
#

so collections.abc.Callable is preferred over typing.Callable ?

#

be careful though because python -O0 will disable them

grave fjord
grave fjord
spare mauve
#

oh, cool

spare mauve
little hare
little hare
#

!d debug

rough sluiceBOT
#

__debug__```
This constant is true if Python was not started with an [`-O`](https://docs.python.org/3/using/cmdline.html#cmdoption-O) option. See also the [`assert`](https://docs.python.org/3/reference/simple_stmts.html#assert) statement.
spare mauve
little hare
#

-OO is double optimized, if that's what you meant πŸ˜›

grave fjord
#

pretty much everyone always runs python in __debug__ mode :p

oblique urchin
#

At work I once tried to run python in "optimized" mode (which strips docstrings) and everything failed to import because some library unconditionally accessed __doc__ at runtime

little hare
#

python -O will work but python -OO strips the docstrings

little hare
#

a poorly coded one

fierce ridge
#

also i wonder what the benefit of -O ever is or was

oblique urchin
#

some data sciency thing, it was a long time ago

#

let me see if I can reproduce it now

little hare
oblique urchin
#
    param_rule.__doc__ = func.__doc__.replace('xxx', xxx).replace('yyy', yyy)
#

this one

#

and pyspark ``` File "/home/jelle/ans/venv/lib/python3.6/site-packages/pyspark/conf.py", line 72, in <module>
doc = re.sub(r"(\W|^)uU", r'\1\2', doc)

fierce ridge
#

oh that

#

i've seen that, pymongo i think does it too

#

or motor does it using pymongo doc strings

#

actually i wonder how does functools.wraps handle that?

oblique urchin
fierce ridge
#

can you detect the -O level at runtime? it would be a trivial fix to guard that behind a check

oblique urchin
#

yeah something in sys

void panther
#

what's the reason for the operations?

fierce ridge
oblique urchin
#

skimage fails too ``` File "/home/jelle/ans/venv/lib/python3.6/site-packages/skimage/measure/_regionprops.py", line 634, in _parse_docs
doc, flags=re.DOTALL)

little hare
rough sluiceBOT
#

sys.flags```
The [named tuple](https://docs.python.org/3/glossary.html#term-named-tuple) *flags* exposes the status of command line flags. The attributes are read only...
oblique urchin
little hare
#

no wait it is

#

sys.flags.optimize

void panther
little hare
#

code introspection iirc

fierce ridge
# void panther What's that useful for?

tools that frequently are used in an interactive context like pyspark, so you get nice help() output. also tools like sphinx don't rely on static analysis, they actually import your module which causes the whole thing to be exec'ed

spare mauve
#

I'm guilty of reading __doc__ for types.CodeType

#

it has no signature...

tranquil turtle
#
code(argcount, posonlyargcount, kwonlyargcount, nlocals, stacksize, flags, codestring, constants, names, varnames, filename, name, firstlineno, linetable, freevars=(), cellvars=(), /)
rustic gull
#

can i ignore type errors of a type alias? (just to annotate the funcion)
Context = discord.ext.commands.context.Context
i dont think the library has stubs

soft matrix
#

it does have stubs

#

either the library is typed if you use v2 or there are types-discord or something that someone made

#

!pypi discord.py-stubs

rough sluiceBOT
open hawk
#

How do you use NamedTuple in type hinting? is in like NamedTuple[str, str] or do I need to specify the name of my particular named Tuple

soft matrix
#

NamedTuple currently does not support subscription

#

!d typing.NamedTuple

rough sluiceBOT
#

class typing.NamedTuple```
Typed version of [`collections.namedtuple()`](https://docs.python.org/3/library/collections.html#collections.namedtuple "collections.namedtuple").

Usage:

```py
class Employee(NamedTuple):
    name: str
    id: int
```  This is equivalent to:

```py
Employee = collections.namedtuple('Employee', ['name', 'id'])
```...
soft matrix
#

shows how to use it

open hawk
#

Hmm, okay, thanks

#

Oh, I can also just use the name of my named tuple as long as I define it in scope, that's much cleaner

open hawk
#

Oh well I made a named tuple like so, start_finish_tuple = namedtuple('start_finish_tuple', ['start', 'finish']) and I just wanted to add a type annotation for that particular named tuple, not any generic NamedTuple

#

but I can write def some_function() -> start_finish_tuple: as long as start_finish_tuple is defined in scope

trim tangle
#

if you're using typing, why use the untyped namedtuple? @open hawk

soft matrix
#

i think they are changing that

trim tangle
#

ah

#

If you want any tuple with two strings, you can do Tuple[str, str]

open hawk
#

Ah I see

trim tangle
#

I don't think there's a way to require a namedtuple without naming a specific one, that'd be strange

open hawk
#

Yeah that makes sense

soft matrix
#

Tuple[str, str] is also compatible with your namedtuple as well

open hawk
#

I didn't read far enough, you can add type annotations in your namedTuple definition like so

start_finish_tuple = namedtuple('start_finish_tuple', [('start',str), ('finish',str)])
soft matrix
#

not the standard collections version

#

idk if you can even still use that old syntax anymore on the typing version

#

oh you can

open hawk
#

Oh, my IDE didn't like that, the only change need is

start_finish_tuple = NamedTuple('start_finish_tuple', [('start',str), ('finish',str)])
#

In the long run this is likely to be changed to a timestamp, but you know, YAGNI (yet)

terse sky
#

i'm curious though, why use a namedtuple instead of simply a dataclass with frozen=true

open hawk
#

lol because I'm just familiar with namedtuples and unfamiliar with dataclasses.

#

No better reason than that

terse sky
#

tbh I'd just get used to dataclasses then πŸ™‚

open hawk
#

I hear they're useful, and I probably will soon, I'm just trying to get a minimum-viable-product for a colleague

terse sky
#

fair enough

open hawk
#

I also jus discovered that my tuple is actually holding pandas.Timestamp values, thanks typing πŸ‘

#

I had forgotten that the weren't just a date string

trim tangle
#
class StartFinish(NamedTuple):
    start: str
    finish: str
open hawk
#

I thought those were equivalent?

trim tangle
#

they are

#

idk, the class version makes more sense to me

open hawk
#

lol I just liked the one-liner definition, but after adding typing it's a bit verbose, so I think I actually like the class version more

terse sky
#

at that point you really may as well use a dataclass lol

#

almost identical

#

the main thing is that the dataclass gives you a lot more control over certain things, if you'r einterested, and the dataclass will not have numeric access, and *

#

in most cases when I have something like this, I don't want people doing things like start_finish[1]

#

or *start_finish

open hawk
#

Is is as simple as an annotation?

trim tangle
open hawk
#

Data classes, I wanted to figure out to use them. It really seems like it is as easy as an annotation

open hawk
#

Right, lol, it's called an annotation in Java

trim tangle
#

I think it's a bit different in Python

#

in Python it's just syntax sugar for a function call

terse sky
#

yeah, just

@dataclass
class StartFinish:
    start: str
    finish: str
#

@open hawk

#

by default you'd be able to modify stuff

#

s = StartFinish("hi", "bye"); s.start = "hello" would be legal

#

if you pass frozen=True to the decorator then it would be more like a named tuple in this regard

open hawk
#

Awesome

wicked scarab
#

pycharm evals the string in Literal? How to prevent it though

fierce ridge
#

i'm pretty sure that's a pycharm bug

wicked scarab
fierce ridge
#

that's a shame. i haven't used pycharm much at all since i got neovim lsp and dap set up and running. file a bug report?

rough sluiceBOT
#

:incoming_envelope: :ok_hand: applied mute to @rustic gull until <t:1637828340:f> (9 minutes and 59 seconds) (reason: duplicates rule: sent 4 duplicated messages in 10s).

wicked scarab
lavish loom
#

can someone tell about the class methods that have __ i know they are dunder methods but i wanted to know if we can create our own ad does it follow pep8

trim tangle
lavish loom
trim tangle
#

Why do you want to create a custom 'dunder method'?

lavish loom
#

i want to know if pep8 allows creating methods with starting double underscore

trim tangle
#

starting double underscore with no ending underscore has a special meaning

#

but aside from that, it tells that methods should be in snake_case, so I guess no

#

PEP8 is just a convention. You don't have to follow it

lavish loom
pastel egret
lavish loom
trim tangle
pastel egret
#

For __names, in classes those are changed to _ClassName_name. That way if you have superclasses and subclasses, both can use an attribute name and it won't interfere with each other.

trim tangle
rough sluiceBOT
#

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

001 | I am foo
002 | foo
003 | False
trim tangle
#

anyway, this is really off topic for this channel

lavish loom
#

my bad

#

thank you regardless

undone carbon
#

why does mypy gimme tiz error

alias = int | float | str | bool
Unsupported left operand type for | ("types.Union")
trim tangle
undone carbon
#

py 3.10.0
mypy 0.91.0

undone carbon
#

brehh

soft matrix
#

It works on the latest GitHub version

trim tangle
#

yep @undone carbon it works on master

#

(switch to master on the playground website)

undone carbon
#

huh

#

tiz is strange

trim tangle
#

This should be fixed in 0.920

undone carbon
#

heh

#

okay

trim tangle
#

πŸ™‚

undone carbon
#

u mean it's not released yet?

#

bruh

#

so wat's wrong @trim tangle ? it's just a mypy bug?

undone carbon
#

bruh

grave fjord
#

There was some activity yesterday!

undone carbon
#

how should i fix tiz mypy error? Cannot find implementation or library stub for module named "beartype"

trim tangle
undone carbon
#

gg

#

lemme process for a min lmaoo

#

ah tat explains

grave fjord
#

Running mypy with pre-commit?

undone carbon
#

just wanna confirm, in py3.10 it is recommended to do tuple[int] instead of Tuple[int] right?

buoyant swift
#

yeah

little hare
#

unless you support less than 310 πŸ˜›

buoyant swift
#

yeah like 3.9 :P

little hare
#

or 3.8

#

or even....3.7 ew

buoyant swift
#

the joke was that that feature was added in 3.9

little hare
#

oh i forgot that....

#

I often support 3.8

undone carbon
rustic gull
#

What would be the best way of type hinting a dict without having to import typing?

rustic gull
#
        self.card_deck = {
            "A": 1,
            "2": 2,
            "3": 3,
            "4": 4,
            "5": 5,
            "6": 6,
            "7": 7,
            "8": 8,
            "9": 9,
            "10": 10,
            "J": 10,
            "Q": 10,
            "K": 10,
            "BlackJack": 10,
        }

Is the dict I have

rustic gull
little hare
#

what python version are you on?

rustic gull
#

3

little hare
#

minor version, too

#

eg 3.6, 3.7, 3.8, 3.9, 3.10, etc

#

if you don't know, you can use python3 -V and it'll tell you

rustic gull
#

3.10

little hare
#

gotcha

#

same syntax as typing.Dict[], but use dict[] instead

#

so the above would be dict[str,int]

rustic gull
#

hmm

#

guessing str will be the keys

#

and int will be the values?

little hare
#

ye

#

!d typing.Dict

rough sluiceBOT
#

class typing.Dict(dict, MutableMapping[KT, VT])```
A generic version of [`dict`](https://docs.python.org/3/library/stdtypes.html#dict "dict"). Useful for annotating return types. To annotate arguments it is preferred to use an abstract collection type such as [`Mapping`](https://docs.python.org/3/library/typing.html#typing.Mapping "typing.Mapping").

This type can be used as follows:

```py
def count_words(text: str) -> Dict[str, int]:
    ...
```   Deprecated since version 3.9: [`builtins.dict`](https://docs.python.org/3/library/stdtypes.html#dict "dict") now supports `[]`. See [**PEP 585**](https://www.python.org/dev/peps/pep-0585) and [Generic Alias Type](https://docs.python.org/3/library/stdtypes.html#types-genericalias).
rustic gull
#

I see I see

#

but how would I typehint a list then?

#

lets say this is my list:

mylist = [1, 2]
trim tangle
#

typing.List[int]

rustic gull
#

it should be list[int] but someone said that it should be list[int, int]

trim tangle
#

whoever said that is wrong

rustic gull
#

Ah okay

#

also

#

in a class

#

if i want to typehint self, it should be self: object right?

trim tangle
#

why do you want to typehint self? @rustic gull

rustic gull
#

I'm trying to typehint as much as I can as it helps me understand what is what and how it works in depth etc..

#

just for learning

trim tangle
#

You should not typehint self most of the time

#

There are some rare times you should, in that case use a typevar:```py
F = TypeVar("F", bound="Foo")

class Foo:
def me(self: F) -> F:
return self

rustic gull
#

So I should not typehint when instantiating my class either?

trim tangle
#

hm?

rustic gull
#

like this:

game: object = Game()
```?
trim tangle
#

No, you shouldn't do that

rustic gull
#

Is there a particular reason for that?

trim tangle
#

are you using a type checker?

rustic gull
#

Nope

trim tangle
#

why are you using type hints then?

rustic gull
#

So I understand some stuff when reading my code?

trim tangle
#

they won't provide that much value, and you'll get them wrong, so other people will have a hard time

rustic gull
#

oh..

#

like this is my code

#

so I shouldn't type hint my stuff?

trim tangle
rustic gull
#

ah I see

trim tangle
rustic gull
#

What is that?

trim tangle
rustic gull
trim tangle
#

most popular is mypy, but pyright is becoming more popular

trim tangle
#

IDEs have plugins for them, yes

rustic gull
#

lol I'm just gonna remove my typehints then xD, but how am I gonna understand what is what when reading and editing my code?

trim tangle
#

Nobody says you're not allowed to use type hints

rustic gull
#

my code will be long and it really helps knowing what is what without having to scroll to the section where I define it

buoyant swift
#

idt that's the right takeaway. you shouldn't remove typehints rather start using a type checker

little hare
#

^^

rustic gull
#

I see, how would a type checker look like as an example?

trim tangle
#

what IDE are you using?

little hare
#

the thing is you just need to get the type checks right hehe

rustic gull
#

VSC

trim tangle
# rustic gull VSC

If you don't have the Pylance extension, install it.
If you do, go to settings -> Pylance -> type checking mode -> "basic"

#

boom, you have a type checker

#

now you should have pop-up hints:

#

and type errors:

rustic gull
#

bro...

#

im dumb af, why wouldn't i think of something like this

#

xD this is so smart

#

It works

soft matrix
trim tangle
#

yep

#

or if you don't use vscode but use pyright

rustic gull
#

But I should still typehint what a method is returning right?

soft matrix
#

yeah

little hare
soft matrix
#

you would put the return type as Self

soft matrix
#

its not provisional in 3.10

little hare
#

3.11 then

soft matrix
#

its gonna hopefully be in 3.11

rustic gull
#
    def start_cards(self) -> list[str]:
        starting_cards = random.sample(list(self.card_deck)[:-1], 2)
        if 'A' in starting_cards and any(card in starting_cards for card in ('10', 'J', 'Q', 'K')):
            starting_cards.append(list(self.card_deck)[-1])
        return starting_cards

So this for example, is fine for typehinting?

soft matrix
#

yep

rustic gull
#

Alright tysm guys

little hare
#

as bad as it is

#

i've actually cheated on my typehints in 3.8

rustic gull
#

wow wait I have a bunch of errors in my other codes now?

trim tangle
#

I'm working on projects ranging from 3.6 to 3.9 πŸ‘€

little hare
#

oof

#

i've cheated with string annotations

#

"dict[str,int]"

soft matrix
#

i just future annotations

trim tangle
#

all these hacks break if you want to inspect the annotations

little hare
#

yeah

trim tangle
#

which is, to be fair, a niche thing

little hare
#

a niche thing
except for literally my entire project

rustic gull
#

I have a question

little hare
#

go for it

rustic gull
#

a list is a class, and a object?

trim tangle
#

all classes are objects

rustic gull
#

so classes = objects?

trim tangle
#

no

#

all dogs are animals

rustic gull
#

but all animals aint dogs

#

I see

#

so there are different types of objects, such as classes?

trim tangle
#

list is a type, str is a type, type is a type

#

the type of 1 is int, the type of "foo", is str, and the type of list is type

#

!e

print(type(1))
print(type("foo"))
print(type(list))
rough sluiceBOT
#

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

001 | <class 'int'>
002 | <class 'str'>
003 | <class 'type'>
little hare
#

~~close enough~

rustic gull
#

the definition of confusion is this section of chat xD

#

so

trim tangle
#

oops

#

thanks

rustic gull
#

so 1 is int, a int is what? a list? a list is what? a type? a type is what? a class? a class is what? a object?

#

im confused

#

so strings arent actually string

trim tangle
#

All types -- str, int, list etc. -- inherit from object

buoyant swift
#

but what type is type 😩

rustic gull
#

and what is a object πŸ‘€

little hare
#

!d object

rough sluiceBOT
#

class object```
Return a new featureless object. [`object`](https://docs.python.org/3/library/functions.html#object "object") is a base for all classes. It has methods that are common to all instances of Python classes. This function does not accept any arguments.

Note

[`object`](https://docs.python.org/3/library/functions.html#object "object") does *not* have a [`__dict__`](https://docs.python.org/3/library/stdtypes.html#object.__dict__ "object.__dict__"), so you can’t assign arbitrary attributes to an instance of the [`object`](https://docs.python.org/3/library/functions.html#object "object") class.
rustic gull
#

everything in python are objects of what I know, but why is it called a list?

buoyant swift
#

because if you called everything an object, it'd be very confusing very quickly

little hare
#

lists are called lists because they contain a list of objects

rustic gull
# rough sluice

then wouldn't it be like: objects are classes, classes are objects?

#

it's circular?

trim tangle
buoyant swift
#

#type-hintingtheory

rustic gull
buoyant swift
#

yes, but not necessarily a class

rustic gull
#

I see

little hare
#

!e ```py
print(issubclass(list,object))

rough sluiceBOT
#

@little hare :white_check_mark: Your eval job has completed with return code 0.

True
rustic gull
#

so:

mystring: object = "hello"

Is wrong, but actually right?

little hare
#

yes

#

!e print(isinstance('hello',object))

rough sluiceBOT
#

@little hare :white_check_mark: Your eval job has completed with return code 0.

True
rustic gull
#

So a person could actually typehint everything as a object

little hare
#

yeah, but it wouldn't be accurate or helpful

#

its not wrong

rustic gull
#

I see, that's why type exists right?

trim tangle
#

you generally don't need to typehint local variables, their types are automatically inferred

rustic gull
#

!e ```py
print(type(123))

little hare
#

!e print(type(123))

rough sluiceBOT
#

@little hare :white_check_mark: Your eval job has completed with return code 0.

<class 'int'>
trim tangle
#

But you can do this:

class Animal:
    pass

class Dog(Animal):
    pass

class ScaryDog(Dog):
    pass

dog = ScaryDog()  # inferred as ScaryDog
dog: Dog = ScaryDog()
dog: Animal = ScaryDog()
dog: object = ScaryDog()
dog: Union[Dog, int] = ScaryDog()
rough sluiceBOT
#

@rustic gull :white_check_mark: Your eval job has completed with return code 0.

<class 'int'>
trim tangle
#

all these are legal, because ScaryDog satisfies all of them.

rustic gull
#

Yeah I see

little hare
#

huh i just realised I should be using type() instead of __class__.....

rustic gull
#

since classes are objects

buoyant swift
#

i'm not sure what you mean by that. it's just telling you that what you printed is the class int

rustic gull
#

and a class int = object?

buoyant swift
#

ah i see, no you can't make that substitution

#

since classes support operations that object doesn't

#

err, at least, int doesn't

rustic gull
#

interesting

little hare
#

!e print(type(object))

rough sluiceBOT
#

@little hare :white_check_mark: Your eval job has completed with return code 0.

<class 'type'>
little hare
#

!e print(type(object()))

rough sluiceBOT
#

@little hare :white_check_mark: Your eval job has completed with return code 0.

<class 'object'>
rustic gull
#

wait object() is a builtin method?

little hare
#

its a call of class object

rustic gull
#

oh right

#

!object

#

!object()

little hare
#

that is one long tag...

rustic gull
#

how did you get the class object?

#

!class object

rough sluiceBOT
#

Classes

Classes are used to create objects that have specific behavior.

Every object in python has a class, including lists, dictionaries and even numbers. Using a class to group code and data like this is the foundation of Object Oriented Programming. Classes allow you to expose a simple, consistent interface while hiding the more complicated details. This simplifies the rest of your program and makes it easier to separately maintain and debug each component.

Here is an example class:

class Foo:
    def __init__(self, somedata):
        self.my_attrib = somedata

    def show(self):
        print(self.my_attrib)

To use a class, you need to instantiate it. The following creates a new object named bar, with Foo as its class.

bar = Foo('data')
bar.show()

We can access any of Foo's methods via bar.my_method(), and access any of bars data via bar.my_attribute.

little hare
#

!e

rough sluiceBOT
#
Command Help

!eval [code]
Can also use: e

*Run Python code and get the results.

This command supports multiple lines of code, including code wrapped inside a formatted code block. Code can be re-evaluated by editing the original message within 10 seconds and clicking the reaction that subsequently appears.

We've done our best to make this sandboxed, but do let us know if you manage to find an issue with it!*

little hare
#

^ eval command

rustic gull
#

!d object

rough sluiceBOT
#

class object```
Return a new featureless object. [`object`](https://docs.python.org/3/library/functions.html#object "object") is a base for all classes. It has methods that are common to all instances of Python classes. This function does not accept any arguments.

Note

[`object`](https://docs.python.org/3/library/functions.html#object "object") does *not* have a [`__dict__`](https://docs.python.org/3/library/stdtypes.html#object.__dict__ "object.__dict__"), so you can’t assign arbitrary attributes to an instance of the [`object`](https://docs.python.org/3/library/functions.html#object "object") class.
rustic gull
#

oh there

trim tangle
# rustic gull and a class int = object?

All dogs are animals. Bob is a dog. Therefore, he's also an animal. Therefore, he's also a eukaryote.
But when someone asks "who's Bob?", you don't answer "he's a eukaryote", you answer "he's a dog"

rustic gull
#

I see I see

#

So basically, in the terms of a dummie, everything is a object, but there are different types in objects, such as a int, string, lists, classes etc..

little hare
rustic gull
#

Ahhh

#

Makes sense

#

so typehinting actually does something in a code, i thought it was just there to let the person viewing the code understand what is what, just like a comment

#

thanks for the information guys

#

appreciate it!