#internals-and-peps
1 messages · Page 29 of 1
though there are 3 following functions with @_require_builtin and all of them returns None
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
so we are directly using importlib instead of frozen importlib here?
okayy i guess not
yup
but i guess the frozen modules are there for a reason
yeah set it back
we need the frozen imports
though does it compile fine for you?
yup
the problem for you is that _requires_builtin is getting a string for some reason
should I just try to reclone the repo?
how can I directly clone https://github.com/python/cpython/commit/60403a5409ff2c3f3b07dd2ca91a7a3e096839c7 this instead of cloning from main
same but it would be easier to switch commits and branch with git
i was gonna suggest adding print(old, new) before line 45 in Lib/importlib/_bootstrap.py but you try doing that first i guess
cloning....
for some freaking reason visual studio don't want to fetch externals before building
had to use cli to do it
did, debug compiled fine, release said can't open input file pcbuild/amd64/python313.lib
ran clean.bat
recompiled
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
what should I do now?
what the python
I executed build.bat instead of visual studio build button
and guess what
it freaking worked
how the hell
oh
and tkinter works
@stable grail problem is with build system
how do you build installer for python
Which is what the documentation says to do
it worked fine in 3.13.0a0 though
what should I do?
ran command in visual studio and it worked
somehow
what is immortal.c
never mind it didn't work
I forgot skip build and docs flag and it was generating them so I thought it worked but it didn't
but that doesn't seem to be the problem
did you restart your terminal after installing build tools?
yup
let me try to reboot
wins key > developer command prompt for VS 2022
then navigate the poaths and try again
doesn't work
as I said I have tried it in visual studio too
uninstall whatever it is you have installed and try this, #1215299553914519572 message, alternatively try the second suggestion liste there
that's what I have?
then try the second suggestion there
there is just visual studio?
read the bottom error where it says retarget solution
done that
doesn't work
okay, what exactly is it that you're doing and why?
trying to build cpython x64 3.13.0 msi
why?
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
let me download the windows build, how do i reproduce your error?
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?
don't crosspost. i answered you in #python-discussion
also it doesn't even belong to this channel
wait
clone this 60403a5 on from 3.13 branch
install visual studio 2022 community with these components:
python native development tools
.net framework 3.5 development tools
(C++ are mentioned in image)
run Tools/msi/buildrelease.bat -x64
okay but aren't you saying it's reproducible in the official builds?
can be
I can't test on vm because it will take ages, I don't have a fast one
but this venv issue is 100% reproducible you can try by creating a new venv with 3.13.0 release**(installed from windows installer from python.org)** and run python -m tkinter in venv
I was thinking about finding the issue in cpython about this and create a PR or issue with possible fix
i thought your error was going to be related to this one, https://github.com/python/cpython/issues/118973, but doesn't look like it, let me download 3.13.0 from python.org and check it out
not at all
i couldn't repro it
i think your problem might be with something in your $PATH
also if you compile cpython the issue is not there
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
my best advice i would say is to use windows sandbox so that you have a clean enviroment with no messy path shenanigans or a messy enviroment at all
I have tried using offical installer in fresh install of windows 10 vm
I can try in sandbox too
let me try copy pasting the amd64 directory in there
i mean to build the installer
ohh
well at the end its a vm
will try it tomorrow
its 00:25 here
adios
tried on fresh windows 10 vm
you need build tools correctly setup for them to work
well I already have v143 build tools installed
also 3.5 .net
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?
I only have the latest(v143) installed
let me see
https://basedbin.fly.dev/p/VG9I6o.txt looks like it
also
run the build process with full paths
same
are you following the devguide while doing this?
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
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.
what
the problem with building on windows is that there are so many variables to manage, so writing documentation is v ery miss
development of such big codebases on windows is shit
so what you need from the build tools is... get the 100% correct options. probably only 10 mb of data
on linux its much easier with libs available in package managaer, make and gcc
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
also for some reason microsoft wants to force visual studio just to compile
while its not a even a good editor
we may even get a time where devs stop building for windows
they just give source code and say compile yourself
just use WSL on windows
it requires windows to build for windows
you can't build for windows from linux
I tried it and it still doesn't build
also tried installing wix even though ti fetched that automatically but still doesn't work
hi
the stuff with universal v143 on it
I will try tonight thanks
hello
Is Flask the most useful tool for web app development with python? Or is there a better option?
Ask over in #python-discussion plz
Gotcha, thanks
looks like its compiling now
thanks
@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
I think you can download the build tools separately from Microsoft, if it wasn't removed again
…tion on Windows (GH-125250) (#125312)
gh-125235: Keep _tkinter TCL paths pointing to base installation on Windows (GH-125250)
(cherry picked from commit b3aa1b5fe260382788a2df416599325ad680a5e...
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.
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?
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
Like maybe with a kwarg for how many levels
Default being -1 to signify infinite levels
what if you pass a str
I mean not really, "flatten" isn't "flatten_all" or something like this
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
nice
I believe rust has struct from struct type naming for alternate constructors
Lots of languages have that approach in general
I meant this particular name for this particular concept
Start a new thread, and drop a link to it on the old thread
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`?
read from this line https://github.com/python/cpython/blob/main/Objects/dictobject.c#L340
Objects/dictobject.c line 340
The other half of the strategy is to get the other bits of the hash code```
and the other lines below
i cannot read owo
why does it do the for loop twice? i know it says manual loop unrolling, but why
Objects/dictobject.c line 994
static inline Py_ALWAYS_INLINE Py_ssize_t```
for performance
which is by manual loop unrolling
probably something related to it happening 2 times per iteration
well no shit
i dug through the blame and there's really no particular reason given
except "it's a hotspot and that probably improved the performance"
why doesn't that count as a reason?
it does
it's just the only reason i found
i misunderstood "except"
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
str is the correct operation for that, there's no alternative I've been able to find.
right, which is why i'm wanting to ask for a property method to be implemented
oh, I misread
Why isn't it pythonic though
I find that quite pythonic
because pathlib already provides multiple methods / properties which return things as a str object
!d pathlib.PurePath.name for example
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
''
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
what do you suggest it would be named?
strpath, fullpath idk_naming_is_hard
path.strpath wow, so pythonic
bikeshedding the name is kind of missing the point
.fullpath then
i think i'll open a DPO thread on this
yea, I don't hate .fullpath, tho that should probably be str(path.resolve())
but then we're back to using str, which is what i want to avoid
yea, my point is that fullpath makes no sense as a replacement for str(path), but it'd be useful as a separate operation.
going to use this
str(path) not necessarily equals str(path.resolve()), due to relative paths
In [16]: str(Path('a/b'))
Out[16]: 'a\\b'
and fullpath sounds like it would be the latter
(is what I think lakmatiol is getting at)
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
path == Path(str(path))
Is there anyone having good resources to learn python decorator?
I will advice this book. it is the most rich on Python specific sugarness, its gotchas, how to use and best practices
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
Thank you for the help, l’ll check this book! I am struggling with decorator
Is it possible to create chatbots with python and pythons framework ?
Discord is full of them
Web site chatbots
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 😭😭
Ask this in the #data-science-and-ml channel
Ask this in #discord-bots channel
Yeah? The difference comes down to interfacing with users on your website instead of Discord
#web-development may be the most relevant channel to ask questions about this
Got it
Is anyone using structlog? Is it better than the traditional logging library?
Please let me know
I think the real benefit is it's more machine parsable?
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):
Open an issue on CPython, explaining clearly what you want to add
alright!
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?
other than using gc.get_referrers()
What do you want to do based on the outcome? Perhaps this is a time for weakrefs
weakrefs don't work on lists
wrap them in a proxy class
soo how would i detect if the object inside can be garbage collected?
i.e. the only referrer left is the proxy
the container would hold a weakref to the proxy, and the proxy would be reclaimed if the container were the only referrer.
that sounds a lot like it relies on the proxy being passed around instead of the object but okay
yes, you would need to do that.
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())
It's tricky because gc.get_referrers can return an empty list when an object is reachable
Eg in the above case ^
You can use sys.getrefcount but it changes if you're in a generator/coroutine/both
it's unspecified when unreachable objects are collected
Right but they have to be collected eventually
Implementations aren't allowed to defer collection of unreachable objects forever
in fact when implementations self test they have to fix this function:
https://github.com/python/cpython/blob/ed24702bd0f9925908ce48584c31dfad732208b2/Lib/test/support/__init__.py#L799-L813
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()```
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"
It's not really possible to do with small integers
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
okay but what if i want to use weakrefs to unmodified list objects
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
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
Objects/typeobject.c
was wondering what channel to use to ask for advice
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...
because it takes time to build out stuff, 3.13 lays out the groundwork for future improvements.
I'm betting 5 years to get to where pypy is right now lol
a new python is released roughly every year, you might be surprised by what happens between now and then 😛
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.
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
it's like playtesting games
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
Mind sharing the benchmark?
So that interested early adopters will try it and provide feedback, like you will be doing when you give your benchmark to @final geode!
are you sure you built a performance build of cpython?
It's nothing special, just something that tests integer math and tight inner loops: https://gist.github.com/veegee/8860afdf289f2a5b5bae9b65f4e26368
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
"Release" means make a big stink about it everywhere and have very little to show for it.
Thanks, this is helpful. I’ll dig into it this week. Want me to ping you when I learn more?
Of course!
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.
Also, while I have you: are your results on main or 3.13.0? And your hardware/os?
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```
nogil is probably the bottleneck, not the JIT
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.
I'll try again without that
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 :\
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).
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```
JIT enabled performs faster than JIT disabled on your machine
@final geode so there's a very slight improvement vs 3.12 (which does 19s on the test)
I mean, 20% sure.
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**
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 😦
Yeah, the comprehension is much easier to JIT than the functional version.
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.
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 ❤️
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.
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 :/
And sys.addaudithook(None) breaks all kinds of REPLs in many versions and OSes
https://github.com/python/cpython/issues/125852
sorry for pulling back an old msg -- does this fix https://github.com/python/cpython/issues/118973 ? having trouble building the installer locally, i can't replicate your build on my box (definitely a VS noob issue, lol)
no I managed to compile python and installer also the issue was in path prefix which is now fixed
ah, gotcha. but that only fixes importing tkinter in a venv?
who knows pyqt5
It's my goal 🙂
oh it's mark
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?
this seems like a bug
Yeah, I don't think that's supposed to happen
That's definitely a bug. Could you make a CPython issue? Thanks
1 core dev was probably enough
Any message including the phrase "Aborted (core dumped)" is a core dev magnet
How does this test run? It's not in a class https://github.com/python/cpython/pull/126042/files#diff-1cab14f7e86d7fddf1d9a2cb12c3f5ef50844cf932eb67a97f7fb6acff8330c2R570
(cherry picked from commit 80eec52)
Co-authored-by: devdanzin 74280297+devdanzin@users.noreply.github.com
Co-authored-by: Bénédikt Tran 10796600+picnixz@users.noreply.github.com
Co-authored-by: Jel...
you can see that the same PR made changes to Lib/test/test_audit.py which execute that function from a unittest test method
I guess the setup for the audit tests is a bit baroque
I didn't check but I assume it runs the test in a fresh process so it can test the audit system in isolation
correct
Ah could do with comments why it doesn't use assertRaises
that embed 💀
it's Miss Islington: https://www.youtube.com/watch?v=iGx1hiSJbCo
Witch hunting season begins, and there is no fallacy in the reasoning of Sir Bedevere, the Wise~
!e () = []
someone recently brought this to my attention and its wild that it doesn't break
:warning: Your 3.13 free threaded eval job has completed with return code 0.
[No output]
makes sense
hey how could i remove a ban
That's off topic for this channel
Hi
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)
Looks like you can call it via https://github.com/python/cpython/blob/3.13/Lib/tkinter/__init__.py#L2459
Lib/tkinter/__init__.py line 2459
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)```
please report a bug
If you can call it via tkinter.Tk() even better
...or worse depending on your perspective
!e
import tkinter
tkinter.Tk(screenName=None, baseName='', className='\U0010FFFF')
: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
Ah it's not installed
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
Nice
Please raise a ticket and post the repro with tkinter.Tk also
I will, as soon as I get back from an errand. It found another in the meantime:
import sre_constants
sre_constants._makecodes("", {}, 10)
Hmm that's deprecated, can you get to that via re?
Could be troubling actually
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)
:warning: Your 3.13 free threaded eval job has completed with return code 0.
[No output]
!e
import sre_constants
sre_constants._makecodes("", {}, 10)
Hmm can't reproduce
What python version are you on? It's a worrying one because it all looks like pure python
: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'
I also get the unhashable TypeError for that code, tried 3.12 and main
main
Commit hash?
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
Well now your reward is that you have to git-bisect it
I checked out that commit and still couldn't reproduce (on macos)
can't repro on linux either
and what?
How to remove a ban is detailed when you join the discord and agree to the rules
and what?
i am not a discord nerd here i just didn't know so i asked
any problems?
This isn't the correct channel to ask in
Ok i didn't know dude
You can DM @summer lichen
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
I answered you in #c-extensions
It repros for me in a JIT build only (I should be more organized with my builds)
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
nice, definitely report this as a bug, I'm guessing @final geode will be very interested. (I haven't tried to repro)
Aborts on JIT+debug, segfaults on JIT main.
Yeah i did thanks
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?
cc. @crimson drum
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.
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:
\0refers to the null character, not capture group 0\YYYrefers to octal characterYYY, not capture groupYYY[\b]matches\x08. notb\xYYis hex characterYY- The maximum
mandnin{m}and{m,n}is4294967294, or2**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.
\0 refers to capture group 0 if you are in an r-string.
- documented
Groups are numbered starting from 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.
- documented, right after point no. 4
(Note that
\bis used to represent word boundaries, and means “backspace” only inside character classes.)
- 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 \\
- undocumented
https://docs.python.org/3/library/re.html
in other words, you have to get \ 0 to the regex engine, where it will mean group 0. r"\0 is one way to do that, "\\0 is another.
there is a capture group 0, it's the entire matched string.
that works?
i've only used it in re.Match objects
!e print(__import__("re").fullmatch(r"\0", "\0"))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
<re.Match object; span=(0, 1), match='\x00'>
it only makes sense in the replacement for re.sub. Perhaps the docs need to clarify that.
ah
#bot-commands message
docs actually match there
!e Also no print(__import__("re").sub(r"a", "a", "\0"))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
�
!e print(__import__("re").sub(r"a", r"\0", "a"))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
�
did you read what I said about r-strings?
@ruby elm in any case, you can make a pull request to improve the docs if you like.
Ah, I see I missed those in the re docs. I suppose then the question is should the re __init__ be updated to match that, since it gives an incomplete explanation?
there is: the complete matched string.
!e print(__import__("re").sub(r"a", "a", r"\0"))
0 index in match objects, sure, but \0 does not exist specially
:white_check_mark: Your 3.12 eval job has completed with return code 0.
\0
it's re.sub(from_, to, string) btw
!e print(__import__("re").sub(r"a", r"\0", r"a"))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
�
i see what you mean.
you can use \g<0> though
!e print(__import__("re").sub(r"a", r"\g<0>", r"a"))
:white_check_mark: Your 3.12 eval job has completed with return code 0.
a
tbf \g is undocumented
it's in the docs
for one small part?
what does that mean?
i see what you mean. That could also be added.
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)```
i wouldn't list the limits, since they are far larger than anyone will ever hit.
it feels like trivia
\g is explained in the re.sub part of the docs https://docs.python.org/3/library/re.html#re.sub
Unlike
\number,\g<number>supports a group number starting at 0, referring to the entire matched string.
or something similar
The backreference
\g<0>substitutes in the entire substring matched by the RE.
i mean that's not the section i expected it to be in
but it is re.sub()-only behavior
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?
I think it should give a concise summary, aiming for correctness but not comprehensiveness
Could be a good idea to add a line like "refer to the Python docs page for details"
i don't think we need to say "refer to the docs". We'd add that to every docstring.
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.
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
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.
.__doc__ vs .__doc_extra__
we should fix help(help) if we can.
help() is helpful
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
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'.
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.
But I think it'd be nicer if help(help) gave you help about the help system instead
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.
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
This wasn't my first instinct because help>x and help(x) work different. help(re) fails if re isn't in scope, but succeeds regardless of what re is in help>re
I see, so it's help('re') that does the same thing.
What's help>?
The help utility thing from help or help()
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.
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'
first type help, which gives you a help> prompt
then type help (or anything) in that prompt
oh there's a help repl TIL
I don't think anyone would actually do this unless they are purposefully trying to break it, but it is silly that it works.
Another thing you can do is (help(), help()) which makes you have to exit the help repl twice.
This is the _Helper.__repr__ is a repl?
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.
That's kind of asking for it, isn't it?
If you do [input() for _ in itertools.count()] you also get stuck
I mean yes, but normally even if you get the repl stuck you can ctrl+c to get out, but this is immune to even that.
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
anyone have strong opinions on docs signatures and language around args/kwargs? i'm curious if anyone has feedback on the discussions https://github.com/python/cpython/issues/125897 and https://github.com/python/cpython/pull/125945#discussion_r1816853024
maybe you'd be interested in: https://discord.gg/ygjd3XwJ
yeah, this issue is way in depth than i originally anticipated when reviewing it. extra eyes would be appreciated
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
you could report it, but i don't know if it will get fixed. breaking things with gc is typically your fault
That sounds like a bug to me. Silly tricks with gc.get_referrers aren't always fixable but this looks like a pretty normal way to use gc.
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
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
Weird that is_finalized() would have an effect here, I took a quick look at the code and don't see how it could have a side effect
Report a bug 🙂 That one is likely easy to fix
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()
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
you can report that, i'll take a look
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
Which one do you want first? gc aborts, tracemalloc segfault, curses abort or a strange grp one?
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)
Not sure this helps, but I can't get a repro if I use a stored lambda, seems to work only with a fresh one:
import gc
gc.freeze()
l = lambda x: None
gc.is_finalized(l)
gc.collect()
gc.unfreeze()
gc.collect()
# No abort
there's definitely something shady going on with the reference counts
i suspect DRC has something to do with it
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.
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
here's the context: #1302360304562339961 message
Because of the dual from package import module and from module import name
Since file is missing, python tries to interpret it as second thing. So . becomes current package's init file... where this import was, hence circular import error
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
yes
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?
maybe idk what you mean. When I try it, I get, "IndentationError: unindent does not match any outer indentation level"
On the stream of tokens level, that is. I'm not sure if that indentation error is raised by the lexer or the parser. I have no idea.
Does it try to 'round off' to the nearest indentation level below for error recovery?
it doesn't seem to do any error recovery. A dedent to a level not seen before is an error. Done.
So if it encounters this error, it panics. Hmm.
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?
Grouping symbols ignore whitespace, even if it's after a line break
And that doesn't happen in the parser?
I actually have no idea, to be honest.
That means the lexer must have a stack of open grouping characters (or at least a grouping count)
i don't have any insight into the inner workings. I just tried a bad dedent and saw what happened.
i think it has both, yeah
it only generates indents/dedents when in any type of grouping
You can experiment with python -m tokenize and type code at it
When outside one, you mean.
oh yeah
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: :/
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
yes, pure Python code like that should never crash
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
Thanks! Let me check.
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.
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)
go for it! new PR would be even better 😄
that one feels like it shouldn't be hard to fix
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()"
Can confirm (x64 Linux, 3.10-3.13)
Thank you!
!e
from _ssl import _SSLSocket; s =_SSLSocket(); s.do_handshake()
:warning: Your 3.13 free threaded eval job has completed with return code 139 (SIGSEGV).
[No output]
139 SIGSEGV
Also
python -c "from _pyrepl._minimal_curses import tigetstr; tigetstr('')"
Please file issues for these. Thanks
is there a proposal for Private and Protected type hints
Probably not, the __ and _ prefixes fill that role reasonably well.
#python-discussion is for general python discussions. Off topic discussions can go in one of the three off topic channels like #ot0-psvm’s-eternal-disapproval
__ = Private
_ = Protected (probably?)
so yeah
_private
__i_need_this_only_in_this_class
__protected__
don't make up your own __dunder__ names: those are for Python
I might have actually found something not in the re docs. The part about char sets [] says
Character classes such as
\wor\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\Aand\Z, which give a "bad escape" error.
Makes sense to me, those aren't characters or character classes themselves. I don't see how it would make sense to put them in a character class.
Although coming up with a good reason to put \b inside one is also hard.
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.
Octal/unicode/hex escapes don't work, they get parsed as the corresponding character by Python itself.
It's not all zero-width escapes though, since \b is also one. Interesting.
I'd say that they work, since they get transformed correctly even inside an r-string ```pycon
re.fullmatch(r"[\100]", "@")
<re.Match object; span=(0, 1), match='@'>
If they didn't work, I'd expect this to instead get parsed as an escaped `1`, followed by two `0`s.
That's because specifically in char groups, `\b` means backspace instead of word boundary.
Huh, indeed; mea culpa.
Interesting, didn't know \b meant backspace inside of brackets.
People seem to sort of make up their own dunder names a lot
Eg __version__ or __{pypi_name}__
yes. they shouldn't.
__version__ is particularly weird, as it's banned by docs.python.org but the pep 396 has a note saying it might be ok
_name is ill-suited for private, since it cannot exist in a subclass without conflicting.
Usually it is fine since your class won't be subclassed
__mylib_mything__ has a very low chance of collision with future cpython names
I would use sunders
Where do the docs ban __version__?
so its protected
Any use of * names, in any context, that does not follow explicitly documented use, is subject to breakage without warning.
Not every concept will map neatly from Java to Python
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"
or maybe "warranty void if broken", i.e. "if you touch this, all promises are off"
yep
Also sealed
So classes can be subclassed in one context but not another
New one, confirmations welcome.
python3 -c "import time; time.pthread_getcpuclockid(2)"
Segmentation fault
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
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)
Thanks!
reproes on main+macos but not 3.12+linux
main+linux aborts too
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
This is all thanks to Victor Stinner, he made a tool (fusil) in 2008 that found many segfaults, I just rediscovered it, added a few things and am running it when time allows. Talked to him and will publish it in a bit.
Aw, time.pthread_getcpuclockid is documented as being segfaulty:
https://docs.python.org/3/library/time.html#time.pthread_getcpuclockid
Interesting, that's not great for a Python-level function. Wonder if it's possible to validate the thread id so we can avoid the segfaults.
Looks like it's not possible:
https://github.com/python/cpython/issues/115378
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
Just install a SIGSEGV handler!
depending on how the function works in C you might be able to do more interesting things than get a segfault
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
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
!cban 1136816274303885322 We are not a server for hiring
:incoming_envelope: :ok_hand: applied ban to @near fiber permanently.
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
oops I wrote that code. Please send a bug and I'll work on it
What happened? Calling bytes_object.buffer(large_negative_number) in a debug build aborts with this message: >>> b"".buffer(-2**31 - 1) python: Objects/typeobject.c:9321:...
you keep giving me and bénédikt things to do 😅
Hii is there anyone who is preparing for PECP or had PECP?
disclaimer: no bugs will be harmed during fixing the issue
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:
- 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.
- 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
- 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?
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...
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
Ah, the heap_pop code was added last week in https://github.com/python/cpython/pull/123926
@glass mulch FWIW, the issue is that a subinterpreter can start running after the final destruction check, which breaks a lot
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)
oh yeah, i noticed that a little while back. i don’t think we’re doing anything with IDs right now so let’s leave it
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?
Got another one on main:
python: ./Modules/_interpretersmodule.c:462: _run_in_interpreter: Assertion `!PyErr_Occurred()' failed.
Aborted (core dumped)
that’s probably the exception problem i described in your other issue
yeah, leave it be. i’m not sure what eric is envisioning for incref and decref right now, so we’ll fix it later
This has a short repro, might help:
import _interpreters
_interpreters.exec(False, "aaaa", 1)
that looks like a different bug, report it
Oh, it segfaults on non-debug builds
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 🙂
could i be added? i want to see how it works
thank you!
Done. fusil_messy is what I have been running against CPython and now PyPy. fusil is the repo I want to make public, where I'll reconstruct the main fuzzer from fusil_messy, fusil_python_threaded.
i saw, thank you, fine w you if i fork for internal testing?
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.
Sure. Feel free to send open or address issues of you want, anything really.
awesome!
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 🙂
Is there a way to sandbox it?
<@&831776746206265384>
I have a weird issue in an issue, there's a reproducer for an issue that should only work on pypy but it works on 3.12.3 and 3.13.0 does anyone know what's causing it: https://github.com/python/cpython/issues/126775 see "Important Meta issue" heading
hi
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?
it is passed to __init_sublcass__ (and to the metaclass objects __call__)
__call__, really? That would imply it's called with the class already.
It should be __new__
!e
class Foo(metaclass=print, end='hello, world\n'): pass
:white_check_mark: Your 3.12 eval job has completed with return code 0.
Foo () {'__module__': '__main__', '__qualname__': 'Foo'}hello, world
yes i'm pretty sure it calls __call__
the secret to any class initialization is a __call__() call
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
TIL i don't need to specify type as a base when using metaclasses
it is slightly horrifying that this works tbh
esoteric python!!
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..
yes
you never know how many layers of objects you're gonna pass through
yea, that's what I meant with the metaclass object.
it does metaclass.__call__, not directly metaclass.__new__
TypedDictis not a metaclass, it's a superclass- it's passed to
TypedDict.__init_subclass__()
Thanks @flat gazelle ! That was super quick 🙂
I will check the specifics of __init_subclass__.
(type(metaclass).__call__)
ah yea, doing so directly gives you the descriptor smh
It does type(metaclass).__call__
Yes, I meant this metaclass: https://sourcegraph.com/github.com/python/cpython/-/blob/Lib/typing.py?L3125
!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
: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'}
ah
that's TypedDict's metaclass
or at least something to imitate TypedDict
since it doesn't necessarily use that
Lib/typing.py lines 3337 to 3338
_TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)```
yea, I forgot that you get the attribute before the descriptor protocol in this case.
TypedDict being a def-made object is a bit silly, what.
a what.
TIL TypedDict is not a class
Take a look at the typing_extensions backport if you want to find things that are even more fun
src/typing_extensions.py line 1042
@_ensure_subclassable(lambda bases: (_TypedDict,))```
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
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.
yea, the metaclass gets called, which then calls __new__
Reading discourse on pep 765. What on earth is GvR getting at with the for a[i] in ...: ... comment?
This is an excellent piece of research and perhaps we should do more PEPs based on such investigations. That said, I am personally sad to see this syntactic corner case disappear. To me, when I designed it, the semantics were always completely logical. (E.g., if you have two nested try/finally blocks, if the inner finally returns, the outer fin...
I think he's referring to the idea that for a[i] in range(10): is a suprise to people: that the loop target can be something other than a simple variable.
It is a surprise to me and when trying to Google it the AI said it's syntax error.
It does like an anti pattern
This seems so useless and convoluted
#bot-commands message
I have very rarely used it in cases like
config = {...}
for config['optlevel'] in 0, 1, 2, 3:
do_tests(config)
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
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 :(
if for can take tuple targets, why not non-name targets?
for {}() in range(10):
print("Ta da! Unused loop variable")
!e ```py
for [] in [[]]+[[]]+[[]]:
print('foo')
:white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | foo
002 | foo
003 | foo
THis is Guido's point: Python has primitive constructs that can be combined together in ways that "don't make sense" but you don't forbid all those ways, they just don't get used.
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.
That makes more sense. As does @flat gazelle example
I posted an even better example to Bluesky: https://bsky.app/profile/did:plc:w225kiqaw67ddpex4jmoo7rs/post/3lb5ehqs3qc2c
<@&831776746206265384>
please don't advertise in this server
Hello
Woahh
Since when 👁
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
I have just republished @vstinner's fuzzing tool fusil:
https://github.com/devdanzin/fusil
It's a library for creating fuzzers. I've been using it to find crashers in #CPython (23 found so far) and #PyPy (15 found so far).
The #Python #fuzzer works by generating random code with function/method calls using random arbitrary (and interesting) va...
Nice, could you update the change log?
@dusk comet should i focus on that repo then?
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!
hm? what repo?
https://github.com/devdanzin/fusil
as in, you're no longer going to work on those other private repos
We did for a little while, but that was simply because two different devs working on different components with different preferences
(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 )
(ironically in this project python was the user facing software and rust the backend... Which is why we moved it to js/web)
you must be confusing me with someone else
indeed, i was confusing you with @glass mulch , oops
iteration over set isn't ordered by insertion. does this mean iteration over set is O(buckets) instead of O(entries)?
answer: yes
since buckets/entries=O(1) it doesn't matter much
well no since you can add then remove loads of items
It's buckets+items, and because buckets<items it boils down to just items
Yes, that repo was a private one and now it's been made public. So many issues, so little time 🙂
I've added basic changes made to the changelog and expect to do it in a more rigorous way before releasing 1.6, thanks for the heads up.
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 😬
right, so no more private stuff, just focus on the public one? i'll open a PR or two soon
That's right. Wow, thank you very much! 🙂
"because buckets<items" this isn't ever true
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
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.
Applying the fix from https://github.com/python/cpython/pull/109761 solves the issue.
Fixes #109746.
If Python fails to start newly created thread due to failure of underlying PyThread_start_new_thread() call, its state should be removed from interpreter' thread states list ...
: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.
Hello
@raw night Hello, this server is not the right place to advertise your linkedin profile.
@grave jolt may I know the server which is right place for this ??
No, I don't know
: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.
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
: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
those yields work as expected
unpacking too
not sure where's the confusion here, but maybe i'm too used to it
unpacking has 2 different meanings in seemingly same contexts
yield i find more reasonable to be expected
but i feel like it could be interpreted that a = yield 'a' and b, = *g,
oh, i see
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)
This seems entirely unrelated to the channel and server
!cban @brittle stag spam
:incoming_envelope: :ok_hand: applied ban to @brittle stag permanently.
you meant the deleted spam, not messages above?
<@&831776746206265384> scam
!cban 1285208360328761477 scam
:incoming_envelope: :ok_hand: applied ban to @brittle sedge permanently.
sometimes i wonder if the server should have self-role access for this channel
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)
yes
is there a reason you're sending random messages in different channels?
yes for Voice Verification need 50 msg to complete
it needs to be organic, not spammy.
sorry man not trying to spam just trying to entry conversation
Because it's a thin wrapper around the C function https://en.cppreference.com/w/c/program/system and that's how it behaves
You can run two os.system calls in different threads
Better to just use subprocess.run though
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
that's intended
the interpreter returns a SyntaxError when the expression being unpacked has a precedence lower than the "bitwise OR" (|) operator

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
The // operation is made to return an integer value. However, when either operand is a float, the result is an integer in the form (type) of a float. I think there are several advantages to making this return an int. For one, there is no circumstance using the standard types where // would return anything other than an integer value, so having...
The real fun is that the type of the result of exponentiation depends on the sign of the exponent.
do you have an example
i don't think i got you right.
2**2 is 4 (an int), 2**-2 is 0.5
yeah that's what i first though but that makes sense i guess ...
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)]
now it's fun lol
FPE casually adding an insignificantly low number for the real side
>>> ((-1)**-1e-99*-1e99).imag
3.141592653589793
``` 😳
What is actually going on there? (too lazy to think about it)
(-1) ** -x as x approaches 0, the resulting imaginary part (without leading zeroes) approaches pi
no idea why tho :p
yeah that's not right tho, it should approach 0
lim (-1)^(-x) as x -> 0 should be 1
cool
it does approach 0
but the leading zeroes in the imaginary part also get infinitely many
infinitely big zero 🤯
Oh oops I read the second operation as a power, not a multiply
so as it approaches 0, the imaginary part essentially gets wiped out
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}")
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?
I hope so because I recently approved a change to 3.13 that relies on this property. Let me look it up.
https://docs.python.org/3/glossary.html#term-iterator "Iterators are required to have an iter() method that returns the iterator object itself"
Yeah, but this doesn't mean that it doesn't do e.g. ```py
def iter(self):
self.side_effect()
missiles.launch()
self.counter = 0
return self
True. I guess we could explicitly say that, I'd support a docs PR to make that change
It can do other things, can't it?
It can but it shouldn't
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__
I do think it'd be reasonable to have that be part of the semantics, yea.
That seems overly restrictive to me, and not necessary
Well, "not doing anything else at all" might be too restrictive
But not mutating the iterator seems reasonable
Well you can always ignore recommendations
IG you could put like logs or breakpoint() in there
They're saying to make it a requirement for something to be called an iterator, not a recommendation
Yeah exactly
Sounds good to me
Would be weird if my duck stopped quacking
My iterator should behave like an iterator
I'm not smart enough to know if mutating the iterator in __iter__ is enough to no longer behave as an iter, if you are, then fair enough, but you're much smarter than me 😄
that I would argue should not be allowed
You can always implement your custom methods, having standard methods with standard semantics and definitions does not stop you from doing that
if it were allowed, it would force every correct function handling iterators to carefully manage their iter calls
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
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
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?
Ask in #python-discussion , that's a better channel for this question.
ok thanks
Has there been any discussion of adding methods to the generator type, like map, filter, and limit?
But there's already syntax support for map and filter
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
the builtin map and filter aren't part of syntax, but I see what you mean about generators being a protocol rather than an exact type.
You don't need the built in map or filter
You just use generator expressions
ah, you are right (including about the syntax part--my apologies)
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
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?
In fact, you can already do something like ```py
Pipe(generator) | (map, lambda x: x * 2) | (filter, lambda y: y > 0) | (limit, 69)
but realistically, just using generator expressions or loops will be the solution in Python
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
parameter aliases?
yup
i think it's better explained with these examples ```py
f(is_XY=True) # True True
f(XY=False) # False False
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)
I mean, why do you want two different ways to name a parameter?
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:
convenience
no idea
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)
no, they are just anded
for those of us activating weapons of mass destruction from IPython
okay wait
i had this problem with my Vector class where i wanted to support giving x and y OR giving magnitude and direction
I would split it into Vector(x, y) and Vector.polar(4206.9, pi)
that would be nicer, yes
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
unfortunately i already implemented manual argument parsing to support both
if you add enough of those groups to a function, it starts to get bloated
yeah i guess there are better ways than this
💀
Was reading PEP 768 and wondering whether this would be useful for something like memray, until I read the list of authors :)
It will! 🤣
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))
1,2 - reminds me of a comma operator in C
3,4 - there was either a discussion or a pep about it, if I am not dreaming it up
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?
I think that's a newly added feature
Oh not quite what you say, skip_file_prefixes (added in 3.12) was what I was thinking of https://docs.python.org/3.14/library/warnings.html#warnings.warn
Tutorials
Ask in #python-discussion
@opaque solar I can teach you if you want and I will help you to earn certificate from Harvard online CS50
Please don't solicit people to contact you directly like this. If you want to help, see #1035199133436354600
Can you tell me how to get started from scratch learning python
has str? ever been considered as an alternative to str | None?
In terms of default arguments?
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?
This isn't the right channel
wich one is
If you're not sure on a channel use #❓|how-to-get-help
Yes. I think there was a discussion on the typing-sig mailing list
What did people hate about it?
I haven't looked up the discussion, but new syntax is always a hard sell, and I don't like that it special-cases None too much
what is necessary to formally get a PEP accepted?
That’s life with computer languages
the steering council thinking it's a good idea, i guess?
usually you'd precede PEP writing with a message to the Ideas category of discuss.python.org
the process is documented in https://peps.python.org/pep-0001/
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.
it's quite fuzzy 🫤
politics 😐
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"
more politics sigh
okay
@rose schooner i understand why you don't write PEPs :p
What kind of process do you have in mind that doesn't involve "politics"?
Why assume politics in technical subjects?
i'm pretty sure that would derail the topic here, but let's say "focus on merrit of the idea, not the person"
if i were to write a PEP it would be about a great feature that isn't any of the toys i currently have amassed in cpython4
(some of them might be great features but i don't like making arrangements with the public in general)
question is whether it might be better to get approval for a toy first and gradually make bolder proposals or make the boldest proposal first in hopes of getting less bold proposals approved instead..
if it were based on merrit of the idea instead of person, the order wouldn't matter, but alas..
