#esoteric-python
1 messages · Page 41 of 1
@versed eagle :x: Your 3.12 eval job has completed with return code 1.
001 | File "/home/main.py", line 2
002 | print(1 <> 2) # same as 1 != 2
003 | ^^
004 | SyntaxError: invalid syntax
it works with my local 3.12
oh well
check out https://peps.python.org/pep-0401/
Python Enhancement Proposals (PEPs)
Any other esoteric python things that modifies allowed syntax?
!e most of the other future statements dont do anything in modern python, because they're already implemented, but there is this
from __future__ import braces
@versed eagle :x: Your 3.12 eval job has completed with return code 1.
001 | File "/home/main.py", line 1
002 | from __future__ import braces
003 | ^
004 | SyntaxError: not a chance
its quite silly
ok, now how do i revert <>...
dont import barry as flufl
too late for that
any suggestions for how to achieve something like this:
class C:
registry = {}
...
asdf = C()
assert C.registry['asdf'] is asdf
not very efficient, but this is working alright.
class C:
_registry = {}
@classmethod
@property
def registry(cls):
for k, v in globals().items():
if isinstance(v, C):
C._registry[k] = v
return C._registry
def __repr__(self):
for k, v in C.registry.items():
if v is self:
return f'C(name: {k})'
asdf = C()
print(asdf) # prints "C(name: asdf)"
you could add a flag so registry only goes searching if there are any new instances of C
good idea
@elfin ether take a look at this for finding containers of objects after they are created: https://paste.pythondiscord.com/2NEA
random thought: sum(n) == n*(n-1)//2 if n is a nonnegative integer
i was confused for the first 10 seconds until i remembered what sum() takes
hmm, what is the sum of increasing sequence of integers from 0 to -10?
it feels like the same formula should work, if we count each number -1 times
you got me beat then, sum(1) is invalid right?
do you mean sum of integers in [0, n)?
if yes, it can be generalised for negative numbers
!e ```py
def rangesum(n):
s = n and n // abs(n) # sign of n
return s * (n*(n-s) // 2)
for i in range(-100, 101):
# to avoid division by zero. rangesum returns 0 when given 0 as input though, so it still works
if i:
i_sign = i // abs(i) # make sure the range increments in the right direction
assert sum(range(0, i, i_sign)) == rangesum(i)
@versed eagle :warning: Your 3.12 eval job has completed with return code 0.
[No output]
the trick is to account for the sign of n
i assume sum(n) means the sum of range(n), because of the following equation
ah yea fair
You can use math.sign instead of the abs trick
are you sure? i've read a while ago somewhere on stack overflow that python developers could not agree on all the edge cases of such sign function and so that it was never implemented
Oh yeah, you have just copy sign, my bad
I am a software engineer and I use chat gpt4 to assist me as a tool
Nothing wrong with that
sure, but there is something wrong with copy and pasting its output here-- the wrong thing being that it violates the rules of this server
if you don't like the rules, talk to the moderators i guess ¯_(ツ)_/¯
til about math.copysign, thanks
(though imo it should instead be an attribute or method on numeric classes, i.e., int.sign, float.sign, and complex.sign)
!e
print(((B:=lambda x,y:x+y),(C:=lambda x,y:x-y),(A:=B(x=50,y=50)),(__:=C(x=A-15,y=A-25)))[3])
@sick reef :white_check_mark: Your 3.12 eval job has completed with return code 0.
10
((50+50)-15)-((50+50)-25)
hey, i have a little script where i overload the __or__ method on builtin functions to be able to do function chaining like in bash (i'm using forbiddenfruit which is a library that allows to overload operators from builtin functions using ctypes)
Here's the code :
from forbiddenfruit import curse
from collections.abc import Iterable
from inspect import signature
from types import *
_func_types = [FunctionType, LambdaType, MethodType, BuiltinFunctionType, BuiltinMethodType, MethodDescriptorType, MethodWrapperType]
def _pipe(self, func):
def wrapper(*args, **kwargs):
"""Wrapper for the function combination"""
res = self(*args, **kwargs) if callable(self) else self
try:
if func == print or len(signature(func).parameters) > 1:
if isinstance(res, dict):
return func(**res)
if isinstance(res, Iterable):
return func(*res)
except:
pass
return func(res)
if func == print:
wrapper()
else:
return wrapper
for t in _func_types:
curse(t, "__or__", _pipe)
and here's how it works :
def double(x):
return 2 * x
2 | double | double | double | print # 16
map(str.lower | str.capitalize, ["mEsSy", "tExT"]) | print # Messy Text
what are your thoughts about this and how would you make it better ?
!e ```py
print(eval("print(print(print(print(print(print(print(print(print(print(print(print(print("Hello World"))))))))))))"));
@lunar juniper :x: Your 3.12 eval job has completed with return code 1.
001 | File "/home/main.py", line 1
002 | print(eval("print(print(print(print(print(print(print(print(print(print(print(print(print("Hello World"))))))))))))"));
003 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
004 | SyntaxError: invalid syntax. Perhaps you forgot a comma?
hey eso types: i have a challenge for you: golf this nedbat code
bomb = """
(lambda fc=(
lambda n: [
c for c in
().__class__.__bases__[0].__subclasses__()
if c.__name__ == n
][0]
):
fc("function")(
fc("code")(
0,0,0,0,0,0,b"BOOM",(),(),(),"","","",0,b"",b"",(),()
),{}
)()
)()
"""
eval(bomb, {"__builtins__": {}})
eval() is tempting, but it’s truly dangerous. Here’s how common safety attempts can be circumvented.
that code looks... disgusting 😶
i am not good at golfing, but ().__class__.mro()[1].__subclasses__() has less characters than using __bases__ :)
cant you just __base__.__subclasses__()?
is the challenge just what it does?
so smallest segfault
!e
bomb = """
(lambda fc=(
lambda n: [
c for c in
().__class__.__bases__[0].__subclasses__()
if c.__name__ == n
][0]
):
fc("function")(
fc("code")(
0,0,0,0,0,0,b"BOOM",(),(),(),"","","",0,b"",b"",(),()
),{}
)()
)()
"""
eval(bomb, {"__builtins__": {}})
@flint hollow :warning: Your 3.12 eval job has completed with return code 139 (SIGSEGV).
[No output]
with no imports?
smallest bomb that can survive eval(bomb, {"__builtins__": {}})
yes
!e py bomb = "(m:=lambda:m).__class__(m.__code__.replace(co_code=b''),{})()" eval(bomb, {"__builtins__": {}})
@rugged sparrow :warning: Your 3.12 eval job has completed with return code 139 (SIGSEGV).
[No output]
@flint hollow ^ thats pretty small
why does it not crash the REPL
unless put in an exec(r"""...""")
It should crash even without the eval, the guy challenged to do it without buildins, so the eval was used to remove them
weird
it behaves differently when i tried to reproduce the noncrash
now it does crash
oh
wait a minute
It should either segfault or hit a breakpoint/trap
Depending on the flags used to build python
it's so weird
>py
Python 3.13.0a3 (tags/v3.13.0a3:f009305, Jan 17 2024, 13:25:20) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> bomb = "(m:=lambda:m).__class__(m.__code__.replace(co_code=b''),{})()"
>>> eval(bomb, {"__builtins__": {}})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
eval(bomb, {"__builtins__": {}})
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 1, in <module>
File "<string>", line 1, in <lambda>
SystemError: no locals found when storing 'm'
>>> (m:=lambda:m).__class__(m.__code__.replace(co_code=b''),{})()
<crash>
Huh, looks like 3.13 eval doesn't init locals properly?
i'd say it's more proper now since it doesn't crash then
but i don't have enough of an idea of python internals to know if it is indeed proper
i think i might've done it okay
>>> sum(1)
0
>>> sum(2)
1
>>> sum(5)
10
first n integers from start (defaults to 0)
>>> sum(5, start=2)
20
no that's a system error, I would bet there is some optimization where it doesn't add locals if it doesn't think it needs to and that code somehow bugs it out. (Or it somehow got lucky and constructed the opcodes needed for that from the empty byte string). Can you test (m:=lambda:m) by itself?
works fine
Hmm try the original code, without the call
works fine
Weirder
produces a lambda
And with the call it gets the locals not found?
Ooo even weirder lol
Try disassembling the resulting lambda? It might raise a weird exception
nope
no specific eval() call btw ```pycon
bomb = "(m:=lambda:m).class(m.code.replace(co_code=b''),{})"
t = eval(bomb, {"builtins": {}})
eval("t()")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
eval("t()")
~~~~^^^^^^^
File "<string>", line 1, in <module>
File "<string>", line 1, in <lambda>
SystemError: no locals found when storing 'm'
it works on any as long as t is defined as that lambda
yes
Interesting
wait hold on this is weird
I'll dig into this more later today, will build 3.13 locally
actually it does produce the same error when t() is called outside
maybe i just did the code on 3.12
That makes it a bit less weird
i had a lot of python shells open
Still interesting
and it gets confusing sometimes
Yea fair
I'll dig in at the C source level later today and figure out a root cause
Thing I made, most overly complex way to turn one string into another string using 1 line:
for x,l in enumerate("Franz"): (l := ord(l)) and print(f"{(chr(l-3))*(x==0)}{(chr(l+3))*(x==1)}{(chr(l+19))*(x==2)}{(chr(l-9))*(x==3)}{(chr(abs(l-89)))*(x==4)}",end="")
Technically anything can be a one linear
If you allow exec/eval
anything can be a one-liner even without exec/eval
Really? Ok
theoretically
anything that doesn't do silly things like reading its source file
why not?
because the source would be different
so it could behave differently from the equivalent multi-liner code
it can write to source file, and then change it back at the end of the process
assuming you have write permissions on the file, yeah
well, you cant change anything without a way to observe it
so we should make a distinction that makes sense
looking into source code is not a normal thing for a program to do, so breaking it is fine, imo
even if you change def into lambda it could be observed (you might patch the code object though)
normal functions and equivalent lambdas are written in pretty different ways, so bytecode almost always will be different (and if you patch it - then it pretty much the same thing as doing exec/eval)
also, one-expression code usually allocates more objects than normal code, and you can observe it (it changes state of the allocator, so objects might be allocated in different places)
doing try-except or with in expression-only code is impossible
either code generation is required, or some external module (iirc, contextlib provides a way to solve this problem)
and this might change traceback
neither code generation nor external modules are required
match-case is possible, but it requires a lot of verbose code
example?
try:
1/0
except:
pass
``` please convert this code into expression
by chilaxan,
read his code, bruh
it uses neither code generation nor external modules
it uses contextlib which has non-expression code in it
this is basically the same as writing ```py
def try_(...):
try:
...
except:
...
it is, relative to our file
im not talking about 3rd party modules
so does the builtins module, and we still use builtin functions
writing normal code when you are supposed to write esoteric (one-line in this case) code is boring
dont forget that we are in #esoteric-python
what does this have to do with writing normal code?
.
how so
if that's equivalent, how is defining any function locally different than just importing it from another file?
I think I have some code that abuses generators and the fact that they can sort of catch exceptions ish, to simulate exceptions, would need to dig it up
But it couldn't be fully generalized to catch all exceptions 🤷♂️
hmm, would disabling my copy and paste keys while programming help me to actually make functions for repeated tasks instead of copying and pasting?
?
huh?
import pickle
import datetime
import decimal
import uuid
import collections
import re
import io
import sys
SAFE_TO_IMPORT = {
'builtins.range',
'builtins.complex',
'builtins.set',
'builtins.frozenset',
'builtins.slice',
'builtins.str',
'builtins.bytes',
'builtins.list',
'builtins.tuple',
'builtins.int',
'builtins.float',
'builtins.dict',
'builtins.bool',
'builtins.bin',
'builtins.None',
'datetime.datetime',
'datetime.time',
'datetime.timedelta',
'decimal.Decimal',
'uuid.UUID',
'collections.namedtuple',
'collections.OrderedDict',
're.Pattern',
}
class RestrictedUnpickler(pickle.Unpickler):
def find_class(self, module, name):
module_dot_class = '{}.{}'.format(module, name)
if module_dot_class in SAFE_TO_IMPORT:
try:
module_obj = sys.modules[module]
except KeyError:
raise Exception("Module Not Found") from None
return getattr(module_obj, name)
raise Exception("Forbidden Module")
def persistent_load(self, persistent_id):
if persistent_id == "<<NoneType>>":
return type(None)
def challenge(input: str):
return RestrictedUnpickler(io.BytesIO(input.encode('utf-8'))).load()
``` new challenge for y'all, get full code exec from `challenge(<input>)`
i am not 100% sure its possible, but if anyone can solve it its yall
@lunar marsh you might want to give it a shot ^
those are some very specific imports 🤔
(its from a real world package)
if you can find a solve, we split the bounty lol
haha alright bet
i have all of the path to hit that code path
and ik how to get code exec if we can get a reference to <type 'code'>
imagine not stacking all of your imports on one line
!e
f=lambda c:c==1and'""'or f'f"{f(c-1)}"'
eval(f(152))
@torn cypress :x: Your 3.12 eval job has completed with return code 1.
001 | /home/main.py:1: SyntaxWarning: invalid decimal literal
002 | f=lambda c:c==1and'""'or f'f"{f(c-1)}"'
003 | Traceback (most recent call last):
004 | File "/home/main.py", line 3, in <module>
005 | eval(f(152))
006 | File "<string>", line 1
007 | f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f"f""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
008 |
... (truncated - too long)
Full output: https://paste.pythondiscord.com/KSXSAMKSBIJVRSNVROL2JBOXCY
perish
#1219231910790823977 message
multiple starred tuples that don't error ```pycon
*(a, b), *(c, d) = 1, 2, 3, 4
a
1
b
2
c
3
d
4
hello, there is someone who already used opencv library? I have some questions about my code
this was not a productive use of my time.
import numpy as N;import matplotlib.pyplot as H;𑀇=int('001100',2);Δ=lambda 𑀇:len(𑀇);𝛬=lambda 𝛌:int(𝛌);p=lambda i:i[::1];q=lambda i:i[::-1];Ω=lambda x:N.sin(x);Θ=N.pi;Π=N.sqrt(𑀇);F=H.figure(figsize=(𑀇-Δ([𑀇,𑀇,𑀇])/𑀇/𑀇,𑀇/𑀇+𑀇/𑀇+𑀇/𑀇),facecolor=chr(𑀇*𑀇-(𑀇+𑀇+𑀇+(𑀇//𑀇))),dpi=𑀇*𑀇*Δ([𑀇,𑀇,𑀇])*Δ([𑀇,𑀇,𑀇])+𑀇/𑀇,edgecolor=(𝛬(𑀇/𑀇),𝛬(𑀇/𑀇),𝛬(𑀇/𑀇)),tight_layout=True);Z=N.linspace(-𑀇,𑀇*𑀇,𑀇**Δ([𑀇,𑀇])*Δ([𑀇,𑀇,𑀇]));𑀇Z=q(Z);Z𑀇=p(Z);S = N.linspace(𑀇*𑀇,-𑀇,𑀇**Δ([𑀇,𑀇])*Δ([𑀇,𑀇,𑀇]));M=(N.empty(Z.shape));𑀇M=q(M);M𑀇=p(M);𑀇S=q(S);S𑀇=p(S);W=(N.empty(S.shape));𑀇W=q(W);W𑀇=p(W);M[::𝛬((𑀇-𑀇-𑀇/𑀇))]=Ω(𑀇Z)/1-Ω(Z𑀇)/1;Z[::𝛬((𑀇//𑀇))]=Ω(𑀇M)/Π-Ω(𑀇M)/Π/2;M[::𝛬((𑀇-𑀇-𑀇/𑀇))]=Ω(𑀇M)/1-Ω(M𑀇)*+(𑀇/𑀇);M[::𝛬(𑀇//𑀇)]=Ω(𑀇M)*Π/2-Ω(M𑀇)*Π/2;W[::𝛬((𑀇-𑀇-𑀇/𑀇))]=Ω(𑀇S)/1-Ω(S𑀇)/1;S[::𝛬((𑀇/𑀇))]=Ω(𑀇W)/Θ-Ω(𑀇W)/Θ/2;W[::𝛬(𑀇-𑀇-𑀇/𑀇)]=Ω(𑀇W)/1-Ω(W𑀇)*+(𑀇/𑀇);P,=H.plot(W𑀇-𑀇M-N.tan(Z)*-Ω(S),Ω((M)[::𝛬((𑀇-𑀇-𑀇/𑀇))]/(Θ))+Ω((W)[::𝛬((𑀇/𑀇))]/(Π/2)));P.set_color(chr((𑀇*𑀇)-(𑀇+𑀇+(𑀇//((𑀇+𑀇)//𑀇)))));H.axis('off');H.show()
Craxylzy
replace exec with print and you probably will be fine
and print will print the code that your friend tried to execute on your machine
solved, forgot to delete it - thy for trying to help tho 🫶
is this a programming language?
yk... APL and all 
very productive use of time
So I wrote this line last night (Tkinter code), but was surprised after that it worked/confused about how:
self.button = tk.Button(self.frame, text='Button', font=custom_font, bg='#334455', command=lambda: self.button_click(self.button))
The button appears to work/be stable. How can I create an anonymous lambda function passing/using self.button before it exists?
the lambda isnt called until after you've set self.button
Yes, but I've read that lambdas take the value from the context at the moment of creation (so it would be getting the value of self.button prior to it being set to the new Button).
Lambdas are closures in Python.
A closure is a function that captures the environment in which it was defined, including any variables that were in scope at the time of its definition. This allows the function to access those variables even after they have gone out of scope or changed their values.
it captures self, not self.button
import that
!e
print = p;s+m+h=0;s+1;if s==60:s=0;m+1;if m==60:h+1;if h==24:h=0;while h<24:
p(s,m,h)
code
!e print = p;s+m+h=0;s+1;if s==60:s=0;m+1;if m==60:h+1;if h==24:h=0;while h<24:
p(s,m,h)
@rocky leaf :x: Your 3.12 eval job has completed with return code 1.
001 | File "/home/main.py", line 1
002 | print = p;s+m+h=0;s+1;if s==60:s=0;m+1;if m==60:h+1;if h==24:h=0;while h<24:
003 | ^^^^^
004 | SyntaxError: cannot assign to expression here. Maybe you meant '==' instead of '='?
well, I can tell you that it doesn't happen simply by obfuscation, you kinda have to use some obscure, uncommon stuff
code
!e for example:
[real := False, forever := False, [type("", (), {(i := "__init__"): lambda t: [k := "t", setattr(t, "s", type("s", (), {i: lambda s: [setattr(s, k, 0)] and None, (c := "__call__"): lambda s, l, f=0: not (isinstance(s, t.s) and (print("%s:%s:%s" % (str(t.hi.t).zfill(2), str(t.mi.t).zfill(2), str(t.si.t).zfill(2))) or __import__("time").sleep(real))) and getattr(s, k) + 1 < 60 and (setattr(s, k, getattr(s, k) + 1) is None and s(t.mi)) or not setattr(s, k, 0) and (f and l())})), setattr(t, "m", type("m", (t.s,), {c: lambda s: not setattr(s, k, getattr(s, k) + 1) and (s.t < 60 or setattr(s, k, 0) or t.hi()) and t.si(s, 1)})), setattr(t, "h", type("h", (t.m,), {c: lambda s: 0})), setattr(t, "si", t.s()), setattr(t, "mi", t.m()), setattr(t, "hi", t.h()), *map(lambda x: [t.si(t.mi, 1), setattr(t.hi, k, x)], range(25))] and None})() for _ in forever and __import__("itertools").cycle([0]) or [1]]]
@torn cypress :x: Your 3.12 eval job timed out or ran out of memory.
001 | 00:00:00
002 | 00:00:01
003 | 00:00:02
004 | 00:00:03
005 | 00:00:04
006 | 00:00:05
007 | 00:00:06
008 | 00:00:07
009 | 00:00:08
010 | 00:00:09
011 | 00:00:10
... (truncated - too many lines)
Full output: too long to upload
still too long? smh /s
clearly winning the code golfing competition i see
ah yes, when you need over 900 characters to simply print out some time in a 24 hour format in a loop...
for reference, this is like a playable game and it's less than 500 characters
||though I have a feeling you were trying to be sarcastic, I wasn't entirely sure, so I was sort of trying to be sarcastic back as well, but.... yeah, welll... now it's awkward||

too esoteric
you made it more awkward
not 100% sure if its on topic or off topic but I made a thing I think some people here might like 🙂
https://www.codewars.com/kata/63d4b700bce90f0024a9ca19
its a question about how you can represent python code to use a low amount of unique chars
Very much on topic. In Python 2, the lowest amount of characters needed was 8, so with the same approach it would be 10 in Python 3: https://codegolf.stackexchange.com/a/11697
ooh
ill go ahread and read it but nice too see people had the same idea 🙂
my sample answer is actualy 9 chars in python3
but its a very neat idea to use that trick
Interesting. Do you use ()?
yea
you can solve it and see the exact solution if you want the one you linked is under 12 chars so it will pass the tests
just make sure to self compile before submitting the answer
(gets behind a lot of cheeky answers)
You can get 8 in Python3 as well :) https://theblupper.github.io/pyfuck.html
how do i learn this
learn what
Is there a quick method for saving an array to disk and reading each element from the file without loading the entire array into RAM?
do you know the size of each element
yep
it's is n-D-Array of uint8
but it's dimensions are fix.
oh
then yes
just write it all into a file and then read it out piecewise
seek if you want random access instead of sequential
@versed eagle Yes, I Need Random access instead of sequential. & Python Loops are Blazigly fast.
Is there is an already implementation.
The array is an video.
.
seek if you want random access
What dose it means?
if you want random access, seek through the file to where-ever you want to read the data from instead of reading piecewise sequentially
How?
file.seek
Thanks
Can I just toss a codegolf challenge in here? This is my best result, 245 chars. I wonder how much shorter you folks could get it
||```py
n=int(input())
S=sum
l=[[[x*(i<b)for i in(0,1,2)]for x in(1,2,3,0)]for b in[n//3[3],n%3]]
e=[[0]*3]*2
[print("".join(" - ( O|' O|' )' ( /' /) "[i::4]for i in p))for p in[S(zip(*z),())for z in zip(S(l[::2],[])+e,S(l[1::2],e)+e)]if S(p)]
||The string and the list comprehensions are mad expensive but I had to settle for this eventually 😄||
Spoilered my solution in case someone wants to do it with a fresh mind, here's the challenge:
BEES? BEES!
Print this little fellow and his crew to the console.
OO //
-(||)(')
'''
Your input per stdin or argv is a single integer >= 1 that determines how many bees should be printed.
Bees always fly in formation though:
Maximum number of bees in a row is 3. Each bee has a bee-width distance to the neighbouring bees in the same row. The first line of each new row of bees is the same line as the last line of the previous row, and every second row is offset by the width of one bee to make that possible (see examples below). The bees fill the rows from top to bottom and left to right.
Don't print any extraneous empty trailing or leading lines.
Some example inputs + outputs:
2
OO // OO //
-(||)(') -(||)(')
''' '''
5
OO // OO // OO //
-(||)(') -(||)(') -(||)(')
''' OO // ''' OO // '''
-(||)(') -(||)(')
''' '''
13
OO // OO // OO //
-(||)(') -(||)(') -(||)(')
''' OO // ''' OO // ''' OO //
-(||)(') -(||)(') -(||)(')
OO // ''' OO // ''' OO // '''
-(||)(') -(||)(') -(||)(')
''' OO // ''' OO // ''' OO //
-(||)(') -(||)(') -(||)(')
OO // ''' ''' '''
-(||)(')
'''
Have fun!
cute bees!
Thanks 😄
165 chars
||```py
j=(" "*8).join
c,r=divmod(int(input()),3)
for n in range(c+1):p=" "8(n%2);k=[3,r][n==c];print(p+j([" OO //"]*k),p+j(["-(|<remove this...>|)(')"]*k),p+j([" ''' "]*k),sep="\n")
I mean, that's like perfect, thanks discord...
just need to get rid of <remove this...>
because discord parses || in the string as end of the spoiler, smh
use a \
to escape it
nvm discord doesnt parse escapes inside codeblocks
because of course
exactly
ugh discords markdown parser is so cursed lol
153 chars ||```py
c,r=divmod(int(input()),3)
for n in range(c+1):f=lambdas:(" "8).join(n%2("",)+s[3,r][n==c]);print(f(" OO //"),f("-(|<remove this...>|)(')"),f(" ''' "),sep="\n")
143 chars 166 chars ||```py
c,r=divmod(int(input()),3)
for n in range(c+1):print(map(lambdas:(" "8).join(n%2("",)+s*[3,r][n==c]),[" OO //","-(|<remove this...>|)(')"," ''' "]),sep="\n")
137 chars 144 chars ||```py
c,r=divmod(int(input()),3)
for n in range(c+1):print([(" "8).join(n%2[""]+s[3,r][n==c])for*s,in[" OO //","-(|<remove this...>|)(')"," ''' "]],sep="\n")
126 chars 133 chars ||```py
c,r=divmod(int(input()),3)
for n in range(c+1):
fors,in" OO //","-(|<remove this...>|)(')"," ''' ":print((" "8).join(n%2[""]+s[3,r][n==c]))
129 chars ||```py
N=int(input())
for n in range(N//3+1):
fors,in" OO //","-(|<remove this...>|)(')"," ''' ":print((" "8).join(n%2[""]+s[3,N%3][n==N//3]))
~~128 chars ||```py
N=int(input())
for n in range(N//3+1):[print((" "8).join(n%2[""]+s*[3,N%3][n==N//3]))for*s,in" OO //","-(|<remove this...>|)(')"," ''' "]
128 chars ||```py
N=int(input());J=" "8
for n in range(N//3+1):
fors,in" OO //","-(|<remove this...>|)(')"," ''' ":print(n%2J+J.join(s[3,N%3][n==N//3]))
What the Hell is going on.
golf 🏌️♂️
your code doesn't work though
3
O O / / O O / / O O / /
- ( | | ) ( ' ) - ( | | ) ( ' ) - ( | | ) ( ' )
' ' ' ' ' ' ' ' '
This doesn't look like the desired output
looks more like a alaskan bull worm than a bee
it stopped working from this point onwards
hmm
130 chars fixed ||```py
N=int(input());J=" "8
for n in range(N//3+1):
for s in" OO //","-(|<remove this...>|)(')"," ''' ":print(n%2J+J.join([s]*[3,N%3][n==N//3]))
123 ||```py
N=int(input());J=" "8;a=0
while N>0:
for s in" OO //","-(|<remove>|)(')"," ''' ":print(aJ+J.join([s]*min(N,3)))
a=1-a;N-=3
Why Not Sequence. typing.Sequence
122 chars alt 123 ||```py
N=int(input());J=" "8;a=0
while N>0:
for s in" OO //","-(|<remove>|)(')"," ''' ":print(-aJ+J.join([s]*min(N,3)))
a=~a;N-=3
122
N=int(input());J=" "*8;a=0
while N>0:
for s in" OO //","-(|<remove>|)(')"," ''' ":print(a*J+J.join([s]*min(N,3)))
a^=1;N-=3
another 122
N=int(input());J=" "*8;a=0
while N>0:
for s in" OO //","-(||)(')"," ''' ":print(*[J*-a+s+J*-~a]*min(N,3))
N-=3;a=~a
121
N=int(input());a=1
while N>0:
for s in" oo //","-(||)(')"," ''' ":print(*(J:=' '*8,*[s+J]*min(N,3))[a:])
a^=1;N-=3
120
N=int(input());a=0;J=' '*8
while N>0:
for s in" oo //","-(||)(')"," ''' ":print(*(J*a,*[s+J]*min(N,3)))
a^=1;N-=3
print(*(J*a,*[s+J]*min(N,3)))
print(J*a,*[s+J]*min(N,3))
``` ?
oh yea
.. ..
( —) ( —)
'''` .. '''`
( —)
.. '''` ..
( —) ( —)
'''` .. '''`
( —)
'''`
Damn, you folks are insane 😄
Wait a minute, those are solutions to an easier challenge
Check the formation again, the difficulty is that the bees are overlapping 😄
Very cool stuff tho, I'll make that a part of the challenge on my server
Do you mean *args?
Because those are tuples.
If all elements have the same type:
def something(*values: int):
pass
something(3, 5)
If the elements have different types you can typehint them like this since 3.12:
from typing import Unpack
def something(*values: Unpack[tuple[int, str]]):
pass
something(3, "spam")
If you weren't talking about *args, the question doesn't make too much sense because it depends on whether you expect values to be a tuple or a list. The typehint doesn't change whether the passed object is mutable or not. If you don't care, you can use Sequence, like Soham said
what do you mean?
- incorrect
- correct
!e
((6,9,(0,1,0,0,()),(0),0,0,(0,((0),(0,(0))))),0+(0)),(c:=0.3*divmod(30,10)[0]),(d
:=c*36/len([0,0,0]),(k:=__import__("builtins"),(0,0,(0,(0,o:=eval("k.print"))),0)
),(c:=80.00000000000001*c),(c:=int(c)),(0,),(j:=""),(0,(0,0,0,(j:=j+chr(c)))),0),
(c:=1.4027777777777777*c),(0,0,(),0,(j:=j+chr(int(c)))),(j:=j+chr(ord(j[-1])+7)),
(j:=j+j[-1]),(0,0,()),(u:=j,(0,10,3,(0x3f))),*(u:=list(map(ord,u))),(u:=(u[-1])),
(0,1,2,([range(2-u)])),(c:=u+3),(0,0,(0,0,0)),(-1),(((),0),(0)),(j:=j+chr(c),24),
((),0,0,-1,divmod(30, 0xffc),(j:=j+" ")),(j:=j+chr(sum([c,u])//2-22)+"AAoAA"[2]),
(0,30,(n:=((c*0)+abs(60.3337/pow(2,2)-36))+94)),(0,3,5,7,c:=k.int),(n:=c(n)),(0),
(0,30,50,70),(([]),j:=j+chr(n)),(k:=k.chr),(j:=j+j[3]+k(87//2+57)+k(66//2)),o(j),
@sick hound :white_check_mark: Your 3.12 eval job has completed with return code 0.
Hello World!
💀
I made a idle game
https://github.com/dislux-hapfyl/pynksh check outh all 5 games
Python 3.9.13 (tags/v3.9.13:6de2ca5, May 17 2022, 16:36:42) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> __peg_parser__
File "<stdin>", line 1
__peg_parser__
^
SyntaxError: You found it!
@unreal echo :x: Your 3.12 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "/home/main.py", line 1, in <module>
003 | __peg_parser__
004 | NameError: name '__peg_parser__' is not defined
This was only a "feature" in one or two versions I believe; when the PEG parser was new.
I think "We'll pass a list and call it a tuple so people don't modify it unless they want to in which case they can ignore the typehint (with care)" is terrible design and any typechecker would agree with me
Of course, how bad it actually is depends on the type of code you're writing and who is expected to work with that, but I can't imagine a case where that would be the best or even a good solution
This could come across as a bit hostile, but be assured that I'm not trying to attack you in any way, I just feel strongly about using typehints correctly 😄
wtf is this
The type carries some implicit meanings as well (list = variable amount of homogeneous items, tuple = fixed count and fixed types), which could be considered more important. The problem of inadvertently mutating lists stays, though. I think a separate indicator (perhaps Mutated[list]) would be a better solution.
Nedbat has a related blog post: https://nedbatchelder.com/blog/201608/lists_vs_tuples.html
How can I print the variable FLAG, via the variable pattern?
I have this snippet:
FLAG = "TEST"
pattern = '{{FLAG}}'
print(f"{pattern}")
I am looking to get TEST as output. Pattern variable must be a string, (it gets its value via input() function but for simplicity I hardcoded it). Also the rest of the code (print statement or FLAG variable) cannot change.
# > [TEST] You must send me (PID 14657) the following signals, in exactly this order: ['SIGINT', 'SIGIT2']
# pid="14657"
pid=$(echo $line | python -c 'print(__import__("re").search(r"PID (\d+)\)", input()).group(1))')
# signals="-SIGINT -SIGIT2"
signals=$(echo $line | python -c 'print("-" + " -".join(eval(__import__("re").search(r"order: (.*)", input()).group(1))))')
Any Ideas To Make This Less Cursed? D: (In Bash)
this is a wrong channel to ask for "less cursed" anything 😄
True D:
But, I Thought Maybe If You Can Cook Cursed Code, You Can Uncurse It
if pattern is just the return value of input() (and nothing else happens to it before it is interposed via f"{pattern}") then there is no way to leak the FLAG value
if there was, then fstrings would be fundamentally insecure
yep, I discusses the problem in #cybersecurity and the print statement had also a .format() function which was the actual exploit
ah yea that will make it vulnerable
!paste
If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/
After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.
wow so many bools
yep
woh let this man cook
(have you tried using kill)
Its Specifically For That.
I Wanted To Uncurse The Parsing Such As: signals=$(echo $line | python -c 'print("-" + " -".join(eval(__import__("re").search(r"order: (.*)", input()).group(1))))')
Oh Well, As Long As It Works D:
Its Specifically For That.
are you implementingkill
No,
WELCOME! This challenge makes the following asks of you:
- the challenge checks for a specific parent process : shellscript
- the challenge will require the parent to send number of signals : 5
hello guys, just made a 1-line padding maker in python
s = lambda L,i=0: ([lambda L: s(L.split("\n"), i + 1),lambda S: s((S[:], max(S, key=len)),i+1),lambda S: s((list([" " * (len(S[1]) - len(line)//2) + line + " " * ((len(S[1]) - len(line)//2) + len(line) % 2) for line in S[0]]), len(S[1])),i+1),lambda S: s("\n".join(["+" + "-" * S[1] + "+", *map(lambda L:"|"+L+"|", S[0]), "+" + "-" * S[1] + "+"]), i + 1)][i](L)) if i < 4 else L
the only problem is that the outer marks aren't getting the desired length ¿any ideas on how to debug this beast?
What is it supposed to do?
That's a fun curse
I suppose the bug is the operator precedence in the second lambda S:
for multiline input, should the lines be centered or left aligned?
I'd assume centered
bet, lets me shave off 2 chars
!e ```py
S = lambda L:'\n'.join([h:=f'+{"-"(N:=max(map(len,I:=L.splitlines()))+2)}+',[f'|{l:^{N}}|'for l in I],h])
print(S('abc'))
print(S('a\nabc\na'))```
!e```py
s = lambda L,i=0: ([lambda L: s(L.split("\n"), i + 1),lambda S: s((S[:], max(S, key=len)),i+1),lambda S: s((list([" " * ((len(S[1]) - len(line))//2) + line + " " * (((len(S[1]) - len(line))//2) + len(line) % 2) for line in S[0]]), len(S[1])),i+1),lambda S: s("\n".join(["+" + "-" * S[1] + "+", *map(lambda L:"|"+L+"|", S[0]), "+" + "-" * S[1] + "+"]), i + 1)]i) if i < 4 else L
print(s("""hello world
it is
i"""))
@digital dirge :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | +-----------+
002 | |hello world |
003 | | it is |
004 | | i |
005 | +-----------+
@rugged sparrow :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | +-----+
002 | | abc |
003 | +-----+
004 | +-----+
005 | | a |
006 | | abc |
007 | | a |
008 | +-----+
use fstring specifiers
Oh, we're golfing? I thought the mission was to use lambdas in a really weird way
why not both
split("\n") is 2 chars shorter than splitlines()
you can't inline \n inside a fstring
at least on <3.12
I am still using 3.11
get with the times, old man
!e 3.11
print(f'Hello\nSee ya')
print(f'Hi{"\n"}Bye')
➜ ~ python3.11
Python 3.11.8 (main, Feb 6 2024, 21:21:21) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> f'{"\n"}'
File "<stdin>", line 1
f'{"\n"}'
^
SyntaxError: f-string expression part cannot include a backslash
>>>```
what did you change
oh got it
messed parenthesis
on padding
just upgraded my indexing-lambda tecniques and made a terminal game of guessing a number in 1 line of code 😄
it's scary big though
s = lambda L, i = 0: [lambda L: (()for()in()).throw(ValueError("Expected None as an argument")) if L != None else s(__import__("sys"), i + 1),lambda sys: (()for()in()).throw(ValueError("Expected Python version 3")) if sys.version_info[0]!=3 else s((sys, __import__("random")), i + 1),lambda modules: (lambda sys, rnd:(print("Welcome to the Python random number guesser!") or s(rnd.randint(0,40),i+1)))(*modules),lambda guesser: (lambda guessed_number:(print("Greater than that!") or s(guesser,i)) if guessed_number < guesser else ((print("Smaller than that!") or s(guesser, i) if guessed_number > guesser else (print("You got it!") or s(guesser,i + 1)))))((lambda inp:(print("guess a number!") or s(guesser,i)) if(not(inp().isdigit())) else int(inp()))((lambda v:lambda:v)(input("Guess a number")))),lambda guesser: (print("You want to play again? [y/yes/sure/true]") or (s(None) if input(">>> ").lower() in {"y", "yes", "sure", "true"} else s(True, 5)))][i](L) if i < 5 else L
to play it, just paste that shit on the terminal and call s(None)
could've made L a keyword argument now that I think of it
just noticed that thinks mess up when you ask it to play again
good luck debuggin that sh!t because I won't
Most easy to read code.
continue, Keep it Up.
@earnest snow You Are Chad.
I have a Suggestion. use (_ for _ in ()).throw(...) instead of (()for()in()).throw(...)
or put a list in it that even though it does nothing but makes thing less readable
but my point is that it works in one line
Yep.
if I wanted to obfuscate it more, I would've made a string-obfuscator and I would've used horrible variable names
the funny thing is that it even does the imports in that line and makes sure that is running in python 3
for anyone that actually is trying to read that, this is but separated in the inner list:
s = lambda L, i = 0: [
lambda L: (()for()in()).throw(ValueError("Expected None as an argument")) if L != None else s(__import__("sys"), i + 1),
lambda sys: (()for()in()).throw(ValueError("Expected Python version 3")) if sys.version_info[0]!=3 else s((sys, __import__("random")), i + 1),
lambda modules: (lambda sys, rnd:(print("Welcome to the Python random number guesser!") or s(rnd.randint(0,400),i+1)))(*modules),
lambda guesser: (lambda guessed_number:(print("Greater than that!") or s(guesser,i)) if guessed_number < guesser else ((print("Smaller than that!") or s(guesser, i) if guessed_number > guesser else (print("You got it!") or s(guesser,i + 1)))))((lambda inp:(print("guess a number! >>> ") or s(guesser,i)) if(not(inp().isdigit())) else int(inp()))((lambda v:lambda:v)(input("Guess a number")))),
lambda guesser: (print("You want to play again? [y/yes/sure/true]") or (s(None) if input(">>> ").lower() in {"y", "yes", "sure", "true"} else s(True, 5)))
][i](L) if i < 5 else L
the below thing is good for 1 liner.
def s(L, i=0): [lambda L: (_ for _ in()).throw(ValueError("Expected None as an argument")) if L is None else s(__import__("sys"), i + 1),lambda sys: (_ for _ in()).throw(ValueError("Expected Python version 3")) if sys.version_info[0]!=3 else s((sys, __import__("random")), i + 1),lambda modules: (lambda sys, rnd:(print("Welcome to the Python random number guesser!") or s(rnd.randint(0,40),i+1)))(*modules),lambda guesser: (lambda guessed_number:(print("Greater than that!") or s(guesser,i)) if guessed_number < guesser else ((print("Smaller than that!") or s(guesser, i) if guessed_number > guesser else (print("You got it!") or s(guesser,i + 1)))))((lambda inp:(print("guess a number!") or s(guesser,i)) if(not(inp().isdigit())) else int(inp()))((lambda v:lambda:v)(input("Guess a number")))),lambda guesser: (print("You want to play again? [y/yes/sure/true]") or (s(None) if input(">>> ").lower() in {"y", "yes", "sure", "true"} else s(True, 5)))][i](L) if i < 5 else L
I could change the lower and upper limits to recursive lambdas to make sure you input an integer so that you can choose them ¿no?
s = lambda L, i = 0: [lambda L: (()for()in()).throw(ValueError("Expected None as an argument")) if L != None else s(__import__("sys"), i + 1),lambda sys: (()for()in()).throw(ValueError("Expected Python version 3")) if sys.version_info[0]!=3 else s((sys, __import__("random")), i + 1),lambda modules: (lambda sys, rnd:(print("Welcome to the Python random number guesser!") or s(rnd.randint(s("choose the lower limit >>> ", 5),s("choose the upper limit >>> ", 5)),i+1)))(*modules),lambda guesser: (lambda guessed_number:(print("Greater than that!") or s(guesser,i)) if guessed_number < guesser else ((print("Smaller than that!") or s(guesser, i) if guessed_number > guesser else (print("You got it!") or s(guesser,i + 1)))))(s("Guess a number >>> ", 5)),lambda guesser: (print("You want to play again? [y/yes/sure/true]") or (s(None) if input(">>> ").lower() in {"y", "yes", "sure", "true"} else s(True, 8))),lambda prompt:(lambda inp:(print("guess a number! not that! ") or s(prompt,5)) if(not(inp().isdigit())) else int(inp()))((lambda v:lambda:v)(input(prompt)))][i](L) if i < 6 else L
I moved the input as s(prompt, 5) and reused it to choose about the limits on the randint call
I'm trying to use the forbiddenfruit library https://github.com/clarete/forbiddenfruit/blob/master/forbiddenfruit/__init__.py
to override tuple.__new__ without success. Anyone care to take a look?
I've been slaving over how to shorten this code past 68 bytes:py import numpy;print(*map(chr,numpy.random.randint(32,127,39)),sep='') There's a second one that is also 68 bytes:```py
from numpy import*;print(*map(chr,random.randint(32,127,39)),sep='')
The code generates a random string with length 39 with each character being a random ascii value between 32 and 126, inclusive. Here's a readable code example:```py
import random
string = ''
for i in range(39):
string += chr(random.randint(32, 126))
print(string)
If anyone has any ideas, I would love to know.
It's been weeks and I can't find a way to shorten it further.
from numpy import*;print("%c"*39%(*random.randint(32,127,39),))
``` 63 using string formatting to convert into chars
I had no idea that existed, thank you so much!
Do you have any resources where I can further learn about that?
It's basically C's printf-style formatting
print("template" % (var1, var2)) is roughly printf("template", var1, var2) in C
it's mostly superseded by f-strings and new format strings though
https://realpython.com/lessons/formatting/ here's an article demonstrating it
That is very helpful, thanks a lot!
I still find old-style formatting very useful when strings naturally contain lots of braces (e.g. LaTeX templates), or when doing multi-step formatting.
Does executing this code: 1,2 call tuple.__new__ or tuple.__call__ (or both, and in what order?)
damn...
is there any way to hook into "literal embedding" from within python?
!e
import dis
def print_bytecode(st):
bytecode = dis.Bytecode(st)
for instr in bytecode:
print(instr)
print_bytecode('(x,2)')
print()
print_bytecode('tuple(x,2)')
@elfin ether :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | Instruction(opname='RESUME', opcode=151, arg=0, argval=0, argrepr='', offset=0, starts_line=0, is_jump_target=False, positions=Positions(lineno=0, end_lineno=1, col_offset=0, end_col_offset=0))
002 | Instruction(opname='LOAD_NAME', opcode=101, arg=0, argval='x', argrepr='x', offset=2, starts_line=1, is_jump_target=False, positions=Positions(lineno=1, end_lineno=1, col_offset=1, end_col_offset=2))
003 | Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=2, argrepr='2', offset=4, starts_line=None, is_jump_target=False, positions=Positions(lineno=1, end_lineno=1, col_offset=3, end_col_offset=4))
004 | Instruction(opname='BUILD_TUPLE', opcode=102, arg=2, argval=2, argrepr='', offset=6, starts_line=None, is_jump_target=False, positions=Positions(lineno=1, end_lineno=1, col_offset=0, end_col_offset=5))
005 | Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=8, starts_line=None, is_jump_target=False, positions=Positions(lineno=1, end_lineno=
... (truncated - too long, too many lines)
Full output: https://paste.pythondiscord.com/GYFYQOAUNNC5GC4DHWY3D7RQRM
Is there any way to intercept BUILD_TUPLE?
if you can get the address of _PyTuple_FromArraySteal (used here: https://github.com/python/cpython/blob/main/Python/bytecodes.c#L1589-L1592), then you can use fishhook.asm (if you are on x86 intel, i am still working on cross platform asm hooks)
Python/bytecodes.c lines 1589 to 1592
inst(BUILD_TUPLE, (values[oparg] -- tup)) {
tup = _PyTuple_FromArraySteal(values, oparg);
ERROR_IF(tup == NULL, error);
}```
you could also use a bytecode tracing function, depending on what you want to be able to do
I want to look at the arguments of a tuple when it is created and take some special action based on the args.
yea an opcode tracing function would work for that, you would just need to grab a reference to the stack to look at the args
acc im gonna write some code to use the new monitoring api to do this
gimme like 15, ill ping you when its done
Here's what I'm trying to do:
_ = object()
z = (lambda x, y: x + y), 3, 4, _
assert z == 7
basically i want to check if the last arg to a tuple is some sentinel and then attempt to evaluate the expression described by the other args
if i can replace the BUILD_TUPLE opcode with CALL_FUNCTION I have a way of hooking into tuple.__call__ and can take the desired action. Is swapping out opcodes a possibility
?
swapping opcodes can be doable, but is also tricky due to cpython optimizers and opcodes needing different amounts of cache
hmm
gimme a bit, ill do the stack strategy
thanks m8
>>> x = 1
>>> x,x,x
Stack[0]: (1, 1, 1)
Stack[1]: 1
Stack[2]: 1
(1, 1, 1)
>>>
``` @elfin ether I have this working, but for some reason python unsets the stacktop inside the frame object before I can read it
so its difficult to know what the current offset into the stack should be
https://paste.pythondiscord.com/UFIQ here is what I have so far, ill keep thinking on how to efficiently retrieve the stack pointer
thanks. this isn't super important or anything, so don't spend too much time unless you're enjoying yourself
eh i always have fun writing cursed python
my python 3.12 doesn't have sys.monitoring ...
mine is on 3.12.2
installing 3.13 now
!d sys.monitoring
New in version 3.12.
Note
sys.monitoring is a namespace within the sys module, not an independent module, so there is no need to import sys.monitoring, simply import sys and then use sys.monitoring.
This namespace provides access to the functions and constants necessary to activate and control event monitoring.
As programs execute, events occur that might be of interest to tools that monitor execution. The sys.monitoring namespace provides means to receive callbacks when events of interest occur.
The monitoring API consists of three components...
I'll let y'all burn in anger with this
C:\>python --version
Python 3.10.5
for me python --version is python 2
can we see your code though
what have you tried that doesn't work?
welp, you got me in that
C:\Users\denba>py -3.7 -V
Python 3.7.9
C:\Users\denba>py -3.8 -V
Python 3.8.10
C:\Users\denba>py -3.9 -V
Python 3.9.13
C:\Users\denba>py -3.10 -V
Python 3.10.11
C:\Users\denba>py -3.11 -V
Python 3.11.5
C:\Users\denba>py -3.12 -V
Python 3.12.0
C:\Users\denba>py -3.13 -V
Python 3.13.0a1
Forbidden fruit had issues with hooking __new__, and built-in type constructors aren't typically called when constructed using literals
lol nice
E:\co>py -3.12 -V
Python 3.12.0
E:\co>py -3.10 -V
Python 3.10.11
E:\co>py -3.11 -V
Python 3.11.0
E:\co>py -3.7 -V
Python 3.7.0
E:\co>py -3.6 -V
Python 3.6.0
E:\co>py -3.5 -V
Python 3.5.0
you also can have 32 bit and 64 bit python
py -3.12-64 -V
one of my boxes has both arm and intel python installed
yes but I don't need them
E:\co>py -0
-V:3.12 * Python 3.12 (64-bit)
-V:3.11 Python 3.11 (64-bit)
-V:3.10 Python 3.10 (64-bit)
-V:3.7 Python 3.7 (64-bit)
-V:3.6 Python 3.6 (64-bit)
-V:3.5 Python 3.5
E:\co>```this is all I got
@elfin ether https://paste.pythondiscord.com/4JLA this should work for basic stuff, there are still some edge cases in how I compute the stack top, and sometimes its just flat wrong lol
sadly the stack top value gets yanked out of the stack frame before monitor/trace functions are called, so i need to recreate it (i walk the entire code object and psudo sim the bytecode for that) or grab it off of the C level frame stack
wow what is this
➜ ~/Desktop python3 -i opcode_hook.py
>>> v = (SENTINEL,)
Evaluating: (<object object at 0x104198830>,)
>>>```
the versions of python I have
Why are you defining empty Structures and filling _fields_ afterwards?
consistency for when need types that reference themselves i guess
oh yeah they do reference themselves
Ah, right..
@quartz wave yo i am trying to fix up my cross platform fishhook.asm, did you ever test fishhook.asm on windows and did it work?
i tried adapting it for windows but it doesn't work
there's the problem with libc (and therefore libc.mprotect()) not being available and there's the problem with windll.kernel32.VirtualProtect() not working (it causing a DEP violation)
there's also a negative offset but i don't know if that's a problem
ah negative offset will prob be fine in my new system, need to fix the VirtualProtect issue tho
my new system compiles the assembly on demand using KeyStone, so itll generate the correct relative jump instructions
just working on getting the virtual protect stuff correct (i think windows was complaining because memory cant be RWX at the same time)
also testing on x86 is a pain for me rn, my main device is an Arm Macbook
but if i get the VirtualProtect stuff to work on windows arm, it should be correct for x86, and the weird cache stuff that I am working on now is only relevant for arm, x86 invalidates automatically as a side effect of the architecture
are you able to use a vm?
the eventual goal is to be able to specify asm injection points using a psudo language, and use the Capstone decompiler to find indexes
a lot of JIT code like this relies on physical architecture behavior, which are not things that VM authors tend to implement fully
ah
i am able to test on ARM windows, because it is ran by apples hypervisor on the actual arm chip, which means it has the correct quirks
i have an x86 machine if you want me to test stuff for you
but x86 code is ran via rosetta or another emulation/translation engine
its all good, i have an x86 laptop, i just need to fix it up lol
ah good
end product from this project will be cool tho, goal is cross platform asm injection via python. (and stretch goal is for it to work on other executables via LD_PRELOAD or a harness program)
so really low level C level hooks, but you can write them in python
what architectures will be supported?
the goal is ARM64 and x86-64, and Windows, MacOS/UnixLike operating systems
also i'm an amateur at this so i just sort of merged cpython's source code with the current asm code
fun
making progress, but will need to spend some more hours on it
also rn uses GCC's cache invaliator, so ill prob cross compile a bunch of wheels once it works
it makes sense that libc.mprotect was not available, its a unix specific feature
I ended up having to move to a C module because when you are changing protections of memory ranges willy nilly, you really want to make sure you don't accidentally call any functions that are currently marked RW (read/write), instead of RX (read/execute)
None
@quartz wave making progress, got my 64bit arm trampoline to work, now to write my x86 one
arm64_trampoline = '''
sub sp, sp, #0x10; # make stack space for 2 64bit registers on stack (16 bytes)
stp x28, lr, [sp]; # save x28, lr onto stack
ldr x28, =0x{address:x}; # load 64bit address into x28
blr x28; # branch and link to [x28]
ldp x28, lr, [sp]; # restore x28, lr from stack
add sp, sp, #0x10; # clear stack space (16 bytes)
ret;
'''
x86_trampoline = '''
push r15; # save r15 register on stack
mov r15, 0x{address:x}; # move 64bit address into r15
call r15; # call r15
pop r15; # restore r15
ret; # return to caller
'''
``` woot x86 works
now to test windows builds, and then v1 of the new fishhook.asm will be done
also gonna shrink the arm asm, have some ideas to make it more efficient
Once the underlying tooling for cross platform injection works, I'm gonna start working on dynamic injection points and other fun tricks
ok so hooks on x86 windows are sorta functional, it gets inside the hook fine, just crashes after leaving it
weird
is there any REPL for asm?
i know it is crazy, but still...
nvm, i just had to google it...
i don't have a ton of time to debug windows today, will probably push this version since it should work on the bot later tonight
@quartz wave https://pypi.org/project/fishhook/ pushed 0.3, has the new asm code, sadly no windows support yet
@fleet bridge ^ you might want to take a look too
im on windows 😄
Python 3.12.0 (tags/v3.12.0:0fb18b0, Oct 2 2023, 13:03:39) [MSC v.1935 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import fishhook
>>> import fishhook.asm
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\Programs\Python\3.12\Lib\site-packages\fishhook\asm.py", line 5, in <module>
raise RuntimeError('fishhook.asm does not currently work on Windows')
RuntimeError: fishhook.asm does not currently work on Windows
``` i can confirm your RuntimeError does work :)
>>> fishhook._asm.writeExecutableMemory(b'123',b'456')
``` i managed to crash the process
yea thatll do it lmao
why is it a native extension? couldn't that be done using ctypes?
modern OS don't like rwx memory pages
so i toggle to rw, write the memory, and toggle to rx
but that means i am marking an entire 4Kb page of function memory as rw
using ctypes means that I can't control if functions inside that page run
now i get it, it makes sense
ironically, the writeExecutableMemory works on windows
its just some other part of my chain gets upset
modern operating systems are so silly
i know its a security thing but like
yea gosh darm them wanting security
its so boring to not be able to write and execute
openbsd when you try to W&X memory
well it works to just toggle really fast lmao
once this pushes to the bot tho i can send some really weird sample code
the amount of hoops i need to jump thru to make sure NULL pyobjects are handled properly due to this single set of 13 lines of code is insane: https://github.com/python/cpython/blob/main/Modules/_ctypes/cfield.c#L1077-L1089
Modules/_ctypes/cfield.c lines 1077 to 1089
static PyObject *
O_get(void *ptr, Py_ssize_t size)
{
PyObject *ob = *(PyObject **)ptr;
if (ob == NULL) {
if (!PyErr_Occurred())
/* Set an error if not yet set */
PyErr_SetString(PyExc_ValueError,
"PyObject is NULL");
return NULL;
}
return Py_NewRef(ob);
}```
just patch ValueError, so that it is no longer an exception class 🤷
and then whatever happens happens
this function is probably inlined everywhere, right? so it is not possible to patch
It's not inlined anywhere, I could patch it out, but I don't want to break other code that depends on the value error
Current plan is a custom C subclass of _ctypes._SimpleCData
And I'll write custom get and set functions in C
welp ctypes.h is not included in the default python includes, and the way that get and set functions work changed in 3.13
so i think i will leave handling of NULL py_objects up to the user, since it probably won't be a super common use
and if i think of a clean way to implement later Ill do that
in the meantime, next feature is direct register hooks
@fleet bridge now you can pass registers={<reg name>: <ctype>, ...} into the asm.hook decorator and use ```py
def hookname(*args, * , registers):
print(registers.<reg name>)
and you can set registers.<regname> and it will be set once your function returns
(it will be vastly unstable lol)
@quartz wave if you want to test on windows, the c code should work i think. It just crashes in a weird spot and I did not have time to debug properly, if you can find anything regarding the crash I can probably fix it
you just need to patch out the os check in fishhook.asm
hi
!e @quartz wave @fleet bridge can now try out fishhook.asm inside the snekbox, just need some weird metacode to bypass 3.12 deprecating distutils: ```py
(lambda S:import('sys').modules.update({'distutils':S(),'distutils.sysconfig':S(),'pkg_resources':S()}))(type('',(),dict(getattr=lambda s,a:s,call=lambda s,*a:'')))
from fishhook.asm import get_interned_strings_dict
print(get_interned_strings_dict())```
@rugged sparrow :white_check_mark: Your 3.12 eval job has completed with return code 0.
{'__subclasses__': '__subclasses__', '__basicsize__': '__basicsize__', '__itemsize__': '__itemsize__', '__flags__': '__flags__', '__weakrefoffset__': '__weakrefoffset__', '__base__': '__base__', '__text_signature__': '__text_signature__', 'ag_running': 'ag_running', 'ag_await': 'ag_await', 'ag_frame': 'ag_frame', 'ag_code': 'ag_code', 'ag_suspended': 'ag_suspended', '__alloc__': '__alloc__', 'capitalize': 'capitalize', 'center': 'center', 'expandtabs': 'expandtabs', 'fromhex': 'fromhex', 'hex': 'hex', 'isalpha': 'isalpha', 'isascii': 'isascii', 'isdigit': 'isdigit', 'islower': 'islower', 'isspace': 'isspace', 'istitle': 'istitle', 'isupper': 'isupper', 'ljust': 'ljust', 'removesuffix': 'removesuffix', 'rindex': 'rindex', 'rjust': 'rjust', 'swapcase': 'swapcase', 'title': 'title', 'zfill': 'zfill', '__self__': '__self__', 'cell_contents': 'cell_contents', '__objclass__': '__objclass__', '__func__': '__func__', '__wrapped__': '__wrapped__', 'co_lines': 'co_lines', 'co_positions': 'co_pos
... (truncated - too long)
Full output: too long to upload
capstone depends on distutils for right now, newer version should remove dependency when they distribute it
# New Object
Woman = type('Woman', (object,), {'content':{}})
We getting certain political affiliations with this one 🗣️🗣️🗣️🔥💯
lmao
Why Political Tho? Can Be Done For Anything Else Too 😶🌫️
why did you inherit it from object
it is already object
though why 'content' is a empty dict
because man know nothing about woman?
Plot Twist: Woman Wrote The Code
hello all! do you guys remember the evil trick which replaced the globals dict type with a custom object which would just return the dict's key??
# evil trick
@type.__call__
class Globloglabgalab:
def __getitem__(self, name):
# try get from globals, but if we cant,
# return, the key's name
globals()[name] = name
# would not raise an error about the var not being found
print(hello)
# >>> hello
I think you already know 
yea there was more to it then that, i think its here if you scroll up
no I don't now tell me
else...
((they wouldn't ask if they already knew))
DEP violation
that's what it says
and i don't really know how to use a debugger on an assembly file
Ooo ok, that actually tells me a lot. Means some memory is not being set as executable for some reason
lol why do people prefer something weird like tuple.__itemsize__ over just 8
because 8 is not correct for every machine
tuple.__itemsize__ is sizeof(PyObject *)
pointer size varies between machines
(some older machines even have different types of pointers with different sizes!)
how did fuckit do it so that the module is callable? if module attributes can be changed from within the module itself, I've got quite an evil idea.
you can set sys.modules[yourmodulename] to any object
fuckit.py line 207
sys.modules[__name__] = _fuckit('fuckit', __doc__)```
what olivia said
Indeed
In a while I'll send an absolute catastrophy using that
@dry mirage I remember a while back we were talking about fishhook.asm and it didn't work on your ubuntu machine, pushed an update with a brand new asm hook strategy that now builds an absolute address for the jump, it works on x86 and ARM64 Unix like (tested on macos, kali, and ubuntu), working on fixing up windows now
Oh neat, would love to try. Did you have to do different strategies for arm64 addresses?
https://github.com/chilaxan/fishhook/blob/master/fishhook/jit.py#L49-L70 I build a assembly trampoline, based off of what a given hook needs
using fragments for arm64/x86
https://github.com/chilaxan/fishhook/blob/master/fishhook/jit.py#L90-L115 this is where the actual trampoline is built
basically for both, it backs up a temporary register, loads the 64bit constant into a temporary register, calls it, then restores the temp register
it also generates asm instructions to allow for reading and writing some registers via a hook
!e ```py
from fishhook.jit import *
address = 0xdeadbeefdeadbeef
payload = '\n'.join([
inst('push', TMP_REG),
inst('load_const', TMP_REG, address),
inst('call', TMP_REG),
inst('pop', TMP_REG),
inst('ret')
])
print(payload)```
@rugged sparrow :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | push r15;
002 | mov r15, 0xdeadbeefdeadbeef;
003 | call r15;
004 | pop r15;
005 | ret;
does your get_interned_strings_dict() mechanism require an exception be raised?
it shouldn't
because one thing i noticed in the debugger is that an exception was apparently raised and attempted to be displayed
but got suppressed by the fatal error from the DEP
python exception or windows exception
idk
hmm
i have theories on why its not working, been doing research to see if there is a memory protection cache
and its also possible that the memory areas are too close together
the weird thing I see is that the hook successfully fires (like if you add a print, it outputs)
ok i got the contents
it's an OSError about an access violation writing to some address
it's sandwiched between 2 fatal exceptions btw
Of course it is lmao
no that was me being sarcastic lol
this testing is really helpful
can you change the third arg of https://github.com/chilaxan/fishhook/blob/master/fishhook/asm.py#L43 and https://github.com/chilaxan/fishhook/blob/master/fishhook/asm.py#L48 to PREAD | PWRITE | PEXEC (import them from fishhook._asm)
fishhook/asm.py line 43
writeExecutableMemory(mem, default)```
`fishhook/asm.py` line 48
```py
writeExecutableMemory(mem, trampoline)```
that will set the memory after writing to the most permissive
its possible there is a section of memory that I am marking as Read/Execute that still needs to be Writeable as well
oki
i think its a keyword arg prot_after
so: py writeExecutableMemory(mem, default, prot_after = PREAD | PWRITE | PEXEC) and py writeExecutableMemory(mem, trampoline, prot_after = PREAD | PWRITE | PEXEC)
that still might be a good thing to try 🤷♂️
discard the 2 fatal errors with the OSError
i did a weird thing that caused it :p
sori
tbh the failures it has on windows are likely to cause DEP fatal errors
your all good
i am gonna add some code to _asmmodule.c at somepoint, rn it doesnt call https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-flushinstructioncache because I assumed that x86 does it automatically
i might have been wrong
it goes through ctypes then errors at some place which i assume is the changed memory
this https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect also might need to be the base address of a memory page, right now its the address of the injected instructions
this is with the prot_after = PREAD | PWRITE | PEXEC?
ill make some updates to the C code tonight after I eat dinner, ill ping when there is an update on github (you will have to install from source tho cause I don't wan't to push new wheels till i fix this)
could just use this snippet of code i think
https://github.com/python/cpython/blob/main/Python/jit.c#L95-L103
Python/jit.c lines 95 to 103
// Do NOT ever leave the memory writable! Also, don't forget to flush the
// i-cache (I cannot begin to tell you how horrible that is to debug):
#ifdef MS_WINDOWS
if (!FlushInstructionCache(GetCurrentProcess(), memory, size)) {
jit_error("unable to flush instruction cache");
return -1;
}
int old;
int failed = !VirtualProtect(memory, size, PAGE_EXECUTE_READ, &old);```
thank you cpython jit devs
@quartz wave just pushed the addition, not at my windows machine to test compile, but if you pull the git and test that would be great
ill test on my vm, but it has been unreliable in the past with fishhook lol
my pc malfunctioned when i tried to see what changed
maybe i did something
it's not turning back on fully
maybe i should try to be more careful about this next time
its not turning on??
that def should not happen
it shouldn't have been able to do anything more then crash python
hmm
it's on a cycle of turning on for some time, off, repeat
monitor is unresponsive
so i can't test rn
do a full power cycle
huh?
yeah i did that
and its still failing to boot?
thats concerning
I am gonna stick to testing on my own hardware now
i don't want to break anyone's stuff
smh its like they dont want us to golf anymore
fyi this has come up multiple times here before
oh ok
!e also ```py
a = True
print(~a)
@quartz wave :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | /home/main.py:2: DeprecationWarning: Bitwise inversion '~' on bool is deprecated. This returns the bitwise inversion of the underlying int object and is usually not what you expect from negating a bool. Use the 'not' operator for boolean negation or ~int(x) if you really want the bitwise inversion of the underlying int.
002 | print(~a)
003 | -2
if there is a sign there is a story behind it
is there a way to return something custom when I use something like MyClass and Myclass and MyClass or MyClass
rather not have it be very weird code just thought this is best place to ask
Not really. You can customize which side should be returned (by implementing __bool__), but not much more.
do you care if the object gets overwritten?
because you could have __bool__ check why it was called, and if it was because of an and or or operator, modify itself in memory to be a different object via ctypes
you'd have to be careful about the size of the object you return, but it should be possible
that's straight up trying to make python unsafe
You are aware what channel you are in? :)
I'm making a whole python library in one line, of course I am
wdym
its not going to bite you
you're perfectly safe
Memory safe by replacibg memory addresses using ctypes
Everything is memory safe if you do things right, the point is that you can mess everything up
Everything is memory safe if you do things right
exactly
people should stop making mistakes so often
memory unsafe stuff is perfectly fine for this channel
@earnest snow would it make you feel better if we implement it by swapping out the return value on the frame stack itself?
i have demo code for that
The or/and thing? That's probably a better idea yeah
I'll write a proof of concept
py
!e ```py
from fishhook import hook
@hook(str)
def eq(s,o):return 1
exec(r'''
if "School" == "Hell":
print("fuck")
else:
print('still bad but better I guess')
''')
@quartz wave :white_check_mark: Your 3.12 eval job has completed with return code 0.
fuck
LAMAO
Why in an exec?
any idea how to golf this further
import sys
D=-1,0,1
E=enumerate
for Y,l in E(A:=sys.argv[1].split('\n')):print(''.join('.#'[4+('.'>c)>sum(len(l)>X+x>-1<Y+y<len(A)!='.'>A[Y+y][X+x]for y in D for x in D)>2]for X,c in E(l)))```
it simulates the next generation of a conways game of life game
because of optimizer
optimizer doesn't optimize comparisons
i just tested it out in #bot-commands after that
interesting...
string munging is so fun
Just free the memory properly 🗣️🗣️🔥
https://github.com/disentcorp/dateroll sweet library to make date math easier
exactly
if you are new, you aren't supposed to be in this channel because this channel is filled with horrible nightmares of python, you should explore other channels like #python-discussion
!res for you
The Resources page on our website contains a list of hand-selected learning resources that we regularly recommend to both beginners and experts.
Welcome to the best channel, where you get 100% taught real, correct and idiomatic Python
here we do things the Pythonic way
daterewind
bitter library to make date english harder
I need to track the existence of an extension type that doesn't allow me to create weak references to it. Any ideas?
Background is, I'm working with pyodbc.Connection objects, and something somewhere is leaking them. I've been pulling my hair out trying to figure out what, so I'd like to track the existence of those objects directly to figure out which ones are sticking around longer than they are supposed to. The obvious way to do this would be with weak references, but when I try I get cannot create weak reference to 'pyodbc.Connection' object, so that's out. Is there some other way? I could save the id of each Connection object, which is just the memory address IIUC, but is there a way to safely inspect that memory address later on and determine whether this is still the same object?
I can't assign new properties to the Connection object the usual way, but maybe there's a hacky way around that? Then I could attach a marker object to the Connection and just watch for it to be cleaned up?
you can override pyodbc.Connection.__del__ and implement some logic there
I can't seem to override properties on either the instance or the class itself
and I don't think I can subclass it because there's no way to tell pyodbc to give me a different class when I ask it for a connection
ok, just ran across this, which might constitute selling my soul to the devil but will also probably work? https://stackoverflow.com/questions/24497316/set-a-read-only-attribute-in-python/24498525#24498525
have you tried fishhook or forbiddenfruit ?
Fishhook will work for extension classes, might even let you add a __weakref__ property to enable weakrefs
in normal cases __weakref__ is a slot, and slots require some space in object struct
i dont think you can add legit slots with fishhook, but adding __weakref__ descriptor should be possible (but it would require some external storage, because there is no space in the object itself)
Yea I meant the descriptor, I haven't made fishhook so cursed that it allocs new slotvars quite yet
do it
Thought of a fun one: programs without literals
there arent any cases i can think of where that would affect things overly much
Here's a fun question. Is it possible to create a generator object or a coroutine object with a single expression using these rules?
- The only available builtins are:
str,int,float,randint(fromrandom) andfoo(a custom Python function) - Attributes starting with
func_or__are not allowed - Attributes
formatandformat_mapare not allowed - Lambdas are not allowed
- Generator expressions are not allowed
I know this is weirdly specific... it is
i think disallowing generator expressions is redundant since they're already disallowed by containing multiple subexpressions
No no, subexpressions are allowed
So str(str(str([x for x in [1, 2, 3]]))) is good
with a single expression
That's a single expression, a function call
I meant that you can't have import, def, or just multiple separate expression statements
sorry if that was unclear
So what you can do is create literals, use operators, and use methods/attributes that meet the above rules
til you can make a generator without a genexpr or import
You mean, the good ol' yield inside a function?
Oh I don't know if it's actually possible, I want to find out 🙂
lmao
lmao
i don't think it's possible with those restrictions
with lambda yes
with no lambda there is nothing we can do
!e
print(lambda: (yield))
@formal sandal :white_check_mark: Your 3.12 eval job has completed with return code 0.
<function <lambda> at 0x7fd42ad22a20>
what does foo do
def foo(x):
"""docstring"""
return int(random.random()*x)
dynamic literals ([], (), {}, "")
list(), tuple(), dict(), str()
yeah but constructing them with elements will take more lines of code than usual
yeah that's true
1 is (list()==list()), and you can get strings with chr
so string literals will be kind of brainfuckesque
t = 1, 2, 3
``` `1, 2, 3` here is technically a literal
i mean this sort of works ```py
T = lambda *args: args
t = T(1, 2, 3)
assuming 1, 2, and 3 are substituted with their non-literal equivs
here's how to create a list ```py
*t, = T(1, 2, 3)
print((1, 2, 3))
ez
that just writes it to stdout that doesn't return it
equivalent ones can be constructed without literals
Are there any way to get eval(not in string, in function) without using compile, exec, eval and use as few amount of alphabet character as possible
programming warcrimes in yt
Unrelated
that's how i wrote a print("Thanks!") program ```py
import collections
import contextlib
import io
import itertools
with contextlib.redirect_stdout(this := io.StringIO()):
import("this")
(*(0, 1, 36, 57, 286, 296, 855),) # ?????
magic = collections.Counter(loader.get_code(name).co_consts[~3])
print(*itertools.compress(this.getvalue(), map(magic.get, itertools.count())), sep="")
are imports allowed?
no, since import x is not an expression
i especially like the (*(0, 1, 36, 57, 286, 296, 855),) # ????? part ❤️
but i meant __import__().
i guess it's not in the
that's not in the "builtins" so that's not available
btw if you dont have __import__, then import statement would not work either

is random defined in the scope of foo?
no, only randint
so that function basically doesn't work, interesting
wait, are we allowed to write code in foo?
excluding attributes starting with __ makes this so much harder :D
i believe it's a builtin
we aren't
it is possible to create a generator object if only str is directly available, but dunder attrs ain't disallowed xd
i'll actually dump my thinking here
as i solve that challenge
>>> print(*[(i,c) for i,c in enumerate(str.__base__.__subclasses__())],sep='\n')
(0, type)
(1, async_generator)
(2, bytearray_iterator)
(3, bytearray)
(4, bytes_iterator)
(5, bytes)
(6, builtin_function_or_method)
(7, callable_iterator)
(8, PyCapsule)
(9, cell)
(10, classmethod_descriptor)
(11, classmethod)
(12, code)
(13, complex)
(14, _contextvars.Token)
(15, _contextvars.ContextVar)
(16, _contextvars.Context)
(17, coroutine)
(18, dict_items)
(19, dict_itemiterator)
(20, dict_keyiterator)
(21, dict_valueiterator)
(22, dict_keys)
(23, mappingproxy)
(24, dict_reverseitemiterator)
(25, dict_reversekeyiterator)
(26, dict_reversevalueiterator)
(27, dict_values)
(28, dict)
(29, ellipsis)
(30, enumerate)
(31, filter)
(32, float)
(33, frame)
(34, frozenset)
(35, function)
(36, generator)
...
``` just take 12th `object` subclass, create a `code` object out of it, then make `function` object (35th `object` subclass), then call it to get a generator
i dont think this challenge is possible
you cant use dunders
obviously
:incoming_envelope: :ok_hand: applied timeout to @tranquil yarrow until <t:1712968871:f> (10 minutes) (reason: newlines spam - sent 126 newlines).
The <@&831776746206265384> have been alerted for review.
!unmute 712654007876976750
:incoming_envelope: :ok_hand: pardoned infraction timeout for @tranquil yarrow.
!paste
If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/
After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.
pls
thanks, sorry.
yes, it is possible, but on Python <3.8 (the question didn't state what exactly the version has to be and whether it must be before EOL).
Python 3.7 example generator object created with a single expression using the rules:
[(yield) for _ in ()] # <generator object <listcomp> at ...>
the ability of using yield expressions inside implicit scopes (which includes list/dict/set comprehensions) was removed in 3.8.
moreover, afaik list/dict/set comprehensions no longer create implicit scopes since Python 3.12 due to inlined comprehensions.
on Python 3.8+, here's my modest progress as for now. cc @formal sandal
after a closer look, I observed a few things.
first, I assume some of the rules are just to distract.
there are no func_* attributes that could possibly help solving the problem.
I am also not sure how <I guess str>.format or <I guess str>.format_map would help, but I didn't check.
foo seems completely useless either and it was not clear whether it even worked (is random defined in foo.<locals>?)
I assumed we might somehow get something useful from the attributes matching the constraints, but I didn't find anything useful:
https://paste.pythondiscord.com/YBWA
as you can see, nothing interesting here.
if you have any more ideas/hints where I can explore further, let me know.
cc @fleet bridge
i think you forgot about .mro()
this allows you to get reference to object
not sure what to do with it though
>>> int.mro()
[int, object]
>>> int.mro()[1]
object
i don't see any useful attributes in object.
yeah, there are only dunders and .mro() once again
regardless, mro() was a good catch!
I also tried to check for some existing generators in gc.get_objects() and determine where they come from.
I found some spots in the stdlib where I can create generators, but they are not accessible in any legal (as in the question) way.
I was hoping I will get there through randint, but I can't.
nothing really useful there.
@formal sandal is random defined at the global scope?
that would probably simplify a lot
because then I could use random._os.walk()
and voilla, we have a generator.
WAUT THAT WASNT A DUNDER>
it's both a type method and dunder attribute
there is a __mro__ descriptor and mro method on classes
>>> [*bytes.maketrans(b'', b'')] == [*range(256)]
True
this code ^ also observes objects that are results of calling methods
i would also recommend adding this somewhere before the code ^, it adds nice reprs to some builtin objects that dont have nice reprs: https://paste.pythondiscord.com/HYIA
{self: str,
'capitalize': {self: str.capitalize, str.capitalize(): ''},
'casefold': {self: str.casefold, str.casefold(): ''},
'center': {self: str.center},
'count': {self: str.count, str.count(, ): 1},
'encode': {self: str.encode, str.encode(): b''},
'endswith': {self: str.endswith,
str.endswith(, ()): False,
str.endswith(, ): True},
'expandtabs': {self: str.expandtabs, str.expandtabs(): ''},
'find': {self: str.find, str.find(, ): 0},
'index': {self: str.index, str.index(, ): 0},
'isalnum': {self: str.isalnum, str.isalnum(): False},
'isalpha': {self: str.isalpha, str.isalpha(): False},
'isascii': {self: str.isascii, str.isascii(): True},
>>> object.__dict__
mappingproxy({ '__new__': object.__new__,
'__repr__': sc._@__repr__,
'__hash__': object.__hash__,
'__str__': object.__str__,
'__getattribute__': object.__getattribute__,
'__setattr__': object.__setattr__,
'__delattr__': object.__delattr__,
'__le__': object.__le__,
'__eq__': object.__eq__,
'__ne__': object.__ne__,
'__gt__': object.__gt__,
'__ge__': object.__ge__,
'__init__': object.__init__,
'__reduce_ex__': object.__reduce_ex__,
'__reduce__': object.__reduce__,
'__getstate__': object.__getstate__,
'__subclasshook__': object.__subclasshook__,
'__init_subclass__': object.__init_subclass__,
'__format__': object.__format__,
'__sizeof__': object.__sizeof__,
'__dir__': object.__dir__,
'__class__': <slot object.__class__>,
'__doc__': 'The base class of the class hierarchy.\n\nWhen called, it accepts no arguments and returns a new featureless\ninstance that has no instance attributes and cannot be given any.\n',
You could use str.format to access any attribute inside of foo's global scope, but repr/str will be called on it
unless getting this attribute has side effect, it is useless
we can get arbitrary strings by just writing string literal
also, *.format is forbidden
Oh welp
Can sm1 help me with an phyton project
yeah but much would change by then
not equivalent but whatever makes you happy i guess
do coroutines count?
oh wait i guess they aren't generators by themselves
but they do share the same object structure as generators..
anyone have an idea on how to golf this further
import sys
for b in sys.argv:
r=[a:=0]*99
for i in b:b+='\n'+' '*a+'a+=1 a-=1 r[a]+=1 r[a]-=1 print(end=chr(r[a])) while-r[a]: 0'.split()[n:='><+-.['.find(i)];a+=n//5
exec("#"+b)```
ive been trying to make the big string shorter recently but cant figure out anything
no
wtf am i seeing
first time here?
every time i consider trying hard drugs, i look at this channel to scare myself out of it
Oh that's very interesting. Good finding
lmao
decrease indentation i guess
indentation is tabs discord just automatically changes it to spaces
8
?
this is for that sandbox thing i assume?
yeah 🙂
@fleet bridge > bytes.maketrans(b'', b'')
that was fun
thanks 😊
i am tempted to write code that will do random stuff with random objects and keep track of results, but im scared it will rm -rf / my machine 🙂
since i want to get results, killing a system every time is not a good option
even VM wont help much
is it possible to fork the process into different physical machine? 🤔
you could do a vm and clone it each time you brick it
or wsl
you can make copies easily
well, if i brick it before i observe useful results, then it is useless
You could use something like qemu
what do you mean by [do random stuff with random objects]
literally that
get some attributes, call objects, construct new objects, etc...
it might be useful in challenges, where some restrictions are present. And such tool can help us observe space of possibilities
why do you worry about removing your root directory then
as long as you're not calling a few specific functions you'd be fine
the whole point of the thing is to not do the search manually
and i dont think it is possible to reliably tell if operation X will blow your system
even simple a.b can invoke a descriptlr, which will call os.system(...)
you dont need to reliably tell
you just need to unconditionally block things which could blow your system
e.g. os.system
probably os.* actually
(really posix.*!)
(or whatever the windows equivalent is i guess)
ok
but should i block open(...)? pathlib.*? socket.*? ctypes? _ctypes? threading? multiprocessing?
ok, what about normal stuff? a:int; b: int; s: str; l: list: a*b? a**b? a<<b? s*a? l*a?
fyi, it is theoretically possible to crash the process with ast.safe_eval (or rather anything that performs code parsing, since parsing untrusted input can crash)
and in this case, everything is "untrusted", because it comes from unknown source and can be of any value (because it is constructed randomly from random objects)
block things that read from or otherwise interact with the file system or processes and such in a noncontrolled way
second row of examples don't necessarily destroy the system, but they can take up entire memory of your machine
but they can take up entire memory of your machine
that can be prevented
so can all of the first row too, but it'd be more work probably since there are more of them
how would you block that? with trace function? it can be messed with/deleted/...
you can tell the operating system to not give you very much memory
hook malloc to fail early
etc.
>>> import _testcapi
>>> _testcapi.crash_no_current_thread()
Fatal Python error: PyThreadState_Get: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL)
Python runtime state: initialized
Thread 0x000040cc (most recent call first):
File "D:\GitHub/cp_exts\sc.py", line 175 in target
File "D:\Programs\Python\3.12\Lib\threading.py", line 989 in run
File "D:\Programs\Python\3.12\Lib\threading.py", line 1052 in _bootstrap_inner
File "D:\Programs\Python\3.12\Lib\threading.py", line 1009 in _bootstrap
Current thread 0x00001254 (most recent call first):
File "<stdin>", line 1 in <module>
Extension modules: _xxsubinterpreters, _xxinterpchannels, psutil._psutil_windows, _wmi, _testcapi (total: 5)
[process exited with code 3221226505 (0xc0000409)]
lots of ways to do things
i dont know what this is meant to show
that you should also block _testcapi i guess?
that there are too many ways to do stuff, and it is pretty hard to block them all
pretty hard, yes
but you wanted to prevent it from deleting your files, not from crashing the process
the one has a lot less ways of doing things than the other
ultimately to read files, it's going to have to execute a syscall
is your goal to determine code constructs with odd side effects?
my goal is to automatically solve challenges like this ^
ah
in my experience challenges like that depend on such specific side effects that you need to be very specific with them
idk if a random generator is gonna find successful techniques
i think randomly generating would be less useful than a breadth-first exhaustive search
obviously it'd go on forever but you might find some interesting stuff after 2 or 3 layers
fair fair
also do we know if that challenge is actually possible?
does this challenge actually have a solution (on newer python versions that disallow [(yield) for () in ()])?
i dont believe so
It's not a riddle, it's more of an exploratory question 🙂
There's a small but somewhat popular library that I've kind of... deconstructed, and it could have a serious vulnerability if it's possible to complete the challenge
Luckily the listcomp trick doesn't work on it
If you're willing to DM me the library, there may be other side effects that can be abused to bypass the syntax whitelist you gave
!e
match = 1
case = 1
match match:
case case:
print("match case")
@covert rivet :white_check_mark: Your 3.12 eval job has completed with return code 0.
match case
should be illegal
match case:
case match:
...
and you made it from illegal to war crime I think
lloool
!e ```py
match = 7
case = 5
match match-case:
case match:
print("ooh")
print(case-match)
@quartz wave :white_check_mark: Your 3.12 eval job has completed with return code 0.
001 | ooh
002 | 3
the syntax highlighting hurts
ok i got my pc back
the changes don't work btw
it's the last thing i tried before my pc entered limbo
I figured
if only this could be done for all keywords
We had a discussion a while back, about which keywords could be made soft. Turns out it's almost all of them.
l=[9,5,7,4,0,2,6,3,1,8]
while any(l[x]<l[x-1]and(a:=l[x],l.insert(x-1,a),l.pop(x+1))for x in range(1,len(l))):print(l)```
Bubble sort successfully golfed, what next?
quick
blocksort could be fun
blobsort
ha, can't golf it if it doesn't exist
proceeds to invent (or rather, find?
) a new sorting algorithm to then golf it
blobsort seems like it would be a variation of bucket sorting
blobsort 🤔
@magic wraith :white_check_mark: Your 3.12 eval job has completed with return code 0.
[2, 3, 5, 5, 6, 6, 9, 10, 13, 16, 26, 33, 44]
make golfed bogo-bogo-bogo sort
was actual bogo sort ever golfed here?
!e py from random import* from itertools import* a=[7,6,1,3,8,4] while 1-all(i<=j for i,j in pairwise(a)):shuffle(a) print(a)
@magic wraith :white_check_mark: Your 3.12 eval job has completed with return code 0.
[1, 3, 4, 6, 7, 8]
if imports are not negligible, then py while 1-all(i<=j for i,j in zip(a,a[1:])):shuffle(a)
if imports are negligible, then
while 1-all(map(ge,pairwise(a))):shuffle(a)
*le
actually it should be starmap also
this is a surprisingly good RNG: py [id(x)%9 for x in [[]for _ in range(1000)]] ```py
n = 100_000
x = [id(x)%9 for x in [[] for _ in range(n)]]
c = collections.Counter(x)
{i: round(c[i] / n, 3) for i in range(9)}
{0: 0.111, 1: 0.111, 2: 0.111, 3: 0.111, 4: 0.111, 5: 0.111, 6: 0.111, 7: 0.111, 8: 0.111}
there seems to be a pattern in there
>>> d = lambda x,p: (c:=__import__('collections').Counter(x),n:=sum(c.values()),{i: round(c[i] / n, 3) for i in range(p)})[-1]
>>> d([id(x)%9 for x in [[] for _ in range(10_000)]], 9)
{0: 0.111, 1: 0.111, 2: 0.111, 3: 0.111, 4: 0.111, 5: 0.111, 6: 0.111, 7: 0.111, 8: 0.112}
>>> d([id([])%9 for _ in range(10_000)], 9)
{0: 0.0, 1: 0.0, 2: 0.0, 3: 1.0, 4: 0.0, 5: 0.0, 6: 0.0, 7: 0.0, 8: 0.0}
>>> d([id(_ * _)%9 for _ in range(10_000)], 9)
{0: 0.337, 1: 0.0, 2: 0.001, 3: 0.325, 4: 0.337, 5: 0.0, 6: 0.0, 7: 0.0, 8: 0.0}
>>> d([id(_ ** _)%9 for _ in range(10_000)], 9)
{0: 0.013, 1: 0.073, 2: 0.052, 3: 0.057, 4: 0.193, 5: 0.315, 6: 0.212, 7: 0.013, 8: 0.072}
>>> d([id(_ ** _)%9 for _ in range(10_000)], 9)
{0: 0.121, 1: 0.028, 2: 0.14, 3: 0.024, 4: 0.068, 5: 0.239, 6: 0.233, 7: 0.104, 8: 0.044}
>>> d = lambda x,p: (c:=__import__('collections').Counter(x),n:=sum(c.values()),{i: round(c[i] / n, 3) for i in range(p)})[-1]
i ran this a bunch of times:
>>> d([id([[],[],[],[],[],[],[]]*_)%9 for _ in range(10_000)], 9)
this:
{0: 0.111, 1: 0.111, 2: 0.445, 3: 0.222, 4: 0.0, 5: 0.0, 6: 0.0, 7: 0.0, 8: 0.111}
gets printed as this (and also with less spaces):
1 1 4 2 0 0 0 0 1
results:
1 1 4 2 0 0 0 0 1
2 1 1 2 0 0 1 1 1
3 0 1 1 0 1 0 2 1
1 0 1 1 0 2 1 1 2
1 0 1 0 0 2 1 1 3
1 0 1 1 0 2 2 1 1
1 0 2 1 0 2 0 1 2
0 0 2 1 0 2 1 1 2
1 2 1 1 0 2 0 1 1
0 3 0 2 0 1 2 0 1
1 2 0 3 0 0 1 0 2
0 2 0 2 1 0 1 0 3
i am doing this in repl, and repl performs a bunch of allocations. This is why results are changing
d = lambda x,p: (c:=__import__('collections').Counter(x),n:=sum(c.values()),{i: round(c[i] / n, 3) for i in range(p)})[-1]
for _ in range(10):
x = d([id([[],[],[],[],[],[],[]]*_)%9 for _ in range(10_000)], 9)
x = {i: round(v * 9) for i, v in x.items()}
print(' '.join(map(str, x.values())))
# results (same every time, and not uniform):
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
0 1 1 0 1 2 2 1 1
with some allocations to break the pattern: ```py
d = lambda x,p: (c:=import('collections').Counter(x),n:=sum(c.values()),{i: round(c[i] / n, 3) for i in range(p)})[-1]
for _ in range(10):
import gc
gc.collect()
import random
_ = [[] for _ in range(random.randint(1, 1000))]
x = d([id([[],[],[],[],[],[],[]]*_)%9 for _ in range(10_000)], 9)
x = {i: round(v * 9) for i, v in x.items()}
print(' '.join(map(str, x.values())))
results (different every time, more uniform):
1 1 1 1 1 1 0 2 1
0 2 1 1 1 1 1 1 1
0 2 1 1 1 1 1 1 1
1 2 1 0 0 2 1 2 0
2 1 1 1 1 1 1 1 0
0 1 1 1 1 1 1 1 2
1 1 0 2 1 1 1 1 1
1 2 1 1 2 0 1 1 0
1 1 1 1 1 1 1 0 2
0 2 1 1 1 1 1 1 1
Wonder what could be the most esoteric DFS implementation
Has to be a recursive one for sure idk how to make it more esoteric
def dfs(g, s, v=None):
return (v := v or set()).union(*(dfs(g, n, v | {s}) for n in g[s] if n not in v))
while any(map(gt,a,a[1:])):shuffle(a)
for _ in(answer:=__import__("random").randint(1,100),g:=-1):(x:=lambda g=g:(g:=int(input("Guess: ")),(print("Higher"),x(g))if g<answer else(print("Lower"),x(g))if g>answer else print("Correct")))and x(g) guess the number game compacted into 1 line of code
does 2 games but okay otherwise
oh yeah because of for loop
(f:=lambda a,b=__import__('random').randint(1,100):(a>b)-(a<b),sum(iter(lambda:print(["Correct","Lower","Higher"][x:=f(int(input()))])or x,0)))
Not code golf, but still pretty weird. Without running the code, what do you think this would output?
# 1
x = []
y = []
x.append(y)
y.append(x)
try:
print("1")
print(x == y)
except Exception as e:
print(e.__class__.__name__)
print(f"x: {x}; y: {y}\n")
# 2
x = []
y = []
x.append(x)
y.append(y)
try:
print("2")
print(x == y)
except Exception as e:
print(e.__class__.__name__)
print(f"x: {x}; y: {y}\n")
# 3
x = []
y = []
x.append(y)
y.append(y)
try:
print("3")
print(x == y)
except Exception as e:
print(e.__class__.__name__)
print(f"x: {x}; y: {y}\n")
Answer:
||```
1
RecursionError
x: [[[...]]]; y: [[[...]]]
2
RecursionError
x: [[...]]; y: [[...]]
3
True
x: [[[...]]]; y: [[...]]
my attempt: ||```py
1
RecursionError (or RubtimeError)
x: [[[...]]]; y: [[[...]]]
2
same error as before
x: [[...]]; y: [[...]]
3
True
x: [[[...]]]; y: [[...]]
yay, im correct
Lol, maybe it wasn’t that great of a gotcha
What’s your rationale as to why the last one ||returns True||?
because i remembered that list.__eq__ has a fast way for cases where self is other
so, roughly, x == y first performs x is y check, it fails, then it compares elements: x[0] == y[0] which is equivalent to y == y, which can be evaluated immediately because y is y
RubtimeError
just noticed 😄
Ah that’s interesting, so it still does the fast check for nested elements. It was confusing behavior for me, thank you
!e ```py
nan = float('nan')
print([nan] == [nan])
@fleet bridge :white_check_mark: Your 3.12 eval job has completed with return code 0.
True
yeah, it first does is check and only then ==
||```
1
<can't figure this out>
2
<can't figure this out>
3
True
x: [[[...]]]; y: [[...]]
i don't get how python makes a ||RecursionError||
oh
i missed a crucial C api function call
|| isnt list eq basically just all(map(operator.eq, self, other)) ||
nope
it's merged with __lt__ etc. so
def list_richcmp(self, other, op):
if not isinstance(self, list) or not isinstance(other, list):
return NotImplemented
if len(self) != len(other) and (op == _EQ or op == _NE):
# Shortcut: if the lengths differ, the lists differ
return op == _NE
# Search for the first index where items are different
for x, y in zip(self, other):
if x is y:
continue
k = richcmp(x, y, _EQ)
if not k:
break
else:
# No more items to compare -- compare sizes
# (Py_RETURN_RICHCOMPARE() expanded and optimized below)
res = len(self) == len(other)
if op == _EQ:
return res
if op == _NE:
return not res
res2 = len(self) > len(other)
if op == _GT:
return not res and res2
if op == _GE:
return res or res2
if op == _LT:
return not res and not res2
if op == _LTE:
return res or not res2
# We have an item that differs -- shortcuts for EQ/NE
if op == _EQ:
return False
if op == Py_NE:
return True
# Compare the final item again using the proper operator
return richcmp(self, other, op)
oh right the whole rich comparison thing
simplified for equals ```py
def list_eq(self, other):
if not isinstance(self, list) or not isinstance(other, list):
return NotImplemented
if len(self) != len(other):
# Shortcut: if the lengths differ, the lists differ
return False
# Search for the first index where items are different
for x, y in zip(self, other):
if x is y:
continue
if not x == y:
break
else:
# No more items to compare -- compare sizes
return len(self) == len(other)
# We have an item that differs -- the lists aren't equal
return False
||its this, right? ```py
k = richcmp(x, y, _EQ)
if not k:
i never understood why they didn't just have them be separate