#internals-and-peps

1 messages ยท Page 125 of 1

flat gazelle
#

julia is not statically typed

#

and it is most certainly not anywhere close to python

gleaming rover
#

I don't think I mean Julia

#

๐Ÿฅด

flat gazelle
#

yeah, the issue is that slight patches to existing languages will rarely see much adoption, since they aren't enough of an improvement

#

crystal is the one that does best from all the projects I know of, and crystal is scary impressive

#

and yet, ruby is so much more useful than crystal is

verbal escarp
#

well, i'm generally happy with the direction python is going, otherwise i wouldn't bother working on a crazy project like justuse ;D

flat gazelle
#

yeah, there seems to be a real effort to improve things

#

better errors, more specific errors, patma, ...

gleaming rover
#

yeah, but at the same time, backward compatibility (which is of course crucial)

#

kind of like a Java situation

flat gazelle
#

yeah, let's not have py2 to py3 2

#

and java is also avoiding the painful java 8 to 9+ transition happening again

#

I truly do wonder to what extent will existing languages improve and to what extent will they be overtaken by new languages, unsaddled by backwards compat

#

yes

verbal escarp
#

not sure why you think python needs to break backwards compatibility at this point

#

since there really is a lot being deprecated in every new release

gleaming rover
#

this really sucks

#

see: statement-only pattern matching

charred coral
#

ask me about being stuck in py 2.7

verbal escarp
charred coral
#

lol the depreciation rate is very high with python

verbal escarp
flat gazelle
#

yeah, not really sure how to remedy it. You can't really rewrite the whole language to be expression based by now, and going half way would probably leave us in a scala like situation, just well, not as nice

charred coral
verbal escarp
#

if that syntax needs braces to work, so be it :p

static bluff
# verbal escarp if that syntax needs braces to work, so be it :p

This. I've had people loose their shit at the very mention of braced codeblocks, but anonymous in-place callbacks are helluh useful for any asynchronous program. In Python, there is no good way to replicate

setTimeout(() => {
  # multi-lined anon function goes here
}, 100) # setTimeout used as an example
#

I realize that adding support for braced blocks goes entirely against Python's indentation-based architecture, but there is no way you can't have both

#

Well, it doesn't need to be anonymous - just that defining it in other ways is akward

verbal escarp
#

callbacks in networking or GUI programming are usually only needed a single time, so no point in naming them

static bluff
#
def someMethodOnAClass(self):

  variableIWantScopedInMyCallback = 1234

  def someCallback():
    return variableIWantScopedInMyCallback * 2

  setTimeout(someCallback, 1000)

or

def someMethodOnAClass(self):

  variableIWantScopedInMyCallback = 1234

  @setTimeoutDecorator1000)
  def someCallback():
    return variableIWantScopedInMyCallback * 2
#

The javascript approach is simply easier to read, in my and a lot of other people's opinion

def someMethodOnAClass(self):

  variableIWantScopedInMyCallback = 1234

  setTimeout(() => {variableIWantScopedInMyCallback * 2})
#

In what way?

#

Oh, you mean the camel case?

verbal escarp
#

nvm PEP8, you could call your anonymous function _()

static bluff
#

XD I'm working on a project that enables pure-python DOM manipulation. To make things a little easier on JS developers who want to use it, the API is built with camelcase. Its my auto at this point

verbal escarp
#

but using a def to define a one-off function simply is unnecessary boilerplate

static bluff
#

And using lambda instead of an operator is just kinda silly

grave jolt
#

well, each programming community has its rules and guidelines, many Python programmers won't appreciate a library that uses camelCase

#

I'm using camelCase in TypeScript because that's what TypeScript uses and snake_case in Python because that's what Python uses

#

doesn't really matter, just a convention to have consistent naming across projects

static bluff
#

"many Python programmers" aren't the only demographic I have to consider

verbal escarp
grave jolt
#

yeah (also logging), it seems a bit out of place to the eye to be honest

static bluff
#

Additionally, I'm going for as close a replication of the important JS API as possible. This lets Python developers directly translate JS tutorials they see online without having to do any translation and also makes life easier for JS developers

grave jolt
#

are you making a library for selenium or for brython?

#

or for something else?

static bluff
#

You've worked with me on this many times, Fix XD

quasi hound
#

My current project has like 12 super long functions defined that I only use once

#

Would be cool if this stuff was added

#

Fat arrow or whatever

static bluff
#

Its a graphics framework that launches an HTML renderer (cefPython) and creates a virtual clone of the DOM in the python runtime. Using custom descriptors on the elements in that proxy dom - prosto chango, pure-python web graphics

quasi hound
#

So no HTML/CSS/JS, it's just python?

#

If it's not super slow people are gonna love this

static bluff
#

No, there's HTML. You write your HTML in numerous documents though, and a custom importer stitches them all together into a singular HTML composite. I know this might be a bit controversial but any web developer will tell you that HTML can get out of hand quickly. A modular HTML system is my choice as the developer and I stand by it. Beyond that though, HTML and CSS is onboarded by a custom importer. You can implement your own JS but its heavily discouraged. Modifying the DOM in javascript would result in de-synchonization between the two runtimes

grave jolt
static bluff
#

Also lol

verbal escarp
#

well, in ascii there are still more unused characters ๐Ÿ˜‰

charred pilot
#

hell yeah, ] shell prompt

static bluff
#

=> cough precident cough

flat gazelle
#

what I could imagine would be something like unnamed decorator calls

@setTimeout(100):
    print('it is now 100 millis later')
verbal escarp
#

o.O

static bluff
#

A decorator without anything to decorate is... well I don't know what that is

verbal escarp
#

i'm not convinced either ๐Ÿ˜‰

static bluff
#

A closure, I suppose?

flat gazelle
#

yeah, that's not great syntax by any means

verbal escarp
#

too bad $ has such a bad rep

static bluff
#

Always great talking with y'all

flat gazelle
#

the issue is simply that a block as a full expression doesn't really have nice syntax. braces are great, but you would probably use something that doesn't conflict with a set literal, like <> or (), and even then, you are left with the incredibly ambiguous case of where should indentation continue. It's creates some tough to make sense of syntax, you can look at nim to see how it looks, it has indented blocks as expression

static bluff
#

Food thought

#
def some_method():
  
  some_variable = 1

  some_callback_registrar(lambda :
    # use normal block indentation here
  )
#

The braces are really just for aesthetics. The salient point is the definition of functions anonymously as expressions (I think thats the correct terminology). You can impose the same restrictions on indentation for the anon function as you would any other function. Its where you can place the definition that counts. In terms of the grammar you'd just need to keep track of the starting indentation and apply all the same rules except also demand that at no point in the anon can anything have less indentation that of the line its defined on plus one

flat gazelle
#

That still has ambiguities, but it is pretty much exactly how one of the syntaxes works in nim.

static bluff
#

Using braces might be useful as start-end flags for the parser, but aren't requisite

flat gazelle
#

It is definitely an option, however. There is sadly the question of

fun(lambda:
    a, b=3
)
```not being super clear
static bluff
#

I guess all I mean to say is that the arguments against multiline and more attractive lambdas are dwindling while the use cases are piling up. Even from aa minimalist perspective it seems like a good idea

flat gazelle
#

Yeah, I think if someone proposes a good enough grammar, it would probably get into the language

#

But I haven't seen one that would work well

static bluff
#

Lemme get back to you, in a years time, when I get to work on my language

flat gazelle
#

Sure

grave jolt
#

hopefully you do better than the previous person who tried to make an ambitious language implementation ๐Ÿ™‚

flat gazelle
#

I have much higher hopes for skywalker's language than for Leigh

verbal escarp
#

well, keep in mind that you might want to define lambdas as dict values, so indentation alone might be difficult

static bluff
#

Its just for learning purposes. Explore some ideas, learn what makes a language tick. Its like the programmer's equivalent of a triathlon. Coming in first is great, but just completing it is an achievement. Plus, I'll be annoying you guys with questions about it ad nosium

flat gazelle
#

You do probably need an end tag of sorts, since the expression grammar was not made with an indented block in mind (see my second element/unpacking ambiguity)

static bluff
#

On the topic of unpacking

#
a, b = {'a': 1, 'b': 2}
#

I want this

verbal escarp
#

that's not a good idea ๐Ÿ˜‰

flat gazelle
#

Patma more or less gives you this, just in a slightly more verbose and more powerful form

static bluff
#

Yeah, I guess you're right

flat gazelle
#

And well, unlike JS, you don't build objects of various values nearly as much in most codebases

#

In part thanks to optional arguments

static bluff
#

ARGUMENZ!

#

Ha

grave jolt
static bluff
#

Pursuant to a previous discussion, I've done aa bit of refactoring. Thoughts?

gleaming rover
#

by inspecting stack frames

#

it didn't work in all cases

#

but it was fun

gleaming rover
#

okay, I guess one problem is that Python has __getitem__ and __getattr__, whereas in JS they're effectively the same thing

verbal escarp
#

that's not the problem i see, for me the syntax is ambiguous

#

and also not foolproof - just think of keys that can't be names

gleaming rover
gleaming rover
#

I don't really see that as a problem

#

you can't pass such a dict to a function taking a ** argument too

#

that would cause a runtime failure

verbal escarp
#

TypeError: keywords must be strings

#

but {a,b} means something entirely different to me

#

it looks like you're trying to make a set of sorts

gleaming rover
#

but sets are unordered so that wouldn't make sense semantically

#

and since {} are used for dict literals too I think the analogy is reasonably clear

verbal escarp
#

exactly my problem

gleaming rover
verbal escarp
#
f(**{1:2})
Traceback (most recent call last):
  File "<pyshell>", line 1, in <module>
TypeError: keywords must be strings
gleaming rover
#

that's exactly what I said

#

it causes a runtime failure

#

ordered iterable destructuring does the same thing

static bluff
#

For the record some_function(**{'some-invalid-identifier': 1}) won't throw an error, but using a non-string will

static bluff
gleaming rover
gleaming rover
#

and raising an exception if there's a mismatch

static bluff
#

{a, b, **rest} = some_big_and_complicated_dict would be kinda nice, no?

#

We already do it with kwargs

gleaming rover
#

it would, but

#

I would like similar functionality for attributes

#

and we're kind of running out of tokens

static bluff
#

XD I was gonna say that, but I was afraid being asked politely to leave

#

About the attributes

#

{a, b} = some_object seems fine to me tbh. Most people understand that objects are really just dictionaries+ under the hood

pliant tusk
#

If the dict de structuring was implemented you could do {a, b} = vars(some_object)

quasi hound
#

Dicts should just have a + operator that combines them

def __add__(self, other):
    return dict(self).update(other)
def __iadd__(self, other):
    self.update(other)
#

this = {**pretty, **stupid}

verbal escarp
#

you can do pretty | stupid

quasi hound
#

Adding makes more sense if you ask me

verbal escarp
#

not to me

quasi hound
#

It's what all the other data structures do

#

Or is just like

#

It works but you gotta think about it a bit

verbal escarp
#

if you consider them as sets, kind of

quasi hound
#

Not as obvious

verbal escarp
#

it makes perfect sense

quasi hound
#

kk

spark magnet
#

@quasi hound there were long discussions about this on the Python-Ideas mailing list, and likely a PEP covers why the syntax was chosen.

gleaming rover
quasi hound
#

Order matters with dicts tho
a.update(b) โ‰  b.update(a)

gleaming rover
#

tbh I think mandating that dicts maintain insertion order was a bad idea

#

okay I guess if it's restricted to iteration it's fine

#

I DON'T KNOW ๐Ÿฅด

quasi hound
#

I like that actually

#

And sets should too

grave jolt
fallen slateBOT
#

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

001 | {'a': 2}
002 | {'a': 1}
quasi hound
#

Bc dict.keys is a set

#

And it keeps its order

#

^^

gleaming rover
#

๐Ÿฅด

#

I think there was reasoning on this in the PEP

quasi hound
#

!e

print({'a': 1} == {'a': 2}
fallen slateBOT
#

@quasi hound :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 |     print({'a': 1} == {'a': 2}
003 |                               ^
004 | SyntaxError: unexpected EOF while parsing
quasi hound
#

Ok shut up

gleaming rover
#

or rather

#

in what sense is it a set

quasi hound
#

I thought that's how hash tables worked

gleaming rover
#

like are we talking about the abstract data structure set, the mathematical set, or the Python set?

quasi hound
#

Python set

#

I know it's KeysView, whatever that is

gleaming rover
#

!e

print(isinstance({}.keys(), set))
fallen slateBOT
#

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

False
quasi hound
#

!e
print(type({}.keys()))

fallen slateBOT
#

@quasi hound :white_check_mark: Your eval job has completed with return code 0.

<class 'dict_keys'>
gleaming rover
#

I guess you could say it's set-like?

quasi hound
#

See I don't know what that is

#

Exactly

#

Stop playing games

verbal escarp
#

it's more the other way round, the initial implementation of sets was basically a dict without values, iirc, while mathematical sets are the most basic structure

gleaming rover
#

without a direct analogue

prime estuary
#

dict_keys is a set, it's an instance of collections.abc.Set, and has all the same sort of operators and methods frozenset has.

#

From here: https://docs.python.org/3/library/stdtypes.html#dict-views:

Keys views are set-like since their entries are unique and hashable. If all values are hashable, so that (key, value) pairs are unique and hashable, then the items view is also set-like. (Values views are not treated as set-like since the entries are generally not unique.) For set-like views, all of the operations defined for the abstract base class collections.abc.Set are available (for example, ==, <, or ^).

gleaming rover
#

Set is the first one

prime estuary
#

Yeah. It's not an instance of set since that's a specific implementation.

quasi hound
#

Thanks

#

I should've said ADT then

#

Idk why you even said mathematical set

visual shadow
#

So I can't fault the decision having seen how useful insertion ordered dicts can be

halcyon trail
#

Idk, I don't find it terribly useful

#

But also don't see why it was a bad idea

#

I'm pretty neutral to it

#

If you've been programming a while and in other languages it's pretty ingrained not depend on dicts being ordered

novel mortar
#

why is the logging module not using snake_case?

raven ridge
#

Because it's a port of the Java log4j library and predates Python standardizing on snake case

#

Yeah, unittest is based on junit

raven ridge
#

I think they were probably right.

spice pecan
#

OrderedDict is still useful when you need efficient reordering

#

I guess it just makes it a bit more of a specific use-case kind of deal than it used to be, as in a lot of cases insertion order would be all that is needed

gleaming rover
gleaming rover
#

pytest is so good

#

test parameterisation and fixtures are beautiful

verbal escarp
#

iirc they actually had dicts explicitely in a random order at one point to educate people not to rely on order

#

i find it very useful to have dicts be insertion-ordered

#

and sets should be too

#

retrieving items from a set is so unnecessarily hard..

#

it would make sets so much more useful if you could just pop() the last inserted item

verbal escarp
#

sure is, but with set qualities ๐Ÿ™‚

#

O(1) for test, no duplicates..

spice pecan
#

Well, depending on how much you care about memory efficiency, you could write a simple wrapper that abuses dicts

#

(or stores the insertion order in a list)

verbal escarp
#

sure could, but i'd prefer to have more useful built-in sets ๐Ÿ™‚

spice pecan
#

Their design is very different, which is exactly why they didn't get the same optimization as dicts which allowed to preserve insertion order

#

So if all you need is insertion order and O(1) membership, a dict with None values would do

#

dict_keys for set-like operations

elder blade
#

Actually that reminds me about something I've been wondering about. ```py
class Hashable:
unique: str
other: int

def __init__(self, unique, other):
    self.unique = unique
    self.other = other

def __hash__(self):
     return hash(self.unique)
Can I use a set to store these objects, and then get them back so that I can get the in-memory `other` attribute?
#

Or would I need to use a dict that uses unique as the key?

visual shadow
#

it;s hashable, it can go in a dict. whatever else you want to do is up to you

peak spoke
#

afaik you'd need a dict that maps a key to itself if I understood what you want correctly

verbal escarp
#

you can retrieve it from the set if you iterate over it

#

i've done it before, but it's ugly as heck

visual shadow
#

hm, i'll be honest, i dont know why you'd want to use a set for retrieving things.

verbal escarp
#

sometimes you want any item from a set

#

tbh i forgot why i needed to do that in the first place, it's been a long time past

elder blade
#

Won't that even have some level of overhead if I use a dictionary? It stores the hash, key and value right?

spice pecan
#

There will be some overhead, but the question is, will it be significant enough to justify weird set hacks?

peak spoke
#

I'm not sure if there are any set hacks to do that maintain the time complexity

visual shadow
spice pecan
#

You can store that in a set, and you can get a quick membership check, but you can't retrieve it gracefully

visual shadow
#

to me, that seems like the simplest straight-line solution

spice pecan
#

The example provided just looks like a dict with extra steps, but I assume it's simplified for the sake of being an example

visual shadow
#

well no, i understand the ask i think. basically, bluenix wants objects that are actively getting hash collisions

#

and in this case, that's a desried/expected thing, and so the existing object should be given back

#

to me however, that feels counterintuitive, so if i was coding it up, i would have explicitly put these calculated "hashes" as keys myself, the objects as values, and written out the if conditions explicitly.

elder blade
#

Umm no, not really.

I have a bunch of these objects, and a lot of those other fields. Sometimes I construct a new object with the same unique, and so in that case I want to be able to grab the old object.

elder blade
visual shadow
#

so, unique are the keys, and the objects are the values

#

am i missing something?

elder blade
visual shadow
#

ah okay, yeah i think that's the simplest solution ๐Ÿ™‚

unkempt rock
#

Hmm

mighty pasture
#

Plus in the end there is a Timeout error so is there any way to fix that error

unkempt rock
#

Hey, could anyone link me to a website/git that has a SHA256 code that uses pure mathematics without using a module?

verbal escarp
#

what is "pure mathematics"?

unkempt rock
#

not using a module to compute the algorithm

#

just if, else, while, and other built in functions

verbal escarp
#

for performance reasons it seems

unkempt rock
#

performance is not an issue anymore lol

#

@verbal escarp

#

is there a code that u could link to me?

#

im in a hurry

verbal escarp
tacit wyvern
#

Is there a good file format for storing 2d arrays that expand in length and width. Serialization might be the only option I can think of off the top of my head.

tacit wyvern
charred wagon
#

I think this is the wrong channel for your question. Maybe open a help channel?

tacit wyvern
#

I would but Iโ€™m just spitballing here with no actual code

deft pagoda
tacit wyvern
charred coral
#

Has anyone ever had an issue with string.__contains__ not working in a Linux environment, but no problems on Windows? Same versions of both py as well as all modules from pip

Edit: pip actually not relevant

charred pilot
#

what issues?

charred coral
# charred pilot what issues?

Sorry for late response. I asked in help but I think it was a little advanced. I have a function that takes a <5mb JSON array with nested arrays full of pictures - probably 20,000 images per response. The function that works without an issue simply uses a nested for loop and iterates over the array and appends the MediaURLs to a new array and returns that back to the calling function.

charred coral
#

Using that function structure to build both the array of urls and well as get the count had no problems on Windows.. either that or I had restricted the limit of the API request and there is a bad set of data in that specific pull (or missing Media key). Either way, the contains didn't seem to help it.

raven ridge
#

That can be simplified to just

def count_media(data):
    return sum(len(value.get("Media", [])) for value in data["value"])
charred pilot
#

what's with the manual del and gcing

charred coral
# charred pilot what's with the manual del and gcing

So the import script, if we replicate from the beginning of the vendors database, it downloads over 1,000,000 real estate listings and processes appx 17m jpeg files in total (request streamed into another s3 bucket). After it has ran about 20-30 times, if we dont del the data or run gc.collect() it will run OOM. One thing we weren't sure of was if the del was required for gc.collect() to clear the data in memory

charred pilot
#

del only gets rid of that reference to the object, if there are other references the object will stay alive

charred coral
charred coral
unkempt rock
#

Sanity check - this snippet that reverses a slice of a list will create the reversed slice fully and separately before putting it back in the list, right?

#

!e ```py
a = list(range(10))
print(a)
a[2:8] = a[7:1:-1]
print(a)

fallen slateBOT
#

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

001 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
002 | [0, 1, 7, 6, 5, 4, 3, 2, 8, 9]
unkempt rock
#

and thus would use more memory (O(N)) than a slice reverse could do if optimal (O(1))

charred wagon
#

If you're in doubt you could look at the dissassembly

unkempt rock
#

I forget how to do that lemon_thinking

charred wagon
#

!d dis.dis

fallen slateBOT
#

dis.dis(x=None, *, file=None, depth=None)```
unkempt rock
#

!e like this pithink py import dis def f(a): a[2:8] = a[7:1:-1] print(dis.dis(f))

fallen slateBOT
#

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

001 |   3           0 LOAD_FAST                0 (a)
002 |               2 LOAD_CONST               1 (7)
003 |               4 LOAD_CONST               2 (1)
004 |               6 LOAD_CONST               3 (-1)
005 |               8 BUILD_SLICE              3
006 |              10 BINARY_SUBSCR
007 |              12 LOAD_FAST                0 (a)
008 |              14 LOAD_CONST               4 (2)
009 |              16 LOAD_CONST               5 (8)
010 |              18 BUILD_SLICE              2
011 |              20 STORE_SUBSCR
... (truncated - too many lines)

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

unkempt rock
#

not totally sure how to read it rooDerpy but I see BUILD_SLICE in there

charred wagon
#

Yeah you can see it happens twice

#

Maybe it would be more obvious if you compared it against a version that assigns the slice to an intermediary variable before inserting it. It shouldn't be much different.

unkempt rock
#

!e py import dis def f(a, b): a[2:8] = b print(dis.dis(f))

fallen slateBOT
#

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

001 |   3           0 LOAD_FAST                1 (b)
002 |               2 LOAD_FAST                0 (a)
003 |               4 LOAD_CONST               1 (2)
004 |               6 LOAD_CONST               2 (8)
005 |               8 BUILD_SLICE              2
006 |              10 STORE_SUBSCR
007 |              12 LOAD_CONST               0 (None)
008 |              14 RETURN_VALUE
009 | None
unkempt rock
charred wagon
#

I mean like this

#

!e ```py
import dis
def f(a):
b = a[7:1:-1]
print(b)
a[2:8] = b
print(dis.dis(f))

fallen slateBOT
#

@charred wagon :white_check_mark: Your eval job has completed with return code 0.

001 |   3           0 LOAD_FAST                0 (a)
002 |               2 LOAD_CONST               1 (7)
003 |               4 LOAD_CONST               2 (1)
004 |               6 LOAD_CONST               3 (-1)
005 |               8 BUILD_SLICE              3
006 |              10 BINARY_SUBSCR
007 |              12 STORE_FAST               1 (b)
008 | 
009 |   4          14 LOAD_GLOBAL              0 (print)
010 |              16 LOAD_FAST                1 (b)
011 |              18 CALL_FUNCTION            1
... (truncated - too many lines)

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

charred wagon
#

the print demonstrates that it is indeed a full object of its own

#

And apart from the print call and loading the slice from the b variable, the disassembly is the same.

unkempt rock
#

ah, I see

potent fractal
#

What is the difference between front and back end coding

cunning ravine
potent fractal
#

Ok thnx

#

It's like when you click on subscribe button it becomes read that is the front end work and the process is made from the back end people.................... ........ this is from ehat is understood

#

Is it right?

paper echo
static bluff
#

What are you guys' thoughts on beartype?

#

I'm reading through the docs and, beyond being hilarious in their own right, indicate they are aiming for production-grade runtime type validation in Winter 2022

flat gazelle
#

a lot of types cannot be checked at runtime, for example you cannot verify that a list[bool] is actually a list[bool]

#

but it seems useful when you are aware of it's limitations

static bluff
#

Why can't you?

charred pilot
#

it would incur massive runtime costs, imagine if it was 100000 long

static bluff
#

So, you can, you just shouldn't

charred pilot
#

yeah, but that's why you can't do it realistically

flat gazelle
#
all_bools: list[list[bool]] = []
def add_to_bools(arg: list[bool]):
    all_bools.append(arg)
my_list: list[int] = [True, False]
add_to_bools(my_list)
my_list.append(5) # oh no
#

also, functions, coroutines, dictionary and list subclasses, generators, ...

static bluff
#

I'll be doing more reading on it, but my understanding is that such challenges are exactly what they're working on

flat gazelle
#

I mean, if they can solve the halting problem, good on them

#

you could keep tags on the types to remember the content they expect, so a fuction would only error when called etc

#

which is not bad all things considered

#

but IDK how you would keep those tags on python objects

static bluff
#

*"Beartype 1.0.0 brings us perfect compliance constant-time compliance with all annotation standards. That's good. But is that it?

It is not."*

#

They're aiming for 1.0 in December 2022, though I'd imagine mid 2023 is more realistic

flat gazelle
#

it's an interesting project for sure

static bluff
#

Of course, I don't expect some revolutionary mathematical proof or whatnot, but "compliance with all annotation standards" would sit right with me for sure! ๐Ÿ˜„

flat gazelle
#

it they can keep a runtime tag on an arbitrary object to track all protocols it has ever been assigned in constant time, I would be very impressed

static bluff
#

The reason I'm asking is, well, I imagine I'll be finish up this project in a year or so, and it'd be nice to equip it with beartyping when that becomes possible

#

Its more than enough already, I suppose, for a limited scope. It can do built-in types, most nested generics, callables. Its the curious cases they're working on now I think

#

The real headscratcher I've got going on right now is that I don't like the error messages they put out. I'd like to rewrite them, but its not as simple as just catching the error and replacing it with my own because information about what caused the error isn't really carried along with the error

#

I could, I suppose, copy-and-paste the library and just rewrite the exceptions

#

I guess the most pythonic approach would be subclassing their decorator, studying the nuts-and-bolts of how it works, and just overriding the bits relevant to the writing of the error

flat gazelle
#

I see, this isn't really a type safety tool, more of a error faster tool

halcyon trail
#

For generic types it makes much more sense to let the type protect its own type invariant

#

Rather than try to verify downstream

nova iris
#

does anyone know why this behaviour is in python? for me it doesn't seem like there'd be any benefits for this redundancy; since a += b is equivalent to a = a.__iadd__(b), why does __iadd__ modify the list in-place, and return it again for assignment? it seems like only doing the return would suffice for augmented assignment syntax ```py

a = [0]
a.iadd([1])
[0, 1]
a
[0, 1]

return AND in-place?? weird

flat gazelle
#

it's an optimisation of sorts

#

__iadd__ is made special like that exactly to allow in place modification

#

for example

some_numpy_array += 5``` should not copy the array
nova iris
flat gazelle
#

it will have the same result, but consider a 10000 long list

radiant fulcrum
#

memory allocation

flat gazelle
#

you would have to copy the list, add one element to it, then return the new list, then remove the old list from memory

boreal umbra
#

I think it's more than the semantics of __iadd__ is the same even if it's being used for a data type that doesn't get modified in place.

nova iris
#

OMG

#

PYTHON IS AMAZING

#

WOWOWOWOWOWOWOOW

#

.bm 874008100510761031 for further reference :DDDD

boreal umbra
#

that is clearly not intended

#

the way that lancebot rejected that

nova iris
#

lol time to open issue

boreal umbra
#

I dunno, maybe it is intended. Anyway, consider int.__iadd__ You can't change the int in-place (unless it has a special implementation in C), so a write to the symbol table is necessary.

#

!e

a = 5

def foo():
    a += 1
    print(a)

foo()
print(a)
fallen slateBOT
#

@boreal umbra :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 7, in <module>
003 |   File "<string>", line 4, in foo
004 | UnboundLocalError: local variable 'a' referenced before assignment
nova iris
boreal umbra
#

interesting

nova iris
#

okay, so summary: mutable objects that can perform in-place changes change in-place first before returning the changed object in __iadd__ so that they don't have to recreate a new object with the increment (which would be in the case of only return, no in-place change), because that would be less efficient from the extra memory allocation python has to do @flat gazelle @radiant fulcrum @boreal umbra
am i right?

flat gazelle
#

pretty much

nova iris
#

yay! thanks a lot y'all, this cleared it up a bunch!!

#

what seemed like redundant at first actually had PythonBlackMagicโ„ข๏ธ underneath, this is so cool

pliant tusk
#

this behavior does get a little unintuitive in some cases tho ```py

x = ([],)
x[0] += [1,2,3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
print(x)
([1, 2, 3],)

nova iris
#

understanding this weirdness

pliant tusk
#

yea its easy to see why it does that by looking at dis output and knowing how INPLACE_ADD works

nova iris
#

uh wat

#

you're telling me you can x pow= 3, 5 or some crap like that? ๐Ÿ˜‚

#

why is the modulo param even in there- ternary augmented assignment doesn't exist

#

or does it

#

same with this here

Note that ternary pow() will not try calling rpow() (the coercion rules would become too complicated).
so then... why the heck is modulo there

flat gazelle
#

I assume ipow is used by a **= b

nova iris
#

and to my knowledge, you can't really augmented assign a function call lol

flat gazelle
#

hmm, yeah, there doesn't seem to be much of a reason for that

nova iris
#

i guess it's to just be clean and uniform? even though that optional param will never be defined in these two dunders

flat gazelle
peak spoke
#

The argument probably exists because the pow builtin and direct uses will use that method

nova iris
flat gazelle
#

but why would you call __rpow__ manually

nova iris
#

pow(1, 2, 3) would be int.__pow__(1, 2, 3), because we know that __rpow__ won't be used in this case (it's only used for ** syntax)

#

so __rpow__ and __ipow__'s modulo parameter is useless

#

ofc, like @flat gazelle said, you could call it manually

#

but no one would do that

#

debug purposes, perhaps?

deep bramble
#

does python have support for something like async lambda?

flat gazelle
#

more or less no

deep bramble
#

why? is it just that nobody has ever attempted to add it or was it proposed and denied for some reason?

flat gazelle
#

I believe there wasn't much reason. For almost all the cases, you can just return the unawaited coroutines

deep bramble
#

I mean, that's kind of the same as saying that you can just pass in the function object

#

this means that the async function still has to be defined as a function which is a bit unpractical for certain use-cases, this is pretty much the same problem that lambda solves with sync functions

flat gazelle
#

yeah, it would be neat, but I am not sure it's important enough to really be worthwhile, I don't mind the

async def a():
    async def b():
        pass
    return b()
```that much
deep bramble
#

I would find it quite useful with unit-tests, I often find myself having to either write an async mock and define what it's call will return, or define a full async function and pass that in so that a function can await given coroutines even if they only return a static value

#

I don't suppose that there's an easy way to convert regular sync functions to coroutines

flat gazelle
#

!d asyncio.coroutine

fallen slateBOT
#

@asyncio.coroutine```
Decorator to mark generator-based coroutines.

This decorator enables legacy generator-based coroutines to be compatible with async/await code:

```py
@asyncio.coroutine
def old_style_coroutine():
    yield from asyncio.sleep(1)

async def main():
    await old_style_coroutine()
```...
deep bramble
#

it's not really a generator based function though

flat gazelle
#

not sure when they are getting depracated though

#

that's good, otherwise this wouldn't work

#

yield from is await

deep bramble
#

yeah, but I meant simple return

flat gazelle
#

then just return

deep bramble
#

like ```py
make_coro(lambda x, y: True)

flat gazelle
#

!e

from asyncio import coroutine, run
async def amain():
    print(await coroutine(lambda x, y: True)(1, 23))
run(amain())
fallen slateBOT
#

@flat gazelle :white_check_mark: Your eval job has completed with return code 0.

001 | <string>:3: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
002 | True
flat gazelle
#

but well, yeah, the decorator is going away soon

peak spoke
#

you can use types.coroutine

flat gazelle
#

ah, didn't know about that one, that's useful

#

if all you want are constant coroutines, you could also just do

def make_coro(fun):
    async def coro(*args, **kwargs):
        return fun(*args, **kwargs)
    return coro
deep bramble
#

!e ```py
from types import coroutine
coro = coroutine(lambda x: True)
await coro(2)

fallen slateBOT
#

@deep bramble :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 3
002 | SyntaxError: 'await' outside function
peak spoke
#

the coroutine from types is a bit more limited in its use than asyncio's so I'm not sure if you can use it on a lambda like that. Not sure what it does with normal functions

deep bramble
flat gazelle
#

other than the depracated asyncio decorator, afaik no. py In [21]: from types import coroutine ...: coro = coroutine(lambda x: (yield) or True) ...: asyncio.run(coro(2)) ...: ...: Out[21]: Truethis does work,but it isn't all that great

deep bramble
#

hm, well thanks I suppose I'll go with the decorator then, but yeah, this is precisely why async lambda would be great

unkempt rock
#

I use arch

deep bramble
unkempt rock
#

Async in python

#

is not very well optimised

flat gazelle
#

the core job of async is waiting, and no matter how you implement things, you will wait just as long

grave jolt
#

Christopher Neugebauer

https://2020.pycon.org.au/program/VVNEZR

When you type โ€œimport thisโ€ into a Python interpreter, you get PEP-20, 20* aphorisms that describe what โ€œGoodโ€ Python code looks like. Most of these are prescriptive, and have been used to settle countless arguments about how Python should grow, or how new ideas should be implemen...

โ–ถ Play video
cobalt agate
#

Folks,
What's the best library to randomize color of a pixel artwork? Or even modify it?

radiant fulcrum
#

mmm probably numpy

#

at the end of the day a picture is just a big array of numbers

#

numpy's ability to very efficiently apply operations to the array makes that easier and quicker

visual shadow
grave jolt
#

yeah I think it somewhat sums up some disagreements on the mailing lists when people were trying to back up their position using the Zen

#

can't really find the place

visual shadow
#

I didn't even think anyone was claiming that the zen would give you the end-all be-all answers to how to code, so to me, all i watched was an opinion fleshed out which i didn't think needed fleshing out.

tropic parrot
#

whats computer science guys?

boreal umbra
grave jolt
#

I know this is super cursed, but is there a way to make a conditional check about the type checker? Like

if using mypy:
    ...
elif using pyright:
    ...
elif using pyre:
    ...
else:
    ...

so that mypy only detects its block of code as non-dead, pyright its own and so on.

gleaming rover
#

not necessarily true + not scalable though

grave jolt
#

I guess the real solution is to standardize typing, but, well

#

basically, we want to make a thing called Arg where you can only invoke Arg[A, B] where B has to conform to SomeProtocol[A] (A should match the first argument), at runtime Arg[A, B] should evaluate to B but to the type checker it should be equivalent to A.

main ginkgo
#

maybe theres a way to pipe the code through something that can tell if/which type checker is being used

gleaming rover
#

feels like just inconsistencies in 3rd party type checkers ๐Ÿ˜”

#

so like...

#
def func[A, B <: ConverterT[B], ConverterT[_]](a: A): B = ???
#

that's what I'm thinking

#

not sure if my mental model is right I just woke up

#

but no ideas, sorry ๐Ÿ˜” tbh I don't even use anything but PyCharm's checker

grave jolt
gleaming rover
#

I also ran the mypy snippet

#

like

grave jolt
#

The background of that is that we wanted to make discord.py play nice with type hints. Right now you convert argument like this ```py
class IntConverter(Converter):
async def convert(self, ctx: Context, argument: str) -> int:
return int(argument)

async def my_command(ctx: Context, number: IntConverter):
...

and at runtime, `number` will be `int`, which screws with all type checkers. So we wanted to make something that would allow  ```py
async def my_command(ctx: Context, number: Annotated[int, IntConverter]):
    ...
```, so that the type checker is happy, and the library works. But using `Annotated` requires monkeypatching discord.py, and it doesn't ensure that `int` is what `IntConverter` produces.
gleaming rover
#

but you want to turn it into a more appropriate type

grave jolt
#

yeah

#

and then reuse the converters

gleaming rover
#

just like parsing URL parameters

grave jolt
#

yeah yeah, like FastAPI

gleaming rover
#

so in the case of a command wiht one argument

grave jolt
#

I'm not entirely sure how it works, but the central problem we're solving is that discord.py uses annotations in a way that is not compatible with type checkers

gleaming rover
#

hm.

gleaming rover
#

that we're trying to work around

grave jolt
#

yep

gleaming rover
#

is there a way

#

to mark one type as a subtype of another

#

?

#

tbh I don't know how the tools work

grave jolt
#

nobody knows how they work

gleaming rover
#

like in the abstract sense it's not a super hard problem but I have no idea how to implement it

#

the gist of it is that you want to take an argument Wrapped[T] and have it be treated as a subtype of T

#

in the function body

#

right?

#

so you enforce two constraints: that it is an instance of Wrapped (the converter) and it can be used as T (the output value)

#

that feels like the simplest solution to me without going into rather complex stuff

small quest
grave jolt
small quest
#

nah i'm not gonna get into a discussion about monkeypatching the lib

#

that should be a last resort

grave jolt
#

What's the proper way to add documentation to attributes? Methods have docstrings, but attributes don't

#

And I don't want to create a no-op property for every attribute

paper echo
#

@grave jolt sphinx recognizes a string literal after an attribute or top-level definition as a docstring

#
a = 12345
"""This is the 'a' definition."""
grave jolt
#

๐Ÿค” interesting

#

In my case, I just want to document private attributes in code

#

So I wanted to know which style is the least cursed to other developeres

halcyon trail
#

If it's for private stuff why not simply a comment?

#

Kind of confused

#

Like I think salt did, I assumed the reason you were asking was because it was some kind of public doc

grave jolt
#

Yeah I guess I can just put an inline comment

blissful comet
#

Work on typpete is coming along nicely:

https://github.com/adsharma/Typpete

https://github.com/adsharma/py2many/issues/96
https://github.com/caterinaurban/Typpete/issues/59

Would love to get more feedback on what's not working well. Should have it on pypi once the naming/forking issue is resolved.

GitHub

Contribute to adsharma/Typpete development by creating an account on GitHub.

GitHub

I think it would be useful to utilise https://github.com/ilevkivskyi/typing_inspect , or similar to offload some of the type inference/analysis work.

GitHub

I've made some usability improvements in the fork at: https://github.com/adsharma/Typpete A few questions: Are these improvements interesting? If not and if you'd prefer that I main...

elder blade
naive adder
#

oops wrong channel sorry

olive marsh
#
...     pass
... 
>>> class B(A):
...     pass
... 
guys can we pass info from B to A
program execution most come to B before going to A. we will pick that point and add some info to it, before the program execution goes to A.
can we add some info in A from B
boreal umbra
#

@olive marsh you would be able to call methods defined in A on an instance of B, yes

olive marsh
#

No I want to pass info from B to A. i know i can call functions of A from B

#

call i make this other way round

#

i just want to pass some info

boreal umbra
#

What do you mean by "pass info from B to A"?

olive marsh
#

like my class A has everything inside it. you can initialize that class only but user can subclass the A and add some info to it. according to this the behaviour of A gets changed

#

sorry, i don't know how to ask. I am confused, dealing with an internal framework of the company. I will ask someone from the company.

#

Btw,edited my question

elder blade
#

B is A

#

But extended, B is A with more stuff

visual shadow
#

If this is the ask, to me it sounds like the Y of an XY problem. Perhaps there's a better way to organize or refactor this code.

#

Now, having said that, technically B could just make an instance of A class and probably achieve whatever you're thinking of. But I can't help but feel that in that case do B and A really have a subclass relation?

viral yacht
#

Hey everyone i am encountering very weird issue

#

I have MacBook m1 and i am not able to run psycopg2 as i get import error

#

These are the sc. I am using fast API and it was working fine , until i added import psycopg2

grave charm
#
    def get_piece_moves_at(self, y: int, x: int) -> List[Tuple[int, int]]:
        board = self.board
        piece = board[y][x]
        direction = self.get_piece_direction_by_color(piece)
        moves = []
        new_y = y + direction
        
        try:
            if board[new_y][x] is None:
                moves.append((new_y, x))
        except IndexError:
            return []
        
        for x_ in (1, -1):
            new_x = x + x_
            try:
                if board[new_y][new_x].color != piece.color:
                    moves.append((new_y, new_x))
            except IndexError:
                continue
            except AttributeError:
                continue
            ``` is this bad ![WatchItBurn](https://cdn.discordapp.com/emojis/419799219046580231.webp?size=128 "WatchItBurn")
quasi hound
#

no not really

#

x_ is a shitty variable name but it looks fine

#

overall

grave charm
#

I'm pointing at the try except

brave badger
#

@viral yacht psycopg2 doesn't seem to have (full) support for M1s yet

paper echo
#

is this from a leetcode type of website or some popular online course?

nova iris
#

๐Ÿ˜” why doesn't divmod fall back to __floordiv__ and __mod__... why do we need to explicitly create __divmod__

opal meadow
#

if am not wrong, immutable's are addressed by value and mutables are addressed by reference?

flat gazelle
#

no, both are handled the exact same way

opal meadow
#

oh

#

so how are immutable's defined?

flat gazelle
#

they aren't defined

opal meadow
#

I mean
how does it state that it's an immutable

flat gazelle
#

it doesn't

#

it just doesn't define any operations that change it

opal meadow
#

how else does it know it cannot be changed?

#

oh

#

so its like no __setitem__ for tuples/strings?

flat gazelle
#

yup

opal meadow
#

o

#

thanks!

static bluff
#

Would you guys mind taking a look?

#

I've made my thoughts on runtime checking fairly plain in the past (I'm in favor). This little setup of code is to validate a dictionary of configuration-settings passed in at startup by the user. It uses beartyping in place of instance checks because beartyping can handle generic types

#

I think this setup will give me a fair bit of flexibility in validating many different types with different requirements

#

I just need to write in the errors

#

If this pans out, I might make it possible to dynamically add new conditions (like the min-length checker). Could be interesting to see

paper echo
#

@static bluff side note: you might enjoy clojure or clojurescript

#

rich hickey feels the same way as you do about static types

#

rather, you might find his thoughts interesting

static bluff
#

Thanks! ๐Ÿ˜„

charred wagon
#

Is it possible to make a type checker think X is a subclass of Y without actually making X subclass Y?

#

Does typing have any mechanism for that?

static bluff
#

That depends on the type checker

charred wagon
#

Hold on

#

Let me rephrase then

#

Is there a consistent, standardised way to do the above?

static bluff
#

Specifically, you're talking subclass and not instance of

paper echo
#

you might need a protocol

grave jolt
halcyon trail
#

does mypy not recognize explicit registration? that's disappointing

paper echo
#
class Thing(Generic[A, B]):
    ...

class ThingLike(Protocol[A, B]):
    ...

# no
def foo(thing: Thing[A, B]):
    ...

# yes
def foo(thing: ThingLike[A, B]):
    ...
paper echo
#

protocols everywhere for everyone

#

more protocols

charred wagon
#

The context is that arrow.Arrow implements the datetime.datetime interface but doesn't actually subclass it. This causes type checkers to complain if I pass the former where the latter is expected. I can't really modify either one unless I monkeypatch.

halcyon trail
#

confirmed, mypy ignores ABC registration

#

yeah, use a protocol

grave jolt
#

yeah

halcyon trail
#

a protocol is basically an interface that the static type checker implicitly checks for satisfaction

#

as opposed to someone having to explicitly declare that the type implements the interface

grave jolt
#

protocols do have some unobvious behaviour, like how a property doesn't satisfy an attribute and vice versa

charred wagon
#

How would I use a protocol?

Third party library has a function that expects datetime.datetime
I use arrow.get() to receive an arrow.Arrow

halcyon trail
#

ah then you're boned

grave jolt
#

yeah

halcyon trail
#

the argument would be, this third party library asked for exactly a datetime.datetime, they annotated it as such

#

so you can't really assume it's okay to pass anything else

grave jolt
#

yep, and they could do something like assert isinstance(foo, datetime.datetime), or later use in a union, which could break stuff

halcyon trail
#

write wrappers that take arrow.Arrow, convert to a datetime.datetime, and call the function ๐Ÿคทโ€โ™‚๏ธ

charred wagon
halcyon trail
#

but yeah this is generally the kind of reason why standard libraries are nice

charred wagon
#

For the isinstance problem I thought of monkeypatching arrow to return an Arrow subclass that has a metaclass with isinstance and issubclass hooks

grave jolt
#

I think writing a conversion function is a simpler solution

halcyon trail
#

yeah

charred wagon
#

Well arrow has arrow.Arrow.datetime but I just wanted it to be more transparent

#

I don't wanna use .datetime every time :(

halcyon trail
#

just alias the type as something locally then?

#

a few extra characters is definitely not worth any sentence with the words monkeypatching, subclassing, metaclass, isinstance, and issubclass all in it ๐Ÿ™‚

paper echo
#

it'd be nice if we had a protocol_from thing

#

ProtocolFrom[datetime.datetime] would mean "treat this as a Protocol but with all the annotations from datetime.datetime"

grave jolt
halcyon trail
#

protocol_from is a nice workaround, but people should probably be programming more against interfaces to begin with

grave jolt
#

well, programming to interfaces everywhere can lead to more complicated code, which wouldn't really look like Python

#

like, imagine if Sir Lancebot applied dependency inversion

halcyon trail
#

out of curiosity, why do you think that?

#

do you think a function is simpler if it says that it accepts List[int] instead of Sequence[int] ?

static bluff
halcyon trail
#

the thing is that in python you're really always programming against interfaces (or almost always), anyway.

charred wagon
# halcyon trail a few extra characters is definitely not worth any sentence with the words monke...

Maybe. With isinstance checks it's frustrating because it goes against duck typing. Here I am with a type that would work totally fine as a replacement if not for that check. It's not even really the libraries' fault because they don't have an easy way to say "I need a type that behaves like datetime.datetime but it doesn't specifically have to be that one". Even with protocols it doesn't fully solve the problem since that cannot encode behaviour.

halcyon trail
#

So cornering the type system and preventing it from doing something properly that you're really already doing seems silly

halcyon trail
#

@charred wagon what do you mean by "protocols cannot fully solve the problem because they cannot encode behavior" ?

#

not exactly. what he's saying is true in the sense that protocols only check for syntax; they check for functions with certain names and certain signatures/annotations.

#

That said the type system just can't check behavior for you

charred wagon
#

If a function has a side effect, a protocol cannot encode that information. So the only way to be sure you'll get a type that performs that side effect is to annotate with that exact type.

halcyon trail
#

if a function has a side effect, the python type system generally cannot encode that information?

#

or maybe I should say, maybe it could in theory, but it just doesn't

#

people don't write python that way

grave jolt
# grave jolt ๐Ÿค”

Well, in case of datetime, you'll need to create your own DatetimeLike protocol or such and specify explicitly the interface of what you're expecting.
So if you accept datetime:
"I accept datetime.datetime"
And if you accept "datetime or the like"
"I accept any object that has these properties: ..., for example a datetime.datetime"

charred wagon
#

Yeah, I know. I'm just justifying the situation with using isinstance

halcyon trail
#

that's what Haskell is for ๐Ÿ™‚

#

I'm just saying the limitations of the type system in terms of not being able to encode all the behavior don't have anything to do with your immediate problem

grave jolt
charred wagon
#

I wasn't trying to say that was the case.

halcyon trail
#

well, you said "protocols don't fully solve the problem", but that problem is completely orthogonal to what protocols are about ๐Ÿคทโ€โ™‚๏ธ

grave jolt
#

speaking of behaviour, even in Haskell you pinky promise that you obey certain contracts when you implement an interface (create instance of typeclass)

halcyon trail
#

Sure, of course

#

If your type system can verify all the behavior then making your types work is the same as writing a working program

paper echo
halcyon trail
#

hey man, this is the internet, you're not allowed to be persuaded about anything...

paper echo
#

i think given the state of python, ProtocolFrom could be a good idea. maybe i'll post on typing-sig or python-ideas

#

i'm sure it's bad for some reason or other

halcyon trail
#

Yeah, it would definitely help given the practical realities of things.

grave jolt
grave jolt
#

like, Pyright is already nearing the lines of code of the Agda compiler

halcyon trail
#

but, to mention again an example I've probably mentioned before, in Kotlin, List and MutableList are interfaces. Nobody really uses the "concrete class" in typical programming. And it's fine.

grave jolt
#

the issue with Python is perhaps that some built-in things (iterables, iterators, callables, etc.) are extensively used in a duck-typed way, but other things (like datetime.datetime) are used in a nominal way, or something like that

halcyon trail
#

can you explain what you mean here by nominal?

grave jolt
#

opposite of structural typing

#

i.e. when you use the concrete type

flat gazelle
#

interfaces are also nominal typing

halcyon trail
#

okay, that's not so much nominal vs structural, but just the fact that they are using interfaces in one case, and concrete classes in the other

charred wagon
halcyon trail
#

if someone annotates with Iterable[int] or something, life is simple because that's not a particular class

flat gazelle
#

the issue is more with open vs closed types, though most python types are at least somewhat open

#

but well, a Protocol or an abc is far easier to implement than a subclass

halcyon trail
#

@charred wagon but that has nothing to do with protocols, the fact that the entire python type system, generally, cannot guarantee behavior.

#

(well, any type system really)

#

even if you annotate exactly datetime.datetime, someone can inherit from datetime.datetime, and have a derived class whose behavior doesn't have the invariants expected by the library

charred wagon
#

Er... I am not saying that it has something to with protocols. I'm saying: we have problem X and Y. Protocols can solve X, but that's 50% of the problem and we're left with Y.

halcyon trail
#

Okay, even then though, Y is just literally an intrinsic problem of all type systems? Not something that libraries need to "worry" about per se... it would just be user error if someone implemented an interface (including behavior) incorrectly ๐Ÿคทโ€โ™‚๏ธ

grave jolt
#

Protocols don't require you to explicitly subclass them/get registered

halcyon trail
#

yes

#

you just implement it, and the static type checker implicitly recognizes that it fulfills the protocol

#

well, sometimes you don't control the class

grave jolt
#

@charred wagon
An interface usually contains the function shapes and some invariants that the implementors promise to obey. Like how Sequences promise that their __len__ returns a number x so that indices [0; x) are valid. Perhaps I'm misunderstanding what you mean?

halcyon trail
#

but then you can register, is the counter-argument

#

in python specifically, protocols make a kind of sense because the "real language", which has no static typing of course, is duck-typed

#

so, it makes a kind of sense, you make the static typing world kind of follow what's already happening in the dynamically typed language underneath

#

In a broader context, yeah, I don't think that structural sub-typing, i.e. python protocols, are a great idea

#

they're featured in Go.

#

and offhand I don't know any other mainstream statically typed language that uses them.

grave jolt
#

OCaml and PureScript, but I suppose that's not very mainstream
also TypeScript, but it's not "real" static typing

halcyon trail
#

i think they probably seemed like an upgrade because in the past, the main thing we've had is inheritance. and inheritance is intrusive. So it can be a big headache if you don't control a class but want to make it satisfy some interface.

flat gazelle
#

clojure's spec is pretty much structural, but it's a question of whether that's a real type system

halcyon trail
#

That said, a bunch of languages now solve that problem in a different way

#

which is they make it explicit, but they allow either the person controlling the type, or the person controlling the interface, to explicitly declare the relation

#

this is what Haskell and Rust and Swift and I'm sure many more languages do

charred wagon
#

That possibly could be represented as types, but the current interface is designed to just return a datetime, which is the same type as aware times.

halcyon trail
#

yeah, this stuff though was designed long before static type checkers though so people didn't really design things with better static enforceability in mind

#

definitely, naive and aware datetimes should be separate types

charred wagon
#

For what it's worth I think naive datetimes are just a bad idea in general

paper echo
halcyon trail
#

that seems like an over-aggressive stance for a library to take, but it could probably work in some cases

#

definitely in some languages/domains that's just not practical

paper echo
#

"shouldn't be that hard" is famous last words though

halcyon trail
#

The good news is that "shouldn't be that hard" mapped to a known problem, so when that problem is solved, we'll have a solution!
The bad news is that it mapped to the NP complete class of problems ๐Ÿ˜ฆ

charred wagon
grave jolt
#

it's when the duck gets hurt and the monkey patches it

halcyon trail
#

If isinstance rejected subclasses though then breaking LSP would be too easy

paper echo
halcyon trail
#

the bottom line is... this stuff is hard ๐Ÿ™‚

paper echo
#

you can use type(x) is Foo otherwise

halcyon trail
#

yeah

grave jolt
halcyon trail
#

well that's the big reason why isinstance is recommended over type is

paper echo
halcyon trail
#

at any rate. I think in the future what can help is the standard library defining more interfaces

#

and encouraging people to use them

paper echo
halcyon trail
#

I mean even now they coudl define ABC's/protocols for datetime stuff, and make their own datetimes inherit/conform to thos interfaces

#

and libraries could actually change their tyep annotations to the interfaces

#

this is actually a non-breaking change since it's broadening

charred wagon
halcyon trail
#

when you say "behavior subtyping" what exactly do you mean? Like, promising that subtypes of an Integer interfaces, have the invariant that x + y == y + x ?

grave jolt
#

maybe it's not that bad though

halcyon trail
#

btw, while I like python's type annotations, and I see the benefit of gradual/optional typing in some cases, conversations like this and coding experiences like this, have convinced me that I'd basically just prefer a statically typed language.
Yes, the gradual typing does give you some options you don't have in a statically typed language. But there's actually a pretty big complexity tax to reconciling two type systems in your language now.

#

I've felt this way for a while, ever since I've tried to use type annotations in non-trivial ways.

grave jolt
halcyon trail
#

that's a very good example

#

let's continue:

def norm(p: Point2D) -> float:
    return math.sqrt(p.x**2 + p.y**2)
#

very very misleading

grave jolt
#

recently pyright disabled narrowing on non-final TypedDicts for a similar reason

#

i.e. when you have ```py
class Foo(TypedDict):
x: int

class Bar(TypedDict):
y: str

def thing(foo: Union[Foo, Bar]):
if "x" in foo:
# it's a Foo
else:
# it's a Bar

class Baz(Bar):
x: str # oops

charred wagon
halcyon trail
#

LSP doesn't enforce identical behavior

#

if the subtype behaved identically then obviously there would be no point in it existing

charred wagon
#

Right, and that's the problem with LSP

halcyon trail
#

that there's no enforcement of what's "substitutable" ?

charred wagon
#

I think it's not clearly defined

halcyon trail
#

It's not that it's not clearly defined

#

it's just that it completely depends on your code

#

it completely comes back to the contract of your interface

grave jolt
#

it's the job of the parent class to define what invariants it has

#

and a subclass is substitutable if those invariants are respected

#

I think that's a reasonable definition

halcyon trail
#

in many cases realistically there aren't even iron clad invariants

#

there's just... desired behavior

grave jolt
#

yeah, well, invariant is a strong word

charred wagon
paper echo
#

i think narrowing on typeddicts is pretty niche anyway and you probably shouldn't be doing it

halcyon trail
#

Amusingly it seems like Liskov's original definition was that the behavior be "identical" which is silly (as wikipedia notes), and Liskov talks a bit about that.

grave jolt
paper echo
#

well yeah in that case there's nothing to narrow

#

i don't think any narrowing is possible in that case, right?

grave jolt
#

๐Ÿค” yeah I guess, it's just that Foo and Bar could have different semantics, so x could mean different things in Foo and Bar, so the matching would've been unintentional (like in Point2D/Point3D)

paper echo
#

how do go and ocaml handle situations like this?

grave jolt
#

I have no idea

paper echo
grave jolt
#

well, the issue is that the programmer might not have considered the fact that Foo and Bar could intersect, because Baz could be defined in a separate module altogether

#

pyright in particular has a philosophy of sticking to the safe side of things, but mypy has the same behaviour

#

(I think, actually, mypy doesn't do TypedDict narrowing at all, even if they're final?)

paper echo
#

would be really useful for working with externally-derived data

#

then again this is where the clojure philosophy of "dont bother using types to represent the domain" comes in

#

you could fetch the openapi schema and wire it up to spec

#

otherwise you have to statically/ahead-of-time compile type definitions from the schema

#

(assuming the API even has a schema which 99% of the time in my experience it doesn't)

grave jolt
#

Is there some standard/good way to make a decorator work for both instance methods and standalone functions? i.e I want to support both of those:

@foo
async def thing(self, bar: Bar, baz: Baz) -> FizzBuzz: ...
@foo
async def thing(bar: Bar, baz: Baz) -> FizzBuzz: ...
paper echo
#

I don't think it matters in most cases

#

As in, you don't need to do anything special to handle either case

#

I think?

#

Not sure if there are issues with unbound methods

boreal umbra
#

I wish type objects supported set notation.

# desired semantics
>>> bool <= int
True
>>> "hello" in str | int
True
>>> try:
...     some_horrible_thing()
... except Exception - AssertionError as e:
...     # idk, but e isn't an assertion error
#

I don't really know what properties I want values returned by type.__or__, etc. to have, though

#

I just know that I want it.

#

though I guess it would have to be backwards compatible with whatever that operator returns in the context of type annotations.

gleaming rover
boreal umbra
gleaming rover
#

althoughโ€ฆ

#

you canโ€™t use sets in except clausesโ€ฆright?

boreal umbra
#

idk

gleaming rover
#

is it not the case?

boreal umbra
#

I think this would involve a grammar change, yes

gleaming rover
#

wouldnโ€™t it be nice

#

if our builtin types were CamelCase too

#

list[int] ๐Ÿฅด

grave jolt
#

I think you can put any expression there

#

!e

try:
    pass
except 420 + 69:
    pass
fallen slateBOT
#

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

[No output]
grave jolt
#

yeah

boreal umbra
#

nice

#

is there a dunder that gets called in that context?

gleaming rover
grave jolt
grave jolt
gleaming rover
grave jolt
#

and, sadly, dynamic isinstance (like with ABCs or runtime-checkable protocols) doesn't work here

gleaming rover
#

that makes sense

elder blade
paper echo
boreal umbra
#

Oh nice!

grave jolt
#

Unions work as well I think

#

Yeah, in 3.10

paper echo
#

cool!

grave jolt
#

@paper echo I actually like your ProtocolFrom idea. It would e.g. make testing code that talks to external services easier

static bluff
#

I'm very happy with today's progress ๐Ÿ˜„

#

I think I'll just write some comments and docstrings, and then I'll be ready to move on to the next thing ๐Ÿ˜ฎ

#

Exciting!

unkempt rock
#

hey

#

is anyone can coding an algo in python for trading futures ?

#

here ?

valid rose
#

pretty sure if someone can do that, they wouldn't be sharing it with others

unkempt rock
#

ahaha

undone hare
#

Hello @unkempt rock, we don't allow for recruitment here, please don't ask people to DM you

unkempt rock
#

ah okay

regal olive
#

Hi guys

#

Can i get a help here for my question

#

[[1, 2, 3, 4],
[5, 6 ,7, 8],
[9,10,11,12]
]

Print the numbers in this above 2D matrix backwards:
Output: 12, 11, 10, 9, 8, 7, 6, 5, 4 , 3, 2 , 1

#

Can you guys please help me on this

unkempt rock
#

you can simply google this

#

plenty of examples available already

sacred yew
#

what have you tried

#

also doesn't belong here anyways

grave jolt
#

Why does Concatenate require that the last parameter is a ParamSpec?

#

Why can't I do this? ```py
def require_auth(
fn: Callable[Concatenate[P, AuthUser], Awaitable[Response]],
) -> Callable[P, Awaitable[Response]]:
...

#

ff?

flat gazelle
#

you cant get + overloading as powerful as in julia in python, since it is a method, not a function

barren aurora
#

if i pass an argument to a function, does that go as a pointer? for example ```py
In [1]: def a(c):
...: del c
...:

In [2]: b = 444

In [3]: a(b)

In [4]: b
Out[4]: 444```, so is like the argument c holding the memory of b, and when you delete it, it deletes just the pointer and not b itself

flat gazelle
barren aurora
#

oh

peak spoke
#

the name gets evaluated to its object and that gets a new local name bound to it

spice pecan
#

del never deletes the object directly

#

It removes a reference, and if that was the last remaining reference, in CPython it will get terminated immediately

paper echo
#

is there some kind of dead code elimination algorithm that can remove "unused" variables like _hy_anon_var_1?

def hailstone_sequence(n: int) -> Iterable[int]:
    while n != 1:
        if 0 == n % 2:
            n //= 2
            _hy_anon_var_1 = None
        else:
            n = 3 * n + 1
            _hy_anon_var_1 = None
        yield n
peak spoke
#

I don't think there's anything that'll automatically remove it because of it possibly being used dynamically but I believe there is a flake8 warning for it

paper echo
#

yeah i am willing to assume that there are no dynamic references to it

#

however if it could be extended to dict lookups with string literal keys, that'd be great

#
def eg():
    _hyx_letXUffffX25 = {}
    _hyx_letXUffffX25['x'] = 5
    return 3

removing _hyx_letXUffffX25['x'] and subsequently _hyx_letXUffffX25 itself would be very useful too

unkempt rock
#

are you trying to reverse obfuscated code? ๐Ÿ™‚

paper echo
paper echo
#

the original code was:

(defn h []
  (let [x 5]
    3))

(defn ^(of Iterable int) hailstone-sequence [^int n]
  (while (!= n 1)
    (if (= 0 (% n 2))
      (//= n 2)
      (setv n (+ (* 3 n) 1)))
    (yield n)))
grave jolt
#

@paper echo some linters can detect unused variables, maybe you could steal an algorithm from e.g. flake8? ๐Ÿ™‚

paper echo
#

i looked in vulture's source i wasn't able to figure out what exactly it was doing. i'll see about flake 8

#

very interesting. fun language, although it's very unstable right now as they progress towards 1.0

#

it's a bit like neovim was before the 0.5 release. the last stable release is now way out of date but they're not really close to releasing 1.0 yet

fallen slateBOT
#

src/flake8/plugins/pyflakes.py line 56

"UnusedVariable": "F841",```
`pyflakes/checker.py` lines 2162 to 2167
```py
def checkUnusedAssignments():
    """
    Check to see if any assignments have not been used.
    """
    for name, binding in self.scope.unusedAssignments():
        self.report(messages.UnusedVariable, binding.source, name)```
paper echo
#

unless flake8 has a python api

grave jolt
paper echo
#

hackless would be ideal. let me see how pyflakes actually does it

#

it looks like it has its own algorithm for figuring out lexical scopes

#

no type annotations in the source code ๐Ÿ˜ฆ

#

oh... FunctionScope is a subclass of dict, that's really simple and makes sense

fallen slateBOT
#

pyflakes/checker.py lines 642 to 652

def unusedAssignments(self):
    """
    Return a generator for the assignments which have not been used.
    """
    for name, binding in self.items():
        if (not binding.used and
                name != '_' and  # see issue #202
                name not in self.globals and
                not self.usesLocals and
                isinstance(binding, Assignment)):
            yield name, binding```
paper echo
#

!e ```python
from dis import dis

def f():
if a:
return 1
elif b:
return 2
else:
return 3

def g():
return 1 if a else 2 if b else 3

dis(f)
dis(g)

fallen slateBOT
#

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

001 |   4           0 LOAD_GLOBAL              0 (a)
002 |               2 POP_JUMP_IF_FALSE        8
003 | 
004 |   5           4 LOAD_CONST               1 (1)
005 |               6 RETURN_VALUE
006 | 
007 |   6     >>    8 LOAD_GLOBAL              1 (b)
008 |              10 POP_JUMP_IF_FALSE       16
009 | 
010 |   7          12 LOAD_CONST               2 (2)
011 |              14 RETURN_VALUE
... (truncated - too many lines)

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

paper echo
#

neat, those are the same almost the same

paper echo
#

not sarcasm

grave jolt
#

I guess it sort of makes sense

paper echo
#

everything else in python is a dict

#

name lookups might as well be, right?

#

why is there an extra

             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

in f?

#

is cpython not able to figure out that this if is "total" and that the function can't proceed past it?

#

i guess it makes sense that it couldn't

grave jolt
#

yeah it sometimes add that just to be sure

#

even if a function only contains a single if-elif-else chain

paper echo
#

i wonder if pypy optimizes away unused assignments

viral osprey
#

hi i have a pyqt question which room should i use?

flat gazelle
viral osprey
#

thx

visual shadow
atomic egret
#

What's the difference between typing.Coroutine and typing.Awaitable?

crystal notch
atomic egret
#

are there some non-coroutines that are still awaitable, or vice versa?

native flame
#

Any object can be made awaitable if its class implements the __await__ dunder

atomic egret
#

so what's special about coroutines?

#

also, does the __await__ method have to be async?

static bluff
#
    # ----------------------------------------------------------------------------------------------
    # ----------------------------- Internal Application File Structure ----------------------------
    # ----------------------------------------------------------------------------------------------
    # IMPLEMENTATION NOTE: bundled '.exe' application prohibit writing internally to the program.
    # In order to write logs and other files, a location on the drive must be chosen. This location
    # defaults to a directory known as the 'external root', and is dynamically created at:

        #   Windows : C:\Users\<username>\Application Support\<application-name>
        #   Linux   : /home/<username>/Application Support/<application-name>
        #   OSX     : /users/<username>/Application Support/<application-name>

    # Many important locations used by Pyscript are relative to this directory, which cannot be
    # created until after the application's name has been collected at startup. They are initialized
    # with null values and are updated when the Application object is created.

    # The user may supply alternative locations as needed.
#

Does this make sense?

flat gazelle
#

why not use appdata on windows and XDG paths on linux.

static bluff
#

๐Ÿ˜ฎ

#

Really, this is the best I could cobble together not having access to a PC or a Linux machine. Just sorta grasping at whatever I can find

#

If you have some wisdom you'd like to pass down I'd be grateful

#

Which reminds me, I need to get my computer here triple bootable. I wanted to last weekend but I didn't have even a single USB drive in the house so I couldn't do linux

flat gazelle
static bluff
#

Sending this your way

#

The actual locations notwithstanding, my logic is sound?

flat gazelle
#

ye, storing files at some location is normal

#

for windows, use %appdatalocal% (or %appdata% if you want to sync across devices)

static bluff
#

Is there any reason I can't just use os.expanduser('~/Application Support')?

flat gazelle
#

because there are standards for where these files should go, to avoid a mess and stay compatible with non standard setups

#

not all users have a home, not all user homes are writable

static bluff
#

praise

#

This is information I've searched for but I've never found

#

I've made a screen shot of the comments you've made pointing to various locations (I hope thats okay, privacy and all)

#

I've got my hands full with another task right now but I'll come back and pester you all for specifics regarding this when the time comes

flat gazelle
#

yeah, that's fine. for linux/unix, freedesktop is what you want, but the docs on windows appdata are a bit sparse, most of what I can find is for C#, and it's a bit hard to infer what to do with that

static bluff
#

Sorry for a rather basic question ๐Ÿ˜

#

Not getting any love in my help channel

#

If I have, say, a bunch of styles I want to describe

class WindowStyle(Enum):
  BORDERLESS: auto()
  THIN_FRAME: auto()
  THICK_FRAME: auto()
  DARK_MODE: auto()

How do I go about exporting each individual flag? Or, do I actually call the WindowStyle class in some way?

radiant fulcrum
#

can it only be one flag selected at a time?

#

or a combo?

static bluff
#

They can be comboed

#

Well, most can. There are multiple types, some bitwise enabled, others containing lots of different data types

radiant scroll
#

I just discovered that python has a frozenset type, I've been searching for how is it useful and the only thing I found was that it's just an immutable and hashable version of set. While this definition does make sense, what's the actual use-case of it? I can't think of any scenario where I'd want to use frozenset instead of a set, or if I needed it to be immutable, tuple, does someone here have some actual example where neither set nor tuple would be a proper type to use, but rather a frozenset would?

flat gazelle
#

I have used it before for storing a set of all combinations

#

you can put a frozenset into a set, and a combination is not ordered, unlike a tuple

radiant scroll
#

but does the fact that tuple is ordered actually prevent some usability here?

charred pilot
#

it's semantics. a combination isn't ordered, but a tuple has order

flat gazelle
#

@radiant scrollwell, consider

{(1, 2)} | {(2, 1)}
#vs
{frozenset((1, 2))} | {frozenset((2, 1))}
#

only one of these results is correct for a set of combinations

radiant scroll
#

oh interesting, that does make sense

#

thanks!

elder blade
#

Hmm, anyone have any tips on typing a decorator?

I have: ```py
_T = TypeVar('_T')

def test(func: _T) -> _T: ...

But this would of course allow any type through
#

Wouldn't def test(func: Callable) -> Callable loose all information regarding return type and arguments?

flat gazelle
#

how about _T = TypeVar('_T', bound=Callable)

grave jolt
#

if you want to be more precise, you can use ParamSpec and friends (PEP 612) from typing_extensions

#

but, as I learned the hard way, it's not as good as in TypeScript

elder blade
paper echo
#

+1 for paramspec!

#

does mypy support it yet? it doesn't seem to work in mypy-play

static bluff
#

I'm having FUNNNNNNN

#

๐Ÿ˜„ ๐Ÿ˜„ ๐Ÿ˜„

#

You dudes have any awesome programming music?

elder blade
#

Hmm, I don't even know if this is possible. But I need to type a function that will return a class. It works somewhat like this: ```py
def test(...): ... # Not sure how to do this

my_type = test(a=int, b=str)

Above is the same as

class my_type:
a: int
b: str

I have working code for runtime.. static type checkers are probably not advanced enough to understand this right?
static bluff
#

Can't you use -> type?

elder blade
#

Yes, but then that is simply type without any annotations.

#

It works kind of like a named tuple, any idea how I can hook into this?

#

I assume static type checkers have special cases for named tuples to support these kinds of things: Point = typing.NamedTuple("Point", [('x', int), ('y', int)])

grave jolt
paper echo
#

if so, you can do this

def test(): -> type[MyBase]:
    ...

MyType = test()
#

oh i see

#

this is for setting annotations at runtime... yeah

#

just use Hy tbh

#

who needs type checker plugins when you have macros?

elder blade
elder blade
paper echo
#

that, or, we need something like Foo = Protocol("Foo", a=int, b=str), like TypedDict and NamedTuple

paper echo
paper echo
#

i don't think you can do this with hy either, without the Protocol thing i demonstrated above

elder blade
paper echo
#

if you had the Foo = Protocol("Foo", a=int, b=str) syntax, you could write a macro that expanded to it, or something

elder blade
#

Macro?

paper echo
#

(in hy)

elder blade
#

Ah lmao

grave jolt
elder blade
#

If you do **kwargs: int it becomes Dict[str, int]

elder blade
grave jolt
# grave jolt I meant in the type hint real

in Python, *args just has a single type for all arguments (like tuple[int, ...]), whereas typescript encodes *args as a tuple with structure, such as tuple[int, str, str, ...]. And these tuple types can be manipulated in some ways

elder blade
#

Hmm, I don't know what I'd prefer honestly

grave jolt
# elder blade Hmm, I don't know what I'd prefer honestly

it would be useful if you could do py class Kwargs(TypedDict): foo: int bar: str baz: Sequence[float] and then ```py
def f1(x: Foo, **kwargs: Kwargs): ...
def f1(x: Foo, y: Bar, **kwargs: Kwargs): ...
...

instead of repeating the kwargs or just slapping `Any`
elder blade
#

Yeah, that would be very nice. Honestly doing it inline would be nice: ```py
def f1(x: Foo, y: Bar, **kwargs: {'foo': int, 'bar': int, 'baz': Sequence[Float]}): ...

#

The thing is though, at this point you should simply have: ```py
def f1(x: Foo, y: Bar, *, foo: int, bar: int, baz: int): ...

grave jolt
#

now imagine that you have 10 kwargs, and they repeat in 6 functions

elder blade
grave jolt
#

like matplotlib and such

elder blade
#

Yeah

paper echo
static bluff
#

Is is DataClass or Dataclass?

elder blade
#

from dataclasses import dataclass

#

I think that you say it verbally as a "Dataclass"

static bluff
#

Danke

static bluff
#

Is there any special protocol I have to follow if I want to create an abstract class designed for use as a type hint?

static bluff
#

I guess that's the word

boreal umbra
#

Can you explain what it is some more?

static bluff
#

Yeah

#

I'm gearing up to crack open and reimplement the beartype library, a runtime enforcement API
A recent addition to beartyping is the 'functional validator', lambda functions dressed up as type annotations which validate according to some kind of value check
My own implementation of this will be the 'Condition' class. It is an abstract class designed to be subclassed and its 'validate' and 'throw_exception' methods overloaded. Subclasses of this class are to be used as annotations on typecheck-decorated functions

#

I havn't started in on this part of the project yet, I'm just writing out a skeleton for now

#

But I'm wondering if there is some special protocol I have to follow for an abstract class designed specifically for typehint purposes

boreal umbra
#

Now that you've explained it, I'm not really sure. I think it would be up to you to develop the type hints and the decorators to interface with one another

static bluff
#

Thankfully I'm not really having to pull anything new out of my butt, just rearrange things a bit

#

But yeah. Beartype probably has some configuartion they've slaved over. I'll just inherit from object for now and get to it when I get to it

#

๐Ÿ˜›

#

๐Ÿ‘

#

Help me rewriting this? I'm having a real tough time finding the right words

#
# --------------------------------------------------------------------------------------------------
# -------------------- Runtime Type and Value Enforcement | The Dataclass Class --------------------
# --------------------------------------------------------------------------------------------------
"""This module contains Pyscript's Enforced class, a mixin class whose objects support annotation
enforcement on a per-attribute basis."""

from typing import Any

class Enforced(object):
    """The Enforced class is a mixin class with an overloaded '__setattr__' method, such that
    annotations on attributes are enforced using the enforcement API."""

    def __setattr__(self, attribute: str, value: Any):
        ...
prime estuary
static bluff
#

Noted!

#

Thanks Spen

deft pagoda
#

do you think this slice should be cached?:

In [36]: slice(None) is slice(None)
Out[36]: False
#

i feel like it's such a common one

#

or like slice(None, -1) and friends

spark magnet
#

slice is hardly ever used, so why cache it?

paper echo
#

does "hello"[1:] not explicitly instantiate a slice?

spark magnet
visual shadow
#

!d slice

fallen slateBOT
#

class slice(stop)``````py

class slice(start, stop[, step])```
Return a [slice](https://docs.python.org/3/glossary.html#term-slice) object representing the set of indices specified by `range(start, stop, step)`. The *start* and *step* arguments default to `None`. Slice objects have read-only data attributes `start`, `stop` and `step` which merely return the argument values (or their default). They have no other explicit functionality; however they are used by Numerical Python and other third party extensions. Slice objects are also generated when extended indexing syntax is used. For example: `a[start:stop:step]` or `a[start:stop, i]`. See [`itertools.islice()`](https://docs.python.org/3/library/itertools.html#itertools.islice "itertools.islice") for an alternate version that returns an iterator.
visual shadow
#

I suppose the issue with caching slice None is that slice(1, None) is different, and so on

#

Which means that slicing is common sure, but slice None not so much, perhaps

deft pagoda
#

i don't know which slices are most common, but my guess is :, ::-1, :-1 , 1:

visual shadow
#

That seems like a good guess to me

paper echo
#

there does seem to be some (very small) overhead:

Python 3.9.4 (default, Apr  8 2021, 21:58:31)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.24.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: text = "hello"

In [2]: %timeit [text[1:] for _ in range(1000)]
123 ยตs ยฑ 4.68 ยตs per loop (mean ยฑ std. dev. of 7 runs, 10000 loops each)

In [3]: s = slice(1, None)

In [4]: %timeit [text[s] for _ in range(1000)]
111 ยตs ยฑ 3.47 ยตs per loop (mean ยฑ std. dev. of 7 runs, 10000 loops each)

In [5]: assert [text[1:] for _ in range(1000)] == [text[s] for _ in range(1000)]
#

12 microseconds over 1000 operations is pretty small, i can imagine why they didn't bother with interning/caching slices

visual shadow
#

Aye, I think it's probably just not used enough in a single code base to make it worth it