#esoteric-python
1 messages · Page 26 of 1
a,b=0,1
x=[]
for i in range(int(input())):x.append(a);a,b=b,a+b
print(*x)```
this is the fibonacci sequence, but im trying to golf it, some advices? this looks too begginer
there's a code golf challenge for the fibonacci numbers that I think would be really similar to that so I'll avoid explaining too much
but it's probably better not to keep a list and just print stuff
ahh because the puzzoles is with a list
but thanks stickie
i could do it shorter
13... characters -
a,b,x=0,1,[]
exec('x+=a,;a,b=b,a+b;'*int(input()))
print(*x)```
why do you need a list
oh
ok i c
is it possible to set something up to run code whenever globals is modified?
Tho this is very wrong
We have done it a few times here but you can swap the globals dictionary with a subclass of it
ooh nice
accidental list(range(2*10**9) almost killed my computer
i do not recommend running that code
i think itd be fine to run that 😉
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 1, in <module>
003 | list(range(2*10**9))
004 | MemoryError
!e list(range(2*10**9)
@astral rover :x: Your 3.11 eval job has completed with return code 1.
001 | File "/home/main.py", line 1
002 | list(range(2*10**9)
003 | ^
004 | SyntaxError: '(' was never closed
@vast basin
for me it automatically kills the process
ye there's a few ways
you can change the type of the globals dict to hook its __setitem__
you could use a tracing function
you could also do bytecode parsing but that gets super complicated when you're dealing with multiple versions of python
hooking the globals type is probably the best/easiest option
yeah last time I did it I used bytecode parsing and it is super portable (real)
Looks good to me.
For me at allocated around 40 gb of memory (considering i have only 16 gb of physical memory)
!epy tree=lambda d:[f:=d,[(f:=f-1,print(f"{' '*f}{'*'*((j+1)*2-1)}"))for j in range(d)]] tree(11)
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | *
002 | ***
003 | *****
004 | *******
005 | *********
006 | ***********
007 | *************
008 | ***************
009 | *****************
010 | *******************
011 | *********************
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/cilatijubo.txt?noredirect
Its just 11 lines and still says too many lines
Guess it also takes \n
That max is set to 10, which is why you get the message, but the truncation logic is wrong and allows 11
It's a bug
bot#2492
92 -> 74
!e
tree=lambda d:[print(('*'*i).center(d*2))for i in range(1,d*2,2)]
tree(11)
@tough willow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | *
002 | ***
003 | *****
004 | *******
005 | *********
006 | ***********
007 | *************
008 | ***************
009 | *****************
010 | *******************
011 | *********************
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ivaqiyalud.txt?noredirect
tree=lambda d:[print(f"{'*'*i:^{d*2}}")for i in range(1,d*2,2)]
63 -> 62 ```py
def tree(d):
for i in range(1,d2,2):print(f"{''i:^{d2}}")
62 -> 59 ```py
def tree(d,i=1):
while i<d2:print(f"{''i:^{d2}}");i+=2
!e 74 -> 41 ```py
i=1
while i<22:print(f"{'*'*i:^22}");i+=2
@quartz wave :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | *
002 | ***
003 | *****
004 | *******
005 | *********
006 | ***********
007 | *************
008 | ***************
009 | *****************
010 | *******************
011 | *********************
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/livaxudoba.txt?noredirect
59 -> 58 ```py
def tree(d,i=1):exec("print(f"{'*'i:^{d2}}");i+=2;"*d)
Single line only(no use of statements and no semi colons)
since when was that a rule
Since now
60 ```py
def tree(d,i=1):exec("print(f"{'*'i:^{d2}}")\ni+=2\n"*d)
:0 soo cool
Ig I should change expected indent to no use of statements
Sopy tree=lambda d,i=1:exec("print(f\"{'*'*i:^{d*2}}\")\ni+=2\n"*d)
ok yes
def tree(d,i=1):exec("print(f\"{'*'*i:^{d*2}}\");i+=2\n"*d)
59
i already have a 58
ah, ok 👍
just slapped some random things together and got tired while writing this, so i didnt completed the code
!e
print((classmethod(type(slice.__mro__[0]).__mro__[1].__doc__).__class__.__name__[8].upper()).__add__(....__repr__()[::-1][-1].lower()).__add__(type(int.from_bytes(b"\xFF\xFF", byteorder="little").__eq__(int(str("190326753248076643792647923649875".__add__("69593707450387")[::-1][-1]))-1)).__name__[-1].__mul__(memoryview(b"69").nbytes)).__add__(chr(memoryview(bytes(int.from_bytes(b"\0x", byteorder="big") & int.from_bytes(b"\0x", byteorder="big"))).nbytes - 9)).__add__(str(['x+=a,;a,b=b,a+b;', '*x']).split("'").__getitem__(int("101", 2).__mul__(int("10", 8).__sub__(int("3F", 16))).__mod__(int("11", 2)).__add__(int("101", 2)).__sub__(4))))
@kindred stone :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello,
Hello,
golfing challenge: invert boolean (true -> false, false -> true)
lambda b:b-1if b else b+1```
!e
print((lambda b:b-1if b else b+1)(True))
@unique heath :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | /home/main.py:1: SyntaxWarning: invalid decimal literal
002 | print((lambda b:b-1if b else b+1)(True))
003 | 0
!e
print((lambda b:b-1if b else b+1)(False))
@unique heath :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | /home/main.py:1: SyntaxWarning: invalid decimal literal
002 | print((lambda b:b-1if b else b+1)(False))
003 | 1
f = lambda b:b-1if b else b+1
f = lambda b:0if b else 1
f = lambda b:not b
f = lambda b:1-b
f = 1 .__sub__
f = 0 .__pow__
import operator as o
f = o.not_
!e
NOT = 1 .__sub__
print(NOT(True))
print(NOT(False))
@languid hare :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0
002 | 1
aw a little slower than denball
f = lambda b:b-1if b else b+1
f = lambda b:0if b else 1
1-b
how thfeuf kc dopes that wokr
!epy print((lambda _:False if _ else True)(True))
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
False
!epy print(not True)
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
False
lambda b:0if b else 1 where
It went on vacation
lambda b: bool(0if b else 1) shorter
Though you can do not b
This is shortest
!epy print((lambda _:~_)(True))
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
-2
thats still True
!e```py
print((lambda :-1if _ else~)(True))
print((lambda :-1if _ else~)(False))
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | /home/main.py:1: SyntaxWarning: invalid decimal literal
002 | print((lambda _:_-1if _ else~_)(True))
003 | /home/main.py:2: SyntaxWarning: invalid decimal literal
004 | print((lambda _:_-1if _ else~_)(False))
005 | 0
006 | -1
how didnt i think of
f = 0 .__eq__
first
its shorter and returns a boolean
!e
f = 0 .__eq__
print(f(True))
print(f(False))
@languid hare :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | False
002 | True
while("False")
this is cursed
yeah got it
it's because an empty string acts like false and a well, not empty string acts like true
(1).__sub__
a,y=map(int,open(0))
print(sum(366 if i%4<1 and(i%100>0 or i%400<1)else 365 for i in range(y-a,y))+1)
anyone know a better way to shorten this further?
removing spaces and brackets firstly
a,y=map(int,open(0)) doesn't work for me, ValueError: invalid literal for int() with base 10: '\n'
:incoming_envelope: :ok_hand: applied timeout to @queen jetty until <t:1681625403:f> (10 minutes) (reason: duplicates spam - sent 4 duplicate messages).
The <@&831776746206265384> have been alerted for review.
you need to pass in input without a newline
I think piping in with echo should work
Only if you add -n, IIRC
a,y=map(int,open(0))
print(sum(365+(i%4<1and i%100>0or i%400<1)for i in range(y-a,y))+1)
the else 366 is necessary
oh wait
yeah that works
ty
i think this works ```py
a,y=map(int,open(0))
print(sum(366-(i%16>i%25<1)for i in range(y-a,y))+1)
maybe not
code
that >< comparison chain is one beauty
i don't think it works

it's designed for the case that i is always a leap year
if i obfuscate my code with pyarmor, the other ppl that executes the code needs pyarmor aswell?
it will be included in a folder called pytransform
using fishhook how can i do this ```py
a = "Hello World!"
print(a) # Hi World!
i cant find it
thanks that'll work
its actually perfect
reimplementing std library
def isinstance(a, b):
if type(b) == tuple:
return any(c in type.mro(a.__class__) for c in b)
else:
return b in type.mro(a.__class__)
a=type(int|str)
def i(i):
if isinstance(i,a):return i.__args__
if not isinstance(i,tuple):raise TypeError("isinstance() arg 2 must be a type, a tuple of types, or a union")
i,u=[i],set()
while i:
for e in i.pop():isinstance(e,a)and(e:=e.__args__),i.append(e)if isinstance(e,tuple)else u.add(e)
return u
def u(i,u):
try:return getattr(i,"__instancecheck__")(u)
except:0
def isinstance(e,o):return any(a in type(e).__mro__ or u(a,e)for a in([o]if type in type(o).__mro__ else i(o)))
lol thanks
I dont think this is correct
Types are compared by id, not by ==, so there might be a problem with metaclasses
And you are not taking into account __instancecheck__
как быстро выучить python? помогите, господа
Wrong channel. Ask in #python-discussion
ok, sorry
This is really hard to understand but it is very cool!
!rule 4
4. Use English to the best of your ability. Be polite if someone speaks English imperfectly.
ok how the hell does this new impl work
ooh that one is a fun one. there is no verification that the tuple used by partial to store args is the same length as when the function started inside of the partial.__repr__. basically like this: py def __repr__(self): args_len = len(self.args) for i in range(args_len): add_to_str(repr(self.args[i]))
so WeirdRepr replaces the tuple with a specific pair of items (a tuple and an array's backing right after each other)
and then partial tries to call tp_repr on the items located in that array backing because the new tuple is shorter
so you can make a fake instance of Fake with a custom address in its slots and use that to fake an arbitrary object
*and get a reference to it
its probably the most contrived exploit i have written
Meanwhile I might have to use your getmem impl at work
oh god
My supervisor asked me for a task that python doesn't really support out of the box
But using memhax I could accomplish it :)
Unfortunately most systems run windows so no /proc/self/memory for me to use
im really curious about what the task is tbh
and also i would recommend writing a C extension over using memhacks. that would be more stable
Unfortunately company policy is that we cannot compile any native tools ourselves nor use native tools that aren't whitelisted
Ah yes, writing x86, my favorite
Honestly I can't wait for CPUs to switch to ARM (they won't, but I pray every night they do)
also if you actually need to get the memory of the entire process, I would use ctypes instead of any of my bugs. ```py
from ctypes import c_ubyte
import sys
mem = (c_ubyte * sys.maxsize).from_address(0)
that would be more stable then any bug would be
*stable is relative with memhacks tho
I'm not sure how much of this is NDA but it involves being able to call pandas methods on regular python objects, e.g. list.map(...)
i mean fishhook would work for that but you said you can't non-whitelisted software
makes sense tbh
Oh actually forbiddenfruit has a funny way to bypass mappingproxy
does it use the __req__ trick?
def patchable_builtin(klass):
refs = gc.get_referents(klass.__dict__)
return refs[0]``` this returns the dict backing the class' mappingproxy
req?
just normal methods not any dunders?
A few dunders sadly which is gonna be a little tricky but not impossible
But what's this req thing you're talking about 👀
!e ```py
def getdict(cls, E=type('',(),{'eq':lambda s,o:o})()):
'''
Obtains a writeable dictionary of a classes namespace
Note that any modifications to this dictionary should be followed by a
call to PyType_Modified(cls)
'''
return cls.dict == E
print(getdict(int))```
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
{'__new__': <built-in method __new__ of type object at 0x7f8c9fc579a0>, '__repr__': <slot wrapper '__repr__' of 'int' objects>, '__hash__': <slot wrapper '__hash__' of 'int' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'int' objects>, '__lt__': <slot wrapper '__lt__' of 'int' objects>, '__le__': <slot wrapper '__le__' of 'int' objects>, '__eq__': <slot wrapper '__eq__' of 'int' objects>, '__ne__': <slot wrapper '__ne__' of 'int' objects>, '__gt__': <slot wrapper '__gt__' of 'int' objects>, '__ge__': <slot wrapper '__ge__' of 'int' objects>, '__add__': <slot wrapper '__add__' of 'int' objects>, '__radd__': <slot wrapper '__radd__' of 'int' objects>, '__sub__': <slot wrapper '__sub__' of 'int' objects>, '__rsub__': <slot wrapper '__rsub__' of 'int' objects>, '__mul__': <slot wrapper '__mul__' of 'int' objects>, '__rmul__': <slot wrapper '__rmul__' of 'int' objects>, '__mod__': <slot wrapper '__mod__' of 'int' objects>, '__rmod__': <slot wrapper '__rmod__' of 'int' ob
... (truncated - too long)
Full output: https://paste.pythondiscord.com/ahasajetix.txt?noredirect
mappingproxy.__req__ dispatches to dict.__req__ on the wrapped dictionary
Lmao
and dict.__req__ calls arg.__eq__(mp)
if you want i can send you some sample code which is basically smaller fishhook with only attr hooking (no orig or anything else)
Honestly at this point I want to just drop my work and look through the interpreter to see just how many ways we have to bypass mappingproxy and/or access raw memory
there are a lot, i have a few really neat ones that work on <=3.11
involves the GC being called in odd places
not that I have found, but thats because I only really look at cpython
other impls would have different bugs in different places probably
I wonder if pypy allows for the extended_argument exploit
no idea
i can look
*but pypy does not implement id the same way so you would need to get an info leak as well
dang
it does not, it has partial's implemented differently
Oh I was talking about the 256 bytecode one from a while back
ohh the custom code object one
you can crash it
but its a different exploit process to get it stable
wait, __req__ exists? 🧐
*it does not technically
but __eq__ still does reverse dispatch
could you mess with python to make the syntax like javascripts?
etc. True is true
{} for code blocks
and are there any tutorials or books to learn more about esoteric python and code golfing
im very interested in hooking
well yeah that's obvious
probably doable with a custom codec
Custom codec, custom import hook for preprocessing, patching compiler at runtime
Just some ways you could probably do it
what about this?
The Abstract Equality Comparison Algorithm but Python - aeca.py
you could implement that via fishhook to avoid the Illegal hardware Instruction issue. And you would not have to deal with ctypes directly
no Illegal hardware instruction for me which is good
this is hell ```py
[] == []
False
how wtf
nvm i tried to execute some other code and got an illegal instruction error
can you modify the code of functions from modules you imported
depends on the module
for example
colorama
if u wanted green u would do colorama.Fore.GREEN
but
nvm thats a bad example
i just want to change the code of functions in a module
If it's a module implemented in Python, then yes.
its a third party library
That doesn't matter, it just matters whether it's Python or something else (like an extension module written in C, for example)
ah i misread i thought you said implemented by python
thanks that looks pretty good
i get this error when importing: py from asm import Deserializer, LOAD_CONST, CALL_FUNCTION, POP_TOP, Serializer, RETURN_VALUE, LOAD_FAST ModuleNotFoundError: No module named 'asm'
fixed it but now i get this error.. py ALL_OPS = {v: eval(k) for k, v in opmap.items()} ^^^^^^^ File "<string>", line 1, in <module> NameError: name 'CACHE' is not defined
which python version
py 3.11.2
hm
you don't have pyasm installed which it depends on
which is strange considering it's a required dependency
for some reason when i installed pymixin, no other modules were installed
3.11+ isn't fully supported yet, try 3.10
if you forbid __ in input, can you still eval arbitrary code? py inp = input('> ') if '__' in inp:exit('fail') else:eval(inp, {'__builtins__':{}}) I have been trying some stuff, wondering if i am missing something simple
eval(chr(...)+chr(...)+...)
no builtins ^
{'__builtins__':{}} this makes it so python doesn't add in its builtins
so you can't access __subclasses__ on something to get to a useful class
i can do something stupid like 10**10**10**10
there is some package that can execute code safely
it basically forbids dunders and some builtins
what package?
i dont remember
ah that evals ast
im more curious about bypasses for just blocking __ and all builtins
Ik there are some exotic ones
but wondering if there are any simple ones
no, it is not the package i am thinking about
i cant find it, but i remember that it is evaluating string using eval with no builtins after checking that code has no suspicious expressions (such as dunders)
ill keep looking for it. can you think of any bypasses?
no, this package has many stars on github and i dont think there were any vulnerabilities
so blocking __ and builtins is enough
if you can find that project can you send me a link?
without dunders and builtins you can get only builtin objects (int, strings, lists, ...) and call theirs methods
there is no way to get reference to any class, because you cannot do type(...) and .__class__
funny way to get bytes object that contains numbers from 0 to 255: b''.maketrans(b'',b'')
!e assert b''.maketrans(b'',b'') == bytes(range(256))
@fleet bridge :warning: Your 3.11 eval job has completed with return code 0.
[No output]
clever
awesome thanks
I think it is possible to replace all literals (strings, lists, ints, ...) with our new fully compatible reimplementation of these classes, but with additional restriction on length of these objects. So 10**10**10**10 or [1]*10**10 doesn't explode but raises some exception.
You can replace literals by ast modification.
Maybe you also should wrap all calls, getitems and getattrs into wrapper that returns "restricted" objects instead of raw ints/lists. You also should disallow shadowing your wrapper function.
You should make sure that there is absolutely no way to get raw unrestricted objects.
where's the fun in that smh
probably not, but its still not a good idea to let things like that get into your locals
even if you delete __builtins__, your other vars are still available in that context
better to just entirely nuke python out and implement a pure math expr parser
Hey, I wonder what are you working on?
x={"FIRE":"WATER","WATER":"EARTH","EARTH":"FIRE","FRIEND":"HEAL","FOE":"ATTACK"}
for i in range(int(input())):t,e=input().split();print([f"{x[t]} {x[e]}",f"{x[t]} {e}"][t[1]=='R'])
Ik, the goal is to build a challenge where the goal is to break out
but if you pass globals={'__builtins__': {}} you cannot access the upper scope vars directly
oh right, it overwrites
hesitant to say impossible, but i don't see a way to do it
you have nothing to help you escape, just standard python syntax
no functions
jail.py
import builtins
# remove all the stuff we don't need
for key in vars(builtins).copy():
if key not in {'input', 'print', 'Exception', 'repr', 'eval'}:
del builtins.__dict__[key]
del builtins
while True:
try:
inp = input('>>> ')
for blocked in {'__', ':', ' ', '\t', '\n'}:
if blocked in inp:
raise Exception('Invalid Input')
else:
print(repr(eval(inp, {'__builtins__': {}})))
except Exception as e:
print('Error', e)
``` this is the current jail
it is possible to break btw @vast wave
just tricky
how
@fleet bridge @quartz wave challenge for yall ^
what's your idea?
lemme test it
send it with spoiler tags when you do
nvm
doesnt work, the other solution would be invalid
yeah no i dont see a way to do it
what's the solution
i'm not gonna say until more time has passed
@versed eagle @dry mirage you might also want to try this challenge ^
it just crashed my process (maybe because of a lot of my custom REPL stuff)
i will try that challenge without this: ```py
for key in vars(builtins).copy():
if key not in {'input', 'print', 'Exception', 'repr', 'eval'}:
del builtins.dict[key]
you shouldnt run it in a repl. just python3 jail.py. It calls input to get user input
yeah, in this case it works 👍
yea the builtins clearing messes with a lot of repl stuff
but it also makes the challenge more difficult
Same code with some convenient features (better errors and ingoring empty lines): ```py
import builtins
remove all the stuff we don't need
for key in vars(builtins).copy():
if key not in {'input', 'print', 'Exception', 'repr', 'eval'}:
del builtins.dict[key]
del builtins
while True:
try:
inp = input('>>> ')
if not inp:
continue
for blocked in {'__', ':', ' ', '\t', '\n'}:
if blocked in inp:
raise Exception(f'Invalid input: {blocked!r}')
else:
print(repr(eval(inp, {'builtins': {}})))
except Exception as e:
print('Error:', e)
Nice, ill add that to mine
I can also host this somewhere so that it can be accessed via netcat
i wonder if replit would let me
i wonder if it is even possible to create any dict except for empty one
comprehensions can be done like this: [(x)for(x)in[1,2,3]]
no statements are allowed (because of no and :)
wait, it is eval, so anyway i cannot use statements
no walrus, no lambdas, no dunders
empty set: {1}&{2}
some dicts can be made like this: ```py
''.maketrans('13','24')
{49: 50, 51: 52}
another way to create dicts: {}.fromkeys({1,2,3})
>>> {}.keys().mapping
mappingproxy({})
if you store the dict somehow you can add and remove items with update and pop/remove
arbitrary dicts:```py
[(d.update([('a','b')]),d)[-1]for(d)in[{}]][0]
{'a': 'b'}
list comprehension is used for assignment
string with dunder: '_''_init_''_'
>>> type('',(),[(d.update([('_''_init_''_',[].append)]),d)[-1]for(d)in[{}]][0])()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list.append() takes exactly one argument (0 given)
>>> type('',(),[(d.update([('_''_init_''_','{}'.format)]),d)[-1]for(d)in[{}]][0])()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: Replacement index 0 out of range for positional args tuple
>>> type('',(),[(d.update([('_''_init_''_',''.format)]),d)[-1]for(d)in[{}]][0])()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'str'
``` bound functions are not descriptors, so i dont know how to capture self (if we figure out how to get `type`)
like i said, its tricky
this is hard, i like it
TIL int.from_bytes accepts any Iterable[int]: ```py
0 .from_bytes([1,2,3,4])
16_909_060
thats interesting i didn't know that
i figured out how to get some code object and some frame object
how?
generators
noice
so i think i can construct almost any code object
AttributeError: attribute 'f_code' of 'frame' objects is not writable
😭
i also can do iter(x)
did you get a reference to iter? or using a listcomp?
>>> g=((0)for(_)in[0])
>>> g.gi_frame.f_locals
{'.0': <tuple_iterator object at 0x000001875C267EB0>}
>>> g.gi_frame.f_locals['.0']
<tuple_iterator object at 0x000001875C267EB0>
oo okey
whats the goal
get arbitary code exec from the limited eval
okey
i have access to globals() and to globals()['__builtins__'] so i can add arbitrary vars to global and builtin scopes
@fleet bridge when you solve it make sure to spoiler
it is ok that i am posting here some thoughts?
ooh is there a challenge somewhere
yea thats all good
there
#esoteric-python message @languid hare
run it as python3 jail.py, the goal is to get full code exec from the limited eval
ah
how to create new global var: ```py
[()for(d)in[(()for()in()).gi_frame.f_globals]for(d['var'])in['value']],var
([()], 'value')
you're a genius
im definitely stealing that
.replace()
that would give you a new var just in that one line since globals are a new dict on every run
yes, but you can use it instead of walrus to make arbitrary complex expression with assignments
true, it does allow for more complex expressions
replace returns a new code object so you would have to find a way to assign it somewhere
any of these things will lead to breaking out of jail: getattr, type, <global frame>, 1 allowed dunder
maybe reference to any python function, but im not sure
type alone would allow escaping from jail?
like this
you don't have dunders tho so you can't get to useful ones like FrozenImporter
ah, you can get frametype, generatortype and construct new generator with arbitrary code
and you can't make methods
gonna try this hold on
!e py type(()for()in())()
@rugged sparrow :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 1, in <module>
003 | type(()for()in())()
004 | TypeError: cannot create 'generator' instances
which version
have you bypassed it? @rugged sparrow
yes
reference to almost any module would also be very useful
could i know it secretly
nope, you gotta solve it
it was worth a shot
just to be clear, is the goal builtin retrieval
i think the goal is to do os.system('...') or eval('...') or exec('...')
kay
yea that is the goal
my POC does os.system
actually I would say that the goal is just os.system or something similar
How to get any char if you know its ord():
>>> ord(':')
58
>>> '\0'.translate([(d.update([(0,58)]),d)[-1]for(d)in[{}]][0])
':'
wait, it can be done in a lot easier way: ```py
'\x3a'
':'
that will help once you have eval in order to get imports working again
i'm giving up, i'll try it tomorrow
@earnest wing lmk how far you get
well I think I know a way of getting dunder methods
yeah, should be pretty doable from there
What's your strategy?
||__dunder__|| ||second character is not an underscore||
oh that is not an intended solution
wtf
but fair enough
(those will be blocked in the next one tho)
classic pyjail cheese lmao
haha, did sort of feel like cheating :P
||this doesn't work (but should, so im looking into that now)||
you can do 1 .__dunder__ to save a char
ah
that trick also does not work after the builtin clearing
||i assume because it tries to import some encoding corrector (but that fails due to lost __import__)||
Ah interesting
that makes sense
yea it attempts to import unicodedata
so the cheese does not work thats good
but ill explicitly block that on the next one
@sudden osprey thanks tho, the next one will have this: inp = normalize('NFKD', input('>>> '))
to avoid the odd error, this is the new challenge code
import builtins
from unicodedata import normalize
# remove all the stuff we don't need
for key in vars(builtins).copy():
if key not in {'input', 'print', 'Exception', 'repr', 'eval'}:
del builtins.__dict__[key]
del builtins
while True:
try:
inp = normalize('NFKD', input('>>> '))
if not inp:
continue
for blocked in {'__', ':', ' ', '\t', '\n'}:
if blocked in inp:
raise Exception(f'Invalid Input {blocked!r}')
else:
print(repr(eval(inp, {'__builtins__': {}})))
except Exception as e:
print('Error', e)
``` @sudden osprey
i got distracted
fair enough
but not far, mostly toyed around with ||generator frames / code objects||
as well as the funny ||.0 local||

|| youre close there ||
im trying to think of a way to bypass " "
in my string
starting to think its impossible
i guarantee it is not impossible
i got rce
send me your impl, Im curious about your exploit path
you can dm it or just spoilertag it here
"\x20"
yeah i got it
||my attempt was to use load_module but of course that uses __import__ so didnt work||
what is this channel for?
python weirdness
hm
yea i have something i guess
Ive shown this before in #python-discussion and in #1035199133436354600 but im wondering if the people who frequent here can help because i cant get W H and all the other letters
its only using class conversion so
i cant use and functions
what's "break" btw
out of curiousity, how would type help you if you got it out of the string?
i forgot

||do type({}) to get dict, then you can make a class and assign it "arbitrary" members (except it wouldn't help you create functions either..)||
yea i am making another jail where you can make classes off the bat (i provide a function for it) but it doesn't make it any easier (hopefully, this new one is supposed to be more difficult)
Okay, I figured out how to set global variables. Not sure if that helps me yet :D
can you share your way for setting globals?
this is my
||```py
'{x.class.base.subclasses}'.format(x=())
<built-in method subclasses of type object at 0x00007FFED0B78DF0>
probably custom terminal stuff?
@half escarp :x: Your 3.11 eval job has completed with return code 143 (SIGTERM).
001 | Error name 'getattr' is not defined
002 | Error name 'getattr' is not defined
003 | Error name 'getattr' is not defined
004 | Error name 'getattr' is not defined
005 | Error name 'getattr' is not defined
006 | Error name 'getattr' is not defined
007 | Error name 'getattr' is not defined
008 | Error name 'getattr' is not defined
009 | Error name 'getattr' is not defined
010 | Error name 'getattr' is not defined
011 | Error name 'getattr' is not defined
... (truncated - too many lines)
Full output: too long to upload
Try to spoiler tag solutions
there ya go
that solution uses the intended strategy of || using generator frames to step out to the main frame||
||.f_back||?
is it supposed to be ran on a file to make it work?
this is a very version specific solution
doesn't work in 3.11
||had to adjust offset by 1 backwards||
Yea you run the code as jail.py
i put it in the REPL
Ah yea that won't quite work
I mean it's still escapable but the repl makes it a degree easier
Certain stuff is initialized upon entering the repl that puts a lot more things into local scope
aren't all those wiped out by the 2nd argument to eval()
||no-offset|| way ||```py
[*([x.append(((x[0].gi_frame.f_back.f_back.f_globals)for()in((),)))or(x[0])for(x)in[[]]][0])][0]["\x5f\x5fbuiltins\x5f\x5f"].eval('((x.{0}call{0}.{0}globals{0})for(x)in"".{0}class{0}.{0}bases{0}[0].{0}subclasses{0}()if"{0}globals{0}"in(x).{0}call{0}.{0}dir{0}()).{0}next{0}()["sys"].modules["os"]'.format('\x5f\x5f')).system
||Part of the challenge is getting os.system after breaking out of the eval||
The one I am working on right now will definitely not work in the repl and should be way more difficult then this one
eh idk
Sorry, I meant builtins.
||.setdefault with the globals from the frame of a generator comprehension||
my code also can set builtins
what the fuck
i was gone for one day
is there a way to obfuscate function kwarg names
func(OBFUSCATED_NAME="Hi")
``` OBFUSCATED_NAME will be interpreted as another name inside func
thats my goal
just pass in **{}
worked thanks
yea people here work fast
could you call __import__ by string using generator frames, like in here with builtins (i could probably use this method and getattr but there could be a better way)
it doesnt need to be using generator frames
# .env
SENSITIVE="sensitive data" #\n
MORE="more data"
read_dotenv=lambda k: [v[1]for l in open(".env", "r")if (v:=l.replace("\n", "").split("="))[0]==k]or None
assert read_dotenv("SENSITIVE") == "sensitive data"
assert read_dotenv("MORE") == "more data"
assert read_dotenv("NON_EXISTENT_KEY") is None
looking to shorten this
__import__ is removed from builtins so you would have to find a frame that stored it in globals
hm; got it 🙂
assert all((read_dotenv(x)==y for x,y in zip(("SENSITIVE","MORE","NON_EXISTENT_KEY"),("sensitive data","more data",None)))```
Might actually be shorter without the zip, not sure
Not strictly the same, but would give the same result (one assert instead of 3, and does ==None instead of None)
these asserts where there just to tell what are the expected results of the function, i was looking to the actual implementation of read_dotenv being shorter
Well you've got a space after the if that can be removed to begin with
You also don't need the , "r" in the open() since r mode is the default
your code fails your asserts :/
because of comments
:^)
exec(open('.env').read()) read_dotenv=lambda x:globals().get(x,None)
sure
actually
exec(open('.env').read()) read_dotenv=globals().get
not in the spirit of what you want, but passes your tests
none of my tests passes on my own function🤦♂️
i wrote them right before sending and didnt tested them, mb
only the last one that checks for None works 😆
this works pretty well, nice catch
yeah
if you dont set the variables with quotes it wont work
but its nice for what was proposed
just don't use it in any real code...
obviously
is hexadecimal good enough string obfuscation for scanners
What Scanners
there are no specific ones, im just trying to avoid regex patterns by obfuscating strings (in this case im obfuscating "__builtins__")
yet i have no clue what is good enough
Why do you want to do that
to avoid regex patterns
im learning evasion techniques
Evasion for what
I don't know what you are talking about, sorry
idk the proper term for it
im bored
def print(*args, sep=" ", end="\n", file=None, flush=False):
if not file:
file = open(1, "w")
file.write(sep.join(map(str, args))
file.write(end)
if flush:
file.flush()
def input(prompt=''):
return open(0).readlines(1).strip("\n")
implement type and object
from posix import * is your friend
I guess that wouldn't work on windows
🧐
!e @fleet bridge researching building functions without functions as I build another challenge: || py print([ [ SumArgs.append((1,2,3,4))or(SumCall(None)), SumArgs.append((5,6,7,8))or(SumCall(None)), ] for(SumArgs)in[[]] for(SumCall)in[( [ temp.insert(0,temp.pop()+arg) for(arg)in(args) ]and(temp[0]) for(args)in(SumArgs) for(temp)in[[0]] ).send] ]) ||
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
[[10, 26]]
iirc there's implementations of it for windows (wrappers on whatever library windows uses)
or a vm
had to delete and resend to run !e
✨
I hate that. My brain melts
abusing generators for fun and profit 🙂
for the next one you will have to build functional classes using that strategy
Now i understand how your code does what it does. It is very tricky
Right now I'm trying to research how to build a wrapper so that arguments and execution can happen at the same time like a regular function
SumArgs is changing size, and at the same time you are iterating over it. Why it is not causing any exceptions?
Or changing container size is forbidden only for dicts?
Changing the container size is only forbidden on types where it's dangerous
So, dicts + sets + frozensets?
Yes
Although there's a trick where you can actually change the values of a set while iterating over it
But you run into implementation quirks of the underlying Hash table
Like you can only swap out eight items
I'll dig around and see if I can find the code
can someone help with this
are you obfuscating the string or the thing itself
string
whats the regex you're trying to avoid matching
pretty hard to avoid matching a regex if you don't know what it is
Docs says that objects equality should imply hashes equality. What if our object is returning different hashes?
I can put two objects that returns hashes 1 and 2, then do 🪄 and then their hashes are now 2 and 1 (instead of 1 and 2). And if i try using one object as key i will get value corresponding to other key.
I think y'all can make a lot of fun with that
i dont have the regex but i know that it checks for dunders, hexadecimal string and getattr
i have a way to get __import__ but i cant access the attributes because getattr is blocked
and the attribute itself is blocked
use "\x5f\x5fbuiltins\x5f\x5f"?
vars(obj)[attrstr]
thats hexadecimal
You can scroll up a bit and find code that can execute arbitrary code and has no dunders or getattr
I posted a small code that constructs one char string from its ord
You can combine these ideas
i'll have a look and thanks @versed eagle that will work i think
does it also work for subprocess?
i need Popen
you probably don't
You can do os.system(py -c 'import subprocess') or something
from posix import * is your friend
or nt if you're on windows ig
actually why not just import builtins
ill try other ways first
doing that seems lazy imo
octal is, not sure about binary
doesnt octal use hex?
Wdym by "hex"?
actually nvm
hexadecimal
how do I code a bonzi buddy
but one I can set to any picture I want
you know
like a desktop stripper
octal is base 8, hex is 16
esopy challenge:
golf an accurate version of print
def print(*a,s='',e='\n',p=0,o=0):(f:=open(p,'w'),f.write(s.join(map(str,a))+e),f.flush()if o else ...)
``` 1liner
102 chars
yes
fine
def print(*a,sep='',end='\n',file=0,flush=0):(f:=open(file,'w'),f.write(sep.join(map(str,a))+end),f.flush()if flush else ...)
Why ```py
sep.join(map(str,a))
Cant we just do
```py
sep.join(a)```
!e
print(''.join([1,2,3,4]))```
@unique heath :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 1, in <module>
003 | print(''.join([1,2,3,4]))
004 | ^^^^^^^^^^^^^^^^^^
005 | TypeError: sequence item 0: expected str instance, int found
Ok
!e ```py
def print(*a,sep='',end='\n',file=0,flush=0):(f:=open(file,'w'),f.write(sep.join(map(str,a))+end),f.flush()if flush else ...)
print(5, 6, 7)
@quartz wave :warning: Your 3.11 eval job has completed with return code 0.
[No output]
wth
!e ```py
def print(*a,sep='',end='\n',file=0,flush=0):(f:=open(file,'w'),f.write(sep.join(map(str,a))+end),f.flush()if flush else ...)
print(5, 6, 7, flush=1)
@quartz wave :warning: Your 3.11 eval job has completed with return code 0.
[No output]
ok it doesn't work in the sandbox
!epy import sys sys.stdout.write('blah')
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
blah
!epy print(open(0))
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
<_io.TextIOWrapper name=0 mode='r' encoding='utf-8'>
oh they have the fd wrong
corrected (not golfed) ```py
def print(*a,sep=' ',end='\n',file=1,flush=0):(f:=open(file,'w'),f.write(sep.join(map(str,a))+end),f.flush()if flush else ...)
1 and 0? Where do they lead?
golfed ```py
def print(*a,sep=' ',end='\n',file=1,flush=0):(f:=open(file,'w')).write(sep.join(map(str,a))+end),flush and f.flush()
0 - stdin
1 - stdout
2 - stderr
I thought 0 leads to stdout
Though you forgot to close tuple
what tuple
if i add a parenthesis at the end then i forgot to start a tuple
Nevermind got it
can't you do f=open(...);f.write(...)
yes
Arguably using 1 for the file would not be correct. Default print always uses whatever file is in sys.stdout
Also, the file argument is meant to take a file object, not a path
I don't think anyone really thought too hard about hashing slices, especially since you can just use a tuple and seq[slice(*tup)]
my_dict["key_a":"key_b"] would make a copy with just the items from key a to b (in insertion order)?
!e you can make slices with mutable items in them: print(slice([],[],[]))
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
slice([], [], [])
wouldnt it make sense though if the underlying items are hashable to have them be hashable much like MappingProxy
You also can make tuples with mutable items, but tuples are hashable if all items are hashable. Slices are always unhashable
There was some discussion about slice hashability in #internals-and-peps
fair enough
!e @fleet bridge figured out that multiple loop comprehensions can modify prior variables so Sum is neater py print([ [ SumCall(SumArgs.append((1,2,3,4))), SumCall(SumArgs.append((5,6,7,8))) ] for(SumArgs)in[[]] for(SumCall)in[( [ (sum) for(sum)in[0] for(arg)in(args) for(sum)in[sum+arg] ][-1] for(args)in(SumArgs) ).send] ])
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
[[10, 26]]
specifically to prevent dict slicing I would assume, since that can be a nasty footgun
a slice is just an object so it should have no special treatment there, but also there may be an implicit assumption that slicing "works" on dicts
this can create silently incorrect, innocuous seeming programs which is not super nice
how would dict slicing even work lmao
like ‘i want everything from ‘banana’ to 13.12’
since dicts are ordered now you could theoretically slice like that consistently, but still it would be unintuitive
yeah i guess but you could simply slice through the keys or values tbh
yea it would not be a smart feature
now imagine set slicing lmao
!e ```py
from fishhook import hook
@hook(int)
def getitem(self, idx):
return int(str(self)[idx])
print(12345[2:4])```
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | /home/main.py:7: SyntaxWarning: 'int' object is not subscriptable; perhaps you missed a comma?
002 | print(12345[2:4])
003 | 34
it might be more useful to check what representation the int used
since presumably if the user does 0b01010100[::-1] (84), they want 0b00101010 (24) as a result, rather than 48
!e ```py
from ctypes import CFUNCTYPE as y,cast as x,c_int as n,c_ssize_t as e,c_void_p as k,py_object as b;a=k16;z=a.from_address;i=z(z(id(list))[13]);u=x(i[5],y(n,b,e,b));e=x(i[3],y(b,b,e));i=a();z(id(int))[14]=x(i,k);i[:3]=0,x(y(b,b,b)(lambdaa:e(*a[::~0])),k),x(y(n,b,b,b)(lambda a,i,e:u(i,a,e)),k)
arr = [2, 3, 4, 5]
1[arr] = 2[arr]
print(f"{arr = }")
print(f"{0[arr] = }")
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | /home/main.py:4: SyntaxWarning: 'int' object is not subscriptable; perhaps you missed a comma?
002 | 1[arr] = 2[arr]
003 | /home/main.py:7: SyntaxWarning: 'int' object is not subscriptable; perhaps you missed a comma?
004 | print(f"{0[arr] = }")
005 | arr = [2, 4, 4, 5]
006 | 0[arr] = 2
real C
yeah honestly seems to be no other reason than they didn't want slices in dicts, but there are other ways to implement that in dict, I don't see why the implementation is on slice
@fleet bridge if you want another challenge, I submitted one to hack the box: https://app.hackthebox.com/challenges/fake-snake
@dry mirage ^ you also might like this one
thanks defender 😔
It seriously flagged nc?
here's a different style of problem with a pretty obvious solution if you know the trick
while 1:
try:
for c in(i:=input('>>> ')):
if ord(c)<256:raise Exception(f'Invalid Input {i!r}')
print(repr(eval(i)))
except Exception as e:print('Error: ', e)
(get arbritrary os.system)
neat
Can you post challenge description here please?
how do you get builtins using "__builtins__" string?
generator frames arent allowed
!epy print(globals()['__builtins__'])
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
<module 'builtins' (built-in)>
i shouldve mentioned this too but globals is also not allowed
Ok
!epy print(locals()['__builtins__'])
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
<module 'builtins' (built-in)>
that too
eval('__builtins__')?
eval/exec is blocked
theres a lot of things ive tried
You are randomly creating rules
?
those were pretty obvious
thats why i didnt say
no, they weren't
u think eval isnt obvious?
yes
okay.
i think i found a solution
!e
import random
print(
getattr(random, '__builtins__').keys()
)
@tough willow :white_check_mark: Your 3.11 eval job has completed with return code 0.
{'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>,
... (truncated - too long)
Full output: https://paste.pythondiscord.com/nipajoduva.txt?noredirect
!e
import random
print(
getattr(random, '__builtins__').keys()
)
@tough willow :white_check_mark: Your 3.11 eval job has completed with return code 0.
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__build_class__', '__import__', 'abs', 'all', 'any', 'ascii', 'bin', 'breakpoint', 'callable', 'chr', 'compile', 'delattr', 'dir', 'divmod', 'eval', 'exec', 'format', 'getattr', 'globals', 'hasattr', 'hash', 'hex', 'id', 'input', 'isinstance', 'issubclass', 'iter', 'aiter', 'len', 'locals', 'max', 'min', 'next', 'anext', 'oct', 'ord', 'pow', 'print', 'repr', 'round', 'setattr', 'sorted', 'sum', 'vars', 'None', 'Ellipsis', 'NotImplemented', 'False', 'True', 'bool', 'memoryview', 'bytearray', 'bytes', 'classmethod', 'complex', 'dict', 'enumerate', 'filter', 'float', 'frozenset', 'property', 'int', 'list', 'map', 'object', 'range', 'reversed', 'set', 'slice', 'staticmethod', 'str', 'super', 'tuple', 'type', 'zip', '__debug__', 'BaseException', 'BaseExceptionGroup', 'Exception', 'GeneratorExit', 'KeyboardInterrupt', 'SystemExit', 'ArithmeticError', 'AssertionError', 'AttributeError', 'BufferError', 'EOFError', 'Imp
... (truncated - too long)
Full output: https://paste.pythondiscord.com/apixeroteh.txt?noredirect
!epy print(__import__('__hello__').__getattribute__('__builtins__'))
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
{'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>,
... (truncated - too long)
Full output: https://paste.pythondiscord.com/yeruwehuhi.txt?noredirect
Incoming text from @tepid matrix
No getattr
true
np
should work on any module that doesn't overwrite _builtins_ and doesnt have __all__ i think
oh
!epy print(__file__)
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
/home/main.py
!epy import os with open(__file__) as f: a=f.read() if not os.path.isfile('/home/_'): with open('/home/_', 'x'):... exec(a) print('hi')
@arctic skiff :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | hi
002 | hi
I can't because of their tos for submitted challenges
!e @unique heath
import sys
def print(*a,sep=" ",end="\n",file=sys.stdout,flush=0):file.write(sep.join(map(str,a))+end);flush and file.flush()
print(123, 'abc', print, sep='sep')
with open('test.txt', 'w') as file:
print(123, 456, sep='abc', end='a', file=file)
@low lynx :white_check_mark: Your 3.11 eval job has completed with return code 0.
123sepabcsep<function print at 0x7f7089e844a0>
test.txt
123abc456a
!e
print(len('''import sys
def print(*a,sep=" ",end="\n",file=sys.stdout,flush=0):file.write(sep.join(map(str,a))+end);flush and file.flush()'''))````
@unique heath :white_check_mark: Your 3.11 eval job has completed with return code 0.
124
huh
strange
im getting 125
speak in #python-discussion
should be 125, the \n is being unescaped into 1, but the source would have it as 2
yeah, it should be "\\n" in this code that counts length of other code
in actual code it would just be the one character wouldn't it?
yes, but in source code it is two characters long
in golfing we've always counted newlines as one character haven't we?
I typically wrap the code in a raw string so that it doesn't perform escapes
it is not a newline, it is a string literal which contains newline symbol
so it requires two chars in code: "\n"
that is why use r when using len()
you cant
@languid hare :x: Your 3.11 eval job has completed with return code 1.
001 | File "/home/main.py", line 1
002 | ([a, b, c] := [1, 2, 3])
003 | ^^^^^^^^^
004 | SyntaxError: cannot use assignment expressions with list
i have to golf my code
but it fails
l=lambda:sorted(map(int,input().split()));a,b,c=d=l()
print('YNEOS'[d!=l()or a*a+b*b!=c*c::2])
it's a code that inputs each side length of two triangles and determine if it is possible to produce two triangles of given side length, by cutting a rectangle.
i think this: d!=l() will always be True
because d is an int and l() is a list of ints
oh wait
it is a,b,c=d=l() not a,b,c,d=l()
are there any plans to remove these restrictions from walrus?
i think it can work as regular assignment, but it also returns whatever left right side evaluates to

In the future, if such
use-cases are found, the grammar can be expanded.
personally im not too sure why they seemed to be against iterable unpacking in the first place
in the example they gave the issue to me seems to be more of an ambiguity in the grammar, whether
x, y := 3, 4 should be a 3-tuple that also assigns y, or should it be a 2-tuple which performs a destructuring assignment
of course that goes away when you use parenthesis like a sane person
(x, y) := (3, 4)
works for me
>>> l=lambda:sorted(map(int,input().split()));a,b,c=d=l();print('YNEOS'[d!=l()or a*a+b*b!=c*c::2])
3 4 5
3 4 5
YES
>>> l=lambda:sorted(map(int,input().split()));a,b,c=d=l();print('YNEOS'[d!=l()or a*a+b*b!=c*c::2])
1 2 3
1 2 3
NO
!e really weird way of running code on interpreter exit: ```py
def onexit(func, cache=[]):
def gen():
try:yield
except:
func()
raise
g = gen()
g.send(None)
cache.append(g)
@onexit
def _():
print('this ran when the process exited')
print('I ran first')
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | I ran first
002 | this ran when the process exited
!e ```py
def gen(f):
try:yield
except:f();raise
def onexit(f,c=[]):g=gen(f);g.send(c.append(g))
onexit(lambda:print(globals()))
print('a')
@quartz wave :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | a
002 | {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f880d33f750>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins'>, 'gen': <function gen at 0x7f880d2e44a0>, 'onexit': <function onexit at 0x7f880d2e4680>}
nice
ye
it works because tp_finalize for generators calls gen_close, which in turn sets PyExc_GeneratorExit as the active exception and then calls gen_send. so if you have a bare try catch you catch the GeneratorExit which lets you run code as the generator is freed
(just have to make sure to re-raise the GeneratorExit otherwise you get a RuntimeError)
do u know how this works cuz all im seeing is a bunch of gibberish
this explanation doesnt make sense to my little brain
it uses like details a normal python programmer isn't supposed to know
ah
i need to learn more esopy
!e print("Hello!")
#bot-commands @sick hound
whats the g.send(c.append(g)) for? preventing gc?
append g to c and send None to g
why do you need to send something to g?
It's to prevent gc, the generator completes when it is collected
!e
def onexit(func, cache=[]):
def gen():
try:yield
except:
func()
raise
g = gen()
cache.append(g)
@onexit
def _():
print('this ran when the process exited')
print('I ran first')
@low lynx :white_check_mark: Your 3.11 eval job has completed with return code 0.
I ran first
huh
The generator has to be in the middle of executing. That's what the .send is for
If a generator is never started, it doesn't have to be closed
*technically this is not quite true, gen_close is still called, but if the generator is not currently inside a try block it cannot catch the GeneratorExit exception, and if it has never been used (by .send or otherwise) then it cannot be inside a try block
gen returns a generator when called, and you can sort of imagine that to be a function that can be paused. Calling .send executes everything until the first yield. Then the generator is stored in the cache list. When the generator is garage collected (at the end of the program or if the cache is cleared), the interpreter raises a GeneratorExit exception inside of it at the current point of execution. Because it is sitting at the first yield (inside a try/except block) that GeneratorExit exception is caught, func is called, and then the GeneratorExit is re-raised by the argument-less raise.
doesn't that still get picked up by the cyclic GC?
As long as cache is held by onexit it won't get picked up. But on interpreter exit it gets cleared out
hmm
!e
def onexit(func, cache=[]):
def gen():
try:yield
except:
func()
raise
g = gen()
next(g)
cache.append(g)
@onexit
def _():
print('this ran when the process exited')
print('I ran first')
@low lynx :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | I ran first
002 | this ran when the process exited
sys._exit 
I thought it was os._exit
oh it seems to be
that actually makes a bit of sense
glad i could explain it a bit, feel free to ping me if you have any other questions
i have a question, where the fuck did you learn this shit
i try to find books on this topic and i cant
i spent a lot of time reading the cpython source code and looking for edge cases
also lots of trial and error
ah
it would help if i knew c
yea, C is def a good language to know for messing with the low level stuff like this
Python really is fun ```py
def onexit(func, /, *, _cache=[]):
cache.append(type("", (), {"del": lambda s, *, **__: func()})())
yea that will work too, i wrote mine because I wanted to see if i could get one working without any builtins
replace type with [].__class__.__class__
*builtins or dunders
ah
hey guys am i wrong or there is a way using f string to avoid math.ceil
!e you could just print(1.3.__ceil__())
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
2
nooo haa
but
i was saying something.... shorter
using the f string thereisn't a way?
fstrings round to nearest
@sly ibex :white_check_mark: Your 3.11 eval job has completed with return code 0.
2
!e py print(f'{1.3 = :.0f}') print(f'{1.8 = :.0f}')
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 1.3 = 1
002 | 1.8 = 2
!e
import math
print(math.ceil(1.3))
print(math.ceil(1.8))
@sly ibex :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 2
002 | 2
yeah this method works (if you somehow got 1-1/inf)
it also works with modular arithmetics
for example, you want to round 7 up modulo 3. You can do (7+(3-1))//3*3 and get 9
!e that will only work if your decimal is only 2 points: py print(int(1.001+0.99))
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
1
idea of 3-1 is the same as 1 - eps
what is the shortest way to get smallest positive value?
>>> import sys;eps=sys.float_info.epsilon
>>> ceil = lambda x: int(x + 1 - eps)
>>> ceil(1.0)
1
>>> ceil(1.1)
2
>>> ceil(1.00000001)
2
>>> ceil(1.000000000001)
2
>>> ceil(1.00000000000000001)
1
idk if this will work with big values
float_info.epsilon is slightly different semantically but should accidentally give the correct result for numbers close to 1
math.nextafter is closest to what you want I think
!e ```py
import sys;eps=sys.float_info.epsilon
print(f"{1e-128:.128f}")
print(f"{eps:.128f}")
print(1e-128 > 0)
print(eps > 0)
@meager zinc :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
002 | 0.00000000000000022204460492503130808472633361816406250000000000000000000000000000000000000000000000000000000000000000000000000000
003 | True
004 | True
!e noting this:
for i in range(500,1,-1):
if (v := eval(f"1e-{i}")) != 0:
print(v, v > 0)
break
@meager zinc :white_check_mark: Your 3.11 eval job has completed with return code 0.
1e-323 True
!e pro tip: ```py
print(10**-10)
@vast wave :white_check_mark: Your 3.11 eval job has completed with return code 0.
1e-10
!e dropping this here to help the obfooscators
print(__builtins__.eval(__builtins__.__dir__().__getitem__(__import__.__dir__().__len__().__sub__(______:=(___:=(_:=__name__.__getitem__((__:=__name__.__class__().__len__()))).__add__(_).__len__()).__mul__((____:=___.__mul__(___))).__add__((_____:=(_:=__name__.__getitem__(__)).__add__(_).__add__(_).__len__()))))))```
@unique heath :white_check_mark: Your 3.11 eval job has completed with return code 0.
<built-in function eval>
!e golfed ```py
print(builtins.eval(builtins.dir()[len(dir(import))-((:=len((:=name[(:=len(name.class()))])+))***2+len(name[]++))]))
@vast wave :white_check_mark: Your 3.11 eval job has completed with return code 0.
<built-in function eval>
!e golfed
print(eval)```
@unique heath :white_check_mark: Your 3.11 eval job has completed with return code 0.
<built-in function eval>
most epic golf of all time
#python-discussion message i think ```py
for p in[eval('[f"{1950+%d*10}s",%%d,[]]'%i%x)for i,x in enumerate("5x5NExB9GEpydZwCtGa2BP 1kjfmZ8JGrDA5YrBVVZLRx 0eMhi5F148eRenCW2C48nL 4DgEvihGmE3r5wUHUS7Wwv 2eh6kA7m2vUSalEBnKs5yC 1GOVol2EIX1sPDjspcHOtG 5RI8VCGELpG38SCVZBiGs0 4L6k3WNfixzwFI92ba0dqr".split())]:
R=requests.get(f"https://api.spotify.com/v1/playlists/{p[1]}/tracks?limit=50",headers={"Authorization":f"Bearer {access_token}"});print("Playlist: "+p[0])
for t in R.json()["items"]:s=t["track"];a=s["album"];z=a["release_date"];s["name"]in p[2]and int(z.split("-")[0])<2020and a["release_date_precision"]in{"year","month","day"}and print(f"{p[0]}: {s['name']} ({z})")
i am so glad i don't see code like this everydya
that's some nice code wym
beautiful
wtf is "code gore"
no clue myself
Basically just terrible looking code in simple terms
lol

I wonder if there's code porn
like food porn
when the food looks extremely good
is there one for codd
code
what 😭
It's how I felt about the code I cleaned up earlier
Good functional python
Pretty sure there's code porn somewhere
Don't go look for it, it might be unsafe code

Bad practices everywhere
Man why do so many professional unadvised technical terms apply for this
just curious
real
the source for GNU Hello
I wonder if there used to be a proper fp channel on this cord ? 🤔
lol probably
Hello my esoterism enthusiasts, I am happy to announce that for the first time ever, the International Obfuscated Python Code Competition is accepting submissions. This contest is similar to the IOCCC (International Obfuscated C Code Contest), and is intended to reward creative and perverse code style. A short bio about the judges and more details about the logistics of the competition will be released on April 30th, with submissions ending August 30th, 2023. Answers to FAQs as well as more information about the rules can be found on the website: pyobfusc.com
this is an approved post
https://pyobfusc.com
Obfuscated Python competition
@sharp kestrel if you could pin it that would be great--this channel seems to have a decent amount of activity
def J():A='Safe at last';B='Run away';C='\n';D='';E='doo-doo';F=['Baby','Mommy','Daddy','Grandma','Grandpa',"Let's go hunt",B,A,"It's the end"];G={B:'(ah!)',A:'(phew)'};H='Shark';I='';D=[f"{3*f'{A} {H if B<=4 else I}, {E}, {E}{C}'}{A} {H if B<=4 else G[A]if(A:=F[B])in G.keys()else I}{C*2}"for B in range(len(F))];return D;print(J())
What?
first time here?
Amazing! I am looking forward to stressing the judges
If you can make a judge quit judging the competition on the spot because of your submission you get ultimate notoriety
this doesn't produce any output when I run it?
is this the baby shark song lyrics generator?
I guess this is a small problem either on the bot side or on my side. For me it works, but the bot doesnt run it, maybe because the call to the functions is on the same line as declaration 🤷
editing it to
def J():A='Safe at last';B='Run away';C='\n';D='';E='doo-doo';F=['Baby','Mommy','Daddy','Grandma','Grandpa',"Let's go hunt",B,A,"It's the end"];G={B:'(ah!)',A:'(phew)'};H='Shark';I='';D=[f"{3*f'{A} {H if B<=4 else I}, {E}, {E}{C}'}{A} {H if B<=4 else G[A]if(A:=F[B])in G.keys()else I}{C*2}"for B in range(len(F))];return D;
print(J())
actually makes it work on the bot
well its weird af for me now, i'm trying to run it by myself but it generates the wrong thing for some reason lmao
havent used python in a long time and just came back for some simple scripting so decided to do some funny esoteric
yeah I feel you haha
I think you just need to strip some newlines
or use ''.join()
well the thing is before it actually printed the correct lines, now even when i backup to older versions it does.. this
oh, actually this was caused by the fact that cls doesnt really fully clear the terminal lmao
oh yeah lol that's an old footgun
def a():
b = "\n"
c = ""
d = "doo-doo"
e = ["Baby", "Mommy", "Daddy", "Grandma", "Grandpa", "Let's go hunt", "Run away", "Safe at last", "It's the end"]
f = {"Run away": "(ah!)", "Safe at last": "(phew)"}
i = "Shark"
j = ""
c = [f"{3 * f'{e[g]} {i if g <= 4 else j}, {d}, {d}{b}'}{e[g]} {i if g <= 4 else (f[e[g]] if (h:=e[g]) in f.keys() else j)}{b*2}" for g in range(len(e))]
return "".join(c)
print(a())
so thats the more ,,readable" version
you can also change the "in f.keys()" to just "in f"
also if you wanted to change all those assignments to walrus operators you could use a lambda and save a few chars overall I think haha
!e
def A():I='Safe at last';H='Run away';C='\n';A='';D='doo-doo';B=['Baby','Mommy','Daddy','Grandma','Grandpa',"Let's go hunt",H,I,"It's the end"];E={H:'(ah!)',I:'(phew)'};F='Shark';G='';A=[f"{3*f'{B[A]} {F if A<=4 else G}, {D}, {D}{C}'}{B[A]} {F if A<=4 else E[B[A]]if(H:=B[A])in E else G}{C*2}"for A in range(len(B))];return ''.join(A)
print(A())
@karmic pumice :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | Baby Shark, doo-doo, doo-doo
002 | Baby Shark, doo-doo, doo-doo
003 | Baby Shark, doo-doo, doo-doo
004 | Baby Shark
005 |
006 | Mommy Shark, doo-doo, doo-doo
007 | Mommy Shark, doo-doo, doo-doo
008 | Mommy Shark, doo-doo, doo-doo
009 | Mommy Shark
010 |
011 | Daddy Shark, doo-doo, doo-doo
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/bipojalupo.txt?noredirect
fixed :d
hell yea
fun way to get back into python lmao
yeah python is really fun for stuff like this
how do u get rid of those damn massive previews
woah, these ones always impress me
<link>
nah, not like html
well this is supposed to be the correct way
OH
hahaha
I was confused
also this is my fav one I've made https://gist.github.com/juliusgeo/1da759d07af0b447a78d0ccb14162c57
yeah it looks impressive
thank god for the walrus operator hahah
I also made something that takes code that is just lambdas or basic expressions and reflows it into ascii art
it results in some really weird coding style
it can reflow itself so the main program kinda shows
how awkward it is to write like that
but you need to do that anyway for really intense whitespace transformation
all of the time i wasnt using python i was learning godot and the gdscript language doesnt really have that much features yet and its not really made for funky esoteric stuff to work on it, so i kinda missed it XD
it doesnt even have list comps 
ahh yeah that makes sense
damn wtf
list comps are like
the best thing about python haha
yeah it was sad to not have list comprehensions in a language that even states on the docs that its similar to python syntax-wise
I mean most of the time when a language says they have python syntax they just mean it's easy to read
but most of the time they don't make it easy to write
1 sec, ill share a small snippet
func Jump(move_axis: Vector2) -> void:
if cur_jumps > 0:
cur_jumps -= 1
velocity.y = jump_velocity; velocity.x = move_axis.x * speed_limit_h
var particle = preload("res://Scenes/JP.tscn").instantiate()
particle.global_position = self.global_position - Vector2(0, -10)
particle.rotation = PI / 4 * move_axis.x
$"/root/World/Particles".add_child(particle)
func _physics_process(delta: float) -> void:
var move_axis: Vector2 = Vector2(Input.get_axis("ui_left", "ui_right"), 0)
if (is_on_floor()): cur_jumps = max_jumps
if Input.is_action_just_pressed("ui_up"): Jump(move_axis)
set_collision_mask_value(2, !Input.is_action_pressed("ui_down"))
if !(is_on_floor()): velocity.y += gravity * delta
if velocity.x == 0: velocity.x = move_axis.x * starting_velocity_h
else:
var accel_h = acceleration_h * move_axis.x * delta
if sign(velocity.x) != sign(accel_h): accel_h *= 5.0;
velocity.x = clamp(velocity.x + accel_h, -speed_limit_h, speed_limit_h)
if !move_axis.x: velocity.x = move_toward(velocity.x, 0, delta * 100.0)
move_and_slide()
(it isnt even supported in markdown yet, sadly)
wtf and they also have var?
also, i was quite surprised that a language for a game engine doesnt have static typing for dictionary key and value types and for nested collection element types 💀
yeah
to be fair, type hinting in python is really fucking hard
but they could surely implement that on the engine side
well atleast its doable
I mean I worked on PyMongo last year when it switched over to being fully type annotated
and it was a nightmare
easily 9 months of work
mypy is really opinionated, but also has a ton of weird edge cases and straight up doesn't support some things
here you get this 
you constantly have to sprinkle in #type:ignore after everything
LMFAOOOOO
