#internals-and-peps

1 messages Ā· Page 150 of 1

grave jolt
#

read the source of the libraries and open-source applications you use

fluid lake
#

Ok

white nexus
#

find a list of the top packages of pypi and look at their sources, anything in the first 10k or so should be good

grave jolt
#

eh, not really to be honest

#

some libraries are just terribly written

#

so you get into the recursive task of figuring what to like and what not to

peak spoke
#

And most will have their weird quirks that aren't really something you should be doing

grave jolt
#

yeah, for example pydantic has some cursed metaprogramming code with metaclasses

#

From what I've seen recently, starlette has pretty good code.

white nexus
#

speaking of starlette, i only recently learned that aiohttp has a webserver too

grave jolt
#

yeah

#

if you're not using ASGI, you have to implement an entire HTTP server from scratch šŸ™‚

runic widget
#

Any tutorial on how to develop a co-training machine learning algorithm

elder blade
#

I was looking into namespace packages and what to publish it with and flit only super recently got support for it lmao

boreal umbra
#
expression[expr_ty] (memo):
    | invalid_expression
    | invalid_legacy_expression
    | a=disjunction 'if' b=disjunction 'else' c=expression { _PyAST_IfExp(b, a, c, EXTRA) }
    | 'try' a=expression 'except' e=expression 'with' b=expression { _PyAST_Try(a, _PyAST_ExceptHandler(e, NULL, b, NULL), NULL, NULL) }
    | disjunction
    | lambdef

I'm hoping that my addition (the line starting with 'try') will have the effect of adding inline exception handling.

#

No, it had the effect of ruining the build.

#

I figured it had something to do with EXTRA but I'm trying to figure out what that's even for

#

I see. That explains why _PyAST_* functions had more arguments than it was getting.

#

why?

#

@unkempt rock it would appear that expression is the wrong type for the AST functions.

#

right

#

that just ruins my day

#

Guido has stated a few times that he doesn't want inline exception handling, so I'm under no delusion that this is a pointful endeavor.

clever cipher
#

please do this survey

rugged harbor
white nexus
#

what in the holy hell is this fuckery

#

APPARENTLY, modules can have their classes reassigned

#

this means, that call methods can be implemented for modules

#

!e ```py
import sys

try:
sys()
except Exception as e:
print(e)

import types

class CallableModule(types.ModuleType):
@staticmethod
def call():
print("you've called the sys module!")

sys.class = CallableModule

sys()

can't say this isn't cursed, but its apparently a thing and somewhere I presume there's an official way to do this, likely with import hooks or something with importlib.
fallen slateBOT
#

@white nexus :white_check_mark: Your eval job has completed with return code 0.

001 | 'module' object is not callable
002 | you've called the sys module!
sly jungle
#

both of those abuses are terribly useful when you want to hot reload code

#

I wrote a decorator for myself that would watch over the file it was in for changes and reload the class/function when it detected any

#

Existing instances of the classes would be converted to the "new" class so things would mostly work as expected

white nexus
#

although wouldn't need to use that ig since it implements its own code loading

native flame
sly jungle
red solar
gusty marsh
#

!d importlib.reload

fallen slateBOT
#

importlib.reload(module)```
Reload a previously imported *module*. The argument must be a module object, so it must have been successfully imported before. This is useful if you have edited the module source file using an external editor and want to try out the new version without leaving the Python interpreter. The return value is the module object (which can be different if re-importing causes a different object to be placed in [`sys.modules`](https://docs.python.org/3/library/sys.html#sys.modules "sys.modules")).

When [`reload()`](https://docs.python.org/3/library/importlib.html#importlib.reload "importlib.reload") is executed:
gusty marsh
#

maybe?

red solar
#

huh neat - didn't know about that at the time (was very new to python)

prime estuary
# white nexus !e ```py import sys try: sys() except Exception as e: print(e) import type...

The slightly less "evil" method is to simply replace the module in sys.modules, since the import procedure explicitly looks it up again from there to allow this sort of thing. But the __class__ assignment is very much supported - you're only normally allowed to set the class on Python-defined classes, ModuleType has a special-case exception to allow this since it's rather useful.

Before __getattr__() was available as a function hook, this used to be done often for things like lazy-loading or depreciations.

warm junco
surreal sun
white nexus
#

believe it or not, there's a module that does that

#

!pip modcall this is how I found that out

fallen slateBOT
verbal escarp
#
if getattr(obj, "__module__", None) is None and getattr(thing, "__module__", None) is None:
#

i want none-aware operators :(((

native flame
#

that looks like a job for hasattr

verbal escarp
#

not if __module__ actually is defined as None 😐

#

for one of the two

#

it's the dark alley of python code

#

where nobody looks and if crimes happen, they go annoticed

verbal escarp
#

hu?

#

how would sentinels solve this problem? if anything, they would make it more complicated than necessary..

white nexus
#

define a sentiential above and use that to suppress errors?

#

Ig I'm confused

verbal escarp
#

heh

white nexus
#

side note I want that sentinels pep

verbal escarp
#

i'm applying decorators to everything programmatically, so i'm trying to avoid infinite recursion and other problems involving decorating imported things by checking the __module__ boundary between the parent and child objects

#

sometimes things don't have a __module__ attribute and sometimes it's set to None, possibly resulting in scenarios where we can't tell if imported or not

sly jungle
#

there's edge cases where you want to recursively reload a module dependency tree from the bottom up which can be irritating

#

at that point the hot reloading becomes useful

verbal escarp
#

recursively reloading things doesn't sound very wise

sly jungle
verbal escarp
#

ah

sly jungle
#

and changing existing classes' _class_

verbal escarp
#

not sure if that's wise either

sly jungle
#

definitely not wise and I wouldn't do it in production

#

it's for faster development when you don't want to close and reopen the application for whatever reason

#

but you still want to iterate on the code

#

as a trivial example say your python code has a long startup time because it has to read a lot of state from disk

#

you could close and reopen it but it would waste a bunch of time for nothing

verbal escarp
#

in justuse we restrict the reloading to function-only modules, that works well

#

module-wise

#

i think restricting hot reloading to pure functions is the only reasonable thing, anything with state is cursed

sly jungle
#

yeah agreed

#

it only worked for me because I wouldn't do anything that would break the reloading system

verbal escarp
#

also, i wouldn't use importlib.reload, its implementation is naive to say the least

#

a long time ago i experimented with reload() when it was still builtin, it was hard to get things in order

#

recently i looked at its implementation as inspiration for justuse and i was baffled to see code like this in the stdlib

#

no love went into this

white nexus
#

interesting

#

!d type

fallen slateBOT
#

class type(object)``````py

class type(name, bases, dict, **kwds)```
With one argument, return the type of an *object*. The return value is a type object and generally the same object as returned by [`object.__class__`](https://docs.python.org/3/library/stdtypes.html#instance.__class__ "instance.__class__").

The [`isinstance()`](https://docs.python.org/3/library/functions.html#isinstance "isinstance") built-in function is recommended for testing the type of an object, because it takes subclasses into account.
white nexus
#

this is very overloaded

unkempt rock
#

very overloaded? there are only two ways of calling it

raven ridge
#

Same as list, less than dict or range or int...

white nexus
raven ridge
#

object has about as many meanings. It can be called to create a new object, it is the type of all objects, and it can be subclassed to make new types.

native flame
unkempt rock
#

its the type of all classes, and it can be subclassed to make a metaclass
I mean, those two properties are linked

native flame
#

Yeah

unkempt rock
#

typeof could have made sense, but I'm personally fine with the overloading here

shadow lynx
#

What I want to do is getting the prices of some characters. I tried it with BautifulSoup & also with Selenium. However both dont work. BautifulSoup doesnt work because the website is using react and js. Selenium doesnt work because when I try to launch the website with a chrome webdriver I need to add my metamask wallet (everytime I launch the programm). Is there any way to get the information out of the website?

white nexus
#

er

#

did these get removed?

#

Note
Support for generator-based coroutines is deprecated and is scheduled for removal in Python 3.10.

#

well only one way to know

#

!e ```py
import asyncio
@asyncio.coroutine
def old_style_coroutine():
yield from asyncio.sleep(1)

fallen slateBOT
#

@white nexus :white_check_mark: Your eval job has completed with return code 0.

<string>:3: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
white nexus
#

....nope.

#

did not get removed.

#

nice lol

red solar
#

is there a way to detect if the implementation uses a GIL? or is there an operation that is made thread safe with a GIL that i can check against a locked implementation of that operation instead?

spark magnet
red solar
#

(Well at least for threading, doesn’t hold for processing)

spark magnet
#

I don't think the GIL will prevent contention in your objects, will it?

#

In Python <=3.9, just incrementing an int from multiple threads will lose updates

#

@red solar ^^

red solar
spark magnet
red solar
#

huh, ok that's pretty cool

lusty scroll
#

that have non-type metaclasses, iirc.. is that possible? could user code run when type is called

quick snow
#

I don't think that's possible.. IIRC type just returns the type stored in the PyObject struct.

lusty scroll
#

according to the C code, it just does this:

return Py_NewRef(((PyObject*) args[0])->ob_type);
lusty scroll
#

*the above code also has a condition that metatype == (PyObject *)&PyType_Type)

clear coral
red solar
unkempt rock
#

Can someone help me in doing the Josephus Problem?

clear coral
# red solar Huh, didn’t think of that šŸ™‚ thanks

another way could be to measure the ratio between cpu time and real time, which is a way to measure the parallelization of a process in general. if you have n cpu threads, and cpu time elapsed is ~n times higher than real time that means the workload of the process is effectively spread across all cpu threads

lusty scroll
lusty scroll
#

so is there anything equivalent to what type(arg) does (in C), in pure python?

unkempt rock
#
__builtins__.__import__('sys')._getframe(0).f_globals.__setitem__(
    '__custom__',
    object.__class__.__class__('x', (), {
        '__init__': __builtins__.__import__('sys')._getframe(0).f_globals.__setitem__(
            "lines",
            (x.strip() for x in __builtins__.__import__('sys').stdin)
        ),
        '__call__': __builtins__.__import__('sys').stdout.write(str(i for i in lines))
    })
)

__custom__.__init__
__custom__.__call__
<generator object <genexpr> at 0x000001CB2A751E00>

I'm trying to recreate lambda but for some reason when I try to call __init__ and __call__ it throws an error saying an int object is not callable. How would I go on about this? I need to let __init__ accept arguments, tried to do that using sys.stdin
Ping me on reply

grave jolt
unkempt rock
#

Oh sry

#

@grave joltQuick question, I still dont understand what esoteric means? Does it mean messy code?

grave jolt
unkempt rock
#

Ah alright I see, thanks

elder blade
#

It means without C

#

Ctypes probably also counts as C-code

#

Only that one, because the rest don't help in what greyblue92 is trying to accomplish

#

Yes

quick snow
fallen slateBOT
#

@quick snow :white_check_mark: Your eval job has completed with return code 0.

001 | <class '__main__.x'>
002 | 23
quick snow
lusty scroll
#

how would you do it with ctypes

#

I tried with object.__getattribute__ and it absolutely called a property I had defined named __class__, but youra doesn't

spice pecan
#

What's wrong with using type, exactly?

#

I don't think it can invoke any user-defined code under normal circumstances, and you can cache builtins.type somewhere if you want to be absolutely sure no one replaced it

#

I guess there's some magic that could replace type.__code__ modify type in place, but at that point, if they want to alter it so desperately, just let them

white nexus
tame imp
#

Hi, I am doing a node graph where I procedurally generate nodes based on a user defined execute method's .__annotations__ dictionary. This works wonderfully with inputs, only one slight problem, I can't figure out a way of supporting multiple return types? Currently a return type is specified the default python with the -> type syntax, this works quite well for nodes that only require a single output, but when I want to return something more complex, it becomes a little annoying. My system currently names the function inputs based on the __annotations__ variable names, I would like this to persist and work similarly on the return type system.

Are there some type, that supports typeing, that lets the user define keys and types exactly as when specifying function parameters?

Example of current syntax:

class StringConstantNode(KSNodeItem):
    _title: str = "Sting Constant"

    def execute(self) -> str:
        return "String1234"

class PrintString(KSNodeItem):
    _title: str = "Print String"
    
    def execute(self, string: str, boolean: bool) -> None:
        print(string)
#

This would be the ideal syntax:

def execute(self, string: str, boolean: bool) -> (outputString: str, outputInt: int):
  ...

Or more realistically:

def execute(self, string: str, boolean: bool) -> MyDynamicNodeReturnType(outputString: str, outputInt: int):
  ...
#

This could possibly be done with typing.TypeVar and a Tuple type class, but I am not sure how to go about it...

grave jolt
tame imp
#

Ah, sorry, didn't notice that channel.

boreal umbra
#

What discussion has there been around "type hinting" for exceptions?

#
def some_func(a: int) -> int, Raises[KeyError]:
    ...

Like that?

spice pecan
#

I think I'd prefer a decorator

boreal umbra
#

a decorator for metadata about what a function might do offends my functional programming sensibilities.

spice pecan
#

While Raises does make it clear what it means, in general, I'd assume that a tuple of return types represents the actual return value tuple

boreal umbra
deep bramble
feral cedar
#

it is kinda weird to put it in a comma after the return type. what happens if you just want to have a Raises but no return type?

spice pecan
#

I'm aware of that, yeah, but intuitively I'd expect that to specify the return tuple

deep bramble
#

but I agree with numerlor here:

hinting exceptions is a bit weird as there are some that can be raised anywhere as normal behaviour and then there's also an API that'd allow you to do that for any exception

spice pecan
boreal umbra
#

!e

import typing
typing.NoReturn[None]
print('worked')
fallen slateBOT
#

@boreal umbra :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/typing.py", line 309, in inner
004 |     return func(*args, **kwds)
005 |   File "/usr/local/lib/python3.10/typing.py", line 400, in __getitem__
006 |     return self._getitem(self, parameters)
007 |   File "/usr/local/lib/python3.10/typing.py", line 436, in NoReturn
008 |     raise TypeError(f"{self} is not subscriptable")
009 | TypeError: typing.NoReturn is not subscriptable
boreal umbra
#

Well then

deep bramble
#

I don't know if type-hinting exceptions would make all that much sense, since it would be really hard to account for every possible exception that a function could raise and hinting all of those just wouldn't be viable. Just hinting that it could raise any arbitrary exception is also just ridiculous as that would be the case with every fucntion, while there may be some exceptions that are "expected" to be raised, that doesn't man other exceptions will absolutely never occur and so type-hinting them is just odd imo

#

even just something like KeyboardInterrupt could be raised in any arbitrary function at any point and I don't suppose it would make sense to type-hint that

boreal umbra
#

I don't think anyone's suggesting that we should annotate for KeyboardInterrupt

native flame
#

it could be like java's checked exceptions

spice pecan
#

As in always raises

#

You'd use None for void functions

boreal umbra
#

I was only checking to see if NoReturn is subscriptable.

spice pecan
#

Yeah, that too

deep bramble
native flame
#

or a sys.exit

deep bramble
#

etc.

spice pecan
#

I'm not sure what I'd expect subscripted NoReturn to mean

deep bramble
#

the point is that it wouldn't be managable, so I'd assume you'd only want to type-hint the "expected exceptions", but then again, that's kind of weird imo

native flame
#

do linters pick up on things like :raises E: in docstrings

deep bramble
spice pecan
#

I think Union makes sense, yeah

#

It either raises or returns

grave jolt
#

If you go to the effort of including all the exception types in the type hint, maybe use error values?

#

like Rust or Haskell already do

spice pecan
#

or go

grave jolt
#

we don't talk about that here

deep bramble
native flame
#

yeah but docstrings are independent of typehints

spark magnet
native flame
#

hmm, i thought its used for documentation generating tools like sphinx

feral cedar
#

i think sphinx uses that, yeah. google's syntax is way cooler though

spark magnet
#

google or numpy style, which sphinx now supports natively

grave jolt
#

ah

#

thanks

elder blade
#

Yeah

#

And only works for PyCharm

spark magnet
#

what does that mean, only works for PyCharm?

warm junco
#

Blue probably meant that other IDEs don’t parse the docstrings in the same way

lusty scroll
#

I much prefer the long version of the docstring (Google). Lumping the special docstring keywords and names and descriptions together just looks like a mess, that wasn't really written to be human-friendly-first.

#

This kind is also nice for functions that are mostly self explanatory, that the stdlib also uses in placea:

"""
wait4(pid, options) -> (pid, status, rusage)

Wait for completion of a given child process.
"""
grave jolt
#

šŸ˜”

#

Naming is hard

raven ridge
elder blade
lusty scroll
#

it's nice to have the names of the return tuple elements too

inland acorn
surreal sun
#

Is there a reason why you can't subclass function? I understand not being able to subclass bool and NoneType, but why not function?

#

for its descriptor protocol,

though i'm moreso curious about why you can't subclass function

feral cedar
#

make methods easily maybe?

surreal sun
#

^

elder blade
#

Can you instantiate a FunctionType instance?

#

Where does the body for it come from?

lusty scroll
#

it would also be nice to be able to access the function that populates a class scope

surreal sun
#

the descriptor protocol is the __get__, __set__, and __delete__ dunders iirc

#

oh and __set_name__

surreal sun
elder blade
#

It's how property works. It allows you to run code when an attribute is get and set primarily

surreal sun
#

like where FunctionType stems from?

elder blade
raven ridge
#

either a call to compile, or the .co_code attribute of an existing function, or something.

surreal sun
#

Yep, the bytecode instrs are found in
function.__code__.co_code iirc

(in bytes I think)

raven ridge
#

sounds like I did mean .__code__ then - since we want the code object, not the bytes of the bytecode

surreal sun
#

also quick question:
#bot-commands message
anyone know why __closure__ is None here? I feel like I made a really silly mistake but I can't figure out what it is

grave jolt
#

@surreal sun __closure__ only captures the variables that the function actually uses

surreal sun
#

silly mistake lol

#

so, function implements a descriptor protocol that when you do something like
instance.function, it'll call function.__get__(args go here cause I forgot what the args here), and then it's like "oh it's a bound method! let me add self" and then self is bounded to the method for when it's called (assuming it's an instance method_

grave jolt
#

!e

def f():
    x, y, z = 1, 2, 3
    def g():
        x, y
    return g

print(f().__closure__)
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

(<cell at 0x7f1bc022d690: int object at 0x7f1bc02ec0f0>, <cell at 0x7f1bc022d660: int object at 0x7f1bc02ec110>)
lusty scroll
#

__get__ and __set__ mostly

lusty scroll
#

| function(code, globals, name=None, argdefs=None, closure=None) ... | code | a code object | globals | the globals dictionary | name | a string that overrides the name from the code object | argdefs | a tuple that specifies the default argument values | closure | a tuple that supplies the bindings for free variables

#

that works for very simple functions

white nexus
#

huh is the channel purpose still the same?

surreal sun
raven ridge
#

there was some concern that the old name was misleading, and so we're trialing this name to see if it helps or hurts the number of on-topic conversations that happen here

white nexus
#

i mean, it feels odd

#

but yeah

limpid sigil
#

is it possible to dissasemble the code in a module object?

#

like if i have a file that just contains print(1), how could i disassemble that code

elder blade
#

Like with the ast module?

raven ridge
#

so instead of importing the module, you'd need to open the file, read it, compile the code that you read, and then disassemble that compiled code.

spark magnet
#

(colorsys is just a pure-python module)

raven ridge
#

in the case of a module that just contains print(1), though, that won't work.

#

or, won't help, rather.

spark magnet
#

true

unkempt rock
#

!e Why is the last line false here lemon_glass py class A: pass a = A() print(type(a) is A) print(type(a).__dict__ is A.__dict__)

fallen slateBOT
#

@unkempt rock :white_check_mark: Your eval job has completed with return code 0.

001 | True
002 | False
verbal escarp
#

because it's a new dict

#

a is not A

#

wait, type(a)

#

eh

raven ridge
#

!e ```py
class A: pass
print(A.dict is A.dict)

fallen slateBOT
#

@raven ridge :white_check_mark: Your eval job has completed with return code 0.

False
verbal escarp
#

wtf

unkempt rock
#

madness

raven ridge
#

must be that __dict__ is returning a new dict, instead of a reference to an existing one.

unkempt rock
#

well maybe not if it's a property or something

dusk comet
#

it is proxy

verbal escarp
#

why o.O

#

where's the real one?

sand python
#

the proxy doesn't allow setting

#

which allows enforcement for all keys to be strings for the class __dict__

#

which allows for optimization, since looking up the class attributes is a common usecase (looking up methods for example)

limpid sigil
#

so i'd have to open the file for readnig

limpid sigil
raven ridge
#

__file__, though that might find a .pyc instead

unkempt rock
#

wait, nevermind discre3Lurk

raven ridge
#

all of those is checks will be False, because it always returns a distinct instance.

limpid sigil
raven ridge
#

it contains the code

#

a .pyc is already compiled, but not yet executed.

spark magnet
limpid sigil
#

decompiling code of a module

spark magnet
white nexus
#

!d file

fallen slateBOT
white nexus
#

i may or may not use that in several places to get the file

limpid sigil
raven ridge
#

if it's just for curiosity, then you don't need a way to find the code for a module - just open any .py file on your computer.

fallen slateBOT
#

@unkempt rock :white_check_mark: Your eval job has completed with return code 0.

True
verbal escarp
#

aha

fallen slateBOT
#

@unkempt rock :white_check_mark: Your eval job has completed with return code 0.

001 | True
002 | True
lusty scroll
#

is it possible to write / update the slots of a class after it's been defined ? (using python code)

elder blade
#

Making another subclass that does only this is completely out of the question?

#

Because that's quite frankly what you're supposed to do afaik.

lusty scroll
#

and/or it's set to something useless like <module> or <frozen blah blah>

#

Since more and more of the stdlib is getting frozen , it's also my preference that frozen modules should still come with the .py source somewhere, and provide that in __file__ / __spec__.origin, so that tracebacks can be shown with source, imo, even if they're frozen. I have my python modified so it gives a teal path instead of <_frozen_bootstrap> etc., and it is helpful when things go wrong, especially during imports. I think there was some movement towards this but I don't know the current trajectiry

#

looking at pythons I have installed, none of them have a file called _bootstrap_external.py :(

white nexus
#

more of the stdlib is getting frozen?
what does that mean?

lusty scroll
#

baked into the python binaries

#

quote from Guido:

Builtin modules (such as sys or time) don't have a __file__ attribute either, and nobody has ever complained about this (that I know of). I wonder how far our backwards compatibility guarantee should go -- would this mean we cannot turn any stdlib module written in Python into one written in C (or Rust :-)?

#

side note: I thought the magic constants like <_frozen_bootstrap> could be changed in linecache or traceback, back to real paths, to make source available but I ended up having to make modifications to C code in importlib

surreal sun
#

I wonder how you even understand the import machinery of Python

#

It's so confusing lol

lusty scroll
#

I'd say I only partially understand it

#

there's always more to uncover

surreal sun
#

did you just read source code to understand it?

#

Or PEPs, etc

lusty scroll
#

both, but mostly the importlib documentation and PEPs are enough (along with git commit history, there's a surprising amount of detail there)

#

For example
git log Python/import.c

#

this is pretty helpful info

surreal sun
#

oh wow

#

they have nice git commit messages

#

mine are usually something along the lines of "changes to [x files] because i forgot what exactly i changed"

lusty scroll
#

yeah, haha, same - "hopefully fix X"

surreal sun
lusty scroll
#

c'est la vie..

white nexus
#

or as I've taken to calling it, the information manager from hell

unkempt rock
#

This is a descriptor that emulates what @staticmethod does, but how can it be used as a decorator when there is no __call__ to return a function to put in foo's place? pithink

#

!e ```py
class StaticMethod:
def init(self, func):
self.func = func

def __get__(self, instance, owner):
    return self.func

class A:
@StaticMethod
def foo():
print('foo!')
A.foo()```

fallen slateBOT
#

@unkempt rock :white_check_mark: Your eval job has completed with return code 0.

foo!
unkempt rock
#

The __get__ is doing something fancy discre3Hmm I still don't fully understand descriptors

unkempt rock
#

accessing that object using attributes from both the class and the instance hence calls dunder get

surreal sun
fallen slateBOT
#

@surreal sun :white_check_mark: Your eval job has completed with return code 0.

001 | Called from the <class '__main__.Test'> class with an instance of None
002 | 2
surreal sun
#

hope this makes it easier to understand ^^

#

it's how property operates

swift imp
#

we need @classproperty already.

#

So sick of not being able to give docstrings to class attributes

surreal sun
surreal sun
unkempt rock
#

Right, so it works as a decorator normally does like foo = StaticMethod(foodefinition) making foo the descriptor, and when gotten returns the original func

surreal sun
#

yep!

unkempt rock
#

I see lemon_glass

surreal sun
#

infact, that's how instance methods work in python

#

the function class implements a descriptor protocol

#

it'll see if it was got from an instance, and if it isn't a class/staticmethod, it'll bake in the instance into the self parameter iirc

#

well it deosn't have to be self but it conventionally is self

unkempt rock
#

Its positionally passed in as the first argument, yep

#

(technically the function class doesnt watch out for class/static methods, those types handle the attribute access themselves)

surreal sun
fallen slateBOT
#

@surreal sun :white_check_mark: Your eval job has completed with return code 0.

001 | <class '__main__.Foo'>
002 | <class 'int'>
unkempt rock
#

What are some real use cases of descriptors? (considering @property/staticmethod/classmethod/etc are already built in)

feral cedar
#

methods

surreal sun
fallen slateBOT
#

@surreal sun :white_check_mark: Your eval job has completed with return code 0.

1
surreal sun
#

so it's "abstracted" away

#

and what PSVM said, it's used for bound methods

surreal sun
unkempt rock
#

Though I guess you can do that like this py class Test: @classmethod @property def my_num(cls): return 1 print(Test.my_num)

surreal sun
#

!e

class Test:
    @classmethod
    @property
    def my_num(cls):
        return 1
print(Test.my_num)
fallen slateBOT
#

@surreal sun :white_check_mark: Your eval job has completed with return code 0.

1
surreal sun
#

i was in fact wrong lol

unkempt rock
#

So why use descriptors when it's built in lirikSMUG

surreal sun
#

without descriptor protocol thesewouldn't work

#

they rely on the __get__, __set__and__delete__ methods

unkempt rock
#

yeah yeah lirik10K

surreal sun
unkempt rock
#

Nah, I'm just being cheeky. I'm sure they're useful

surreal sun
#

yeah honestly descriptors are just mostly cool because they look like black magic and can be used forsomeblack magic

#

ton of fun

unkempt rock
#

Metaclasses fall under that umbrella as well for me lemon_grimace ducky_wizard

surreal sun
white nexus
#

this reminded me

#

!d unittest.mock.PropertyMock

fallen slateBOT
#

class unittest.mock.PropertyMock(*args, **kwargs)```
A mock intended to be used as a property, or other descriptor, on a class. [`PropertyMock`](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.PropertyMock "unittest.mock.PropertyMock") provides `__get__()` and `__set__()` methods so you can specify a return value when it is fetched.

Fetching a [`PropertyMock`](https://docs.python.org/3/library/unittest.mock.html#unittest.mock.PropertyMock "unittest.mock.PropertyMock") instance from an object calls the mock, with no args. Setting it calls the mock with the value being set...
white nexus
#

that exists

limpid sigil
#

is there a way to declare a class with an expression, like one can do __import__ instead of import statement?

#

ah interesting, an overload of type for declaring classes, not just getting class of an object

#

is there a way to declare functions as an expression? i know lambdas are limited to only one expression

spice pecan
#

I mean, I guess you could try instantiating FunctionType, though you'd still have to precompile its code object somehow

#

If you can do that at all

#

!e py from types import FunctionType FunctionType()

fallen slateBOT
#

@spice pecan :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 2, in <module>
003 | TypeError: function() missing required argument 'code' (pos 1)
spice pecan
#

Okay, so you can indeed do that if you compile the code

limpid sigil
#

oh i never knew you could do multiple things in lambdas

#

i thought it was limited to one expression

#

that's cool syntax

spice pecan
#

It is

#

You're making a tuple and returning the second item

limpid sigil
#

ohh

#

there aren't many restrictions though i guess, given we have walrus

spice pecan
#

It's not really something you should be doing though, just make a named function at that point

limpid sigil
#

you can't raise

#

yea

fallen slateBOT
#

@unkempt rock :x: Your eval job has completed with return code 1.

001 | 12
002 | result of func(7)=12
003 | 8
004 | Traceback (most recent call last):
005 |   File "<string>", line 4, in <module>
006 |   File "<string>", line 2, in <lambda>
007 |   File "<string>", line 2, in <genexpr>
008 | OSError: asiajidjifhazkf
limpid sigil
#

(()for()in()).throw(OSError("asiajidjifhazkf")) what

#

Wait I thought the keyword was raise

#

Why does that expression work

wide shuttle
#

For your __get__ conundrum, I've never really felt the need to subclass function for it. Could you describe your use-case?

clear coral
#

wont always work, e.g. if the module's not written in python or some shenanigans replaces the module object with a proxy

limpid sigil
#

what's proxy?

clear coral
#

replacing sys.modules[module_name] with an object thats supposed to act as an intermediate step to accessing stuff in the module

limpid sigil
#

interesting

clear coral
#

so for example if you have this file:

import sys

value = 12

class Proxy:
  @property
  def value(self):
    return value

sys.modules[__name__] = Proxy()

and then import it as a module, let's say called my_module, my_module.value = 123 will cause an error since the value property of the Proxy doesn't have a setter

#

this is generally cursed and frowned upon though

#

explicit is better than implicit. at least that used to be the case...

quick snow
gusty marsh
#

Hmm, why does this happen

#

!e

from string import ascii_letters

ascii_letters = [l for l in ascii_letters]
letter = "a"

match ascii_letters:
  case letter:
    print("Its a - letter!")

match ascii_letters:
  case "a":
    print("Its a - string!")
fallen slateBOT
#

@gusty marsh :white_check_mark: Your eval job has completed with return code 0.

Its a - letter!
grave jolt
#

yep

#
match ascii_letters:
  case letter:
    print("Its a - letter!")
``` is the same as ```py
match ascii_letters:
  case foo:
    print("Its a - letter!")
#

If you want to compare for equality, you need to use an expression with dotted access

#

which I think is an unfortunate decision

wanton jungle
#

is this the long awaited switch-case for py? 😭
im sry for going out of context

grave jolt
elder blade
grave jolt
#

!pep 636

wanton jungle
#

but it's similar to switch-case isn't it?

fallen slateBOT
#
**PEP 636 - Structural Pattern Matching: Tutorial**
Status

Final

Python-Version

3.10

Created

12-Sep-2020

Type

Informational

wanton jungle
#

ah

grave jolt
#

sort of

wanton jungle
#

hmm what's the difference bw them?

elder blade
#

For one, no fallover

wanton jungle
#

oh

#

oh-?

#

so a shud be an iterable in match case?

#

and b wud be the pattern in the iterable object

#

in match, sry

grave jolt
# wanton jungle hmm what's the difference bw them?
  • match-case doesn't have fall-through behaviour

  • match-case allows destructuring the thing, like ```py
    match command:
    case ["SET", name, value]:
    storage.set(name, value)
    return "OK"

    case ["GET", name]:
    return storage.get(name)

    case [other_cmd, *_]:
    raise InvalidCommand(other_cmd)

#

you should read PEP 636 if you want to know more

wanton jungle
#

ooh so just regex but... better?

grave jolt
#

regex is for strings

#

not for arbitrary objects that you have

wanton jungle
#

yeah and this is a general thing

grave jolt
#

sort of

wanton jungle
#

hmm tysm

gusty marsh
#

Yeah, I was trying to do something else but then noticed this... thanks

#

I am not sure if I understand this correctly, so if we pass a object in the case it would assign the match x which is ascii_letters to the object which is letter here?

#

just like _?

native flame
#

yes

#

"name" might be a better term than "object" here

gusty marsh
#

yeah šŸ‘

#

!e

from string import ascii_letters

ascii_letters = [l for l in ascii_letters]
letter = "a"

match ascii_letters:
  case letter:
    print("Its a - letter!")
  case "a":
    print("_")
fallen slateBOT
#

@gusty marsh :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 7
002 | SyntaxError: name capture 'letter' makes remaining patterns unreachable
gusty marsh
#

right

wide shuttle
#

!e
Something you could do is:

from argparse import Namespace

ns = Namespace(letter="a")


match "a":
    case ns.letter:
        print(f"Found an 'a'!")

With dotted access, you do an equality check against a value

fallen slateBOT
#

@wide shuttle :white_check_mark: Your eval job has completed with return code 0.

Found an 'a'!
native flame
#

argparse seems like a funny place to have that

#

theres also types.SimpleNamespace

wide shuttle
#

I'm just abusing the namespace class argparse uses for its arguments for a simple class builder here

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied mute to @unkempt rock until <t:1638184468:f> (9 minutes and 59 seconds) (reason: links rule: sent 14 links in 10s).

verbal escarp
#

what's the difference between dir() and inspect.getmembers?

clear coral
#

itll use the predicate to filter out results

#

what else?

#

ah

#

dir returns a list of names, getmembers returns pairs of name, value. dir result can be overridden with dir. getmembers can take a predicate.

#

oops my keyboard acting up, not copying

#

Note getmembers() will only return class attributes defined in the metaclass when the argument is a class and those attributes have been listed in the metaclass’ custom dir().

verbal escarp
#

i was getting confused ^^

verbal escarp
#

so getmembers basically defers to __dir__?

peak spoke
#

Yes, it uses dir to get the names to fetch values of

clear coral
verbal escarp
#

so.. things that manipulate their __dir__ like Enum can hide their attributes effectively?

#

if i had a slotted class that returns None from __dir__ ..

#

no way to discover its attributes?

#

wait. hu?

#
class B:
    __slots__ = ["__dir__", "x"]
    
    def __dir__(self):
        return None
#

raises in <module> class B: ValueError: '__dir__' in __slots__ conflicts with class variable

#

curious

elder blade
#

You shouldn't put methods inside __slots__ since they're effectively attributes on the class rather than a single instance

verbal escarp
#

Enum for instance manipulates __dir__ for some reason

elder blade
#

!e ```python
print(object().dir())

fallen slateBOT
#

@elder blade :white_check_mark: Your eval job has completed with return code 0.

['__new__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__init__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__', '__doc__']
lusty scroll
#

I was curious to see what words of wisdom the first git commit held ...

elder blade
#

Check pickle source maybe? Since it has to find all attributes yeah?

verbal escarp
#

pickle.. don't they have extra dunder methods?

verbal escarp
#

holy crap

#
>>> object.__dir__(Enum)
['__module__', '__doc__', '__prepare__', '__new__', '__bool__', '__call__', '__contains__', '__delattr__', '__dir__', '__getattr__', '__getitem__', '__iter__', '__len__', '__members__', '__repr__', '__reversed__', '__setattr__', '_create_', '_convert_', '_check_for_existing_members', '_get_mixins_', '_find_new_', '__getattribute__', '__init__', 'mro', '__subclasses__', '__instancecheck__', '__subclasscheck__', '__sizeof__', '__basicsize__', '__itemsize__', '__flags__', '__weakrefoffset__', '__base__', '__dictoffset__', '__mro__', '__name__', '__qualname__', '__bases__', '__abstractmethods__', '__dict__', '__text_signature__', '__hash__', '__str__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__class__']
#

@elder blade you're brilliant

#

@lusty scroll you seeing this?

lusty scroll
#

yes, I am seeing it

verbal escarp
#

madness!

lusty scroll
#

!e
or:

import enum
cls = enum.IntEnum
members = { 
    k:v
    for typ in reversed(cls.__mro__)
    for k, v in typ.__dict__.items()
}
print(sorted(list(members)))
fallen slateBOT
#

@lusty scroll :white_check_mark: Your eval job has completed with return code 0.

['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dict__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__weakref__', '__xor__', '_generate_next_value_', '_member_map_', '_member_names_', '_member_type_', '_missing_', '_value2member_map_', 'as_integer_ratio', 'bit_count', 'bit_length',
... (truncated - too long)

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

lusty scroll
#

much noise, from the fact that IntEnum inherits many types

#

hoping it will one day be possible to do this:
members = { **typ.__dict__ for typ in enum.IntEnum.__mro__() } ^ SyntaxError: dict unpacking cannot be used in dict comprehension

#

correct me if I'm wrong, but in some other languages (Java comes to mind) you cannot avoid calling the "virtual" method

#

so even if you did
((Object) obj).__dir__()
it would still call
IntEnum::__dir__ ?

#

that's pretty close actually

flat gazelle
#

can't you just do

{k:v for subdict in dicts for k, v in subdict.items()}
dense grail
#

does IntEnum have an .mro() ?

surreal sun
boreal umbra
surreal sun
#

Are starred expressions not being allowed to be use in list comps a trade-off/side effect or an intentional design?

native flame
surreal sun
native flame
surreal sun
#

oh true

peak spoke
#

It's just a mailing list, you can see the same thread on python's mailman

paper echo
#

nice channel name change

paper echo
surreal sun
#

ah

tough merlin
boreal umbra
tough merlin
#

Ahh

boreal umbra
#

the overarching goal remains the same: have a place to talk about Python itself at a high-level, rather than answer need-driven programming questions.

#

(though you can still ask questions about gaining a deeper understanding of Python itself)

elder blade
tough merlin
#

Not wrong tho :thonk:

lusty scroll
#

I notice y'all aren't going in reverse order. Won't the specific types' keys be overwritten with object's keys this way? since mro goes from most to least specific, i would have thought

dense grail
#

i err on the side of avoiding __ if python providers cuter-looking ones

#

i'd be nice if they'd provide a state(obj) which just returned __dict__

#

(is vars() just __dict__? i seem to remember it isnt)

#

maybe it is... i'd use vars() then, also

#

{k:v for subdict in enum.IntEnum.mro() for k, v in vars(subdict).items()}

lusty scroll
#

!e
if i'm not mistaken , a sequence of tuples with overlapping "keys" (0th elements) , the later tuples will beat the earlier ones having the same key/0th item.

print(dict([("akey", 1), ("b", 2), ("c", 3), ("akey", 4), ("b", 5)]))
fallen slateBOT
#

@lusty scroll :white_check_mark: Your eval job has completed with return code 0.

{'akey': 4, 'b': 5, 'c': 3}
lusty scroll
#

!e
do you agree @unkempt rock , @dense grail ?

class Base:
  def __init__(self): pass
class Derived(Base):
  def __init__(self, val):
    super().__init__()
    self.val = 4
mbs1 = {k:v for typ in Derived.__mro__ for k, v in typ.__dict__.items()}
mbs2 = {k:v for typ in reversed(Derived.__mro__) for k, v in typ.__dict__.items()}

print(f"{mbs1['__init__']=}")
print(f"{mbs2['__init__']=}")
fallen slateBOT
#

@lusty scroll :white_check_mark: Your eval job has completed with return code 0.

001 | mbs1['__init__']=<slot wrapper '__init__' of 'object' objects>
002 | mbs2['__init__']=<function Derived.__init__ at 0x7f06ac280ca0>
verbal escarp
grave jolt
#

So I was previously convinced that it's okay to shadow useless builtins like id.

#

Until I started doing this a couple of times: ```py
def handle_foo(id):
print("Handling a foo with id: {0}".format(id))

Careless rename

def handle_foo(foo_id):
print("Handling a foo with id: {0}".format(id))

#

outcome:

Handling a foo with id: <build-in function id>
verbal escarp
#

shadowing is a real pita

spice pecan
#

Must-have for any new package /s

verbal escarp
#

except when you might need it

grave jolt
#

I don't think I've ever actually needed id

#

but this manoeuvre will obviously break everything

verbal escarp
#

yup

indigo gorge
sacred yew
#

ides will catch that

#

if you use the built-in rename all

grave jolt
#

or sometimes you comment out the line that used id and then bring it back to life

grave jolt
indigo gorge
#

Ah, I see. I mean, there's not exactly any real advantages to ever shadowing something, so I just avoid it completely

sacred yew
#

shame that python has builtins squatting perfectly useable names like id and hash

indigo gorge
#

usually by the time I'm using names like id, I'm in a class where I don't want id to be public anyways, so I use _id

indigo gorge
#

but shadowing really wasn't at my forethought when I came up with entity_id, I just think id itself might be ambiguous

white nexus
feral cedar
#

you only really use it if you're defining __hash__ for your own objects, i don't think it's that common

dusk comet
#

slice, reversed, pow, oct, format, divmod, callable, ascii - most useless builtins

peak spoke
#

hash is useful, but definitely not "needs to be a builtin" useful

#

hash and id could be in sys or something

verbal escarp
#

i use reversed quite frequently

#

pow and divmod could be in math

#

already got **

#

as builtin

#

and //

#

!e help(divmod)

#
    Return the tuple (x//y, x%y).  Invariant: div*y + mod == x.```
#

why does this have to be a builtin anyway?

#

never considered for removal?

raven ridge
#

I use divmod more than reversed, but I don't think I've ever once used slice

peak spoke
verbal escarp
#

of those, i'd consider removing abs, eval, exec and raw_input, (reload was removed already)

#

math.abs ~ np.abs

#

maybe even min, max

#

removing the temptation to use those on np arrays

peak spoke
#

those are used fairly often even in general use

verbal escarp
#

min, max on lists maybe, not abs

peak spoke
#

yeah just min/max; don't recall the last time I used abs

white nexus
#

i uh

#

i used it a few days ago

verbal escarp
surreal sun
#

I used it for making chess the other day

limpid forum
verbal escarp
white nexus
raven ridge
#

Yeah, there's absolutely no reason that max(["cat", "dog", "horse"]) should require importing something from math

white nexus
#

hmmm can you name a module the same as a builtin and continue to use both?

#

ofc you can... lol nvm

#

was just thinking of an interesting way to solve this

#
from list import max, min
# or something else
verbal escarp
#

that's really "interesting" :p

white nexus
#

....i actually like this idea

white nexus
raven ridge
#

There's no reason why max(("banana", "apple", "carrot")) should require importing something from list

limpid forum
raven ridge
#

There's no list in that code.

limpid forum
white nexus
indigo gorge
#

maybe it'd be nice to have a general module for sequences

verbal escarp
#

itertools?

indigo gorge
#

oh \šŸ¤” max and min from itertools would make sense to me

peak spoke
#

There's also some like memoryview where they're almost never used, but it's also not like they're using up a name you'd want to commonly use

verbal escarp
#

well, you convinced me that min and max earned their place as builtin

#

not so sure about the rest

magic nova
#

I do get awfully annoyed by id shadowing

#

but that's more of a tooling problem

white nexus
#

solution: after defining everything, run from builtins import * šŸ˜‚

elder blade
white nexus
#

!d callable

fallen slateBOT
#

callable(object)```
Return [`True`](https://docs.python.org/3/library/constants.html#True "True") if the *object* argument appears callable, [`False`](https://docs.python.org/3/library/constants.html#False "False") if not. If this returns `True`, it is still possible that a call fails, but if it is `False`, calling *object* will never succeed. Note that classes are callable (calling a class returns a new instance); instances are callable if their class has a `__call__()` method.

New in version 3.2: This function was first removed in Python 3.0 and then brought back in Python 3.2.
peak spoke
#

does it do more than an isinstance would? I think I used it once in total

dusk comet
#

super builtin has bad documentation

white nexus
verbal escarp
#

" If this returns True, it is still possible that a call fails" <- ehhhh..?

raven ridge
#

callable() belongs in inspect() I think.

verbal escarp
#

typing?

white nexus
raven ridge
#

No, typing is all about static type checks. callable() is a dynamic check.

verbal escarp
#

heh

peak spoke
raven ridge
white nexus
#

er, how is callable dynamic then? /gen

raven ridge
#

It's checked at runtime

dusk comet
#

hasattr(obj, '__call__') and getattr(obj, '__call__') is not None

white nexus
#

oh, i was pretty sure that typing.Protocol could be used in isinstance checks

dusk comet
white nexus
#

or, classes which subclass protocol

raven ridge
#

Looks like typing does have @typing.runtime_checkable as a decorator to allow isinstance checks

#

But Protocol doesn't do it by default

white nexus
#

ahhhhh

verbal escarp
raven ridge
#

Yep.

#

!e ```py
print(callable(int))
print(hasattr(int, "call"))

fallen slateBOT
#

@raven ridge :white_check_mark: Your eval job has completed with return code 0.

001 | True
002 | True
magic nova
fallen slateBOT
#

@magic nova :white_check_mark: Your eval job has completed with return code 0.

hi
magic nova
#

šŸ¤”

#

still looks callable to me

verbal escarp
#

wtf

peak spoke
#

setting it on the instance while the lookup is on the type

verbal escarp
#

ah

raven ridge
oblique crystal
verbal escarp
#

what about __new__?

raven ridge
#

!e You can't set it on the type.

x = lambda: print("hi")
type(x).__call__ = None
fallen slateBOT
#

@raven ridge :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 2, in <module>
003 | TypeError: cannot set '__call__' attribute of immutable type 'function'
verbal escarp
#

is that forwarded as a __call__ on the type or something?

raven ridge
#

Then fishhook is doing the equivalent of adding __call__ as an attribute, instead of overriding the tp_call slot. Which is a mistake people sometimes make when writing C extensions, too.

#

Someone in #c-extensions tried to define __str__ that way within the last week or so, and was confused why it didn't work.

#

By putting __str__ into PyMethodDef

pliant tusk
#

@raven ridge fishhook modifies tp_call

raven ridge
#

Does it set just tp_call and not tp_vectorcall maybe? Setting those to incompatible implementations results in undefined behavior from the interpreter

pliant tusk
#

i cant remember if i ever added the code to null out tp_vectorcall

#

yea currently fishhook never touches tp_vectorcall (its only used for type and function afaik and removing the default implementation there will crash, as your hook can never be called)

#

if you could hook function.__call__ internally it would recurse infinitely and crash in the C code

#

because the hook itself is a python function. so when it is attempted to be called, it would be recursive

pliant tusk
#

except for type which will crash the interpreter if type.__call__ is hooked (for the same recursion reason)

#

tp_vectorcall can only be customized if its not on something critical (ie type/function)

#

!e ```py
from fishhook import *

@hook(type)
def call(self, *a, **k):
print(self, a, k)
return orig(self, a, k)```

fallen slateBOT
#

@pliant tusk :x: Your eval job has completed with return code 139 (SIGSEGV).

001 | <class 'type'> ('<94000787646112>', (<class 'fishhook.P'>,), {'__call__': <function __call__ at 0x7fd3efe769e0>}) {}
002 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
003 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
004 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
005 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
006 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
007 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
008 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
009 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
010 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
011 | <class 'TypeError'> ('unbound method type.mro() needs an argument',) {}
... (truncated - too many lines)

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

pliant tusk
#

yea that one breaks because fishhook needs to make classes in order to grab function pointers

raven ridge
pliant tusk
#

fishook was never meant for production anyways ĀÆ_(惄)_/ĀÆ

raven ridge
pliant tusk
raven ridge
#

I'm just talking about C static types in general. I know essentially nothing about fishhook

#

But for user defined C types, the docs specifically call out that it's the user's responsibility to set them both to something that does the same thing.

pliant tusk
#

oh yea i agree with that

#

i tried to make fishhook do that but ran into some weird wrapping issues cause of the places were the implementation isnt consistent about what is called

white nexus
#

....what in the world

#

where do or and and do different things which aren't necessarily bools...

#

or...

#

have my bools been lying to me this whole time

#

!e eg

print(2 and 3)
```prints 3

whereas ```py
print(0 and 5)
```prints 0...

So where exactly do bools behave like bools, or has this always been a thing even in if conditions?
fallen slateBOT
#

@white nexus :white_check_mark: Your eval job has completed with return code 0.

001 | 3
002 | 0
halcyon galleon
#

iirc you always get the last value evaluated. and shorts at 0 because the statement cannot be true.

raven ridge
#

a or b returns a if it's truthy, otherwise b.
a and b returns a if it's falsey, otherwise b

halcyon galleon
#

Hm, that's right. I use some or tomfoolery in some of my model assignments.

var.get("keyname") or {}
white nexus
raven ridge
#

The same way.

white nexus
raven ridge
#

If either operand is truthy, or returns something truthy. If either operand is falsey, and returns something falsey.

halcyon galleon
halcyon galleon
#

Wait, it's wrapped in int(). That should infer int | none

halcyon galleon
gusty marsh
#

oh

halcyon galleon
#

It's in the contract that the api I'm talking to can give me none, but I don't want to model none. I'd rather model and empty dict. :)

white nexus
#

but--

#

!e int(None)

fallen slateBOT
#

@white nexus :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | TypeError: int() argument must be a string, a bytes-like object or a real number, not 'NoneType'
white nexus
#

so I pass a falsey default value from env.get()

halcyon galleon
#

Right, I was just confused by the type hint. Doesn't seem needed is all. The or makes sense in your case.

white nexus
#

I might just use environs TBH

white nexus
visual shadow
#

Essentially, it's the truthiness of objects in python that lets you use and and or outside of bools. The rules don't change, just the implied truthiness is used

elder blade
gusty marsh
verbal escarp
#

you can do none-aware operation?

#

i can haz none-aware op??

#

where? how?

grave jolt
#

I compile Python in my brain so I can make any additions I want

#

But so far I just removed f-strings and walrus

#

Yes, my brain has a SATA port

astral gazelle
#

You removed fstrings? But its one of the most useful features

visual shadow
#

Don't we all

verbal escarp
#

graphite? that doesn't make sense :p

#

did you mean graphene?

#

i'd say the next big thing are silicon chips, actually

#

optronics

grave jolt
#

what an unfortunate course of action

verbal escarp
#

what the heck?

deep bramble
#

lol

verbal escarp
#

i was just experimenting a little with __call__ and found something curious

#
def f(): pass
object.__setattr__(f, "__call__", lambda: print("ehhh"))

>>> f()
>>> 
grave jolt
verbal escarp
#

<@&831776746206265384> would you mind?

quick snow
#

@gray hemlock wrong channel, go to #ā”ļ½œhow-to-get-heck

gloomy rain
#

!pban 654239909732941844 Seems like you're only here to troll. Please take that elsewhere.

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied purge ban to @gray hemlock permanently.

verbal escarp
#

ty

quick snow
#

Also aren't magic methods looked up on the type anyways?

#

So this wouldn't even work if it would work

verbal escarp
#

well, i was more surprised that object.__setattr__ didn't complain about it in the first place, i was expecting some kind of read-only wrapper

spice pecan
#

function.__call__ returns a wrapper, yeah

quick snow
spice pecan
#

!e ```py
def f():
print(f.attr)

f.attr = 10
f()

fallen slateBOT
#

@spice pecan :white_check_mark: Your eval job has completed with return code 0.

10
quick snow
#

!e

class Foo:
    def __str__(self):
        return "foo"
f = Foo()
f.__str__ = lambda: "bar"
print(f)
fallen slateBOT
#

@quick snow :white_check_mark: Your eval job has completed with return code 0.

foo
verbal escarp
grave jolt
#

you can set arbitrary attributes on a function object

spice pecan
#

It's an attribute on the function object

verbal escarp
#

what about closure functions?

grave jolt
#

same

verbal escarp
#

can you get access to them from the outside?

grave jolt
#

outside of where?

verbal escarp
#

as attribute of f?

quick snow
#

yep

grave jolt
#

When you make a "closure function" you create a new object every time

spice pecan
#

it's a name lookup followed by an attribute lookup, there's no magic going on

verbal escarp
#

lame

grave jolt
#

!e

def f():
    def g():
        return g.x
    return g

g1 = f()
g2 = f()
g1.x = 42
g2.x = 69
print(g1(), g2())
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

42 69
astral gazelle
#

isnt there a way to refer to the function itself inside of it

grave jolt
#

you can probably do that with inspect

astral gazelle
#

eh, also lame

verbal escarp
#
def f():
    def g():
        print("foo")

>>> f.g
Traceback (most recent call last):
  File "<pyshell>", line 1, in <module>
AttributeError: 'function' object has no attribute 'g'
#

that's more interesting to me

zenith topaz
#

Why would it have an attribute g? Does the function even exist yet?

gleaming rover
#

there's one g for every invocation of f

quick snow
#

the code object exists already, but not the function

grave jolt
grave jolt
#

functions don't really store their locals, because there may be several calls to the function at once

#

and that would create a lot of cycles

verbal escarp
#

let's say i want to decorate g() from the outside, programmatically

#

i'd need to get the code object and work with that?

grave jolt
#

yeah, that's just changing the code of f

peak spoke
#

Unless you're in a multi threaded context you also don't really have a chance of accessing the locals from a function, apart from the things the function itself calls but those can have them passed in in the first place

verbal escarp
quick snow
#

Depends what you want to do

verbal escarp
grave jolt
#

I'm not sure how to do that correctly, never done that

verbal escarp
#

okay, easy peasy >.>

#

(no clue, never done it myself either)

quick snow
#

You can do it without inspect and parsing AST

spice pecan
#

you could manipulate bytecode directly, but that's a bit of a hassle

quick snow
#

You don't need to do that either

spice pecan
#

manipulating bytecode to decorate the function would be pretty easy

quick snow
#

Just create your own wrapper function (a) that calls a dummy function (b), then replace the code object of the b with the code object of a, after having replaced the code object of b with the code object of the function to be decorated (c).

spice pecan
#

fixing jumps that come after that... yeah nah

quick snow
#

You get (and set) the code objects inside co_consts, no need to ever touch co_code

verbal escarp
quick snow
verbal escarp
#

thanks šŸ™‚

quick snow
#

Damn, I can't set __closure__. That might make this difficult in general :D

grave jolt
surreal sun
#

cc @verbal escarp ^ if you wanna do it this way

#

getsource wouldn't work in the REPL regardless so even fix's solution wouldn't work

halcyon galleon
# elder blade But `dict.get()` has an argument for defaults 😢

(a little late, I slept... yay!) You are 100% correct, .get() does have a default. In this edge case, however, the dict being parsed should contain another object at the keyword but can contain None. So even if I default to an empty dict, I hand a factory None if that's the valid value of the key. Instead of the overhead to identify and handle None, I chose to still create an object. Just an empty one.

# Instead of handling `None` as a possible value for
# .build_from(), we default to an empty dict() which
# allows the factory to fullfil the request.
team = Team.build_from(result.get("team") or {})

Perhaps a bit of laziness, but it allows the object factory to remain simple, asks forgiveness instead of permission, and falls-through on bad data from an unreliable vendor. Since its a provider library, ultimate validation of the data is on the consumer regardless.

elder blade
#

Huh šŸ¤”

verbal escarp
verbal escarp
surreal sun
verbal escarp
surreal sun
#

it's more of a lazy way to do it

verbal escarp
#

always good to have options

elder blade
#

@rapid schooner I don't think this is the purpose of this channel

white nexus
#

it rewrites every assertion by default, so its likely to have a good internal way of modifying the code

unkempt rock
fallen slateBOT
#
**PEP 505 - None-aware operators**
Status

Deferred

Python-Version

3.8

Created

18-Sep-2015

Type

Standards Track

surreal sun
#

Woah

#

this is awesome

native flame
#

thats pretty epic

#

i dont think ? currently has any meaning anywhere?

white nexus
#

since when do you write c?

boreal umbra
#

but not in the core language, no

native flame
#

hm

unkempt rock
#

can i talk about language dev here

#

making one on python

opaque chasm
verbal escarp
#

very cool!

outer shale
#

what is that in python ?

self.foo()(params)
deep bramble
#

foo() call returns a callable

spice pecan
#

foo is a method that returns another callable

#

which is then being immediately invoked

outer shale
#

oooh okay thx men

#

im stupid šŸ’©

tawdry terrace
#

If it's the first, it's just a placeholder name

oblique raven
wide totem
gusty marsh
oblique raven
#

Where are you seeing it?

wide totem
#

under "Retrieving source code", scrolled a bit down

#

OH

#

god. i need to go to bed

oblique raven
#

getblock not getdoc lol

wide totem
#

lolpain im so sorry

oblique raven
#

At some point I started looking at getsource, these names sorta mix together

#

Thanks Jason, that looks about right

raven ridge
oblique raven
#

On that note, is there someway to get all the lines that define a variable? I can probably figure out the first line of the variable by just looking for it's name, but that's kinda hacky, and can't find the last line for multi-line variables

paper echo
fallen slateBOT
#

@paper echo :white_check_mark: Your eval job has completed with return code 0.

001 | x 2:0 - 2:24
002 | y 4:0 - 11:1
oblique raven
#

This is insane, ty ty

#

I love it

paper echo
#

ast is great

verbal escarp
#

last time i wondered how to decorate closures, which was only doable with extremely volatile code from hell.. now i'm wondering if there is a more straight forward way to at least tell whether there's a closure function inside (and maybe its name)?

elder blade
#
def some_func():
    count = 0
    def closure():
        nonlocal count
        count += 1
        return count
astral gazelle
#

do closures need to be nested in functions

verbal escarp
verbal escarp
#

although, i'm not 100% about classes in classes

#

that could also be closures in a sense

#

<@&831776746206265384>

unkempt rock
#

!ban 913379681426866186 Racism

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied ban to @grim quarry permanently.

verbal escarp
#

ty

astral gazelle
verbal escarp
astral gazelle
#

yea, the difference is how they can be referred to, not how they close over values then

#

so any function that uses a name not passed to it is a closure

verbal escarp
#

difference is that functions also can have attributes, which are available outside and don't have to be passed in

#

but a closure function isn't even defined really until the outer function is called

#

you need to do some crazy bytecode or ast-gymnastics to do anything with a closure-function

#

so now i figured it might be simpler to just detect closures and notify the user about unreachable functions

lusty scroll
#

why not make your decorator decorate the return value of the outer function

spice pecan
#

yeah

#

you could just run the decorator as a regular function on the return value

#

and maybe wrap that into another decorator if you need to

verbal escarp
#

hu?

#

let's say you have an inner function and some looping etc. happening in the outer function

olive marsh
verbal escarp
#

if you want to decorate the inner function for instance to see what's happening, decorating the outer function's return value (which doesn't necessarily return the inner function) wouldn't help any

verbal escarp
#

it's weird.. i love using closures to simplify stuff, but now this seemingly simple problem almost is en par with figuring out how to make subprocess-interpreters work

#

it's like the spanish inquisition

olive marsh
verbal escarp
tall tree
#
print("hello world")
paper echo
astral gazelle
#

that was exactly what i was thinking but if you look at examples of closures online theyre always nested in some other function

lusty scroll
#

while it could go either way, closures usually capture their lexical state right? e.g. a closure would 'close over' the parameters passed to the enclosing function

grave jolt
#

it closes over the names, not the values

#

well, not really names

#

but references to values

lusty scroll
#

right

#

not a copy of the values themselves

verbal escarp
#

you sure about this applicant? šŸ˜‰

lusty scroll
#

looks almost too easy

verbal escarp
#

well, apparently it doesn't work with this example

#

šŸ¤·ā€ā™‚ļø

lusty scroll
verbal escarp
#

the heck?

lusty scroll
#

not sure if that's the expected result

olive marsh
verbal escarp
#

yeah, g is the closure

verbal escarp
#

"the search for closure" - the new novel about love and sadness and weird edge cases

olive marsh
verbal escarp
#

what would g be if not a closure?

olive marsh
#

nested function

#

its not closure

verbal escarp
#

oh godness

#

what's the difference?

olive marsh
verbal escarp
#

oh, so internally it's only considered a closure if g needs a reference to something in the outer function

#
def f():
    x = 23
    def g():
        return x
    return
olive marsh
#

exactly

verbal escarp
#

but i also get the same result as @lusty scroll - it returns ["closure"] and not the name

#

if there's an internal difference between nested functions and closures, how to deal with nested functions?

#

i feel like tumbling down a rabbit hole šŸ˜„

elder blade
#

Doesn't pickle permit against nested functions?

#

Check pickle source

verbal escarp
#

i dimly remember having problems pickling closures in the past, yes

verbal escarp
#

ty

#

i recall having seen STORE_FAST before

#

hahaha

#

i broke your code šŸ˜‰

#
def f():
    x = 23
    def g():
        return g
olive marsh
#

but this opcode should we followed by MAKE_FUNCTION with argrepr='closure'

verbal escarp
#

now it returns ['x']

olive marsh
verbal escarp
#

def g(): return g is so outlandish, it should probably belong in #esoteric-python

lusty scroll
#

how to compute this:
ValueError: b requires closure of length 0, not 1

#

i noticed for my test function it was doing LOAD_CONST instead of LOAD_CL0SURE, from the looks of it

verbal escarp
#
def g: return g
x = g
while True: x = x()
#

recursion error or no? ;D

olive marsh
#

updated again, hopefully this will work for all

#
    import dis
    ans = []
    flag =0
    nflag = 0
    bytecode = dis.Bytecode(some_function)
    for ins in bytecode:
        if nflag == 1:
            ans.append(ins.argrepr)
        if ins.opname == 'LOAD_CLOSURE':
            flag = 1
        if ins.opname == 'MAKE_FUNCTION':
            nflag = 1
        else:
            nflag = 0
    return ans if flag == 1 else []```
verbal escarp
lusty scroll
#

!e
this sort of works:

from types import FunctionType, CodeType, CellType
def a():
  def b(t):
    return 9
  return b
    
def find_closure(some_func):
    import dis
    ans, args = [], []
    bytecode = dis.Bytecode(some_func)
    for ins in bytecode:
        if ins.opname in ('LOAD_CLOSURE', 'LOAD_CONST'):
            args.append(ins.argval)
        if ins.opname == 'MAKE_FUNCTION':
            ans.append([*args[-2:], ins.argval])
    return ans

x = find_closure(a)[0]
func_b = FunctionType(x[0], a.__globals__, x[1], None, (CellType(),) * x[2])
print(func_b)
print(func_b(7))
fallen slateBOT
#

@lusty scroll :white_check_mark: Your eval job has completed with return code 0.

001 | <function b at 0x7f8884895a20>
002 | 9
paper echo
#

i agree that it's often not explained well

lusty scroll
paper echo
surreal sun
#

yeah, unfortunately not many ideas make it

#

Which idea?

#

Link? Im on phone rn

#

Ah

boreal umbra
#

Hasn't the idea of treating type instances like sets been floated over the years? Is there a reason this hasn't been implemented?

#

(or rather, made part of the spec)

spark magnet
boreal umbra
#

@spark magnet obj in cls being an alternative to isinstance, comparison operators for issubclass

spark magnet
#

i see

nova iris
#

haven't set foot in this unfamiliar territory for a long time... internals-and-peps? this place has changed

#

agreed. the line between eso and ad used to be thin

nova iris
mild flax
nova iris
#

i forgot the actual repo path, but i made a metaclass whose classes have subclass testing with comparison ops

#

, >=, <, everything works

nova iris
nova iris
#

ah yes, thank you

#

after aoc i shall make squarepython

#

square functions, square classes, any ordinary python callable shall be squared

white nexus
#

4 sided classes, duh

white nexus
#

well that was an interesting read

#

spent some time reading a person arguing against python, saying that they would rather teach someone python 2 than 3

#

especially because python doesn't have a standard
lol

#

this is gold

#

there's this part that stands out to me, could someone who was around/known a bit about the 3.0 to 3.4 gap explain a bit?

You also have no idea what history of Python was like. the 13 years you quote are very misleading. Very few people wanted Python 3 13 years ago. It's a miracle that Python 2 vs Python 3 didn't end up the same way Perl 5 did. It very much could've been the same story (in retrospect, it would've been better, if Python 3 just died / was renamed after some anime character, while Python 2 stayed).

Python 3 versions prior to 3.5 weren't really used. There were many reasons. Performance degradation, incompatibility. In general, Python 3 didn't and still doesn't offer anything of value that would justify updating from Python 2. It's all cosmetic changes, which incur a huge penalty on anyone wanting to update. The acceptance of Python 3.5 started with large Linux distributions being forced into it by Python Foundation abandoning support for Python 2.7. Nobody wanted to pick up the slack and support Python 2.7, so, naturally they had to use the newer version, just to stay afloat.

In my life, I had to update Python from 2.5 onward in many different projects. There hasn't been a case when things improved as a result of update. At best they stayed the same.

raven ridge
#

The first Python 3 version I ever used was 3.5. 3.0 and 3.1 were missing some important features that eventually led to the ability to write 2+3 compatible code in a reasonable way - like support for u"foo" unicode literals. 3.0 and 3.1 both had some serious bugs as well, I believe.

#

Support did eventually coalesce around Python 3 for various reasons - nice new features, loss of upstream support for 2, etc - but for a long time, it's true that it wasn't clear that 3 would win, and big corps were reluctant to switch to it as a result

#

the first Python 3 version with a feature that I really miss when writing Python 2 code is 3.6, with f strings

#

and when they switched to Unicode strings for text, it took them a long time to figure out how to handle things that people expect to be able to use string functions with, but which don't necessarily have a well defined encoding - like command line arguments and filesystem paths, both of which are arbitrary byte strings, not necessarily textual strings.

torpid bridge
#

Python 3, for me, fixed a lot of crucial language feature errors that would/did result in a huge amount of bugs. But yes, there was a huge amount of momentum for python2, and python2 wasn't a bad language, it just could have been better. And such a big change came with some very large speedbumps that didn't really get cleaned up until 3.4ish

#

Plus, nobody really has a desire to rewrite all their code just so that later they'll write less bugs. You need new features to be attractive, and those started properly showing up with 3.4

raven ridge
#

Python 2 made it really easy to write code that worked with your test input, but failed in production when it had to deal with real people's names, or things like that. But at the same time - once you had that code tested and debugged, there was very, very little value in upgrading to Python 3