#internals-and-peps

1 messages ยท Page 135 of 1

halcyon trail
#
getLogger(loggername).makeAddHandler(StreamHandler, format, level)
#

the main annoyance here to me is that you can't construct handlers, directly passing format, and level

#

but again, i have my own format that I like to use, codebase wide, so I end up with small helper functions for logging that add handlers using my format anyway, and things like that

#

so it makes very little difference in the end

paper echo
#

Maybe a third-party package will be a good way to explore this design space somewhat anyway

white nexus
#

I ended up adding both yaml and toml support to the configuration.

halcyon trail
#

yeah, maybe, it just faces the issue that IMHO it doesn't solve a big enough problem for people to want to use it. Using a package to save a dozen lines of very simple code, is eh

#

I feel that way even about loguru though

white nexus
#

I kinda wanna stop coding after writing what I wrote last night screams

#

Pre-commit hook which automatically generates example configuration files if I edit my configuration and its defaults

#

....To an .env file, a json file, a yaml file, and a toml file

#

Hmmmm, logging conversation both_eyes

#

pathlib and os.Path have entered the chat.

paper echo
#

oh, os.path.

#

eh. Pathlib is an entirely new interface

#

i'm more bothered by things like template strings (wtf why are these in the stdlib??), dictconfig and fileconfig, etc.

#

my burning desire to write from datetime import datetime as DateTime

flat gazelle
#

template strings exist so that you can safely pass arbitrary objects into user defined templates

white nexus
#

well, I made them so the end user would have a default base to build off of

paper echo
#

i was also being somewhat rhetorical though. they used to add all kinds of random stuff in the name of practicality / availability back when it was really difficult/annoying to install python packages

white nexus
#

what are template strings?

paper echo
#

and now they're being very (justifiably) cautious about adding new things

#

i still scratch my head at how pattern matching got accepted

sacred yew
#

in the string module

#

basically useless

paper echo
#

seems like hopping on the "we are typed now" trend

sacred yew
#

except in 1% of string formatting use cases

paper echo
# sacred yew basically useless

i wouldn't say it's useless, if i needed user-defined templates in an application i'd at least consider template strings instead of {}-formatting

white nexus
# paper echo that's actually an interesting idea. i'd personally do it with a makefile

here, if you want to see the pre-commit hook I wrote which exports to the four necessary files. https://github.com/discord-modmail/modmail/blob/cf906c007043c87ee70ee85beb00d099ced7cc0e/scripts/export_new_config_to_default_config.py

GitHub

A Modmail bot for Discord. Allowing safe moderator conversations with server members one server at a time. - modmail/export_new_config_to_default_config.py at cf906c007043c87ee70ee85beb00d099ced7cc...

paper echo
#

cool, ty

flat gazelle
#

pattern matching IMO makes sense. Sure it's kind of insane in terms of spec, but argument normalisation was far more error prone and hard to grasp without it

#

which is something you do for a lot of public API functions

paper echo
#

but how often are you pattern matching on types or protocols and destructuring individual attributes thereof?

white nexus
#

I now need to make the user interface which can modify a configuration option while online-- this is legit gonna be the hardest part, wish me luck

flat gazelle
#

overall, I do think extending the stdlib and language features is more of a good thing than a bad one

white nexus
#

seriously please wish me luck

paper echo
#

in my experience, it's more like this:

if isinstance(x, Thing1):
    x_clean = process_thing1(x)
elif isinstance(x, Thing2):
    x_clean = process_thing2(x)
else:
    x_clean = x
#

so sure,

match x:
    case Thing1():
        x_clean = process_thing1(x)
    case Thing2():
        x_clean = process_thing2(x)
    case _:   # argh why isn't this "else:"
        x_clean = x
flat gazelle
#

well, with patma you could have an api that would run the process thing when matched, though I am not sure if that is intended

wide shuttle
paper echo
paper echo
#

i know the main argument against else was "how far do you indent it?"

flat gazelle
#

I am still in support of object() as the wildcard match

white nexus
#

huh, I'll probably use template strings for this

paper echo
#

does that not work @flat gazelle ?

white nexus
#

syntax seems easier for an end user to put it TBH

flat gazelle
#

it does, but it should've been the official way

white nexus
#

eg "Hey, welcome to $server!" vs "Hey, welcome to {server}!"

paper echo
white nexus
#

actually, which of those seem easier? pithink

#

if you were an end user (who didn't know much python)

halcyon trail
#

I'll have to use pattern matching more in python to get a feel for it.
it does seem like a fair bit of complexity, and in the end most of the examples I've seen, it's basically just nicer if statements

wide shuttle
halcyon trail
#

In static languages it makes a lot more sense because it generally gets combined with smart casting

flat gazelle
#

@wide shuttlethat's what it already does is the thing

paper echo
#

@white nexus the $ doesn't clash with .format or % which is valuable, i think (the string needs to be specifically compiled before templating) and you can exercise greater control over the templating style

#

you probably don't want end-users to have control over float precision or space-padding

white nexus
#

lol

#

yeah

#

well

#

meh, the message is literally what displays to their users

flat gazelle
#

it is consistent in how it works in other cases, and object as the universal base type is well known, can be used multiple times in the same pattern without a new keyword

white nexus
#

so whatever they configure it as is what is shown.

paper echo
#

you can't split case over multiple lines too, right?

pseudo cradle
#

@wide shuttle Have you always been owner? If not, congrats! If so, don't mind me...

paper echo
#
match x:
    case (
        Thing()
        if foo(x)
    ):

you can't do this, right?

white nexus
paper echo
#

possibly is, i have no idea about the internals

white nexus
#

!d string.Template

fallen slateBOT
#

class string.Template(template)```
The constructor takes a single argument which is the template string.
pseudo cradle
#

Helpful documentation

paper echo
#

it just looks like re.escape is used to process the "delimiter"

#

it looks like it builds a regex for the placeholders and uses re.sub at templating run-time

white nexus
#

oh god no this configuration is gonna be a mess

#

just realised that I need to have a validator for every string input

#

WELL.

#

TBH str.format may work as well

#

what are some advantagese of the one syntax over the other?

paper echo
#

again i think the advantage of Template is more control for you, less control for the user

#

and depending on your application { might be more annoying than $ to have to escape

#

somewhat annoyingly there's no option to change the brace style, you have to override Template.pattern for that, which requires copying their somewhat ugly regex from the source code

peak spoke
#

I used it to do replaces where braces are valid syntax from the user, wouldn't want expose the escaping needed to be done in python to them. There's also the safe replace or what's it called

pseudo cradle
#

Gotta sanitize your inputs

paper echo
#

also annoyingly you can't easily drop in a regex instance instead of re because of how Template.__init_subclass_ is designed

white nexus
#

you can subclass Template

#

I once tried to use regex

#

was more complicated than re

paper echo
#

yes, but you have to override a lot of stuff to use pattern types other than the stdlib

white nexus
#

so I stopped

paper echo
#

is it? afaik it's a superset of re

#

the main reason i use it is for unicode character classes

white nexus
#

yeah

paper echo
#

which re doesn't support

white nexus
#

it is a superset

#

but it was more complicated ๐Ÿ˜…

pseudo cradle
#

Just double brain capacity and processing power, ez

fallen slateBOT
#
**PEP 638 - Syntactic Macros**
Status

Draft

Created

24-Sep-2020

Type

Standards Track

white nexus
#

one sec

pseudo cradle
#

I also have a questino

paper echo
#

absolutely hell fucking no to that syntax

pseudo cradle
#

We've had some great conversations in this channel about None propagation (setting up your projects to return None in certain cases, perhaps with invalid inputs/data or when analytics have a low level of confidence). I've been thinking, how would that look like in practice? IMO it would be handled at the decorator level and be one of two things:

  1. Check to see if the input is None. If that's the case, return None

or

  1. Try except and catch errors related to None and then return None.

or

  1. Both at once!

Which might be preferable?

#

Sorry for text wall

fallen slateBOT
#

modmail/addons/converters.py lines 17 to 28

LOCAL_REGEX: re.Pattern = re.compile(r"^\@local (?P<addon>[^@\s]+)$")
ZIP_REGEX: re.Pattern = re.compile(
    r"^(?:https?:\/\/)?(?P<url>(?P<domain>.*\..+?)\/(?P<path>.*\.zip)) (?P<addon>[^@\s]+)$"
)
REPO_REGEX: re.Pattern = re.compile(
    r"^(?:(?:https?:\/\/)?(?P<githost>github|gitlab)(?:\.com\/| )?)?"
    # github allows usernames from 1 to 39 characters, and projects of 1 to 100 characters
    # gitlab allows 255 characters in the username, and 255 max in a project path
    # see https://gitlab.com/gitlab-org/gitlab/-/issues/197976 for more details
    r"(?P<user>[a-zA-Z0-9][a-zA-Z0-9\-]{0,254})\/(?P<repo>[\w\-\.]{1,100}) "
    r"(?P<addon>[^@]+[^\s@])(?: \@(?P<reflike>[\w\.\-\S]*))?"
)```
paper echo
#

@unkempt rock i'd want something like this

defmacro foo(expr1, expr2):
    ...

where the arguments are all ast objects

white nexus
#

Yes, I had to switch feature branches to send this ๐Ÿ˜”

paper echo
#

no joke i would consider quitting python if that pep got accepted

pseudo cradle
#

That's hardcore

paper echo
#

standards track? jesus fuck

white nexus
#

Last year, Guido used the code name "Python 3000" to refer to a mythical future version that would be perfect but not necessarily backward-compatible. Since then, the Python team has realized that a quantum leap is not necessary. All desired changes can be implemented gradually using the new warnings framework and the future module to give users a transition period (see "What's New in Python 2.1" for more information).

pseudo cradle
white nexus
#

noooooooooo

pseudo cradle
#

Doesn't matter as long as they work, though

white nexus
paper echo
#

@unkempt rock am i reading this right? is this a compiler directive encoded as a comment?

# (func, _ast.STMT_MACRO, VERSION, ())
stmt_macro!:
    multi_statement_body
#

or is this just an example of how a statement macro might look when it's being used?

#

hold on, no. i think i misread this

pseudo cradle
paper echo
#
@macros.macro_processor(macros.STMT_MACRO, 1_08)
def switch(astnode):
    ...

this is fine

#

no idea what 1_08 means but whatever

wide shuttle
#

Just 108

paper echo
#

yeah, it's a version number

#

interesting

#

i'm still confused about this pep, how do you actually define a macro?

#

the reason i suggested something like defmacro is because the parser should be able to pick out the defmacro's, apply them to the rest of the file, and keep going

white nexus
#

this syntax

#

๐Ÿคฎ

#
do_nothing_marker!:
def foo(...):
  ...
#

this will completely fuck people up

#

since the current rule is the line below a line that ends with : must be indented

#

except if the line above ends with !:, then its okay

paper echo
#

yeah, that's bad too

wide shuttle
#

Hmm, it allows Python to scream at you.

try_!:
    body
finally!:
    closing
paper echo
#

@white nexus maybe the idea is that you can use it to implement decorator-like things? i am really not a fan though

wide shuttle
#

I'm mostly! not! used! to! seeing! so! many! exclamation! marks! at! the! end! of! names! in! my! code! (but that's a me-problem).

undone hare
paper echo
#

Hm

#

I missed that section

#

I'm also not sure what it's telling me

white nexus
#

counter point: macros won't be stable for many years to come

paper echo
#

I should clarify that my initial disgust was from when I thought macros were defined by a special comment

bronze sleet
#

what do you think about adding async in sqlalchemy (latest update)

white nexus
#

wtf?

#

why is this not working like it should

#

@paper echo ๐Ÿ˜ 

paper echo
#

wat

#

what did i break?

white nexus
#

I blame the person who introduced me to the libraries

#

but for some reason

#

marshmallow.EXCLUDE is not having any effect on my code anymore

paper echo
#

oh dear

white nexus
#

so when I do this

loaded_config_dict = ConfigurationSchema().load(data=loaded_config_dict, unknown=marshmallow.EXCLUDE)
#

marshmallow is raising a ValidationError since I have extra parameters

paper echo
white nexus
#

MWE?

paper echo
#

minimal working example

#

or in this case MRE, minimal reproducible example

#

basically a small self-contained program that reproduces the issue

white nexus
#

... that's gonna be hard but I'll try

#

its all contained in one file but I don't think I can get less than that

paper echo
#

well... i don't envy you ๐Ÿ˜‰ but one thing i've learned is, coming up with the MRE helps you find the bug 90% of the time

#

and if it doesn't, you basically start "bisecting" between your code and the MRE until you figure it out

white nexus
#

yeah....

surreal sun
#

The syntactic macros' syntax is confusing

#

It seems.. counter-intuitive to Python being a friendly language, in terms of how it looks

I think there should be a much nicer syntax as @paper echo pointed out

#

What is the best no op dunder method to use on an instance? That looks as close as the instance name as possible when accessing it but triggering something within the class

#

The closest one I could use were the unary operator ones, since they look as close to the class instance as normal

halcyon trail
#

i'd honestly be surprised if the macro stuff were accepted

#

but I've been wrong before

surreal sun
#

It likely won't

#

But it would be kind of cool ngl

paper echo
surreal sun
#

Ah

paper echo
#

it just defines its internal representation and its semantics

candid pelican
#

hey

from enum import Enum, auto
import uuid
import pygame

class Keys(Enum):
    ARROW_UP = auto()
    ARROW_DOWN = auto()
    ARROW_LEFT = auto()
    ARROW_RIGHT = auto()


class Player(object):
    """creates a player and their methods."""

    def __init__(self, name: str, x: int, y: int) -> None:
        self.id = str(uuid.uuid4())
        self._speed = 1
        self._data = {'name': name, 'x': x, 'y': y}

    @property
    def data(self) -> dict:
        return self._data

    @data.setter
    def data(self, value: dict):
        if not isinstance(self.data, dict):
            raise TypeError("data must be a dict.")

        self._data = value

    def key_pressed(self) -> Keys:
        """get the keys pressed by player."""
        KEYS = pygame.key.get_pressed()
        
        keys_list = [
            KEYS[pygame.K_UP],
            KEYS[pygame.K_DOWN],
            KEYS[pygame.K_LEFT],
            KEYS[pygame.K_RIGHT],
        ]
        
        ALLOWED_KEYS = [
            Keys.ARROW_UP,
            Keys.ARROW_DOWN,
            Keys.ARROW_LEFT,
            Keys.ARROW_RIGHT,
        ]

        if any(keys_list):
            return ALLOWED_KEYS[keys_list.index(True)]

i created this class Player as you can c but think that the method key_pressed is in the wrong place bc the class player should just have the player info... not the input layer i suppose that the method key_pressed should be a function... I wanna know what do you think abt it.

surreal sun
#

descriptors implement __get__, __set__, __delete__, and __set_name__ (I think I"m missing something)

#

.rp descriptors

verbal swift
#

hey can someone help me with this problem

paper echo
surreal sun
#

Has anyone ever looked at how CPython memory manages?

Is the allocation of memory just like:

how big is this object -> size class index -> corresponds to which pool to go to ->
if no pools available in the arena -> create a new pool -> once done, free the pool
if pools are available, just allocate the object to that pool

candid pelican
#

bc the game class have the method move_player that take 2 parameters the player object and the key pressed...

#

and moves the player...

surreal sun
#

Thank you! :D

uncut sage
white nexus
#

yum

#

attr.fields(config().default.bot.__class__)[1].metadata[METADATA_TABLE].description

wise locust
#

hey

thorn grove
#

Anyone know anything about Pythons AI uses in the medical field ?

eager trail
#

modelling community spread of infections? modelling high dimensional data in the medical field, etc

astral gazelle
#

There was this kaggle competition i looked through a while ago that had people use a series of MRIs of patients heads to determine if they had glaucoma
The winner used python, so theres that

cobalt agate
white nexus
#

Hmm, what are some of yallz favorite libraries?

hybrid pagoda
#

Hi can I ask some questions

#

?

#

so my question is simple ig

#

What services students need ??

What services do common people need in everyday life??

PLS ANSWER THESE QUESTIONS

white nexus
#

!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.

hybrid pagoda
#

This is not H.W

white nexus
#

well

hybrid pagoda
#

or exam

white nexus
#

!rule 7

fallen slateBOT
#

7. Keep discussions relevant to the channel topic. Each channel's description tells you the topic.

white nexus
#

this channel is about python itself.

hybrid pagoda
#

ye

#

ohh

white nexus
#

!ot you would likely have better luck in

fallen slateBOT
hybrid pagoda
#

u know coding?

#

btw do u know how to make a face recog program using python ?

white nexus
# white nexus Hmm, what are some of yallz favorite libraries?

Meta Libraries

poetry for project management.
poetry is a project manager, like pipenv or pdm. Poetry also replaces setup.py, which is awesome.
Extremely good at what it does, but IMO tries to do too much.

twine for uploading builds to pypi
While poetry has support for this, given how only one shot is allowed for a push to pypi, I use twine. I do not want poetry breaking on this, since I use the alpha builds.

pipx used for installing python tools globally
the tldr: pipx is a wrapper for pip and venv, Long form: pipx makes venvs, installs tools, and adds them to path. Very very simple idea, flawless execution. I highly recommend this as a way to install any command line tool from pypi.

taskipy used for tasks.
This program is excellent. Allows defining tasks in pyproject.toml, so the same boring command can be ran just with task command This also enables repeatability, and saved keystrokes ๐Ÿ˜„

TOML
atoml for toml file parsing.
Style-preserving toml reader and writer. This is a fork of tomlkit, which is used in poetry. If not needing to preserve user style, could use tomli and tomli_w.

HTTP Libraries
aiohttp, httpx, httpie
These are not all comparable, but are worth listing together since they all perform the same action. However, there's some mighty big differences between the 3.

aiohttp is an asyncronous http library-- with websocket support. If websockets are needed, aiohttp is my goto library.

httpx is a drop-in replacement for requests. Its supposed to fix a lot of the problems with requests (do not quote me on this), but also adds many new functions for more features. In addition, it has an asyncrounous engine as well. However, it does not support websockets.

httpie is a library which is kind of an outsider on this list.
This is a replace for curl, and should be installed to a global venv, perhaps with pipx. Its pretty cool, haven't played with it too much tho.

Python style tools
black - the best formatter. #black-formatter for more info
flake8 - linter. TLDR its a combination of multiple other linting libraries.

GIT Related
Aight, this is a fun category, and I have an extra guest for it too. ๐Ÿ™‚
pre-commit runs before commits, catch errors in advance. Extremely easy to write your own hooks, too.

dulwich a complete python implementation of git. Yes, you read that correctly.
I'm not sure what the intended use case is, since if there's an existing git repository, git is already installed, but given that it can clone repositories, its actually incredibly useful.

Testing
pytest The best testing framework for python. Ofc, it means nothing if you don't write tests.

coverage.py (coverage) this is the way to get coverage for python.
Its best used with testing, and lets you know what code ran and didn't run with the tests. Please note: coverage is not the best way to write tests, and should only be an indicator that something ran. Whether it was actually tested or not, that is up to the tests.

I think that wraps up my favorite libraries, I'm interested in anyone else's favorite go-to libraries too ๐Ÿ˜›

#

... I think I was bored. No, I do not have a blog because if I did I would have posted this there.

undone hare
#

You should get a blog haha

white nexus
#

meh

surreal sun
# white nexus ***__Meta Libraries__*** **poetry** for project management. poetry is a project...

discord.py
Easy to use, and itโ€™s the library Iโ€™ve used while doing my open source contributions mainly.

asyncio
I know this is stdlib but I still really love it - even though Iโ€™m incompetent at it, it is still very powerful regardless, and very useful for I/O, which is what I do commonly.

dis
YASL (Yet another standard library), though it has changed my general recent use of Python, and greatly helps me with when Iโ€™m messing with bytecode and has even helped me learn it partly.

inspect
This is a bit more descriptive when inspecting source code and what not, and is useful for also messing around

candid pelican
#

why the function print makes my code slow??

unkempt rock
#

Does anyone has any idea on Marketing Mix Modelling?

hexed spire
paper echo
paper echo
#

Taskipy looks interesting for systems that don't easily have access to GNU Make

#

I know people have used Tox for that in the past

#

I used to use Snakemake which i have grown to dislike

undone hare
naive adder
#

you probably want sys.stdout.write but print provides more function tho

#

maybe sys.stdout.write is faster

undone hare
#

it will most probably have really similar speeds

naive adder
#

oh

elder blade
#

If anything it could be slower

#

Python needs to lookup sys, then stdout and then write.

naive adder
#

wait is the file param set to sys.stdout by default in print

#

!d print

fallen slateBOT
#

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)```
Print *objects* to the text stream *file*, separated by *sep* and followed by *end*. *sep*, *end*, *file*, and *flush*, if present, must be given as keyword arguments.

All non-keyword arguments are converted to strings like [`str()`](https://docs.python.org/3.10/library/stdtypes.html#str "str") does and written to the stream, separated by *sep* and followed by *end*. Both *sep* and *end* must be strings; they can also be `None`, which means to use the default values. If no *objects* are given, [`print()`](https://docs.python.org/3.10/library/functions.html#print "print") will just write *end*.

The *file* argument must be an object with a `write(string)` method; if it is not present or `None`, [`sys.stdout`](https://docs.python.org/3.10/library/sys.html#sys.stdout "sys.stdout") will be used. Since printed arguments are converted to text strings, [`print()`](https://docs.python.org/3.10/library/functions.html#print "print") cannot be used with binary mode file objects. For these, use `file.write(...)` instead.
naive adder
#

uhh

paper echo
#

Isn't print by default basically sys.stdout.write followed by sys.stdout.flush?

#

Do the printing in a separate thread ๐Ÿ˜›

peak spoke
#

It doesn't flush by default, the "only" thing it offers is the convenience of being a builtin and how it accepts and formats its args

silk pawn
fallen slateBOT
#

Objects/floatobject.c line 926

double_round(double x, int ndigits) {```
amber walrus
#

How do I typehint an int with the radix?
Something like value: int(base=16)

spice pecan
#

An int is an int, the base only really matters in its string representation

#

How would you expect that typehint to behave?

amber walrus
spice pecan
#

So you want to take a string that represents a base-16 int?

amber walrus
#

Yeah

#

Like a color string atm

#

#000000 or 0x000000

#

for example

spice pecan
#

You could use typing.Annotated or a custom alias for str

#

Since that is what you're actually passing

amber walrus
#

OK thanks

paper echo
paper echo
# amber walrus #000000 or 0x000000

unfortunately you can't do this currently in python. it would be very cool if we had a mypy plugin that could check if a string matched a certain pattern, but even then it would only work on either string literals or with a TypeGuard (3.10)

#

!pep 647

fallen slateBOT
#
**PEP 647 - User-Defined Type Guards**
Status

Accepted

Python-Version

3.10

Created

07-Oct-2020

Type

Standards Track

paper echo
#

i'm not sure how those will integrate (if at all) with Annotated

amber walrus
paper echo
#

yeah, for now you have to specify it as a runtime constraint

woeful sinew
#

Hello

peak spoke
#

while not enforceable beyond the type, a type alias goes a long way

paper echo
#

let me try with Literal

#

actually i'm not even sure how that'd work

wicked pumice
#

A frog wants to maximize their probability of reaching 1 on a number line from 0.00000001 after 100 turns. Each turn they can choose a number f between 0 and 1 and have 0.55 chance of multiplying their position by 1+f and a 0.45 chance of multiplying their position by 1-f.

#

This is pretty hard

#

You have to create an algorithm to maximize the chances of you reaching 1

#

on the number line

#

really interesting but hard

sacred yew
#

that sounds like a math problem

#

@wicked pumice

wicked pumice
#

it is

#

but no one is answering :((

sacred yew
#

doesn't mean you can post it in an unrelated channel

candid pelican
#

how can i host my tcp server using the socket library???

#

using my pc

main lynx
#

there's examples in the socket lib docs iirc

paper echo
#

has there ever been a serious proposal for destructuring mappings with =?

{'x': x, **_} = {'x': 1, 'y': 2}
radiant fulcrum
#

that looks

#

incredibly esoteric

#

I understand it's idea being similar to foo, *_ = [1, 2, 3] but Idk

gleaming rover
#

requiring **_ for parity with ordered container destructuring makes sense

white nexus
#

I'd put it on pypi, but there's not really much here that could go on pypi so I'll just link to it but tldr I made a configuration system which will export defaults to a toml file, yaml file, and a .env file:)

#

And uh, maybe I'll make a blog blobcatanimeeyes

paper echo
paper echo
spring sedge
#

lst = ['Beans','Toast','Eggs','Bacon']
print("List before adding newline character to it:",lst)
lst = '\n'.join(lst)
print("List after adding newline character to it:\n",lst)
=Output

gleaming rover
spring sedge
#

is that advanced enough

spring sedge
#

it works

#

makes a list

gleaming rover
spring sedge
#

oogh

#

my bad

gleaming rover
#

np

spring sedge
#

Have fun

gleaming rover
#

!e {1: 1}[1] = 1

fallen slateBOT
#

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

[No output]
gleaming rover
#

๐Ÿ˜”

#

I guess it would be ambiguous

lusty scroll
#

is there a reason no function would appear to have anything in __annotations__ ? and typing.get_type_hints() always returns {} (python 3.9)

lusty scroll
#

false alarm, the annotations are there, there's just much less stdlib coverage than I expected

main lynx
#

seems like typeshed covers much of stdlib?

#

then again stdlib has a lot of generics

#

..or does it?

lusty scroll
# main lynx ..or does it?

i'm not sure, is typeshed something i can use in combination with stdlib, like if i have a reference to the function?

#

is it possible to type check a recursive type hint?

peak spoke
#

depends on the checker

#

typeshed provides stub files for the stdlib and some other packages, I don't think it's really accessible at runtime

unkempt rock
sand goblet
#
from timeit import timeit

def f1(x=list(range(10000))):
    x.reverse()

def g1(x=list(range(10000))):
    for i in range(5000):
        temp = x[i]
        x[i] = x[-1 - i]
        x[-1 - i] = temp

def f2(x=list(range(10000))):
    return sum(x)

def g2(x=list(range(10000))):
    total = 0
    for n in x:
        total += n
    return total

print(timeit(stmt=f1, number=1000))
print(timeit(stmt=g1, number=1000))
print("- " * 20)
print(timeit(stmt=f2, number=1000))
print(timeit(stmt=g2, number=1000))```
Why is the time difference between list.reverse and doing it in python so much larger than sum and doing it in python? sum is only about 5 times as fast, but list.reverse is about 800 times as fast
#

I was thinking sum is still kind of slow because it needs to look up the value of the number in RAM, and it canโ€™t put it in cache memory. list.reverse only needs to move around the whole python objects, so it doesnโ€™t need to look things up in RAM as much

#

But it seems like neither would it need to when doing it in python

sand python
#

it's the power of compiler optimizations

lusty scroll
#

what about reversed()?

sand python
#

a function in c that does the work of reverse or sum will be optimized into very efficient machine code

sand goblet
#

But sum isnโ€™t that fast, while list.reverse is very fast

#

Hundreds of times as fast

sand python
#

as for why sum is so much slower, it would take more looking into it

lusty scroll
#

i would expect interpretation to be some order of magnitude slower, but not sure how much

sand python
#

it's possible that the optimization gains from using c code simply aren't as heavy

lusty scroll
#

IIRC bytecodes in python aren't really optimized at all too

sand goblet
#

Whatโ€™s the bytecode telling the computer to do that makes it so much slower?

sand python
#

bytecode has to be translated into machine code

#

look at the disassembly of f1 and g1 for example

#

!e ```py
import dis

def f1(x=list(range(10000))):
x.reverse()

def g1(x=list(range(10000))):
for i in range(5000):
temp = x[i]
x[i] = x[-1 - i]
x[-1 - i] = temp

print("f1:")
dis.dis(f1)
print("g1:")
dis.dis(g1)

fallen slateBOT
#

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

001 | f1:
002 |   4           0 LOAD_FAST                0 (x)
003 |               2 LOAD_METHOD              0 (reverse)
004 |               4 CALL_METHOD              0
005 |               6 POP_TOP
006 |               8 LOAD_CONST               0 (None)
007 |              10 RETURN_VALUE
008 | g1:
009 |   7           0 LOAD_GLOBAL              0 (range)
010 |               2 LOAD_CONST               1 (5000)
011 |               4 CALL_FUNCTION            1
... (truncated - too many lines)

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

sand python
#

f1 is 6 op codes total

#

g1 is like 25, and like 20 of them are being looped through, so you end up with more like 100,000 op-codes executed total

#

each one needs to be executed separately by the python interpreter

#

that's a lot of overhead

sand goblet
#

So

lusty scroll
#

one by one, through a big switch statement, internal functions called, etc

sand goblet
#

It canโ€™t pre-load the instructions, or something?

#

It has to complete one, stop and load the next, complete that one, stop and load the next, etc?

sand python
#

cpython, as far as I'm aware, doesn't do that

#

pypy has a JIT compiler which is supposed to do some of that

lusty scroll
#

a jit might

sand goblet
#

Why canโ€™t it?

lusty scroll
#

people have tried

surreal sun
sand python
#

it can, pypy is one implementation of python that tries and does to some extent

#

cpython is unlikely to have it though

sand goblet
#

Why canโ€™t it load the instructions the bytecode will tell it to do before it gets to it?

surreal sun
#

^
There was a core dev talk that Python Disc hosted last year, and one of the questions was regarding a JIT coming to CPython, the core dev said it was highly unlikely as it would bea big undertaking

surreal sun
lusty scroll
#

yeah, they have side effects

sand goblet
#

Why canโ€™t it do it?

lusty scroll
#

it might have to jump for example

sand goblet
#

Like for if-elif-else?

#

Or while?

surreal sun
#

Yep, POP_JUMP_IF_FALSE

#

i.e. if statements

#

and the likes

#

!d POP_JUMP_IF_FALSE

fallen slateBOT
#

POP_JUMP_IF_FALSE(target)```
If TOS is false, sets the bytecode counter to *target*. TOS is popped.

New in version 3.1.
surreal sun
#

Ah, alright, so it is if statements i think for sure

sand goblet
#

Canโ€™t it just stop and clear out the wrong branch it guessed and load the correct branch, like CPUs do with machine code?

sand python
#

that is way lower level stuff

#

and it is done, all cpus do it

#

even when running python

sand goblet
#

So itโ€™s just a bunch of overhead piling up that makes it so slow?

sand python
#

I should make it clear that all the op-codes are preloaded into memory, if that's what you're asking about. That isn't where the overhead is coming from, it's literally the translation of bytecode into machine code that is slow

#

every python op-code has some c code associated with it which has to executed

#

literally a giant switch statement that says if the opcode is this, do that

#

for every opcode

surreal sun
sand python
#

dynamic typing is one of the things that make python hard to optimize or jit

#

you can't make assumptions about the object you're working on

lusty scroll
#

also it's running mainly having to read/write from the heap to get the objects I believe, which is a lot slower than registers, which C functions could use to manipulate values

sand goblet
#

So list.reverse vs reversing in python, is python slower because the computer ends up needing to carry out hundreds of times more instructions? Or is it slower because somewhere along the way, the computer still needs to access stuff from RAM on each iteration, even though itโ€™s still just moving around whole python objects?

sand python
#

a combination of both, although I think the amount of instructions that need to be executed would be the primary reason

sand goblet
#

sum isnโ€™t very fast even though itโ€™s compiled, Iโ€™ve assumed thatโ€™s because it still needs to access each of the numeric values through pointers

#

But list.reverse doesnโ€™t have that problem

sand python
#

yeah, it's likely because of that derefencing

#

a python list is contiguous memory filled with pointers to python objects, so reversing that is very simple, no dereferencing needed

#

summing requires dereferencing, and there is no guarantee that the integers will be in contiguous memory

surreal sun
#

also, might be also because sum has to look for the object's __add__ every time,

#

!e

class Test:
  def __add__(self, other):
    return 2

  def __radd__(self, other):
    return self.__add__(other)

print(sum([Test(), Test(), Test()]))
fallen slateBOT
#

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

2
sand goblet
#

So then hashing is involved too

#

To look that up

white nexus
#

hmmmmmmmmmmmm

#

ye, hashing is fun

#

trying to figure out the best way to store thes variables but I am not sure how I'll be accessing them. lol

#

ah, got it

#

pseudo-nested dictionary

bronze narwhal
#

Can someone tell me why can't I run this code?

fallen slateBOT
#

Hey @bronze narwhal!

Uh-oh! It looks like your message got zapped by our spam filter. We currently don't allow .txt attachments, so here are some tips to help you travel safely:

โ€ข If you attempted to send a message longer than 2000 characters, try shortening your message to fit within the character limit or use a pasting service (see below)

โ€ข If you tried to show someone your code, you can use codeblocks
(run !code-blocks in #bot-commands for more information) or use a pasting service like:

https://paste.pythondiscord.com

bronze narwhal
#

Can someone tell me why is this code not running?

naive adder
#

it's a json? so i don't think it'll do anything unless you interact with it

#

and perhaps this is the wrong channel to ask lol

bronze narwhal
naive adder
#

o

bronze narwhal
#

No idea why it didn't work.

naive adder
bronze narwhal
#

Well what do you mean lol.

#

Are you not sure what that code is written in?

raven ridge
naive adder
# bronze narwhal

oh this is an ipython notebook, you need ipython to open it i think

bronze narwhal
#

.-.

#

Ah.

#

Wait how do I open on Jupyter @warm kernel

#

I've never used it before. CS_Shrug

#

Opening jup takes me to this browser.

#

Sure.

paper echo
#

How do we get pattern matching but not the damn Z

white nexus
#

(/j ofc)

#

oh god

#

that post, does enrage me

#

how can you support a format without supporting the full format??

#

this is like a json parser that fails parsing strings

gleaming rover
#

I got that before

#

I thought it was a bug in JS

#

being a loyal Pythonista

#

TURNS OUT...

white nexus
#

hmmmm

#

what are the true differences between os and sys? why are there two libs if most commonly, both are used?

peak spoke
#

sys interacts with the interpreter, not os

paper echo
white nexus
#

wtf

#

why would you be resistant to that

paper echo
#

There were some specific reasons offered, including "it's asymmetrical with isoformat" and "we need a better interface for this anyway"

#

Neither of which are good reasons imo

#

It seems like a pretty obvious concession to practicality to me, but there's a reason these people are core maintainers and i am not

peak spoke
#

I understand not doing it as it's easily replaceable by the user and not wanting to implement a full parser which would be complicated or outline what exactly it can parse, but then it's also a common pitfall

paper echo
#

If it was already in python, would anyone be asking for its removal?

#

That's how i felt about my logging proposal too and why i was surprised to get pushback on it

white nexus
paper echo
#

If it magically appeared in the language tomorrow, and nobody said "why is this here, it doesn't belong here", I think that's a good candidate for inclusion

#

Note: there are many things already in the stdlib that fail the "why is this here" test

#
white nexus
#

basically i wanna ask myself that question

peak spoke
#

From what it looks like to me the the main issue with things like adding the Z is deciding on what exactly to include and the discussions around it, like the question if it should be expanded beyond just the Z and in exactly what way

paper echo
fallen slateBOT
#
**PEP 594 - Removing dead batteries from the standard library**
Status

Draft

Created

20-May-2019

Type

Standards Track

paper echo
#

The discussion is about Z in 2021, not about the ideal datetime parsing interface in 2023

peak spoke
#

I think generally the idea is to get if expanding its scope more is worth it if changes are already getting introduced (in this case Z alone may not be seen as worth it) but that leads to stalemates like this

white nexus
#

!d fileinput

fallen slateBOT
#

Source code: Lib/fileinput.py

This module implements a helper class and functions to quickly write a loop over standard input or a list of files. If you just want to read or write one file see open().

The typical use is:

import fileinput
for line in fileinput.input(encoding="utf-8"):
    process(line)
```  This iterates over the lines of all files listed in `sys.argv[1:]`, defaulting to `sys.stdin` if the list is empty. If a filename is `'-'`, it is also replaced by `sys.stdin` and the optional arguments *mode* and *openhook* are ignored. To specify an alternative list of filenames, pass it as the first argument to [`input()`](https://docs.python.org/3.10/library/fileinput.html#fileinput.input "fileinput.input"). A single file name is also allowed.
white nexus
#

this is extremely useless

#

pathlib, os, read, etc, for loops, not that hard to just... iterate all of the files yourself

paper echo
# white nexus pathlib, os, read, etc, for loops, not that hard to just... iterate all of the f...
white nexus
white nexus
#

idc if a third party library has a function to load from a file, but the json library which is already extremely slow? ๐Ÿ˜”

pulsar crow
#

Can anyone tell me, why the signature of the __get__-method ( __get__(self, obj, type): got obj as well as the objects type type? One could simply use the type-function on obj to determine the value if needed

paper echo
#

Roll this functionality into argparse

white nexus
#

as it is handy for quick scripts.

paper echo
#

Make a top level function to handle -

white nexus
#

oh yeah, I've never used argparse

#

i figure if I'm ever gonna make a cli I'll use click

paper echo
white nexus
#

but I suppose if I need a quick arg pass, maybe I'll just use argparse next time

#

but if I'm making something I intend to be public, I'll probably use click

#

idk really

#

afk

pulsar crow
#

someone probably knows a cornercase

#

or this was needed back then and noone wanted to break stuff later

#

Ok there already is an explanation

white nexus
#

๐Ÿ˜”

#

is there a way to implement this?

#

Easily*

#

I could make a method which would recursively check

peak spoke
#

attrgetter?

white nexus
#

wdym

peak spoke
#
In [9]: a=attrgetter("config.user.bot.prefix")

In [10]: from types import SimpleNamespace as sn

In [11]: bot=sn(config=sn(user=sn(bot=sn(prefix=0))))

In [12]: a(bot)
Out[12]: 0
paper echo
lusty scroll
white nexus
#

!d functools.reduce

fallen slateBOT
#

functools.reduce(function, iterable[, initializer])```
Apply *function* of two arguments cumulatively to the items of *iterable*, from left to right, so as to reduce the iterable to a single value. For example, `reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])` calculates `((((1+2)+3)+4)+5)`. The left argument, *x*, is the accumulated value and the right argument, *y*, is the update value from the *iterable*. If the optional *initializer* is present, it is placed before the items of the iterable in the calculation, and serves as a default when the iterable is empty. If *initializer* is not given and *iterable* contains only one item, the first item is returned.

Roughly equivalent to:
lusty scroll
#
>>> functools.reduce(getattr, "config.user.bot.prefix".split("."), bot)
0
#

or

from types import SimpleNamespace as sn
bot=sn(config=sn(user=sn(bot=sn(prefix=0))))
import __main__

functools.reduce(getattr, "bot.config.user.bot.prefix".split("."), __main__)
0
#

though operator.attrgetter is a bit cleaner

elder blade
#

For example when it is used on a class, that's when you get the type

#

I would be more interested in learning about why __exit__ gets the error type and error (I don't think there's a case where you get one without the other).

lusty scroll
#

is it the exception type and value? like what you get from sys.exc_info() - which also has the traceback

#

so you can reraise the error like

raise exc_type, exc_value, None
lusty scroll
verbal escarp
lusty scroll
verbal escarp
#

i love reduce :p

peak spoke
#

Not sure if I'd be more inclined towards the attrgetter or reduce here, I guess both will be the same as it'd be abstracted away in a clearer func

verbal escarp
#

still wonder if operator.truediv would work there

lusty scroll
#
>>> class T:
...   class Attr:
...     def __get__(att,obj,type):
...       print(att,obj,type)
...       return 7
...   a = Attr()
...   b = Attr()
...
>>> T.a
<__main__.T.Attr object at 0x7ff715dd60> None <class '__main__.T'>
7
>>> T.b
<__main__.T.Attr object at 0x7ff715dd90> None <class '__main__.T'>
7
>>>
>>> T().a
<__main__.T.Attr object at 0x7ff715dd60> <__main__.T object at 0x7ff715d6a0> <class '__main__.T'>
7
>>> T().b
<__main__.T.Attr object at 0x7ff715dd90> <__main__.T object at 0x7ff715d7f0> <class '__main__.T'>
7
#

^ it looks better if the Attr has a nice repr that includes the name, obviously

#
>>> T().a
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized

And that's why you have to be careful with __repr__ ...

verbal escarp
#

wtf..

lusty scroll
#

!e

class Num:
  class MultAttr:
    def __init__(self, name):
      self.name = name
    def __get__(att,obj,type):
      print(att, obj, type)
      return obj._data * (1 + ord(att.name) - ord("a"))
    def __repr__(self):
      return f"<Attr {self.name}>"
  
  def __init__(self, d):
    self._data = d
  def __repr__(self):
    return f"<Num '{self._data}'>"
  
  a = MultAttr("a")
  b = MultAttr("b")


t1 = Num(1)
t2 = Num(10)

t1.a
t1.b
t2.a
t2.b
fallen slateBOT
#

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

001 | <Attr a> <Num '1'> <class '__main__.Num'>
002 | <Attr b> <Num '1'> <class '__main__.Num'>
003 | <Attr a> <Num '10'> <class '__main__.Num'>
004 | <Attr b> <Num '10'> <class '__main__.Num'>
verbal escarp
#

how do i get a reference to the function that called a function from inside? inspect stack only gives me a str..

#

and

#
import inspect

def get_keyword_param_names(locs):
    func = globals()[inspect.stack()[1].function]
    print(func, type(func))
    return {name:locs[name] for name, param in inspect.signature(func).parameters.items()
        if (
            param.kind is inspect.Parameter.KEYWORD_ONLY 
            or param.kind is inspect.Parameter.VAR_KEYWORD
        )}

def foo(*, a, b, **kwargs):
    return get_keyword_param_names(locals())
s = foo(a=2, b=3)
print(s)
#

looks brittle

peak spoke
#

you can use the frame's globals but I don't think there's any better option

#

You could also parse the params yourself from the code object the frame is executing, I think it has everything you need for that

surreal sun
verbal escarp
#

ty

surreal sun
#

Np

peak spoke
#

would have to look into how inspect does it

surreal sun
#

Let me find the source code for inspect

peak spoke
#

probably through pos indices that are exposed through other co_ attrs in co_varnames and some co_flags

surreal sun
zenith flint
#

What are some great third-party tools/APIs that should be used be in production? I'm thinking like Sentry for error logging, Grafana for monitoring, etc.

verbal escarp
zenith flint
#

I'm looking for a list of the common ones that should be used in every project (like Sentry and Grafana)

lusty scroll
#

looking at this code in typeshed, it seems invalid. array.array[Any] gives you a TypeError that subscript can't be applied to type() objects:

ReadableBuffer = Union[bytes, bytearray, memoryview, array.array[Any], mmap.mmap]  # stable
WriteableBuffer = Union[bytearray, memoryview, array.array[Any], mmap.mmap]  # stable
#

shouldn't that be a type annotation, not an assignment?

peak spoke
#

It's probably a type alias used over the stub module

#

There were some other cases like that with invalid generics but I guess typecheckers understand them and it doesn't matter that it's not valid python as it's never ran

lusty scroll
#

but I guess it's meanmt for the big players (mypy, IDEs) that can already locate imports and infer types of things by parsing

peak spoke
#

I recall os.PathLike also having that "issue" but it looks like it got the syntax in 3.9

lusty scroll
#

is there a reason the stdlib can't use inline type hints?

peak spoke
#

And well it is at least syntactically valid so you could leverage some parts like the parser, just not actually runnable

#

majority of it is in C that's not distributed with the install

lusty scroll
#

ahh

peak spoke
#

For python modules I think they just don't want to introduce them into the files because of the potential maintenance and runtime cost when an alternative solution available

lusty scroll
#

i see, well, it would be nicw if there was a package to grok the stubs for you

#

it seems crazy to parse two ASTs and try to match them up

#

is there another way it could work?

#

i would have preferred if they went with a declaritibe syntax

boreal umbra
#

The current signature for sum is sum(iterable, /, start=0), but I wish it was sum(*values, *, start=0). Same with math.prod.

lusty scroll
#

like

module = sys
[functions]
sys.breakpointhook = (*args: Any, **kwargs: Any) -> Any
sys.getsizeof = (obj: object, default: int) -> int
peak spoke
lusty scroll
#

guess it's a historic/compatibility thing

#

since we didn't have kw-only args when they designed it (I think?)

white nexus
#

!d operator.attrgetter is there not a setter counterpart?

fallen slateBOT
#

operator.attrgetter(attr)``````py

operator.attrgetter(*attrs)```
Return a callable object that fetches *attr* from its operand. If more than one attribute is requested, returns a tuple of attributes. The attribute names can also contain dots. For example:

โ€ข After `f = attrgetter('name')`, the call `f(b)` returns `b.name`.

โ€ข After `f = attrgetter('name', 'date')`, the call `f(b)` returns `(b.name, b.date)`.

โ€ข After `f = attrgetter('name.first', 'name.last')`, the call `f(b)` returns `(b.name.first, b.name.last)`.

Equivalent to:
lusty scroll
#
setter = operator.attrgetter("first.second.third.__setattr__")
setter(thing)(val)

might work?

#

nah, that would not work, would it

boreal umbra
lusty scroll
#
>>> setter = functools.partialmethod(functools.partial(operator.attrgetter("config.user.bot.__setattr__")(bot)), 79)._make_unbound_method()
>>> setter("age")
>>> bot.config.user.bot.age
79
#

works but quite hideous

lusty scroll
#

python 1.6 maybe.. I think that's the oldest available

#

wonder if anyone was able to run it, certainly not me

lusty scroll
#

is there a decent python parser that actually shows the source in its repr?

#

like returns the string of source code

#

ast doesn't or i would use that

sand goblet
raven ridge
#

I don't think it checks that it's an int. I think it always looks up the function to call at that memory offset. For types defined in Python, I think the function at that memory offset does a lookup of the __add__ dunder and makes a Python call to it. For types defined in C, the function at that memory offset can just do the work.

#

At least, I'm pretty sure that's how it works, @sand goblet

sand goblet
#

Then does it need use hashing ever when you use operators? Or does it just reserve a specific memory location for the dunder methods?

#

And if you define it in python, then the function it looks up in C just looks up that memory location?

#

Or it canโ€™t do that and still needs to use hashing for python defined classes?

crimson tangle
#

I am trying to host a discord bot on replit and then monitor it on uptimerobot for it to be 24x7 online.

I am getting a 404 error when I monitor the HTTPS link. The problem is not resolved.

Things I did to troubleshoot

  1. Made sure the link is correct.
  2. Made sure the code works fine (it does, and it works perfectly when I run it from my browser)
  3. Made sure settings on replit monitor are correct as well.

Any help would be greatly appreciated.

paper echo
#

You could wrap the parse and dump functions into a class with the right repr

peak spoke
lusty scroll
#

i want to see what i am working with in the REPL without calling str() constantly

#

if I could override the repr function in one place that might be ok, but i don't know how i could set that up

#

since there'.s a bunch of different node classes

flat gazelle
#

I would assume there would be an ipython hook you could use to create a custom repr for ast nodes

lusty scroll
#

that's an interesting idea, I know there's sys.displayhook for the regular repl shell

surreal sun
white nexus
#

Can post it shortly, but basically it uses operator.attrgetter :)

white nexus
#
        get_value = operator.attrgetter(option.rsplit(".", -1)[0])
        setattr(get_value(self.bot.config.user), option.rsplit(".", -1)[-1], value)
quasi hound
#

how can i turn this off

#

so damn annoying

surreal sun
#

Is there a way to convert something to the type of bytes you'd see in function.__code__.co_code?
Like bytecode represented with bytes in python itself

I want to convert a string into those bytes

elder blade
#

Don't you use the AST module for that?

white nexus
quasi hound
#

no i just like hitting control R control R when debugging

#

don't wanna have to keep exiting

#

i close them all when i'm done

#

my record is in the 50s

#

that's how many processes i had open once

#

i was testing a bot for hours

white nexus
#

that restarts a debugging process in vscode

surreal sun
white nexus
#

but you can rebind the keybind & also pls use #editors-ides for vscode discussion

quasi hound
#

ty

surreal sun
#

So, for some reason, I now have a code object at the <module> level, and I want to get the code object wihtin it

#

because there's the function I want within that code object

#

how do I get the nested code obj

raven ridge
#

That is, no matter what, it calls the type's nb_add slot at a known, fixed offset from the start of the type object in memory. For built in types, that function does the work. For classes defined in Python, that function looks up the appropriate dunder (or dunders) and calls them, which requires a lookup (or lookups) against the type's class dict

fallen slateBOT
#

Objects/typeobject.c line 8202

/* Common code for update_slots_callback() and fixup_slot_dispatchers().```
surreal sun
#

inspired from plusplus, I decided to try my own way to edit something dynamically

#
@patch_code("(x := x + 1)", "++x")
def hello_world(param):
    x = param
    if ++x == 2:
        print("It's 2!")
    else:
        print(x)

hello_world(2)
>>> 4
#

replaces ++x with (x := x + 1)

sand goblet
stuck valley
#

In what cases can all of the various argument combinations occur with __import__?

pulsar lotus
#

hey are you still open to helping people figure out smart contracts and python

upbeat oracle
#

anyone have any experience working with MTP/pymtp; accessing file directory of device/phone mounted on your PC? the library pymtp library doesnt seem to be working
getting the following error:

   >>> TypeError: LoadLibrary() argument 1 must be str, not None
white nexus
#

....

#

this idea is cursed

#

but basically I need to split a string on all capitalized letters

peak spoke
#

re.split

white nexus
#

this feels like a horrible idea

#

I should just hardcode the values

#

!d re.split

fallen slateBOT
#

re.split(pattern, string, maxsplit=0, flags=0)```
Split *string* by the occurrences of *pattern*. If capturing parentheses are used in *pattern*, then the text of all groups in the pattern are also returned as part of the resulting list. If *maxsplit* is nonzero, at most *maxsplit* splits occur, and the remainder of the string is returned as the final element of the list.

```py
>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']
white nexus
#

hmmmm

#

HowCouldIConvertThis to How could i convert this?

#

!e ```py
import re
print(re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9])\s(\s*):',r'static PyObject*\npy_\1(void)\n{','def myfunc():'))

fallen slateBOT
#

@white nexus :white_check_mark: Your eval job has completed with return code 0.

001 | static PyObject*
002 | py_myfunc(void)
003 | {
white nexus
#

how in the world does this work

#

like this ๐Ÿ‘€

#

!e ```py
import re
print(re.sub(r"([A-Z])", r" \1", "HowCouldIConvertThis"))

fallen slateBOT
#

@white nexus :white_check_mark: Your eval job has completed with return code 0.

 How Could I Convert This
undone hare
white nexus
#

because previously I thought it was extremely complicated ๐Ÿ˜…

#

& then sent the answer because finding questions with no answers is extremely annoying ยฏ_(ใƒ„)_/ยฏ

undone hare
#

Well, even if it is a complex question, it should go in a help channel. This channel is for discussions around the language itself.

#

Questions that messes around with the Python internals are probably fine too

wise comet
#

hi hi does anyone here know how to rewrite tensorflow v1 keywords to v2

undone hare
wise comet
#

sure thanks

verbal escarp
#

.oO(iron man looking for help, that's a first)

lusty scroll
#

is it considered normal for python to create (and set tracebacks for) 184 exceptions during interactive startup?

#

could be slowing things down, or at least using a lot of memory holding onto so many FrameType objects?

livid mason
#

I have a doubt. Why doesnt python have anonymous functions like javascript?

builder.queryType({ fields: (t) => ({ hello: t.string({ args: { name: t.arg.string(), }, resolve: (parent, { name }) => `hello, ${name || 'World'}`, }), }), }); 

I know there's lambda, but it's not multi line. Are there any better options?

#

Pls ping me when help, thanks!

gleaming rover
#

is an anonymous function

#

by definition

#

but yeah they kinda suck in Python

surreal sun
elder blade
peak spoke
#

; is invalid in a lambda as it's a part of the statement syntax

#

that's a meaningless statement unless you're planning on writing unmaintainable code

#

Python doesn't and most probably won't have more freedom with lambdas so you're forced to use normal functions, that's it

verbal escarp
#

i think it was one of the misconceptions regarding lambda that restricting it to a single statement would somehow make it safer, but just like with eval, you can break out of it and do whatever you like

#

i've seen horrifying exploits involving generators etc that would work around the limitation

peak spoke
#

sure, but you won't see that in any real application that has reasonable maintainers

#

But ; is just invalid as it's used for chaining statements which can't exist in a lambda in the first place

verbal escarp
#

yeah

#

problem is that the restriction doesn't matter from any reasonable standpoint

#

if it's about security, you can work around it and if it's about clean code - the workaround is even messier

peak spoke
#

I don't think multi statements lambdas would really fit in syntax wise

verbal escarp
#

i do

#

there's a couple of scenarios where you need a function that is called exactly once in the code, so naming it doesn't make much sense in many cases

#

so, you're stuck with a def _(): which is even worse on many levels

sand goblet
#

Why doesnโ€™t list have certain methods that other objects do, like set.discard or str.replace or str.translate? And will they ever add those? Or do they not want to add any other methods?

flat gazelle
#

discard is del l[i:i+1], replace and translate probably just aren't useful enough to be added. You could probably get a list method added if it were needed, there is definitely a usecase for .get when traversing json.

sand goblet
#

What about list.remove, but an error doesnโ€™t happen if it canโ€™t find the value?

flat gazelle
#

that one could make some semblance of sense, but even then it is trivial to just make as a helper

visual shadow
#

i think it's primarily because you could keep coming up with "potentially useful" methods, and you just have to stop somewhere.

flat gazelle
#

yeah, as of right now there are enough things in list IMO. If you really need complexity, there is always numpy

fallen slateBOT
#
**PEP 594 - Removing dead batteries from the standard library**
Status

Draft

Created

20-May-2019

Type

Standards Track

white nexus
verbal escarp
#

no need for another method

#

the replacement method for strings suck, it should take a dict

sand goblet
sacred yew
#

idk how multiline lambdas relates in any way to security

sand goblet
#

And I guess str.translate too

verbal escarp
sand goblet
#

Oh wait, yeah

#

Duh

sand goblet
#

It replaces any pattern that matches, not specific substrings

verbal escarp
#

which could be said isn't pythonic either, so no point there

#

the "illusive trait" that mostly corresponds to "being pythonic" is probably "executable pseudo-code"

#

but nobody writes "lambda" in pseudo-code, so not even a point there

#

Lambda calculus (also written as ฮป-calculus) is a formal system in mathematical logic for expressing computation based on function abstraction and application using variable binding and substitution. It is a universal model of computation that can be used to simulate any Turing machine. It was introduced by the mathematician Alonzo Church in the...

#

the syntax used in lambda calculus itself is (x,y) ->

surreal sun
#

I always thought of Pythonic as using the most understandable approach to something, for example, using datetime.strptime to convert a YYYY-MM-DD string to a datetime object, rather than parsing it yourself

verbal escarp
#

so if the idea was to base the whole thing on the idea of lambda calculus, then he should've taken the syntax as defined there and not make up a keyword nobody outside of math or CS would understand (and even then only barely)

surreal sun
#

I would honestly like anon as the keyword instead, or anonymous

#

Ofc a soft keyword

#

for an anonymous function

verbal escarp
#

would make more sense to anyone coming from outside of those fields, yes

surreal sun
#

But thatโ€™s just me ig

verbal escarp
#

but imo it doesn't need a keyword

sand goblet
surreal sun
#

I would agree with that but then beginners would be confused (the str.replace)

verbal escarp
sand goblet
#

What would it be called? str.sub?

#

Like re.sub?

verbal escarp
#

that's a lovely notion

sand goblet
#

I feel like thatโ€™s probably how people use re.sub a lot of the time, as a substring replacer

#

When theyโ€™re replacing more than just individual characters

verbal escarp
#

on the other hand, lambdas are everywhere in GUIs or networking as callbacks, but almost non-existent in scripts (which was probably the reason why GvR was shocked when people protested when he suggested to remove lambdas in general)

#

it's actually kind of ironic

#

the people (artists, GUI-designers etc) who need it the most are those who don't have the background to understand it at a glance

sacred yew
#

(\x -> x + 1)
though how a "\" looks like a "ฮป" is a mystery

charred pilot
verbal escarp
#

the buffet table pattern i came up mostly is as elegant as it is thanks to the lambdas, but it's severely limited - for instance, i can't easily insert logging statements etc. before the function-chain is called

#

as a reminder:

#
        case_func = {
            (False, False, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
            (False, False, False, True): _pebkac_no_version_no_hash,
            (False, False, True, False): _import_public_no_install,
            (False, True, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
            (True, False, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
            (False, False, True, True): lambda **kwargs: _auto_install(_import_public_no_install, **kwargs),
            (False, True, True, False): _import_public_no_install,
            (True, True, False, False): lambda **kwargs: ImportError(Message.cant_import(name)),
            (True, False, False, True): _pebkac_version_no_hash,
            (True, False, True, False): lambda **kwargs: _ensure_version(_import_public_no_install, **kwargs),
            (False, True, False, True): _pebkac_no_version_hash,
            (False, True, True, True): lambda **kwargs: _pebkac_no_version_hash(_import_public_no_install, **kwargs),
            (True, False, True, True): lambda **kwargs: _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **kwargs), **kwargs),
            (True, True, False, True): _auto_install,
            (True, True, True, False): lambda **kwargs: _ensure_version(_import_public_no_install, **kwargs),
            (True, True, True, True): lambda **kwargs: _auto_install(_ensure_version(_import_public_no_install, **kwargs), **kwargs),
        }[case]
        result = case_func(**locals())
#

that's how it looks like

white nexus
verbal escarp
#

it is!

#

case = (bool(version), bool(hashes), bool(spec), bool(auto_install))

white nexus
#

I really feel like a data class or enum or something would be more readable

verbal escarp
#

it covers all combinations of those four

#

it's not data

white nexus
#

What's a truth table?

verbal escarp
#

it's a flattened decision tree, basically

#

~200 lines of if/elif code in one table ๐Ÿ™‚

#

yup

#

instead of a large if/elif tree, there's a single check for each var and a lookup in the table for the combination

languid yoke
verbal escarp
#

it's a different mechanic though

languid yoke
verbal escarp
#

pattern matching works with if/elif basically, a table doesn't

#

but out of curiousity, how would you implement that buffet table as a case/match?

gleaming rover
#

do you think arbitrary-width integers by default, as in Python, are a good design choice?

verbal escarp
#

i do. makes prototyping much easier if you don't have to care about those details at first

languid yoke
# verbal escarp but out of curiousity, how would you implement that buffet table as a case/match...

Probably something like```py
match case:
case (_, _, False, False):
result = ImportError(Message.cant_import(name))
case (True, _, True, False):
result = _ensure_version(_import_public_no_install, **locals())
case (False, _, True, False):
result = _import_public_no_install(**locals())
case (False, False, False, True):
result = _pebkac_no_version_no_hash(**locals())
case (False, False, True, True):
result = _auto_install(_import_public_no_install, **locals())
case (True, False, False, True):
result = _pebkac_version_no_hash(**locals())
case (False, True, False, True):
result = _pebkac_no_version_hash(**locals())
case (False, True, True, True):
result = _pebkac_no_version_hash(_import_public_no_install, **locals())
case (True, False, True, True):
result = _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **locals()), **locals())
case (True, True, False, True):
result = _auto_install(**locals())
case (True, True, True, True):
result = _auto_install(_ensure_version(_import_public_no_install, **locals()), **locals())

gleaming rover
#

๐Ÿ˜ข

languid yoke
verbal escarp
languid yoke
#

It's just as ugly, but much clearer.

verbal escarp
#

i don't think so

#

the code between the cases makes it harder to quickly check for a specific combination

languid yoke
#

An alternative where everything lines up:```py
match case:
case (_, _, 0, 0):
result = ImportError(Message.cant_import(name))
case (1, _, 1, 0):
result = _ensure_version(_import_public_no_install, **locals())
case (0, _, 1, 0):
result = _import_public_no_install(**locals())
case (0, 0, 0, 1):
result = _pebkac_no_version_no_hash(**locals())
case (0, 0, 1, 1):
result = _auto_install(_import_public_no_install, **locals())
case (1, 0, 0, 1):
result = _pebkac_version_no_hash(**locals())
case (0, 1, 0, 1):
result = _pebkac_no_version_hash(**locals())
case (0, 1, 1, 1):
result = _pebkac_no_version_hash(_import_public_no_install, **locals())
case (1, 0, 1, 1):
result = _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **locals()), **locals())
case (1, 1, 0, 1):
result = _auto_install(**locals())
case (1, 1, 1, 1):
result = _auto_install(_ensure_version(_import_public_no_install, **locals()), **locals())

verbal escarp
#

heh

#

there's a nice boon for match/case though

#

it gets rid of the lambdas

#

on the other hand, the result = is a bit more verbose

languid yoke
verbal escarp
#

yeah, you've got a point

languid yoke
#

It could get extracted into its own function with a return instead of a result =, and each case could be on a single line.

verbal escarp
#

i'll consider moving to match/case when we drop the older python versions

languid yoke
#
def choose_thing(case, **kwargs):
    match case:
        case (_, _, 0, 0): return ImportError(Message.cant_import(name))
        case (1, _, 1, 0): return _ensure_version(_import_public_no_install, **kwargs)
        case (0, _, 1, 0): return _import_public_no_install(**kwargs)
        case (0, 0, 0, 1): return _pebkac_no_version_no_hash(**kwargs)
        case (0, 0, 1, 1): return _auto_install(_import_public_no_install, **kwargs)
        case (1, 0, 0, 1): return _pebkac_version_no_hash(**kwargs)
        case (0, 1, 0, 1): return _pebkac_no_version_hash(**kwargs)
        case (0, 1, 1, 1): return _pebkac_no_version_hash(_import_public_no_install, **kwargs)
        case (1, 0, 1, 1): return _pebkac_version_no_hash(_ensure_version(_import_public_no_install, **kwargs), **kwargs)
        case (1, 1, 0, 1): return _auto_install(**kwargs)
        case (1, 1, 1, 1): return _auto_install(_ensure_version(_import_public_no_install, **kwargs), **kwargs)
verbal escarp
#

ah!

languid yoke
#

Discord highlighting is grating me a little.

verbal escarp
#

yeah, that's not too bad, although choose_thing would be an ideal case for a lambda ๐Ÿ˜‰

#

as an actual anonymous function

languid yoke
#

That would mean going back to the dictionary and lambdas, because match isn't an expression.

verbal escarp
#

nah, i mean if we had actual lambdas

#

not the pseudo lambdas we currently have ๐Ÿ˜‰

languid yoke
#

This would look a little cleaner in Rust.

#

Match expressions, no case keyword and blocks of code in lambdas.

#

That's what I'm internally comparing Python to.

verbal escarp
#

not a bad thing to compare to

#

thanks for the idea

languid yoke
#

Anything to help stop lambdas from creeping in everywhere.

verbal escarp
#

hrhr

sand goblet
white nexus
real prairie
#

heyo

#

where should I go to talk about good practices and the pythonic way?

#

i'm wondering what's the proper way to catch a specific excapction according to y'all

rapid rover
#
"""
1. Create a pyqt window
2. Set the application layout as a grid layout
3. Create 3 tabs each with one button
3. Button 1, exits the application
4. Button 2, prints "Hello world" to console
5. Button 3, opens a new window.
"""

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QTabWidget

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 Tab Widget")
        self.setGeometry(350,150,600,600)
        self.UI()

    def UI(self):
        vbox = QVBoxLayout()
        tabWidget = QTabWidget()

        button1 = QPushButton("Exit")
        button1.clicked.connect(self.exitWindow)
        tabWidget.addTab(button1, "Tab 1")

        button2 = QPushButton("Print to console")
        button2.clicked.connect(self.printToConsole)
        tabWidget.addTab(button2, "Tab 2")

        button3 = QPushButton("New Window")
        button3.clicked.connect(self.newWindow)
        tabWidget.addTab(button3, "Tab 3")

        vbox.addWidget(tabWidget)
        self.setLayout(vbox)
        self.show()

    def exitWindow(self):
        self.close()

    def printToConsole(self):
        print("Hello World")

    def newWindow(self):
        self.nw = NewWindow()

class NewWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("New Window")
        self.setGeometry(350,150,600,600)
        self.UI()

    def UI(self):
        self.show()

def main():
    App = QApplication(sys.argv)
    window = Window()
    sys.exit(App.exec_())

if __name__ == '__main__':
    main()

This was generated by OpenAi's GPT-3 Codex.

#

I am in awe

real prairie
#

holly

rapid rover
#

With such specific instructions too

#

it did as was requested pretty much to a T

real prairie
#

how does the grid layout look? Sensible values for the parameters?

rapid rover
#

it looks like this

#

lmao

#

pretty good for an ai though

#

The buttons do what they are supposed to do as well

#

also thought this was pretty cool (also generated with GPT-3):

"""
1. Create a function called SendEmail
2. The function will take message, to, from, password and subject parameters.
3. Send email message
"""

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def SendEmail(message, to, from_, password, subject):
    msg = MIMEMultipart()
    msg['From'] = from_
    msg['To'] = to
    msg['Subject'] = subject
    msg.attach(MIMEText(message, 'plain'))
    server = smtplib.SMTP('smtp.gmail.com: 587')
    server.starttls()
    server.login(from_, password)
    text = msg.as_string()
    server.sendmail(from_, to, text)
    server.quit()

SendEmail("Hello", "to@gmail.com", "from@gmail.com", "password", "Subject")
real prairie
#

that's nuts

rapid rover
#

I agree

eager trail
#

wait, that's autogenerated?

rapid rover
#
"""
1. Create a function called SendEmail
2. The function will take message, to, from, password and subject parameters.
3. Send email message
"""

These were the instructions I gave it.

verbal escarp
verbal escarp
# rapid rover Yes, it is.

yeah, copilot is quite impressive at first glance, but i'd be very careful about generating such long code

#

you need to understand the code yourself 100% and make sure it doesn't mess up the details (which happens quite a bit)

#

it also tries to be helpful in generating comments, but it messes up majorly

#

like when you try simple maths like # 23923 * 34983 = it would put an arbitrary number in, which feels like "there, i know the solution, just believe me" although it's completely wrong

#

another instance was when i had a complex algorithm and copilot suggested a - on first glance legit - stackoverflow url

#

but when i clicked the url, it was obvious copilot had taken a valid but completely wrong url, chopped off the str after the post id and put a string there that appeared to be related to the code i was working on

#

it completely lied to me

#

i dread the day newbies use copilot to build their stuff and then whine about how "the AI takes their jobs away", then use a tool like that and whine about how "you still need to know how to program, boo!"

languid yoke
#

If you start with buggy code, copilot will intentionally* write more buggy code, because that's what it expects would come next.

  • Shorthand, although it's not easy to prove it does things intentionally.
verbal escarp
verbal escarp
#

and more often than not copilot produces crap like


    @__call__.register(None, str, str, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool,)
#

:p

gleaming rover
#

I have a newfound respect for language designers

#

this parsing thing is hard

elder blade
gleaming rover
#

a lot of them look like that

elder blade
#

Ah yeah

verbal escarp
#

no, that snippet is a function i decorated with singledispatch

#

and copilot added the whole idiotic bool rest without a hint of intelligence :p

#

"artificial intelligence" my ass

elder blade
#

That actually reminds me, there should be a way to decorate with an instance's methods.

class Test:
    def __init__(self, callback):
        self.callback = callback
        self.intelligense = -1

    def intelligence(...):
        ...

@.intelligence(2)
@Test
def dummy():
    ...

# So that it becomes
def dummy():
    ...

dummy = Test(dummy)
dummy = dummy.intelligence(5)
#

I've had some use-cases but resorted to helper functions that basically make that required call.

flat gazelle
#

@elder bladehow about operator.methodcaller

elder blade
#

Interesting, yeah that could actually work

verbal escarp
#

grml.. why can't i use singledispatch to dispatch on None ๐Ÿ˜

spice pecan
#

Have you tried NoneType?

#

Since None is used as a shorthand for its own type in type hints

#

It's available in types IIRC, and ig you could also use type(None)

verbal escarp
#

yeah, i worked around it with type(None)

#

annoying nevertheless

#

the error message was also not really helpful, just saying "can't take None"

spice pecan
#

Actually

#

None seemed to work for me

verbal escarp
#

ahh, then i'm to blame myself

#

i wrapped the wrapper to implement a method-singledispatch

spice pecan
#

Oh

#

Is it different from singledispatchmethod?

verbal escarp
#
def methdispatch(func) -> Callable:
    dispatcher = singledispatch(func)

    def wrapper(*args, **kw):
        # so we can dispatch on None
        if len(args) == 1:
            args.append(None)
        return dispatcher.dispatch(args[1].__class__)(*args, **kw)

    wrapper.register = dispatcher.register
    update_wrapper(wrapper, func)
    return wrapper
#

yeah, i missed .__class__

#

that's probably cause of the glitch

spice pecan
#

Seems so

#

Actually, AFAIR *args is a tuple

fallen slateBOT
#

:incoming_envelope: :ok_hand: applied mute to @cursive stone until <t:1632490787:f> (9 minutes and 59 seconds) (reason: discord_emojis rule: sent 22 emojis in 10s).

verbal escarp
#

i wished there was a proper method-singledispatch..

spice pecan
#

!d functools.singledispatchmethod

fallen slateBOT
#

class functools.singledispatchmethod(func)```
Transform a method into a [single-dispatch](https://docs.python.org/3.10/glossary.html#term-single-dispatch) [generic function](https://docs.python.org/3.10/glossary.html#term-generic-function).

To define a generic method, decorate it with the `@singledispatchmethod` decorator. Note that the dispatch happens on the type of the first non-self or non-cls argument, create your function accordingly...
verbal escarp
spice pecan
#

You'd get an AttributeError appending to a tuple

verbal escarp
#

must've been added since i last checked the documentation for singledispatch ๐Ÿ˜„

#

thanks!

#

yeah, singledispatch is from 3.7, singledispatchmethod is 3.8.. makes sense

spice pecan
#

It was a relatively recent addition, yeah

verbal escarp
#

another 10 lines of code removed, nice

small swallow
#

anyone have experience in libcst?

#

theres so much and i cant make heads or tails of it

#

numpy.ma.core.maskedarray

#

so hard to read tho

verbal escarp
#

reminds of xml :p

small swallow
#

ast tree was already a headache and this is harder

#

i appreciate some guidance if anyone is willing to give some

#

please ping if you do i'll do more research

rapid rover
sacred yew
#

does it even work on more complex functions that arent just "grab a SO answer and modify the arguments slightly"

errant crest
#

Hello

sacred yew
#

it feels like a crutch for language/library limitations

#

and any fully functional coding ai would still require you to program
just that the programming language is now your "high level" step by step description instead of a "lower level language" like python

errant crest
#

I need help with threads

#

Can someone help me

sacred yew
verbal escarp
#

and not reproducable

#

it really is more a tool for inspiration in that case

#

a quite fun one, tbh

sacred yew
#

any fully functional coding ai

#

copilot is not in any way fully functional ๐Ÿ™‚

verbal escarp
#

what do you mean "fully functional"?

sacred yew
#

as in, actually works

#

and doesn't generate random gatbage

verbal escarp
#

oh, it works

#

you just need to be vigilant

#

much like those cars that can drive semi-autonomous

#

you wouldn't say they "don't work" just because they can't handle all situations, but it's a nice comfort to have if you can kick back on a boring route

#

name = f"{package_name}:{module_name}" or = f"{package_name}/{module_name}"? any preferences?

sacred yew
#

second one

verbal escarp
#

slash it is

sacred yew
#

looks like what nodejs and go (?) use

verbal escarp
#

yo

#

python!

elder blade
lusty scroll
#

next AI assistant should work on AST nodes, not text

#

I think the result would be someehat better

tulip condor
#

can any good python programming can pm me? i need small help

#

programmer*

verbal escarp
#

why can't you post it in a help-channel or here?

tulip condor
#

no-body is ready to help so..

#

i tried posting in help channel

verbal escarp
#

well, is the question advanced?

gleaming rover
verbal escarp
lusty scroll
#

maybe all the help channels could be combined into one, what could go wrong .

#

the one issue with slash and dot is , if you replace slashes with dots, you lose the separation

#

or vice-versa

verbal escarp
#

i like slashes, it corresponds nicely to Path

lusty scroll
#

PHP uses backslash, I think

#

so that one's out

verbal escarp
#

backslashes have a different meaning in strings

lusty scroll
#

indeed.. on sane platforms

verbal escarp
#

i don't know about go etc, but it's not a bad thing to go a path well-wandered

lusty scroll
#

pun intended ?

verbal escarp
#

although, me saying that probably is ..

#

i'll shut up ๐Ÿ˜‰

lusty scroll
#

lol

#

so when do we get __pypackages__/

#

did I misremember the name? that local module dir thing

#

!pep 582

fallen slateBOT
#
**PEP 582 - Python local packages directory**
Status

Draft

Python-Version

3.8

Created

16-May-2018

Type

Standards Track

static bluff
#

In general

#

What's the best way to reduce a user's exposure to a certain segment of a codebase?

astral gazelle
#

Make it as hard to read as possible

static bluff
#

Python has no privacy. I have some code that is really, really best left untouched. I don't want to explicitly stop someone from playing with it if they really want to, but I'd like it obviously private (moreso than just with underscore-notation)

verbal escarp
verbal escarp
static bluff
#

I'm sure between all out big squishy brains we can come up with something

verbal escarp
#

# DO NOT TOUCH OTHERWISE ALL HELL BREAKS LOOSE

static bluff
#

Here's the context

#

And its a bit complicated so bear with me

verbal escarp
#

or rather # THIS CODE IS AUTO-GENERATED AND WILL BE OVERWRITTEN IF MODIFIED

static bluff
#

I'm writing a graphics library for python, one which leverages web graphics by creating a pythonic clone of the DOM in the page. Make sense?

verbal escarp
#

then people will keep their hands off :p

static bluff
#

Changes to these clone elements are transmitted to Javascript in real time

lusty scroll
#

who will see it

static bluff
#

Nowโ€”for a whole host of reasonsโ€”any element manipulation (of these python clone elements) takes place in a subprocess of the main application process.

#

And thats fine. The user can do whatever they want with all that

#

But I'm typing away this morning and I realized, I'm going to have to parse the HTML before the window is launched, manipulate it, rewrite it, and then launch the window to display it

lusty scroll
static bluff
#

So unfortunately, I have to maintain a 'live template' of an HTML document within the main application process. This live template is the parsed and objectified version of the raw HTML text document the user is launching

#

Does all that make sense?

#

My thing is, and I don't really know why except that my instincts tell me so, I'd like to dissuade the user from screwing around with the innards of this template

lusty scroll
#

like beautifulsoup? but for graphics

static bluff
#

Sorta

flat gazelle
#

you could do some inspect magic and raise a warning when accessed, but if isn't part of the API, just the _ should be enough

static bluff
#

Beuatiful soup parses a document. Mine parses a document, and establishes a connection to the live-and-rendered version of it running in a browser. Changes to the parsed dom get reflected in the live version

sacred yew
#

if your users ignore the obvious signs of "internal api" and continue, they either know what they're doing already, or are hopeless cases

lusty scroll
#

what mechanism are you using to communicate state with the browser

static bluff
#

With Python, is more of a suggestion than anything. I'm just going to put this out thereโ€”there is always the nuclear option of privatizing this segment of the API using Cython

sacred yew
#

just use double underscore as extra privacy

static bluff
sacred yew
#

but imo it doesnt really matter

verbal escarp
#

it doesn't add anything and only leads to annoyance

#

dunders are only useful if you require name-mangling

static bluff
#

Unfortunately, the cefPython 'browser' object exists in the main application process and is unavailable to the window process in which the elements live. I could always use message passing (windowProcess -> applicationProcess -> JS, or reversed) but I think a direct connection via websocket will be better

verbal escarp
#

which you very rarely need

static bluff
#

I guess a big part of this comes down to how the Template object is used. In the application process, I need to parse HTML document, and inject into it a bunch of script and stylesheet (link) elements

#

These script elements are the Javascript-side of the API, and are needed to communicate with the python runtime

static bluff
#

So there's three steps to launching the application. Create the application object (thereby initializing the framework), create a template object (providing to it the location of an HTML document), and create a window object, providing to it a template object to render

#

Does that seem logical?

verbal escarp
#

doesn't seem unreasonable

#

not sure if it's logical though ๐Ÿ˜‰

static bluff
#

That template contains elements. I'd prefer those elements be 'out of the way'

lusty scroll
#

window is meant to mirror the entire chromium window? or just a document?

static bluff
#

A 'window' is actually a wxpython frame widget with a cefpython 'browser' object embedded inside. A browser o ject is an html renderer and a link to a running js running, associated with the page being rendered

#

Running js runtime*

lusty scroll
#

oh, so it's like a window with a webview embedded

static bluff
#

Sure :p

#

So, anyone have any thoughts on all this?

elder blade
lusty scroll
#

looking at the CEFPython code, they do the single-underscore thing too, so if anyone could shoot themselves in the foot, I'd think they'd have already done so with CEFPython

elder blade
#

I would say that we differ greatly in how we think, I am usually of the mentality that you should never stop the user from themselves. If someone wants to fuck themselves over then be my guest y'know

lusty scroll
#

im always annoyed when i see the program I'm trying to use has child locks on it

#

or its intentionally obfuscated to hide the python source,,etc. just makes me more determined to break its encapsulation ๐Ÿ˜…

static bluff
#

Its not so much that I want to stop the user from accessing something. Go! Do! Learn, make mistakes, have fun

#

Its that I want the API to be simple, and beginner friendly

#

And that means hiding the nitty gritty from view, so its only there if you're intentionally looking for it

elder blade
#

And in that case an _ will be enough to hide what you want

static bluff
#

There's also the fact that if you expect a user be interacting with something, there is an expectation of unambiguity required in its design. Best practices must be followed to the letter, clean and unambiguous error messages, and redundancy needs to be in place