#internals-and-peps

1 messages ยท Page 131 of 1

nova iris
#

oh wait sorry, 100 ms faster at 100000 runs

#

i forgot about that lmao

#

pretty much

#

unless i'm using some frickin' large hadron collider crap 1 microsec is good

main lynx
#

1 microsecond per decorated function at import time, would need to be importing a lot of code to be sweating it

nova iris
#

besides, partial has way more readability

nova iris
peak spoke
#

how would the implementation without partial even look without copying the function?

nova iris
#

triple def

peak spoke
#

update_wrapper is its own public function, you would need that under your def if you wanted to get rid of partial or similar functionality

main lynx
#

if you really want it to be fast just paste the decorator code inline in every function, ez

nova iris
#

ah, so this is why functools opted for partial
you were right, @peak spoke, they need it to also be a standalone function (for decorator classes)

#

and readability is the cherry on top of the cake

#

thanks y'all for figuring this out with me!

surreal plume
#

Hi Guys

#

I want to do something like that

#

using django rest framwork

#

anyone can help me?

#

I tried this

nova iris
surreal plume
#
class ServiceImageSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = ServiceImage
        fields = ['photo']


class ServiceSerializer(serializers.ModelSerializer):
    images = ServiceImageSerializer(many=True)

    class Meta:
        model = Service
        fields = ('id', 'title', 'description', 'features', 'images')```
nova iris
#

this is #internals-and-peps, we discuss python's advanced features, implementation details, use cases, and its future

paper echo
#

Eating your own dog food or โ€œdogfoodingโ€ is the practice of using one's own products or services. This can be a way for an organization to test its products in real-world usage using product management techniques. Hence dogfooding can act as quality control, and eventually a kind of testimonial advertising. Once in the market, dogfooding can dem...

nova iris
#

functools using functools :D

paper echo
#

the following are all more or less equivalent:

  1. creating a closure that passes some arguments into another function (the "double-nested" decorator technique)
  2. creating a callable class
  3. partial function application
#

in fact i think partial is implemented using the 2nd one? but maybe in C and not in pure python

#

or maybe it's pure python which is why it has extra overhead

tiny whale
#

my guess is no, but is there anyway to start off with a TypedDict like this:

#
class ABC(TypedDict):
    a: int
    b: str
#

and then feed a set[Literal["a", "b"]] to then get another TypedDict permitting only the keys within that set?

#

my use case for this is SQL queries. I have a function that returns a TypedDict after executing a "select *". But this returns a lot of unnecessary data which I have profiled to be a performance problem, so I want to only grab the relevant columns. But I want to statically type this. So idea is that this method takes a set[Literal["the", "relevant", "keys"]] and returns a TypedDict only allowing those keys. There is another TypedDict that serves as the source of truth for every column's type (I automatically generate this from my SQL DDL), so I'd want to generate the query-specific TypedDict from that base TypedDict

elder blade
#

Have you looked into PyDantic?

#

This sounds somewhat similar to part of what it does

tiny whale
#

we use pydantic, but for runtime parsing of values. when you say it sounds similar, do you think the above functionality would be present in the mypy plugin from them as well? if so, i'll check it out, since I'm trying to do this at type-hint time

main lynx
#

then you can have a helper to make the dataclass type from a set

#

curious if mypy can validate this..

tiny whale
#

this gets close (assuming mypy can validate it), only thing that could be better is not having to specify types again. So keeping a single source of truth for the types (a dataclass containing all the fields), and using that source of truth + key names to create the new dataclass instead of having to specify each type again in the tuples. But sadly that's not possible

main lynx
#

looks like make_dataclass accepts annotations, which you can pull from the single source of truth

#

tbh i would probably make all the query types explicit TypedDict or what have you with some automated test to validate the fields and their annotations against the canonical master list

#

have a common base class then you can iterate over __subclasses__ for validation

#

this 100% satisfies mypy and you can probably do it with pydantic too

#

and you probably get better hints in your IDE etc. etc.

tiny whale
#

yup, best option would have been to autogenerate. but second best option is to duplicate types but then validate that they are in sync. Instead of iterating over __subclasses__, I'll just check that the type-hinted return type of each method is actually accurate at runtime during the integration tests when talking to the database

#

thanks a lot for the help

paper echo
#

I think this is a great idea though

#

It's like the clojure spec "select" proposal

#

This is one of many reasons why I am starting to seriously look into Hy as a serious tool

#

Because you don't have to write type checker plug-ins and implement your own primitives, you just write macros that expand to annotations that already are supported

#

That said I really should learn how to write a mypy plugin

tiny whale
paper echo
#

I have a lot of ideas for things like this I am really just need to make a PoC

#

Yep

#

Beware it's changing a lot during the alpha

#

I wouldn't rely on it until 1.0 comes out stable

#

I also need to contribute some optimizations to the code generator, specifically removing dead code that gets generated in if/elif and function definitions

tiny whale
#

maybe one day typing itself will evolve to support the functionality, but I do like the direction it is going down so far. ParamSpec / Concatenate are already something I have a lot of uses for (mainly authentication decorators)

paper echo
#

The one thing we don't yet have is the ability to operate on concrete types that have already been defined

#

ParamSpec works for parameterized/generic types

#

But there's no ability to "clone" the type of an existing binding

#

You just have to copy and paste it

#

I've previously proposed ParamSpecFrom and ProtocolFrom but I think those aren't general enough. I'll have to ponder it more before I make a serious proposal to typing-sig

#

The former would be extremely useful for subclassing, the latter for making protocols out of existing concrete types.

#

So in your case you should imo be able to do something like create a protocol from existing type, and then slice a subset of attributes off of it

#

No reason such a thing shouldn't work with typeddict

#

And if there isn't a known annotation for the thing, then it uses the same logic as for other untyped bindings

#

i.e. Any or object, depending on your mypy config

#

I don't think this is possible in traditional statically typed languages without dependent types, but I don't see a reason it shouldn't work

#

Maybe somebody with more formal CS/PL theory training can set me straight

chrome sluice
#

erf, why is ```
randomPoint = random.randrange(newStartPoint, newEndPoint)

giving me a number outside the range ?
spark magnet
chrome sluice
#
newStartPoint: 56524
newStartPoint: 57944
randomPoint  109305

that is console log. This is within a program that has Py support. Davinci Resolve, thinking its that, cant get it to happen in py console

spark magnet
#

hmm, the label should say newEndPoint, but can we see the actual code also?

chrome sluice
#

ya soz about that

#

checking to make sure

paper echo
#

it also helps if you use a random.Random() instance with a fixed seed for generating random numbers. in general it helps make your results reproducible, which is good for testing and debugging

#

(it's mostly used by scientists for making sure their research is reproducible, but it has benefits for other users)

chrome sluice
#

ahh endpoint seems to be off

#

some reason ia ssumed the second newstartpoint was my endpoint just using the wrong label

nova iris
#
>>> a = [0, 1, 2, 3]
>>> *a[1], b = a
>>> a
[0, [0, 1, 2], 2, 3]
>>> b
3
>>> *a[1:3], b = a
>>> a
[0, 0, [0, 1, 2], 2, 3]
>>> b
3
```lol, python's `*` syntax on assignments work on subscriptions, slicings, attribute references, and nothing... literally:```py
>>> *[], [] = [[]]
>>> 
fierce geode
#

@merry oyster

#

any chance u know how to push these?

merry oyster
#

There's the checkmark at the top. This isn't really on-topic for this channel, though.

unkempt rock
naive saddle
#

!e *[], [] = [[]]

fallen slateBOT
#

@naive saddle :warning: Your eval job has completed with return code 0.

[No output]
sharp fog
#
class SyntaxError(Exception):
    """Base class for exceptions raised by the parser."""

    def __init__(self, msg, lineno=0, offset=0, text=None, filename=None,
                 lastlineno=0):
        self.msg = msg
        self.lineno = lineno
        # NB: offset is a 1-based index!
        self.offset = offset
        self.text = text
        self.filename = filename
        self.lastlineno = lastlineno

    def find_sourceline_and_wrap_info(self, space, source=None):
        """ search for the line of input that caused the error and then return
        a wrapped tuple that can be used to construct a wrapped SyntaxError.
        Optionally pass source, to get better error messages for the case where
        this instance was constructed without a source line (.text
        attribute)"""
        text = self.text
        if text is None and source is not None and self.lineno:
            lines = source.splitlines(True)
            text = lines[self.lineno - 1]
        w_filename = space.newtext_or_none(self.filename)
        w_text = space.newtext_or_none(text)
        return space.newtuple([space.newtext(self.msg),
                               space.newtuple([w_filename,
                                               space.newint(self.lineno),
                                               space.newint(self.offset),
                                               w_text,
                                               space.newint(self.lastlineno)])])

Interesting ๐Ÿ‘€

analog dagger
#

anyone here can help me with coding problems tomorrow 8-10 am??
[9:29 AM]
coding questions like dynamic programming ,graph and trees

sharp fog
#

Im unable to find how CPython handles its Syntax Errors

#

i would like to compare both

grave jolt
#

!rule 8

fallen slateBOT
#

8. Do not help with ongoing exams. When helping with homework, help people learn how to do the assignment without doing it for them.

pliant hemlock
#

Hello, is there a way to perform sanity checks before pytest goes about traversing through file directory to find test files? In other words, is there a "setup" file that pytest reads and runs before starting to look for test files?

fleet ice
#

Why do we have mutability? Can't we just treat stuff like lists
Also how does py know that the obj is mutable

stray steeple
#

Is there a way to call the value of a variable instead of the variable?

#

kinda in C when you set it equal to the mem address at that time, instead of the variable pointing to that address

fleet ice
#

I know that much but y tho

stray steeple
#

basicaly it takes that value at the mem address, copies it, then sets a new pointer to it

flat gazelle
#

no, that is impossible

#

it is an invalid operation on a lot of objects

#

or well, just about all objects

#

except maybe a string

stray steeple
#

a string you say? maybe I can do some type conversions

flat gazelle
#

you still can't do it

#

it would be skipping calling the object creation protocol, which would break a lot of things

#

as well as forcing the objects to share various metadata which is mutable

stray steeple
#

I see, I appreciate the information. Always happy to learn.

fleet ice
#

Why do we have mutability? Can't we just treat stuff like lists
Also how does py know that the obj is mutable

stray steeple
# fleet ice I know that much but y tho

def solver():
for y in range(9):
for x in range(9):
if grid[y][x] == 0:
for n in range(1, 10):
if possible(y, x, n):
grid[y][x] = n
solver()
grid[y][x] = 0
return
global griddy
print(grid[0]) # stupid ass python .. it works here.
griddy = grid[0]
return

solver()
print(griddy) #

#

the value printed the 2nd time doesn't match the 1st time.

deft pagoda
stray steeple
#

I rewrote it already, I was just wondering if python had a different way for the future.

#

I moved my other functions inside. Not what I wanted to do, but its working, meh.

deft pagoda
#

i pinged you in the correct channel, this is not the correct channel

verbal escarp
#

#2 python version for botocore is 2.7 sigh

#

and 3.7 apparently is the most popular one for 3

fleet ice
#

Is the precedence of operations in python same as math's

paper echo
paper echo
#

!e ```python
print(62 + 22)

fallen slateBOT
#

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

16
peak spoke
#

yeah I think most of the stats like package downloads don't realistically reflect the general usage of the language because automated tools will pull them at a rate orders of magnitude larger than normal users

paper echo
#

all the other ones make sense, e.g. colorama i think is a dependency of ipython

#

maybe botocore reflects usage of the aws cli

verbal escarp
paper echo
#

im surprised that its so apparently dominated by a single tool

verbal escarp
#

i'm just as surprised

paper echo
#

botocore, urllib3, s3transfer, idna, colorama, boto3, click

verbal escarp
#

also, why 2.7?

paper echo
#

maybe there are huge deployments on old red hat systems that have 2.7 with backported security patches or something like that

verbal escarp
#

ah.. that would make sense

paper echo
#

does s3 itself still ship with 2.7?

#

maybe s3 images come with the aws cli pre-installed running on 2.7

verbal escarp
#

it says 2.7 and 3.4

#

combined with automated tools that would explain things

#

could it be that tools like that are used on alexa devices?

#

first signs that IoT finally is taking off?

#

automated tools finally dominating man-made platforms ^^

elder blade
#

How come I've never known about botocore?

#

What's it for?

#

Oh I see now, that's interesting

paper echo
#

there must be a truly astronomical number of clients using the aws sdk

verbal escarp
paper echo
#

because it's an "internal" support library that you don't need to interact with..

verbal escarp
#

it sounds like a niche, but the numbers are staggering

paper echo
#

i only know about it from reading the boto3 docs

#

nobody uses it directly, it's a dep of boto3

verbal escarp
#

yeah

paper echo
#

like urllib3, it's not weird if you've never "heard of" urllib3

verbal escarp
#

i actually expected numpy on top

#

but it's only #20

paper echo
#

20 is surprisingly high if anything

#

i expected this to be dominated entirely by "ops" libraries

verbal escarp
#

that's another way to see it

#

ops libraries like pip?

elder blade
#

Yeah, or like Certifi, Colorama which are big too

#

It seems like pretty much all libraries require those haha

verbal escarp
#

well, colorama is right there on top

#

typing-extensions is weird

#

maybe we can infer what kind of clients are using those libs by looking at the daily downloads

#

hm.. not really any significant difference apparent for me

paper echo
#

i assume that's the aws sdk using type annotations on 3.6/3.7

#

there are some things worth backporting on 3.8 now too

#

even 3.9

verbal escarp
#

i was looking for those stats to determine which python versions are worth supporting.. turns out 3.9 isn't even on the horizon for most :p

#

3.7 would be the one that has the most impact these days, i guess

peak spoke
#

the yearly survey should be more indicative of that

#

although I guess that would be skewed more to the higher versions as I think people who regularly update and watch the development more closely are also more likely to know about the survey

grave jolt
#

!e
Why do dataclasses allow overriding attributes like this?

from dataclasses import dataclass

@dataclass
class Foo:
    x: int
    y: str

@dataclass
class Bar(Foo):
    x: list

print(Bar(1, "aaa"))
print(Bar.__dataclass_fields__)
fallen slateBOT
#

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

001 | Bar(x=1, y='aaa')
002 | {'x': Field(name='x',type=<class 'list'>,default=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,default_factory=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD), 'y': Field(name='y',type=<class 'str'>,default=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,default_factory=<dataclasses._MISSING_TYPE object at 0x7fcf027af070>,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),_field_type=_FIELD)}
grave jolt
# elder blade Why not?

that breaks subtyping somewhat, no?

def function(foo: Foo) -> int:
    return foo.x + 42

bar: Bar = ...
print(function(bar))
#

I mean, from a typehint perspective, not the runtime

elder blade
#

So now they're invariant?

grave jolt
#

hm??

elder blade
#

Foo and Bar

grave jolt
#

wdym by 'invariant'?

trail elk
#

hello can someone help with something?

verbal escarp
trail elk
#

i think its imple

#

whenever i open chrome it just says come

grave jolt
#

@trail elk
This channel is for meta-discussions about Python. If you have need help with something specific, you should see #โ“๏ฝœhow-to-get-help and claim a help channel

verbal escarp
#

not really meta

visual shadow
#

well it's supposed to be i guess, when we're not talking type hints ๐Ÿ˜›

verbal escarp
#

well, this is a meta-discussion about python ๐Ÿ˜‰

#

but a discussion about python isn't meta :p

grave jolt
#

but yeah, I might have used the term incorrectly

#

I hope the meaning was clear though

grave jolt
unkempt rock
elder blade
#

!e Please someone send me God ```py
import inspect
from typing import Optional, get_args

def test(
val: Optional[int]
) -> None:
pass

for name, value in inspect.signature(test).parameters.items():
print(name, get_args(value.annotation)[-1] is None)

fallen slateBOT
#

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

val False
elder blade
#

It's False

#

!e Please someone send me God ```py
import inspect
from typing import Optional, get_args

def test(
val: Optional[int]
) -> None:
pass

for name, value in inspect.signature(test).parameters.items():
print(name, get_args(value.annotation)[-1] is type(None))

fallen slateBOT
#

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

val True
grave jolt
#

oh

#

interesting

nova iris
#

@paper echo thanks for telling me about all that unicode normalization stuff and giving me the resources last time :D i finally understood NFC/D/KC/KD (although the compatibility is still a bit confusing lol)
today i broke a quiz app because i used a base char + combining char instead of a precomposed char on an answer lol... someone isn't normalizing their unicode inputs ;)

paper echo
#

being a unicode wizard is a good skill

#

it's very important for data-unfucking

nova iris
paper echo
#

you just have to know the core concepts

#

also understanding what utf-8 is and how it is/isn't related to unicode, if you don't already

#

and knowing about unicode character classes can be helpful too, the 3rd-party regex library supports them

#

!pypi regex

fallen slateBOT
nova iris
#

regex vs re...

#

hm

paper echo
#

re is stdlib and faster, regex is 3rd party and slower but has more features

grave jolt
#

regex isn't always slower, for example it prevents catastrophic backtracking (most of the times)

nova iris
#

yeah, i still got tons of stuff to work through, i'm only scratching the surface... but i know about basic normalization now, so that's great

#

also, someone's message just got nuked (by pgp?)

paper echo
grave jolt
#

it also supports a timeout

paper echo
#

i think google's re2 is specifically designed to be safe against "regex attacks"

#

but i can't get it to build on macos ๐Ÿคทโ€โ™‚๏ธ

undone hare
#

I know the discussion is 2h old, but what the heck. Regular regex engines uses a DSF pattern, making them subject to catastrophic backtracking (O(n^2) runtime, for example with .*.*). RE2 on the other end will explore every possibility at the same time, making the execution time pretty much consistent. It does mean it is slower for well designed regexes, but it also means it can accept arbitrary regexes and run them without problems without turning into another https://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016

white nexus
#

What's the correct* way to type annotate __init__ methods?

#

As somehow even without a return, calling them returns an instance of the class

grave jolt
#

@white nexus No, calling __init__ doesn't return an instance of the class.

#

Callind __new__ does.

#

I think mypy and pyright accept not annotating the return type of __init__ at all

white nexus
#

then what is __new__?

#

how are they different

#

because uh, my inits are currently annotated with the class ๐Ÿ˜“

naive saddle
#

!eval

class Logging:
    def __init__(self) -> None:
        print("the instance has already been created and now I need to 'initialize' it")

    def __new__(cls) -> "Logging":
        print(f"i'm about to create an instance using the class {cls}")
        return super().__new__(cls)

l = Logging()
fallen slateBOT
#

@naive saddle :white_check_mark: Your eval job has completed with return code 0.

001 | i'm about to create an instance using the class <class '__main__.Logging'>
002 | the instance has already been created and now I need to 'initialize it'
grave jolt
#

there isn't really any magic in __init__, it really doesn't return anything

#

it already gets an object that calling the class would return in its self argument

verbal escarp
#

__new__ on the other hand is quite magic and easy to mess up ๐Ÿ˜

white nexus
#

...why do I have a ghost mention now

plucky basalt
#

sorry didn't notice it had been answered

elder blade
#

You can edit your message with ~~ on both sides to make it strike-through

#

That's what I usually do as to not cause ghost pings haha

stuck valley
#

What's the dunder called during slicing?

peak spoke
#

it passes a slice to getitem

#

Or a tuple I suppose, not sure how exactly the slice is passed when it's sliced with tuples

#

ah it doesn't create a tuple with 1,:, but getitem receives (1, slice(None, None, None))

stuck valley
#

Ah, thanks!

surreal sun
#

What do you all think would be some "advanced" projects

#

I'm trying to generate a list of beginner, intermediate, and advanced projects

#

for a possible command for sir lancebot

#

but I've never really ventured into that territory so i wouldn't know

charred pilot
#

i don't think such a command would be very helpful. it'd just spawn questions like "how do i know i'm advanced" and the likes. plus, we already have !projects. also, #community-meta ?

languid yoke
#

If it sent one of each idea, then you could look at the ideas to see which you think you could achieve.

surreal sun
#

And yeah I'll head over to community meta

paper echo
# white nexus What's the correct\* way to type annotate `__init__` methods?

mypy supports omitting the annotation on self in methods, but if you really want to do it right, you'd do this:

from typing import TypeVar

ThingT = TypeVar('ThingT', bound='Thing')

class Thing:
    def __init__(self: ThingT, x: int, y: str) -> None:
        self.x = x
        self.y = y

this way subclasses can all use the same ThingT annotation and it will all get inferred correctly

#

this is important for e.g. class methods

#
from typing import Type, TypeVar

ThingT = TypeVar('ThingT', bound='Thing')

class Thing:
    def __init__(self: ThingT, x: int, y: str) -> None:
        self.x = x
        self.y = y

    @classmethod
    def from_tuple(cls: Type[ThingT], tup: tuple[int, str]) -> ThingT:
        return cls(*tup)
white nexus
#

why that rather than string annotations?

paper echo
#

you need the typevar to support subclassing correctly

white nexus
#

eg```py
class Thing:
def init(self: "Thing", x: int, y: str) -> None:
self.x = x
self.y = y

@classmethod
def from_tuple(cls: "Thing", tup: tuple[int, str]) -> "Thing":
    return cls(*tup)
paper echo
#

well ThingT doesn't exist otherwise

#

or does mypy create implicit typevars for you?

white nexus
#

fixed2*

paper echo
#

oh

#

if you have a subclass of Thing, then that subclass from_tuple method will have the wrong annotation

#

e.g. if you have SpecialThing(Thing), SpecialThing.from_tuple will still be marked as returning Thing, not SpecialThing

#

that's not usually what you want

white nexus
#

ah

#

but its fine in cases where you aren't going to be subclassing a class?

peak spoke
#

Would the typevar properly handle subclasses?

paper echo
#

yeah, but most of the time i just omit annotation on self/cls anyway

#

with bound=, yes @peak spoke

torpid bridge
#

Self works, though, doesn't it?

paper echo
#

what's Self? i don't see it in typing

white nexus
torpid bridge
#

urgh

#

Maybe that's a rust thing

charred pilot
#

yeah, and a pretty useful thing too

white nexus
#

freaking automatic deleting command invokcations sorry

boreal umbra
#

Are these the same?

with open(...) as f:
    f.write('blah blah blah\n')
    print('blah blah blah', stream=f)
verbal escarp
#

i'd like to plot continuous wavelets (i'd use pyplot.matshow(coef, fignum=1, aspect="auto") in jupyter) but in pyqtgraph instead, anyone know how to do that?

verbal escarp
torpid bridge
boreal umbra
torpid bridge
#

...no. No I think they're the same

#

flush triggers a write

boreal umbra
#

so much for my toilet joke.

torpid bridge
#

TLDR python buffers output

charred pilot
#

it flushes the output when it finds a newline i think?

peak spoke
#

They should act the same

#

print will only flush when you pass in the kwarg, otherwise the buffering is left to the stream (stdout on newlines, files were whatever)

verbal escarp
#

The file argument must be an object with a write(string) method; if it is not present or None, sys.stdout will be used. Since printed arguments are converted to text strings, print() cannot be used with binary mode file objects. For these, use file.write(...) instead.

Whether output is buffered is usually determined by file, but if the flush keyword argument is true, the stream is forcibly flushed.

peak spoke
#

Well, print will do the newline in a separate write if the end kwarg is not removed

verbal escarp
#

there's the subtle difference - byte vs str

peak spoke
verbal escarp
#

is there a better channel to ask about plotting with pyqtgraph? ^^

charred pilot
peak spoke
verbal escarp
#

ty

verbal escarp
#

random thing that could be PEPed: there should be infinite ints in python

peak spoke
#

what would be the use case?

charred pilot
#

what can't you do with float("inf")?

verbal escarp
#

some APIs only accept ints, not float

charred pilot
#

how would they accept infinity then ๐Ÿค”

verbal escarp
#

int("inf")? ๐Ÿ˜„

#

no idea, but i stumbled over that problem a couple of times, passing in None doesn't work either because it doesn't compare

peak spoke
#

Is there a case where it has to be an int but infinity makes sense? For example if it only does comparisons the api should accept any (real) numeric type

verbal escarp
#

well, my latest encounter was with versions

#

testing against Version to be more concrete

#

Version only can deal with ints, but i don't want to test any actual int that users might choose, but it still needs to have valid comparisons

charred pilot
#

what's a Version?

verbal escarp
#

from packaging.version import Version

#

it might be feasible to do it as a sibling of math.inf

#

like math.int_inf

#

and int("inf") would return that singleton

#

just an idea

paper echo
#

That might be problematic at the C API level and in the C implementation

#

You would need a special pyobject that isn't an int and add a special case to every int operation

#

I agree it would be useful but I think it's probably considered not worth it since you can cast to float to compare with inf

elder blade
#

Is there even a standard for integers?

spice pecan
#

You don't have to cast to float at all actually

elder blade
#

I know there's a standard for floats which says there should be an infinite one

#

!e ```py
print(int(float('inf')))

fallen slateBOT
#

@elder blade :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 1, in <module>
003 | OverflowError: cannot convert float infinity to integer
spice pecan
#

!e ```py
print(21024 < float('inf'))
float(2
1024)

fallen slateBOT
#

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

001 | True
002 | Traceback (most recent call last):
003 |   File "<string>", line 2, in <module>
004 | OverflowError: int too large to convert to float
elder blade
#

Yeah that's what I thought

spice pecan
#

So there's no need for a special inf that is an int

#

You can just use the float one with ints that are outside of float range

deft pagoda
#

i mean, it's probably not that difficult to just subclass int and write your own inf

#
In [2]: class Inf(int):
   ...:     def __gt__(self, other):
   ...:         return other is not self
   ...: 
   ...:     def __add__(self, other):
   ...:         return self
   ...: 
   ...:     def __sub__(self, other):
   ...:         return NAN if other is self else self
   ...: 
   ...:     def __lt__(self, other):
   ...:         return False
   ...: 
   ...:     ...
   ...: 

In [3]: INF = Inf()

In [4]: INF < 3
Out[4]: False

In [5]: INF > 10
Out[5]: True

In [6]: INF > 11
Out[6]: True
paper echo
spice pecan
#

Oh, gotcha

#

Not without an implicit cast I believe

astral gazelle
#

If im initialising a whole bunch of instances of a class, but the class only has state, no functionality, do i use a dataclass or is it gonna kill performance

peak spoke
#

if the performance/footprint is a concern I'd use a named tuple

#

I think the fetching of attrs will be a bit slower because it has to go through the itemgetter, but instantiating is going to be faster and the instances themselves are going to be smaller

paper echo
#

you can also use attrs

wheat isle
#

is it possible to make a 3d scatter plot with pandas

crude owl
#

Does anyone know how to shuffle a list until a certain condition is met?

sand edge
#

Guys

#

I need help

crude owl
#

I went to a help channel, new to the Discord! Sorry guys

astral gazelle
#

More things about perf, do fstrings carry overhead, does it cost more to have a regular string be f string, ie

f"name"
# compared to
"name"
peak spoke
#

they'll both be saved as code constants

astral gazelle
#

Okies, time to bring some consistency to this code i guess

last tapir
#

Very odd ask: Does anyone know of a very small python module that has an entry point? I want to test that a particular machine can pip install something and execute it's entry point and I want that package to be as small as possible and platform agnostic. Anyone have any suggestions?

visual shadow
#

could always make one perhaps

last tapir
#

What are some small python packages that have entry points?

#

There doesn't seem to be a great way to search that in pypi

astral gazelle
#

Just make one yourself, all it needs is an init file and a main file afaik

main lynx
#

making your own requires publishing to pypi in this case

#

which is.. not the end of the world?

flat gazelle
#

if you just mean python -m package, all you need is a __main__.py file in the package and it will work

#

afaik it can even be a namespace package

main lynx
# last tapir Very odd ask: Does anyone know of a very small python module that has an entry p...
$ pip install certifi
Collecting certifi
  Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
     |โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ| 145 kB 4.5 MB/s 
Installing collected packages: certifi
Successfully installed certifi-2021.5.30
$ python -m certifi
.../site-packages/certifi/cacert.pem
nova iris
unkempt rock
#

yes

nova iris
last tapir
#

what is the difference between a wheel's console script and scripts found in .data/scripts/?

unkempt rock
#

Hello, I am using ctypes to call the windows api "bitblt" but I noticed it takes almost 10ms to respond

#

But in c++ its sub 1ms

#

What's going on here? I should be calling the samr APIs directlf

mint dock
#

I am trying to install a package from a private index (say package A) but have package A's dependencies be installed from pypi. I think there is some recent change in how pip handles this.

I previously had

pip install --index-url https://isprivate.com --extra-index-url=https://pypi.org/simple/ A

however that is installing package A from pypi, not the private repo :/

main lynx
#

i would think use a proxy to forward from the private index

nova iris
#

i can't believe i've never discovered this before

#

so apparently you can assign to slicings of lists (only with step value of 1, though)... i guess their __setitem__ allows it

#

which means...

#
>>> (a:=[])[:] = range(100)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, blah blah blah result truncated, 99]
```~~*who needs list comps*~~ ||\s||
grave jolt
deft pagoda
naive drum
#

Hi guys, does anyone happen to know of any code templates for onboarding patreon customers to a telegram channel and discord server? I'm not really sure where to start I'm too new to this.

paper echo
#

They aren't any standard part of the distribution package

#

Where do you even see ./data/scripts?

paper echo
mint dock
last tapir
nova iris
nova iris
fallen slateBOT
paper echo
mint dock
#

what if a different version of pkg-a is also on pypi?

paper echo
paper echo
#

good question

mint dock
#

i think that's how I originally set my config up...

last tapir
paper echo
# mint dock https://github.com/pypa/pip/issues/8606#issuecomment-665547688

@ivanst0 It doesn't. The indexes are treated equally.
https://github.com/pypa/pip/issues/8606#issuecomment-665554122
the order might be arbitrary even

GitHub

This is totally related to #5045, but I can not comment on it. For me this should be re-opened, because it's a security issue. I provide the package xxx to the private repository my-company...

#

and it seems like overall there isn't really any conclusion

mint dock
#

yeah, that's what I came up against... I figured out a decent workaround, the private package (pkg-a) only has one dependency, which I wanted to grab from pypi anyway, so I'm manually installing that dependency first...

paper echo
#

mirroring pypi with devpi might be the best long-term solution

mint dock
#

then when I install pkg-a, specifying the private repo, it sees the dependencies are there and it's fine...

paper echo
mint dock
#

yup, am reading that now ๐Ÿ˜„

paper echo
last tapir
paper echo
#

ah, that's a bummer

#

i wonder why, just lack of effort/interest?

#

related: i was talking to webknjaz on #pypa irc recently, they suggested treating the pip-compile output as a "constraints" file rather than a "requirements" file, so you'd do something like this:

pip-compile -o requirements.lock requirements.in
pip install -r requirements.in -c requirements.lock
#

i didn't even know pip constraints files were a thing

#

but there's also apparently a bug in pip where constraints files don't work right if they have hashes in them

#

so ๐Ÿคทโ€โ™‚๏ธ

sturdy willow
#

hello

#

what to do if I cannot write a project in Python, but I have been studying it for 8 months

verbal escarp
unkempt rock
#

Can anyone help me in this function

leaden igloo
leaden igloo
sturdy willow
#

ok

fleet ice
#

Why does strings have to be immutable?

grave jolt
# fleet ice Why does strings have to be immutable?

They generally don't. But it makes some things easier:

  • if strings were mutable, they couldn't be hashable, i.e. they couldn't be used as dictionary keys, which is, well, a big problem, since Python is built on top of dictionaries keyed by strings in many places
  • it allows for some optimizations (for example, if you return a constant string from a function, it doesn't have to be recreated every time you call the function)
  • programs with immutable values are generally easier to understand and write
fleet ice
grave jolt
fleet ice
grave jolt
#

and, well, some programs are easier to understand if you mutate stuff.

#

ultimately you can't avoid mutability, otherwise your program wouldn't literally do anything

fleet ice
#

Did the first ever comp language use mutability

#

Nvm

#

It isn't related now. thanks for info!

grave jolt
fleet ice
verbal escarp
charred pilot
#

you have to be mutating something, writing to stdout, writing to a db, etc

verbal escarp
#

that depends very much on the definition of "mutating"

#

if you write something for the first time on a tape, you mutate it once and never again

#

if that bit was set once before, it most definitely is mutated, with either definition

#

but i'm saying that setting a bit shouldn't count as "mutating", thus any write-once datastructure shouldn't count as mutable.. and you can do anything with a write-once datastructure, as long as you have enough space

peak spoke
#

Final applies to any name to indicate it shouldn't be reassigned, Literal is an annotation that only the passed literal values can be used

verbal escarp
#

write-once datastructures often are simpler to reason about, that's the main benefit

#

i'm saying "write-once" now in place of "mutable", for clarity

#

of course, such datastructures are extremely wasteful most often

#

it's possible to reduce waste by using diff-tricks and only care about the actual changes, but then it can become even more difficult to reason about than mutable datastructures

#

the direction would be towards document-databases etc

gleaming rover
#

for example...in languages like Python and Java, which are relatively big on mutation, there's a difference between value equality (==) and reference equality (is)

unkempt rock
#

i.e. i use one here

#

and it can build with pyinstaller. then upload the zips to my release page

#

that's just a test. but it can do all 3 environments. so having it do a pip freeze instead would be easy

paper echo
#

tfw unicode

# NOTE: Technically this doesn't cover everything. There's
# a hard-coded list of additional codepoints, and NFKC
# normalization is applied before matching. See:
#   https://docs.python.org/3/reference/lexical_analysis.html#identifiers
#   https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Character_Classes
py_identifier_pattern_start = r"[_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}]"
py_identifier_pattern_continue = r"[_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}]"
py_identifier_pattern = fr"{py_pattern_start}{py_pattern_continue}*"
py_module_pattern = fr"{py_identifier_pattern}(?:\.{py_identifier_pattern})*"
py_entrypoint_pattern = fr"{py_module_pattern}:{py_identifier_pattern}"
#

eaiser to read imo:

py_identifier_start_chars = [
    '_',
    '\p{Lu}',
    '\p{Ll}',
    '\p{Lt}',
    '\p{Lm}',
    '\p{Lo}',
    '\p{Nl}',
]
py_identifier_continue_chars = [
    *py_identifier_start_chars,
    '\p{Mn}',
    '\p{Mc}',
    '\p{Nd}',
    '\p{Pc}',
]
py_identifier_pattern_start = "[" + "".join(py_identifier_start_chars) + "]"
py_identifier_pattern_continue = "[" + "".join(py_identifier_continue_chars) + "]"
py_identifier_pattern = fr"{py_pattern_start}{py_pattern_continue}*"
py_module_pattern = fr"{py_identifier_pattern}(?:\.{py_identifier_pattern})*"
py_entrypoint_pattern = fr"{py_module_pattern}:{py_identifier_pattern}"
#

gah forgot r on all those strings

/'\\p/ s/'/r'/
deft pagoda
#

when you just get lazy and use lark

nova iris
paper echo
#

jsonschema either MUST's or SHOULD's that the regex is ecma

paper echo
nova iris
#

but the thing in the lexical definition wasn't that

#

all characters in id_start whose NFKC normalization is in "id_start xid_continue*"

paper echo
#

oh

#

hmmm

nova iris
#

how does a char's nfkc be in another pattern

#

it doesn't make sense

#

is that ebnf within ebnf...

paper echo
#

yes lol

#

i'm not sure how that works

nova iris
#

it's this crucial difference that separates id_start from xid_start (the latter is used in identifier's definition), but i can't understand it

paper echo
#

oh

#

hm

#

i think it's accounting for the possibility that the decomposed form could "spill over" into xid_contiue

#

i'm not sure if it's possible for that spillover to persist after re-composing

nova iris
paper echo
#

this is the kind of thing where i wish someone left a note as to why

nova iris
#

lol yeah same

#

if only i knew c, perhaps i can dig into the lexer code or whatever controls this

paper echo
#

nothing like hard-coding 300 lines of C in a triple quoted string

#

who knows

#

i'm 3 layers deep into yak shaving right now, i have to cut it off here

nova iris
#

lol

paper echo
#

making a jsonschema for pyproject.toml tool sections, so i can generate setup.cfg and tox.ini files from pyproject.toml

#

because there's no spec for either yet and i figured i can at least slap one on the internet somewhere and the devs of setuptools and tox can decide to use it or not

verbal escarp
#

@paper echo here is something for you ๐Ÿ™‚

#
>>> np = use("numpy", version="1.21.2", hashes={'b5e8590b9245803c849e09bae070a8e1ff444f45e3f0bed558dd722119eea724'}, modes=use.auto_install) 
Collecting numpy==1.21.2
  Using cached numpy-1.21.2-cp39-cp39-win_amd64.whl (14.0 MB)
Installing collected packages: numpy
  Attempting uninstall: numpy
    Found existing installation: numpy 1.21.2
      Successfully uninstalled numpy-1.21.2
ERROR: Could not install packages due to an OSError: [WinError 5] Zugriff verweigert: 'C:\\Users\\micro\\.justuse-python\\venv\\numpy\\1.21.2\\Lib\\site-packages\\~umpy\\.libs\\libopenblas.XWYDX2IKJW2NMTWSFYNGFUWKQU3LYTCZ.gfortran-win_amd64.dll'
Check the permissions.

<numpy>:112: UserWarning: The NumPy module was reloaded (imported a second time). This can in some cases result in small but subtle issues and is discouraged.
  exec(compile(code, f"<{name}>", "exec"), mod.__dict__)
>>> np.__version__
'1.21.2'
>>> exit()
PS F:\Dropbox (Privat)\code\justuse\src> python
Python 3.9.6 (tags/v3.9.6:db3ff76, Jun 28 2021, 15:26:21) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.__version__
'1.19.3'
#

not ideal yet ๐Ÿ™‚

#

but the pieces are starting to fall into place

#

two different numpy versions in the same environment, one public, one private

verbal escarp
#

not viable in the same process yet, though thanks to some weird caching on numpy's part

muted pewter
#

It's an advanced joke ๐Ÿ˜…

undone hare
#

Doesn't matter if it is about python or not, please don't post random memes here

muted pewter
#

ok sry

verbal escarp
#

๐Ÿ™‚

#

"only installing packages is missing, but we'll figure it out, shouldn't be too hard" - young, naive me, a few months ago

lusty scroll
#

I sort of recall there's some way to prevent pip from installing to a temp folder then copying to the final location

lusty scroll
sand goblet
#

!e ```py
import sys

d = {}

for n in range(10000):
d[n] = None

print(sys.getsizeof(d))

for n in range(10000):
del d[n]

print(sys.getsizeof(d))```

fallen slateBOT
#

@sand goblet :white_check_mark: Your eval job has completed with return code 0.

001 | 295000
002 | 295000
sand goblet
#

This suggests that dictionaries donโ€™t decrease in size. But:

#

!e ```py
import sys

d = {}

for n in range(10):
d[n] = None

print(sys.getsizeof(d))

for n in range(10000):
del d[0]
d[0] = None

print(sys.getsizeof(d))```

fallen slateBOT
#

@sand goblet :white_check_mark: Your eval job has completed with return code 0.

001 | 360
002 | 640
sand goblet
#

How does it not linearly increase in size here even though the consecutively filled array should be building up a bunch of empty space? If it never decreases in size.

#

Does it only account for the size of the hashed into array, not the consecutively filled array?

halcyon galleon
#

getsizeof only returns the size of the object, not the contents. To get the size of the dict as it grows/shrinks you'd need to collect the size of the objects within too

I wrote this to help track the size of payloads going out-bound in an api. Seems to work decently (it's missing a few bytes here and there I think)

def sizeof(obj: Union[Dict[str, Any], List[Any], Tuple[Any, ...]]) -> int:
    """Return total size in bytes of object (included nested)"""
    size_of = 0
    for val in obj.values() if isinstance(obj, dict) else obj:
        nested = isinstance(val, (dict, list, tuple))
        size_of += sizeof(val) if nested else sys.getsizeof(val)
    return size_of
#

I suppose if you really wanted to be simple (and the dict was serializable) you could just json.dumps it and get the char count of the string.

#

Things I only think of when talking about what I've thought of rooDerp

sand goblet
#

But it showed growth in the first example

#

I think that it shows how many bytes the underlying array is using

#

But yeah, in the second example, it doesnโ€™t increase in size beyond 640

#

Actually, I wonder why it doesnโ€™t stay at 360

#

Does it only decrease the size of the consecutively filled array, and it never decreases the size of the hashed into array?

raven ridge
#

Deleting an entry from a dict leaves a placeholder in its place. I think that's all you're observing there

sand goblet
#

And it only decreases the size of the consecutively filled array?

#

But not the other one?

#

Because it makes sense that the hashed into array wouldnโ€™t build up memory on the 2nd example since it keeps hashing to the same space

#

If thatโ€™s what you meant by placeholder

raven ridge
#

I mean that, after you do del d[0], the hash table bucket that previously stored the value now stores a placeholder that says "there used to be a value here but now there isn't".

sand goblet
#

Yeah

#

And then it gets put back in that same spot

#

But what about the other array? That one it just resizes to a smaller size when thereโ€™s too much empty space?

#

But the same thing isnโ€™t done with the hash table array?

raven ridge
#

The same thing is done with the hash table array, but deleted entries aren't empty space. They hold placeholders.

unkempt rock
raven ridge
raven ridge
unkempt rock
#

oh, neat

sand goblet
#

So it canโ€™t get rid of dummy slots for some reason?

#

I was imagining that it would just go through the whole table and rehash everything into a smaller one once there were too many

raven ridge
#

It could do that, but since rehashing every item is expensive and slow, it doesn't want to

sand goblet
#

As in it just never ever does it?

raven ridge
#

It does it when the table grows too large

#

The deleted entries take up space, so eventually if you keep adding then deleting then adding then deleting, it uses up enough space that it decides it must resize and rehash everything. At that point it might allocate a smaller array for the hash table than it started with, if most slots are filled with "deleted" placeholders.

sand goblet
#

But it didnโ€™t do it after 1 million things deleted

#

!e ```py
import sys

d = {}

for n in range(100000):
d[n] = None

print(sys.getsizeof(d))

for n in range(100000):
del d[n]

print(sys.getsizeof(d))```

fallen slateBOT
#

@sand goblet :white_check_mark: Your eval job has completed with return code 0.

001 | 5242968
002 | 5242968
sand goblet
#

It couldnโ€™t do 1 million here

#

Idk

raven ridge
#

Right, it would do it when it needs more space.

#

The shrinking would happen on the path for inserting an key into the hash table, not on the path for deleting a key from it.

sand goblet
#

Wouldnโ€™t it just use the dummy slots?

#

Or it doesnโ€™t work that way?

#

Wait

raven ridge
#

Give me a moment, I'll point you to the resize code...

sand goblet
#

Would that end up making it have problems finding things?

#

I think maybe thatโ€™s why it canโ€™t do that.
Nvm, it seems like it doesnโ€™t do that, the comment says dummy slots can be refilled.

raven ridge
fallen slateBOT
#

Objects/dictobject.c lines 1082 to 1093

/*
Restructure the table by allocating a new table and reinserting all
items again.  When entries have been deleted, the new table may
actually be smaller than the old one.
If a table is split (its keys and hashes are shared, its values are not),
then the values are temporarily copied into the table, it is resized as
a combined table, then the me_value slots in the old table are NULLed out.
After resizing a table is always combined,
but can be resplit by make_keys_shared().
*/
static int
dictresize(PyDictObject *mp, uint8_t log2_newsize)```
sand goblet
#

When is that seen? I tried filling a dict, deleting everything from it, and filling it again, but it never changed its size after the initial filling

raven ridge
fallen slateBOT
#

Objects/dictobject.c lines 374 to 385

/* USABLE_FRACTION is the maximum dictionary load.
 * Increasing this ratio makes dictionaries more dense resulting in more
 * collisions.  Decreasing it improves sparseness at the expense of spreading
 * indices over more cache lines and at the cost of total memory consumed.
 *
 * USABLE_FRACTION must obey the following:
 *     (0 < USABLE_FRACTION(n) < n) for all n >= 2
 *
 * USABLE_FRACTION should be quick to calculate.
 * Fractions around 1/2 to 2/3 seem to work well in practice.
 */
#define USABLE_FRACTION(n) (((n) << 1)/3)```
raven ridge
#

So at the point where an insertion would push the dictionary load over 2/3rds of slots occupied, it will resize. For this, dummy (previously used) slots and active slots count as used, empty (never used) slots don't.

#

When you insert 10k items into the table, it reaches some size, at some load factor less than 2/3rds. Deleting those items changes neither the size nor the load factor - it just replaces active slots with dummy ones. Reinserting the same keys again (or ones that hash to the same slots) doesn't change the size or the load factor - the dummy slots just transition back to active.

#

But, inserting other values that hash to different slots increases the load factor by transitioning more slots to active from empty, and that can cause a resize. And if it does, the table can shrink.

sand goblet
#

!e ```py
import sys

d = {}

for n in range(10000):
d[n] = None

print(sys.getsizeof(d))

for n in range(10000):
del d[n]

start_size = sys.getsizeof(d)
print(start_size)

for n in range(10000):
d[n] = None
size_now = sys.getsizeof(d)
if size_now != start_size:
print(n, size_now)
break```

fallen slateBOT
#

@sand goblet :white_check_mark: Your eval job has completed with return code 0.

001 | 295000
002 | 295000
003 | 922 73816
sand goblet
#

I wonder why it decreased here even though itโ€™s reinserting the same values

raven ridge
#

Hm. I must have something wrong, then. But it does show that the resize is happening in the insert path and not the delete path, at least

sand goblet
#

Yeah

#

I tried it with other multiples of 10 and it didnโ€™t show it

#

So that was confusing

#

But I guess itโ€™s just because itโ€™s hard to get it to be at the right size to trigger it by just picking random sizes like that

surreal sun
#

So replacing the dummy slots with slots with NoneType apparently decreases size?
does NoneType contain less bytes than a dummy slot?

#

or a singular byte

#

Is NoneType just one byte i'm guessing?

#

Or is that irrelevant to the question at all

raven ridge
#

This isn't counting the size of the objects in the table at all. They're totally irrelevant. It's only counting the size of the table itself, not the objects referenced by that table

sand goblet
#

What about the consecutively filled array?

#

Could it be because itโ€™s resizing that?

#

But not the hash table array?

raven ridge
#

It's possible that it's got something to do with that, yeah.

sand goblet
#

!e ```py
import sys

d = {}

print("initial size:", sys.getsizeof(d))

d[0] = None

print("size with 1:", sys.getsizeof(d))

for n in range(10000):
d[n] = None

print(sys.getsizeof(d))

for n in range(10000):
del d[n]

start_size = sys.getsizeof(d)
print(start_size)

for n in range(10000):
d[0] = None
size_now = sys.getsizeof(d)
if size_now != start_size:
print(n, size_now)
start_size = size_now
del d[0]```

fallen slateBOT
#

@sand goblet :white_check_mark: Your eval job has completed with return code 0.

001 | initial size: 64
002 | size with 1: 232
003 | 295000
004 | 295000
005 | 922 232
sand goblet
#

So itโ€™s because itโ€™s also keeping track of how much empty space is in the consecutively filled array?

#

And a resize can also get triggered if that one builds up too much empty space

verbal escarp
#

the short answer

#

use("name") delegates to use_str(name), which checks/registers to sqlite registry, makes sure that version and hash are given, checks pypi for the artifact and makes sure that it's supported on the current platform, (then should pull the artifact from a P2P network and then) delegates the installation to pip as a subprocess, then loads the module, applies aspects to it and wraps it in a ProxyModule for further functionality

#

easy peasy

#

i'd say the main function for the installation alone is

#
def _load_venv_mod(package_name, version) -> ModuleType:
    venv_root = _venv_root(package_name, version)
    pkg_path = _venv_pkg_path(package_name, version)
    venv_bin = venv_root / "bin"
    python_exe = Path(sys.executable).name
    current_path = os.environ.get("PATH")
    venv_path_var = f"{venv_bin}{os.path.pathsep}{current_path}"
    if not venv_bin.exists() or not pkg_path.exists():
        check_output(
            [python_exe, "-m", "venv", "--system-site-packages", venv_root],
            encoding="UTF-8",
        )
    for p in venv_root.rglob("**/python.exe"):
        venv_bin = Path(p).parent
        python_exe = "python.exe"
    pip_args = (
        venv_bin / python_exe,
        "-m",
        "pip",
        "--no-python-version-warning",
        "--disable-pip-version-check",
        "--no-color",
        "install",
        "--progress-bar",
        "ascii",
        "--prefer-binary",
        "--force-reinstall",
        "--exists-action",
        "b",
        "--only-binary",
        ":all:",
        "--no-build-isolation",
        "--no-use-pep517",
        "--no-compile",
        "--no-warn-script-location",
        "--no-warn-conflicts",
        f"{package_name}=={version}",
    )
...
#
...
    if _venv_is_win():
        output = run(
            ["cmd.exe", "/C", "set", f"PATH={venv_path_var}", "&", *pip_args],
            encoding="UTF-8",
            stderr=sys.stderr,
        )
    else:
        output = run(
            ["env", f"PATH={venv_path_var}", *pip_args],
            encoding="UTF-8",
            stderr=sys.stderr,
        )
    log.debug("pip subprocess output=%r", output)
    orig_cwd = Path.cwd()
    try:
        os.chdir(pkg_path)
        entry_points = _find_entry_point(package_name, version)
        for pkg_prefix, entry_module_path in entry_points:
            path = entry_module_path.absolute()
            with open(path, "rb") as f:
                return _extracted_from__load_venv_mod_54(f, package_name, pkg_prefix, path)
    finally:
        os.chdir(orig_cwd)
nova iris
#

hey guys, what's the best way to make a decorator class that accepts optional arguments? my current approach is using a function which, when keyword args are supplied to it, creates a new class that is a subclass of my original decorator class with the kwarg as a free variable
is there a more efficient approach than creating a new class everytime i decorate?

#

my current code:```py
def squarefunction(
function: Optional[Callable[..., Any]] = None,
*, no_verify: bool = False,
):
"""Decorate a function to become a SqaureFunction instead."""
if function is not None: # if deco is invoked in the "normal" way
return SquareFunction(function, no_verify)

class SquareFunctionDecoWrapper(SquareFunction):
    def __init__(self, func):
        super().__init__(func, no_verify)

return SquareFunctionDecoWrapper

```where SquareFunction is my original deco

#

WAIT A DAMN MIN-

#

I CAN JUST USE A FUNCTION

#

BRUH

#
def squarefunction(
        function: Optional[Callable[..., Any]] = None,
        *, no_verify: bool = False,
):
    """Decorate a function to become a SqaureFunction instead."""
    if function is not None:  # if deco is invoked in the "normal" way
        return SquareFunction(function, no_verify)

    def decorator(func):
        return SquareFunction(func, no_verify)

    return decorator
```lesssgo this works
elder blade
# nova iris ```py def squarefunction( function: Optional[Callable[..., Any]] = None,...

You usually do this: ```py
def squarefunction(
function: Optional[Callable[..., Any]] = None,
*, no_verify: bool = False,
):
"""Decorate a function to become a SqaureFunction instead."""
def decorator(func):
return SquareFunction(func, no_verify)

if function is not None:  # if deco is invoked in the "normal" way
    return decorator(function)

return decorator
nova iris
#

if it's negligible, then yeah, this way is more readable

elder blade
#

That's a fair argument, but this decorator is only used whenever you're actually starting your application (when defining the function where this is used)

#

It should be negligible

elder blade
#

It starts to make more sense when your decorator function is more complex than instantiating a class

nova iris
nova iris
#

thanks!

pliant tusk
#

nested functions in python are negligible at runtime, because they only allocate a function object and store the code object on it

nova iris
#

rejoice, as functions invoked with parentheses are no more.

#

introducing... SQUARE FUNCTIONS!

#

example:```py
@squarefunction
def func(a, b, *, c):
print(a, b, c)

func(1, 2, c=3) no no no

func[1, 2, "c":3] # this is the way

#

it has support for parameter verification, instance methods, arbitrary amount of args, and more!

visual shadow
#

one parenthesis requires 2 keys to write (shift + 9), one square brackets require 1. this is clearly a win.

nova iris
nova iris
#

also, congrats on getting mod, @visual shadow!

grave jolt
verbal escarp
#

could you subclass set to make a {} function? ๐Ÿ˜‡

nova iris
verbal escarp
#

hmm.. probably need some AST transform to make it work

pliant tusk
#

func{x} wouldn't parse to AST tho

verbal escarp
#

tricky

#

maybe better that way ^^

grave jolt
#

func@{ ... } would work, though

#

but the args would have no order, though

#

and no kwargs

pliant tusk
#

Could look at the bytecode to get order at least

nova iris
# grave jolt and no kwargs

yeah, there wouldn't be a good kwarg representation like in the case of using subscription syntax (where i used slices)

sand goblet
#

So using OrderedDict instead wouldnโ€™t just be more efficient, it would actually make the time complexity lower?

verbal escarp
#

the best thing you can do is to measure it

#

put it in a func, measure the time for n up to 1000000 or so, plot it

#

there's not really a substitute for measuring things

#

and there's not really a substitute to plotting those things

#

especially runtimes can be wildly non-linear

sand goblet
#

Alright, Iโ€™ll try to measure it

verbal escarp
#

need a template?

#

@sand goblet

visual shadow
sand goblet
sand goblet
#

And it seems like it does it because of space built up in the consecutively filled array.

#

Because in the hash table array, it should just keep getting placed in the same slot and not build up any extra space there

verbal escarp
#

@sand goblet can you show a plot?

#

and the according code

sand goblet
#

I learned matplotlib a while ago, so Iโ€™ll have to relearn it

#

Unless I feel lazy and just use timeit

#

I mean hopefully there will be enough of a time difference for it to be clear that the dict size makes a difference

sand goblet
spark magnet
sand goblet
spark magnet
#

weird

spark magnet
#

it doesn't happen in python2

sand goblet
#

Itโ€™s because of the consecutively filled array it started using

#

I think

#

I think that if you did the same thing before 3.6 then it wouldnโ€™t do that

#

Since it wasnโ€™t using that 2nd array back then

#

But after 3.6, when you do that, that array keeps on building up more and more empty space. So now it ends up needing to resize due to that

spark magnet
#

@sand goblet but that implies that the consecutively filled array is pre-allocated for more than 900 elements, which doesn't seem right.

#

oh, because it's 10,000 elements to begin with

#

I see

sand goblet
#

Yeah

#

And I guess maybe that 922nd time was where it ran out of space and had to resize

spark magnet
#

yes, if you start with 100 elements, it resizes at 70. with 1000, it's 365

sand goblet
#
from timeit import timeit

setup_f = """
def f(d):
    for _ in range(100000000):
        del d[0]
        d[0] = None
"""

print("starting")

for n in range(9):
    setup = f"d = dict.fromkeys(range({10**n}))\n" + setup_f
    print(
        f"size of 10**{n}:",
        timeit(setup=setup, stmt="f(d)", number=10)
    )

print("done")```
#

output: starting size of 10**0: 134.0548474 size of 10**1: 152.4461155 size of 10**2: 151.38745489999997 size of 10**3: 166.49713710000003 size of 10**4: 169.86379470000008 size of 10**5: 224.49477790000003 size of 10**6: 232.23714919999998 size of 10**7: 236.50534930000003 size of 10**8: 322.2628354000001 done

#

it doesn't seem linear

#

I don't get how

#

It seems like it should take more time since it needs to resize a bigger array, but it's not increasing linearly

#

I rewrote it to check the size after running f, and itโ€™s not like itโ€™s never decreasing the size

#

The smaller dicts end at reasonable sizes

#

So idk

raven ridge
raven ridge
sand goblet
#

I donโ€™t get how does it make it amortized in this situation

raven ridge
#

the array itself is larger, since it has more keys in it

#

and when the array is resized is based on how full it's become (meaning that it takes more insertions before the larger array needs to get resized)

spark magnet
#

@sand goblet this is how lists have O(1) append(): resizing is less frequent as the list gets larger

raven ridge
#

and the new array's size is a multiple of the original array's size - it grows by 50% or so - preserving the property that resizes continue to be less frequent each time it needs to resize

sand goblet
#

Iโ€™m imagining the way it would work is:
at the size of 10, it would go up to maybe around 20 used spaces, and then resize down to something closer to 10 again, and keep doing that in a loop.
at the size of 100, it would go up to maybe around 200 used spaces, and then resize down to something closer to 100 again, and keep doing that in a loop.
at the size of 1000, it would go up to maybe around 2000 used spaces, and then resize down to something closer to 1000 again, and keep doing that in a loop.
Something along those lines, except not with exactly the same numbers

#

Because itโ€™s staying at the same number of used spaces

raven ridge
#

taking that and running with it:
At 10 it would need to resize every 10 insertions, so 10,000,000 times.
At 100 it would need to resize every 100 insertions, so 1,000,000 times.
At 1000 it would need to resize every 1000 insertions, so 100,000 times.

#

The resizes become more expensive but less frequent.

sand goblet
#

Oh

#

Yeah

#

Ok, thatโ€™s the reason why

nova iris
surreal sun
nova iris
surreal sun
#

Your code is very well documented tho

#

people who follow PEP8 all the time and not just when it is required >>>>>

nova iris
surreal sun
#

Ahh

#

So it uses qualname?

nova iris
nova iris
surreal sun
#

Ah

nova iris
#

Tomorrow I'll clean it up a bit, I tjink usinh the underlyinh finctipns and metjoda are better

#

Btw, that was a test to see what happens when i type on mobile wiyhout correvting myself lmao

#

Bruh i make way too many spellinv errors because my svreen is small

surreal sun
#

LOL

shut swan
surreal sun
#

@nova iris OHH I get it

class Foo:
    pass
class B:
    var = Foo() # calls Foo.__set_name__

B.var # calls Foo.__get__
variable = B.var # calls Foo.__set__
nova iris
surreal sun
#

When is foo.set called?

#

Thatโ€™s the only thing Iโ€™m confused on

nova iris
#

Inst.descr = value

surreal sun
#

Ahh ok

#

But then that removes the old value

fringe grotto
#

can some one help me solving a examination code?

unkempt rock
#

Why does putting list around groupby consume the inner iterators here?

#

!e ```py
from itertools import groupby
for k, g in list(groupby("AAABBCDDDD")):
print(k, list(g))

fallen slateBOT
#

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

001 | A []
002 | B []
003 | C []
004 | D []
unkempt rock
#

!e it works fine without it pithink ```py
from itertools import groupby
for k, g in groupby("AAABBCDDDD"):
print(k, list(g))

fallen slateBOT
#

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

001 | A ['A', 'A', 'A']
002 | B ['B', 'B']
003 | C ['C']
004 | D ['D', 'D', 'D', 'D']
deft pagoda
#

Seems like it reuses the same 2nd argument:

In [24]: from itertools import groupby

In [25]: g = groupby("AAABBCDDDD")

In [26]: h, i = next(g)

In [27]: j, k = next(g)

In [28]: list(i)
Out[28]: []
#

_grouper object, hmmm:

In [31]: k
Out[31]: <itertools._grouper at 0x21d51bc4eb0>

In [32]: k?
Type:        _grouper
String form: <itertools._grouper object at 0x0000021D51BC4EB0>
Docstring:   <no docstring>

In [33]: from itertools import _grouper

In [34]: _grouper?
Init signature: _grouper(self, /, *args, **kwargs)
Docstring:      <no docstring>
Type:           type
Subclasses:
#

The returned group is itself an iterator that shares the underlying iterable with groupby(). Because the source is shared, when the groupby() object is advanced, the previous group is no longer visible.

unkempt rock
#

Curious pithink

#

so you'd have to [(k, list(g)) for k, g in groupby("AAABBCDDDD"))] to list it properly

deft pagoda
#

yeah

#

np

prisma gyro
#

Right now I am browsing the web to find a solution/lib to detect real time sounds from a stream. Anyone has some good recommendations?
As an example detect the classic Mario jump sound from a stream input

verbal escarp
nocturne delta
#

in which file of python directory can i find built in functions

#

like max min etc

#

if it is in scripts folder

#

๐Ÿ‘€

#

like you can access built in modules in Scripts folder

verbal escarp
#

which file?

#

that's in cpython

nocturne delta
#

damn knew it

nocturne delta
#

Or are they used directly in the script

verbal escarp
#

no idea what you mean

paper echo
nocturne delta
#

what is the difference

peak spoke
#

cpython is the reference implementation of python, cython is an another language on top of python

nocturne delta
#

oh they are just the opposite

#

one is extension in another

paper echo
#

And yes, a lot of Python modules and functions are written in C in the reference implementation CPython, not in Python itself, either for technical necessity or for performance

sharp flume
#
....__new__(....__class__).__str__()
grave jolt
sharp flume
#

brb

nova iris
# surreal sun But then that removes the old value
>>> class DataDescr:
    def __get__(self, instance, owner=None):
        return instance.__yeet
    def __set__(self, instance, value):
        instance.__yeet = value

        
>>> class Foo:
    lol = DataDescr()

    
>>> f = Foo()
>>> f.lol
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    f.lol
  File "<pyshell#5>", line 3, in __get__
    return instance.__yeet
AttributeError: 'Foo' object has no attribute '_DataDescr__yeet'
>>> f.lol = 3
>>> f.lol
3
>>> Foo.lol = 4
>>> f.lol
4
>>> Foo.lol
4
```no, during instance value setting `__set__` is called, but not during class attribute retrieval
#

also, my idle's indents are messed up so :P

nova iris
surreal sun
#

I messed around with prepare a bit

#

typechecking weird looking dataclass

#

!e

from __future__ import annotations
import builtins


class Attrs(dict):
    """Dictionary that takes over namespace."""
    def __init__(self, dct: dict):
        self.values_dct = dct

    def __missing__(self, key):
        if key not in self.values_dct.keys() and not key.startswith('__'):
            if (result := getattr(builtins, key, None)) is None:
                try:
                    result = globals()[key]
                except KeyError:
                    result = locals()[key]

            if not isinstance(self.values_dct.get(
                    (var_name := list(self.keys())[-1])), result):
                raise TypeError(f"{var_name} is not of the type {key!r}")
        elif key.startswith('__'):
            raise KeyError

        value = self.values_dct.get(key)
        self[key] = value
        return self[key]


class AttrDefinition(type):
    """Metaclass for setting the namespace to a special dictionary"""
    def __prepare__(*args, **kwargs):
        return Attrs(kwargs)


class TypeCheckingDataclass(metaclass=AttrDefinition):
    """No-op for allowing kwargs to be passed into the namespace"""
    def __init_subclass__(cls, **kwargs):
        pass

class Foo(TypeCheckingDataclass, x=2, y=2):
  (x, int)
  (y, int)

print(Foo.x)

class Bar(TypeCheckingDataclass, x=2, y=2):
  (x, str)
  (y, int)
fallen slateBOT
#

@surreal sun :x: Your eval job has completed with return code 1.

001 | 2
002 | Traceback (most recent call last):
003 |   File "<string>", line 46, in <module>
004 |   File "<string>", line 47, in Bar
005 |   File "<string>", line 20, in __missing__
006 | TypeError: x is not of the type 'str'
surreal sun
#

it also works with classes within the file itself, instead of just builtins

empty heath
worldly ridge
#

The only reason I used class here is to initialize 1 var only so I will be able to use this s3_client everywhere in the class
Then I use the other method scan_bucket with multithreading.
Do you think itโ€™s a good reason to use class?

#

I am getting really confused with basic design skills & the overall project structure

empty heath
#

@worldly ridge likely not, but occasionally it's ok

#

it's true people don't generally like 1-method classes

#

the way to think about classes (better than the typical textbook "bundles of state and behavior" which doesn't mean much) are they're for "nouns" -- if you have an important noun in your problem you might have a class

#

is an "S3BucketEnum" a thing you're likely to say (in english) when describing what your program does (unlikely, so probably it's not a good class, but if your program is super centered around S3 manipulation, maybe)

#

also if whatever == "protected": protected = True bla bla is a long way to write protected = is_protected == "protected"

verbal escarp
#

i don't see how that s3 client is in any way relevant

#

so no, i don't see any point in making it a class

charred pilot
#

it's not used anywhere in that class?

verbal escarp
#

i don't see anyway

#

maybe somewhere off the screen

#

if s3_client isn't mutated, having it in that class is pretty moot

charred pilot
#

i don't get the enum part of that class

verbal escarp
#

possibly the enum is a collection of functions

#

but then you don't need an extra class..

#

it's a bit wonky ๐Ÿ™‚

prisma gyro
worldly ridge
worldly ridge
astral gazelle
lunar trail
#

@worldly ridge let's not bypass our filters

worldly ridge
lunar trail
# worldly ridge oh sorry

It's much more polite to just ask for more information. That's why we don't allow dumping the link

mystic cargo
verbal escarp
#

grr.. i'd really like a None-aware operator or somesuch

#
from collections import namedtuple

T = namedtuple("tuple", "name")

d = {"foo": T("foo")}

d["foo"].name
#

no problem

#

d.get("foo").name also nice

#

but now try to access the dict programmatically ๐Ÿ˜ฆ

#
thing = "bar"
d.get(thing).name
=> 

Traceback (most recent call last):
  File "<pyshell>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'name'
surreal sun
verbal escarp
#

tbh i don't know the ideal solution to this problem

#

i just know the status quo sucks :p

#

that's why i'm posting it here, maybe there's some spark of genious

unkempt rock
#

You get a decent error message from it

verbal escarp
#

i don't want an error message, i want to default to None or something else without loads of boilerplate

surreal sun
#

getattr(d["foo"], name, None), looks for the attribute name in d["foo"] and defaults to None if there is no name attr iirc

#

Unless that's not what you're trying to do

verbal escarp
#

i know what it does, but that doesn't cover the KeyError ^^

surreal sun
#

Ah

unkempt rock
#

you would use getattr(d.get(thing), "name", None)

verbal escarp
#

yeah

verbal escarp
#

then i could also go with "if name in d:", but there really should be a nicer way

#

maybe something like d[thing]?.name

surreal sun
#

!e

class NoneAwareDict(dict):
  def __matmul__(self, other):
    try:
      return self[other]
    except KeyError:
      return None

my_dict = NoneAwareDict()
my_dict['foo'] = 'bar'
print(my_dict['foo'])
print(my_dict@'bar')
print(my_dict['bar'])
fallen slateBOT
#

@surreal sun :x: Your eval job has completed with return code 1.

001 | bar
002 | None
003 | Traceback (most recent call last):
004 |   File "<string>", line 12, in <module>
005 | KeyError: 'bar'
surreal sun
#

@verbal escarp

#

Something like that

#

or if you wanted to, you could try and patch it into the dictionary builtin itself

verbal escarp
#

i somewhat doubt it would fix the attribute error on None in the subsequent lookup

surreal sun
#

Ah

#

well that you would have to just deal with that

#

Because the dictionary just returns the key, it won't handle the value

unkempt rock
#
In [15]: class NoneAttr:
    ...:     __getattribute__ = lambda *_: None

In [16]: class NoneVals(c.UserDict):
    ...:     __missing__ = lambda *_: NoneAttr()

In [17]: from collections import namedtuple
    ...: T = namedtuple("tuple", "name")
    ...: d = NoneVals({"foo": T("foo")})
    ...: d["foo"].name, d['bar'].name
Out[17]: ('foo', None)
``` this is viable if you're sure you're going to be doing an attribute access, but I just wouldn't bother
halcyon trail
#

@verbal escarp there's languages that handle null chaining beautifully

charred pilot
#

swift has their cool ? operator

verbal escarp
#

how is it handled in those languages?

charred pilot
#
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."
``` <https://docs.swift.org/swift-book/LanguageGuide/OptionalChaining.html>
verbal escarp
#

aha, that would be akin to what i suggested, no?

charred pilot
#

uhhhh, what did you suggest? a null coalescing operator?

verbal escarp
charred pilot
#

oh yeah, it works like that basically. it gives you an optional though

halcyon trail
#

In kotlin you have ?., Null chaining operator, and scope functions,.and a null ternary operator

#

@verbal escarp if you can write out the python code with null checks explicit etc I can "translate" so you can see

surreal sun
#

!pep 505

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

Deferred

Python-Version

3.8

Created

18-Sep-2015

Type

Standards Track

surreal sun
#

delayed i thikn

#

whatever deferred means which is delayed iirc

paper echo
#

I still can't believe we got pattern matching instead of this

#

I would love null-aware/null-propagating . for getattr and [] for getitem

#

I'm less convinced by the null-coalescing ?? operator because we have falsy None, so or works fine 99% of the time

#

??=is a neat trick but ?. and ?[] were seriously valuable

gleaming rover
#

I don't even want statement-based pattern matching

#

time to write Python 4

unkempt rock
#

is localshop still around?

surreal sun
#

One of the reasons for denying 505 was;

#
This has been deferred on the basis of the proposed operators being intended to aid traversal of partially populated hierarchical data structures, not for traversal of arbitrary class hierarchies. This is reflected in the fact that none of the other mainstream languages that already offer this syntax have found it worthwhile to support a similar syntax for optional function invocations.
#

another one was that ? is one of the last available alphanumeric chars for operators

main lynx
#

i would want neither, reject modernity, embrace tradition

paper echo
#

So it's not general enough?

#

Actually optional function invocation is a great idea

#

Well optional conditional on an argument, not the function itself

#

And yes there's no syntax for that because it's a lot more complicated

peak spoke
paper echo
#

Why is traversing an arbitrary class hierarchy relevant here?

#

Nobody wants to do that, people want to operate on data without twisting themselves around

surreal sun
paper echo
#

What does traversing a class hierarchy even mean

surreal sun
#

I don't know it's way too eloquent

#

what does optional function invocation mean? like 0 or func()?

#

or 1 or func()

#

which will call it depending on if it doesn't short circuit?

paper echo
#

Oh hold on

#

You guys misread, I just went back to the doc

#

That was the reason for rejecting a generic syntax for None-short-circuiting function calls

#

As in foo?(x) short circuiting on x

#

So they are saying that they didn't want to over-generalize

#

Which is why they are suggesting PEP 505 and not some very generic thing that works for all function calls

#

Or worse, they are shooting down a proposal for foo?() to dispatch on foo

#

You could make an argument for foo?(), ?., and ?[] all dispatching on their first arguments

#

Although the semantics of self in method calls would be questionable and inconsistent

#

But this is very clearly not the PEP deferral reason

#

It seems like the issue is whether None is special enough to warrant special syntax

#

I personally think it very obviously is, but ๐Ÿคทโ€โ™‚๏ธ

#

Hmmm... imagine if you could subclass None? It would break the is None idiom so it wouldn't work in Python

#

But could have been an interesting language feature

peak spoke
#

What would be the use of subclassing it?

paper echo
#

Custom sentinel values and placeholders, like exceptions

#

To allow the programmer to distinguish between different kinds of missingness

surreal sun
#

You could probably place None with a subclassable None using forbidden fruit or just ctypes i think

#

iirc

#

more like subclassable Nonetype

paper echo
#

Right

surreal sun
#

I would do that but I don't know the deep depths of ctypes or forbidden fruit lol

peak spoke
#

Just make your own class then, none doesn't get you anything

surreal sun
#

Hm, fair

peak spoke
#

The sentinel pep also looks nice

surreal sun
#

what sentinel pep?

peak spoke
#

Sentinel values, don't know the number

paper echo
#

The advantage to subclassing NoneType would be that you could "catch" any form of missingness with isinstance(x, NoneType)

#

Including forms you yourself didn't define or think to include in the check

grave jolt
#

more kinds of null... sounds scary

peak spoke
#

Do you want to include cases you didn't define?

paper echo
#

Basically making it analogous to Exception

surreal sun
#

I was bored so I tried to make a rust looking closure

eval isn't very secure though

#

!e ```py
from future import annotations
from forbiddenfruit import curse

def or(self, other):
if not isinstance(other, str):
raise TypeError

return ClosureFunction(self, other)

curse(list, "or", or)

class BlankSpace:
"""Made for the purpose of looking like a closure"""
def or(self, other):
"""Allowing to look more like a closure"""
return other

class ClosureFunction:
def init(self, params, func):
self.params, self.func = params, func

def __call__(self, *args, **kwargs):
    assert len(self.params) == len(args) + len(kwargs)
    for value, name in zip(args, self.params):
        locals()[name] = value

    for param_name, param_value in kwargs.items():
        locals()[param_name] = param_value

    result = eval(self.func)
    return result

ใ…ค= BlankSpace()
cool_func = ใ…ค|['x', 'y', 'z']|"x + y + z"
print(cool_func(1, 2, 3))

fallen slateBOT
#

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

6
surreal sun
#

Wait a minute, forbiddenfruit works on snekbox??

onyx flower
#

what is literals ?

fallen slateBOT
#

typing.Literal```
A type that can be used to indicate to type checkers that the corresponding variable or function parameter has a value equivalent to the provided literal (or one of several literals). For example:

```py
def validate_simple(data: Any) -> Literal[True]:  # always returns True
    ...

MODE = Literal['r', 'rb', 'w', 'wb']
def open_helper(file: str, mode: MODE) -> str:
    ...

open_helper('/some/path', 'r')  # Passes type check
open_helper('/other/path', 'typo')  # Error in type checker
```...
fallen slateBOT
#

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

6
spice pecan
#

oh wow

#

!charinfo ๏พ 

fallen slateBOT
toxic fractal
#

i have two list ,
img_list contains bunch of numpy arrarys
img_ID contains ID

problem : i want Index of 'scissor.png' which is in img_ID how i can access it?

visual shadow
fallen slateBOT
#

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

hi
#

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

{}
vast cloud
#

On a different note, I read in the PEP505 discussion thread that there is 5 different singletons, which ones? Only None comes to my head

visual shadow
#

True and False also. Can't immediately think of more.

grand crag
#

NotImplemented and Ellipsis too, iirc

flat gazelle
#

ye, None True False NotImplemented Ellipsis are the 5

#

True False are not singletons, but shhh

grand crag
#

what is the singleton to rule them all ? ๐Ÿ˜‰

#

True and False, at least in CPython implementation, are singletons ๐Ÿค”

flat gazelle
#

singleton is a class with a single instance to my knowledge

#

True and False are two instances of the same class, ergo not a singleton

granite sphinx
#

def python(x):

grand crag
#

makes sense, indeed

grave jolt
#

@flat gazelle I think in this context it means something like "an object which is equal only to itself"

flat gazelle
#

which is not true for True and False

#

since they are numeric types

grave jolt
#

hmm

#

๐Ÿค” right

vast cloud
#

Nicenice

grave jolt
#

then I have no idea what it means lol

vast cloud
#

This might be somewhat philosophical but the poster probably just meant True and False as well

#

Unless someone can think of 2 other ones

flat gazelle
#

probably things you should use is to compare with

grave jolt
#

what kind of a definition is based on "should"

#

What about this: an object you cannot construct in another way. For example, if you do 5 == 5 or bool(42) you get the same object

flat gazelle
#

well, int and str will also share some instances

#

but IG it is a good enough definition

grave jolt
#

yeah, but it's not guaranteed

#

caching can be done by anything (if it doesn't break stuff)

flat gazelle
#

how about just instances of types where python specifies a finite number of instances

grave jolt
#

that's a better definition

#

what about just types with a fixed, finite set of instances?

#

hmmmmmmmmmmmmmmm

#

well, float has a finite number of instances

flat gazelle
#

they do not, you can have two distinct equal floats

grave jolt
#

hm wait, it doesn't

#

yeah yeah, just a finite number of values, the objects might be different

#

'finite number of instances' is good because it includes enums

#

well, bool is an enum, conceptually

fallen slateBOT
#

class enum.Enum```
Base class for creating enumerated constants. See section [Functional API](https://docs.python.org/3.10/library/enum.html#functional-api) for an alternate construction syntax.
grave jolt
#

!e

from enum import Enum

class Bool(int, Enum):
    No = 0
    Yes = 1

print(Bool.No, Bool.Yes)
print(Bool.No is Bool.No)
print(Bool.Yes is Bool.Yes)
print(Bool.No.value, Bool.Yes.value)
fallen slateBOT
#

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

001 | Bool.No Bool.Yes
002 | True
003 | True
004 | 0 1
grave jolt
#

you can click on the embed title to visit the full page

grave jolt
#

it doesn't include object-sentinels

gleaming rover
#

I give it 30 min before we devolve into type theory

grave jolt
#

N-dimensional ectofibrocardiomorphism

#

you win

#

Maybe we should just define the semantics behind is and == and then it will become clear?

#

is is used when you want to compare objects by identity, == when by value (whatever equality means between these values (wink numpy))

#

But that is not a useful definition -- it doesn't tell you when you use is and == besides a tautology

astral gazelle
#

Are file writes in python buffered?
Does using an intermediate buffer list instead of writing in a loop give any noticeable perf benefits?

flat gazelle
#

ye, some buffering is done

grave jolt
#
import time
for i in range(10):
    print(i, end=" ")
    time.sleep(0.1)
verbal escarp
#

i realised there's a very useful pattern in func signatures

#

one positional-only, rest keyword-only

#

it's quite fascinating how much it simplifies call-chains

astral gazelle
#

Would you still recommend i use a buffer list instead of having a bazillion writes in a loop?

#

Im processing a lot of text files

verbal escarp
#

did anyone else stumble across that pattern?

grave jolt
astral gazelle
#

I'll get to that eventually, some bugs still holding me back from running the script, was hoping for a clear advantage with buffer lists

grave jolt
#

@astral gazelle but what are you going to do with the list? writelines?

astral gazelle
#

Right now im joining it into a big string and dumping it in the file with write

verbal escarp
#

big string?

#

how big?

#

how long is your longest line?

astral gazelle
#

Couple thousand lines, average of like 80char per line

#

Per file

verbal escarp
#

ok, that works

grave jolt
#

sounds like on the order of megabytes