#internals-and-peps

1 messages · Page 136 of 1

static bluff
#

When something is explicitly marked as private, the only people you need to worry about reading your code are 'hackers' — deep divers I should say

#

And they can contend with the lack of safety precautions just fine. But I don't want anyone swimming into too deep of waters in search of treasure, and drowning

#

It seems, though, that there is a consensus. Don't even bother with the babyproofing. Just try to keep it as clean and logical as possible, and then document it to death

verbal escarp
#

you achieve that by good and proper doc strings for whatevery you intent as user-facing API

static bluff
verbal escarp
#

actually, you can

#

help(stuff), IDEs etc. all rely on proper docstrings

#

and are presented to the user whenever they run into trouble

#

external web sources as documentation on the other hand probably are only looked at if there's a link in the docstring

static bluff
#

Hmmmm

#

Well, nothing for it but to push forward I guess

#

Though, I'm still keeping the Cython idea in the back of my mind. Its a means of completely cutting off access to stuff if need be, without having to jump through any convoluted hoops

lusty scroll
#

ate you distributing binary-only releases?

static bluff
#

And again, its not about preventing anyone from messing around, just separating the safe from the unsafe

#

No, pip

#

I mean, I'd never considered a binary-only research.

#

*release

lusty scroll
#

thats nice

verbal escarp
#

if people run into problems, having the source can help a great deal

static bluff
#

Always a pleasure my friends. I'm off to go learn about 'cin' and 'cout' in C++. Riviting stuff

sand goblet
#

Why are some standard library modules written in C and others are written in python? Even if it’s a module where speed doesn’t matter, wouldn’t writing it in C reduce python’s overall size?

flat gazelle
#

because python is easier to maintain

peak spoke
#

More maintainable to write in, and wouldn't distributed python source be smaller than including the binary?

sand goblet
#

.py files might be smaller

#

But are .pyc files smaller?

static bluff
peak spoke
#

doesn't really matter if they're not distributed, and locally their size is irrelevant

sand goblet
#

Oh

peak spoke
#

my whole testing python install is only 300MB with a lot of huge frameworks which is fairly small compared to other things you'd find on a modern PC

sand goblet
#

So it’s a non-issue

peak spoke
#

Yes, the few saved kb if we're generous are vastly outweighed by the ease of maintaining python instead of C

sand goblet
#

On disk

#

Would memory be much different?

#

It’s still dealing with python objects underneath, right?

elder blade
#

Yes, but depending on what this module does you don't need to always deal with Python's object.

#

Hmm, I don't have a good way to compare sadly. I was thinking of using some Cython-generated files I have but Cython uses macros very strongly to tweak code so the files become huge.

visual shadow
lusty scroll
#

any new module written in C has to have a writeup justifying it, I think

acoustic crater
#

I think there's also something to be said for Python intermediates who don't know C being able to investigate how a module does what it does

rapid rover
#

It is able to grasp pretty complex functions, as with this example: #internals-and-peps message

I gave it very specific instructions, and while the end result isn't necessarily pretty, it followed my instructions completely...

main lynx
#

i could get behind running mypyc on all the pure python stdlib modules

verbal escarp
#

"pure python stdlib" .. ehh.. yeah :p

elder blade
#

Many of them are slight hacks though right

#

I don't think they would get behind strongly typing it

verbal escarp
#

"slight" 😉

lusty scroll
#

lol

grave jolt
#

What's the correct way to report a malware package (such as a typo-squatting token grabber) to PyPI?

lusty scroll
#

there's a reason they said "don't imitate stdlib" i guess

verbal escarp
grave jolt
#

security@python.org?

lusty scroll
velvet lava
verbal escarp
#

hold on

verbal escarp
#

upvote

velvet lava
#

@verbal escarp , thanks man

grave jolt
verbal escarp
#

trying to remember how i reported a package once

grave jolt
#

I reported two packages, didn't get an ACK, one of the packages is still up 😦

verbal escarp
#

and from there, there are several other issues

#

specifically

#

which was opened 2018 and is still open :p

grave jolt
#

Should I reemail pypi? Maybe they just lost my message?

verbal escarp
grave jolt
verbal escarp
#

doesn't that mean there should be a button on pypi to report spam?

#

maybe you need to be logged in?

peak spoke
#

doesn't look like that was merged

verbal escarp
#

sigh.

verbal escarp
#

support isn't a big topic for pypi

#

"how to get support" says: For support related to a specific project, see the links on the Projects page. For something more general, or when you’re just not sure, please open an issue on the packaging-problems repository on GitHub.

#

maybe reporting it via github is the way to go?

grave jolt
#

no, it explicitly says on the page to not report security issues publically

#

that would be a disaster

verbal escarp
#

it's not a security issue for pypi though

#

it's a security issue for everyone else

peak spoke
#

You don't expose any vulnerability by reporting a malicious package, it's even better as other people can clearly see that it's malicious without looking at it themselves before it's removed

grave jolt
#

some people will inadvertently download it

peak spoke
#

whether it would be the proper place, I have no idea but there seem to have been a few issues like that

grave jolt
#

I already defused the package, so no worries

verbal escarp
#

public and non-anonymous doesn't feel right, though.. i wished there was a sanctioned method for this 😐

verbal escarp
#

table of contents?

#

that would be quite valuable in justuse

elder blade
lusty scroll
#

it's surprising that they've been hit quite a few times and there's still no interest in an efficient reporting mechanism

#

don't jupyter notebook store python in json though?

elder blade
#

.ipnyb files are just JSON

lusty scroll
#

i see its a floating widget with the TOC on the notebook itself

#

seems like vscode should have just implemented a notebook extension, then TOC would automatically work

astral gazelle
#

What on earth is a TOC

sacred yew
#

table of contents?

#

lol

elder blade
#

It is

astral gazelle
#

Im asking with regards to the vscode gh issue above, is it actually table of contents?

elder blade
#

We're discussing IPython features I guess?

elder blade
#

The typical workflow is then to open an Interactive Window and execute a few of the cells of interest. So for finding these cells in the large file the described TOC is useful.

astral gazelle
#

Pretty sure vscode already has a table of contents of some sorts, doesnt breadcrumbs count as a navigation tool

tulip condor
#

hello guys, anyone with can help me with generating a small ms access report of the database?

elder blade
#

Do you guys get the thing with Exception groups?

#

Gonna read the proposal now but interested what others think

surreal sun
#

Which proposal?

elder blade
surreal sun
#

Maybe the PEP is just too verbose but is this trying to do something with Exceptions having sub-exceptions for example so you can catch them too??

elder blade
#

Yes

#

You want to raise two exceptions at the same time

surreal sun
#

Hmm, I don’t really like this proposal

elder blade
#

I think it will be good

surreal sun
#

Yeah I just don’t think I’m understanding it

#

I guess it can result in more descriptive errors

elder blade
#

If I kind of understand it correctly, instead of discord.py's CommandInvokeError wrapping an error you can have this I think?

surreal sun
#

So less of a need of inheritance, I suppose?

median palm
#

Alright, so lets say I have a decorator, which decorates a function. Inside this decorator, I want to access all of the variables inside the decorated function, without having any variables that I declared in the decorator show up or overlap

#

is there a way for me to access the decorated functions state here

verbal escarp
#

can you post your code?

median palm
#

for the decorator?

surreal sun
#

Did I spell it wrong, hm

median palm
#

I also want it to have access to globals

#

not just locals

median palm
# verbal escarp can you post your code?
def macro(func: typing.Callable):
    source_str = inspect.getsource(func)
    source_str = source_str.replace("@macro", "")
    source_str = source_str.replace(f"def {func.__name__}():", "")
    source_str = textwrap.dedent(source_str)

    tokens = tokenize.tokenize(BytesIO(source_str.encode("utf-8")).readline)
    for toktype, tokval, _, _, _ in tokens:
        if toktype == tokenize.COMMENT:
            lexer = MacroLexer(tokval.replace("#", ""))
            lexer.tokenize()

            parser = MacroParser(lexer.tokens)
            code = parser.parse()
            source_str = source_str.replace(tokval, code)

    @functools.wraps(func)
    def wrapper():
        exec(source_str)

    return wrapper
#

I'm finding and replacing certain parts of code with python code

#

I'm not sure its quite practical, but its fun :P

surreal sun
#

Could you get the frame of the function and do f_locals, would that work?

peak spoke
#

the function only has some state while it's running, how do you want to access is outside of the function's runtime? (without concurrency)

verbal escarp
median palm
#

hm, I could read up on it

surreal sun
#

I mean I found and replaced parts of python code without the AST, but maybe it wasn’t the best way

#

It probably wasn’t

elder blade
median palm
#

I'm taking code as a string, finding comments, taking the text inside the comments, sticking it to a parser, which then gives me valid python code in return, which I then insert into a string which contains the original functions source code, and then I exec it

peak spoke
# median palm wdym?

if you have def f(): a=5; b=6 the locals with the values only exist during the function's execution, but it doesn't sound like you need to access that state. This sounds more suited to something like an import hook

median palm
#

oh yeah

#

hm, what's an import hook?

#

If I can't access the functions locals while running, what if I modify the function a bit so that it returns the locals stored inside that function, run it, get the locals from that, and then work from there

#

wait no, that doesn't work

#

hm, what if I tokenize the functions code, extract the locals, and evaluate them

#

hm, maybe not

#

wait nvm it might work

surreal sun
#

An import hook is something that intercepts an import (I think)

#

At least from what I've gathered while readin gstuff

median palm
#

hm, ok

#

maybe I could do this with ast

tulip condor
#

I need help in generating a ms access database report, anyone to assist me?

boreal umbra
heady mauve
#

Pretty sure I've discovered a bug in the CPython implementation of context managers. No idea how I triggered it, but at the end of my program, if I use a context manager to clean up, it dumps random binary in the first print called from the exit function of the context manager. Switch from a context manager to a try/finally block and voila, it disappears...

#

Wait no, nevermind. Switching to a try/finally only fixes it sometimes...

verbal escarp
#

can you post your code?

heady mauve
verbal escarp
#

the snippet that you think is giving you trouble, not your whole project please

heady mauve
#

cd to the directory, run python Logical.py examples\led.lgc

verbal escarp
#

minimal example 😉

heady mauve
#

and here's the code that calls it:

if __name__ == '__main__':
    with ansiManager():
        sim = simulation()
        sim.main()
heady mauve
#

and the last stable release did not do it. I didn't really touch the ANSI part between then, but I have no idea what's happening here.

#

Ok, I figured it was dumping memory...

#

looks like a help string

small swallow
#

anyone who knows how to use libcst can i get some help in #help-potato

pulsar gale
#

does anyone use mac

#

or macbook

verbal escarp
#

link?

fierce silo
#

Is programming in danger in the future? because of possible AI programmers and these days anyone can create websites and projects easily.

elder blade
#

Simple answer no

#

Who is making those services that allow anyone to create websites?

#

The AIs are trained on human programming yeah?

fierce silo
#

they will be

#

in future

#

and those services are made by fewer than everybody

paper echo
#

!ot

fallen slateBOT
lusty scroll
#

humans writing code directly is bad enough

#

humans writing code writing code will be better, im sure

elder blade
#

Wait isn't ParamSpec implemented yet?!

verbal escarp
elder blade
#

I always thought it was implemented

#

In like Python 3.8 or something

verbal escarp
#

not sure what ParamSpec is supposed to be

elder blade
#

I have a usage that looks roughly like this: ```python
P = ParamSpec('P')

class Command:
def init(self, callback: Callable[P, Coroutine]) -> None:
...

def __call__(self, *args: P, **kwargs: P) -> Coroutine:
    ...
elder blade
#

Why can't I find documentation about it

verbal escarp
#

never encountered it in the wild

elder blade
#

Aaaaahhhh

#

Python 3.10

#

Decorators that mutate the signature of the decorated function present challenges for type annotations. The ParamSpec and Concatenate mechanisms described in PEP 612 provide some help here, but these are available only in Python 3.10 and newer. More complex signature mutations may require type annotations that erase the original signature, thus blinding type checkers and other tools that provide signature assistance. As such, library authors are discouraged from creating decorators that mutate function signatures in this manner.

static bluff
#

Aiiight AD people

#

I'd like to steal some brain power if it's okay

#

This framework I'm working on. The graphics library.

#

The shape its taking, frankensteined together as it is, is essentially a python powered web browser

#

As with Chromium (google chrome minus the bells and whistles), my program is a multiprocessed one. I have a strong suspicion that other browsers also run each window in their own processes as Chromium does

#

So here's the basic setup. I've got a main Application Process (AP), and each window does its work in its own Window Process (or Render Process)

#

This setup is something I just gravitated towards as I worked the problem, but I know its not the only option. If its alright, I was hoping someone could help me spitball the pros and cons of this approach

lusty scroll
#
def add_logging(f: Callable[..., R]) -> Callable[..., Awaitable[R]]:

that just makes me cry

#

Callable[..., R] gives zero information except that it returns something called R, no?

static bluff
#

I have... no idea what you're talking about

lusty scroll
#

it's code from the Parameter Spec PEP

lusty scroll
static bluff
#

Forget it XD I'm in too deep. I can't get any good feedback from anyone without explaining so fuckin much, and even then people are missing big chunks and can't really see the whole project

#

I appreciate it, and I'll just keep my mouth shut from now on

main lynx
#

i'm reading what you wrote and still a bit confused what it has to do with python

#

or why you wouldn't use something like pyglet or pygame/opengl instead of subprocessing browsers

static bluff
#

Pygame is fairly primitive, and opengl is way too low level

#

If either of those were good answers to making applications with Python, there would be plenty of applications with Python already made in them

#

Can't say I've ever given pyglet much thought though

main lynx
static bluff
#

Don't get me wrong, Pygame is lovely ❤️ It has a special place in hearts of many python devs because its a great place to start with both graphics, and python in general.

#

But its surface based approach, as opposed to element based, prohibits 'serious' usage. Any time you make a change to some 'thing' you need to completely wipe the screen, and redraw. This is very slow and complicated.

#

I went through the motions of implanting an object based architecture on top of Pygame that took care of clearing and redrawing elements every frame (assuming some change to some object had occured since the last one). Aside from being hellishly slow, it began to resemble an element based system

main lynx
#

right, pygame with software rendering is very slow, wouldn't recommend it

static bluff
#

To my understanding, every other graphics frame is (and rightly should be) widget based in that you the user never actually make any draw calls, you just specify the graphical attributes of a thing and the system takes care of the rest.

#

From what I've seen, and it has been a while since I toured all the different libraries, they are all either too complicated or just look like crap—or both

#

I don't ever expect anyone to use my library, but the theory is sound. Remote control over web graphics using a pythonic implementation of Javascript's element API

main lynx
#

remote control over web graphics is pretty common in industry prototypes, putting python in the browser not so much

#

also almost nobody gets data streaming into or out of browsers right

#

had to explain to two different roomfuls of engineers that browsers can't open raw UDP sockets just last week 😄

lusty scroll
#

how do you have to redraw everything?

#

it's double buffered

#

you just draw the changed stuff, right

#

then it blits the area to your screen

lusty scroll
elder blade
#

The problem is that type checkers don't know if the first ... and the second ... is the same ...

#

This is what ParamSpec solves

lusty scroll
#

why is it ... ? doesn't the function have to know what the arguments are?

elder blade
#

... is a sentinel (special flag value) that means "variable unknown arguments"

surreal sun
#

It could be any function though too

#

Meaning that you wouldn't know

elder blade
#

Otherwise you would have the arguments in a list like: [int, str, str] (a: int, b: str, c: str)

heady mauve
#

And generally conhost's output buffering breaking. I suspect Windows Update had something to do with that...

heady mauve
#

as far as I can tell

lusty scroll
#

printing reprs of things has crashed my terminal before

heady mauve
#

I saw stuff like help strings, pyc binaries, etc. The weird part was that a specific print statement always triggered it.

lusty scroll
#

Sounds like memory corruption

heady mauve
#

I think something one of my libraries was doing or how rapidly I was calling print without scrolling the console caused buffer overflows, either in CPython's print source or in conhost.

lusty scroll
#

honestly dont know how that stuff could end up in a python string unless it was overwrittrn

heady mauve
#

I honestly think conhost was reading outside the string

lusty scroll
#

maybe some atexit() function

heady mauve
#

that is where it happened but not what caused it

lusty scroll
#

was trying to print a warning

#

that was too late :p

heady mauve
#

Anyway, this is what fixed it:

sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
#

I put that after the imports in the main file, then fixed a thread contention and voila!

lusty scroll
#

you had to reinit stdout?

#

i see..

heady mauve
#

I reinitialized it with buffering disabled

lusty scroll
#

sure seems like a bug..

surreal sun
#

How exactly does an import hook work?

white nexus
#

wdym

surreal sun
white nexus
#

??

#

oh i think i kinda know somewhat

surreal sun
#

How do they work exactly

white nexus
#

wait nope

lusty scroll
#

you implement a Finder protocol

#

and stick it in sys.meta_path

#

!e

import importlib.abc
print(dir(importlib.abc))
fallen slateBOT
#

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

['ExecutionLoader', 'FileLoader', 'Finder', 'InspectLoader', 'Loader', 'MetaPathFinder', 'PathEntryFinder', 'Protocol', 'ResourceLoader', 'ResourceReader', 'SourceLoader', 'Traversable', 'TraversableResources', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_bootstrap', '_bootstrap_external', '_frozen_importlib', '_frozen_importlib_external', '_register', 'abc', 'machinery', 'runtime_checkable', 'warnings']
lusty scroll
#

then you'll get called to find modules and you can respond, delegate loading the source code from the successive finder, then do whatever replacement you want, and return that basically

#

MetaPathFinder is the easiest to subclass

rotund fulcrum
#

!e

#

!e help

#

!e print("Hello, world!")

#

Ok

sturdy timber
#

!warn 890860286007971861 Don't post random dodgy links here

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied warning to @idle garnet.

lusty scroll
#

!e

from importlib.abc import Finder
from _sitebuiltins import _Helper as help
help(Finder.__init__)
unkempt rock
#

can you help me with this

lusty scroll
elder blade
#

There's just a missing parenthesis on the line above (27)

native flame
#

What is the reasoning behind set methods such as set.intersection and set.union accepting any iterable as the second argument but the corresponding operators (|, &) accepting only sets?

sturdy timber
#

Possibly to ensure a & b is the same as b & a, for example

#

It's more explicit and shows that it's the set that's controlling the operation, not the other type

charred pilot
native flame
#

!e no

print({1, 2, 3}.intersection([2, 3, 4, 5]))

print({1, 2, 3} & [2, 3, 4, 5])
fallen slateBOT
#

@native flame :x: Your eval job has completed with return code 1.

001 | {2, 3}
002 | Traceback (most recent call last):
003 |   File "<string>", line 3, in <module>
004 | TypeError: unsupported operand type(s) for &: 'set' and 'list'
charred pilot
#

oh duh, you can still loop

native flame
sturdy timber
#

yeah can't think of anything

charred pilot
#

list += str

native flame
#

🤔

gloomy rain
charred pilot
#

oh depends on your definition of work

native flame
#

no i meant whether or not it errors

gloomy rain
charred pilot
#

list can use += with any iterable but not necessarily the other way around

gloomy rain
#

Although, I guess the assignment operator works like that

#

a = 1 is fine but 1 = a will error

native flame
#

oh right, = does count as an operator

sturdy timber
#

Is = an operator? I guess it's mainly just semantics, but i'm not sure i'd call it one. I'd say := would be more of on operator, still not sure i'd call it one though

#

nvm I guess it is

#

"assigment operator" is a fairly common term

native flame
#

oh i found one, str % int and int % str

In [25]: "h %d" % 1
Out[25]: 'h 1'

In [26]: 1 % "h %d"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-26-0be8d1c43bc1> in <module>
----> 1 1 % "h %d"

TypeError: unsupported operand type(s) for %: 'int' and 'str'
spice pecan
#

Whether or not = would count as an operator in Python is an interesting question since it doesn't return anything, unlike in most other languages

peak spoke
#

Really just depends on how you define "operator", I'd call = itself an operator but as a whole it's the assignment statement

spice pecan
#

Yeah, I'd still count that as an operator

#

A very special operator, but still

surreal sun
#

I mean if the __i*__ set is considered as operators, = is probably an operator too

verbal escarp
#

actually, = is an operator, you can modify the behaviour

#

i've done so once, but i wouldn't recommend it in general

sturdy timber
verbal escarp
#

you can have side-effects on assignment

grave jolt
#

on assignment of a name - no

charred pilot
#

with descriptors?

grave jolt
#

unless you mean assigning to an attribute or key

#

or unless you mean C++

verbal escarp
#

no, python

grave jolt
#

then what do you mean?

verbal escarp
#

let me show you the one and only example where i used it to make things nicer for the user

#

for example in [4], there's T.down = S(20, 20)

#

S is a function which is turned into a Set on assignment as a sideeffect to add logical operators

#

which makes it much nicer for the user

#
    def __setattr__(self, name, value):
        """Define a set within a domain or assign a value to a domain attribute."""
        # It's a domain attr
        if name in self.__slots__:
            object.__setattr__(self, name, value)
        # We've got a fuzzyset
        else:
            assert str.isidentifier(name), f"{name} must be an identifier."
            if not isinstance(value, Set):
                # Often useful to just assign a function for simple sets..
                value = Set(value)
            # However, we need the abstraction if we want to use Superfuzzysets (derived sets).
            self._sets[name] = value
            value.domain = self
            value.name = name
#

that's how it works behind the scene

#

i'm pretty sure you could also do that with module-level variables, but i've never tried to change the Module implementation, so feel free to experiment

grave jolt
#

yeah, you can customize attribute setting

#

but you can't do that with module-level vars

#

well, you can if you return a proxy instead of your module

verbal escarp
#

:]

#

you're reading my mind

knotty tendon
#

Is there any way in python to fork a new process from a function when calling another function which is totally independent from the calling fn?
Example:

def fn1():
stmt1
call_independent_fn2() #achieve ||elization here
stmt3
return

grave jolt
#

then you'll have to use something weird if you want to set variables in your module

lusty scroll
sturdy timber
#

@verbal escarp Wait so what's your definition of an operator?

knotty tendon
verbal escarp
grave jolt
#

I'm afraid everything is an operator then

verbal escarp
#

yeah, pretty much

lusty scroll
grave jolt
#

hm???

verbal escarp
lusty scroll
#
  • to a subtype of ModuleType so __getattr__ and __setattr__ can be customised, that is
grave jolt
#

__getattr__ already works

lusty scroll
#

idk what exactly was meant by proxy but figured subtype of ModuleType isnt necessarily one

verbal escarp
#

hmm

#

question is where to make the change..

lusty scroll
#

proxy would be kind of a delegating module, I would think

verbal escarp
#

tricky

lusty scroll
#

i guess you start with a regular ModuleType object, then set __class__ on it?

verbal escarp
#

but i think you can only do that on a module you imported

#

not on the module you're coming from, no?

lusty scroll
#

oh, I don't think it specifies. I'll dig it up

verbal escarp
#

ohh

#

you could get it via sys.modules["__main__"]

#

hehe

#

😈

#
<method-wrapper '__setattr__' of module object at 0x00000264BB8872C0>```
#

ohh yeah

#

now we only need to rebind a free function as a method of that module

lusty scroll
#

This goal that motivated this patch was getting __class__ assignment to work on modules, which are mutable and uncacheable and totally safe. With this patch it becomes possible to e.g. issue deprecation warnings on module attribute access,
https://bugs.python.org/issue24912
some strong opinions on that bug 👀

verbal escarp
#

at this point the whole distinction of "free variable" and "bound" becomes a blur

lusty scroll
verbal escarp
#

if you write a function in a module, it's kind of bound to that module.. philosophically, there's never a "free function"

lusty scroll
#

(6).__class__ = float

#

assume thats been fixed

verbal escarp
#

a long stroll into monkey-patching land

lusty scroll
#

heheh

verbal escarp
#

let's try it with a MethodType

lusty scroll
#

lol ModuleType is literally singled out

verbal escarp
#

not sure why this isn't working

#
import sys
from types import MethodType, ModuleType

def foo(mod, name, value):
    object.__setattr__(mod, name, value * 2)
    
sys.modules["__main__"].__setattr__ = MethodType(foo, sys.modules["__main__"])
x = 2
print(x)
#

but i guess that's one way to approach it

spice pecan
#

In your case, __setattr__ becomes an instance attribute

#

Most dunders aren't directly looked up on the instance, they're looked up on its type instance

verbal escarp
#

which is correct, since __main__ is an instance of ModuleType

spice pecan
#

!e ```py
class Example: pass

e = Example()
e.setattr = print
e.xample = 42
type(e).setattr = print
e.xample = 42

fallen slateBOT
#

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

xample 42
spice pecan
#

So that's one of the reasons it didn't work

#

The other is I'm not sure if global assignments use __setattr__ at all

verbal escarp
spice pecan
#

!e ```py
import main as main
from types import ModuleType

class Doubler(ModuleType):
def setattr(self, attr, value):
if isinstance(value, int):
value *= 2
super().setattr(attr, value)

main.class = Doubler

x = 21
print(x)

fallen slateBOT
#

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

21
spice pecan
#

Seems like it isn't

flat gazelle
#

ye, afaik globals bypass dunders

#

only module level accesses work

spice pecan
#

Module-level __getattr__ is special-cased, right?

#

As in, it works if it's defined on an instance and not its type

flat gazelle
#

ye, that one is an entirely different protocol

lusty scroll
spice pecan
#

Generally, yes, but global assignments don't trigger __setattr__ anyway

spice pecan
lusty scroll
#

something must be calling __setattr__ (or Py_GenericSetAttr or some C function I guess)

spice pecan
#

Not necessarily, it could directly affect the dict, for example

lusty scroll
#

i wonder if a ModuleType could have __slots__

spice pecan
#

!e ```py
class Example:
setattr = lambda *a: print('No')

e = Example()
e.denied = 10
e.dict['sneaky'] = 10
print(e.sneaky)

fallen slateBOT
#

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

001 | No
002 | 10
verbal escarp
spice pecan
#

Technically yes, but, as I've shown a bit later, assignments don't trigger __setattr__

verbal escarp
#

Traceback (most recent call last):
File "F:\Dropbox (Privat)\code\justuse\tests.tests.A", line 7, in <module>
sys.modules["main"].class.setattr = MethodType(foo, sys.modules["main"])
TypeError: can't set attributes of built-in/extension type 'module'

spice pecan
#

You can either replace the class or use something like forbiddenfruit to patch the original

verbal escarp
#

python doesn't like that at all

spice pecan
verbal escarp
#

replace the class, yeah

spice pecan
#

If you do the same but explicitly use attribute assignment, the value should be doubled

#

!e ```py
import main as main
from types import ModuleType

class Doubler(ModuleType):
def setattr(self, attr, value):
if isinstance(value, int):
value *= 2
super().setattr(attr, value)

main.class = Doubler

x = 21
main.y = 21
print(x, y)

fallen slateBOT
#

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

21 42
spice pecan
#

Maybe you could fiddle with the underlying dict, actually

verbal escarp
#

well, that's what i feared about the current module being special

#

you can do the whole weird stuff with modules you imported, but the one you're currently in is somehow holy

spice pecan
#

I wouldn't say so

#

If you try the same with a different module, assignments within that module are treated the same way

verbal escarp
#

if __main__ really was the module you're currently executing, it should also hit x, no?

#

and i'm replicating the same behaviour here

#

either way i'm trying to execute it, doesn't work

spice pecan
#

No, because the implementation of assignments uses a different mechanism. Regular assignment and attribute assignment aren't the same thing, even though their semantics are similar (especially in terms of modules)

#

If you try to do that in a different module and then perform a global assignment within that module, it still won't trigger __setattr__

#

Regardless of whether it's imported

verbal escarp
#

okay

spice pecan
#

!e ```py
class DoubleDict(dict):
def setitem(self, key, value):
if isinstance(value, int):
value *= 2
super().setitem(key, value)

from types import ModuleType
class Doubler(ModuleType):
pass

import main as main
main.class = Doubler
main.dict = DoubleDict(main.dict)
x = 10
print(x)

verbal escarp
#

so pure x is never an attribute of the current module, truely free?

fallen slateBOT
#

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

001 | Traceback (most recent call last):
002 |   File "<string>", line 13, in <module>
003 | AttributeError: readonly attribute
spice pecan
#

Ah, that's unfortunate

spice pecan
verbal escarp
#

but assignment is restricted

#

bleh

#

so, how does python assign a free variable?

#

it's a weird question.. 😄

spice pecan
#

Most likely by directly changing the module dictionary

verbal escarp
#

that's something a noob would ask in the first 5 minutes of learning the language

spice pecan
#

We'll have to take a look at the source for STORE_NAME/STORE_GLOBAL

verbal escarp
#

15 years later.. same question

fallen slateBOT
#

Python/ceval.c line 3020

TARGET(STORE_GLOBAL): {```
spice pecan
#

how do you get it to show multiple lines again?

fallen slateBOT
#

Python/ceval.c lines 3020 to 3029

TARGET(STORE_GLOBAL): {
    PyObject *name = GETITEM(names, oparg);
    PyObject *v = POP();
    int err;
    err = PyDict_SetItem(GLOBALS(), name, v);
    Py_DECREF(v);
    if (err != 0)
        goto error;
    DISPATCH();
}```
spice pecan
#

Oh, I missed the second L

#

Thanks!

#

It directly mutates the dict

verbal escarp
#

so there's no way to delegate this behaviour at this point, ok

spice pecan
#

Reassigning __dict__ was the closest one, but still not enough

verbal escarp
#

at least it's possible for vars in "imported" modules

pliant tusk
#

is your goal to control what happens when globals().__setitem__ is called?

verbal escarp
#

as long as it involves an attribute access

spice pecan
#

There's one thing we didn't try yet

#

forbiddenfruit

verbal escarp
verbal escarp
spice pecan
#

Spoiler, didn't work

verbal escarp
#

aw

pliant tusk
#

!e ```py
from ctypes import *
obase = py_object.from_address(id(globals()) + 8)

class fglobals(dict):
slots = ()
def setitem(self, key, value, dict=dict):
try:
obase.value = dict
print('setting', key, 'to', value)
self[key] = value
finally:
obase.value = class

obase.value = fglobals
a = 1```

fallen slateBOT
#

@pliant tusk :white_check_mark: Your eval job has completed with return code 0.

setting a to 1
verbal escarp
#

oh god xD

spice pecan
#

ctypes wins again

pliant tusk
#

forbidden fruit wouldn't help because that changes behavior for all dictionarys

spice pecan
#

Let's see if I can remember how to make a recursive tuple

pliant tusk
#

so we cheat and change the type the dictionary that globals returns to a subclass that we control

verbal escarp
#

that's so crazy

pliant tusk
#

@spice pecan challenge, make a recursive tuple without ctypes

spice pecan
#

!e ```py
tup = [],
tup[0].append(tup)
print(tup)

fallen slateBOT
#

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

([(...)],)
pliant tusk
#

!e ```py
def gadget(n):
def f(*v):
nonlocal n
if v:
n = v[0]
else:
return n
return f

C = gadget.code
gadget.code = C.replace(
co_code=b'\x88' + C.co_code[1:]
)

x = (0,)
gadget(list.setitem)(tuple)
list.setitem((x, 1, 2, 3), 3, x)
gadget(list.setitem)(list)
print(x)```

fallen slateBOT
#

@pliant tusk :white_check_mark: Your eval job has completed with return code 0.

((...),)
spice pecan
#

Ok, that's smart

#

Defining a function to alter it's bytecode is a genuinely interesting move

pliant tusk
#

yea i got it down to one byte of alteration too

verbal escarp
#

damn

#

but i wouldn't rely on this trick for obvious reasons :p

#

i wouldn't have guessed it's possible though, at all to manipulate the code on this level

#

boon and bane of leaky internals, i guess?

pliant tusk
#

the above code actually abuses a bug to write an address to id(object) + 3 * 8

verbal escarp
#

what's that?

unkempt rock
#

hello

#

im new

#

and im 13 years old and intrested in coding

#

!e

#

i cant send my code

#

too bug

#

big

pliant tusk
#

!paste

fallen slateBOT
#

Pasting large amounts of code

If your code is too long to fit in a codeblock in discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.

verbal escarp
# unkempt rock hello

hi, if you're looking for help with your code, you could try to post it in one of the available help channels 🙂

unkempt rock
#

is this a good code

#

my first code veer

#

ever

#

im new so

verbal escarp
#

this channel is for discussing weird quirks and uses of the language itself

unkempt rock
#

i only know how to code trivias

#

whats help rice

#

and bagel

#

and falafel

verbal escarp
#

just a name of different channels

#

yeah, those are open

#

just click on one of them and start asking there

#

whichever suits your taste best 😉

verbal escarp
unkempt rock
#

i was bored

#

and thats why i did it

#

i normally dont comment lol

verbal escarp
#

comments are directed at people unfamiliar with your code - or you, in a year or so - that is, people who know how to code but don't know why you did what you did

#

your comments indicate that you grew bored of repeating your code - a good sign to start using loops and functions

#

and then.. finite state machines 🙂

#

it's the go-to concept of anything that relates to states - from flowcharts (conversation scripts) to buttons being clicked

#

FSMs are used extensively in GUIs, game scripts

unkempt rock
#

im on mac rn and it shows idle is open but i cant close it and i cant open it what do i do

surreal sun
#

Question — what exactly is mappingproxy?

flat gazelle
#

it's essentially a mapping not backed by a hash table, e.g. for classes with slots

novel vector
#

Crypto.Cipher is from pycrypto which is deprecated, yet pycryptodome seems to be using it, am I the only one to light up here a big WTF bulb?

paper echo
#

There is no enforcement that module names be unique across packages distributed on pypi

#

I think the "cryptography" library also uses those names

#

!pypi pycryptodome

fallen slateBOT
paper echo
#

!pypi cryptography

fallen slateBOT
#

cryptography is a package which provides cryptographic recipes and primitives to Python developers.

paper echo
#

Ah no, cryptography has a different API

novel vector
#

And if you do Crypto.__file__ on your pc you will see that Crypto is from pycrypto, and crypto is from pycryptodome I guess

#

C vs c difference

lusty scroll
#

could be boredom too, ig 😅

lusty scroll
#

in fact you can get the original (mutable) dict if you use a simple helper function to read 8 bytes into the mappingproxy object (with ctypes)

surreal sun
lusty scroll
surreal sun
#

Hm

lusty scroll
#
  • for 64-bit
#

for 32-bit its 8

surreal sun
#

If type is a mapping proxy wouldn’t that not work?

#

Oh wait Nvm

#

Class dictionaries are mapping proxies

lusty scroll
#

idk if mappingproxy has to contain a regular dict, but whatever it contains should be some kind of mapping-like thing (and the offset to it is fixed)

#

also taking advantage of the fact that id is the address of the object

#

lets see if the eval is on a 64-bit python

#

!e

import ctypes
mp = type.__dict__
print(mp)
realdict = ctypes.py_object.from_address(id(mp) + 16).value
print(realdict)
fallen slateBOT
#

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

001 | {'__repr__': <slot wrapper '__repr__' of 'type' objects>, '__call__': <slot wrapper '__call__' of 'type' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'type' objects>, '__setattr__': <slot wrapper '__setattr__' of 'type' objects>, '__delattr__': <slot wrapper '__delattr__' of 'type' objects>, '__init__': <slot wrapper '__init__' of 'type' objects>, '__new__': <built-in method __new__ of type object at 0x7fa5721aa980>, 'mro': <method 'mro' of 'type' objects>, '__subclasses__': <method '__subclasses__' of 'type' objects>, '__prepare__': <method '__prepare__' of 'type' objects>, '__instancecheck__': <method '__instancecheck__' of 'type' objects>, '__subclasscheck__': <method '__subclasscheck__' of 'type' objects>, '__dir__': <method '__dir__' of 'type' objects>, '__sizeof__': <method '__sizeof__' of 'type' objects>, '__basicsize__': <member '__basicsize__' of 'type' objects>, '__itemsize__': <member '__itemsize__' of 'type' objects>, '__flags__': <member '__flags
... (truncated - too long)

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

lusty scroll
#

weird, for me the first prints as
mappingproxy({ ... }) but not here?

spice pecan
#

It's the difference between str and repr

#

printing it skips the mappingproxy(...) wrapper

lusty scroll
#

ohhh makes sense

#

its not doing repr if you do print(x)

spice pecan
#

Yeah, print calls str instead

#

And the REPL uses repr for the last value

lusty scroll
#

!e

import ctypes
mp = type.__dict__
print(repr(mp)[0:128])
realdict = ctypes.py_object.from_address(id(mp) + 16).value
print(repr(realdict)[0:128])
fallen slateBOT
#

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

001 | mappingproxy({'__repr__': <slot wrapper '__repr__' of 'type' objects>, '__call__': <slot wrapper '__call__' of 'type' objects>, 
002 | {'__repr__': <slot wrapper '__repr__' of 'type' objects>, '__call__': <slot wrapper '__call__' of 'type' objects>, '__getattribu
silk pawn
fallen slateBOT
#

Objects/setobject.c line 177

return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);```
silk pawn
#

i know that dicts resize following a 2x rule, but i'm trying to figure out the rule for sets

fallen slateBOT
#

Objects/setobject.c line 577

if ((so->fill + other->used)*5 >= so->mask*3) {```
silk pawn
#

ok, did some getsizeof testing, and it seems that a set expands from 216 bytes to 728 bytes as soon as the 5th element is added (though 728 bytes may be including the size of the ints i added, i'm not sure about that), so i think it starts with allocating space for 4 objects

charred pilot
#

216 bytes?

silk pawn
#

yes

white nexus
silk pawn
#

nah

charred pilot
#

nah empty dicts are like 340

silk pawn
#

it used to be 232 bytes for an empty set a while back

static bluff
white nexus
#

horrific

static bluff
#

I'm still working on my best practices, hence my asking you guys to take a look

#

Can you elaborate?

white nexus
#

Ah, sorry, I didn't realise that what yours 😅

#

I'll take a closer look in that case

silk pawn
static bluff
#

"horrific" was a bit startling. I didn't think it could be that bad

silk pawn
#

ah yes, pep8 says 80, and black resizes to 88

#

i'd recommend going with 88 though

static bluff
#

I've taken a poll in the past, and there doesn't seem to be a consensus on the matter. Some people even use more than 100

silk pawn
#

however if using 88 adds a significant amount of lines, 100 isn't a bad choice

#

honestly, some of the projects i contribute to use 120, and it looks fine to me, but i also do very little coding on my phone

static bluff
#

"coding on my phone"

#

shudder

silk pawn
#

i only do it when my bot breaks and i dont have my computer on me

#

i see that you have some comments on the line they're describing, and some right before the line, and some right after

#

i believe best practice is to put all comments right before the line they describe

silk pawn
#

you use a lot of getattr without specifying a fallback value. for example in approveTransit (i'll get to using snake_case later). you can just use ``self.family, target.document`, etc

#

function names use camelCase, when they should be snake_case (at least in python). variable names shuld be snake_case too, only class names should be camelCase

#

other than that, just look into isort and try it out, and you should be set. your imports aren't horribly sorted/formatted, but it doesn't hurt to familiarize yourself with isort

static bluff
silk pawn
#

yeah, dom stuff

static bluff
#

Yeah, DOM stuff

silk pawn
#

in that case, i'd just use the style that the people most likely to be reading your code would use

#

if you're targeting it to be used by python users though, i'd use snake_case

static bluff
#

I'm targeting complete beginners to all languages primarily, and then JS users looking to build apps offline with a better language secondarily

#

And, and I might be totally off the mark here, but between a python programmer and a JS programmer its the JS programmer who needs the handicap

#

Nontheless, thanks so much for giving it a look! I'm happy to hear no major issues, apart from the obvious offensive disregard of some standards

#

And I do hear you with regard to the stylistic stuff. I'm walking a bit of a tightrope

#

Cause it's pretty :3

static bluff
#

@white nexus ping me if you like

white nexus
white nexus
#

@static bluff sorry, I shouldn't have called it horrific, that's disrespectful regardless of who wrote it 👀 I also heavily lint and style my code which makes me biased

static bluff
#

Well—for technical reasons—I have to go about things a bit differently and it can be blinding to a lot of python devs, especially experts

#

I don't take it personally

static bluff
white nexus
#

Ye, I actually understand a lot more from what you've explained now :P

elder blade
#

79 for docstrings and comments

#

With a goal and upper limit of 95, then error on 105 giving me the flexibility if there are long lines that would look worse over multiple lines

#

I rather have a higher length for linter error, than set it at 95 and have a bunch of noqa comments

silk pawn
silk pawn
white nexus
#

B950

unkempt rock
#

if you can help me dm me pls

unreal cave
#

ok am I crazy? I have a hand compiled python 3.9.5 install with a virtual environment, it's been working like a chaaarm for months now, but today I try to install numpy on a new system and it's freaking out about the wrong version of libc (wants 2.29, but 2,28 is installed) I tested this across several systems and experienced the same problem; however, it was working fine last weekend O_o

timid orbit
#

try installing an older version of numpy

#

or maybe you did a system update and forgot to reboot?

unreal cave
#

That's just it I did, same problem, I have several systems running on cloned images

#

to verify I did a pip freeze on the environment I setup last week (that is still working in place mind you)

#

so I created a new virtual environment, sources into it and installed the same version of numpy that is working in the origional

#

hard crashes on import stating a versioning problem with libc

verbal escarp
#

and sourcery really helps simplifying the code down to well known idioms

#

like turning "if foo == False" into "if not foo" etc

#

which also helps a lot when it comes to mental load and readability

#

i believe i just found a potential bug in your code @static bluff

#

clone = getattr(self, 'document').createElement(getattr(self, 'tagname'))

#

if self.document is None, it will throw an attribute error because None has no attribute createElement

#

L376

astral gazelle
#

Doesnt List[...] imply Iterable[...]

verbal escarp
#

i'd say so

astral gazelle
#

Ok im missing something then, thanks

verbal escarp
#

nobody would be crazy enough to remove the ability to iterate from a list, i don't think

#

maybe it needs to be a mutable iterable?

astral gazelle
#

Ok so the problem is im going from a union of a couple things to a union of fewer things i believe

verbal escarp
#

the whole typing should be boiled down to protocols methinks

astral gazelle
#

Im going from List[one | two | three] down to List[one | two], i think thats why i get an error

verbal escarp
#

that could be an issue, yeah

#

maybe you can reformulate one | two to include three implicitely

astral gazelle
#

Im not sure i can, theyre both different structures of tuples

verbal escarp
#

do you have to throw out three?

astral gazelle
#

Tuple[str,str,str], Tuple[str,str] and Tuple[str,int]
Its a config dict and i possibly need all of them or a combination

verbal escarp
#

ahh

astral gazelle
#

I guess i can generalise my target list

verbal escarp
#

heh

native flame
verbal escarp
#

("foo", "1") 😉

elder blade
astral gazelle
#

Im extending another list so i guess so? Not sure

astral gazelle
verbal escarp
native flame
verbal escarp
verbal escarp
native flame
#

||text||

verbal escarp
#

||uhh.. offtopic as spoiler, neat 😉 ||

verbal escarp
astral gazelle
#

Im parsing excel sheets, its
(heading, direction, alias)

verbal escarp
#

and why do you need (str, int), you could just handle (str, str) and convert the value to what you need.. ohh, god excel, no.. ahhh

astral gazelle
#

Hahahahaha

#

Yes sadly this is inherited and i dont wanna change a whole bunch

verbal escarp
#

excel as config?? omg

#

that's horrible

astral gazelle
#

I can figure it out some other time anyway, this isnt even on the list of problems with the codebase

verbal escarp
#

i can only imagine :p

#

if that is your config

#

you have my sympathy

#

@astral gazelle maybe you can use pandas for that job

#

it handles excel okay

#

although, you'd need to query numpy arrays instead of dicts..

#

shrug

astral gazelle
#

Already using openpyxl which is what pandas uses

#

Its okay i guess, but im trying to move to either json or literal python files with dict configs would be so much better

#

The problem is the users dont know python, but everyone knows excel

spice pecan
#

At least it's not word

lusty scroll
#

!e

from collections.abc import Iterable
print(f"{issubclass(list, Iterable)=}")
fallen slateBOT
#

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

issubclass(list, Iterable)=True
lusty scroll
#

ofc ABCs are all dirty, lying cheaters anyway

verbal escarp
#

if i had to design this, i'd have proposed a way to combine protocols

#

a list would be <iterable + mutable> or somesuch

gleaming rover
#

the approach I normally see goes something like Iterable -> Collection -> Ordered -> MutableOrdered -> List

#

i.e. the immutable-mutable split is last

spice pecan
#

I mean, isn't that literally the inheritance hierarchy?

#

Except for the fact that list isn't a subclass

#

Lists conform to the MutableSequence ABC, which inherits from Sequence, which inherits from Reversible and Collection, which inherits from Sized, Iterable and Container

gleaming rover
#

like "mutable" by itself

#

wouldn't fit as an interface/protocol/whatever IMO?

#

except as a marker

#

because the nature of mutation differs for each type of container

spice pecan
#

Yeah, containers just get another MutableX variant

verbal escarp
#

well, probably depends on the default

#

if we say immutable is the default

#

then mutable might be more meaningful

#

maybe mutable is a bad example

#

but my point is still valid

#

if we had a way to combine protocols, we wouldn't need to codify every single possible combination as an ABC

#

imagine ABCs as tokens that represent specific protocols and then have sets of those tokens to represent possible combinations

#

say, you need an ordered collection that's usable as a key (-> hashable)

#

but also mutable like a list

#

you could just combine ABC-"tokens" that represent those traits

#

{hashable, ordered, mutable}[int]

#

something like that

#

it's basically a promise that whatever thing is used, it has those traits

#

as a container for ints

#

doesn't look too shabby, does it?

spice pecan
#

Again, that's mostly the way it already is

#

The mutable thing is the only issue, because you can't really have that as a protocol, you never know if a method does or doesn't mutate the container

verbal escarp
#

that's nowhere near how it currently is

spice pecan
#

There are ABCs for hashable and ordered containers

verbal escarp
#

yeah, but how do you combine those promises?

spice pecan
#

By using them as mixins

#

By inheriting a protocol from them

verbal escarp
#

yeah, that's nowhere near what i'm proposing

spice pecan
#

I mean, so far the only difference is the ability to combine them without defining a named protocol

#

As well as difficult-to-define traits such as mutable

verbal escarp
#

not really difficult, no

#

the problem is that there is no defined unified protocol for mutability

spice pecan
#

Exactly, that's what makes it difficult

verbal escarp
#

but it's not difficult to define

spice pecan
#

Any method can potentially mutate the container, and there can be containers that are mutable, but don't implement __setitem__, for example

#

How would you define Mutable?

verbal escarp
#

i wouldn't, i'd regard it as a promise, delegatable to icontract and friends for testing

spice pecan
#

It's an interesting topic, I'd love to hear your ideas on it, since I don't really know how we could define a Mutable protocol either without it not being applicable to a valid mutable (albeit unconventional) container or directly inheriting from it

verbal escarp
#

maybe hypothesis can help

valid rose
#

(this may be on topic for here) is there a way to see how much memory a specific object is taking? in my case ```py
big_honking_dict = {...}
big_honking_dict.sizeof() # Always returns 216, irrespective of the size

 how do i know how much memory `big_honking_dict` is taking (in bytes btw)?
verbal escarp
#

go through all methods, pass in stand-in items as params and check if the items in the container were mutated

#

i can very well imagine that it could work as a automatic test

spice pecan
#

The reason it doesn't change is because it's not filled up enough to trigger a resize, try larger numbers

valid rose
#

let me try and get back

spice pecan
#

!e ```py
from sys import getsizeof
print(getsizeof(dict.fromkeys(range(10_000))))

fallen slateBOT
#

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

295000
valid rose
#

oooo nice

#

this is bytes right?

spice pecan
#

Yeah

valid rose
#

thanks @spice pecan 👍

spice pecan
#

Though that would be a curious solution to the problem

#

I feel like having an empty Mutable ABC that is an explicit base class for all mutable containers would be the most reliable solution, although that would require certain changes to built-ins and stdlib

valid rose
spice pecan
#

That's because you're using the same key over and over again

#

The resulting dictionary only contains one key-value pair

valid rose
#

yeah

#

i just realised how dumb that is

#

i apologize for my incompetence

verbal escarp
#

heh

spice pecan
#

fromkeys is a good way to quickly create a dict with a certain amount of keys

verbal escarp
#

why not just take the _ as key?

spice pecan
#

^

#

Although that would be identical behavior

valid rose
#

i basically want to know how much a dict with 10000 string-float key value pairs will take, which is what i was aiming for

valid rose
verbal escarp
#

the code you posted

spice pecan
#

The keys and values themselves aren't counted

valid rose
verbal escarp
#

you're throwing away the _ in the range

spice pecan
#

__sizeof__ only gives you the size of the container itself, because every object can have a different amount of references to it, and counting them as part of the container would be a bit incorrect

valid rose
#

perhaps for my use case i should just pickle.dump it and look at its file size

verbal escarp
#

you can just use that as key, you could convert it to str if you really want str-keys

valid rose
#

(since that was im going to be doing in the end)

#

sorry for the inconvenience, carry on 👍

spice pecan
#

Actually, nevermind, that would be more important for lists than dictionaries, since you can't have equivalent strings in a dict and floats are vastly more likely to be separate objects than to reference the same float

zenith flint
#

I've got 2 decorators, one of them being new_thread() which launches the function in a new thread, other being error_handler() which handles exceptions. In error_handler() I've got line_number = currentframe().f_back.f_lineno which gets the line number where the function was called.

If I run the below code with @new_thread() commented out, the error handler decorator prints Error handler ... line 14 ... which is correct. But if I run it in a new thread, it prints Error handler ... line 892 .... How could I get the accurate line number if a new thread is involved?

@new_thread()
@error_handler()
def test_func():
    x = 1/0
    return x

test_func()  # <- Looking for the line number of this, `currentframe().f_back.f_lineno` works if `@new_thread()` is not used
def new_thread():
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            t = threading.Thread(target=func, args=args, kwargs=kwargs)
            t.start()
            return t

        return wrapper
    return decorator
def error_handler(count=0, wait=0, log_exc=True, exc_info=True, capture_exc=True, print_exc=True, print_traceback=True, slack_exc=True, message=None):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            retries = 0
            while True:
                try:
                    return func(*args, **kwargs)

                except Exception as e:
                    retries += 1
                    func_name = func.__qualname__
                    line_number = currentframe().f_back.f_lineno
                    if message is None:
                        exc_message = f"{type(e).__name__}: {e}"
                    else:
                        exc_message = message
                    msg = f"Error handler ({func_name}, line {line_number}): {exc_message} ({retries}/{count if count != 0 else 'INFINITE'})"
                    print(msg)
                    ...
lusty scroll
#

we sort of have that with "virtual fake" multiple inheritance

#

i'd argue Sequence, Iterable et al should appear in the bases and mro for 'list'

#

we need to decide, is 'list' an implementation of these ABCs or isnt it

#

the whole thing is a big pile of leaky abstractions 😫

verbal escarp
#

well, as i said earlier about "mutable", i'm not sure if there is any point in trying to codify those abstractions, they only become meaningful if you regard them as promise or contract and be able to test against them

lusty scroll
#

is there a language that has the preferred semantics? one that doesnt rely on implementation inheritance ideally

verbal escarp
#

so, they can be as abstract as you like, really, as long as you can think of ways to test them

verbal escarp
#

yeah, and that

lusty scroll
#

well its cut off, but the point is that UserList is the only subclass of MutableSequence that's in any way close to list, and it has no subclasses

#

perhaps the abc registration thing (I think a register method is used to make issubclass/isinstance work with abcs) should somehow add to the list of subclasses?

#

!e

from collections.abc import *; from collections import *; [print(f"{cls.__name__} subclasses:\n\t{list(map(type.__dict__['__qualname__'].__get__, cls.__subclasses__()))}") for cls in (Collection, Sequence, MutableSequence, UserList, list)]
fallen slateBOT
#

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

001 | Collection subclasses:
002 | 	['Set', 'Mapping', 'ValuesView', 'Sequence']
003 | Sequence subclasses:
004 | 	['ByteString', 'MutableSequence', 'UserString']
005 | MutableSequence subclasses:
006 | 	['UserList']
007 | UserList subclasses:
008 | 	[]
009 | list subclasses:
010 | 	[]
lusty scroll
#

how should that be explained to a beginning python user who is just learning their ABCs...

#

there's room for improvement, we just need a couple more APIs

verbal escarp
lusty scroll
#

tbh why did we ever start doing the capitalized types thing

verbal escarp
#

because type annotations were supposed to be executable but the regular types would be incompatible to eval() in this context

#

i'm not going to say again that i find the idea stupid, but there i go

lusty scroll
#

they broke that then, because if I try to run, say, List[str] its an error, right?

#

at least unsatusfying :\

#

and we have the various ABCs clashing with the typing ones

#

the solution: metaclasses!

verbal escarp
#

reminds me of what is said about regex

#

"you think 'i have this problem, right - let's use regex!', now you have two problems"

lusty scroll
#

exactly

boreal umbra
#
class BowEstimator(BaseBowEstimator):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    @classmethod
    def from_config(cls, *args, **kwargs):
        return super().from_config(*args, **kwargs)

    @classmethod
    def from_saved(cls, *args, **kwargs):
        return super().from_saved(*args, **kwargs)

Is there any way in which this is different from just not implementing these methods?

verbal escarp
#

i don't see any

boreal umbra
#

I guess there's a chance that they're not class methods in the superclass?

verbal escarp
#

urgs

#

if so, it's all murky and bad

boreal umbra
#

they are class methods in the superclass, apparently. Thanks!

obtuse cape
#

Hello everyone i am new here

#

please i wanted to ask if anyone knows how to convert perl code to python? Thannk you

verbal escarp
#

perl code to python?

#

urgs

#

you could also execute perl in python

obtuse cape
#

Thank you

lusty scroll
#

i would look in the module probably

#

i dont know if factory functions in python are very common?

#

in a class i mean

boreal umbra
lusty scroll
#

yeah, a "static method"

flat gazelle
#

yeah, dict.fromkeys for example

lusty scroll
boreal umbra
verbal escarp
#

wdym

boreal umbra
#

a class method, often with a different signature than the __init__ method, that returns a new instance.

#

an advantage of this approach is that since it's a class method, any subclasses will return an instance of that subclass rather than the class in which the method is defined.

main lynx
#

often seen when homebrewing deserialization, e.g. from_json(...)

verbal escarp
#

can you give a minimal example how you use that?

boreal umbra
main lynx
#

!e

import json

class Thing:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar

    @classmethod
    def from_json(cls, data):
        parsed = json.loads(data)
        return cls(parsed["foo"], parsed["bar"])

t = Thing.from_json('{"foo": 1, "bar": 2}')
print(t.__dict__)
fallen slateBOT
#

@main lynx :white_check_mark: Your eval job has completed with return code 0.

{'foo': 1, 'bar': 2}
verbal escarp
#

hu.. curious 🙂

#

never seen that pattern before

boreal umbra
#

and it's nice and explicit

verbal escarp
#

it looks like a kind of dispatch pattern for init

boreal umbra
#

I dunno

#

I should go back to work but perhaps we can continue this lovely OOP discussion some time.

verbal escarp
#

sure

obtuse cape
#

Anyone knows any python script that generates the Arp table information using snmp?

lusty scroll
surreal sun
#

Hm, I'm still confused about import hooks

#

what is an example of one that simply just takes the file and changes i + 1 to i

obtuse cape
#

but thank you

lusty scroll
#

you could write some simple script with scapy, it has very simple function to make ARP requests and send them

#

or do you just want to read the arp cache

static bluff
#

Heya advanced ppl

#

Go one for ya

#

custom_array : MyIterableClass['SomeSpecificType'] = MyIterableClass()

#

Is this possible? I'm wanting to write an iterable class which can be hinted in this manner, but which does not inherit from list

native flame
#

inherit from typing.Generic[T]?

static bluff
#

I'm just reading about that now. I have noooooooo idea how any of that works

#

So I'll read up on that, happy to take any tidbits of wisdom though

native flame
#

think it's like

T = TypeVar("T")
class MyIterableClass(Generic[T]):
  def __iter__(self) -> Iterator[T]:
    ...
static bluff
#

What if I want to specify a specific class, instead of 'T' (just curious)

#

Generic[MyClass]?

native flame
#

i think so

static bluff
#

Weird that Iterable[MyClass] isn't the way. Seems logical

#

Another question — if I want to hold onto element's 'internally' to an object, as opposed to my attaching a list to it as an internal attribute and referencing that lists contents as if it were inside the outer object

#

That's not possible I'm guessing. The 'storage' of the stuff for a list happens in C, I'm guessing, and to get that I would have to inherit list?

trim dagger
#

driver.find_element_by_xpath('//*[@id="UserName"]').send_keys("ExampleUsername") # username

driver.find_element_by_xpath('//*[@id="Password"]').send_keys("ExamplePass") # password

#So this is part of my selenium code where the chromedriver will input the username and password, but I dont want to just
put the info on my bare script. So I need a way to encrypt this.

The problem I'm having is that I need to at the end of all this, turn my script into a .exe file and deploy it into another machine.
How will my local encryption hold over other machines?
What is the best approach here?

#

My goal is that I will have one .exe file at the end and if somehow people go into looking at the source code, the username and password will look encrypted.

static bluff
#

saved

#

Coooool

native flame
static bluff
#

😮

#

Awsome!

#

When did that happen?

native flame
#

yesterday

obtuse cape
lusty scroll
lusty scroll
delicate sage
#

Hmm i tought str(obj) checks directly if obj has a method called __str__ if it has that, it calls that otherwise, it calls the default one
but does it check differently?
because it is not checked via __getattribute__.

#

oh

#

oh i see

#

so str(obj) does something like

internal -> check if obj has __str__
yes? 
      python -> call it
no?
      internal -> call default

?

#

i see

#

i tot maybe using metaclass i can do it, but since it checks internally that also wont work right?

#

i see

prime estuary
#

For efficiency yes, magic methods have to actually be set on the type.

unkempt rock
prime estuary
#

Because the type object at the C level has a huge pile of function pointers corresponding to each magic method. To call the method, it just has to lookup the right pointer.

unkempt rock
#

Ah, cool

undone hare
#

It is __iadd__

#

Are you modifying the cpython source code? concern

raven ridge
#

__iadd__ is += - in-place add

lusty scroll
#

not something dynamic

delicate sage
#

oh

lusty scroll
undone hare
raven ridge
#

The r version is "reflected add"

raven ridge
#

As in, the expression is mirrored and evaluated in reverse

#

Though I suppose "right" works as a mnemonic for all the binary ones (all but __rpow__)

visual flower
#

hey

#

how do you use ren'py?

elder blade
#

__radd__ too slow I guess

static bluff
#

Just found out you can typehint self

#

Just, I mean, duhhhhh you can typehint self

#

Still, got me out of a tricky little issue 😄 😄 😄

olive marsh
#

What exactly is wheels in python?

flat gazelle
#

precompiled libraries more or less

olive marsh
#

Can you explain more? Why it is required n all?

flat gazelle
#

because say you have numpy. In order to install from source, you would need to compile all the C, C++, and fortran code it involves. This is a painfully slow process, so instead python has a system where it gets compiled once for your OS and CPU architecture and then the compiled version gets uploaded to pypi and when installing it, it uses that. The compiled package you can install is a wheel

static bluff
#

Why, in Gods name, is Github so complicated?

obtuse cape
static bluff
#

Why don't they have a simple, visual, drag and drop interface?

livid dove
#

because thats not how most of their customer base works

#

though if you use the visual editor you can do that iirc

#

(press . on any repo)

static bluff
#

I'm all for advanced usage by the command line

#

But there's no reason they can't make no code version

flat gazelle
#

because it exists to host git repositories, and their website is not the correct way to modify the uploaded code (maybe with workflows I could understand it). They do have a web editor, but it is not great and you shouldn't use it.

#

they do make a no code version: see github desktop

#

(no idea what state codespaces are in, but those would also work)

livid dove
flat gazelle
#

that's codespaces afaik

static bluff
#

In case you guys want to take a look

#

There's no comments, sadly. I'm trying to get better at commenting but I find it quite hard. Also, please note, I am aware that Python is supposed to use snake_case. My choice to use camelCase is intentional and I stand by it

#

Still a bit rough around the edges, but it'll do for the time being

verbal escarp
static bluff
#

Sorry, its private still aprrently

#

Lemme figure out how to make it public...

#

Try that

elder blade
#

Like it's so easy to check out PRs or if you need to only commit some lines of your changes

gleaming rover
verbal escarp
#

their merge conflict editor is horror

pliant tusk
#

is there any documentation for why in subscripted types (ie list[int]) if a one item tuple is passed in it gets flattened?

#

!e py print(list[int].__args__) print(list[(int,)].__args__)

fallen slateBOT
#

@pliant tusk :white_check_mark: Your eval job has completed with return code 0.

001 | (<class 'int'>,)
002 | (<class 'int'>,)
pliant tusk
#

this means that list[int, str] and list[(int, str)] are equivalent but they feel like they shouldn't be

gleaming rover
pliant tusk
#

if i implement a class with __class_getitem__, the args are not implicitly tupled

gleaming rover
fallen slateBOT
#

@gleaming rover :white_check_mark: Your eval job has completed with return code 0.

a
gleaming rover
#

oh

#

never mind I misunderstood yoru question

pliant tusk
#

yea it implicitly destructures passed in tuples

#

it would be like if d[1,] implicitly did d[1]

fallen slateBOT
#

Objects/genericaliasobject.c lines 583 to 586

static inline int
setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
    if (!PyTuple_Check(args)) {
        args = PyTuple_Pack(1, args);```
pliant tusk
#

i think this is the culprit, it only packs the tuple if the args aren't already a tuple

gleaming rover
#

so it is more the other way round

pliant tusk
#

which means after that line list[int,] and list[int] both have args set to (int,)

#

yea it only builds the tuple if one isn't passed in

lusty scroll
glacial tundra
#

Yoooo-

#

How does one do this-

visual shadow
#

!ot

fallen slateBOT
timber dragon
#

Why do I need to implement distutils.util.strtobool myself? 😦

verbal escarp
#

deprecation?

timber dragon
#

Yea, but point the reason why it wasn't moved to an another module or sth

verbal escarp
#

lazyness?

sacred yew
#

isnt that basically a 5 line function

#

dont really see the need for it anywhere in the stdlib

main lynx
#

what lib would it live in?

deep bramble
#

Why do people still use CPython if the PyPy implementation is so much faster? What's the actual benefit of CPython over PyPy, since I pretty much can't see any

main lynx
#

maybe string

peak spoke
#

It's not always much faster

deep bramble
# peak spoke It's not always much faster

from what I've tested so far, it usually was a lot faster, especially with lists, and I mean a lot faster, from a program that made ~20M calls for list.append and list.pop in pure python, vs in pypy, it was a huge performance difference

#

but even if it's not faster in every little aspect, for most things, it seems to be a lot faster so what are the actual reasons we're still using CPython by default?

peak spoke
#

The jit has to warm up so it's not suited for most small scripts, the c API is also much slower

verbal escarp
#

uhmmm

#

list.append and list.pop is NOT something you should use as a benchmark

deep bramble
verbal escarp
#

try it again with deque, which is specific for this purpose

peak spoke