#internals-and-peps

1 messages · Page 29 of 1

rose schooner
#

oh

#

that should NOT lead to _requires_builtin

willow pewter
#

though there are 3 following functions with @_require_builtin and all of them returns None

rose schooner
#

replace ```c
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
return -1;
}

PyObject *importlib = PyImport_AddModuleRef("_frozen_importlib");
if (importlib == NULL) {
    return -1;
}

withc
if (PyImport_ImportModule("importlib") <= 0) {
return -1;
}

PyObject *importlib = PyImport_AddModuleRef("importlib");
if (importlib == NULL) {
    return -1;
}
#

and see what you get

willow pewter
#

ok

willow pewter
rose schooner
#

okayy i guess not

rose schooner
#

but i guess the frozen modules are there for a reason

#

yeah set it back

#

we need the frozen imports

willow pewter
#

though does it compile fine for you?

rose schooner
#

yup

#

the problem for you is that _requires_builtin is getting a string for some reason

willow pewter
#

should I just try to reclone the repo?

rose schooner
#

sure

#

see if it works

willow pewter
rose schooner
#

since i don't know how to use git

willow pewter
rose schooner
#

i was gonna suggest adding print(old, new) before line 45 in Lib/importlib/_bootstrap.py but you try doing that first i guess

willow pewter
#

cloning....

#

for some freaking reason visual studio don't want to fetch externals before building

#

had to use cli to do it

willow pewter
#

ran clean.bat

#

recompiled

rose schooner
#

uh oh.

#

python313.lib is supposed to be built with the compilation

willow pewter
#

also just for note

#

which I think might be important

#

I am looking at source code because I (and @stable grail) found a bug that creating venv on 3.13 on windows tkinter imports look for tcl in libs/tcl/ instead of tcl/ and some more werid paths and according to @stable grail possibly it could have affacted more things than tkinter

willow pewter
#

what the python

#

I executed build.bat instead of visual studio build button

#

and guess what

#

it freaking worked

#

how the hell

rose schooner
#

oh

willow pewter
willow pewter
#

@stable grail problem is with build system

#

how do you build installer for python

willow pewter
#

I already have v143 build tools

jade raven
willow pewter
willow pewter
willow pewter
#

somehow

#

what is immortal.c

willow pewter
#

I forgot skip build and docs flag and it was generating them so I thought it worked but it didn't

jade raven
#

did you restart your terminal after installing build tools?

willow pewter
#

let me try to reboot

jade raven
#

then navigate the poaths and try again

willow pewter
willow pewter
jade raven
jade raven
#

then try the second suggestion there

willow pewter
jade raven
#

read the bottom error where it says retarget solution

willow pewter
#

doesn't work

jade raven
#

okay, what exactly is it that you're doing and why?

willow pewter
jade raven
willow pewter
#

i compiled 3.13.0 and tried creating venv with it and its fine so problem must be with installation or build process

#

problem exists in all(rc, stable, alpha, beta) 3.13.0 windows builds

jade raven
#

let me download the windows build, how do i reproduce your error?

unkempt rock
#

From selenium.webdriver.support.ui import expected_conditions as EC
import error: cannot import name accepted under_conditions from 'selenium.WebDriver.support.ui'

#

What should I do?

willow pewter
willow pewter
#

run Tools/msi/buildrelease.bat -x64

jade raven
#

okay but aren't you saying it's reproducible in the official builds?

willow pewter
#

I can't test on vm because it will take ages, I don't have a fast one

willow pewter
#

I was thinking about finding the issue in cpython about this and create a PR or issue with possible fix

jade raven
jade raven
#

i think your problem might be with something in your $PATH

willow pewter
#

did you use venv?

jade raven
#

indeed reproducible

willow pewter
#

so issue must be with installer or build process

#

thats why I was trying to build installer which I just can't for some reason

jade raven
willow pewter
#

I can try in sandbox too

#

let me try copy pasting the amd64 directory in there

jade raven
willow pewter
#

well at the end its a vm

#

will try it tomorrow

#

its 00:25 here

#

adios

willow pewter
#

tried on fresh windows 10 vm

stable grail
#

you need build tools correctly setup for them to work

willow pewter
#

also 3.5 .net

stable grail
#

you need your shell to know about the build tools

#

not the installer

#

is it added to your path

#

and is the correct one, the only one in your path?

willow pewter
#

I only have the latest(v143) installed

willow pewter
stable grail
#

run the build process with full paths

willow pewter
stable grail
#

are you following the devguide while doing this?

willow pewter
#

uh well this is what it says in getting started

#

and I couldn't find much reference about msi

#

shit I missed this part

#

this is in tools/msi/readme.txt

stable grail
#

yeah,,, very few does windows building

#

i had windows in 2018 during pycon, and at that time, there where no working docs for building on windows.

willow pewter
stable grail
#

the problem with building on windows is that there are so many variables to manage, so writing documentation is v ery miss

willow pewter
stable grail
#

so what you need from the build tools is... get the 100% correct options. probably only 10 mb of data

willow pewter
#

on linux its much easier with libs available in package managaer, make and gcc

stable grail
#

but what I do, is get them all, download 20GB of build tools, and then, it will work

#

but nice catch about the ARM build options. that might be the one you need for it all to work without the full install

willow pewter
#

also for some reason microsoft wants to force visual studio just to compile

#

while its not a even a good editor

willow pewter
#

they just give source code and say compile yourself

dusk comet
#

just use WSL on windows

willow pewter
#

you can't build for windows from linux

willow pewter
#

also tried installing wix even though ti fetched that automatically but still doesn't work

unkempt rock
#

hi

rose schooner
#

the stuff with universal v143 on it

willow pewter
willow pewter
sick ridge
graceful jungle
#

Is Flask the most useful tool for web app development with python? Or is there a better option?

graceful jungle
#

Gotcha, thanks

willow pewter
#

thanks

willow pewter
#

@stable grail problem is in installer

#

the compiled version works fine

#

but when I built the installer and installed in vm

#

it doesn't work

idle ravine
willow pewter
halcyon trail
#

is there a reason why chain.from_iterable is so... weirdly named?

#

it's the only thing in all of itertools afaics that's nested below something else

#

I feel like if it was just called flatten instead it would be used more often. both for being much shorter, and for being more clear.

near aurora
#

If I've got an idea for an alternative to a proposed PEP (and the alternative is almost the length of a PEP itself) would it be better to start a new thread on dpo (and reference it in the thread for the proposed PEP) or just post a very long reply?

neat delta
#

from_iterable is an alternate constructor, and most such things are class methods.

while flatten may be more descriptive to one of its common uses, it does have the issue of being slightly inaccurate, as chain.from_iterable only removes a single layer. I would strongly argue that something named flatten should produce a result that is fully flat, with partial flattening being done only at explicit user request, possibly via arguments

faint river
#

Like maybe with a kwarg for how many levels

#

Default being -1 to signify infinite levels

feral island
#

what if you pass a str

halcyon trail
#

flatten already exists and does this exact thing in multiple languages

#

Whereas I've never seen chain.from_iterable or chain_from_iterable much of anywhere but python

halcyon trail
faint river
halcyon trail
#

Lots of languages have that approach in general

#

I meant this particular name for this particular concept

wanton flame
thorn flume
#

quick question -
looking at dictobject.c, it seems to be doing this to find the index of objects that collide

        perturb >>= PERTURB_SHIFT;
        i = mask & (i*5 + perturb + 1);```
why does it shift-right `perturb` and add it to `i`?
fallen slateBOT
#

Objects/dictobject.c line 340

The other half of the strategy is to get the other bits of the hash code```
rose schooner
#

and the other lines below

thorn flume
#

i cannot read owo

thorn flume
fallen slateBOT
#

Objects/dictobject.c line 994

static inline Py_ALWAYS_INLINE Py_ssize_t```
rose schooner
#

which is by manual loop unrolling

#

probably something related to it happening 2 times per iteration

thorn flume
rose schooner
#

except "it's a hotspot and that probably improved the performance"

spark magnet
rose schooner
#

it's just the only reason i found

spark magnet
#

i misunderstood "except"

jade raven
#

what's the best place to request a pathlib property that returns the full path as a string? doing str(Pathobj) isn't pythonic imo

flat gazelle
#

str is the correct operation for that, there's no alternative I've been able to find.

jade raven
flat gazelle
#

oh, I misread

halcyon trail
#

Why isn't it pythonic though

faint river
#

I find that quite pythonic

jade raven
#

because pathlib already provides multiple methods / properties which return things as a str object

fallen slateBOT
#

A string representing the final path component, excluding the drive and root, if any:

>>> PurePosixPath('my/library/setup.py').name
'setup.py'
```  UNC drive names are not considered:

```py
>>> PureWindowsPath('//some/share/setup.py').name
'setup.py'
>>> PureWindowsPath('//some/share').name
''
flat gazelle
#

It is kind of odd that you have a ton of properties that give you parts of the path, but no property that gives you the whole path

faint river
#

what do you suggest it would be named?

jade raven
#

strpath, fullpath idk_naming_is_hard

faint river
#

path.strpath wow, so pythonic

flat gazelle
#

bikeshedding the name is kind of missing the point

jade raven
#

i think i'll open a DPO thread on this

flat gazelle
#

yea, I don't hate .fullpath, tho that should probably be str(path.resolve())

jade raven
#

but then we're back to using str, which is what i want to avoid

flat gazelle
#

yea, my point is that fullpath makes no sense as a replacement for str(path), but it'd be useful as a separate operation.

faint river
#

str(path) not necessarily equals str(path.resolve()), due to relative paths

flat gazelle
#
In [16]: str(Path('a/b'))
Out[16]: 'a\\b'
faint river
#

and fullpath sounds like it would be the latter

#

(is what I think lakmatiol is getting at)

flat gazelle
#

it is a bit of an odd one to think about, since there's no name for the string representing a path other than a path, which makes the operation a type conversion and thus it should be done via str

faint river
#
path == Path(str(path))
twilit lotus
#

Is there anyone having good resources to learn python decorator?

dusty oak
#

she dedicated a good chapter to them there

#

and all within reasonable amount of text too, not too much watery/overloaded

#

the entire book is just 311 pages

twilit lotus
trail cloud
#

Is it possible to create chatbots with python and pythons framework ?

crisp locust
trail cloud
cursive field
#

Guys can U help me learn how to make neural networks

#

I can only make chatbots and need help

#

Ping me if U wanna contact

#

I'm at school btw 😭😭

crisp locust
crisp locust
loud jungle
trail cloud
#

Got it

worthy sandal
#

Is anyone using structlog? Is it better than the traditional logging library?

#

Please let me know

swift imp
south kayak
#

how do I float small suggestions for the stdlib? Ex: making the name of the positionals and optionals groups in argparse modifiable with a simple reassign

Right now I have to modify the internal value after creating the parser
Code (note: I've done a few other hacks to make mine look tidy, but those are much larger changes that I'm not looking to suggest right now):

parser = WarMACParser(
    usage="warmac <command> [options]",
    ... # more stuff here
)
parser._positionals.title = "commands"  # changing positional header
```This code gives this output (notice red box)
#

how it normally looks (using pre-commit as an example. This how mine looked before I changed a few things):

feral island
south kayak
#

alright!

rose schooner
#

how would i check if an object is only referenced by the container it's in?

#

like ```py
class A:
def init(self, x):
self.x = x

a = A(19313)

check if a.x is only referenced by A

gc.get_referrers(a.x) == [a]

x = {4821: 2}

check if 4821 is only referenced by x

which seems to be impossible to check with gc.get_referrers() since it's not directly referenced by the dictionary apparently?

rose schooner
#

other than using gc.get_referrers()

spark magnet
rose schooner
spark magnet
rose schooner
#

i.e. the only referrer left is the proxy

spark magnet
rose schooner
#

that sounds a lot like it relies on the proxy being passed around instead of the object but okay

spark magnet
spark verge
#

Do you expect this to loop forever or halt? And given your choice do you think it's a feature of the language implementation or that it's unspecified?

import gc
import weakref

class A: pass

def main(a):
    lst = []
    a = weakref.ref(a, lambda _: lst.append(True))
    while not lst: gc.collect()

main(A())
spark verge
#

Eg in the above case ^

spark verge
feral island
spark verge
#

Right but they have to be collected eventually

#

Implementations aren't allowed to defer collection of unreachable objects forever

fallen slateBOT
#

Lib/test/support/__init__.py lines 799 to 813

def gc_collect():
    """Force as many objects as possible to be collected.

    In non-CPython implementations of Python, this is needed because timely
    deallocation is not guaranteed by the garbage collector.  (Even in CPython
    this can be the case in case of reference cycles.)  This means that __del__
    methods may be called later than expected and weakrefs may remain alive for
    longer than expected.  This function tries its best to force all garbage
    objects to disappear.
    """
    import gc
    gc.collect()
    gc.collect()
    gc.collect()```
spark verge
#

so the demo could be written like this:

import gc
import weakref
import test.support

class A: pass

def main(a):
    a = weakref.ref(a)
    test.support.gc_collect()
    assert a() is None

main(A())
#

implementations are required to replace test.support.gc_collect with something that will collect all unreachable objects

#

otherwise they didn't "try their best"

spark verge
raven ridge
#

The answer for small integers is just "no". They're always referenced by the small integer cache, in addition to whatever else is referencing them

rose schooner
#

pretty much the only thing i'd need is a weakref.ref() with a callback and works for any object ||(except interpreter-cached values, semantically)||

#

in other words, something to assign a callback for when the object is finalizing

rose schooner
#

just used sys.getrefcount() i guess

#

seems to work pretty well

narrow patio
#

can anybody tell me where in cpython the built-in function type is implemented?

#

like if you look at Python/bltinmodule.c you see a lot of implementations of those functions, but not type

lucid oasis
#

was wondering what channel to use to ask for advice

thin fossil
#

Holy shit guys wtf is this JIT

#

I've had this simple prime number benchmark that I do for anything python related. My baseline time is 20s on Cpython

#

Pypy does it in < 1s

#

This cpython 3.13 with JIT took 40s

#

Although without JIT took 17 seconds, they've been doing some nice interpreter optimizations

#

Graal Python can do it in < 1s

#

If the JIT isn't ready why even release it...

jade raven
thin fossil
#

I'm betting 5 years to get to where pypy is right now lol

jade raven
#

plus keep in mind the work on python's JIT is pretty recent, it's still in its infancy, so to speak, let it learn how to walk

#

pypy has been around since 2008 roughly? it's had a lot of time to improve their own thing.

raven ridge
# thin fossil If the JIT isn't ready why even release it...

What does "release it" mean here? The code exists because it's being actively iterated upon and developed, but it's turned off by default when building the interpreter, and is turned off in every distro I've heard of, and it's described as both "basic" and "experimental" in the release notes.

#

You literally need to pass a flag with "experimental" in the name just to build an interpreter with the JIT

gilded flare
#

it's not a full release and is only available to the ones who wanna test it out

#

if you don't want to or it's too disappointing, then use the normal full release

#

but there's others who wanna see for themselves how it works too

final geode
spark magnet
uneven raptor
#

are you sure you built a performance build of cpython?

thin fossil
#

I reimplemented that in various languages to get a very very rough idea of efficiency

#

pypy is one of the greatest open source projects this decade

thin fossil
final geode
thin fossil
#

And before anyone screams how benchmarks are worse than lies and damn lies, I KNOW.

#

But they're still very important. They tell you something and I find that what they tell you (if you know what you're doing and know how things work) is extremely important.

#

This particular one is showing me how fast the JIT can optimize tight inner loops and integer math, which is the easiest thing to optimise.

final geode
#

Also, while I have you: are your results on main or 3.13.0? And your hardware/os?

thin fossil
# final geode Also, while I have you: are your results on `main` or 3.13.0? And your hardware/...

Installed via:

PYTHON_CONFIGURE_OPTS='--disable-gil --enable-experimental-jit --enable-optimizations --with-lto' PYTHON_CFLAGS='-march=native -mtune=native' pyenv install 3.13.0

Hardware:

Architecture:             x86_64
  CPU op-mode(s):         32-bit, 64-bit
  Address sizes:          46 bits physical, 48 bits virtual
  Byte Order:             Little Endian
CPU(s):                   56
  On-line CPU(s) list:    0-55
Vendor ID:                GenuineIntel
  Model name:             Intel(R) Xeon(R) CPU E5-2697 v3 @ 2.60GHz
    CPU family:           6
    Model:                63
    Thread(s) per core:   2
    Core(s) per socket:   14
    Socket(s):            2
    Stepping:             2
    CPU(s) scaling MHz:   38%
    CPU max MHz:          3600.0000
    CPU min MHz:          1200.0000```
uneven raptor
#

nogil is probably the bottleneck, not the JIT

final geode
#

Oh, I totally missed that in the flags. Yeah, disabling the GIL results in huge slowdowns right now. Try without that.

#

The JIT isn’t even enabled when the GIL is disabled.

thin fossil
#

pyenv must not be using the -j flag for make lmao. I have 56 threads on this dual socket system and it's taking forever to build.

#

Or it might be the linker :\

final geode
#

I'm building too, it's using -j 8 for me, it's the two LTO link steps that take forever (and can't be parallelized).

thin fossil
#

Yeah LTO is the issue

#

Ok just ran the test again, (verified JIT is enabled, and did not disable GIL):

....
[0] Found 664579 prime numbers
[1] Found 664579 prime numbers
[2] Found 664579 prime numbers
[3] Found 664579 prime numbers
[4] Found 664579 prime numbers
[5] Found 664579 prime numbers
[6] Found 664579 prime numbers
[7] Found 664579 prime numbers
[8] Found 664579 prime numbers
[9] Found 664579 prime numbers
Total time: 15.577s```
loud jungle
#

JIT enabled performs faster than JIT disabled on your machine

thin fossil
#

@final geode so there's a very slight improvement vs 3.12 (which does 19s on the test)

final geode
#

I mean, 20% sure.

thin fossil
# loud jungle JIT enabled performs faster than JIT disabled on your machine

pypy:

➜ pypy3 bench3.py
....
[0] Found 664579 prime numbers
[1] Found 664579 prime numbers
[2] Found 664579 prime numbers
[3] Found 664579 prime numbers
[4] Found 664579 prime numbers
[5] Found 664579 prime numbers
[6] Found 664579 prime numbers
[7] Found 664579 prime numbers
[8] Found 664579 prime numbers
[9] Found 664579 prime numbers
Total time: 1.326s```

LMAO 1.326s
#

That's nuckin futz

#

The JVM implementation (using int primitives, not boxed Integer, with custom array implementation) does it in 1.173s

#

That's how absurdly impressive pypy is

#

Yes it does have some disadvantages in very complex logic that is hard to JIT, but compared to the hotspot VM which probably has $billions of funding, I'm consistently blown away by how good pypy is (and on that note, postgresql)

#

On another note, the only reason I have

#res = list(filter(lambda x: x or False, s))```
in there is to try both methods of building the list. It used to be that many years ago (like 10 years ago when I first wrote this), generators and generator expressions were not optimized in pypy. But that quickly changed.

But for 3.13.0, with the list comprehsion used instead of the generator expression, **the time further decreases from 15.577s to 13.051s**
thin fossil
# uneven raptor nogil is probably the bottleneck, not the JIT

So yeah, you're definitely right that nogil was the issue initially. And maybe the above little tidbit about list comprehensions vs generator expressions may help the devs out. I wish I had time to contribute to the JIT myself, but there's no way in hell these days 😦

final geode
#

Yeah, the comprehension is much easier to JIT than the functional version.

thin fossil
#

It's definitely a step in the right direction. I still think it'll take years before we get to anywhere near what pypy can do. But as long as it's not a performance regression, it's all good. It might be at the moment, so I won't be using it until they turn it on by default.

final geode
#

It's not our goal to compete with PyPy's performance.

thin fossil
# final geode It's not our goal to compete with PyPy's performance.

There are not many JITs in the world that can compete with pypy performance lol, so fair enough. Jokes aside, I hear what you're saying and I agree. Making everything a bit faster without introducing runtime performance regressions would be huge.

Thank you for the work that you're doing and the time you're contributing for the betterment of humankind ❤️

final geode
#

Thanks.

#

Appreciate you trying it out and sharing your experience.

thin fossil
#

Ain't no thang, I'm going to be watching it closely. I use python a lot. It's my go-to for prototyping things.

glass mulch
#

Using sys.addaudithook(print) works fine everywhere except PyREPL on Windows, because PyREPL spams time.sleep(0.01) events due to a lack of polling/select in that platform :/

short fiber
willow pewter
#

no I managed to compile python and installer also the issue was in path prefix which is now fixed

short fiber
#

ah, gotcha. but that only fixes importing tkinter in a venv?

unkempt rock
#

who knows pyqt5

crimson drum
rose schooner
#

oh it's mark

unkempt rock
#

who can fix my bot code

supple beacon
#

hey

#

i dont have persmission to talk in rooms

#

!!

glass mulch
#

There's an assert that is very easy to trigger (in debug builds, obviously) with sys.audit:

Python 3.14.0a1+ (heads/main:c5b99f5c2c, Oct 26 2024, 12:35:53) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.audit(9)
python: ./Python/sysmodule.c:522: sys_audit: Assertion `PyUnicode_Check(args[0])' failed.
Aborted (core dumped)

Passing a non-string there results in a clean error in non-debug builds.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected str for argument 'event', not int

Is this a common way of doing checks in debug builds? IOW, is this OK or should it avoid aborting for a simple TypeError?

merry bramble
#

Yeah, I don't think that's supposed to happen

crimson drum
gilded flare
#

1 core dev was probably enough

merry bramble
glass mulch
merry bramble
#

I guess the setup for the audit tests is a bit baroque

feral island
merry bramble
#

correct

spark verge
#

Ah could do with comments why it doesn't use assertRaises

wanton flame
grave jolt
#

yeah I know

#

it's just funny with github using an avatar in the embed

heavy egret
#

hallo

#

this is genral chat?

#

My english is very bad

astral gazelle
white nexus
#

!e () = []

#

someone recently brought this to my attention and its wild that it doesn't break

fallen slateBOT
faint river
unkempt rock
#

hey how could i remove a ban

spark verge
little token
#

Hi

glass mulch
#

Is a segfault in _tkinter interesting, or is it a "here be dragons" module?

#

I took vstinner's old fuzzer, fusil, for a ride and it stumbled upon:

import  _tkinter 
_tkinter.create(None, '', '\U0010FFFF', None)
fallen slateBOT
#

Lib/tkinter/__init__.py line 2459

self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)```
spark verge
#

...or worse depending on your perspective

#

!e

import tkinter
tkinter.Tk(screenName=None, baseName='', className='\U0010FFFF')
fallen slateBOT
# spark verge !e ```python import tkinter tkinter.Tk(screenName=None, baseName='', className=...

:x: Your 3.12 eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "/home/main.py", line 1, in <module>
003 |     import tkinter
004 |   File "/snekbin/python/3.12/lib/python3.12/tkinter/__init__.py", line 38, in <module>
005 |     import _tkinter # If this fails your Python may not be configured for Tk
006 |     ^^^^^^^^^^^^^^^
007 | ImportError: libtk8.6.so: cannot open shared object file: No such file or directory
spark verge
#

Ah it's not installed

feral island
#
Python 3.14.0a0 experimental free-threading build (heads/gh-125331:c315120a535, Oct 30 2024, 11:22:31) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import tkinter
... tkinter.Tk(screenName=None, baseName='', className='\U0010FFFF')
... 
zsh: segmentation fault  ./python.exe
spark verge
#

Nice

spark verge
glass mulch
#

I will, as soon as I get back from an errand. It found another in the meantime:

import sre_constants
sre_constants._makecodes("", {}, 10)
spark verge
spark verge
#

Can you reach it via re._constants _NamedIntConstant?

#

!e

from re._constants import _NamedIntConstant

def _makecodes(*names):
    items = [_NamedIntConstant(i, name) for i, name in enumerate(names)]
    return items
_makecodes("", {}, 10)
fallen slateBOT
spark verge
#

!e

import sre_constants
sre_constants._makecodes("", {}, 10)
spark verge
#

What python version are you on? It's a worrying one because it all looks like pure python

fallen slateBOT
# spark verge !e ```py import sre_constants sre_constants._makecodes("", {}, 10) ```

:x: Your 3.13 free threaded eval job has completed with return code 1.

001 | /home/main.py:1: DeprecationWarning: module 'sre_constants' is deprecated
002 |   import sre_constants
003 | Traceback (most recent call last):
004 |   File "/home/main.py", line 2, in <module>
005 |     sre_constants._makecodes("", {}, 10)
006 |     ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^
007 |   File "/snekbin/python/3.13t/lib/python3.13t/re/_constants.py", line 74, in _makecodes
008 |     globals().update({item.name: item for item in items})
009 |                       ^^^^^^^^^^^^^^^
010 | TypeError: unhashable type: 'dict'
feral island
#

I also get the unhashable TypeError for that code, tried 3.12 and main

spark verge
#

Commit hash?

glass mulch
#

Wait, I'm running a python from october 8th 😦

#
Python 3.14.0a0 (heads/main:31516c98dd7, Oct  8 2024, 17:52:24) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sre_constants
... sre_constants._makecodes("", {}, 10)
...
<python-input-0>:1: DeprecationWarning: module 'sre_constants' is deprecated
  import sre_constants
Segmentation fault
#

WIll re-run all cases on real main and report back later

spark verge
feral island
#

can't repro on linux either

unkempt rock
spark verge
unkempt rock
#

i am not a discord nerd here i just didn't know so i asked
any problems?

spark verge
#

This isn't the correct channel to ask in

unkempt rock
spark verge
nocturne lance
#

I am dealing with ctypes, and getting NameError. there is a structure that points to its parent
something of the lines of:



class RunHeader(ctypes.Structure):
    _fields_ = [
            ...
            ('mv_header', ctypes.POINTER(MvHeader)),
            ...
    ]

class MvHeader(ctypes.Structure):
    _fields_ = [
            ...
            ('run_header', ctypes.POINTER(RunHeader)),
            ...
    ]

is there a efficient way to deal with this? that isn't so hacky

raven ridge
glass mulch
glass mulch
#

JIT debug main:
```py`
Python 3.14.0a1+ (heads/main:d467d9246c, Oct 30 2024, 22:52:43) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

import sre_constants; sre_constants._makecodes('', {}, 10)
<python-input-0>:1: DeprecationWarning: module 'sre_constants' is deprecated
import sre_constants; sre_constants._makecodes('', {}, 10)
python: Python/ceval.c:966: _PyEval_EvalFrameDefault: Assertion `STACK_LEVEL() >= level' failed.
Aborted

feral island
glass mulch
#

Aborts on JIT+debug, segfaults on JIT main.

final geode
unkempt rock
glass mulch
#

ISTM that tracing of audit hooks with sys.monitoring doesn't work like it should: adding a __cantrace__ attribute to the audit hook still doesn't trace it's CALL events:

import inspect
import sys

sys.monitoring.use_tool_id(1, "monitor")
sys.monitoring.set_events(1, sys.monitoring.events.CALL)

def monitor(code, offset, function, obj):
    print(f"MONITORED: {function}")

sys.monitoring.register_callback(1, sys.monitoring.events.CALL, monitor)


def g(*args):
    print()

def f(*args):
    print(args)

f.__cantrace__ = True

class F:
    __cantrace__ = True
    def __init__(self):
        self.__cantrace__ = True
    def __call__(self, *args, **kwargs):
        print(args)

sys.addaudithook(F())
sys.addaudithook(f)

for x in range(3):
    g.__code__
    g()

# Output:
# ('sys.addaudithook', ())
# ('sys.monitoring.register_callback', (<function monitor at 0x7f985301b590>,))
# ('sys.monitoring.register_callback', (<function monitor at 0x7f985301b590>,))
# MONITORED: <class 'range'>
# MONITORED: <built-in function print>
# ('object.__getattr__', (<function g at 0x7f9853f168d0>, '__code__'))
# MONITORED: <built-in function print>
# ('object.__getattr__', (<function g at 0x7f9853f168d0>, '__code__'))
# MONITORED: <function g at 0x7f9853f168d0>
# MONITORED: <built-in function print>
# 
# MONITORED: <built-in function print>
# ('object.__getattr__', (<function g at 0x7f9853f168d0>, '__code__'))
# MONITORED: <built-in function print>
# ('object.__getattr__', (<function g at 0x7f9853f168d0>, '__code__'))
# MONITORED: <function g at 0x7f9853f168d0>
# MONITORED: <built-in function print>
# 
# MONITORED: <built-in function print>
# ('object.__getattr__', (<function g at 0x7f9853f168d0>, '__code__'))
# MONITORED: <built-in function print>
# ('object.__getattr__', (<function g at 0x7f9853f168d0>, '__code__'))
# MONITORED: <function g at 0x7f9853f168d0>
# MONITORED: <built-in function print>
#

Which seems to go against the intention of the C code:

        /* Disallow tracing in hooks unless explicitly enabled */
        PyThreadState_EnterTracing(ts);
        while ((hook = PyIter_Next(hooks)) != NULL) {
            PyObject *o;
            int canTrace = PyObject_GetOptionalAttr(hook, &_Py_ID(__cantrace__), &o);
            if (o) {
                canTrace = PyObject_IsTrue(o);
                Py_DECREF(o);
            }
            if (canTrace < 0) {
                break;
            }
            if (canTrace) {
                PyThreadState_LeaveTracing(ts);
            }
            PyObject* args[2] = {eventName, eventArgs};
            o = _PyObject_VectorcallTstate(ts, hook, args, 2, NULL);
            if (canTrace) {
                PyThreadState_EnterTracing(ts);
            }
            if (!o) {
                break;
            }
            Py_DECREF(o);
            Py_CLEAR(hook);
        }
#

Can you see any obvious error?

glass mulch
#

As an aside, not monitoring these audit hooks makes my attempt to hack them after they are set harder, which might be good. I just ask because it seems the code intends to make them monitorable (and there are no tests of this that I can find).

#

Hmm, I think this is about tracing only, not monitoring. Which would mean you cannot monitor CALL events of sys.audit hooks at all.

ruby elm
#

I've recently been implementing python's regex flavor from scratch, and the explanations given in both the re __init__ docstring and on the re documentation page don't match the actual behavior. The ones I've found so far:

  • \0 refers to the null character, not capture group 0
  • \YYY refers to octal character YYY, not capture group YYY
  • [\b] matches \x08. not b
  • \xYY is hex character YY
  • The maximum m and n in {m} and {m,n} is 4294967294, or 2**32-2
    Ideally this inconsistency wouldn't exist, but I'm not 100% sure where these notes would go, or what the process would be to add them.
spark magnet
gilded flare
# ruby elm I've recently been implementing python's regex flavor from scratch, and the expl...
  1. documented

Groups are numbered starting from 1.

  1. documented

This special sequence can only be used to match one of the first 99 groups. If the first digit of number is 0, or number is 3 octal digits long, it will not be interpreted as a group match, but as the character with octal value number.

  1. documented, right after point no. 4

(Note that \b is used to represent word boundaries, and means “backspace” only inside character classes.)

  1. documented

Most of the escape sequences supported by Python string literals are also accepted by the regular expression parser:

\a      \b      \f      \n
\N      \r      \t      \u
\U      \v      \x      \\
  1. undocumented
    https://docs.python.org/3/library/re.html
spark magnet
spark magnet
gilded flare
#

i've only used it in re.Match objects

ruby elm
fallen slateBOT
spark magnet
gilded flare
#

docs actually match there

ruby elm
fallen slateBOT
gilded flare
#

!e print(__import__("re").sub(r"a", r"\0", "a"))

fallen slateBOT
spark magnet
gilded flare
#

there is no such thing as a \0 group

#

not even in r-strings

spark magnet
#

@ruby elm in any case, you can make a pull request to improve the docs if you like.

ruby elm
spark magnet
ruby elm
#

!e print(__import__("re").sub(r"a", "a", r"\0"))

gilded flare
fallen slateBOT
gilded flare
#

it's re.sub(from_, to, string) btw

feral island
#

!e print(__import__("re").sub(r"a", r"\0", r"a"))

fallen slateBOT
spark magnet
#

you can use \g<0> though

feral island
#

!e print(__import__("re").sub(r"a", r"\g<0>", r"a"))

fallen slateBOT
gilded flare
spark magnet
gilded flare
spark magnet
gilded flare
#

i don't see a dedicated section for it

#

considering \0 vs \g<0>

#

and also \g<name>

spark magnet
ruby elm
#

So with the limit on m and n in {m} and {m,n}, should that be listed somewhere as a concrete number? It comes from here MAXREPEAT = _NamedIntConstant(MAXREPEAT, 'MAXREPEAT') but does that mean it could change based on the implementation? Since it think those come from `here ```c

define SRE_MAXREPEAT (~(SRE_CODE)0)

...

define SRE_MAXREPEAT ((SRE_CODE)PY_SSIZE_T_MAX)```

spark magnet
#

it feels like trivia

ruby elm
gilded flare
ruby elm
#

The backreference \g<0> substitutes in the entire substring matched by the RE.

gilded flare
#

but it is re.sub()-only behavior

ruby elm
#

The only other question I have is with the docstring in the re module's __init__ Which gives a lot less detail than the documentation page, and is what I was mainly going off of. Should it have a link back to the docs saying "see here for the full explination"? Be kept in sync with the docs? Not try to explain and just link to the docs?

feral island
#

Could be a good idea to add a line like "refer to the Python docs page for details"

spark magnet
#

i don't think we need to say "refer to the docs". We'd add that to every docstring.

ruby elm
# feral island I think it should give a concise summary, aiming for correctness but not compreh...

Oh no subjectivity. Where is "correctness but not comprehensiveness"? Since it currently doesn't have anything about substitution behavior, or \number being either \x00 or \group or \octal. It also doesn't have the \b is boundary, except in [\b] where it's backspace. Should those things be added to it? It also says " If the ordinary character is not on the list, then the resulting RE will match the second character" but that's not right since it also accepts the normal python escape sequences.

feral island
#

I might actually trim it down significantly and mention only the most commonly used regex features

#

The idea would be to let new users who use help(re) get a quick sense of what you can do with it

ruby elm
#

Interesting, I didn't know help(module) linked back to the module docs. I'm not sure how much you would want to shrink it down, but at least the default terminal size on windows gives very little space before the -- More --. Also, where's the help on help? I think I found the controls through trial and error, but help(help) leads to _Helper, not an actual explination. It would also suck if someone got trapped into help without knowing how to quit through q or ctr+c, since for me the re help text is over 800 lines long.

dusk comet
#

.__doc__ vs .__doc_extra__

spark magnet
spark magnet
#

also help

#

and in 3.13, help does what help() did in previous versions

#

and help(help) doesn't natter on about Helper, so that's already taken care of.

#

oops, it does

feral island
#

it does have some useful info ``` | Calling help() at the Python prompt starts an interactive help session.
| Calling help(thing) prints help for the python object 'thing'.

ruby elm
#

Interesting, but that also doesn't list the controls when stuck in the -- More -- state. Are those actually listed anywhere?
Something else fun is that "help mode" help> is not useful for re, since doing modules re gives at least 100 results.

feral island
#

But I think it'd be nicer if help(help) gave you help about the help system instead

ruby elm
#

help>re does work, but that wasn't my first instinct.

#

Interestingly, help>help is already covered, so I wonder why help(help) isn't.

feral island
#

it seems like it just recursively creates a nested help session

#

which I'm not sure is the most useful thing to do 🙂

#

wait no, that's not true; it only prints the help intro

ruby elm
#

I see, so it's help('re') that does the same thing.

spark verge
#

What's help>?

ruby elm
#

Another fun thing I guess you could do is help(help()), which puts you into help>, then prints the help for NoneType once you exit help>. Since help(object) returns None, you can infinitely chain help(help(...)) to get however many NoneType help texts printed in a row.

spark verge
#

I just got this:

>>> help>help
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of '_Helper' and '_Helper'
feral island
#

then type help (or anything) in that prompt

spark verge
#

oh there's a help repl TIL

ruby elm
#

Another thing you can do is (help(), help()) which makes you have to exit the help repl twice.

spark verge
#

This is the _Helper.__repr__ is a repl?

ruby elm
#

And I did actually find something bad. If you do [help() for _ in iter(int, 1)] or any other infinite iterator, you get the terminal stuck in the help repl permanently.

feral island
#

If you do [input() for _ in itertools.count()] you also get stuck

ruby elm
#

ie with [input() for _ in __import__('itertools').count()], sure the terminal hangs takes input forever, but ctrl+c still works to get everything back to normal. [help() for _ in iter(int, 1)] seems to be permanent, you have to close the terminal.

#

The closest thing I can think of is if you caught the ctrl+c, ie ```py
while True:
try:
input()
except:
pass

wispy grotto
uneven raptor
glass mulch
#

Is this worth an issue, or is it meh?

For a debug non-gil build (even with GIL enabled) of main on Linux, I get an abort at finalization for this code:

./python -c "import gc; gc.freeze(); gc.is_finalized(lambda: None); gc.collect(); gc.get_count(); gc.collect(); gc.unfreeze()"

Error looks like:

Python/gc_free_threading.c:550: validate_refcounts: Assertion "!gc_is_unreachable(op)" failed: object should not be marked as unreachable yet
Enable tracemalloc to get the memory block allocation traceback

object address  : 0x20000360f10
object refcount : 1152921504606847590
object type     : 0x55d414c25660
object type name: dict
object repr     : {'__name__': 'builtins', '__doc__': [...]}

Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: finalizing (tstate=0x000055d414ca77e0)

Current thread 0x00007f222228a740 (most recent call first):
  Garbage-collecting
  <no Python frame>
Aborted
uneven raptor
#

you could report it, but i don't know if it will get fixed. breaking things with gc is typically your fault

feral island
glass mulch
#

Here's one that happens before finalization, it's the same error but with a shorter repr:

import gc
gc.freeze()
gc.is_finalized(lambda: None)
gc.collect()
gc.unfreeze()
gc.collect()

Error looks like:

Python/gc_free_threading.c:550: validate_refcounts: Assertion "!gc_is_unreachable(op)" failed: object should not be marked as unreachable yet
Enable tracemalloc to get the memory block allocation traceback

object address  : 0x200007373f0
object refcount : 1152921504606846977
object type     : 0x55adadc26660
object type name: dict
object repr     : {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x20000330a20>, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/fusil/python-61/gc-assertion-abort-2/source.py', '__cached__': None, 'gc': <module 'gc' (built-in)>}

Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized

Current thread 0x00007f1b47a64740 (most recent call first):
  Garbage-collecting
  File "/home/fusil/python-61/gc-assertion-abort-2/source.py", line 6 in <module>
Aborted
glass mulch
#

A simple one:

import curses
curses.napms(37)
Fatal Python error: _Py_CheckFunctionResult: a function returned a result with an exception set
Python runtime state: initialized
_curses.error: must call initscr() first

The above exception was the direct cause of the following exception:

SystemError: <built-in function napms> returned a result with an exception set

Current thread 0x00007fe41a8c3740 (most recent call first):
  File "/home/fusil/python-73/curses-fatal/source.py", line 3 in <module>
Aborted
feral island
feral island
glass mulch
#

This one is probably a "don't do that then": a segfault by calling tracemalloc on different threads, only happens with PYTHON_GIL=0.

# This segfaults with PYTHON_GIL=0, works with PYTHON_GIL=1
from threading import Thread
import tracemalloc

alive = [
    Thread(target=tracemalloc.take_snapshot, args=()),
    Thread(target=tracemalloc.clear_traces, args=()),
]

tracemalloc.start()
import inspect # This seems to be important, has to happen after .start()

for obj in alive:
    print('START', obj)
    obj.start()
glass mulch
#

A different gc assert, happens with PYTHON_GIL=0 only:

from threading import Thread
import gc

gc.freeze()
alive = [Thread(target=gc.freeze, args=())]
gc.collect()
gc.unfreeze()
gc.collect()
Python/gc_free_threading.c:554: validate_refcounts: Assertion "op->ob_tid == 0" failed: merged objects should have ob_tid == 0
Enable tracemalloc to get the memory block allocation traceback

object address  : 0x20000278210
object refcount : 1152921504606846994
object type     : 0x5616274befc0
object type name: type
object repr     : <class '_thread.lock'>

Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized

Current thread 0x00007f34ed160740 (most recent call first):
  Garbage-collecting
  File "/home/fusil/python-104/gc-abort-assertion/source.py", line 8 in <module>
Aborted
uneven raptor
#

you can report that, i'll take a look

glass mulch
#

It's also possible to hit this different assert, but I haven't minimized it:

Python/gc_free_threading.c:558: validate_refcounts: Assertion "op->ob_tid != 0" failed: unmerged objects should have ob_tid != 0p
glass mulch
uneven raptor
#

gc abort, but you can go ahead and report the other two. worst case scenario they're wontfixes

#

well, i think i found part of the problem. the reference count of a lambda on the free threaded build is somehow significantly higher than that of an immortal object (1152921504606846976 for lambda: None on my end, but None itself has a refcnt of 3221225472, so that shouldn't be possible)

glass mulch
glass mulch
uneven raptor
#

there's definitely something shady going on with the reference counts

#

i suspect DRC has something to do with it

glass mulch
#

If you pass (x for x in range(10)) to is_finalized it also aborts, but if you store it in a variable it doesn't. So it looks like it has to be a fresh object with no references... not sure of what kinds yet.

spark verge
#

I think the error message for a missing file in a package could be improved

#

currently it looks like this:

 graingert@conscientious  ~/projects/demo_imports   main  tree
.
└── demo_imports
    ├── __init__.py
    └── __pycache__
        └── __init__.cpython-312.pyc

3 directories, 2 files
 graingert@conscientious  ~/projects/demo_imports   main  cat demo_imports/__init__.py 
from . import _version
 graingert@conscientious  ~/projects/demo_imports   main  python -m demo_imports 
/usr/bin/python: Error while finding module specification for 'demo_imports.__main__' (ImportError: cannot import name '_version' from partially initialized module 'demo_imports' (most likely due to a circular import) (/home/graingert/projects/demo_imports/demo_imports/__init__.py))
 ✘
#

demo_import/_version.py is missing

#

demo_import/__init__.py tries to import from . import _version

#

but the error message seems to imply a cyclic import

limpid forum
glass mulch
#

Here's a way to get a SystemError (or abort in debug builds) by accessing a memoryview from threads. It sometimes segfaults on a no-gil debug build, but I'm not sure being no-gil is relevant.

Is it worth filling an issue?

from threading import Thread

av = memoryview(b"something")
av.release()

alive = [
    Thread(target=av.release, args=('/bin/sh')),
    Thread(target=av.__iter__, args=())
]

for obj in alive:
    try:
        print('START', obj)
        obj.start()
    except Exception:
        pass

Rare segfault:

Exception in thread Thread-1 (release):
Fatal Python error: _Py_CheckFunctionResult: a function returned a result with an exception set
Python runtime state: initialized
ValueError: operation forbidden on released memoryview object

The above exception was the direct cause of the following exception:

SystemError: <method-wrapper '__iter__' of memoryview object at 0x200006a6050> returned a result with an exception set

Current thread 0x00007f750b5d0640 (most recent call first):
  File "/home/danzin/projects/mycpython/Lib/threading.py", line 992 in run
  File "/home/danzin/projects/mycpython/Lib/threading.py", line 1041 in _bootstrap_inner
  File "/home/danzin/projects/mycpython/Lib/threading.py", line 1012 in _bootstrap

Thread 0x00007f750bdd5640 (most recent call first):
  File "<frozen importlib._bootstrap_external>", line 142 in _path_split
Python/traceback.c:979:18: runtime error: member access within misaligned address 0x000000000001 for type 'struct _PyInterpreterFrame', which requires 8 byte alignment
0x000000000001: note: pointer points here
<memory cannot be printed>
Segmentation fault
#

Common abort:

Fatal Python error: _Py_CheckFunctionResult: a function returned a result with an exception set
Python runtime state: initialized
ValueError: operation forbidden on released memoryview object

The above exception was the direct cause of the following exception:

SystemError: <method-wrapper '__iter__' of memoryview object at 0x200006a6050> returned a result with an exception set
Aborted
glass mulch
heady maple
#

Hello! I want to ask, what does Python do during lexical analysis, when the indentation level is not in the stack? Does it look ahead for next indents to get the nearest context it can have, or just propagate to the parser?

spark magnet
heady maple
#

Does it try to 'round off' to the nearest indentation level below for error recovery?

spark magnet
heady maple
#

So if it encounters this error, it panics. Hmm.

quick snow
#

Doesn't this dedent to an unseen level?

if True:
               x = (
  2
)
#

I'm pretty sure it doesn't; the lexer doesn't emit a dedent inside parens etc. But how does it know? Does it count?

heady maple
#

Grouping symbols ignore whitespace, even if it's after a line break

quick snow
#

And that doesn't happen in the parser?

heady maple
#

I actually have no idea, to be honest.

quick snow
#

That means the lexer must have a stack of open grouping characters (or at least a grouping count)

spark magnet
rose schooner
#

it only generates indents/dedents when in any type of grouping

spark magnet
#

You can experiment with python -m tokenize and type code at it

quick snow
rose schooner
glass mulch
#

fusil found :D:

python: ./Include/internal/pycore_stackref.h:99: _PyStackRef_FromPyObjectSteal: Assertion `obj != NULL' failed.
Aborted

me having to reduce a huge file with a bug that only triggers sometimes: :/

glass mulch
#

Ok, reduced. For a no-gil main debug build on Linux, I get an abort with the following code. Do you think it's worth filling an issue?

from threading import Thread
from collections import ChainMap, Counter, defaultdict

dictionary = dict.fromkeys(range(100))
counter = Counter(range(100))
chainmap = ChainMap(dictionary, counter)

def mutate_removing():
    for x in range(10):
        dictionary.pop(list(dictionary.keys()).pop())
        counter.pop(list(counter.keys()).pop())
        chainmap.pop(list(chainmap.keys()).pop())

def mutate_adding():
    for x in range(50):
        dictionary[max(dictionary) + x + 1] = x
        counter[max(counter) + x + 1] = x
        chainmap[max(chainmap) + x + 1] = x

alive = []

for x in range(55):
    alive.append(Thread(target=mutate_removing, args=()))
    alive.append(Thread(target=mutate_adding, args=()))

for obj in alive:
    try:
        print('START', obj)
        obj.start()
    except Exception:
        pass
#

Abort looks like:

python: ./Include/internal/pycore_stackref.h:99: _PyStackRef_FromPyObjectSteal: Assertion `obj != NULL' failed.
Aborted
feral island
#

that includes the nogil build

#

Do you need all three of the dict, the Counter, and the ChainMap, though?

#

worth trying if it also crashes with three dicts or something like that

glass mulch
#

Turns out the dict isn't necessary, we can get the same abort with two ChainMaps that reference a Counter. Doesn't seem to work with a dict in the place of the Counter or of the ChainMap.

glass mulch
#

This is getting silly 😄 . New issue, I guess?

./python -c "from unittest.mock import MagicMock as MM; from _pickle import load; load(MM())"
python: Objects/typeobject.c:5583: _PyType_LookupRef: Assertion `!PyErr_Occurred()' failed.
Aborted (core dumped)
feral island
#

that one feels like it shouldn't be hard to fix

glass mulch
#

Can anyone confirm that the following segfaults? I'm suspicious it might be something in my system.

python -c "from _ssl import _SSLSocket; s =_SSLSocket(); s.do_handshake()"
quick snow
glass mulch
#

Thank you!

spark verge
#

!e

from _ssl import _SSLSocket; s =_SSLSocket(); s.do_handshake()
fallen slateBOT
spark verge
#

139 SIGSEGV

glass mulch
#

Also

python -c "from _pyrepl._minimal_curses import tigetstr; tigetstr('')"
crimson drum
#

Please file issues for these. Thanks

gray galleon
#

is there a proposal for Private and Protected type hints

flat gazelle
#

Probably not, the __ and _ prefixes fill that role reasonably well.

fossil pagoda
#

where is the gerneal chat?

#

looking for a beginner python discord server

jovial flame
gray galleon
dusk comet
#

_private
__i_need_this_only_in_this_class
__protected__

spark magnet
#

don't make up your own __dunder__ names: those are for Python

ruby elm
#

I might have actually found something not in the re docs. The part about char sets [] says

Character classes such as \w or \S (defined below) are also accepted inside a set, although the characters they match depend on the flags used.
And that is true for all of the escapes listed, except \A and \Z, which give a "bad escape" error.

quick snow
ruby elm
#

Then I'd say it's missing in the other direction, since octal/unicode/hex escapes work, despite not being a character class like \w or \S.

#

\B also doesn't work, so it looks to be all the zero width escapes

#

Which makes sense, since it doesn't make sense for a character set to have a zero width match, but it is a thing not mentioned.

quick snow
ruby elm
quick snow
spark verge
#

People seem to sort of make up their own dunder names a lot

#

Eg __version__ or __{pypi_name}__

spark magnet
spark verge
#

__version__ is particularly weird, as it's banned by docs.python.org but the pep 396 has a note saying it might be ok

flat gazelle
#

Usually it is fine since your class won't be subclassed

dusk comet
#

__mylib_mything__ has a very low chance of collision with future cpython names

faint river
#

I would use sunders

wanton flame
spark verge
grave jolt
#

A single underscore usually means that a name is not public and should not be relied upon. It's not "protected" in the sense that subclasses can access it (in fact, it is also used for module-level functions and local/global variables, where subclasses don't exist). If a library class is using some _underscored members, it means that they can change in the next version without informing you

#

There are other modes of visibility like "public but only within this library" and "public but only within this module/subpackage", that also don't have a convention. If you care about it, you can leave a comment or something like that.

#

But normally _underscored means "private", as in "if you are not the maintainer of this code, don't use this variable/class/module"

quick snow
#

or maybe "warranty void if broken", i.e. "if you touch this, all promises are off"

grave jolt
#

yep

spark verge
#

So classes can be subclassed in one context but not another

glass mulch
#

New one, confirmations welcome.

python3 -c "import time; time.pthread_getcpuclockid(2)"
Segmentation fault
feral island
#
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import time; time.pthread_getcpuclockid(2)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'time' has no attribute 'pthread_getcpuclockid'
``` on mac
#

but segfaults on 3.12 on linux

glass mulch
#

And

python -c "from sys import maxsize; from itertools import count; count(maxsize)"
python: ./Modules/itertoolsmodule.c:3325: itertools_count_impl: Assertion `(cnt != PY_SSIZE_T_MAX && long_cnt == NULL && fast_mode) || (cnt == PY_SSIZE_T_MAX && long_cnt != NULL && !fast_mode)' failed.
Aborted (core dumped)
glass mulch
feral island
glass mulch
#

main+linux aborts too

jade raven
#

petition to add a segfault hunter as a role like core dev and award it to @glass mulch

#

never seen so many segfaults for python in my life than what i've seen @glass mulch push out in the last month

glass mulch
glass mulch
feral island
glass mulch
uneven raptor
#

theoretically, you could iterate over the active thread states and check if the passed ID is in there, but that would only work for threads that have called PyGILState_Ensure or something similar

raven ridge
#

Just install a SIGSEGV handler!

feral island
#

depending on how the function works in C you might be able to do more interesting things than get a segfault

raven ridge
#

I doubt it, I'd expect it's all reads and no writes, and anyway this is nothing you couldn't do with ctypes in a typical CPython build that isn't trying to do any sandboxing

#

the interpreter could maybe guard against the segfault by using mincore, but that's not enough - it's not just that the address needs to be mapped, but also that the region it's mapped into needs to be large enough to hold a pthread structure, and that size is unknown since the structure is opaque

#

it would be easy enough to make it less likely to segfault, but not at all easy to make it never segfault, I think

#

and any attempt to validate it could still fall afoul of TOCTOU

uneven raptor
#

i wrote something a while back that converted SEGV signals into exceptions that you could literally try/except and then proceed with execution like nothing happened

jovial flame
#

!cban 1136816274303885322 We are not a server for hiring

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied ban to @near fiber permanently.

glass mulch
#

Here's a cute abort:

python -c "b''.__buffer__(-2**31 - 1)"
python: Objects/typeobject.c:9321: wrap_buffer: Assertion `_Py_STATIC_CAST(Py_ssize_t, _Py_STATIC_CAST(int, (flags))) == (flags)' failed.
Aborted
feral island
glass mulch
uneven raptor
real herald
#

Hii is there anyone who is preparing for PECP or had PECP?

merry venture
glass mulch
#

There's something interesting going on. With a lot of code (35 lines) involving interpreters (hundreds) and threads (thousands), it may non-deterministically result in one of the following errors, from most common to rarest:

  1. tstate_delete_common assertion, which seems to indicate a thread creation failed, see https://github.com/python/cpython/issues/109746
python: Python/pystate.c:1739: tstate_delete_common: Assertion `tstate->_status.cleared && !tstate->_status.finalized' failed.
  1. Fatal Python error, seems to be https://github.com/python/cpython/issues/113148
Fatal Python error: Py_EndInterpreter: not the last thread
Python runtime state: initialized

Current thread 0x00007f09af37e640 (most recent call first):
  <no Python frame>

Thread 0x00007f09b0380640 (most recent call first):
  <no Python frame>
Aborted
  1. heap_pop: This one might be new and worth a look?
python: Python/index_pool.c:92: heap_pop: Assertion `heap->size > 0' failed.
Aborted

Does anyone want to take a look at the code so we can try to figure out enough to create an issue?

GitHub

Crash report What happened? Bisected to e11fc03, but I guess this issue exists longer, and assertion that is added to PyThreadState_Clear by this commit just made it visible. import resource import...

GitHub

One of the first thing that happens during interpreter finalization is waiting for all non-daemon threads to finish. This is implemented by calling threading._shutdown(). If an exception is raised ...

glass mulch
#

Got a bt of the heap_pop one:

#0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=140729519150656) at ./nptl/pthread_kill.c:44
[...]
#4  0x00007ffff7cc67f3 in __GI_abort () at ./stdlib/abort.c:79
#5  0x00007ffff7cc671b in __assert_fail_base (fmt=0x7ffff7e7b130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n",
    assertion=0x555555aceaf4 "heap->size > 0", file=0x555555aceae0 "Python/index_pool.c", line=92, function=<optimized out>)
    at ./assert/assert.c:92
#6  0x00007ffff7cd7e96 in __GI___assert_fail (assertion=assertion@entry=0x555555aceaf4 "heap->size > 0",
    file=file@entry=0x555555aceae0 "Python/index_pool.c", line=line@entry=92,
    function=function@entry=0x555555aceb40 <__PRETTY_FUNCTION__.1> "heap_pop") at ./assert/assert.c:101
#7  0x00005555558caa1c in heap_pop (heap=<optimized out>) at Python/index_pool.c:92
#8  0x00005555558cac33 in _PyIndexPool_AllocIndex (pool=pool@entry=0x7ffff780f498) at Python/index_pool.c:173
#9  0x000055555568d9f0 in _Py_ReserveTLBCIndex (interp=interp@entry=0x7ffff780b020) at Objects/codeobject.c:2752
#10 0x0000555555951c33 in new_threadstate (interp=interp@entry=0x7ffff780b020, whence=whence@entry=5) at Python/pystate.c:1516
#11 0x0000555555953994 in _PyThreadState_NewBound (interp=interp@entry=0x7ffff780b020, whence=whence@entry=5)
    at Python/pystate.c:1578
#12 0x0000555555896ee9 in _enter_session (session=session@entry=0x7ffe24ff8740, interp=interp@entry=0x7ffff780b020)
    at Python/crossinterp.c:1548
#13 0x000055555589b9fb in _PyXI_Enter (session=session@entry=0x7ffe24ff8740, interp=interp@entry=0x7ffff780b020,
    nsupdates=nsupdates@entry=0x0) at Python/crossinterp.c:1711
#14 0x00007ffff7c3d217 in _run_in_interpreter (interp=interp@entry=0x7ffff780b020, codestr=0x200006182c8 "f()", codestrlen=3,
    shareables=shareables@entry=0x0, flags=1, p_excinfo=p_excinfo@entry=0x7ffe24ff8870) at ./Modules/_interpretersmodule.c:461
#

Seems to require PYTHON_GIL=0

uneven raptor
#

@glass mulch FWIW, the issue is that a subinterpreter can start running after the final destruction check, which breaks a lot

glass mulch
#

Got another subinterpreters abort, seems to be in 3.13t_d but not main:

python: Python/pystate.c:1292: _PyInterpreterState_IDDecref: Assertion `interp->id_refcount != 0' failed.
Aborted (core dumped)
uneven raptor
glass mulch
#

Well, this one reduced to a lot less than I thought it would:

import _interpreters

interpr = _interpreters.create()
_interpreters.decref(interpr)

Should I leave it be then?

glass mulch
#

Got another one on main:

python: ./Modules/_interpretersmodule.c:462: _run_in_interpreter: Assertion `!PyErr_Occurred()' failed.
Aborted (core dumped)
uneven raptor
uneven raptor
glass mulch
uneven raptor
#

that looks like a different bug, report it

glass mulch
#

Oh, it segfaults on non-debug builds

glass mulch
#

I want to publish updated fusil this week. Hopefully we can add new kinds of fuzzing input to it to help discover more bugs. If anyone wants to take a peek before it's cleaned up (or run it on some different environment or implementation) ping me and I'll add you to the (for now) private repository.

#

Thanks all that have evaluated, diagnosed and fixes issues fusil has found. And thanks Victor for fusil 🙂

jade raven
#

thank you!

glass mulch
jade raven
glass mulch
#

The way it works is it imports a module, lists all functions classes and objects in it, and generates random calls to functions and methods with invalid data. Also adds such calls to threads. The fuzzer is simple, the handling of processes, using a different user to run the fuzzing, matching successful runs and other features of the library is where the magic hides.

glass mulch
glass mulch
#

The one you want to run is fusil_messy, the working fuzzer is fusil-python-threaded. You need to install python-ptrace. And be sure to create a limited user called fusil and run the fuzzer as root, so it can change the process user to this limited user and keep your precious filesystem safe from wacky calls to pathlib, open, os, etc.

#

I've been running it on Linux, might work on Mac.

#

I'll be away for some hours, but let me know if you need any assistance or have any doubts. Happy fuzzing 🙂

jade raven
#

<@&831776746206265384>

spark verge
flat rune
#

hi

pine wraith
#

Hey folks, I was looking at PEP-0589: https://peps.python.org/pep-0589/ and found the concept of totality. I was wondering how is this implemented internally:

class Movie(TypedDict, total=False):
    name: str
    year: int

Here total looks like a kwarg. How is it passed to the metaclass? Can I pass custom kwargs to mine own metaclasses or is it something specific for the use-case of TypedDict?

flat gazelle
quick snow
#

It should be __new__

flat gazelle
#

!e

class Foo(metaclass=print, end='hello, world\n'): pass
fallen slateBOT
rose schooner
#

the secret to any class initialization is a __call__() call

flat gazelle
#

it does __call__ of the object that is kept around as the metaclass (ideally an instance of type), which then calls __new__ and __init__ as is proper.

#

idk whether the kwarg goes to __prepare__ tbh

rose schooner
#

TIL i don't need to specify type as a base when using metaclasses

flat gazelle
#

it is slightly horrifying that this works tbh

rose schooner
#

esoteric python!!

quick snow
#

Well it calls the metaclass of course, but that would go via the metaclasses metaclasses __call__, wouldn't it?

#

Which for type is type, sure..

rose schooner
#

you never know how many layers of objects you're gonna pass through

flat gazelle
#

yea, that's what I meant with the metaclass object.

#

it does metaclass.__call__, not directly metaclass.__new__

rose schooner
pine wraith
rose schooner
flat gazelle
#

ah yea, doing so directly gives you the descriptor smh

quick snow
quick snow
#

!e note how Meta.__call__ is never called.

class Meta(type):
    def __init__(self, *args, **kwargs):
        print("Called meta __init__ with", args, kwargs)

    def __new__(self, *args, **kwargs):
        print("Called meta __new__ with", args, kwargs)
        return super().__new__(self, *args)

    def __call__(self, *args, **kwargs):
        print("Called meta __call__ with", args, kwargs)
        return super().__call__(self, *args)


class Foo(metaclass=Meta):
    pass

print("Before class definition")
class Bar(Foo, ham="spam"):
    pass
fallen slateBOT
# quick snow !e note how `Meta.__call__` is never called. ```py class Meta(type): def __i...

:white_check_mark: Your 3.12 eval job has completed with return code 0.

001 | Called meta __new__ with ('Foo', (), {'__module__': '__main__', '__qualname__': 'Foo'}) {}
002 | Called meta __init__ with ('Foo', (), {'__module__': '__main__', '__qualname__': 'Foo'}) {}
003 | Before class definition
004 | Called meta __new__ with ('Bar', (<class '__main__.Foo'>,), {'__module__': '__main__', '__qualname__': 'Bar'}) {'ham': 'spam'}
005 | Called meta __init__ with ('Bar', (<class '__main__.Foo'>,), {'__module__': '__main__', '__qualname__': 'Bar'}) {'ham': 'spam'}
rose schooner
#

or at least something to imitate TypedDict

#

since it doesn't necessarily use that

fallen slateBOT
#

Lib/typing.py lines 3337 to 3338

_TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)```
flat gazelle
#

TypedDict being a def-made object is a bit silly, what.

rose schooner
#

TIL TypedDict is not a class

fallen slateBOT
#

src/typing_extensions.py line 1042

@_ensure_subclassable(lambda bases: (_TypedDict,))```
merry bramble
#

That decorator has to do some fun things because the hack that cpython uses to make the TypedDict function subclassable doesn't work on old versions of PyPy

#

on old versions of PyPy, typing_extensions.TypedDict is therefore a subclassable, callable instance of an anonymous class instead of a function

pine wraith
#

Actually, it seems that the __init_subclass__ hook is not used at all. I ran this code:

from typing import TypedDict


class A(TypedDict):
    a: int

and ran it with python -m trace --trace main.py > out.txt
This is the relevant part:

main.py(4):  class A(TypedDict):
 --- modulename: typing, funcname: <lambda>
typing.py(3319):  TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)
 --- modulename: main, funcname: A
main.py(4):  class A(TypedDict):
main.py(5):      a: int
 --- modulename: typing, funcname: __new__
#

My suspicion is that it works because __new__ defines a total arg.

flat gazelle
#

yea, the metaclass gets called, which then calls __new__

swift imp
#

Reading discourse on pep 765. What on earth is GvR getting at with the for a[i] in ...: ... comment?

https://discuss.python.org/t/pep-765-disallow-return-break-continue-that-exit-a-finally-block/71348/4

spark magnet
swift imp
#

It does like an anti pattern

#

This seems so useless and convoluted

#bot-commands message

flat gazelle
#

I have very rarely used it in cases like

config = {...}
for config['optlevel'] in 0, 1, 2, 3:
    do_tests(config)
sonic flax
#

i want a way to directly fund work on the PEP541 (pypi name retirement/takeover) backlog

#

it looks like it's over a year long at this point

#

i will go the entire next week without grabbing a coffee so i can fund this

dusk comet
#
for x, y in zip(X, Y): ...

is a common example of that
zip() produces tuples, and they are unpacked to x, y

#

for assignment target can be anything that you can put to the left side of =
same applies to some other situations: ```py
with foo as TARGET: ...

I can't recall any other cases sadly :(

rose schooner
#
for {}() in range(10):
    print("Ta da! Unused loop variable")
dusk comet
#

!e ```py
for [] in [[]]+[[]]+[[]]:
print('foo')

fallen slateBOT
spark magnet
#

BTW, I have used it. in a class with a turn counter: for self.turn in range(self.nturns):

#

and doesn't it make sense? for i in seq is like running i = seq[0] etc over and over. The loop target is an assignment target.

swift imp
spark magnet
swift imp
#

<@&831776746206265384>

somber thicket
#

please don't advertise in this server

opaque wagon
#

Hello

glass mulch
#

I've just republished fusil, the tool by Victor Stinner that has been finding crashers in CPython and PyPy:
https://mastodon.social/@danzin/113510116056712424
https://github.com/devdanzin/fusil

GitHub

Fusil is a multi-agent Python library used to write fuzzing programs - devdanzin/fusil

spark verge
jade raven
#

@dusk comet should i focus on that repo then?

worthy sandal
#

Is anyone using python and rust combined in their project? If so what are the places you applied rust and why? I am a python lover and trying to make use of rust but did not find appropriate scenario... thanks in advance!

dusk comet
jade raven
inland acorn
#

(now the python part is in js, we still got the rust code)

#

But a more general answer, rust is nice for software you need to distribute to end users, which is a bit harder to do with python

#

(also rust is just amazing and should be used for everything /hj )

inland acorn
dusk comet
jade raven
bold marsh
#

iteration over set isn't ordered by insertion. does this mean iteration over set is O(buckets) instead of O(entries)?

bold marsh
#

answer: yes

dusk comet
#

since buckets/entries=O(1) it doesn't matter much

bold marsh
spark verge
#

It's buckets+items, and because buckets<items it boils down to just items

glass mulch
glass mulch
#

Does anyone know if a commit in, say, the last four days could be responsible for a much increased rate of hitting python: Python/pystate.c:1620: PyThreadState_Clear: Assertion 'tstate->_status.initialized && !tstate->_status.cleared' failed.? It has increased significantly in fuzzer runs. I'm not 100% sure it has to come from code change and not something in the fuzzing machine, but it seems to be stable across reboots. Sorry for asking before building an older revision and testing myself 😬

jade raven
glass mulch
bold marsh
#
from sys import getsizeof
s = set()
print(getsizeof(s))
for i in range(256):
    s.add(i)
print(getsizeof(s))
for i in range(256):
    s.remove(i)
print(getsizeof(s))
#

also, buckets isn't bounded by items by the above code

glass mulch
# glass mulch Does anyone know if a commit in, say, the last four days could be responsible fo...

Ah, turns out to be caused by a fix to the fuzzer code. It means a lot more threads are created now, and I guess it hits https://github.com/python/cpython/issues/109746 because of that. Sorry for the noise.

GitHub

Crash report What happened? Bisected to e11fc03, but I guess this issue exists longer, and assertion that is added to PyThreadState_Clear by this commit just made it visible. import resource import...

glass mulch
fallen slateBOT
#

:incoming_envelope: :ok_hand: applied timeout to @thorny ridge until <t:1732388190:f> (9 minutes and 59 seconds) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

flint burrow
#

Hello

grave jolt
#

@raw night Hello, this server is not the right place to advertise your linkedin profile.

raw night
#

@grave jolt may I know the server which is right place for this ??

grave jolt
#

No, I don't know

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied timeout to @sturdy hound until <t:1732460828:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

The <@&831776746206265384> have been alerted for review.

rose schooner
#

unpacking operator has inconsistent precedence and yield takes an implicit tuple as a value, which might cause some confusion

#

why?

#

!e ```py
import traceback

for i, line in enumerate((
r'print("abc" if 1 else "123")',
r'print([
"abc" if 1 else "123"])',
), start=1):
print(f"[{i}]:", line)
try:
exec(line)
except SyntaxError as e:
traceback.print_exc()
print()

def f(*g):
a, b = yield 'a', *g
yield a, b

x = f([1, 2, 3])
print(x.send(None)) # receives first yield
print(x.send('xy')) # sends in place of first yield, receives second yield

fallen slateBOT
# rose schooner !e ```py import traceback for i, line in enumerate(( r'print(*"abc" if 1 el...

:white_check_mark: Your 3.12 eval job has completed with return code 0.

001 | [1]: print(*"abc" if 1 else "123")
002 | a b c
003 | 
004 | [2]: print([*"abc" if 1 else "123"])
005 | Traceback (most recent call last):
006 |   File "/home/main.py", line 9, in <module>
007 |     exec(line)
008 |   File "<string>", line 1
009 |     print([*"abc" if 1 else "123"])
010 |                   ^^
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/UPDGJKH44P4XL4TSPCJYVYOI7Y

merry venture
#

unpacking too

#

not sure where's the confusion here, but maybe i'm too used to it

rose schooner
#

yield i find more reasonable to be expected

#

but i feel like it could be interpreted that a = yield 'a' and b, = *g,

merry venture
#

you would a, b = (yield 'a'), *g instead

#

even print(yield) is an invalid syntax, which makes sense because what would print(yield 1, 2) mean?

#

and you need either print((yield 1, 2)) or print((yield 1), 2)

astral gazelle
#

This seems entirely unrelated to the channel and server

grave jolt
#

!cban @brittle stag spam

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied ban to @brittle stag permanently.

merry venture
astral gazelle
#

<@&831776746206265384> scam

jovial flame
#

!cban 1285208360328761477 scam

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied ban to @brittle sedge permanently.

rose schooner
#

sometimes i wonder if the server should have self-role access for this channel

regal glen
#

While I really like that idea, a decent amount of python contributors are not the most discord literate. Wouldn’t want to lock them out of here. (If you want to continue this, let’s not here and move it to #community-meta)

candid vessel
#

yes

jade raven
candid vessel
jade raven
candid vessel
molten island
#

This breaks the #rules number 9. Don't advertise work or solicit paid work

raven ridge
spark verge
#

You can run two os.system calls in different threads

#

Better to just use subprocess.run though

hallow tulip
#

question, I'm running 3.12.5 (dk if it matters as much) and ran this in an ipynb, but the interpreter returns a syntax error at:
print([*"abc" if 1 else "123"])
^^
SyntaxError: invalid syntax

rose schooner
#

the interpreter returns a SyntaxError when the expression being unpacked has a precedence lower than the "bitwise OR" (|) operator

broken forum
coarse stone
#

Multiplication

#

Sorry, wrong chat

gray galleon
#

why do floor division with floats return floats

merry bramble
# gray galleon why do floor division with floats return floats

Because of possibly unfortunate decisions made a long time ago that cannot realistically be reversed now https://discuss.python.org/t/make-float-i-r-floordiv-return-an-int/24959/1

final geode
#

The real fun is that the type of the result of exponentiation depends on the sign of the exponent.

crude anvil
quick snow
crude anvil
#

yeah that's what i first though but that makes sense i guess ...

sour thistle
#

you can even get complex numbers from int ** float: ```py

[(-2)**n for n in (2, -2, 0.5)]
[4, 0.25, (8.659560562354934e-17+1.4142135623730951j)]

crude anvil
#

now it's fun lol

rose schooner
dusk comet
#
>>> ((-1)**-1e-99*-1e99).imag
3.141592653589793
``` 😳
wild trout
#

What is actually going on there? (too lazy to think about it)

rose schooner
#

no idea why tho :p

wild trout
#

lim (-1)^(-x) as x -> 0 should be 1

rose schooner
#

but the leading zeroes in the imaginary part also get infinitely many

dusk comet
#

infinitely big zero 🤯

wild trout
rose schooner
wild trout
#

I guess it works for any large power

#

the only assumption is sin(x) = x

#

but x doesn't need to be that small for sin(x) = x to be roughly true

#
1       0.0
2       2.0
5       2.938926261462366
10      3.090169943749474
20      3.1286893008046173
100     3.141075907812829
200     3.141463462364135
1000    3.1415874858795636
#
for i in [1, 2, 5, 10, 20, 100, 200, 1000]:
    print(f"{i}\t{((-1)**(1/i)*(1*i)).imag}")
grave jolt
#

Question: is it specified anywhere that the __iter__ of an iterator should only return self, and shouldn't e.g. reset its state or do other things?
I think that's something that's informally expected of iterators (stuff like the recipe here would not work otherwise https://docs.python.org/3/library/itertools.html#itertools.batched), but is it formally written down anywhere?

feral island
#

https://docs.python.org/3/glossary.html#term-iterator "Iterators are required to have an iter() method that returns the iterator object itself"

wild trout
grave jolt
feral island
wild trout
#

It can do other things, can't it?

feral island
#

It can but it shouldn't

wild trout
#

Why not?

#

Is that just the semantic of iterators, that the function only does that and not anything else?

#

That seems to impose a restriction on the programmer that might not be necessary

#

But yeah definitely the current docs don't make it sound like the programmer shouldn't do other things in __iter__

flat gazelle
wild trout
grave jolt
#

Well, "not doing anything else at all" might be too restrictive
But not mutating the iterator seems reasonable

shy grove
#

Well you can always ignore recommendations

flat gazelle
#

IG you could put like logs or breakpoint() in there

wild trout
wild trout
shy grove
#

Would be weird if my duck stopped quacking

#

My iterator should behave like an iterator

grave jolt
#

unfortunately, ducks do not live forever

wild trout
flat gazelle
#

that I would argue should not be allowed

shy grove
#

You can always implement your custom methods, having standard methods with standard semantics and definitions does not stop you from doing that

flat gazelle
#

if it were allowed, it would force every correct function handling iterators to carefully manage their iter calls

feral island
#

The advantage of saying __iter__ should have no side effects is that the interpreter is free to call it multiple times if that's convenient for the runtime

#

(Plus what @flat gazelle said)

#

You can still have side effects in __iter__, they might just happen multiple times when you might not expect it

grave jolt
#

The reason mutating the iterator is potentially bad is that it makes it problematic to pass the iterator to other functions. See the example I linked from the docs:

def batched(iterable, n, *, strict=False):
    # batched('ABCDEFG', 3) → ABC DEF G
    if n < 1:
        raise ValueError('n must be at least one')
    iterator = iter(iterable)
    while batch := tuple(islice(iterator, n)):
        if strict and len(batch) != n:
            raise ValueError('batched(): incomplete batch')
        yield batch

First, it calls iter on the iterable (let's assume the iterable is already an iterator). Then, this iterator is passed to islice on each iteration. islice expects an iterable, so it calls iter on the argument. This looks like reasonable code, but if the iterator changes its state when its __iter__ is called, it's not going to work as expected

final geode
austere totem
#

hey so im pretty new to Python and coding in general, is there something you would recommend to actually use it like projects i could do?

winged sphinx
austere totem
#

ok thanks

boreal umbra
#

Has there been any discussion of adding methods to the generator type, like map, filter, and limit?

spark verge
#

Also the Generator type is a bare minimum ABC, so adding methods would break it

#

We'd need to fix the whole collections.abc.Generator Vs types.GeneratorType issue first

boreal umbra
spark verge
#

You just use generator expressions

boreal umbra
grave jolt
#

I think a bigger issue is that other iterators won't automatically get that

#

You'd probably also want generator.map(lambda x: x * 2) to return something with map, filter and other methods, so map and filter objects now probably also get these methods. And then you'll have an inconsistency in the ecosystem as to which iterators support which helper methods

#

With that limitation, a better solution would probably be some kind of "pipe", so that you don't have to bolt on a map method to every iterator type

spark verge
#

And you'd want list.map to return a list and gen.map to return a generator and set.map to return a set maybe?

grave jolt
#

but realistically, just using generator expressions or loops will be the solution in Python

rose schooner
#

i had an idea

#

nvm

#
def f(XY or is_XY):
    print(XY, is_XY)

f(True)  # True True
f(False)  # False False
#

it's not as practical as when i first had it in mind

dusk comet
#

parameter aliases?

rose schooner
#

yup

#

i think it's better explained with these examples ```py
f(is_XY=True) # True True
f(XY=False) # False False

grave jolt
#

but why

rose schooner
# grave jolt but why

i had an idea with py class Point: def __init__(coord0: Number, coord1: Number, XY or is_XY: bool = False): if is_XY: self.x = coord0 self.y = coord1 else: self.y = coord0 self.x = coord1 ... but i guess it could be better made with this ```py
class XYPoint:
def init(x: Number, y: Number):
self.x = x
self.y = y
...

class YXPoint(XYPoint):
def init(y: Number, x: Number):
super().init(x, y)

grave jolt
#

If you think the old name (in a library) is really bad, maybe it's better to deprecate it, which will require some extra runtime stuff

@deprecationlib.rename_param(new="is_xy", old="xy")
def __init__(self, c0: int, c1: int, /, *, is_xy: bool = True) -> None:
rose schooner
#

no idea

rose schooner
#

that's why i said this

grave jolt
#

it would be cooler to have an and

#
def launch_missiles(i_am_sure and really_sure):
    ...

launch_missiles(i_am_sure=True, really_sure=True)
rose schooner
#

hmm

#

parameters that are only allowed when both are given..?

grave jolt
#

no, they are just anded

#

for those of us activating weapons of mass destruction from IPython

rose schooner
#

okay wait

#

i had this problem with my Vector class where i wanted to support giving x and y OR giving magnitude and direction

grave jolt
#

I would split it into Vector(x, y) and Vector.polar(4206.9, pi)

rose schooner
#

that would be nicer, yes

grave jolt
#

I guess there are some functions that have groups of parameters that are either all provided or all not provided

#

but perhaps that is better replaced with a parameter object

rose schooner
#

unfortunately i already implemented manual argument parsing to support both

grave jolt
#

if you add enough of those groups to a function, it starts to get bloated

rose schooner
#

yeah i guess there are better ways than this

grave jolt
#

💀

quick snow
#

Was reading PEP 768 and wondering whether this would be useful for something like memray, until I read the list of authors :)

unkempt rock
rose schooner
#

more ideas ```py
f() => g()

instead of

(f(), g())[1]

also

f() =< g()
(f(), g())[0]

def add_(x)and(y):
return x + y

def combine_[T](*x: T)and[U](*y: U) -> list[tuple[T, U]]:
return list(zip(x, y))

dusk comet
steel solstice
#

iirc there was a time there was a way to not have to use stacklevel in warnings and just go to a frame with a name is that a thing or am i just misremembering?

feral island
steel solstice
#

ah that was indeed it

#

thank you

opaque solar
#

Hi

#

How can I learn code python

crisp locust
#

Tutorials

winged sphinx
deft kiln
winged sphinx
opaque solar
boreal umbra
#

has str? ever been considered as an alternative to str | None?

steel solstice
#

In terms of default arguments?

shrewd dew
#

just curiouse guys the people that make ''rats'' that like logs your whole imformation like saved cookies and stuff idk i think its like a exe file they run is that extreamly hard to make?

shrewd dew
#

wich one is

spark verge
feral island
boreal umbra
feral island
verbal escarp
crisp locust
rose schooner
#

usually you'd precede PEP writing with a message to the Ideas category of discuss.python.org

sour thistle
quick snow
#

Get it to be a PEP: Be a core dev or have one sponsor it. Have it accepted: For most types of PEPs: Have steering council decision in support.

verbal escarp
merry bramble
#

The Steering Council (at least in recent years) generally hasn't approved PEPs if it's clear that there's a majority (or even a significant minority) of core devs who are uncomfortable with the change. So I would say it's more than just "convince the steering council"; it's really "forge consensus among the core developer team as a whole"

verbal escarp
#

okay

#

@rose schooner i understand why you don't write PEPs :p

quick snow
crisp locust
#

Why assume politics in technical subjects?

verbal escarp
rose schooner
#

(some of them might be great features but i don't like making arrangements with the public in general)

verbal escarp
#

if it were based on merrit of the idea instead of person, the order wouldn't matter, but alas..

rose schooner
#

these would be pretty difficult toys to justify :p ```pycon

x = []
((x=x) => x)() += 5,
x
[5]

#

oh right