#esoteric-python
1 messages · Page 130 of 1
yes and no
good luck with that because it's hell 
how could u de obfusucate pyarmor?
by hand
can i view whats on the stack?
i mean constants or whatever is pushed to the stack
how to view it?
is this the right channel to ask about disassembling python code?
Yes.
!e
import json
try:
json.loads('')
except Exception as json:
pass
print(json)
@proper vault :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 6, in <module>
003 | NameError: name 'json' is not defined
yea except blocks forcibly unload their exception instance
!e py import dis dis.dis(''' try:pass except Exception as e:pass ''')
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | 2 0 SETUP_FINALLY 3 (to 8)
002 | 2 POP_BLOCK
003 | 4 LOAD_CONST 0 (None)
004 | 6 RETURN_VALUE
005 |
006 | 3 >> 8 DUP_TOP
007 | 10 LOAD_NAME 0 (Exception)
008 | 12 JUMP_IF_NOT_EXC_MATCH 22 (to 44)
009 | 14 POP_TOP
010 | 16 STORE_NAME 1 (e)
011 | 18 POP_TOP
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/usamoyomiv.txt?noredirect
Now I am curious about how does disassembled code of match look like
Good afternoon: I have a question about a part of a code I'm working on. I'm trying to make sure that the the input() function needs to be inside the loop for this to work:
question != "bye"
while question != "bye":
question = input("What's your question?")
print("What kind of question is" + question + "?")
print("END OF GAME")
When I answer with "bye" without spacing it''ll display "END OF PROGRAM" however when I make a space between "What's your question?" and "bye" then it'll display "What kind of question is..." what am I doing wrong?
@sick hound ive made progress on allowing dynamic hooking of __doc__ and __name__ ```py
find_char_p(int, int.name.encode())
3
find_char_p(int, int.doc.encode())
22
(it would fail if __doc__ was equal to __name__)
def isvalidptr(addr):
import os
r, w = os.pipe()
try:
os.write(w, getmem(addr, 1))
return True
except OSError:
return False
finally:
os.close(r)
os.close(w)
def find_valid_ptrs(obj):
omem = getmem(id(obj), sizeof(obj), 'P')
for i, v in enumerate(omem):
if isvalidptr(v):
yield i, v
def find_char_p(obj, data):
for idx, ptr in find_valid_ptrs(obj):
if getmem(ptr, len(data)).tobytes() == data:
return idx
``` it uses `os.write` to determine if a pointer can be read (to prevent segfaults)
wait, os.write has protection for that?
Yeah the c write function has protection for it for some reason
I'm trying to find another code path to that function that doesn't require an import of os now
You also have to construct some object that has the buffer protocol that points to your address to test
getmem constructs a memory view
You might be better off in a help channel. Take a look at #❓|how-to-get-help.
meanwhile I've made 0 progress on that esopython guide I said I was gonna write
I can relate.
I just keep writing more things I'll need to document lol
it's mainly like
where do I even start
what should be separate subjects
what knowledge should I assume the reader has
etc
I always start with some headings.
I think I might use it to write a safe_memory class
!e
import dis
dis.dis('''
match x:
case 1: pass
case 2 | 3: pass
case int(): pass
case _: pass
''')
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
001 | 2 0 LOAD_NAME 0 (x)
002 |
003 | 3 2 DUP_TOP
004 | 4 LOAD_CONST 0 (1)
005 | 6 COMPARE_OP 2 (==)
006 | 8 POP_JUMP_IF_FALSE 8 (to 16)
007 | 10 POP_TOP
008 | 12 LOAD_CONST 4 (None)
009 | 14 RETURN_VALUE
010 |
011 | 4 >> 16 DUP_TOP
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/subahukeve.txt?noredirect
how does it handle listcomps
cuz that's the part that made me give up
also that range() call looks off
oh are s and g kwonly params there
in that case I said nothing
thats an assignment expression it returns and stores
def isvalidptr(addr):
import os
r, w = os.pipe()
try:
mem = getmem(addr, 1)
os.write(w, mem)
return len(mem) == 1
except OSError:
return False
finally:
os.close(r)
os.close(w)``` @grave rover better `isvalidptr` (if it returns True, the address should be readable at least)
instead of just using 1?
def isvalidptr(addr, size=1):
import os
r, w = os.pipe()
try:
return os.write(w, getmem(addr, size)) == size
except OSError:
return False
finally:
os.close(r)
os.close(w)```
If you have an async function that returns a coroutine, can you await that function and await the returned value? basically a double await?
theoretically could you chain like 5 awaits that way
How does this work?
and how do you handle indents
e.g. ```py
if x:
if y:
if z:
return 10
elif a:
print(20)
else:
raise Exception(30)

so when you hit a branching statement you just call disassembler() with indent level incremented?
how do you know from where to resume
what is co_linetable for speaking of
there's reljumps and absjumps
How would you make a basic disassembler that just disassembles:
a = 2
I understand everythign except htis part:
bytecode = list(zip(code_object.co_code[::2], code_object.co_code[1::2]))
@sick hound :white_check_mark: Your eval job has completed with return code 0.
a = 2
ah
OH
step 2 is all instructions
1::2 is all opargs
Last question, what does 'a' do in compile?
ah
i tested with the optional size parameter, it causes long hangs for large ranges of memory
compile() requires a filename parameter for use in tracebacks and the like.
any reference for co_linetable or how to read it?
there's a couple C API functions to read it
void print_address_ranges(char *linetable, Py_ssize_t length, int firstlineno) {
PyCodeAddressRange range;
PyLineTable_InitAddressRange(linetable, length, firstlineno, &range);
while (PyLineTable_NextAddressRange(&range)) {
printf("Bytecodes from %d (inclusive) to %d (exclusive) ", range.start, range.end);
if (range.line < 0) { // no line number
printf("have no line number\n");
} else {
printf("have line number %d\n", range.line);
}
}
} ```
that's the example from the PEP
my bad, those functions are not part of the API for some reason
so they're already committed to providing them in all future versions of cpython.. just wondering why not consider them API functions
@snow beacon do you have any tips for writing guides for people who know basically nothing on a subject
Step 1 is to decide who you're writing for. If you're writing for people who know nothing about the subject, then you can take them through your journey of what you now know.
is there a module/lib that allow modifying bytecode without having to go through the whole process of importing types and creating the code object and function object and such
You don't need to import types?
!e ```py
def test():
pass
test.code = test.code.replace(co_code=b"t\x00d\x01\x83\x01S", co_consts=(None, "Hello, World!"), co_names=("print",))
test()
@tacit cobalt :white_check_mark: Your eval job has completed with return code 0.
Hello, World!
from 3.8 onward, that is
You can still easily do it before 3.8
why
?
lol
>>> test.__code__.replace(co_code=b"t\x00d\x01\x83\x01S", co_consts=(None, "Hello, World!"), co_names=("print",))
<code object test at 0x5555c22b10, file "<stdin>", line 1>
>>> test();
Hello, World!
on 3.11 though:
ValueError: code: co_code is malformed
also 3.10 works
PyBytes_GET_SIZE(con->code) % sizeof(_Py_CODEUNIT) != 0 is true
$7 = 7
(gdb) p sizeof(_Py_CODEUNIT)
$8 = 2```
not sure why either of those would change. maybe it's just my build.
Try adding \x00 to the end
btw i checked 3.10 and the sizes are exactly the same, 7 and 2
but there's no _PyCode_Validate in 3.10
do i need to asssign
nice, that fixed it !
so the extra \x00 works in the other versions too
Yeah it does I usually remove it cause it is redundant
11 >> 34 POP_TOP
36 POP_TOP
38 POP_TOP
12 40 LOAD_GLOBAL 2 (c)
42 CALL_FUNCTION 0
44 POP_TOP
46 POP_EXCEPT
>> 48 POP_BLOCK
6 50 LOAD_CONST 0 (None)
52 DUP_TOP
54 DUP_TOP
56 CALL_FUNCTION 3
58 POP_TOP
why the line number can decrease?
def x():
with x:
try:
for x in x:
a()
b()
except:
c()
d()
try disassemble this function using python 3.10
def x():
with x:
hello()
how about this function, it doesn't contain loop
The line number doesn't decrease there, though?
it went from 11 to 12 to 6
in the last, simple code snippet, the one with 3 lines I mean
the line numbers in that snippet does decrease as well
4 0 LOAD_GLOBAL 0 (x)
2 SETUP_WITH 12 (to 28)
4 POP_TOP
5 6 LOAD_GLOBAL 1 (hello)
8 CALL_FUNCTION 0
10 POP_TOP
12 POP_BLOCK
4 14 LOAD_CONST 0 (None)
16 DUP_TOP
18 DUP_TOP
20 CALL_FUNCTION 3
22 POP_TOP
24 LOAD_CONST 0 (None)
26 RETURN_VALUE
>> 28 WITH_EXCEPT_START
30 POP_JUMP_IF_TRUE 17 (to 34)
32 RERAISE 1
>> 34 POP_TOP
36 POP_TOP
38 POP_TOP
40 POP_EXCEPT
42 POP_TOP
44 LOAD_CONST 0 (None)
46 RETURN_VALUE
is that 3.10? In 3.9 it doesn't (or I'm doing something wrong):
2 0 LOAD_GLOBAL 0 (x)
2 SETUP_WITH 22 (to 26)
4 POP_TOP
3 6 LOAD_GLOBAL 1 (hello)
8 CALL_FUNCTION 0
10 POP_TOP
12 POP_BLOCK
14 LOAD_CONST 0 (None)
16 DUP_TOP
18 DUP_TOP
20 CALL_FUNCTION 3
22 POP_TOP
24 JUMP_FORWARD 16 (to 42)
>> 26 WITH_EXCEPT_START
28 POP_JUMP_IF_TRUE 32
30 RERAISE
>> 32 POP_TOP
34 POP_TOP
36 POP_TOP
38 POP_EXCEPT
40 POP_TOP
>> 42 LOAD_CONST 0 (None)
44 RETURN_VALUE
yes it's 3.10
one way the line number can go backwards, is if you are calling a function with several subexpressions as arguments, it will emit those line numbers first, then the line number with the original function call
a bunch of work went into emitting the corect sequence of line numbers for 3.10, so that's probably why there's a difference, iirc
i just need a function to encode/decode co_linetable
from struct import iter_unpack
def decode(code):
curroff = 0
endoff = 0
currline = code.co_firstlineno
for off, line in iter_unpack("BB", code.co_linetable):
endoff += off
currline += line
yield curroff, endoff, currline
curroff += off
this seems to work
but not in this case, where the line number decreases
this is the bug i was looking for
>>> def x():
... print(
... a(),
... b()
... )
...
>>> dis.dis(x)
2 0 LOAD_GLOBAL 0 (print)
3 2 LOAD_GLOBAL 1 (a)
4 CALL_FUNCTION 0
4 6 LOAD_GLOBAL 2 (b)
8 CALL_FUNCTION 0
2 10 CALL_FUNCTION 2
12 POP_TOP
14 LOAD_CONST 0 (None)
16 RETURN_VALUE
I haven't implemented it in my program
@simple crystal :white_check_mark: Your eval job has completed with return code 0.
esoteric
:incoming_envelope: :ok_hand: applied mute to @simple crystal until <t:1634967682:f> (9 minutes and 59 seconds) (reason: newlines rule: sent 23 consecutive newlines in 10s).
too esoteric for automod
type pip install pyartificialintelligence
!e
class hello(**{"metaclass":type("",(type,),{"__new__":lambda*_:"world"})}):...
print(hello)
@restive void :white_check_mark: Your eval job has completed with return code 0.
world
Assignment when your equals key is broken
Shorter, but boring alternative (since 3.9):
@lambda _:"world"
def hello():ö
globals().__setitem__('hello', 'world')
Shouldn't it be ```py
globals().setitem("hello", "world")
exec(f"globals()['hello'] {chr(61)} 'world'")
ye, mb
def __getattr__(name):
return 'world'
from __main__ import hello
!e
def getattr(name):
return 'world'
from main import hello
print(hello)
@knotty delta :white_check_mark: Your eval job has completed with return code 0.
world
module level getattr gets called when you import a name that is not defined in the module
ooo
Interestingly, to set other module level dunders, you have to reassign the entire class of the module itself
ye, and even then it won't work all the time IIRC
import sys
class Mod:
def __getattr__(self, name):
return 'world'
sys.modules[__name__] = Mod()
from __main__ import hello
print(hello)
Oh that's cool. I was actually referring to something like this though:
# my_module.py
import sys
import types
class EditedModuleType(types.ModuleType):
def __call__(self, func: types.FunctionType):
def wrapper(*args, **kwargs):
print(
f"Running {func.__name__}({', '.join([str(arg) for arg in args]+[f'{k}={v}' for k,v in kwargs.items()])})"
)
func(*args, **kwargs)
return wrapper
sys.modules[__name__].__class__ = EditedModuleType
# REPL
>>> @__import__("my_module")
... def f(a, b):
... ...
...
>>> f(1, b=2)
Running f(1, b=2)
Speaking of, tampering with modules are pretty cool
!e
from sys import modules
from types import ModuleType
class Organize(ModuleType):
hello_world = 1
modules["test"] = Organize
from test import hello_world
print(hello_world)
@shut trail :white_check_mark: Your eval job has completed with return code 0.
1
You can also
!e
import sys
class Evil:
foo = 0
@type.__call__
class __all__:
def __getitem__(self, key):
return "foo"
sys.modules["evil"] = Evil()
from evil import *
print("hello? is there anyone there?")
@earnest wing :warning: Your eval job timed out or ran out of memory.
[No output]
Hm, why does this prevent printing"
Does it override the module's __all__ and therefore everything returns foo
Hey, me again
What does the type.__call__ decorator do?
Also, how do I get the default arguments of a lambda?
times out on the import for me
lambdas are just normal functions
I'm not sure which dunder to reda
__import <<"os"
__import <<"tempfile"
__import <<"subprocess"
__import <<"ctypes" <(
"addressof",
"c_int",
"cdll",
"create_string_buffer",
"CFUNCTYPE",
"memmove"
)
__asm(c_int) <(
"BITS 64",
"mov rax, rdi",
"add rax, rsi",
"ret"
)```
Can't send the whole source because it's too big
it replaces it with an "infinite" list
yes it's supposed to
@sly root how many crimes have you commited in the python interpreter?
maaaaany :)
Your insane bro.
idk but although in the inline assembler snippet, I used a method to create variables and run many functions sequentially and at the same time not get an error from python (for example, if you create a variable in a lambda, you get a syntax error)
lambda_that_will_give_an_error = (lambda: b=3)
lambda_that_wont_give_an_error = (lambda a: ___e(a,'b',3)
thx
i dont see any code there that resembles any of my snippets
and even if someone wanted to use that code that would be fine as long as they put a comment or something. I put it online to share it
helo
@dire lark o/ Hi!
hy!
Well @sly root you have interesting taste in repos. In a good way.
If that isn't cool to post just let me know, I'll delete it. It looked interesting to me.
@sick hound let's not post nuker bot repositories in this server, or anywhere for that matter please
@thin trout Thanks Akarys! Will do.
My snippets tend to expand to real projects
See: easy_z3, unibitmap
both are totally cursed and yet both serve a practical function
hey i want to learn to write obsfucated python code mainly to rickroll my friend. how can i get started? i am good at core python but still have lots to learn.
Here's a simple program I wrote for a code contest! As a challenge, try to reverse engineer it :)
how do i get rid of those weird characters? they won't let me read the code or is it a part of code?
i am talking about these characters. these weird h. if they are the part of algorithm then can you please point me to a resource?
why does the file extension say .docx.py instead of just .py?
@earnest wing # trolled eh? 😄
There's some really interesting python feature intersections at play there imo
https://esolangs.org/wiki/Befalse Well, at the very least I've learned something interesting today. Obfuscation is taxing, but I'm intrigued.
?
what in the bill gates is a docx.py lmao
If anyone wants to cheat at the reverse engineering, my entry is a lot less ornamental.
Who doesn't
You're probably the target audience of a guide I made, which I will now shamelessly advertise: https://github.com/IFcoltransG/esoteric-python-guide.
I say "made" but I really need to finish the rest of it. Some other time.
After other things.
My "finish project wherewithal" budget is currently being diverted towards other ends.
that's actually a cool premise
i cheat and do
globals().__setitem__("v", val)
!e
l = lambda a: globals().__setitem__("a", a)
l(6)
print(f'{a=}')
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
a=6
like so. not the cleanest way to set a variable from a lambda,. I'm open to suggestions
lower memory consumption?
!e
import sys
l = lambda a: sys._getframe(1).f_locals.__setitem__("a", a)
l(6)
print(f"{a=}")
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
a=6
now if I could add a shorthand for that (without messing up the call stack) ...
!e
import sys
def setv(k, v): sys._getframe(2).f_locals.__setitem__(k, v)
l = lambda a: setv("a", 6)
l(6)
print(f'{a=}')
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
a=6
not bad, probably works in more places than globals()?
!e
import sys
def setv(k, v): sys._getframe(2).f_locals.__setitem__(k, v)
l1 = lambda: (l2(), a)[-1];
l2 = lambda: setv("a", 6)
print(f'{l1()=}')
@rapid sparrow :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 6, in <module>
003 | File "<string>", line 4, in <lambda>
004 | NameError: name 'a' is not defined
why doesn't that work? 😦
i see why
!e
from sys import _getframe as gf
def setv(n, v, d=0): gf(2+d).f_locals.__setitem__(n, v)
l = lambda: (l2(), a)[-1]
l2 = lambda: setv("a", 6, 1)
print(f'{l()=}')
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
l()=6
very cool @sick hound
that only works when f_locals is globals()
unless you have some additional code (https://github.com/chilaxan/pysnippets/blob/main/f_locals.py)
yes
in that code Null is actually just a singleton flag value
its not actually NULL but when it shows up it tells the code to actually write NULL
!e ```py
def __e(obj,n,v):obj[n]=v
def raise(e):raise e
e,,,__c,__p,__if,__join=(lambda obj,n,v:setattr(obj,n,v)),(lambda ret,*argc:ret),(lambda *argc:0),(lambda obj,n:e(globals(),obj,{*obj,n:""})),(lambda obj:print(obj)),(lambda:[0]if __[1]else __[2]),(lambda a:[a[0],a[1]])
__import=type("import",(),{"init":lambda self:None,"lshift":lambda self,mod:(self,__e(self,"mod",mod),e(globals(),mod,import(mod))),"lt":lambda self,sub:(self,e(globals(),sub,getattr(import(getattr(self,"mod")),sub)))if type(sub)==str else[(self,e(globals(),sub,getattr(import(self.mod),sub)))for sub in sub]})()
include=type("include",(),{"init":lambda self:None,"lt":lambda self,file:exec(open(file,"r").read())})()
cf=type("cf",(object,),{
"init":(lambda self,c:(None,((___e(self,"tfile",___join(tempfile.mkstemp(".cpp","temp",os.getcwd()))),e(self,"source",getattr(self,"tfile")[1])),(open(getattr(self,"source"),"wb").write(c.encode("utf-8")),___e(self,"sts",subprocess.check_output(f'cat {getattr(self,"source")} | g++ -x c++ - ',shell=True)),__if(primt(subprocess.check_output("./a.out").decode('utf-8')),status==0,print(getattr(self,"sts"))))),os.unlink(getattr(self,"source"))))
})
__c=type("c",(),{
"init":lambda self:None,
"lt":(lambda self,c:
cf("\n".join([c+"\n" if c.endswith("{") else c for c in c])))
})()
__import <<"os"
__import <<"tempfile"
__import <<"subprocess"
__c <(
"#include <iostream>",
"",
"int main() {"
" std::cout << "Hello from C++" << std::endl;",
"}"
)```
@sly root :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 12, in <lambda>
004 | File "<string>", line 7, in <lambda>
005 | File "/usr/local/lib/python3.10/tempfile.py", line 337, in mkstemp
006 | return _mkstemp_inner(dir, prefix, suffix, flags, output_type)
007 | File "/usr/local/lib/python3.10/tempfile.py", line 252, in _mkstemp_inner
008 | fd = _os.open(file, flags, 0o600)
009 | OSError: [Errno 30] Read-only file system: '/snekbox/temp3ieav8cz.cpp'
nah
can someone test my inline-c++ snippet?
running it from mobile gives an error:
PermissionError: [Errno 13] Permission denied: './a.out'```
cuz it's not rooted
for windows:
type {getattr(self,"source)} | g++ -x c++ -
-x to compile from stdin
c++ means c++ 🤓
replace > with |
my bad
hm
for me, it compiles without errors, but i can't run the a.out file
# author: Dimitriy i0x <annihilation.ga>
# feel free to modify or copy this code
# but also specify credits (link to this repo or file)
def __e(obj,n,v):obj[n]=v
def __raise(e):raise e
___e,__,___,__c,__p,__if,___join=(lambda obj,n,v:setattr(obj,n,v)),(lambda ret,*argc:ret),(lambda*argc:0),(lambda obj,n:___e(globals(),obj,{**obj,n:""})),(lambda obj:print(obj)),(lambda*__:__[0]if __[1]else __[2]),(lambda a:[a[0],a[1]])
__import=type("__import",(),{"__init__":lambda self:None,"__lshift__":lambda self,mod:__(self,___e(self,"mod",mod),__e(globals(),mod,__import__(mod))),"__lt__":lambda self,sub:__(self,__e(globals(),sub,getattr(__import__(getattr(self,"mod")),sub)))if type(sub)==str else[__(self,__e(globals(),sub_,getattr(__import__(self.mod),sub_)))for sub_ in sub]})()
__include=type("__include",(),{"__init__":lambda self:None,"__lt__":lambda self,file:exec(open(file,"r").read())})()
__cf=type("__cf",(object,),{"__init__":(lambda self,c:__(None,___(___(___e(self,"tfile",___join(tempfile.mkstemp(".cpp","temp",os.getcwd()))),___e(self,"source",getattr(self,"tfile")[1])),___(open(getattr(self,"source"),"wb").write(c.encode("utf-8")),___e(self,"sts",subprocess.check_output(f'cat {getattr(self,"source")} | g++ -x c++ - ',shell=True)),__if(print(subprocess.check_output("./a.out").decode('utf-8')),getattr(self,"sts")==0,print(getattr(self,"sts"))))),os.unlink(getattr(self,"source"))))})
__c=type("__c",(),{"__init__":lambda self:None,"__lt__":(lambda self,c:__cf("\n".join([c_+"\n"if c_.endswith("{")else c_ for c_ in c])))})()
__import <<"os"
__import <<"tempfile"
__import <<"subprocess"
__c <(
"#include <iostream>",
"",
"int main() {"
" std::cout << \"Hello from C++\" << std::endl;",
"}"
)```
fixed
why? I don't follow
why couldn't you set a local anywhere in the stack
# author: Dimitriy i0x <annihilation.ga>
# feel free to modify or copy this code
# but also specify credits (link to this repo or file)
def __e(obj,n,v):obj[n]=v
def __raise(e):raise e
___e,__,___,__c,__p,__if,___join=(lambda obj,n,v:setattr(obj,n,v)),(lambda ret,*argc:ret),(lambda*argc:0),(lambda obj,n:___e(globals(),obj,{**obj,n:""})),(lambda obj:print(obj)),(lambda*__:__[0]if __[1]else __[2]),(lambda a:[a[0],a[1]])
__import=type("__import",(),{"__init__":lambda self:None,"__lshift__":lambda self,mod:__(self,___e(self,"mod",mod),__e(globals(),mod,__import__(mod))),"__lt__":lambda self,sub:__(self,__e(globals(),sub,getattr(__import__(getattr(self,"mod")),sub)))if type(sub)==str else[__(self,__e(globals(),sub_,getattr(__import__(self.mod),sub_)))for sub_ in sub]})()
__include=type("__include",(),{"__init__":lambda self:None,"__lt__":lambda self,file:exec(open(file,"r").read())})()
__cf=type("__cf",(object,),{"__init__":(lambda self,c:__(None,___(___(___e(self,"tfile",___join(tempfile.mkstemp(".cpp","temp",os.getcwd()))),___e(self,"source",getattr(self,"tfile")[1])),___(___e(self,"f",open(getattr(self,"source"),"wb")),getattr(self,"f").write(c.encode("utf-8")),getattr(self,"f").close(),___e(self,"sts",subprocess.check_output(f'g++ -x c++ {getattr(self,"source")}',shell=True)),__if(print(subprocess.check_output("./a.out").decode('utf-8')),getattr(self,"sts")==0,print(getattr(self,"sts"))))),os.unlink(getattr(self,"source"))))})
__c=type("__c",(),{"__init__":lambda self:None,"__lt__":(lambda self,c:__cf("\n".join([c_+"\n"if c_.endswith("{")else c_ for c_ in c])))})()
__import <<"os"
__import <<"tempfile"
__import <<"subprocess"
__c <(
"#include <iostream>",
"",
"int main() {"
" std::cout << \"Hello from C++\" << std::endl;",
"}"
)```
fixed
idk how to make it work for windows
yes, but i forgot to os.unlink the a.out file
maybe it will be a problem if you will run it many times in a row
is it basically just doing echo "<source>" | g++ -x c++ -
there was also inline-assembly snippet but i can't run/test it because i don't have libc.so.6
btw thanks for helping me fixing inline-c
oh i see, there'a some DSL in there
Hey @sly root!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
i was closing it at the end
maybe there was problem in parens so it was closing at the moment when it was needed for g++
thx
__include isn't used?
yes i created it for analogue for c's #include🤓
it looked like it would be cool
it just reads the file and executes everything cuz there's no preprocessor
how annoying that there's no wsy to emit an executable with the same name that will work on both platforms
on linux a.exe works?
@sick hound I'll put your nickname at the top in the "# modified by "comment
okay
soo, i've pushed it to git
@rapid sparrow can you help me with inline-asm snippet?
need to know if its working
can't run it myself because i don't have libc.so.6
await ctx.send ("https://cdn.discordapp.com/attachments/884636730945314847/901406494111727666/IMG_7080.jpg")
^
IndentationError: unexpected indent
``` could someone help me please.
sure
how do i fix the error?
I get FileNotFoundError: [Errno 2] No such file or directory: 'nasm'
what comes before this line
you want to unindent await
unless there's supposed to be the header of a function there
afaik await .... isn't a valid target for a decorator
await ctx.send ("https://cdn.discordapp.com/attachments/884636730945314847/901406494111727666/IMG_7080.jpg")```
could you please fix it
i'm really new to coding.
srry.
you are missing a function def that would have the await ctx.send(...) in it
there's a different channel you should ask in though, #discord-bots
ok
hmhmhm
oh i forgot
i need to pass 3 ret_types, not 1
replace __asm(c_int) with __asm(c_long, c_long, c_long)
then just c_long, c_long
@sick hound so, does it work?
@sick hound ```py
import subprocess, os, tempfile
from ctypes import *
PAGE_SIZE = 4096
class AssemblerFunction(object):
def init(self, code, ret_type, *arg_types):
# Run Nasm
fd, source = tempfile.mkstemp(".S", "assembly", os.getcwd())
os.write(fd, code)
os.close(fd)
target = os.path.splitext(source)[0]
subprocess.check_call(["nasm",source])
os.unlink(source)
binary = open(target,"rb").read()
os.unlink(target)
bin_len = len(binary)
# align our code on page boundary.
self.code_buffer = create_string_buffer(PAGE_SIZE*2+bin_len)
addr = (addressof(self.code_buffer) + PAGE_SIZE) & (~(PAGE_SIZE-1))
memmove(addr, binary, bin_len)
# Change memory protection
self.mprotect = cdll.LoadLibrary("libc.so.6").mprotect
mp_ret = self.mprotect(addr, bin_len, 4) # execute only.
if mp_ret: raise OSError("Unable to change memory protection")
self.func = CFUNCTYPE(ret_type, *arg_types)(addr)
self.addr = addr
self.bin_len = bin_len
def call(self, *args):
return self.func(*args)
def del(self):
# Revert memory protection
if hasattr(self,"mprotect"):
self.mprotect(self.addr, self.bin_len, 3)
if name == "main":
add_func = """ BITS 64
mov rax, rdi
add rax, rsi
ret
"""
Add = AssemblerFunction(add_func, c_int, c_int, c_int)
print(Add(1, 2))
does this work?
@sick hound fixed
hmm
interesting
@sick hound I've got why there was an error
first c_int return type, and then two other c_ints are arg types
try __asm(c_int, c_int, c_int)
hm
on this too? fixed file open error cuz it was written for python 2.x
fixed all errors by rewriting the method🤓
!e ```py
author: Dimitriy i0x <annihilation.ga>
feel free to modify or copy this code
but also specify credits (link to this repo or file)
def __e(obj,n,v):obj[n]=v
def raise(e):raise e
e,,,__c,__p,__if,__join=(lambda obj,n,v:setattr(obj,n,v)),(lambda ret,*argc:ret),(lambda *argc:0),(lambda obj,n:e(globals(),obj,{*obj,n:""})),(lambda obj:print(obj)),(lambda:[0]if __[1]else __[2]),(lambda a:[a[0],a[1]])
__import=type("import",(),{"init":lambda self:None,"lshift":lambda self,mod:(self,__e(self,"mod",mod),e(globals(),mod,import(mod))),"lt":lambda self,sub:(self,e(globals(),sub,getattr(import(getattr(self,"mod")),sub)))if type(sub)==str else[(self,e(globals(),sub,getattr(import(self.mod),sub)))for sub in sub]})()
__include=type("__include",(),{"init":lambda self:None,"lt":lambda self,file:exec(open(file,"r").read())})()
af=type("af",(object,),{"init":(lambda self,asm:(None,(__(___e(self,"tfile",___join(tempfile.mkstemp(".S","temp",os.getcwd()))),e(self,"source",getattr(self,"tfile")[1]),e(self,"f",open(getattr(self,"source"),"wb")),),(getattr(self,"f").write(asm.encode("utf-8")),getattr(self,"f").close(),),(___e(self,"sts",subprocess.check_output(f"nasm {getattr(self,'source')}",shell=True)),__if(print(subprocess.check_output(getattr(self,"source")[:-2]).decode("utf-8")),getattr(self,"sts")==0,print(getattr(self,"sts"))),),os.unlink(getattr(self,"source")))))})
__asm=type("__asm",(),{"init":lambda self:None,"lt":(lambda self,asm:__af("\n".join(asm)))})()
__import <<"os"
__import <<"tempfile"
__import <<"subprocess"
__asm <( """
global start
section .text
start:
mov rax, 0x2000004
mov rdi, 1
mov rsi, msg
mov rdx, msg.len
syscall
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "Hello, world!", 10
.len: equ $ - msg
""")
@sly root :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 | File "<string>", line 11, in <lambda>
005 | File "/usr/local/lib/python3.10/tempfile.py", line 337, in mkstemp
006 | return _mkstemp_inner(dir, prefix, suffix, flags, output_type)
007 | File "/usr/local/lib/python3.10/tempfile.py", line 252, in _mkstemp_inner
008 | fd = _os.open(file, flags, 0o600)
009 | OSError: [Errno 30] Read-only file system: '/snekbox/tempsfx6x5ga.S'
eeh
@sly root i dont think snekbox has nasm either (otherwise you could pipe the binary to stdout and write it into python's process mem)
@remote talon a help channel that's available; #❓|how-to-get-help
yes, I know, but now I have a different problem, windows won't let me delete the file
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\i0x\\PycharmProjects\\pysnippets\\inlinec\\temp76ue_7jp.cpp'
i've rewritten it fully from scratch
__cf=type("__cf",(object,),{"__init__":(lambda self,c:
__(None,
___(
___e(self,"tfile",tempfile.mkstemp(".cpp","temp",os.getcwd())),
___e(self,"source",getattr(self,"tfile")[1]),
___e(self,"f",open(getattr(self,"source"),"wb")),
),
___(
getattr(self,"f").write(c.encode("utf-8")),
getattr(self,"f").close(),
),
___(
___e(self,"sts",subprocess.check_output(f"g++ -o a.out {getattr(self,'source')}",shell=True)),
__if(print(subprocess.check_output("a.out").decode("utf-8")),getattr(self,"sts")==0,0),
),
os.unlink("a.out"),
os.unlink(getattr(self,"source")),
)
)})
everything works normally on linux
problem is in os.unlink(getattr(self,"source")), when deleting the .cpp file
fixed the error
@sick hound also closing __s not works, cuz then os basically not unlinks it xd
What is a python vm language 🤔
Is it a language which has its interpreter written in python?
class yeet(list):
def __setitem__(self,x,y):
try:super().__setitem__(x,y)
except:self.append(y)
def chicken(CHICKEN):
a=yeet()
c=[len(yay.split())for yay in CHICKEN.split('\n')]
assert all([all([this=='chicken'for this in yay.split()])for yay in CHICKEN.split('\n')])
p=q=0
while p<len(c):
if c[p]==0:break;
if c[p]==1:a+=['chicken']
elif c[p]==2:a[-1]=a.pop(-1)+a[-1]
elif c[p]==3:a[-1]=a.pop(-1)-a[-1]
elif c[p]==4:a[-1]=a.pop(-1)*a[-1]
elif c[p]==5:a[-1]=a.pop(-1)==a[-1]
elif c[p]==6:
p+=1
if not c[p]:a+=[a[a.pop(-1)]]
else:a+=[input()[a.pop(-1)]]
elif c[p]==7:
x,y = a.pop(-1), a.pop(-1)
a[x]=y
elif c[p]==8:
x,y = a.pop(-1),a.pop(-1)
if y:p+=x-1
elif c[p]==9:a[-1]=chr(a[-1])
else:a+=[c[p]-10]
p+=1
print (''.join([str(this)for this in a[::-1]]))
icr what chicken is supposed to print at the end
dammit i got something wrong
i think either that or gets compiled to python bytecode
x = int(input("hsjsvdh"))
what is this doing exactly?
it's the language that your python scripts get compiled to
what people call "bytecode"
if it had a name people would call it by the name
but it doesn't, it's python vm language
well i tested it and it didn't work, so not what it's supposed to.
I think i see the issue.
It has now been edited to prevent the issue.
I think the specifications just aren't clear enough
chicken
code:
def online():
content = ploudos.req()
try:
return f"{0 if content['onlineCount'] == None else str(content['onlineCount']) + '/' + str(content['onlineMax'])}"
except KeyError:
return "0/0"
question: Any idea how to make it more compact (maybe lambda 1 liner). (shouldn't be focused on readability)
def online():
try:
return [f"{(content:=ploudos.req())['onlineCount']}/{content['onlineMax']}", 0][content['onlineCount']==None]
except KeyError:
return "0/0"```that's a start
thanks
and is there any way to one line this?
32 chars less
Then you can remove spaces etc.
Use shorter variable names
Use another walrus for content['onlineCount']
etc.
thanks but -.-
No
You can't one-line a try/except
kk
true
thanks
You can in fact one line try except xD
Pretty easy to do a simple try except in one line at least
def foo():
1/0
with type("handler", (), {"__enter__": lambda self: None, "__exit__": lambda self, et, ev, tb: True})(): foo()
with, you can't put it wherever you want
What other functions?
Am I allowed to change the bytecode of functions?
So no changing bytecode
You can
Using contextlib
Hold on, there was a snippet somewhere here
.
Ah so it's a translator basically
a failed one though, it didn't work for the hello world test
something failed is only a step away from being successful
its 4:30 am its staying failed until tomorrow
wait its already tomorrow
its still staying failed today
it's kind of hard to keep up, hoping it's not used that often
hey guys could someone please tell me why the first decorator on this picture has an additional "decorator" function above @wraps and the second decorator doesnt have it?
can you upload a clearer image? can't quite read it
!e
class test:
def __init__(self, d={}):
self.d=d
t1 = test()
t1.d |= {0:0}
t2 = test()
print(t2.d)
@simple crystal :white_check_mark: Your eval job has completed with return code 0.
{0: 0}
thought so but making sure initializer default mutables do that
in case it didn't work like I thought
#bot-commands is a great place to test out all sorts of code. (As long as you promise you'll fill us in if you find anything fun :)
oh, please sorry guys, here is the code:
import cProfile, pstats, io
def permission_required(role):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.has_role(role):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
def profile(fnc):
@wraps(fnc)
def inner(*args, **kwargs):
pr = cProfile.Profile()
pr.enable()
retval = fnc(*args, **kwargs)
pr.disable()
s = io.StringIO()
sortby = 'cumulative'
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print(s.getvalue())
return retval
return inner
so my question is: why the first decorator on this picture has an additional "decorator" function above @wraps and the second decorator doesnt have it?
how do i bring back the >>> in IDLE
the second has a call: return retval
wouldnt first decorator work even without "def decorator(f):" line?
i guess it would so im wondering what s the purpose of it
it's to capture the *args, **kwargs in the lambda state
so f can get called later with those same args is my guess
actually, looking again, that's not what's being captured, but f and role are I believe
!e There's an attribute of sys you can set that to whatever. I can't remember what it is though. Provably cp1 or something like that ```py
print(dir(import('sys')))
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__', '__loader__', '__name__', '__package__', '__spec__', '__stderr__', '__stdin__', '__stdout__', '__unraisablehook__', '_base_executable', '_clear_type_cache', '_current_exceptions', '_current_frames', '_deactivate_opcache', '_debugmallocstats', '_framework', '_getframe', '_git', '_xoptions', 'abiflags', 'addaudithook', 'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix', 'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth', 'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettrace', 'hash_info', 'hexversion', 'implementation
... (truncated - too long)
Full output: https://paste.pythondiscord.com/afutipapeb.txt?noredirect
It's not shown there, possibly due to being in a sandbox.
Open command prompt enter py or python3 and then import sys
dir(sys)
And there will be more options than above
Unless you've played with idle itself then probably reinstall
But in this channel, impossibility is impossible
its ps1 and ps2
yes, ps1 defaults to >>>
ps2 defaults to ...
!e
import sys
print(repr(sys.ps1), repr(sys.ps2))
@fleet bridge :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | AttributeError: module 'sys' has no attribute 'ps1'
As I said, it won't work on the sandbox
They're only there in interactive mode, and IDLE itself might not use them - though it probably does.
@sick hound :white_check_mark: Your eval job has completed with return code 0.
5
!e
print(repr(r''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''fr''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''f'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''r'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''r'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''f'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''fr'''''''''''''''''''''''''''''''''''''''''''''''''''''rb'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''))
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
"'frfrfr'rb"
!e
print(f"""{f'''{f"{f'{0}'}"}'''}""")
@fleet bridge :white_check_mark: Your eval job has completed with return code 0.
0
you can approximate it with code maybe
!e
from code import InteractiveConsole
cons = InteractiveConsole()
cons.push("def fun():")
cons.push(" print('hello from fun')")
cons.push("")
cons.push("print(fun())")
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | hello from fun
002 | None
!e
from code import InteractiveConsole
class SpecialConsole(InteractiveConsole):
_last: str = None
_cmd: str = None
def raw_input(self, prompt):
try:
self._last = self._cmd
if not self.buffer:
if self._rest:
self.buffer += self._rest.splitlines()
self.rest = None
else:
raise EOFError
self.buffer.reverse();
self._cmd = self.buffer.pop()
self.buffer.reverse();
self._rest = "\x0a".join(self.buffer)
self.buffer.clear()
return self._cmd
finally:
print(f"{prompt}{self._cmd}")
if __name__ == "__main__":
c = SpecialConsole()
c.buffer.append("import sys")
c.buffer.append("sys")
c.interact()
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | Python 3.10.0 (default, Oct 6 2021, 00:08:37) [GCC 8.3.0] on linux
002 | Type "help", "copyright", "credits" or "license" for more information.
003 | (SpecialConsole)
004 | >>> import sys
005 | >>> sys
006 | <module 'sys' (built-in)>
007 | >>> sys
008 |
009 | now exiting SpecialConsole...
not perfect, but close?
btw InteractiveConsole sets sys.ps1 and sys.ps2 if they aren't attributes of sys yet
wow we got an upgrade to 3.10 👏
anyone know a way to get the referent from a weakref object?
you call it
ah, thanks!
I was trying to figure out how __issubclass__ knows e.g. list is a Collection. I don't see anything in the abc registry for Collection and it's not derived from anything (except object). Wondering what I'm missing.
it checks what methods exist on the object passed to it (im assuming youre talking about __subclasshook__)
so that's determined by calling Collection.__subclasshook__ ?
Lib/_collections_abc.py lines 78 to 88
def _check_methods(C, *methods):
mro = C.__mro__
for method in methods:
for B in mro:
if method in B.__dict__:
if B.__dict__[method] is None:
return NotImplemented
break
else:
return NotImplemented
return True```
Lib/_collections_abc.py line 412
return _check_methods(C, "__len__", "__iter__", "__contains__")```
ohhhh
its part of python's move towards structural type checking
so the registry thing is probably just an optimization, then
thanks so much @rapid sparrow! highly appreciated sir!
abc.ABC.register and friends
i couldnt tell you
register(subclass) method of abc.ABCMeta instance Register a virtual subclass of an ABC.
ok, this helps a lot
this is what I came up with to show the ABC registry (empty classes not printed)
!e
from pprint import pp; import _abc, inspect, collections.abc; clzs = dict(inspect.getmembers(collections.abc, lambda v: inspect.isclass(v) and hasattr(v, "_abc_impl"))).values(); regclzs = {c.__name__: [d() for d in list(_abc._get_dump(c)[0])] for c in clzs}; pp({k: v for k,v in regclzs.items() if v});
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | {'ByteString': [<class 'bytearray'>, <class 'bytes'>],
002 | 'ItemsView': [<class 'dict_items'>],
003 | 'KeysView': [<class 'dict_keys'>],
004 | 'Mapping': [<class 'mappingproxy'>],
005 | 'MutableMapping': [<class 'dict'>],
006 | 'MutableSequence': [<class 'bytearray'>,
007 | <class 'list'>,
008 | <class 'collections.deque'>],
009 | 'MutableSet': [<class 'set'>, <class '_weakrefset.WeakSet'>],
010 | 'Sequence': [<class 'str'>,
011 | <class 'tuple'>,
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/yijozugipe.txt?noredirect
it didn't show the whole picture, that's why I was curious 🙂
I guess if I wanted a list of all Collection classes the way would be basically call issubclass on every class
!e
import gc, inspect, collections.abc; allclz = [*filter(inspect.isclass, gc.get_objects())]; print(f"{len(allclz)} classes"); print([c.__qualname__ for c in allclz if issubclass(c, collections.abc.Collection)])
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | 314 classes
002 | ['Arguments', 'ArgSpec', 'FullArgSpec', 'ArgInfo', 'ClosureVars', 'Traceback', 'FrameInfo', '_OrderedDictKeysView', '_OrderedDictItemsView', '_OrderedDictValuesView', 'Counter', 'ChainMap', 'UserDict', 'UserList', 'UserString', 'CacheInfo', '_HashedSeq', '_EnumDict', 'EnumMeta', '_Instruction', 'Instruction', '_Environ', 'TokenInfo', 'Attribute', 'TokenInfo', 'waitid_result', 'stat_result', 'statvfs_result', 'sched_param', 'terminal_size', 'times_result', 'uname_result', '_NamespacePath', 'CodecInfo', 'Collection', 'Set', 'MutableSet', 'Mapping', 'KeysView', 'ItemsView', 'ValuesView', 'MutableMapping', 'Sequence', 'ByteString', 'MutableSequence']
!e
print("hello")
@sick hound :white_check_mark: Your eval job has completed with return code 0.
hello
Hey fatal, how are you doing?
can you explain me this code : data = [x + random() for x in range(1, 100)]
thanks
i know it is a loop comprehension
but what the (+) means
its adding x to a random value between 0 and 1
what ?
the range is between 1 and 100
so from 1 to 99
I don't understand your answer
random.random()```
Return the next random floating point number in the range [0.0, 1.0).
who knows the answer to this
# local to function
>>> def func():
... f = open("test.txt", "w")
... f.write("hello world")
...
>>> func()
>>> Path("test.txt").read_text()
'hello world'
# global var
>>> Path("test.txt").unlink()
>>> f = open("test.txt", "w")
>>> f.write("hello world")
11
>>> Path("test.txt").read_text()
''
that's a re-enactment of someone else' code I got asked about
it writes out the file when the f is a local but not a global
do the _io classes that wrap open files have a finalizer that runs only in the first case?
could you explain
open("test.txt", "w") is backed by a file descriptor, isn't it
PyTypeObject PyFileIO_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_io.FileIO",
sizeof(fileio),
0,
(destructor)fileio_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
...
PyType_GenericAlloc, /* tp_alloc */
fileio_new, /* tp_new */
PyObject_GC_Del, /* tp_free */
// ^^ it has __del__
static void
fileio_dealloc(fileio *self)
{
self->finalizing = 1;
if (_PyIOBase_finalize((PyObject *) self) < 0)
return;
_PyObject_GC_UNTRACK(self);
if (self->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) self);
Py_CLEAR(self->dict);
Py_TYPE(self)->tp_free((PyObject *)self);
}
ah
>>> from pathlib import Path
>>> f = open("test.txt", "w")
>>> f.write("hello world")
11
>>> Path("test.txt").read_text()
''
>>> del f
>>> Path("test.txt").read_text()
'hello world'
nice
I'm looking for the shortest (or weirdest) way to read a file to a string
if anyone has ideas
i'll start
!e
print(open(__import__("json").__file__).read()[:250])
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | r"""JSON (JavaScript Object Notation) <http://json.org> is a subset of
002 | JavaScript syntax (ECMA-262 3rd edition) used as a lightweight data
003 | interchange format.
004 |
005 | :mod:`json` exposes an API familiar to users of the standard library
006 | :mod:`marshal` and :m
!e
print((m:=__import__("pathlib")).Path(m.__file__).read_text()[:250])
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | import fnmatch
002 | import functools
003 | import io
004 | import ntpath
005 | import os
006 | import posixpath
007 | import re
008 | import sys
009 | import warnings
010 | from _collections_abc import Sequence
011 | from errno import EINVAL, ENOENT, ENOTDIR, EBADF, ELOOP
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/oxuyanejip.txt?noredirect
there's a slightly cooler, but kinda obvious, one
!e
print((o:=__import__("subprocess")).check_output([f"/usr/bin/cat", o.__file__])[:250])
there's no cat 😩
!e
print((o:=__import__("subprocess")).check_output([f"exec < {o.__file__} ; while read -r ln; do echo \"$ln\"; done"], shell=True)[:250])
sandbox: 2 me: 0
seems like external commands used to work
!e
import sys; sys.addaudithook(print); exec('try:\n print((o:=__import__("subprocess")).check_output([f"/usr/bin/cat", o.__file__])[:250]);\nexcept:\n pass\ntry:\n print((o:=__import__("subprocess")).check_output([f"exec < {o.__file__} ; while read -r ln; do echo \\"$ln\\"; done"], shell=True)[:250]);\nexcept:\n pass\n')
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | compile (b'try:\n print((o:=__import__("subprocess")).check_output([f"/usr/bin/cat", o.__file__])[:250]);\nexcept:\n pass\ntry:\n print((o:=__import__("subprocess")).check_output([f"exec < {o.__file__} ; while read -r ln; do echo \\"$ln\\"; done"], shell=True)[:250]);\nexcept:\n pass\n', '<string>')
002 | exec (<code object <module> at 0x7f891c4c1e70, file "<string>", line 1>,)
003 | import ('subprocess', None, ['', '/snekbox/user_base/lib/python3.10/site-packages', '/usr/local/lib/python310.zip', '/usr/local/lib/python3.10', '/usr/local/lib/python3.10/lib-dynload'], [<class '_frozen_importlib.BuiltinImporter'>, <class '_frozen_importlib.FrozenImporter'>, <class '_frozen_importlib_external.PathFinder'>], [<class 'zipimport.zipimporter'>, <function FileFinder.path_hook.<locals>.path_hook_for_FileFinder at 0x7f891c5e8af0>])
004 | os.listdir ('/snekbox',)
005 | open ('/usr/local/lib/python3.10/__pycache__/subprocess.cpython-310.pyc', 'r', 524288)
006 | marshal.loads (b'\xe3\x00\
... (truncated - too long, too many lines)
Full output: too long to upload
All console commands are blocked now on snekbox
As in os.system etc.
ah, well that explains it 😅
hi
there was a :bigbrain: thing, and now you'll never see it
>>> ().__class__.__class__.__eq__.__name__[:2]+print.__module__+[].__class__.__dir__.__name__[:2]
>>> '__builtins__'
a script that can create a string entirely out of these class and method names would be so cool.
>>> convert('abc')
"string.__class__.__class__.__subclasses__.__name__[7]+print.__module__[0]+ord.__class__.__name__[11]"
hey guys, how can i do to take some expressions or a value from another app with a python script ? thanks
subprocess module ?
Not sure if this counts as esoteric, but I've written a tiny parsing library that uses __build_class__ for some nasty syntactic sugar: https://github.com/L3viathan/parsehole
e.g. ```py
class AddExpression(Tree):
AddExpression + AddOperator + AddExpression
MulExpression
I do not understand
unfortunately, I can't figure out a way to get 'q' from these classes
!e
print(repr(
f"{{:{[].__class__.__mro__[1].__name__[4]}}}".format((int(().__class__.__name__[3],36)+92))
))
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
'q'
shorter would be cool, but ..
[].class.class.eq.name[3]
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
q
wonder how likely is it that list's docstring would change
tries om 2.7
Python 2.7.18 (default, Mar 20 2021, 14:58:25)
[GCC 4.2.1 Compatible Android (6454773 based on r365631c2) Clang 9.0.8 (https:/ on linux2
>>> [].__doc__[19]
' '```
set.__doc__ ?
!e
print(repr(
[].__class__.__class__.__eq__.__name__[3]
))```
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
'q'
you have python 2.1 ? does it give a REPL after that?
looks pretty normal then right
yup
Because eval returns
!e py print(repr( f"{{:{[].__class__.__mro__[1].__name__}}}".format((int(().__class__.__name__[3],36)+92)) ))
@nimble basalt :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | ValueError: Invalid format specifier
!e py print(repr( f"{{:{[].__class__.__mro__[1].__name__[0:]}}}".format((int(().__class__.__name__[3],36)+92)) ))
@nimble basalt :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | ValueError: Invalid format specifier
!e py print(repr( f"{{:{[].__class__.__mro__[1].__name__[4]}}}".format((int(().__class__.__name__[3],36)+92)) ))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'q'
!e print(repr([].doc))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'Built-in mutable sequence.\n\nIf no argument is given, the constructor creates a new empty list.\nThe argument must be an iterable if specified.'
!e print(repr([].doc[19]))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'q'
!e print(repr([].doc[19:]))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'quence.\n\nIf no argument is given, the constructor creates a new empty list.\nThe argument must be an iterable if specified.'
!e ```py
print(
getattr(
[
0
],
'append'
)(
1
)
)
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
None
!e ```py
print(
repr(
str(
repr(
getattr(
[
0
],
'append'
)(
1
)
)
)
)
)
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'None'
!e ```py
print(
repr(
str(
repr(
getattr(
[
0,
[
0,
[
1
][
0
]
]
],
'append'
)(
1
)
)
)
)
)
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'None'
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
"'Ellipsis'"
!e print(repr(repr(repr(repr(repr(...))))))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'\'"\\\'Ellipsis\\\'"\''
!e print(repr(str(repr(repr(repr(repr(...)))))))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'\'"\\\'Ellipsis\\\'"\''
!e ```py
print(repr(repr(repr(
repr(repr(repr(
str(repr(repr(
repr(repr(
getattr(
[
0,
[
0,
[
1
][
0
]
]
],
'append'
)(
1
)
))
)))
)))
))))
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
'\'\\\'\\\\\\\'\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'None\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\\\\\\\\\\\\\\\'\\\\\\\'\\\'\''
Wht lol
What does this do?
!e ```py
_=repr(repr(repr(repr(
repr(repr(repr(
str(repr(repr(
repr(repr(
getattr(
[
0,
[
0,
[
1
][
0
]
]
],
'append'
)(
1
)
))
)))
)))
))))
globals().update({'None': ,})
del globals()['']
shit = None
while "'" in shit:
shit=shit.replace("'","")
while '"' in shit:
shit=shit.replace('"',"")
globals().update({'moreshit': shit})
print(moreshit)
@nimble basalt :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 28, in <module>
003 | TypeError: argument of type 'NoneType' is not iterable
!e ```py
_=repr(repr(repr(
repr(repr(repr(
str(repr(repr(
repr(repr(
getattr(
[
0,
[
0,
[
1
][
0
]
]
],
'append'
)(
1
)
))
)))
)))
)))
globals().update({'none': ,})
del globals()['']
shit = none
while "'" in shit:
shit=shit.replace("'","")
while '"' in shit:
shit=shit.replace('"',"")
globals().update({'moreshit': shit})
del globals()['shit']
print(moreshit)
@nimble basalt :white_check_mark: Your eval job has completed with return code 0.
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\None\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
I'm not sure I understand. Is this Python?
well for sure a keyboard for python
a planned python implementation for brahmi & devanagari scripts : )
(sample python code in Sanskrit for calculating the Fibonacci sequence)
Does it work as an encoding? Or is it more of a preprocessor? Or an entirely separate interpreter based on Python?
i dont understand anything, but most likely there is bug
instead of a, b = b, a + b you wrote a, b = b, a + 1
ah, someone noticed, yea just fixed it : )
found at github
For reference, the idiomatic* way to write it would be for i in map(next, map(iter, enumerate(iter(int, "")))):.
Couldn't you just do for i, _ in enumerate(iter(int, 1)):
@sick hound :x: Your eval job has completed with return code 143 (SIGTERM).
001 | <generator object <genexpr> at 0x7f54901afd80>
002 | <generator object <genexpr> at 0x7f54901afd80>
003 | <generator object <genexpr> at 0x7f54901afd80>
004 | <generator object <genexpr> at 0x7f54901afd80>
005 | <generator object <genexpr> at 0x7f54901afd80>
006 | <generator object <genexpr> at 0x7f54901afd80>
007 | <generator object <genexpr> at 0x7f54901afd80>
008 | <generator object <genexpr> at 0x7f54901afd80>
009 | <generator object <genexpr> at 0x7f54901afd80>
010 | <generator object <genexpr> at 0x7f54901afd80>
011 | <generator object <genexpr> at 0x7f54901afd80>
... (truncated - too many lines)
Full output: too long to upload
Yes, but that has less extraneous functions.
!e
!eval [code]
Can also use: e
*Run Python code and get the results.
This command supports multiple lines of code, including code wrapped inside a formatted code block. Code can be re-evaluated by editing the original message within 10 seconds and clicking the reaction that subsequently appears.
We've done our best to make this sandboxed, but do let us know if you manage to find an issue with it!*
@sick hound :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | NameError: name 'doc' is not defined
!e ```py
import ctypes
tup = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
(ctypes.c_longlong).from_address(id(tup) + 16).value = 11
print(tup)
@tacit cobalt :white_check_mark: Your eval job has completed with return code 0.
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, <NULL>)
!e ```py
import gc
import ctypes
def modify(self, value):
length = self.len()
(ctypes.c_longlong).from_address(id(self) + 16).value = length + 1
(ctypes.c_longlong).from_address(id(self) + (3 + length)*8).value = id(value)
gc.get_referents(tuple.dict)[0]["append"] = modify
tup = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
tup.append(11)
print(tup)
@tacit cobalt :white_check_mark: Your eval job has completed with return code 0.
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)
nice, show python who's boss XD
... your code ...
tup = ()
tup.append(0)
``` and python crashes xD
That'll only work if there happens to be free memory after the tuple.
You could use _PyTuple_Resize() instead.
those punctuation keys are more cursed than everything else combined
How do you press those keys?
With a toothpick?
Or are they meant to be used like a macro, all at once
I mean the lack of enter key is fine
So I noticed that from module import name1, name2, name3 looks very similar to SELECT col1, col2, col3 FROM table in SQL...
# table.py
_cols = []
_AS = False
_data = []
def insert(row):
_data.append(row)
def _compute_result():
return [
{col: row[col] for col in _cols if col in row}
for row in _data
]
def __getattr__(name):
global _AS
if name == "AS":
_AS = True
elif _AS:
_AS = False
rv = _compute_result()
_cols.clear()
return rv
else:
_cols.append(name)
``` ```py
# main.py
import table
table.insert({"email": "a@a.com", "name": "alice", "age": 42})
table.insert({"email": "b@b.com", "name": "bob", "age": 25})
table.insert({"email": "c@c.com", "name": "charlie", "age": 35})
from table import email, age, AS, rows1
print(rows1)
output:
[{'email': 'a@a.com', 'age': 42}, {'email': 'b@b.com', 'age': 25}, {'email': 'c@c.com', 'age': 35}]
and also a great way to clobber memory lol
!e ```py
import gc
def replace_tuple(self, new):
for container in gc.get_referrers(self):
if isinstance(container, dict):
for k, v in container.items():
if v is self:
container[k] = new
elif isinstance(container, list):
for i, v in enumerate(container):
if v is self:
container[i] = new
elif isinstance(container, tuple):
for i, v in enumerate(container):
if v is self:
temp = list(container)
temp[i] = new
replace_tuple(container, tuple(temp))
elif isinstance(container, set):
container.remove(self)
container.add(new)
def append(self, i):
t = list(self)
t.append(i)
replace_tuple(self, tuple(t))
gc.get_referents(tuple.dict)[0]["append"] = append
x = (0,1,2)
x.append(1)
print(x)```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
(0, 1, 2, 1)
^ personal favorite awful tuple.append
@sick hound :warning: Your eval job has completed with return code 139 (SIGSEGV).
[No output]
_PyTuple_Resize makes a new tuple thats larger then sets that into the pointer you give it
so you dont replace the original, you just make a copy
It can't do that because tup->ob_item is an array on the tuple struct not a pointer to an array
(Lists have a pointer to an array)
why not use this?
@leaden vault@earnest wing i hear ya : )
Why have an enter key when you can use \n and ;? /s
Well in fact the keyboard only sends keycodes
The OS can do whatever it wants with those
\r in ancient versions of MacOS, it's been the *nix \n for ages now
mind of I use this idea for a full* sqlite client
with database("test.db") as db:
from table1 import (
foo, bar, thing as baz, _,
limit as one_hundred,
offset as five,
order_by as foo, asc, baz, desc,
)
for foo, bar, baz in db:
print(foo, bar, baz)
How's this
probably some tweaking needed in the syntax
How would you intercept as five and such?
check caller globals in module getattr
for the next import name
(this example should have another extra _ at the end)
challenge: make the shortest code in python that always wins tic tac toe/noughts and crosses.
criteria:
- always gets win or draw
- is short
- uses no modules
i tried doing it and its surprisingly really painful. there's no prize or anything but im curious to see how it'll be approached, considering most of what i've found online is at least 100 lines.
not perfect, but it is a start
def c(b,g):
for i,n in enumerate(b):r=b.copy();r[i] = g;n or (yield i,r)
w=lambda b:next((sum(c) for c in [b[:3],b[3:6],b[6:],b[::3],b[1::3],b[2::3],b[::4],b[2:7:2]] if sum(c)in[3,-3]),0)
def m(g,b):
if a:=w(b):return a,-1
l=[(m(-g,n)[0],i)for i,n in c(b,g)]
return [min,max][g>0](l)if l else (0,-1)
s=[0]*9
while not all(s):_,v=m(1,s);s[v]=1;w(s)and mw;print(s[:3],s[3:6],s[6:],sep='\n');s[int(input())]=-1;w(s) and hw
d
very impressive so far.
just realised i should probably say the format of input and output...
ye, I am using nameerrors to indicate game results
players input has to be dictated by the coordinates of the place they make their turn. e.g a1 = the top left square. output has to be a grid of the board formatted like:
OXX
XOO
OXX
after each time the bot makes the move, the board must be printed.
if the other player forces a draw, the program should return False
otherwise, it should return True
i'll create a document of each entry and how it works.
if its very obfuscated or very weird u get a cookie (but dont win)
multiple entries are allowed, btw! if i see anything particularly cool thats cool.
finally, the code should be run by entering c(v).
v should be who goes first.
minor changes to this format are ok!
finally, its ending on the 13th. ping me with your entries.
have fun
if anything there doesn't make sense dm me.
... not something I'd call a "hug" ._.')
There are two hard problems in computer science...
!e
class Sneaky:
def __eq__(self, other):
other['bit_length'] = 42
int.__dict__ == Sneaky()
print(repr(int.__dict__)[0:250])
print((1).bit_length)
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | mappingproxy({'__new__': <built-in method __new__ of type object at 0x7f8174455540>, '__repr__': <slot wrapper '__repr__' of 'int' objects>, '__hash__': <slot wrapper '__hash__' of 'int' objects>, '__getattribute__': <slot wrapper '__getattribute__'
002 | 42
^ found this trick in https://bugs.python.org/issue43838
the talk of fixing this by having mappingproxy copy the undetlying dict when calling comparison operators, which.... just no...
thankfully they're not fixing it
def str__invert__(self: str) -> str:
return self[::-1]
class str__invert__trick:
def __eq__(self, other):
other['__invert__'] = str__invert__
str.__dict__ == str__invert__trick()
print(str.__invert__('123')) # 321
print('123'.__invert__()) # 321
print(~'123') # TypeError: bad operand type for unary ~: 'str'
why ~'123' doesnt work?
can i use the result of INPLACE_XXX for anything other than STORE_XXX?
for example:
LOAD_GLOBAL (print)
LOAD_FAST (x)
LOAD_CONST 1
INPLACE_ADD # result pushed to stack
CALL_FUNCTION 1 # result used as function argument
i mean when you see INPLACE_XXX, the next instruction is always STORE_XXX.
.
so i get a segfault for fiddling with code object,
one possible cause is what i asked above, but that's just my guess
because PyUnicode_Type has no nb_invert in its tp_as_number methods?
someone here had a package that might help with that (@rugged sparrow ?)
!e
from forbiddenfruit import curse
def __invert__(self):
return self
curse(str, "__invert__", __invert__)
print(~"hello")```
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
hello
You need to modify the slot functions for most dunders
Forbidden fruit or fishhook can do it
I prefer fishhook cause it can handle exceptions in hooked methods (disclaimer I wrote fishhook)
!e
from forbiddenfruit import curse
def __invert__(self):
raise BaseException(self)
curse(str, "__invert__", __invert__)
print(~"hello")```
@rapid sparrow :x: Your eval job has completed with return code 139 (SIGSEGV).
001 | Exception ignored on calling ctypes callback function: <function __invert__ at 0x7fafbf8b8d30>
002 | Traceback (most recent call last):
003 | File "/snekbox/user_base/lib/python3.10/site-packages/forbiddenfruit/__init__.py", line 328, in wrapper
004 | return func(*args, **kwargs)
005 | File "<string>", line 3, in __invert__
006 | BaseException: hello
SIGSEGV lol
that could be an issue
!e
from fishhook import hook
@hook(int)
def __invert__(self):
raise BaseException(self)
print(~"hello")```
@rapid sparrow :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | ModuleNotFoundError: No module named 'fishhook'
>>> from fishhook import hook
>>> @hook(str)
... def __invert__(self):
... raise BaseException(self)
...
>>> ~'a'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __invert__
BaseException: a
>>> ```
there's something to be said for letting the interpreter keep running
!e ```py
from forbiddenfruit import curse
def f(self):
raise Exception
curse(str, 'invert', f)
try:~'a'
except:pass```
@rugged sparrow :x: Your eval job has completed with return code 139 (SIGSEGV).
001 | Exception ignored on calling ctypes callback function: <function f at 0x7fa3c11f8d30>
002 | Traceback (most recent call last):
003 | File "/snekbox/user_base/lib/python3.10/site-packages/forbiddenfruit/__init__.py", line 328, in wrapper
004 | return func(*args, **kwargs)
005 | File "<string>", line 3, in f
006 | Exception:
is it just because they don't call PyExc_Check ?
its because forbiddenfruit uses ctypes to wrap functions
and ctypes is for external libs, not functions that use exceptions
ah
fishhook on the other hand hijacks the process that python already has in place for user defined classes
can any C callback function propagate exceptions?
not easily
because ctypes is built for C code that doesnt mesh with python
otherwise youre supposed to make an extension module
that looks handy
so 3 / 5 is 0 in python 2
ahh
that's why you say it's useless then
oh, I didn't realize
there's no replacement I guess
does it mention it's deprecated in its doc?
ah, since 3.11
well, the python2 lib2to3 will never be deprecated 😄
true, and I still run across repos that never converted, occasionally
there's been a move away from LL(1) parsers which parso and LibCST are still using it looks like
so they won't be able to parse pattern matching
probably not an issue in practice for converting
fissix and modernize are still around ish
oh, I didn't know about fissix, nice
How could i decompile pyarmor?
!eval
f=lambda _=[]:(_.append(0),~-len(_))[1]
while f()<5:
print('foo')
@golden finch :white_check_mark: Your eval job has completed with return code 0.
001 | foo
002 | foo
003 | foo
004 | foo
005 | foo
!eval
n=type('',(),{'__pos__':lambda _:getattr(_,'')(1),'__neg__':lambda _:getattr(_,'')(-1),'__repr__':lambda _:f'{getattr(_,"")(0)}','':lambda s,n,_=[0]:(_.__setitem__(0,_[0]+n),_[0])[1]})()
while ++n <= 5:
print('n is',n)
@golden finch :white_check_mark: Your eval job has completed with return code 0.
001 | n is 1
002 | n is 2
003 | n is 3
004 | n is 4
005 | n is 5
@sick hound :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | File "<string>", line 1, in <lambda>
004 | SystemError: _PyEval_EvalFrameDefault returned NULL without setting an exception
@sick hound :white_check_mark: Your eval job has completed with return code 0.
001 | foo
002 | foo
003 | foo
004 | foo
005 | foo
what on earth even is that
I think I see what you mean actually
neat tricks, but pointlessly obfuscated
yeah I figured that was it
the ellipsis bit is neat though
mhm
Just seeing if I still have the brainfuck interpreter memorised. ```py
def brainfuck(c):
a=import('collections').defaultdict(int)
i=p=t=0
def add(i):
a[i]=(a[i]+1)%256
return i,0
def sub(i):
a[i]=(a[i]-1)%256
return i,0
def left(i):return i-1,0
def rite(i):return i+1,0
def dot(i):
print(end=chr(a[i]))
return i,0
def com(i):
a[i]=ord(import('sys').stdin.read(1))
return i,0
def loop(i):
return i,not a[i]
def end(i):
return i,-bool(a[i])
while 0<=p and p<len(c):
if t:t+=(c[p]=='[')-(c[p]==']')
else:i,t=[
add,sub,left,rite,dot,com,loop,end,lambda i:(i,0)
] ['+-<>.,[]'.find(c[p])] (i)
p+=1-2*(t<0)
return int(bool(t))
rite? why not rght
I have a friend who I need to show some weird stuff
We're talking about private attributes and immutability
Anybody has like a codeblock that changes elements in a tuple?
Nevermind I found it up here: #esoteric-python message
thats not a safe method tho, you shouldnt try to mess with the length of a tuple in place cause youll write over memory
people = ["Jeff", "Meriesa", "Emily", "Ken"]
count = 0
while count < len(people):
print(people[count])
count += 1
Dear lord the unholy ways Python has been used for
this is unholy ? lol
heeey
looks like pretty normal from here
it is indeed
It's not pythonic
people = ["Jeff", "Meriesa", "Emily", "Ken"]
for person in people:
print(person)
this is Pythonic
indeed, very
[print(p) for p in ["Jeff", "Meriesa", "Emily", "Ken"]]
who doesn't love throwing away a list though
now esoteric and pythonic
[*map(print, ["Jeff", "Meriesa", "Emily", "Ken"])]
``` or *functional*
This isn't even that esoteric
Remove all the spaces
I shall make up for that wrongdoing
!e
class PrintVisitor:
def visit_person(self, person):
print(person)
class Person:
def __init__(self, name):
self.name = name
def accept(self, visitor):
visitor.visit_person(self)
def __repr__(self):
return self.name
class People:
def __init__(self, *names):
self.names = names
def accept(self, visitor):
for p in self.names:
p.accept(visitor)
pv = PrintVisitor()
people = People(
Person("Jeff"),
Person("Meriesa"),
Person("Emily"),
Person("Ken"),
)
people.accept(pv)
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | Jeff
002 | Meriesa
003 | Emily
004 | Ken
tada, object-oriented
It's still too well formatted
Lol, enterprise version
!e
_=type("Person",(),{"__init__":lambda self,name:setattr(self,"name",name),"accept":lambda self,visitor:visitor.visit_person(self),"__repr__":lambda self:self.name});pp=type("People",(),{"__init__":lambda self,*names:setattr(self,"names",names),"accept":lambda self,visitor:list(_.accept(visitor)for _ in self.names)});pp(*map(_,["Jeff","Meriesa","Emily","Ken"])).accept(type("PrintVisitor",(),{"visit_person":lambda self,person:print(person)})())
@rapid sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | Jeff
002 | Meriesa
003 | Emily
004 | Ken
"minified" enterprise version 💄
love the __import__("sys").stdin.read(1) ❤️
worry no more if somebody already imported sys or not
!eval
n=type('',(),{'__pos__':lambda _:getattr(_,'')(1),'__neg__':lambda _:type('',(),{'__neg__':lambda s,c=_:getattr(c,'')(-1)})(),'__repr__':lambda _:f'{getattr(_,"")(0)}','':lambda s,n,_=[0]:(_.__setitem__(0,_[0]+n),_[0])[1]})()
while ++n <= 5:
print('n is',n)
while --n >= -5:
print('n is',n)
@golden finch :white_check_mark: Your eval job has completed with return code 0.
001 | n is 1
002 | n is 2
003 | n is 3
004 | n is 4
005 | n is 5
006 | n is 5
007 | n is 4
008 | n is 3
009 | n is 2
010 | n is 1
011 | n is 0
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/etiliqayar.txt?noredirect
thats because python cant know how big to make the stack then
python allocates the stack for a frame on the frame object, and if compositions are inlined then the stacksize is indeterminate
the reason they arent inlined and just call LIST_APPEND is because they are implemented like inline generators (which require the code object) and use most of the same code and logic to compile
what's an inline generator?
ah.. so not a function with yield
I find these preferable, very rarely write them "out-of-line"
that (a) leaks names into the outer scope, and (b) requires adding new compiler logic that differs from the generator logic
!e ```py
[x for x in range(1)]
print(x)
@rugged sparrow :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | NameError: name 'x' is not defined
this would not fail given your version (some may say thats a good thing, but that also differs from inline generator semantics as well)
fair but the point still stands
also the PEPs that added list comprehensions and generator expressions both specify it as a syntactical change, not a core change
that means that changes to the eval loop should not be required for implementation
python2 does so right?
it does
is there any possible code that, when added at the top level of a module, could change the __code__.co_code of a function below it before the module is even executed?
source_original = """
def func():
pass
"""
source_altered = f"""
# code here to change the compiled bytecode of func
def junk():
pass
{source_original}
"""
code_original = compile(source_original, "", "exec")
code_altered = compile(source_altered, "", "exec")
assert (
code_original.co_consts[-3].co_code !=
code_altered.co_consts[-3].co_code
)
you can use this for testing if you like
oh, and you can change the signature of func as long as its the same in both
basically im trying to figure out how much of a module's code you need to give the compiler the correct context when compiling a function (including arbitrarily nested ones, and methods). safest bet seems to be to use the whole module then extract the function bytecode from that, but i'm wondering if it's safe to use a subset of the module code instead, like just grabbing whatever's nearest from the top level leading to that function and using that.
is it possible to modify *iterable (unpacking iterables into func args) behavior?
for example make it unpack double the iterable's content
if its a list of ints, make it unpack all those ints but squared
!e ```py
def doubler(it):
for v in it:
yield v
yield v
print([*doubler(range(2))])```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
[0, 0, 1, 1]
@sick hound like that?
no no like actually modifying the values, eg [1, 2, 3] turns into [1, 4, 9] when unpacking
and without having to add a doubler() there
one way could maybe be to use sys.settrace. you could track code execution, down to individual lines and instructions. then when encountering an unpack do it yourself into the frame.
another way could be to use an import hook + ast, or a custom codec to change the unpacking into whatever you want
what are frames exactly, sorry im pretty much a newbie in this esoteric stuff
do you have any website explaining that or any resource
i think https://docs.python.org/3/reference/datamodel.html and https://docs.python.org/3/library/inspect.html are probably the best bets for frame documentation
nice, thanks
a frame object keeps track of the current execution info, for example the bytecode being currently run, what was the previous function being run, the globals, locals, etc
!e
import inspect
def what_called_me():
current_frame = inspect.currentframe()
previous_frame = current_frame.f_back
print(inspect.getframeinfo(previous_frame))
def test():
what_called_me()
test()
@brazen geyser :white_check_mark: Your eval job has completed with return code 0.
Traceback(filename='<string>', lineno=9, function='test', code_context=None, index=None)
if you scroll down a little on the inspect doc you can see a list of what variables frame objects have
there's something called a 'call stack'. this is more or less a list of frame objects. every time a function is called, a module is executed or a class is defined, a new frame is added on top of the call stack to keep track of the code being executed inside of it. there might be other cases where a new frame is added too but i cant remember atm if so.
the call stack comes in handy when figuring out where to continue off of after the current function returns, or to print helpful error messages pointing to where an exception occurred, since frames keep track of all that.
all good, think i should also make it clear that frames get removed from the call stack after the function/module/class def/whatever finishes. forgot to mention that.

thanks again
I try to break each problem up into one line each.
so getting one character from stdin gets one line:
a[i] = __import__('sys').stdin.read(1)
yes
but 99.99% of the time it shouldn't
well how do we make it so that 0% of the time it shouldn't?
oh what code could do that?
#bot-commands message
(that example probably doesn't work)
im looking for changes before the module is executed
i.e. something thatll change the bytecode of a function below it purely during compilation
I don't believe that's possible (though I'm not aware of the import hacks, which could 50/50 do this)
for example, having a value defined in an outer scope can change which LOAD instruction gets used inside the function
#bot-commands message
working version for posterity
I think you'd have to mess with imports to do that
not so much something im trying to do, just want to know if i should take into account for something im working on atm
Are you evaluating user input?
im transforming and recompiling code
not from user input, just ordinary files
then after recompiling im putting the code back into the function it originally came from
textwrap.dedent(inspect.getsource(function)) doesnt cut it for all functions because it can leave out some important context that affects compilation, so instead im recompiling the entire module with changes done to the specific function
and then after that its just a matter of traversing the recompiled meodule's co_consts to get the new function code
oh, no, then
ideally though, instead of recompiling the entire module, i'd want to cut down the code to just the bits that are context relevant. it seems like that would be whatever ancestor node is at the top level, but im not sure so just sticking with the whole module for now
you mean looking at the source AST?
yeah, i mean ast node
yes, it's possible, certainly for module-level functions. but it's difficult to get the scopes right, especially if the code is inside of a class.
I'd like to see it
should be ready soon, getting the repo up and going and all that now
it relies on line number to make a mapping from code -> node -> code which admittedly isnt the best option but couldnt really think of any better alternative ast markers
my experience (I think for the same reason typing.get_type_hints is problematic when deferred annotations are used) is it's difficult to get the scopes exactly right for any context in order to make sure all the right names are available to the compiler
but if you have something that works, that'd be amazing
as long as there isnt any way to make <#esoteric-python message> this assertion succeed it should be okay
me trying to figure out what I wrote half a year ago to relearn python:
this is how a mathematician writes python
I'm actually starting to understand this.
time to write an image deepfryer now
we can
p = print
p(1,2,3,4)
1 2 3 4
is there a way to 'rename' keywords too ?
like custom names for 'for','import' etc
why would you want that?
There is it's just too tedious to be worth it
pls share
i wanna see how tedious it is : )
As I know,
you can rename Imports...
If you Import random as r
you can use it as r.shuffle(list) instead of random.shuffle(list)
You can if you compile your own version of Python
Alternatively: codec, import hook, ...
i don't think import hook would work on files that have syntax errors
This uses the same mechanism as p = print.
you could pre-process the code though, replace the keywords before parsing
yeah
is there any resource to get started with obfuscating python?
this is some interesting shit i wanna do
basically i wanted to make python work for someone who doesn't know english
and my deepfryer is complete!
it's easier in the long run to simply learn those few words
so this seemed promising : )
if they want to read any python code, they'd need to learn it either way
that's ok
so was wondering if there's an easy way to change those 'for' 'if''s into somethin else
I seem to remember a study that showed new developers were better able to solve programming puzzles when the keywords were translated into their mother tongue.
no idea what the vars mean, but at least i can guess the what it does
maybe at first, but if everyone does that, you can't even guess the algorithm just by looking at code written in "proper python"
is it easy tho, like could i just replace those keywords, and boom, japanese or hindi python!
I can set the constant to deepfry at
well.. i guess it takes a little regex voodoo to catch all for except etc. properly, but in essence it should be fairly trivial if you do it on the plain text
i wouldn't recommend it though, for the simple reason that they couldn't even read the help() without confusion
let alone SO
!e would you catch this?
print(*[0x00for x in input("hello world!")])
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
15
the editor is dumb lol
Here is my deepfryer, enjoy yourselves
import PIL.Image
def deepfry(victim='victim.png', cursed='cursed.png',constant=380):
Im = PIL.Image.open(victim)
x,y = Im.size
target = PIL.Image.new('RGB',(x,y),0xFF0000if constant>0else 0x0000FF)
for j in range(y):
for i in range(x):
if sum(Im.getpixel((i,j))[:3])>abs(constant):
target.putpixel((i,j),0x0000FFif constant>0else 0xFF0000)
target.save(cursed)
target.close(),Im.close()
return 0
if __name__=='__main__':deepfry(constant=100)
pycharm is smort
pycharm holds it's "smart" title
i tried regex to convert code from a text file, tho i need to learn more to make those chars work in other langs
i wonder if regex has the capability tho
made a small edit, so that you can invert it
honestly, if it's about teaching programming to someone who doesn't understand english, i would probably recommend a no-code language even
something graphical without any code-constructs at all
for some reason this only works from PyCharm
I remade the logo
what would you say if it's not about teaching and just for fun and something recreational and #esoteric-python : )
go ahead 😉
actually this was the plan if you're wondering
(func for fib sequence)
Make it harder to read
congratiulations, now it's a captcha
I think only a robot could read that
: ) basically
you are unironically right lol
saying from my sanskrit tests with gpt-3
why is it so blotchy? does discord convert the images to JPEGs?
it seems to be blurry and have alternating thick and thin letters. maybe it's subpixel anti-aliasing gone bad? 🤣
I know this isn't a help channel as such but I feel like the people here will know.
How can I redirect stdout such that I can assign to it. E.g. if I did help_text = help(list.sort) I could then do print(help_text) to get the help text
Edit:
this seems to work
import io
import sys
old_stdout = sys.stdout
s = io.StringIO()
sys.stdout = s
print("test")
sys.stdout = old_stdout
print(s.getvalue())
I chose the wrong deepfry constant
cos I rounded down
Please don't ping users/roles for help. Just ask your question in a help channel (see #❓|how-to-get-help) and someone will help you when they can. @unreal anvil
oh sorry my bad
!e ```py
from ctypes import py_object as p
class annotations(metaclass=lambda*a:type(*a)()):
q={}
def setitem(self, this, that):
if this in globals():
dict.update(globals(),{this:that(globals()[this])})
else:self.q[this]=that
def getitem(self, this):
if this in self.q:return q[this]
return globals()[this].class
def del(self):
p.from_address(id(globals())+8).value = dict
print("Unused variables:",*self.q)
class flogbals(dict):
def setitem(self, this, that):
if this in annotations.q:that=annotations.q.pop(this)(that)
dict.update(globals(),{this:that})
p.from_address(id(globals())+8).value=flogbals
#start
a:str
a = 6
b:str = 9
c: int = a + b
print(c)
#end
@floral meteor :x: Your eval job has completed with return code 139 (SIGSEGV).
69
well it still does it but doesn't clean up properly
!e ```py
import difflib
import io
import site; site.main()
import sys
def get_difference(a: str, b: str) -> list[tuple[int, str]]:
return [(i, x) for i, x in enumerate(difflib.ndiff(a, b)) if x[0] != ' ']
def get_actual_help_text(item):
old_stdout = sys.stdout
s = io.StringIO()
sys.stdout = s
help(item)
sys.stdout = old_stdout
return s.getvalue()
def get_generated_help_text(item):
item_class_name = type(item).name + ":"
method = item.name.split('.')[-1]
signature = item.text_signature.replace("$", "") or "(...)"
item_doc_string = "\n".join(map(lambda s: " " * 4 + s, item.doc.split("\n")))
return (
f"Help on {item_class_name}\n\n"
f"{method}{signature}\n"
f"{item_doc_string}\n\n"
)
def test_help_texts_match(item):
actual_help_text = get_actual_help_text(list.sort)
my_help_text = get_generated_help_text(list.sort)
try:
assert actual_help_text == my_help_text
except AssertionError:
print(get_difference(actual_help_text, my_help_text))
else:
print(f"Help texts for list.{item.__name__} are equal!")
for attr_name in dir(list):
attr = getattr(list, attr_name)
if callable(attr):
test_help_texts_match(attr)
@last locust :white_check_mark: Your eval job has completed with return code 0.
001 | Help texts for list.__add__ are equal!
002 | Help texts for list.type are equal!
003 | Help texts for list.__class_getitem__ are equal!
004 | Help texts for list.__contains__ are equal!
005 | Help texts for list.__delattr__ are equal!
006 | Help texts for list.__delitem__ are equal!
007 | Help texts for list.__dir__ are equal!
008 | Help texts for list.__eq__ are equal!
009 | Help texts for list.__format__ are equal!
010 | Help texts for list.__ge__ are equal!
011 | Help texts for list.__getattribute__ are equal!
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/elixupakaz.txt?noredirect
!e ```py
from ctypes import py_object as p
class annotations(metaclass=lambda*a:type(*a)()):
q={}
def setitem(self, this, that):
if this in globals():
dict.update(globals(),{this:that(globals()[this])})
else:self.q[this]=that
def getitem(self, this):
if this in self.q:return q[this]
return globals()[this].class
def del(self):
print("Unused variables:",*self.q)
class flogbals(dict):
def setitem(self, this, that):
if this in annotations.q:that=annotations.q.pop(this)(that)
dict.update(globals(),{this:that})
def start():p.from_address(id(globals())+8).value=flogbals
def end():p.from_address(id(globals())+8).value=dict
start()
a:str
a = 6
b:str = 9
c:int = a + b
d:dict
print(c)
end()
@floral meteor :white_check_mark: Your eval job has completed with return code 0.
001 | 69
002 | Unused variables: d
perfect
Hey can I get assistance in python over here?
Read #❓|how-to-get-help
!d contextlib.redirect_stdout
contextlib.redirect_stdout(new_target)```
Context manager for temporarily redirecting [`sys.stdout`](https://docs.python.org/3/library/sys.html#sys.stdout "sys.stdout") to another file or file-like object.
This tool adds flexibility to existing functions or classes whose output is hardwired to stdout.
For example, the output of [`help()`](https://docs.python.org/3/library/functions.html#help "help") normally is sent to *sys.stdout*. You can capture that output in a string by redirecting the output to an [`io.StringIO`](https://docs.python.org/3/library/io.html#io.StringIO "io.StringIO") object. The replacement stream is returned from the `__enter__` method and so is available as the target of the [`with`](https://docs.python.org/3/reference/compound_stmts.html#with) statement:
```py
with redirect_stdout(io.StringIO()) as f:
help(pow)
s = f.getvalue()
``` To send the output of [`help()`](https://docs.python.org/3/library/functions.html#help "help") to a file on disk, redirect the output to a regular file...
do you want this?
for this specific use case i think you can use result = pydoc.render_doc(...)
pydoc's in the stdlib, but not very well documented
this is how I do it generally: ```py
class redirect_stdout:
def enter(self, target):
self._kerfunkles = sys.stdout or sys.stdout
sys.stdout = target
return target
def exit(self, *fuckit):
sys.stdout.close()
sys.stdout=self._kerfunkles
with redirect_stdout(open('example.txt'))as f:
help(pow)
write it from scratch, and you can tweak it.
i dont know how long it's been there
nice vararg .. that's a pythonic name if I ever saw one
__enter__ takes no arguments, only self
!e py while True or a: pass
@astral rover :warning: Your eval job timed out or ran out of memory.
[No output]
never compiles
it compiles it just loops infinitely
wait what
James@Jamess-Air ~ % python3
Python 3.10.0 (v3.10.0:b494f5935c, Oct 4 2021, 14:59:20) [Clang 12.0.5 (clang-1205.0.22.11)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> while True or a: pass
...
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^Z
zsh: suspended python3
James@Jamess-Air ~ % ```
!e py print(compile('while True or a: pass', '', 'exec'))
@rugged sparrow :warning: Your eval job timed out or ran out of memory.
[No output]
https://bugs.python.org/issue45773 i didnt find this obviously
does this count?
Is it missing a colon?
yeah i couldnt find a way to get it in there
Does C use any colons?
yeah and you cant have it in macros
You could make main() and numbers expand to something you can put before and after a colon.
Then you could put the colon between them.
Also, the list won't work in Python.
It takes one iterable argument, rather than any number of arguments.
I can't tell if that's C and your screwing with define or python comments
would likely run in either
Where can I ask questions on structure of simple programs?
I am newer to Python.
My friends dad is in the hospital right now and is all he can do is move a finger or two at a time for now. We want to code a program where he can use 1 button on a keyboard to type sentences... like the guy in breaking bad...
Where should I start... any tips are HIGHLY appreciated.
Nevermind
This particular channel is probably the opposite of what you want. Try googling some tutorials, then asking in #❓|how-to-get-help if you get stuck with what you want to make.
I once saw a way of building a class that was its own metaclass
Or atleast did a pretty good job pretending to be
Does anyone have that handy?
yes, I do
one second
class A(type):pass
class B(type,metaclass=A):pass
B.__class__ = B
this?
Is there any way to chain metaclasses past depth-2?
i.e for all objects, can their __class__.__class__ be anything other than type?
oh you're right I forgot __init__
