#internals-and-peps

1 messages · Page 30 of 1

verbal escarp
#

a grammar that has not a single english word in it doesn't look like python to me :p

rose schooner
#
def foo(l):
    l.append(1)
    return l

x = []
foo(x) += 2,
print(x)  # [1, 2]
#

better example

#

calls which you can do augmented assignment on

#

ooh i just had an idea for julia-style functions

verbal escarp
#

ok?

rose schooner
#

i don't even know what point i'm trying to make

verbal escarp
#

i'm curious though

rose schooner
#

so first of all i rarely have great ideas
second of all i don't have my thoughts in order

#

third of all i'm scared of controversy

verbal escarp
#

order is for the feebleminded

rose schooner
#

i'm feeble minded :3

verbal escarp
#

don't share it then :p

rose schooner
#

share what-

verbal escarp
#

your idea

rose schooner
#

it's a good idea currently

#

sometimes ideas already have stuff i can build upon in my toy collection

#

so it makes it easier to implement

#

but it bothers me that my toy collection is about 2 years deviated from the current python/cpython

verbal escarp
#

i'm surprised the for-if change worked so flawlessly once you gave me the hint about the make parser

#

and that's with the current 3.14 code

#

can i propose a pep to adopt latex-style versioning from 3.14 on? 🙂

#

or rather Tex

#

adding more digits to approach pi

rose schooner
#

nvm

#

nvm nvm

#

nvm nvm nvm, i'm getting worked up over nothing

#

can we have a something like ```py
type foo(x: int, y: int) = str

verbal escarp
rose schooner
verbal escarp
#

what's the str? return type?

rose schooner
verbal escarp
#

why not have it type foo(x: int, y: int) -> str?

rose schooner
#

maybe

#

it's still a hypothetical atp

verbal escarp
#

it seems logical to me, since we already have that for defs

#

so you could just copy&paste the function head

rose schooner
#

ooh that just solved another idea problem with my julia-style function declarations

feral island
#

what makes you think it's based on the person?

verbal escarp
feral island
# verbal escarp politics usually is

There are both PEPs by very well-connected people that get rejected (recent example: PEP 760) and PEPs by people outside the core team that get accepted (example: PEP 692). I can't guarantee that personality plays zero role, but clearly it's not the major one.

#

Also, you talk about technical merit as the alternative. I don't think many of these decisions can be purely technical; they are based on a social judgment of what things would be acceptable to the community.

jade raven
#

😦 for PEP 760, i liked it

verbal escarp
feral island
#

It's not

verbal escarp
#

what's the point of a council if they can't rule against public opinion and make unpopular decisions? then we could just put everything to public vote

shy grove
#

Public voting can be easily abused

#

Making them meaningless

#

Especially for something as popular as python

verbal escarp
#

depends on the system

shy grove
#

Public (including me) also like to think about "I would love this feature right now" and less of "How will this look in python after 10 years"

verbal escarp
#

what's so bad about that? we gave up a unified vision when guido quit

jade raven
#

guido didn't exactly quit did he? he just changed roles

flat gazelle
#

I don't think popular votes are all that useful tbh. Most changes are only bad for a minority of usecases, but that's still a Python usecase

verbal escarp
#

i would say he quit and now enjoys his old days doing what he wants without bothering with politics

verbal escarp
flat gazelle
#

If the council doesn't have the power to decide, why bother with it?

verbal escarp
#

in most cases proposals require expert knowledge, dedicated people to work through the process. but it doesn't require expert knowledge to understand if a change would negatively affect you in your specific case

#

so public veto would essentially formalize an "outcry" when people realize that a certain change negatively impacts them

flat gazelle
#

isn't that the point of PEPs

verbal escarp
#

not really?

#

there's the informal step on -ideas, but it's not representative

feral island
#

How would you envision a representative election among the whole Python developer community working?

verbal escarp
#

representative election as in council?

feral island
#

An election that is representative, which is what you appear to want

verbal escarp
#

public veto wouldn't require representation, you could just make a poll (with some caveats)

feral island
#

So the side wins that's best at getting their friends to click a button on the Internet

verbal escarp
#

as i said, with some caveats

#

also, it's not about winning in this case

#

it's about losing

#

it's not "do you want this feature?" but rather "do you NOT want this feature?"

#

the worst case would be status quo

verbal escarp
feral island
#

Right, just as nobody would rally their friends just so a ship gets called Boaty McBoatface

verbal escarp
#

only the council could propose to call the ship Boaty McBoatface. the public only could say "that's crazy, this can't pass!"

#

the public could petition the council for proposals, but the council has no obligations to follow through

raven ridge
inland acorn
#

The whole point of a elected council is that you don't have to bother the entire community for every decision

verbal escarp
#

i'm not proposing to bother the entire community for every decision

#

i'm proposing to give the community a chance to veto changes so the council can propose more bold changes without having to worry that the community could complain afterwards not having had a chance to stop it

inland acorn
verbal escarp
#

a minimum amount of votes to start the poll, then some percentage?

raven ridge
spark verge
#

What about a citizen council?

winged sphinx
verbal escarp
cerulean isle
raven ridge
radiant garden
#

A public veto system is a disproportionately reactionary form of governance that incentivizes language decisions that aren't necessarily great, but are inoffensive. I say disproportionately reactionary because it does not distinguish between apathy and support (only highlighting dissenting opinions) and caters towards users that dislike change overall (by magnifying their opinions on new, not-yet-shipped features). Maybe the idea can be remedied using something like a big public-beta phase, but at that point you can just collect feedback normally.

flat gazelle
#

I do think being very adverse to change is a good idea when it comes to Python

verbal escarp
#

scipy geeks vs AI nerds vs web devs

#

shrug

verbal escarp
raven ridge
#

Sure, but a vote of no confidence solves the same issue, right?

#

The steering council makes a big decision without considering your needs, so you replace them with a new steering council that will consider your needs

radiant garden
verbal escarp
#

not really. it makes it all about personal issues while it's supposed to be about technical issues.. i know it's a thing in RL politics to associate a certain decision to a vote of no confidence, but that always comes with a taste of "it's my way or the highway". in german politics, we have a second instance where the länder have a chance to veto law proposals to exactly get that effect - back to the drawing board without making it a personal issue

radiant garden
#

but i'd say that one is more extreme than the other

verbal escarp
#

a vote of no confidence would directly result in new elections and until the whole process is re-established, the original issue is off the table and nobody will want to touch it again to avoid another desaster

#

i rather think it should be a kind of dialogue, a back and forth

#

only because a proposal was veto'ed, it doesn't have to mean people have to be afraid of getting mobbed off the board just for mentioning it

#

maybe the whole walrus debacle could have been avoided that way

#

dunno

raven ridge
#

The steering council makes decisions based on their understanding of the needs and desires of the community, and in particular they are reluctant to make changes that many core devs oppose

verbal escarp
#

if vetos were an explicit process, the steering council could go for broader strokes, maybe with the risk of getting veto'ed, but not to a point where they couldn't continue working, and if there's opposition, it's not about who is loudest anymore

uneven raptor
#

...isn't the job of the SC to do the vetoing? why do we want vetos for the vetoers?

verbal escarp
#

i don't think the job of the SC is to veto 🙂

uneven raptor
#

well, what is it then?

verbal escarp
# uneven raptor well, what is it then?

as i see it, it's the interface between the public and the core devs. come up with proposals, based on input. i wouldn't say filtering or policing ideas is their job but rather mediate

uneven raptor
#

core devs are supposed to talk to the public too

verbal escarp
# raven ridge The same is true for vetoes

"a minimum amount of votes to start the poll, then some percentage" would at least give two parameters to tune the size and loudness of that minority necessary to have an impact

raven ridge
#

And if it's a public poll, it's easily gameable with bot farms or Mechanical Turk or whatever

#

And if it's not a public poll, then the higher barrier to entry makes it even more likely that only people who have strong negative opinions will vote at all

verbal escarp
#

those are three different issues :p

#
  1. yes, but: someone who is directly impacted by a change can get strongly motivated even though they are usually not. in python that's probably maintainers of important packages (thinking of annotations and beartype, for example) who normally don't care about politics, but get strongly motivated to voice their concerns if they realize that their stuff won't work anymore
raven ridge
#

Those people are already represented well by the current process, right?

verbal escarp
#

not really. remember the debacle with annotations?

uneven raptor
#

they voice their concerns on the DPO thread and it's taken into account before something gets accepted

raven ridge
uneven raptor
#

is there a case of that happening?

raven ridge
#

Even though they got involved very late in the process, after a decision had ostensibly been made, they brought new data forward that caused the decision to be unwound and a new path pursued

verbal escarp
verbal escarp
uneven raptor
verbal escarp
#

uff.

flat gazelle
#

github accounts is a huge sampling bias

#

as is anything else

verbal escarp
winged sphinx
#

I for one am glad that my vote has no bearing nor that of other people like me who know as little as I about the inner workings and history and complexities involved (genuine opinion, not just a joke)

uneven raptor
flat gazelle
#

Yea, it was to be implemented, then people who use non-type hint annotations took issue with it

verbal escarp
uneven raptor
#

right, so what would a public veto vote have done?

verbal escarp
raven ridge
verbal escarp
winged sphinx
verbal escarp
raven ridge
#

the right people are getting involved and representing their constituencies

raven ridge
uneven raptor
verbal escarp
raven ridge
#

in fact - if anything, I suspect the veto wouldn't have passed

#

the constituency that cares about annotations for things other than types is so much smaller than the constituency that cares about annotations for type hints, and the issue is so wonky and difficult to wrap your head around, that it's unlikely the maintainers of the libraries who deeply care about annotations for things other than type hints would have been able to rally support for a veto. The steering council listened to their needs despite that

verbal escarp
#

well. a veto poll would've put a number to that, now we could just speculate

flat gazelle
#

I don't think a number matters. Breaking an entire usecase like that should be avoided regardless of how many users it ends up affecting

raven ridge
#

exactly. This is a thing that's handled well by the small circle of deciders responsible for representing everyone model, and not handled well by a popular vote model

flat gazelle
#

if a change helps 90% of users and forces 2% of users into never updating Python again, it shouldn't happen.

verbal escarp
raven ridge
#

exactly!

#

the steering council should be representing the entire Python community, by gathering feedback on proposals even from small constituencies with uncommon use cases

flat gazelle
#

Python is a vast language, it is possible no one near the language leadership knew about that 2%.

verbal escarp
flat gazelle
uneven raptor
#

so, you want a "steering senate"?

verbal escarp
raven ridge
#

I'm not seeing what you're basing that claim on - you've only provided an example where the sampling was sufficient

verbal escarp
raven ridge
#

I don't understand what you mean by "crisis" or "ad hoc" here

#

the proposal was determined to be fundamentally flawed as it relates to those use cases, and so it was shelved - a veto would have accomplished the exact same thing, right?

#

and a new proposal that does address those use cases was instead proposed instead

verbal escarp
#

as far as i understood, the situation was that they were about to release new code, already had everything ready. then they got hammered with "oh shit, stop it!" and everything was put on hold with no clue how to proceed

raven ridge
#

how would the process have been any different if the SC were veto-able?

verbal escarp
#

depends on the implementation?

raven ridge
#

someone came in at the last minute with a new concern for delayed evaluation of annotations that caused everyone to slam on the breaks. A veto would have at best achieved the exact same result

verbal escarp
#

you asked why i think the sampling is lacking, i've got some anectodal evidence

#

lambdas

#

why do many (most) people think lambdas suck and (like guido argued once) should be removed from the language? because the use-cases where they are useful - GUIs and networking - are nowhere near the core language dev

raven ridge
#

networking is very, very near the core language dev - a massive amount of investment into asyncio has happened over the last few years

verbal escarp
#

that was before asyncio, then guido learned that one-off functions do have a purpose

uneven raptor
#

there are also 6 core dev experts for idle and tkinter

raven ridge
verbal escarp
#

i'm shocked you remember

verbal escarp
#

@raven ridge i'm exhausted. was nice talking to you 🙂

raven ridge
#

my understanding of why the deferred annotations thing led to such drama is that the maintainers of at least one of those big libraries using annotations for something other than types not only waited until the last minute to voice their concerns, but then also advocated for their community members to complain directly to the Steering Council - a "call your representative and tell them not to break your favorite library!" sort of thing

#

it was chaotic - but the way in which it was chaotic is exactly the way in which public calls for vetoes of already-accepted and implemented features would be chaotic (since people would need to rally their constituencies to advocate for a vote, and then vote to veto). So the proposal to enshrine public vetoes in the governance model would only cause more of that sort of chaos, not less

winged sphinx
raven ridge
#

totally predictable from the PEP alone; the implementation had been ready for literally years under a __future__ import

spark verge
verbal escarp
raven ridge
#

The entire abstraction is built on callbacks

#
$ git grep callback Lib/asyncio | wc -l
236
spark verge
raven ridge
#

I'm not sure what "task first" means, but I suppose I shouldn't generalize: asyncio is full of callbacks, at least, even if other async libraries aren't

#

There's 58 matches for "callback" in trio, fwiw

#

Lots in docstrings, but about 30 seem to be real code

spark verge
#

Most are related to guest mode, ExitStack or ssl

raven ridge
#

There's a callback in ParkingLot.park, which is used very heavily

#

More than 200 matches for "Callable[" too. There's plenty of callbacks in this code base

spark verge
#

Usually they're handlers

#

Eg they're async functions that get scheduled later

spark verge
#

What I'm saying is there's no continuation passing

#

Also curio is a bit more pedantic about not having callbacks

swift imp
#

I thought the stringifying type hints pep is what was breaking say pydantic, and not the deferred eval pep

#

The deferred eval pep was to actually be a working replacement for the stringifying pep

#

Did deferred annotations get cut out again?

raven ridge
feral island
#

Deferred evaluation is going to be in Python 3.14

swift imp
#

I remember the discourse being one of the bigger ones

hot aurora
dusk comet
#

it is not even syntactically valid

unkempt rock
#

While

raven ridge
#

that's not even the only syntax error

feral island
#

took me a while to find the other one

unkempt rock
#

it's ok

#

maybe i rely a bit too much on syntax highlighting

pseudo hemlock
#

@hot aurora I have this mug

hot aurora
spark herald
#
def load_words():
    """
    Returns a list of valid words. Words are strings of lowercase letters.
    
    Depending on the size of the word list, this function may
    take a while to finish.
    """
    
    print("Loading word list from file...")
    # inFile: file
    inFile = open(WORDLIST_FILENAME, 'r')
    # wordlist: list of strings
    wordlist = []
    for line in inFile:
        wordlist.append(line.strip().lower())
    print("  ", len(wordlist), "words loaded.")
    return wordlist
boreal umbra
#

Has anyone used weakref in "actual" code? I'm interested to know why and how.

swift imp
swift imp
#

And I want the stored value to be released when the owning instance is garbage collected

spark verge
#

Use it for marking regions that can receive keyboard interrupt

spark verge
raven ridge
dusk comet
#

it is only possible if the object supports weakrefs, which is not always the case

flat gazelle
# boreal umbra Has anyone used weakref in "actual" code? I'm interested to know why and how.

I was writing a UI library of sorts, and I needed a list of all widgets, but someone could write code like this and repeat it several times across the application runtime

def on_click1():
    foo.contents = Text("Please select an option")
def on_click2():
    foo.contents = Button("continue")
``` and so just naively maintaining a list would keep those stale Text and Button objects around until shutdown. It would be possible to track whether an object is attached or detached as part of the objects and manually remove them from the list, but a collection of weakrefs can end up nicer.
deft pagoda
#

like, might keep a weakset of all Focusable widgets, because widgets have a lot of state and you don't want to keep them alive if other references are gone

granite heath
spark verge
granite heath
idle fjord
#

s

#

howdy gng?

deep spoke
fallen slateBOT
#

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

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

grave jolt
#

@steel solstice Am I missing something? Your last comment is correct, slice instances are still not subscriptable, it's the slice class https://github.com/python/cpython/pull/128336

- Make :class:`slice` objects subscriptable at runtime.
+ Make the :class:`slice` class subscriptable at runtime to be consistent with `typeshed <https://github.com/python/typeshed/issues/8647>`.
(or something to that effect)
steel solstice
#

yeah I think I miscommited

swift imp
#

Why do we want slices to be generic though. For what purpose

steel solstice
#

slices can have different parameters to the familiar ints, the old implementation left them as Any and changing that would have been too disruptive without default type parameters, but they can now hold any types as there start, stop and step so they are better typed in the cases they use datetimes or anything other than ints

swift imp
#

That discussion reminded me that pep 637 got rejected.

verbal escarp
# boreal umbra Has anyone used weakref in "actual" code? I'm interested to know why and how.

i've used it to implement a flyweight pattern something like ```py
import weakref

_id2name = weakref.WeakKeyDictionary()

class Thing:
slots = ("id", "weakref") # Add weakref to support weak references

def __init__(self, id_):
    self.id = id_

@property
def name(self):
    return _id2name[self]

def add_name(thing, name):
_id2name[thing] = name # int isn't weakrefable, needs to be the Thing itself

Example usage:

if name == "main":
thing = Thing(1)
add_name(thing, "Alice")
print(thing.name) # Alice

#

has some benefits on memory consumption and i find it easier to fiddle with attributes to a large number of objects on the fly

#

the weakkeydict takes care of cleanup if the thing is deleted

merry venture
unkempt rock
astral gazelle
#

<@&831776746206265384>

torpid bridge
#

!pban 1297923384692441129

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied ban to @modest flower permanently.

merry venture
fallen slateBOT
#

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

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

raven ridge
#

core dev friends: my understanding is that the end goal of the free threading project is to get to a point a few years down the line where the GIL is gone and cannot be reenabled at runtime.

@uneven raptor believes that the goal is to get to a point where it's no longer possible to build an interpreter without free-threading support, but that it will always be possible to create a GIL at runtime if an extension module doesn't support free threading.

Which of us is right?

uneven raptor
#

also for the core devs: if he's right, i'm curious about why. won't removing the runtime GIL break the compatibility for the extensions that don't support it?

spark verge
#

The current goal of the free threading project is to fix all the threading issues in the stdlib and also some work getting the ecosystem working with free threading

neat delta
# spark verge https://peps.python.org/pep-0703/#python-build-modes pep is pretty clear

yeah,

The author believes a worthwhile goal is to combine these build modes and have the global interpreter lock controlled at runtime, possibly disabled by default. The path to this goal remains an open issue, but a possible path might look like the following:
[...]
3. After another 2–3 release (i.e., 2028–2030), CPython switches to the GIL being disabled by default. The GIL can still be enabled at runtime via an environment variable or command line flag

spark verge
#

I suspect it will become clear in the future if that's necessary

#

If the GIL is universally disabled it will probably be deprecated and removed

#

But it's not a goal of the free threading project

#

It's still in the "get the damn thing working" phase

neat delta
#

perma-removed GIl might be significant and backwards-incompatible enough to justify the enormous leap to python 4, too

spark verge
#

Nah

#

Python 3 is a brand

spark verge
uneven raptor
#

not limited API ones

spark verge
#

Like the wheels install and run, they just don't behave correctly

raven ridge
# neat delta yeah, > The author believes a worthwhile goal is to combine these build modes an...

we're disagreeing about how to parse the SC's acceptance message in https://discuss.python.org/t/pep-703-making-the-global-interpreter-lock-optional-in-cpython-acceptance/37075, and in particular the phrase

Some time after the default flip, when we have a good indication it’s no longer widely used, we should start the discussion on removing the GIL build entirely.

Zero thinks that's just about removing the --disable-gil option (and whatever its contrapositive is). I think that's about removing the GIL.

#

I realize that the short term goal is definitely just "get it working", but my understanding is that the long term goal is to reach a point where the GIL no longer exists, and core devs don't need to do 2x the reasoning about correctness.

neat delta
#

hmm, it sounds like the SC and the pep author may have differing ideas. need for a coredev opinion, indeed

grave jolt
#

To me mentioning the "GIL build" suggests that "the distribution of Python without the t letter" will no longer be issued officially, but could still be built customly if you really needed it. But it could be kinda ambiguous

raven ridge
#

yeah, that's definitely what that wording says, but it doesn't match what I've heard from core devs (and SC members 🙂)

neat delta
#

has the idea been suggested to ask in the discuss thread? last comment is from march 2024, but it's not locked

uneven raptor
raven ridge
grave jolt
#

Well, removing the t letter build is a prerequisite to removing the GIL entirely, so I guess they could start the discussion on the former before talking about the latter

#

so you could both be right (in the future)

raven ridge
uneven raptor
raven ridge
#

both

neat delta
#

The details of the phases are deliberately vague, simply because we can’t know all the ecosystem impact details yet
shame wouters has no discord account here (afaik), but i'm not sure the SC knows the answer yet

raven ridge
#

heh. Pablo does have one, but I don't think he pays any attention to it, and in any event it's 1 AM for him 😄

uneven raptor
# raven ridge both

for -Xgil=1, how so? the free-threading team has put tremendous effort into keeping it backwards compatible

raven ridge
#

I'm confident that it's possible to omit a call to PY_BEGIN_ALLOW_THREADS and have your code work when the GIL has not been created but fail when it has

uneven raptor
#

yeah, but that's a legitimate bug. you can't omit Py_BEGIN_ALLOW_THREADS on FT because it breaks critical sections

raven ridge
#

yes, it's a legitimate bug - I never said it wasn't

uneven raptor
#

right, i could crash on FT with only the GIL enabled by doing if (_PyEval_IsGILEnabled(_PyThreadState_GET())) { abort(); }, but that's my fault

raven ridge
#

er - sure, but that's a hard bug to write accidentally

#

omitting a call to PY_BEGIN_ALLOW_THREADS is an easy bug to write accidentally

uneven raptor
#

i guess so. but i'm not sure that means it's a good idea to remove the -Xgil option

feral island
jade raven
crisp locust
#

NO GIL Python should be Python 4 since it will be a breaking change. Like Python 2 to 3

raven ridge
#

Python releases breaking changes in minor versions, there's no need for a new major version

grave jolt
#

yeah, Python doesn't try or advertise following semver

verbal escarp
#

next version after 3.14 would be 3.141 and so on, adding more digits towards pi

#

thus putting the neverending python 4 discussion ad acta

grave jolt
#

smh stealing

verbal escarp
verbal escarp
grave jolt
#

tried that with the jury, didn't work

#

had to return the TV

verbal escarp
#

hrhrhr

#

i mean, we're already making tons of p[y|i] related jokes as a community, so why not

#

the major version numbers are dead after 3, there's no point in pretending

grave jolt
#

I am making a wikipedia page on pyi jokes, but for now it's a stub

verbal escarp
#

😄

#

versioning is pretty much arbitrary anyway - we could even just use github commit hashes and celebrate prime numbers

grave jolt
#

Well, both pi and the current scheme have an advantage over commit hashes. You can more easily figure out which is newer

verbal escarp
#

sure, ok.

#

if that's the major benefit we're aiming for, we could just go the ubuntu way and use year.month

#

but the current scheme suggests we're still hanging onto semver

#

and eventually there will be some grand py 4

#

at least year.month would make it easier to figure out how long a version will be supported

fallen slateBOT
grave jolt
#

Another benefit of the current versioning scheme is that previous Python versions also used it 😉

verbal escarp
#

i would prefer the pi scheme though to follow through with self-deprecating humor - "there will never be a py 4!"

verbal escarp
raven ridge
#

It gets very annoying after 5 or so versions

#

It works ok for Tex because Tex evolves much more slowly, and is basically in bugfix only mode now. But imagine trying to tell people "it's not working because you're using Python 3. 1415, but that feature wasn't introduced until 3.141592". Sounds very un-fun.

grave jolt
#

I am really getting old, I forgot all the digits of pi

raven ridge
#

And pi-based versioning doesn't work for how Python represents versions in the stable C API, anyway, so it's a moot point. Nothing that breaks the limited API is gonna happen

#

!d Py_Version

fallen slateBOT
#

const unsigned long Py_Version```
*Part of the [Stable ABI](https://docs.python.org/3/c-api/stable.html#stable) since version 3.11.*

The Python runtime version number encoded in a single constant integer, with the same format as the [`PY_VERSION_HEX`](https://docs.python.org/3/c-api/apiabiversion.html#c.PY_VERSION_HEX) macro. This contains the Python version used at run time.

Added in version 3.11.
verbal escarp
#

so we're stuck with "let's do py4!" discussions

verbal escarp
# fallen slate

that wouldn't go away though - it's just how it's presented that changes

raven ridge
#

!d PY_VERSION_HEX

fallen slateBOT
#

PY_VERSION_HEX```
The Python version number encoded in a single integer.

The underlying version information can be found by treating it as a 32 bit number in the following manner...
grave jolt
#

Ah, hex. Something to do with curses

raven ridge
#

You get the minor version by looking at bits 9-16 of Py_Version. Which means the highest possible minor version is 255, so the highest representable "pi-versioned" version number would be 3.141, you can't do 3.1415

verbal escarp
#

we'd need a mapping, but we'd need that with any other scheme, too

#

i mean, android does that - just use a simple number internally to check for updates, and presentation can be anything

raven ridge
#

That sounds even more horrible than the horribleness I described above. "that feature wasn't introduced until 3.141592, which was the 4th minor version after Python switched to pi based versioning in 3.14, so you need to check if the minor version reported by the interpreter is at least 14+4 to test if that feature is available"

verbal escarp
#

after 3.14 that is

raven ridge
#

Also, patch versions ruin the joke. And also, it seems un-fun to distinguish between Python 3.14.1 and 3.141.0, or 3.141.5 and 3.1415

raven ridge
verbal escarp
raven ridge
verbal escarp
#

ah

verbal escarp
#

kinda

raven ridge
#

No, it would be 3.year.patch, with an implication that there will never be more than 1 minor version per year

verbal escarp
#

it's weird, i don't like it. dropping the "3." and just keep counting is more elegant

#

it achieves the goal of being able to tell versions apart easily

#

gets rid of the py4 discussions. simple, no confusion about the meaning of the leading "3."

#

switching to a date-based schema midway is more confusing, i think

#

just imagine how you would have to explain it to a newbie

#

i'd say the pi-schema would even be less annoying

uneven raptor
#

IIRC the complaints about dropping the leading three is that “python 26” reads as 2.6, not 3.26

verbal escarp
uneven raptor
#

it’s kind of hard to if the version starts with 2

wanton flame
jade raven
#

but i don't wanna use python 2.6!

raven ridge
#

And then that problem goes away after 5 years once we'd hit Python '30

wanton flame
uneven raptor
raven ridge
#

Only redundancy. It feels pointless to say "3." once we codify that everything will always be "3." forever

flat gazelle
#

slugs are fairly typically just [a-z0-9-]+, so they are just kind forced into the ambiguity. But they already do python314, so it's kind of fine.

uneven raptor
raven ridge
#

Only in the context of what sorts of breaking changes might happen. But no one wants a Python 4

#

I think it's more likely that we'd see a fork of the language than see Python 4

flat gazelle
#

I'm not convinced shifting the entire versioning scheme 11 versions forward is actually going to simplify understanding Python versions within the next decade or so.

raven ridge
#

I think it's a small improvement. At the very least, it gives a pithy answer to "when will we get Python 4": "maybe in 2100"

wanton flame
raven ridge
#

Explaining that takes more work than saying "maybe in 2100", though

#

And realistically, we don't need to decide what the version number will be in 2100 until ~2098

wanton flame
#

shorter version: "when will we get Python 4": "never" 🙂

flat gazelle
grave jolt
#

Imagine waking up in 2101 and now having to port from 2 to 4, that's going to be an even bigger undertaking

jade raven
wanton flame
#

yes, if it's accepted, and if it's accepted with that text

jade raven
#

oh, hugo is here
@wanton flame how's the PEP looking like?
i meant to do a silent ping, didn't work, sorry bout that

uneven raptor
#

well, there could be a superseding PEP if they really wanted a python 4 someday

steel solstice
#

I honestly much prefer the idea of just python 26

spark verge
#

Or 2026

#

What happens in year 4026 and we get version 2026 it will be confusing

jade raven
#

double it and pass it to the next person /s

wanton flame
feral island
#

which is now this year, so I assume they'll be working on a decision soonish

finite mirage
fallen slateBOT
#

failmail :ok_hand: applied timeout to @quasi talon until <t:1736438826:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).

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

rich sluice
#

Can I create an image processing project using Django?

unkempt rock
fallen slateBOT
#

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

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

fallen slateBOT
#

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

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

raven lark
#

Does anyone have a c++ server

spark verge
grave jolt
#

I forgot... what's the point of abc.ABC allowing you to execute the body of an @abstractmethod?

#

The documentation says:

This could be useful as an end-point for a super-call in a framework that uses cooperative multiple-inheritance.
but in that case don't make the method abstract, no?

raven ridge
#

You can use it when the base class knows some of what needs to be done to implement a particular method, but not everything

grave jolt
#

If it does something useful, then it seems plausible that "every widget needs to define how it gets rendered" is not true (maybe just a lack of imagination from the base class author)

raven ridge
#

Because if it wasn't, nothing would enforce that a subclass overrides it, and the parent class doesn't contain a complete implementation, just something that can be delegated to in order to start the work or to finish it

raven ridge
flat gazelle
#

Does it have to be the same method? Usually I'd just make two methods in this case

raven ridge
#

It doesn't, and you could do that. Making it the same method is just an option

grave jolt
#

The reason I don't feel very well about this is: most ABCs I worked with don't make use of this feature, but if you don't remember to add a raise NotImplementedError, you get a potential footgun. To me it would make sense to make this an optional thing you have to opt into

#

Like ```py
@abstractmethod(fallback=True)

raven ridge
#

The implementation of an abstract method is usually pass, not raise NotImplementedError

#

If you make it raise NotImplementedError, you need to know the MRO

grave jolt
#

if it returns None, possibly

raven ridge
grave jolt
#

If the method returns None and an empty action makes sense in that case, then yes, it makes sense to have ```py
def method(self):
pass

or

@abstractmethod(fallback=True)
def method(self):
pass

raven ridge
grave jolt
fallen slateBOT
#

flink-python/pyflink/datastream/functions.py lines 70 to 82

@abstractmethod
def get_state(self, state_descriptor: ValueStateDescriptor) -> ValueState:
    """
    Gets a handle to the system's key/value state. THe key/value state is only accessible if the
    function is executed on a KeyedStream. On each access, the state exposes the value for the
    key of the element currently processed by the function. Each function may have multiple
    partitioned states, addressed with different names.

    Because the scope of each value is the key of the currently processed element, and the
    elements are distributed by the Flink runtime, the system can transparently scale out and
    redistribute the state and KeyedStream.
    """
    pass```
raven ridge
#

The raise NotImplementedError approach is fundamentally incompatible with cooperative multiple inheritance, as far as I can see, unless every subclass implementation of the method either a) examines the MRO to decide whether or not to make a super() call, or b) unconditionally makes the call but suppresses any NotImplementedError

grave jolt
#

But it doesn't make sense in the case where the method is never expected to return None

#

which is why I thought it would be good as an opt-in when you know about this feature, not an opt-out

flat gazelle
#

When the method is never expected to return None, you need to implement a different default. But yea, this is surprising behaviour for sure.

grave jolt
fallen slateBOT
#

Lib/typing.py lines 2855 to 2863

@runtime_checkable
class SupportsInt(Protocol):
    """An ABC with one abstract method __int__."""

    __slots__ = ()

    @abstractmethod
    def __int__(self) -> int:
        pass```
grave jolt
#

and type checkers don't complain about this

flat gazelle
#

Yea, it does seem like library authors don't really know how to write their classes WRT multiple inheritance

grave jolt
flat gazelle
#

Yea, that I don't know. Tho at least __int__ is unlikely to participate in any delegation chains

grave jolt
#

maybe it's more of a type checking issue, and type checkers should just treat abstract method bodies like ordinary bodies

flat gazelle
#

hm, that would make a lot of common patterns inexpressible.

#

IG the simple answer is to just be very careful about using multiple inheritance.

grave jolt
flat gazelle
#
class AbstractStorage[T](ABC):
    @abstractmethod
    def take(k: object) -> T:
        pass
    @abstractmethod
    def give(v: T) -> object:
        pass
```I don't really see how you'd implement `take` here
#

in a typesafe way

#

IG you just have to use a protocol and not inherit from it

#

if you want to write something like AbstractStorage and use multiple inheritance

grave jolt
#

Why not raise NotImplementedError in the abstract implementation?

#

Oh, if you want that

#

Well, presumably you want to raise some exception if the T or object was not found or something like that. You might raise that instead

flat gazelle
#

Yea, that'd work.

fallen slateBOT
#

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

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

strange burrow
#

I'm working on a project which includes an emulation of the behavior of Python's module global scope. I noticed that while all of the initial module globals can be deleted as one would expect, for whatever reason doing del __builtins__ simply replaces the module it is bound to with a dictionary containing all of the builtin names (in CPython 3.13.0). All future deletions of this name do nothing.

It makes sense why this happens, since actually deleting __builtins__ would make all the builtin bindings inaccessible. But doing something like __builtins__ = 3 correctly rebinds the name to 3, and therefore breaks the builtin bindings. Is anyone aware of why these evidently contradictory behaviors occur, or know where in the CPython docs/code I could look for an answer myself?

frigid bison
fallen slateBOT
#

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

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

strange burrow
strange burrow
#

but you can still use builtin functions after deleting __builtins__ and builtins, so I guess there is some other reference to the builtins aside from that

#

Another fun thing is that if you del __builtins__.len in the interpreter, the interpreter crashes since for whatever reason that code deletes the interpreter's len function

feral island
strange burrow
#

Yeah that makes sense, should also when executing a script

#

Does anyone know why the interpreter would share builtins with the program it is interpreting?

#

All I can think of is that it is technically more performant to run the python code natively rather than actually interpreting but that would mean the interpreter could maybe just be a loop around exec at that point

feral island
#

The REPL is basically a loop around exec

strange burrow
fallen slateBOT
#

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

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

vague trout
#

!rule

fallen slateBOT
#

The rules and guidelines that apply to this community can be found on our rules page. We expect all members of the community to have read and understood these.

merry venture
#
fallen slateBOT
#

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

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

tough light
#

I got hacked

fallen slateBOT
#

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

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

acoustic dragon
#

Stop spamming images.

#

Please stop spamming images.

#

<@&831776746206265384>

torpid bridge
#

!pban 1304594867132825721

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied ban to @spare garnet permanently.

boreal hatch
#

welp, looks like my stand fixed it for me

acoustic dragon
#

thanks Luna

boreal hatch
#

:p

#

no, thank bast

acoustic dragon
#

op

boreal hatch
#

off into the great beyond i go

#

-# weeeeeeeeeeeeeeee

acoustic dragon
#

Good bye

dusk comet
#

currently we use _ variable for throw-away values: ```py
_ = f() # function returns something, but we explicitly dont care
begin, _, end = s.partition(sep) # throw away the separator

for _ in range(n): # do something n times, dont care about iteration counter
do()

match f():
case foo(): ...
case bar(): ...
case x: ... # everything else, we do need the value
case _: ... # everything else, we dont need the value


this is fine, but it binds a real variable called `_` ||(except for match-case situation, where `_` is considered a keyword)||

what do you think about using `...` as assignment target?
```py
... = f()
begin, ..., end = s.partition(sep)

for ... in range(n):
  do()
astral crane
#

Wait can you do that? I thought variables could not have special characters

radiant garden
#

has too much connotation of *_ due to numpy's usage

raven ridge
#

Huh - I like that idea. That would have been a better wildcard pattern than _ for the match statement, too

winged sphinx
#

Your post has been removed. This isn't a job board. If you'd like to discuss career and how to conduct a job search, visit #career-advice

merry venture
#

very subtle advantage in the repl, no conflict with _ that is implicitly assigned the most recent value

feral island
#

The conflict with _ for the most recent value does regularly annoy me in IPython. I'll write a, _ = b() and then suddenly I can't use _ anymore to get the most recent value

merry venture
#

it also makes sense semantically, since ellipsis signifies a missing value.

#

more!

#

i think it can also be of speed up advantage, couldn't it?

#

imagine we iterate over range(100) like for ... in range(100).

#

the interpreter can know to not assign ... another element

#

otoh this a, ..., b can be a little unobvious at first glance. in math it is often semantically closer to a, *_, b

#

while a, ..., b in fact means a, _, b

merry venture
#

so if we iterate over a collection that produces new elements, those could be destroyed immediately in many simple cases... correct?

#

though not in case of structural unpacking.

#
for (..., ..., ...) in triples:
    ...

would require a temporary reference to every next element of triples in order to attempt to unpack it to (..., ..., ...)

#

but in case of ```py
for ... in whatever:
...

we'd never need any references to consecutive elements of `whatever`.
merry venture
#

i think it would as well be useful to allow ... as a target in signatures.

#

some functions have to take unused arguments for interface compatibility.

#
def foo(*..., **...):
    print("passed arguments are accepted, but the function never uses the passed-in objects and thus never increases the refcounts of any of them")
#

wdyt about this @feral island?

#

cc @dusk comet @raven ridge

merry venture
#

... would then not require a type annotation (inferred from parent methods or Any (i think object would be inconvenient for some variance-related cases)), and foo() could only be called with one positional argument at the beginning and at the end

#

this wouldn't support standalone keyword parameters though.

#

but there is no need for such

dusk comet
# merry venture cc <@575681145929203724> <@451976922361102357>

I like it

some advantages of ... assignment target:

  • on bytecode level STORE instruction could be replaced with POP, which in theory should be faster
  • it does not introduce local variable, which saves a bit of memory.
  • earlier you drop the reference, earlier the value will be GCd, which should lower average memory usage in some cases
#

about def f(*...): not sure how often that pattern occurs

merry venture
#

they suggested ? instead of ...

merry venture
dusk comet
merry venture
#

indeed

though ... would probably be only useful if "parents" for args were strictly positional

#

imagine ```py
class Parent:
def foo(self, arg, arg2, arg3):
...

class Base(Parent):
# imagine arg in foo() as unused here.
# can't use ... for arg, because it is both positional and keyword
def foo(self, arg, arg2, arg3): # :/
...

dusk comet
#

def foo(self, arg..., arg2, arg2): 🥴

merry venture
#

this resembles syntax for variadic args in other languages

dusk comet
#

btw type stubs use ... as a default value for arguments

merry venture
#

like C++ etc.

merry venture
#

and applied to all over typeshed

radiant garden
merry venture
#

🤔

#

maybe i'm not talking about the same thing

radiant garden
#

Callable[..., T]

merry venture
#

i believe we're not talking about the gradual form used for Callable

radiant garden
#

well then let's do that

merry venture
#

but for RHS values of defaults in signatures, e.g. foo: int = ..., bar: int = ...

radiant garden
#

right ye

merry venture
dusk comet
#
def foo(n: int = ...) -> int: ... # n has some default value, we don't specify it here

SomeCallableType = Callable[..., int] # accepts any args, returns int
#

so there are actually two places in typing where ... is used

feral island
uneven raptor
#

i like it, but my biggest concern would be:

... = 42
print(...)  # Ellipsis?!
dusk comet
#

these two ...'s look similar but do different things:

(a, ..., b) = foo # throw away the middle item
p[a, ..., b] = foo # numpy stuff, idk
grave jolt
dusk comet
tiny pelican
#

can anyone help me with the choice makin one code

winged sphinx
tiny pelican
boreal umbra
#

something I've thought for a while would be nice to have is a context manager that force-exits the context after a specified amount of time. is that something that would become possible without the GIL?

strange burrow
#

i'm not too familiar with async python but it would seem that the context body would have to periodically ping and see if time is up? or otherwise define some cleanup procedure that could work after any intermediate instruction of the body

#

but i guess that would be up to the user

fallen slateBOT
#

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

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

spark verge
spark verge
boreal umbra
spark verge
#

Yeah, see thredo it just works even with the GIL

winged sphinx
spark verge
#

You couldn't cancel the body of a context manager with an interpreter pool

#

You have to be able to pickle the function you want to execute, you can't just send a particular block of code

flat gazelle
#

couldn't you send a SIGINT and hope that the interpreter notices a KeyboardInterrupt sooner rather than later?

spark verge
#

Works only on the main thread

#

The keyboard interrupt handler could see the frame it gets raised in to see if it should raise an exception

#

You'd probably use sigalrm

grave jolt
#

A quick sanity check before I make an ill-informed discourse post... Is it generally true that resetting the state of an iterator in the __iter__ method like this is wrong and should never be done in Python code? ```py
class MyRange:
def init(self, start, stop):
self.start = self.n = start
self.stop = stop

def __iter__(self):
    self.n = self.start
    return self

def __next__(self):
    if self.n >= self.stop:
        raise StopIteration
    self.n += 1
    return self.n - 1

``` (because it makes it impossible to pass this iterator where an iterable is expected, including for loops, making it pretty much useless)

spark verge
#

Don't for loops only call __iter__ once?

inland acorn
spark verge
#

Well it's not wrong you're just rewinding it in some circumstances

inland acorn
#

Should a iterator do that tho? Let me check if docs say anything on this

grave jolt
#

the docs don't say anything about this

inland acorn
#

A container object (such as a list) produces a fresh new iterator each time you pass it to the iter() function or use it in a for loop. Attempting this with an iterator will just return the same exhausted iterator object used in the previous iteration pass, making it appear like an empty container.

grave jolt
# spark verge I'm not sure if it's wrong

For example, consider this itertools recipe (from 3.11 docs): py def batched(iterable, n): "Batch data into tuples of length n. The last batch may be shorter." # batched('ABCDEFG', 3) --> ABC DEF G if n < 1: raise ValueError('n must be at least one') it = iter(iterable) while batch := tuple(islice(it, n)): yield batch It doesn't seem to have any unusual preconditions. If it is MyRange, this is going to yield completely wrong results, as islice will reset the iterator on each call.

grave jolt
#

hm... that just seems like a note of caution to users of iterators, not an explicit requirement (even if advisory) for iterators

#

maybe I'm reading it wrong though

inland acorn
#

@grave jolt

Once an iterator’s next() method raises StopIteration, it must continue to do so on subsequent calls. Implementations that do not obey this property are deemed broken.

grave jolt
#

Actually, maybe that works. Interesting.

inland acorn
#

Tho that is specifically talking about the stdlib afaik

#

But it's a very strong argument for why you shouldn't do it

grave jolt
#

That doesn't prohibit resetting the state on an infinite iterator, but that's a less frequent occurrence anyway

inland acorn
#

(imo the easiest way to implement __iter__ on a collection without having to define a extra class is to just make it a generator)

grave jolt
#

The motivation for the question is: I've seen several low-quality pages (ex. 1, ex. 2, ex. 3, ex. 4) suggest that an __iter__ of an iterator can or even must reset/initialize its state.
I mostly wanted some piece of docs to easily show that no, this is not how Python iterators are normally supposed to work

inland acorn
#

Yhe the closest I have found is that a iterator that raised stop iteration can't be reset

grave jolt
#

well, this example iterator from geeks4geeks doesn't violate that rule ```py
class EvenNumbers:
def iter(self):
self.n = 2 # Start from the first even number
return self

def __next__(self):
    x = self.n
    self.n += 2  # Increment by 2 to get the next even number
    return x
inland acorn
#

Right, __iter__ does say

Return the iterator object itself.
But unfortunately doesn't explicit rule out side effects

grave jolt
#

Correctness aside, I like how this code example straight up ignores the steps for making an iterator class just above it

inland acorn
#

Argh, a lot of places just state "... can just return self" implying it could do more

#

@grave jolt there's also this in the FP section of the docs

Note that you can only go forward in an iterator; there’s no way to get the previous element, reset the iterator, or make a copy of it

#

That last one is very arguably false tho

spark verge
inland acorn
spark verge
#

asyncgenerator is built in

grave jolt
inland acorn
#

I seemingly can't read

#

But I guess that's a strong contender for it being allowed as well

grave jolt
#

that doesn't mean that it's appropriate in __iter__ though

#

For example, you can .seek() on a file object

inland acorn
#

True, honestly I can't find anything that explicitly says it's bad

grave jolt
inland acorn
#

Hmm, time to open GitHub issue? /hj

grave jolt
#

insert link to the /hj video

inland acorn
#

I suppose the definition might mean "... it must continue to do so on subsequent calls. assuming no other methods are called on the object"

#

Or something along those lines

grave jolt
#

other methods, like __iter__? 🙂

inland acorn
#

I suppose yhe

#

Huh list iterator actually obeys it, it will happily iterate new elements assuming it wasn't exhausted

#

!e ```py
x = [1,2]
y = iter(x)
for _ in y: pass
x.append(10)
for e in y: print(e)

fallen slateBOT
inland acorn
#

!e ```py
x = [1,2]
y = iter(x)
next(y)
next(y)
x.append(10)
for e in y: print(e)

fallen slateBOT
grave jolt
#

This doesn't break the rule, because the iterator had never produced a StopIterator exception before you added the 10

inland acorn
grave jolt
#

ah

#

yeah

inland acorn
#

Kinda surprised it likely has a flag for it or something

#

Honestly I think the strongest argument for resetting in iter being wrong is that it breaks the itertools examples

grave jolt
#

Unrelated but... array.array has no clear method?

#

!e

from array import array
xs = array("i", [420, 69])
xs.clear()
fallen slateBOT
inland acorn
#

Huh

grave jolt
#

smh lies in the typeshed

inland acorn
#

!e 3.13

from array import array
xs = array("i", [420, 69])
xs.clear()
fallen slateBOT
inland acorn
grave jolt
#

ah

inland acorn
#

Smh should have looked at the docs

feral island
#

was that one of the things we added because otherwise array was lying about being a MutableSequence?

grave jolt
#

I mean, it kinda makes sense to have clear, since lists also have it

feral island
#

yep ```$ python3.12
Python 3.12.3 (main, Jan 16 2025, 20:46:45) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

import collections.abc, array
issubclass(array.array, collections.abc.MutableSequence)
True
collections.abc.MutableSequence.clear
<function MutableSequence.clear at 0x1045abba0>
array.array.clear
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'array.array' has no attribute 'clear'```

grave jolt
feral island
#

don't do it

grave jolt
#

that's essentially my problem... I wouldn't do that, but I don't know if there's a place in the docs saying that I shouldn't

feral island
inland acorn
feral island
#

I guess the docs say iterator.__self__ should return self but not that you shouldn't do other random stuff in it

inland acorn
grave jolt
#

I understand that my questions may sound stupid, because there are uncountably many wrong things you can do

#

but for some reason this particular wrong thing comes up on the first two pages when I search for "python iterators"

sharp socket
#

Whoa. Is this where the PEP magic happens for Python meowthumbsup

grave jolt
#

nope

sharp socket
#

deadge disappointment

merry venture
#

(everybody is invited)

graceful needle
#

hello guys, i’m a college student who really sucks at python and i just need like a tutor or something. i try to study on my own but i dont really know how. im currently in Advanced Python Application Class but i dont remember a lot from Python Scripting Class, please help

winged sphinx
dusk comet
fallen slateBOT
#

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

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

grave jolt
spark verge
#

The coolest bit is f_generator

candid grove
#

I want to deepen in python memory management.

def generate_data(start, end):
    return list(range(start, end))

def get_data(count=1):
    result = list()
    start = 1_000_000
    end = 2_000_000
    for counter in range(count):
        result += generate_data(start+counter, end+counter)
    del result
    return

get_data(count=1)
get_data(count=10)
get_data(count=10)
get_data(count=10)
gc.collect()

for example, when I run this code on my machine and track the Python process, memory usage goes up from 10MB to 27MB
But if I run the same code with end = 10_000_000, the memory usage stage on 10MB, can anybody explain this behavior?
The second test.

def generate_data(start, end):
    return list(range(start, end))

def get_data(count=1):
    result = list()
    start = 1_000_000
    end = 10_000_000
    for counter in range(count):
        result += generate_data(start+counter, end+counter)
    del result
    return

get_data(count=1)
get_data(count=10)
get_data(count=10)
get_data(count=10)
gc.collect()
spark verge
#

!rules 6 9

fallen slateBOT
#

6. Do not post unapproved advertising.

9. Do not offer or ask for paid work of any kind.

spark verge
candid grove
spark verge
candid grove
raven ridge
uneven raptor
#

memray’s documentation has a great page about the python memory allocator

fallen slateBOT
#

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

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

boreal umbra
#
In [1]: if 1 + 2 == 4:
   ...:     pass
   ...: else:
   ...:     pass
   ...: elif 1 + 2 == 3:
   ...:     pass
  Cell In[1], line 5
    elif 1 + 2 == 3:
    ^
SyntaxError: invalid syntax

If I wanted to make this error message more informative, where in the cpython code base should I be looking?

winged sphinx
boreal umbra
boreal umbra
#
... more gross gcc output above
                             output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command '['/home/python.exe', '-W', 'ignore::DeprecationWarning', '-c', '\nimport runpy\nimport sys\nsys.path = [\'/tmp/tmpikvdd___/pip-24.3.1-py3-none-any.whl\'] + sys.path\nsys.argv[1:] = [\'install\', \'--no-cache-dir\', \'--no-index\', \'--find-links\', \'/tmp/tmpikvdd___\', \'--root\', \'/\', \'--upgrade\', \'pip\']\nrunpy.run_module("pip", run_name="__main__", alter_sys=True)\n']' returned non-zero exit status 1.
make: *** [Makefile:2330: install] Error 1
root@3f02464a54a4:/home# which python3
/usr/local/bin/python3
root@3f02464a54a4:/home# python3
Python 3.14.0a4+ (main, Jan 26 2025, 00:49:54) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
warning: can't use pyrepl: No module named 'msvcrt'
>>> if True: pass
... else: pass
... elif False: pass
  File "<stdin>", line 3
    elif False: pass
    ^^^^
SyntaxError: elif not allowed after else

let's goooooooooooooooooo

#

there was another error message I wanted to change, but I forgot which one

boreal umbra
#

Looks like my solution causes a different syntax error to cause the wrong message

    if something:
        pass
    elif something_else:
        pass
    else:
    pass

this doesn't give the correct message for the indentation error.

quick snow
#

Is there a way to force a thread never to give up the GIL (until I tell it to)?

rose schooner
#

python/cpython#29513 python/cpython#119974

rose schooner
#

python/cpython#119724

neon troutBOT
rose schooner
#

TL;DR that is kind of unadvisable (for now)

#

it's easier to teach that "elif follows if and comes before else" (and it also comes as common sense) than add complexity to have a special error for it

#

but i guess it's useful when the blocks get too big

uneven raptor
fallen slateBOT
#

sys.setswitchinterval(interval)```
Set the interpreter’s thread switch interval (in seconds). This floating-point value determines the ideal duration of the “timeslices” allocated to concurrently running Python threads. Please note that the actual value can be higher, especially if long-running internal functions or methods are used. Also, which thread becomes scheduled at the end of the interval is the operating system’s decision. The interpreter doesn’t have its own scheduler.

Added in version 3.2.
spark verge
uneven raptor
#

i thought that would fall under the category of “until I tell it to”

boreal umbra
feral island
raven ridge
# raven ridge In general, no

The special case where it would be possible is when you write a C extension module, and create a block of code that never explicitly releases the GIL, and never calls anything that implicitly releases the GIL, and never calls into any Python bytecode (including by creating objects with a __init__ written in Python, or destroying objects with a __del__ written in Python). Note that this implies that it cannot allow the GC to run. And even this won't work in a free threaded build of the interpreter, of course

boreal umbra
fallen slateBOT
#

Grammar/python.gram line 1184

_PyPegen_check_legacy_stmt(p, a) ? NULL : p->tokens[p->mark-1]->level == 0 ? NULL :```
raven ridge
boreal umbra
raven ridge
#

ah, I see... I think you'd need to add state to the parser to handle that (not just whether the line is indented, but whether the thing it's inside of is an if or else or elif block)

#

e.g. you wouldn't want to suggest that the elif is at the wrong indentation level for ```py
for i in range(10):
if i % 3 == 0:
print("divisible by 3")
else:
print("not divisible by 3")
elif i % 2 == 0:
print("divisible by 2")

boreal umbra
#

Exactly

#

And you already know that the parser isn't stateful enough for that?

exotic star
#

sorry

fallen slateBOT
#

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

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

raven ridge
#

actually, you'd need to know specifically that that there's an if or elif block above at a lower indentation level, but not an else

#

since you wouldn't want to make that suggestion for this, either: ```py
if done:
print("exiting")
else:
if i % 3 == 0:
print("divisible by 3")
else:
print("not divisible by 3")
elif i % 2 == 0:
print("divisible by 2")

#

I don't think there's any chance that the parser already has that state, that's very specific

quick snow
raven ridge
#

it'd also just break in ~3 years when we have a Python without a GIL

uneven raptor
#

it's easy on FT if you're willing to use the private API

#

marking the interpreter as finalizing will prevent threads from attaching a thread state, and you can force all threads to detach with a stop-the-world

raven ridge
uneven raptor
#

i think that would only be if the runtime was finalizing, not if the interpreter was

raven ridge
#

even for the main interpreter?

uneven raptor
#

yes

#

daemon threads are weird with subinterpreters

raven ridge
#

I didn't realize that the main interpreter being finalized and the runtime being finalized were two distinct states

#

Normally those two things happen in tandem

uneven raptor
#

it's a gray area IIUC

#

sometimes it falls back to the main interpreter even if the runtime says it's not being finalized

#

but in general special-casing the main interpreter for anything is bad

merry venture
fallen slateBOT
#

autohelper/framework/features.py lines 121 to 129

exceptions = []
for hook in hooks:
    try:
        hook()
    except Exception as exc:  # noqa: BLE001
        exceptions.append(exc)
if exceptions:
    msg = "Error calling configuration hooks"
    raise ExceptionGroup(msg, exceptions)```
spark verge
#

EG is mainly for concurrent calls

merry venture
#

it doesn't have to be, i want to not fail early

spark verge
#

I think it's uncommon enough that it shouldn't be in the stdlib

merry venture
#

ok, that would be an argument

spark verge
#

It would encourage people to use it instead of comprehensions which fail early

#

Running everything and failing if any is also quite tricky to name

merry venture
#

makes sense. this functionality could be part of a third-party package

#

something like jaraco.functools could fit

spark verge
#

Omg the jaraco package

merry venture
#

been helping to get it typed

#

need to reiterate on that though, i think

#

oh wow jaraco/jaraco.functools#23

neon troutBOT
merry venture
#

quite some time passed since. maybe one day i'll get back to it

#

now i see a subtle mistake there

#
  1. hold strong references to instances we store IDs of, because once they are no longer strongly referenced by any object, those IDs may point to something else.
#

this assumes objects with no strong references to them are immediately freed

#

but otherwise it's ig mostly valid

rose schooner
naive saddle
round path
fallen slateBOT
#

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

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

timid token
#

s

inland ether
#

Hi

languid forge
#

Hello

winged sphinx
fallen slateBOT
#

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

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

feral pendant
raven ridge
#

The full code of what? I don't understand what you're asking for

boreal umbra
#
In [3]: def func(*args, **kwargs):
   ...:     print(args, kwargs)
   ...:

In [4]: class foo(func): pass
# nothing is printed
TypeError: function() argument 'code' must be code, not str

I'm not sure what to make of this.

grave jolt
# boreal umbra ```ipython In [3]: def func(*args, **kwargs): ...: print(args, kwargs) ...

https://docs.python.org/3/reference/datamodel.html#metaclasses

By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace)
If func was a type, like Cat, this would do: ```py
class Foo(Cat):
bar = 42

m = type(Cat)
Foo = m("Foo", (Cat,), {"bar": 42})
``` the same thing happens in your case, except m happens to not be a metaclass at runtime

#

!e
Example:

class Foo(slice(0)):
    pass
print(Foo.start)
print(Foo.stop)
print(Foo.step)
fallen slateBOT
grave jolt
#

(well, I omitted some elements from the namespace dict)

merry venture
fallen slateBOT
spark verge
#

Damn

radiant garden
#

it is of my opinion that this is appropriate

neat delta
#

while i did not like the pep, @wanton flame, i nonetheless hope that its rejection does not bring you too much unhappiness. my feelings were not personal, and i know you were trying to make things easier for others, including newbies

spark magnet
#

I think i probably told this story somewhere here before... At PyCon last year, Guido and Hugo were talking about the calver proposal. Guido said, "Why start with 3.15, why not do it for the next release?" Hugo said, "well, there's a lot of tooling to update, and people have to get used to it, etc." Guido said, "That doesn't seem like it would take so much time." Hugo: "We also don't want to skip 3.14 (pi)". Guido: "Why didn't you just say so!"

raven ridge
#

Hah, I do love that this is a language where that whim would be taken seriously!

wanton flame
wanton flame
solemn hound
#

why when i try to run a script it auto closes???

rose schooner
#

function type subscription like we do for classes?

#
class A[T]:
    ...

x = A[int]()


def oper[T](...):
    ...

t = oper[str]()
radiant garden
#

I believe that was a pep for that

#

!pep 718

fallen slateBOT
desert iron
#

I want to learn php, do you have any suggestions?

spark verge
fallen slateBOT
fallen slateBOT
#

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

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

woeful olive
spark verge
#

for the does not block from IO part

woeful olive
round path
boreal umbra
round path
quick snow
round path
spark verge
#

I like the note: This is not to be confused with tail call optimization of Python functions, which is currently not implemented in CPython.

#

The wording is more hopeful than previous attempts to do tco

round path
#

I don't think I meant to be optimistic about TCO in Python. But you never know. If the JIT optimizer goes well, we might even get TCO even with working tracebacks. That's super super far out though.

spark verge
#

What's the difference between PTC and TCO? I think one's the what and the other is the way?

round path
#

My understanding is PTC is a language feature, TCO is a "compiler optimization".

spark verge
#

PTC is no visible stack frames in this case and no expansion of memory for recursion/co-recursion. And TCO is the conversion of code into branch/jumps?

round path
#

Hmm not sure

spark magnet
#

Proper Tail Call

#

I think @kenjin has it right: PTC is a language guarantee, and TCO is a technique to achieve PTC, or to use even if the language doesn't guarantee it.

spark verge
#

You can get PTC without TCO right?

spark magnet
#

I'm not a fan of "Proper" as a way to describe something, seems needlessly judgmental

spark magnet
spark verge
#

I thought TCO was replacing stack operations with jumps and branches

spark magnet
#

seems like PTC is "we guarantee a tail call won't grow the stack" and TCO is "a tail call might not grow the stack"

spark magnet
spark verge
#

I also thought that PTC results in recursive functions that are slower than loops but don't grow the stack

#

And TCO was that plus recursive functions were just as efficient as the iterative version

spark magnet
#

¯_(ツ)_/¯

flat gazelle
#

As defined by the scheme report, PTC means every tail call is guaranteed to not grow the stack, regardless of what procedure is called. TCO is an optimalization technique where the stack growth may be omitted.

#

so basically what you said

winged sphinx
flat gazelle
#

it does neither of these things

#

it is a completely separate thing

winged sphinx
#

Oh. Then I still don't.

flat gazelle
#

it is a novel way to implement interpreter loops in C that is better than while(true) switch(opcode)

spark magnet
# winged sphinx Oh. Then I still don't.

the What's New should include something like, "This is an implementation detail of the CPython interpreter. It doesn't change the visible behavior of Python programs at all. It improves their performance, but doesn't change anything else."

round path
#

(or anyone here can open a PR too if they want)

raven ridge
#

This is not to be confused with tail call optimization of Python functions, which is currently not implemented in CPython.
That's not exactly true these days. Tail calls of Python functions now grow the Python stack, but don't grow the C stack

spark magnet
raven ridge
fallen slateBOT
round path
round path
round path
#

Though you're also right that in 3.11, we made it much easier to implement tail calls if we wanted in Python.

raven ridge
round path
winged sphinx
#

Also: I think it'd help to reference the GitHub issue rather than the PR.

round path
winged sphinx
#

Oh. The notes do reference other issues rather than PR's. 66436 for instance.

round path
#

Oh good point! Guess I was wrong.

#

I updated Ned's PR to point to the issue instead.

merry venture
grave jolt
#

Speaking of map... Is it documented anywhere that map will also stop producing items if the given function raises a StopIteration exception?

#

or is that something that you're supposed to have guessed

#

!e

def f(x):
    if x == 5:
        raise StopIteration
    else:
        return x + 10

print(list(map(f, [3, 4, 5, 6, 7])))
fallen slateBOT
grave jolt
#

same with filter and other functions, actually

inland acorn
fallen slateBOT
inland acorn
#

It doesn't stop, it just lets the exception propagate which causes the caller to assume it stopped

grave jolt
#

!e
For example, if a generator function raises StopIteration, it's transformed to a RuntimeError and not "propagated"

def my_genf():
    yield 1
    yield 2
    raise StopIteration

print(list(my_genf()))
fallen slateBOT
# grave jolt !e For example, if a generator function raises `StopIteration`, it's transformed...

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

001 | Traceback (most recent call last):
002 |   File "/home/main.py", line 4, in my_genf
003 |     raise StopIteration
004 | StopIteration
005 | 
006 | The above exception was the direct cause of the following exception:
007 | 
008 | Traceback (most recent call last):
009 |   File "/home/main.py", line 6, in <module>
010 |     print(list(my_genf()))
... (truncated - too many lines)

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

grave jolt
#

!e
In fact, if you try to implement map yourself:

def f(x):
    if x == 5:
        raise StopIteration
    else:
        return x + 10

def my_map(f, it):
    for x in it:
        yield f(x)

print(list(my_map(f, [1, 2, 3, 4, 5, 6, 7])))
fallen slateBOT
# grave jolt !e In fact, if you try to implement `map` yourself: ```py def f(x): if x == ...

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

001 | Traceback (most recent call last):
002 |   File "/home/main.py", line 9, in my_map
003 |     yield f(x)
004 |           ^^^^
005 |   File "/home/main.py", line 3, in f
006 |     raise StopIteration
007 | StopIteration
008 | 
009 | The above exception was the direct cause of the following exception:
010 | 
... (truncated - too many lines)

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

inland acorn
grave jolt
#

Of course, that's probably the explanation of how map came to be like this

#

but from the perspective of the user of map, that's probably not the most obvious behaviour

#

(if you're trying to debug why map is not producing the right amount of items)

fallen slateBOT
#

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

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

boreal umbra
rose schooner
#

and the applying function's StopIteration would be turned into a RuntimeError

feral island
grave jolt
#

you mean, documenting it? or changing the behaviour?

#

because maybe that's intended

#

(and there's probably someone depending on this)

feral island
#

I can see how it happens but it's not really great behavior

#

yeah BC probably means we can't change it

#

we did change it for generators but that went through a __future__

feral island
grave jolt
#

If we step back, I think the underlying problem is that StopIteration is used by the __next__ method to signal exhaustion, and in next to signal the the thing you're nexting is exhausted.
We could have StopIteration be used as part of __next__'s interface, and have next raise its own IterationStopped. Kinda like __eq__ can return NotImplemented, but a == b provides a more sensible interface. That would eliminate all the footguns where you accidentally signal that your iteration is over when you didn't mean to

#

(of course, that is just hypothetical thinking, there's no way that's changing, that's a huge break)

grave jolt
# feral island that seems potentially worth fixing

Btw, here's another consequence of this behaviour ```py
In [2]: def f(x):
...: if x == 3: raise StopIteration
...: return x + 10
...:

In [3]: m = map(f, [1, 2, 3, 4, 5])

In [4]: list(m)
Out[4]: [11, 12]

In [5]: next(m)
Out[5]: 14

> Once an iterator’s `__next__()` method raises `StopIteration`, it must continue to do so on subsequent calls. Implementations that do not obey this property **are deemed broken**.

Though... the file iterator is also broken in this way. You can exhaust the file iterator, then call `seek(0)` and now it's not exhausted anymore. So not sure if this property is really _required_ required
feral island
fallen slateBOT
#

Python/bltinmodule.c line 1487

result = _PyObject_VectorcallTstate(tstate, lz->func, stack, nargs, NULL);```
grave jolt
#

yep

feral island
#

Though I guess f() is not an iterator.

grave jolt
#

Yeah, the object map(f, [1, 2, 3, 4, 5]) is a BrokenIterator, which doesn't necessarily mean that the map class has an implementation bug. Maybe it's just a documentation bug (i.e.: f not raising StopIteration is a precondition of map?)

feral island
#

This is also how I learned about map(strict=True). New in 3.14.

feral island
# grave jolt Yeah, the object `map(f, [1, 2, 3, 4, 5])` is a BrokenIterator, which doesn't ne...

Yes, possibly a documentation bug. Currently map's documentation is very concise though (https://docs.python.org/3.14/library/functions.html#map); mentioning this arcane issue would probably feel disproportionate

#

And confuse more people than it helps

grave jolt
#

I wonder if there's any way to grep for open-source code that relies on this behaviour

#

realistically the only place StopIteration would come up is calling next and doing raise StopIteration (outside of a __next__), maybe I could look into that

feral island
#

Yeah I guess you'd want to look for map/filter calls where the function calls next(). Though of course it could be multiple levels down the callstack

#

Wonder if this works with listcomps

grave jolt
#

a genexpr should perform the StopIteration->RuntimeError conversion

#

!e

def nasty(x):
    if x == 3: raise StopIteration

list(nasty(y) for y in [2, 3, 4, 5])
fallen slateBOT
# grave jolt !e ```py def nasty(x): if x == 3: raise StopIteration list(nasty(y) for y i...

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

001 | Traceback (most recent call last):
002 |   File "/home/main.py", line 4, in <genexpr>
003 |     list(nasty(y) for y in [2, 3, 4, 5])
004 |          ^^^^^^^^
005 |   File "/home/main.py", line 2, in nasty
006 |     if x == 3: raise StopIteration
007 |                ^^^^^^^^^^^^^^^^^^^
008 | StopIteration
009 | 
010 | The above exception was the direct cause of the following exception:
... (truncated - too many lines)

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

grave jolt
#

yep

rose schooner
grave jolt
spark verge
merry venture
fallen slateBOT
#

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

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

rose schooner
#

is there an easier way to generate cleanup code for going from one point to another in the bytecode in codegen.c

#

for example ```py
for x in A:
for y in B:
from here

go here
``` when going from line 3 to line 5, it exits 2 loops which needs 2 sets of END_FOR and POP_ITER

proud tusk
#

yo

#

i need help

spark magnet
proud tusk
#

alr

spark magnet
#

I guess I should ask here: anyone got any tricky ideas how to determine if an AST expression node will compile to a compile-time constant?

feral island
spark magnet
feral island
#

I think Irit has been working on exposing the AST optimizer, so maybe it's now possible to do it directly

#

I think otherwise you have to exactly replicate the logic of the AST optimizer

spark magnet
feral island
#

Mostly binary operations with constants operands are folded, but not always

spark magnet
feral island
#

I think if it throws an error, or results in an overly big constant

#
  1           0 LOAD_CONST               0 (4)
              2 RETURN_VALUE
>>> dis.dis("20 ** 20")
  1           0 LOAD_CONST               0 (104857600000000000000000000)
              2 RETURN_VALUE
>>> dis.dis("200 ** 200")
  1           0 LOAD_CONST               0 (200)
              2 LOAD_CONST               0 (200)
              4 BINARY_POWER
              6 RETURN_VALUE
#

(on 3.9)

#

Also if it throws an error

spark magnet
#

right.

#
>>> @dis.dis
... def f():
...   if 9**9**2: print(1)
...
  1           0 RESUME                   0

  3           2 LOAD_CONST               1 (9)
              4 LOAD_CONST               2 (81)
              6 BINARY_OP                8 (**)
             10 POP_JUMP_IF_FALSE       12 (to 36)
             12 LOAD_GLOBAL              1 (NULL + print)
             22 LOAD_CONST               3 (1)
             24 CALL                     1
             32 POP_TOP
             34 RETURN_CONST             0 (None)
feral island
#
  1           0 LOAD_CONST               0 (0.0)
              2 RETURN_VALUE
>>> dis.dis("1/0")
  1           0 LOAD_CONST               0 (1)
              2 LOAD_CONST               1 (0)
              4 BINARY_TRUE_DIVIDE
              6 RETURN_VALUE
#

Tuples are also folded if they contain only constants, not sure if there's more complex conditions there too

#
  1           0 LOAD_CONST               0 ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
              2 RETURN_VALUE
>>> dis.dis("(1,) * 1000")
  1           0 LOAD_CONST               0 ((1,))
              2 LOAD_CONST               1 (1000)
              4 BINARY_MULTIPLY
              6 RETURN_VALUE
spark magnet
#

@feral island I'm trying to predict when branches will be optimized away, because sys.monitoring won't tell me about them if they are gone. sys.settrace will.

feral island
#

Unfortunately that reduces to the same problem. >>> dis.dis("if (1,) * 100: print('hi')\nelse: print('bye')") optimizes away the else. If you change it to *1000 it doesn't.

spark magnet
#

right

fallen slateBOT
#

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

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

fallen slateBOT
#

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

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

zinc rain
#

;

#

pyautogui

#

Who know use it ?

#

I dont know

#

And

#

I need help

#

Too

#

Big python project

grave jolt
#

!tvmute @zinc rain 7d You were told pretty clearly not to spam to meet the voice gate

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied voice mute to @zinc rain until <t:1739824714:f> (7 days).

zinc rain
#

bruh, u are following me

#

?

#

Why

#

I am mute ?

#

So, i am creating a big casino project

winged sphinx
#

Respect the channel topics. This channel has a specific purposes

zinc rain
#

With friends , and its really importante

#

Yes

#

Ik

winged sphinx
zinc rain
#

I need not help

#

But guy that want, create a empire

merry venture
brisk drift
#

Hi

teal sonnet
winged sphinx
spark verge
#

This is off topic for this channel

lapis timber
spark verge
#

It's not acceptable to spam the same video in multiple channels, this is also an advanced python channel, not about learning python. Also your first 3 messages were the same spam in 3 channels, don't do that

spark verge
fiery axle
#

Hello

boreal umbra
#

We were previously talking about this.

spark magnet
boreal umbra
#

Yes

#

I'm trying to draw attention to the most recent on-topic discussion

spark magnet
#

i see

feral island
spark magnet
feral island
spark magnet
shut pewter
#

romania ?

boreal umbra
merry venture
fallen slateBOT
#

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

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

crisp locust
#

The Python app is more busy on this channel than anything else

jovial flame
raven ridge
jovial flame
winged sphinx
upper compass
#

hi

#

guys

#

i m new

acoustic dragon
thorny lava
#

I just ran into an interesting test case issue that looks like it should have been resolved, but probably hasn't been. In one of my tests there is mock_queue.assert_called_with(None, fw.process, valid_file), but it leads to the error:

E           AssertionError: Expected 'mock' to be called once. Called 2 times.
E           Calls: [call(None, <function process at 0x7685d67e3b00>, PosixPath('/tmp/pytest-of-skeledrew/pytest-9/test_watch_cdr_dir0/active.wav')),
E            call(None, <function process at 0x7685d67e3b00>, PosixPath('/tmp/pytest-of-skeledrew/pytest-9/test_watch_cdr_dir0/valid.wav'))].

Eventually discovered (through looking at mock.py) that it's due to an ambiguity, which is addressed in a GH issue (https://github.com/python/cpython/issues/73097) as well as in the docs. Reason why I find this interesting though is because I generated this and a few other test cases with AI, and the "error" above is expected behavior. So I'm thinking:

  • There is a substantial enough number of projects out there using that method with that particular expectation that it's significantly represented in training sets, leading to actual generation.
  • Without checking the code and docs, it's likely that many users won't understand why their test is failing (especially if it was generated).

Maybe there could be some kind of warning in the implementation itself to alert users?

GitHub

BPO 28911 Nosy @vstinner, @voidspace, @berkerpeksag, @lisroach PRs #251#252#254 Files assert_once_with_doc.patch Note: these values reflect the state of the issue at the time it was migrated and mi...

maiden dune
#

what's the situation with frame.f_locals these days? is it a reliable way to change locals from the outside? iirc there were some changes made regarding this in some version right?

quick snow
#

Yeah, depends on the version. In 3.13+ you can write to it, before you need to call some internal function (PyFrame_LocalsToFast) to make your changes take effect.

#

!pep 667

fallen slateBOT
quick snow
#

Using del, or the pop() method, to remove keys that correspond to local variables on the underlying frame is NOT supported, and attempting to do so will raise ValueError.

This is a bit weird, I think. You can del local variables in functions.

maiden dune
#

i see, thanks

winged sphinx
winged sphinx
feral island
#

Here you can see that the first print(x) uses LOAD_FAST and the second uses LOAD_FAST_CHECK: ```>>> dis.dis("""
... def f1():
... x = 1
... print(x)
... def f2():
... x = 1
... if something: del x
... print(x)
... """)
0 RESUME 0

2 LOAD_CONST 0 (<code object f1 at 0x1051bfb40, file "<dis>", line 2>)
MAKE_FUNCTION
STORE_NAME 0 (f1)

5 LOAD_CONST 1 (<code object f2 at 0x105212230, file "<dis>", line 5>)
MAKE_FUNCTION
STORE_NAME 1 (f2)
RETURN_CONST 2 (None)

Disassembly of <code object f1 at 0x1051bfb40, file "<dis>", line 2>:
2 RESUME 0

3 LOAD_CONST 1 (1)
STORE_FAST 0 (x)

4 LOAD_GLOBAL 1 (print + NULL)
LOAD_FAST 0 (x)
CALL 1
POP_TOP
RETURN_CONST 0 (None)

Disassembly of <code object f2 at 0x105212230, file "<dis>", line 5>:
5 RESUME 0

6 LOAD_CONST 1 (1)
STORE_FAST 0 (x)

7 LOAD_GLOBAL 0 (something)
TO_BOOL
POP_JUMP_IF_FALSE 1 (to L1)
DELETE_FAST 0 (x)

8 L1: LOAD_GLOBAL 3 (print + NULL)
LOAD_FAST_CHECK 0 (x)
CALL 1
POP_TOP
RETURN_CONST 0 (None)

quick snow
spark verge
fallen slateBOT
#

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

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

fallen slateBOT
#

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

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

spark magnet
#

Can anyone explain ExceptionTable in code objects? How to interpret it?

maiden dune
uneven raptor
#

are there any weird issues that could arise from having a non-string key in f_locals
definitely. i'm surprised it even works.
im aware that pep 667 guarantees consistency between locals() and f_locals, but is f_locals always consistent with itself?
it should be, but be aware that PEP 667 is only 3.13+. this won't work for 3.12 and lower, if you're worried about portability.

mortal delta
#

i have a meme!

#

if javascript and python had a child:

willow pewter
fallen slateBOT
mortal delta
fallen slateBOT
#

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

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

maiden dune
uneven raptor
#

crashes, probably. i don’t think it’s something that’s tested for.

#

why do you want a non-string key anyway?

maiden dune
#

using an non-string as the key was intended to pretty much eliminate the possibility of whatever was added to conflict with something already in f_locals or be removed. could just use a random string of course.

raven ridge
naive cairn
#

I'm not sure I understand the purpose of this channel. What is it about? 😅

rose schooner