#esoteric-python
1 messages ยท Page 10 of 1
here's one that doesn't use ''
enc_str = "\x27\x48\x65\x6c\x6c\x6f\x27"
print(enc_str)
``` which is like a really simple thing
could just strip ''
ByteCode
ByteCode seems like a cheap excuse
although its still decent
Imo it doesn't matter how obsfucated you make the encoding process (in this case the bit operations) if you in the end just do .join([chr(...), ...]) cause someone can always just print that out
I would find a different way to produce executable code rather than just chr and join

And, someone can always just rename the variables to make it more readable then go through it step by step

's not bytecode
hexcode?
shitcode?
same thing, easy decode.
uncompyle6 can easy decode that string i think?
no
it's not a deobfuscator
it's a decompiler
yeah?
decompiles python code objects
Yeah pretty sure a decompiler doesn't remove that hex string
which is only accessible via a dead discord invite
@quartz wave I am working on my mixins
i don't know what that is
it's literally just the text written with hex escapes
!e
enc_str = [ 39, 72, 101, 108, 108, 111, 39 ]
enc_str = bytes(enc_str).decode()
print(enc_str)
@fleet bridge :white_check_mark: Your 3.11 eval job has completed with return code 0.
'Hello'
.
its basically code injection
# ABC.py
from Mixin import Mixin, C
import Test
C({'debug': False})
@Mixin(target=Test.SomeTestFunc, at="tail")
def SomeTestFuncMixin(*args, **kwargs):
print(" World!")
Test.SomeTestFunc()
``````py
# Test.py
def SomeTestFunc():
print("Hello", end="")
flag = "CTF{" + "a" * 32 + "}"
PS 7.3 Lmaxplay C:\Users\Lmaxplay\Projects\PythonMixins> python ./ABC.py
Hello World!
PS 7.3 Lmaxplay C:\Users\Lmaxplay\Projects\PythonMixins>
@pure dew see?
anyways my current impl doesn't support external modules
btw the CTF{} part is me testing a thing to access variables
yea its kinda broken on external modules
and can't access vars
and only head and tail injection
well
to inject head or tail, all you have to do is exec() the function in the current namespace, no?
then it runs, and you get access to all its variables
since it never returns and cleans them up
unless they manually del them
no, you cant exec function
!e
def proof():
print("hello world")
exec(proof.__code__)
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
hello world
@fleet bridge
you can exec a code object of a function
which means you can effectively exec a function
!e
def proof(a, b):
print(a, b)
return a + b
exec(proof.__code__)
@fleet bridge :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 4, in <module>
003 | TypeError: proof() missing 2 required positional arguments: 'a' and 'b'
it works only for useless functions without arguments and that are not using any globals
!e
def proof():
print(a, b)
return a + b
exec(proof.__code__, {"a":1,"b":2})
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
1 2
def proof(a, b):
print(a, b)
return a + b
exec(proof.__code__, {"a":1,"b":2})
exec(proof.__code__, {}, {"a":1,"b":2})
``` doesnt work with arguments
provide the arguments you want in the namespace
that doesnt mean that you can exec any function
this guy is trying to decorate arbitrary function, not only argument-less functions
Yeah
@full talon post your mixin source
I overwrite it
Just python being fk
@full talon i thought your mixin idea was cool so i tried my hand at a version that supports local variable access
>>> def SomeTestFunc():
... flag = "CTF{" + "a" * 32 + "}"
... del flag
...
>>> @Mixin(target=SomeTestFunc, at=At("opcode", op="DELETE_FAST"))
... def SomeTestFuncMixin(flag):
... print(flag)
...
>>> SomeTestFunc()
CTF{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
>>> ```
can u show me ur impl
we could work together
yea one sec im adding another target match
>>> class O:pass
...
>>> def test():
... c = O()
... c.a = 1
... b = 1
... if c.a == b:
... print('dont want this')
... elif b == 2:
... print(2)
...
>>> @Mixin(target=test, at=At("match", f=lambda b,c:c.a == b))
... def mixin(b, c):
... print('here', c.a, b)
... b = 2
...
>>> test()
here 1 1
2
>>> ``` got it to work i think?
https://paste.pythondiscord.com/tujiqiyeru.py @full talon
i basically inline the bytecode from the mixin function (along with some logic to make sure jumps work)
actually my stackeffect function might be really broken
nevermind all of it is broken lmao
for loops whoops
>>> do_something=lambda v:None
>>>
>>> def testLoop():
... for x in range(10):
... do_something(x)
...
>>> @Mixin(target=testLoop, at=At("match", f=lambda x:do_something(x)))
... def mixinLoop(x):
... print('here', x)
...
>>> testLoop()
here 0
here 1
here 2
here 3
here 4
here 5
here 6
here 7
here 8
here 9
>>> ``` fixed it, I was handling relative jumps wrong
https://paste.pythondiscord.com/edubopowig.py @full talon
@pure dew ^ working on mixins
@rugged sparrow I am redoing the code
to make it more readable
and use actually readable names 
@rugged sparrow, question: can you join me live in vscode?
like I have the live extension
I NOW, TOGETHER WITH @rugged sparrow, HAVE MIXINS IN PYTHON
๐
smh are we really continuing the sponge trend of stuff named mixins that aren't actually mixins
this is like, actual mixins
it doesn't work with compiled code, YET
as for that it would need to compile ur code to C
In object-oriented programming languages, a mixin (or mix-in) is a class that contains methods for use by other classes without having to be the parent class of those other classes. How those other classes gain access to the mixin's methods depends on the language. Mixins are sometimes described as being "included" rather than "inherited".
Mixin...
Why you are changing original function without decorating it? Isnt is more explicit and more convenient to decorate original function and return some wrapper?
It is possible to implement without messing with bytecode
real definition of mixin:
- fingerprinting and debugging data inserted into the padding bytes of a struct
What I have so far can find and target specific bytecode locations
so...
i have a friend
and he made this crazy fuckign tool
and
all i have to say is
what the FUCK..??????
!e
def no_args(f):
global __func_code_exec__
__func_code_exec__ = f
def inner():
return globals()["__func_code_exec__"](*globals()["args"], **globals()["kwargs"])
return inner
@no_args
def somefunc(a, b, c, d):
print(a + b + c + d)
args = [1, 2]
kwargs = {"c" : 3, "d" : 5}
exec(somefunc.__code__)
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
11
using global variables, you can
to do multiple at a time, you can give each function an attribute thats a unique string, then use that as globals lookup string to avoid name collisions
or something like that
you are still doing f(*args, **kwargs)
you are not even accessing __code__
.
you are calling function itself
look at the bottom
exec(somefunc.__code__)
you can also call somefunc() directly with the same result as execing its .__code__
the point is that you can exec an arbitrary functions __code__ (as long as the __code__ hasn't been messed with in such a way that it doesn't work, or other such edge cases)
you are not exec'ing arbitrary functions code, you are still exec'ing argument-less function code
yes, it works for functions without argument
and your code it equivalent to:
f1 = lambda a, b, c, d: print(a + b + c + d)
f2 = lambda: f1(*args, **kwargs)
f2()
yes, basically
however, as I've said, that isnt the point
the point is that, given a function that requires arguments, it can be used in such a way that it is turned into an 'argumentless' function that can be execed
you've started with this, saying you can't exec a function at all
then you moved to 'only functions with no arguments or globals'
!e ```py
call_with_args = lambda f, *args, **kwargs: lambda: f(*args, **kwargs)
call_with_args(print, 1, 2, 3)()
@fleet bridge :white_check_mark: Your 3.11 eval job has completed with return code 0.
1 2 3
then only 'no arguments'
then 'can do some, but not any function'
here, i've found a way to do any function
if you want to call function with arguments, you can basically do f(*a,**k)
try it
exec the code of that one
instead of calling directly
you are not executing functions code itself, you are creating new argument-less function and calling it
the point was that "you cant exec func.__code__ is func has arguments"`
!e
call_with_args = lambda f, *args, **kwargs: lambda: f(*args, **kwargs)
exec(call_with_args(print, 1, 2, 3).__code__)
@versed eagle :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | TypeError: code object requires a closure of exactly length 3
see
closure will break
with your way of doing it
something about how __closure__ works breaks when you do it like that
and i know that
because i already tried that way of doing this
im not trying to exec __code__ in my example, im just doing what you are doing in different way
it doesnt do what i did though
the whole point of getting it to be execable was that you could run it in the current namespace (or an arbitrary one)
then examine the variables and whatnot
can you provide example of how we can call function that has arguments?
def f(a, b): return a + b
<some magic>
exec(f.__code__, <some magic>) # here f is original f function and f.__code__ is not changed
cool
ooh
framehacking here i go
i dont know of a way to do it without replacing the function and using globals
my way is more of a hack lmao
but if it works, it works ยฏ_(ใ)_/ยฏ
!e @fleet bridge @versed eagle without anything drastic like using asm_hook, you can always do this: ```py
def myeval(code, *args, **kwargs):
p = lambda *a, **k:None
p.code = code
return p(*args, **kwargs)
def f(a, b): return a + b
print(myeval(f.code, 1, 2))```
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
3
but ya as is you would have to do some serious hooks to allow builtin exec/eval to pass args
(or rebuild from source and just pass them along to the frame constructor)
what causes the __closure__ to be incorrect when doing something like this? i've checked and no matter what, it seems that the closure is the correct length that it asks for
and yet it throws an error
whats up with that
__code__ is a constant value (built at compile time). it pulls values for the closure from the function object. So by execing the code obj you have to pass in the closure manually. 3.11 allows this in exec/eval afaik
ah
i see
exec(source, globals=None, locals=None, /, *, closure=None)
Execute the given source in the context of globals and locals.
The source may be a string representing one or more Python statements
or a code object as returned by compile().
The globals must be a dictionary and locals can be any mapping,
defaulting to the current globals and locals.
If only globals is given, locals defaults to it.
The closure must be a tuple of cellvars, and can only be used
when source is a code object requiring exactly that many cellvars.
found it
i didn't know that closure could be passed in
thats interesting
!e
cl = lambda _:(type((lambda __=...:(lambda:__))().__closure__[0])(_),)
def noargs(func):
def inner():
return func(*globals()["args"], **globals()["kwargs"])
return inner
def somefunc(a, b, c, d):
print(a + b)
args = [1, 2]
kwargs = {"c":3, "d":4}
exec(noargs(somefunc).__code__, closure=cl(somefunc))
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
3
now theres no silly global assignments
only getting arguments from namespace
which can be passed into exec
!e
cl = lambda _:(type((lambda __=...:(lambda:__))().__closure__[0])(_),)
def noargs(func):
def inner():
return func(*globals()["args"], **globals()["kwargs"])
return inner
def somefunc(a, b, c, d):
print(a + b)
exec(noargs(somefunc).__code__, {"args":[1, 2], "kwargs":{"c":3, "d":4}}, closure=cl(somefunc))
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
3
Nice!
@fleet bridge the bytecode trickery pays off ```py
def internal():
... flag = 'hidden value'
... del flag
...
@Mixin(target=internal, at=DeleteVar('flag'))
... def internalMixin(flag):
... print('Got flag:', flag)
...
internal()
Got flag: hidden value
All i have left is EXTENDED_ARG then this will be able to inline pretty much any arbitrary python code
i even made it grab cell variables
def DeleteVar(name):
return Match.build([
['DELETE_FAST', name]
])
``` thats all DeleteVar has to be to find the right spot
wow, thats amazing
it is similar to what i did a month ago
@quartz wave reimplemented it for 3.11: https://github.com/thatbirdguythatuknownot/sniplections/blob/main/inline.py
it is also changing some bytecode places, but it is not so general like yours implementation
Mine has its own limitations, like returns in embedded functions are tricky to deal with
my code can:
- replace LOAD_FAST, LOAD_GLOBAL with LOAD_CONST
- replace
a.bwith LOAD_CONST - ...
Especially if you only want them to skip the embedded code and not the entire block
where can i read your code?
I haven't posted the newest yet
I'll prob post it tomorrow morning
I'll ping you
ok
@fleet bridge https://paste.pythondiscord.com/ijadivuqun.py im gonna try to get extended args to work tomorrow but this is what I have rn
use it like this: ```py
@Mixin(target=<python func>, at=<Location>, ret=<Should keep returns in injected code>, globals=<mapping of items to inject into global namespace of target>)
def mixin(<local names + cell names>):
this code gets inlined, so locals and cells will update as expected (hopefully)
Locations have a few simple ones `Head, Return, Opcode(<opcode name>)`
then you have Match which lets you build more complex location specifiers (like Match(lambda x: x == 1) would match local x == 1 in the target. All of the locations have a .after class method to make them inject after the match instead of before, and they can all be joined with | so you can do join matches, like Head() | Match(...). Match.build gives even more granular control and you can specify exact code constructs. Im going to make some special values for it later that will allow for partial matching, like against all ops that start with LOAD but that doesnt work yet lol
what CPython version should it work on?
def f1(a: int, b: int) -> int:
print(a)
del a
del b
return 42
@Mixin(target=f1, at=Head())
def mixin(b: int) -> None:
print(b)
print(f1(1, 2))
dis.dis(f1)
im running this on 3.11, but it doesnt work properly
it is printing only 42
on 3.10 it works
https://pastebin.com/PQMDRmY4
i type-hinted your code
is is not perfect, it still have some Any's in places where i dont understand what is happening
also, you are assigning new attributes to dis.Instruction, so it causes a lot of type-check errors, and i created new Instruction class (only for type-annotations)
ah i wrote it on 3.10
it most likely has to do with how i dont handle RESUME at all but i havent done a lot of investigation of 3.11 bytecode
what does this do lol
3.11 has RESUME, but it is not a big problem
Big problem is inline caches after different instructions. Every instruction has different number of caches (and it is not documented IIRC). If you want to replace some opcode with other opcode, you should care about number of caches, and add of remove some of them. If you dont - it will segfault (because (if you have too much caches) executing CACHE opcode raises error unconditionally, and (if you have not enough caches) opcodes can wtite something to what they think is cache and break next opcode).
convolve a matrix
!e
lst = [[1,1,1],[1,1,1],[1,1,1],[1,0,1]]
print([[sum(sum(list(i), [])) for i in zip(*[[i[n:n+3] for n in range(len(i)) if len((i[n:n+3])) == 3] for i in lst[y: y+3]])] for y in range(len(lst)) if len(lst[y: y+3]) == 3])
@kindred needle :white_check_mark: Your 3.11 eval job has completed with return code 0.
[[9], [8]]
that's not the big problem
the bigger problem is new instructions and the fact that dis.Instruction.target does not exist
whatever that is
what's dis.Instruction.target?
it doesn't exist in CPython 3.10
or is it something broken in CPython 3.11
It's a quick and dirty way to represent jumps (look at disassemble)
made it work in 3.11
note that some newlines for readability were removed because i was testing it on the REPL
You can find a from and to converter for extended args in my Pyarmor unpacker (u can find it on my github)
What did you have to change
remove the CACHEs in disassemble() and add them back in reassemble()
Dope. I've tried making a few myself but always get stuck at edge cases when I have to recalculate jumps
and also handle the new instruction argument format for LOAD_GLOBAL
idx_in_names << 1 | load_NULL_before
load_NULL_before indicates a function call
actually hold on it should only be for LOAD_GLOBAL and not the other instructions that involve *_GLOBAL
i only tested denball's example
seems like this works
this one when using at=Match(lambda x:do_something(x)) results in an error ```py
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 38, in call
File "<stdin>", line 9, in reassemble
AttributeError: 'Instruction' object has no attribute 'target'
Is it possible for a cache instruction to be a jump target?
Because that would cause that issue
shouldn't it be disassembled before then
Jumps get linked when the destination is found, not the jump
I can fix it I just need to add two loops in order to back up and restore the jumps
so i printed the instruction before the error and it's a FOR_ITER
does that have any relation with the problem
actually CACHEs are not returned by dis.get_instructions()
ok so i printed every place that assigns a value to <instruction>.target and none were printed when i executed that code
wdym
maybe i changed something that made it not work?
lemme test it
oh i did nvm
so i think there should be CACHEs in the bytecode
else the jump offsets won't work
yea, ik how to fix that
loop through instructions and add in dummy cache instructions before calculating offsets
why don't we just check op.offset == op2.argval
you can force get_instructions to show cache entries
then tbh might just leave them in the disassembly, shouldn't have any issues
co_exceptiontable makes this incredibly difficult to implement if I want to perfectly inline code
to the point that i might think of a different way to implement it (using tracing)
hello i need help, like if i Want to execute a function "EXAMPLE" with a hotkey like if i pres F10 it will execute "EXAMPLE"? how to Do that?
!e
import ast
import sysconfig
with open(sysconfig.get_paths()['stdlib'] + '/this.py') as f:
txt = f.read()
a = ast.parse(txt)
a.body[0].value.value = 'yznb' #input()
exec(compile(ast.unparse(a), '<string>', 'exec'))
@royal brook :white_check_mark: Your 3.11 eval job has completed with return code 0.
lmao
Interesting way of editing the source code
Wasn't it possible to directly compile the AST without having the unparse it?
wasn't it ast.compile or smth
i tried but didnt work, gave up and unparsed it kek
!eval yeah, it is ```py
import ast
exec(compile(ast.parse("print('aaa')"), "::<>", "exec"))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
aaa
how much do you know about exceptiontable?
Nothing yet, haven't dug into it yet
i prob confused myself, it works
preparing the "call shape" of a function call
entirely removed in 3.12 because logic was moved to CALL
why?
is there some sort of magic in here i don't understand
Exceptions don't work if you don't build the exceptiontable with correctly
has anyone tried making a version of the python interpreter that allows syntax that's deliberately disabled but would fit in so perfectly in this channel?
I'm thinking something like this case: ```py
def method(self, var):
self.var ^= ~self.var<<var
return self.var
being converted to
```py
def method(self, var):
return self.var^=~self.var<<var
or the especially cursed
while var=8:
do_stuff(var)
instead of
while 1:
var = 8
do_stuff(var)
or
while (var:=8):
do_stuff(var)
The ultimate goal is to make the code both more and less readable at the same time, but an obvious side effect is it is harder for a beginner to debug their code.
bro pls tel what i Need to do
!rule 7
7. Keep discussions relevant to the channel topic. Each channel's description tells you the topic.
ok
Thanks
Anyways I need to find a way to make python do backtraces correctly
can i ask This kuestion there?
As atm it is
Yes
oh
can't you use dis._parse_exception_table() in disassemble() and rebuild it in reassemble()
i might be able to
The more cursed syntax sugar the better. I wonder if even you could make it look a bit like c to confuse other programmers even more
currently i'm working on mixins
I'm afraid the most advanced mixins I'm doing these days is mixin drinks just to see what they taste like
Although I have been writing really slow image processing scripts. I feel like the GPU exists for a reason but I'm not exactly sure what for
I've been running one script with a pretty loadbar on my laptop for a week and all it's doing is doubling the size of an image at a rate of 40 pixels a second haha
I would like to append dataframe to CSV file present in Aws S3, using AWS lambda, can anyone help me regarding this. #python
dang, can you no longer implement hacky gotos by modifying f_lasti? It seems to be completely ignored in 3.11
@brisk zenith looks like that was also an issue back in 2019, do you remember the details of why it worked in some cases but failed in others?
oh dear that's a long time ago
i'm currently busy but let me have a think and get back to you on that
probably frame elision?
the what
I think after a certain version (3.11?) stack frames are sometimes created on-demand and aren't used for anything except the output of _getframe()
life is pain
(minus the pointers that are referenced elsewhere from python like f_globals)
@grave rover are you in a trace function?
nope
i think you have to be in a trace function
oof
yup I see it now, next_instr only changes if the current frame is modified, changes to the parent do nothing
you could set f_trace on the parent to a function that changes lasti then unsets trace func
as long as you have a global trace func
looks like you can only edit f_lineno
Do you have to have f_trace_bytecode or whatever it's called active to edit f_lasti perhaps?
maybe? lemme test that
can you still insert code
?









like edit the code
['_asdict', '_disassemble', '_field_defaults', '_fields', '_make', '_replace', 'arg', 'argrepr', 'argval', 'count', 'index', 'is_jump_target', 'offset', 'opcode', 'opname', 'starts_line', 'target']
โฌ๏ธ 3.10
โฌ๏ธ 3.11
['_asdict', '_disassemble', '_field_defaults', '_fields', '_make', '_replace', 'arg', 'argrepr', 'argval', 'count', 'index', 'is_jump_target', 'offset', 'opcode', 'opname', 'positions', 'starts_line']
there
now its more readable
huh
positions was added
3.10
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='sessions', argrepr='sessions', offset=64, starts_line=13, is_jump_target=True)
Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='sessions', argrepr='sessions', offset=64, starts_line=13, is_jump_target=True)
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=110, starts_line=None, is_jump_target=True)
Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=46, starts_line=None, is_jump_target=True)
3.11
Positions(lineno=7, end_lineno=12, col_offset=4, end_col_offset=71)
Positions(lineno=8, end_lineno=8, col_offset=8, end_col_offset=39)
Positions(lineno=9, end_lineno=12, col_offset=4, end_col_offset=71)
Positions(lineno=10, end_lineno=10, col_offset=8, end_col_offset=40)
Positions(lineno=13, end_lineno=14, col_offset=4, end_col_offset=64)
Positions(lineno=58, end_lineno=59, col_offset=4, end_col_offset=64)
!e ```py
import sys, dis
@lambda c:c()
class goto:
def getattr(self, key):
return key
mul = getattr
@lambda c:c()
class label:
def getattr(self, key):
pass
def jump(frame, lbl):
instructions = [*dis.get_instructions(frame.f_code)]
loc = frame.f_lineno + 1
for idx, i1 in enumerate(instructions):
if i1.opname in ['LOAD_NAME', 'LOAD_GLOBAL'] and i1.argval == 'label':
i2 = instructions[idx + 1]
if i2.opname == 'LOAD_ATTR' and i2.argval == lbl:
if i1.starts_line is not None:
loc = i1.starts_line
break
else:
print(f'Warning: label .{lbl} cannot be jumped to')
break
else:
print(f'Warning: label .{lbl} not found')
def jumper(frame, event, arg):
frame.f_lineno = loc
frame.f_trace = global_trace
frame.f_trace = jumper
def global_trace(frame, event, arg):
if event == 'return' and frame.f_code == goto.getattr.code:
jump(frame.f_back, arg)
return global_trace
sys.settrace(global_trace)
i = 0
dest = 'start'
label .start
print(i)
if i >= 10:
dest = 'exit'
i += 1
goto * dest
label .exit```
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0
002 | 1
003 | 2
004 | 3
005 | 4
006 | 5
007 | 6
008 | 7
009 | 8
010 | 9
011 | 10
this is incredibly cursed
without bytecode level jumps labels have to take place at the start of a line other than that, pretty versatile
this can jump forward and backward, just it cant jump into the middle of an expression
@rugged sparrow I am currently having inf loops
running the above?
wait yeah how the heck are you jumping forward
no?
Porting the code to python 3.11
op.target doesn't exist
So I need to use op.positions
inside jump(...) it scans all the opcodes looking for the LOAD_(NAME|GLOBAL) label + LOAD_ATTR dest
once it finds one, it pulls .starts_line and jumps
op.target was a quick hack i did where disassemble added it in
its not native
oh
๐
bytecode in general is a mess
I need to fix it
e.g. around 3.6 (I think?) they also changed jump offsets to be number of instructions instead of number of bytes
it was 3.9 -> 3.10
yeah that one
cause I wrote my first goto on 3.7 and it finally broke at 3.10
because it used ctypes to change opcodes at runtime (bad idea lmao)
*might have been 3.9
change was in 3.10 (source: pyasm)
can u show the diff
for what
and because it handles it there is no diff
@rugged sparrow I am currently fixing the code
its infinitely looping
Ill need to run 2 debuggers
its probably stuck in compute_stack_effect
!e
from ctypes import *
def f():
pass
py_object.from_address(id(f)+8).value = object.__new__
_=f()
print(_, type(_), sep="\n")
@versed eagle :x: Your 3.11 eval job has completed with return code 139 (SIGSEGV).
001 | <E object at 0x7f8fb27384a0>
002 | <class 'str'>
weird behavior when setting the type of a function to something other than a type
why does it return a string
I don't understand python internals enough to deal with this lmao
did some testing
after changing the type of f, trying to access any attribute of it causes an immediate segfault
including attributes that both a function and builtin_method have
(yes, builtin_method isn't the name, but I'm tired and I can't remember the actual name)
calling f repeatedly returns the same string
since you are setting a field that expects a type to something that isnt a type, there is very little control over what happens without in-depth knowledge of the objects you are swapping and what offsets they share
btw i got the injection to work but the stack somehow overflows
hmm means that compute_stack_effect is prob broken then
ok so i investigated a little bit and found out it's broken when computing FOR_ITER stack effect
interesting
tbh I prob should come up with a better way of computing stack effect
as is code like this ```py
if val:
l = [v1, v2, v3, v4, v5, v6, v7]
maybe I'll make it recursive and have it walk every possible path, with some mechanism for rejoining paths
basically generate a bytecode graph then run a pathfinding algorithm to find the greatest path
would need some logic to avoid infinite loops
just add 9999 to stack size ๐
mfw ```c
char foo[99999999999999999];
actually you could just sum the co_stacksize of both functions and that would be enough
you cant pick just the larger of the 2 because you can't know what the stack state at the injection point will be. But if you sum them, then you will have enough space guaranteed. It will just be wasteful
I will still probably write a better calculate_stack_effect because I want the ability to calculate the overall and max stackeffect of arbitary instructions (including specific subsets of a function's bytecode)
Can you inject function into itself?
If you do it N times, you will get 2^N code size
And 2^N stack size, if you are adding two stack sizes
yea, like i said, not perfect
Not bad too. If you are injecting function to place, where stack has maximum size, then resulting stack size must be at least sum of two stack sizes
And if you are have no weird injection trees, stack sizes will be not very big. At most sum of all involved functions (if you are not injecting any function into many places)
started working on a tool to breakdown bytecode into execution graphs. In theory once I get this working I can build optimizers that function on the graph for bytecode level optimizations
Cool!
ok finally i made it work ```py
do_something=lambda v:None
def testLoop():
... for x in range(10):
... do_something(x)
...
@Mixin(target=testLoop, at=Match(lambda x:do_something(x)))
... def mixinLoop(x):
... print('here', x)
...
testLoop()
here 0
here 1
here 2
here 3
here 4
here 5
here 6
here 7
here 8
here 9
I just realized you can hook __new__ using fishhook o.o
!e
((__import__("fishhook").hook(__loader__.__base__)((_:=(lambda __,*___,**____:"hello world"),_.__setattr__("__name__",__spec__.__class__.__base__.__new__.__name__),_)[~0]),print(type("",(),{})())))
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
hello world
not the most esoteric thing, but an interesting idea, imo
I'll make a fully dunder-only version soon
why not use my obfuscator
because I want to do it myself :>
ty :)
your obfuscator is very cool, by the way
later today I'm going to test it on my asm implementation
and see if it works on that
certainly a more fun thing to do than biology lol
tbh would probably be easier to implement these using inspect.getsource get the AST, then inject AST into that tree, then compile
would be more backwards compatible
(lambda clearCmd = input("ENTER COMMAND FOR CLEARING SCREEN:"), width = 10, height = 10, world = "", x = 5, y = 5, player = "@", main = (lambda main, world, width, height, x, y, player, clearCmd, running = True, draw = (lambda world, width, height, x, y, player, clearCmd, os = __import__("os"): [os.system(clearCmd)] + [print(world[i] if int(i - i // height * width) != x or int(i // height) != y else player, end="") if int(i - i // height * width) != width - 1 else print(world[i] if int(i - i // height * width) != x or int(i // height) != y else player) for i in range(len(world))]): [inp := input()] + [running := False if inp == "q" else [[x := x - 1] if (x - 1 > 0 and inp == "a") else [x := x + 1] if (x + 1 < width - 1 and inp == "d") else [y := y - 1] if (y - 1 > 0 and inp == "w") else [y := y + 1] if (y + 1 < height - 1 and inp == "s") else print("ye")] + [draw(world, width, height, x, y, player, clearCmd), main(main, world, width, height, x, y, player, clearCmd)]]) : [world := (world + "#" if (int(i // height) in [0, height - 1] or int(i - i // height * width) in [0, width - 1]) else world + ".") for i in range(width * height)] + [main(main, world, width, height, x, y, player, clearCmd)])()
made a simple gaem in one line
@rugged sparrow do you know whats causeing the mixins to break?
nope
huh
bruh
huh
fixed it
theres... something wrong
its... breaking the print
@rugged sparrow
its crashing when functions are called
that doesn't work with a REPL does it?
Yea it wouldn't work in the repl
Not every bytecode is representable as ast
why would bytecode matter there?
Because after injection you can get bytecode that has no corresponfing ast
For example, you are injecting code to places, where some var is loaded. Injected code may have statements, var may be loaded inside expression. So, you should inject statements into expression. It is impossible at ast level, but is possible at bytecode level
Hey @rocky leaf!
It looks like you tried to attach file type(s) that we do not allow (.ansi). We currently allow the following file types: .gif, .jpg, .jpeg, .mov, .mp4, .mpg, .png, .mp3, .wav, .ogg, .webm, .webp, .flac, .m4a, .csv, .json.
Feel free to ask in #community-meta if you think this is a mistake.
the only problem i see here is careless injection
it's not like we should inject stuff into invalid places
@rugged sparrow if you wanna know, fixing bugs
the mixins are broken lol
https://sas2k.github.io/NumberScript/
hey can anyone give me some feedback on this documentation of my EsoLang
here is the package if you want
!pypi NumberScript
(also the language uses string parsing, then a lexer or parser.)
Encode to ?
"9284919287471394929477295" - this is your result
i dont want the encoded str i want to learn how to encode it
python has a few useful modules
try looking at base64
user@host:~$ python
Python 3.11.0rc1 (main, Aug 8 2022, 18:31:54) [GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64 as b64
>>> b64.b64encode
<function b64encode at 0x7fd94cd17920>
>>> b64.b64encode(b"hello world")
b'aGVsbG8gd29ybGQ='
def bin_chars(STR:str, table:str, lis=[]): [lis.append('1') for char in table if char in STR else lis.append('0')]; return lis
What am I doing wrong?
def bin_chars(STR:str, table:str, lis=[]): [lis.append('1' if char in STR else '0') for char in table]; return lis
AH!
bin_chars=lambda S,t,l=[]:l.extend('01'[c in S]for c in t)or l
Wow, now that is interesting.
you probably don't want an argument default to [] because of the mutability but assuming that's part of the API then vibing
!e ```py
try: ...
except a: ...
@fleet bridge :warning: Your 3.11 eval job has completed with return code 0.
[No output]
TIL: exception list in except is lazy-evaluated
why not just ```py
bin_chars=lambda S,t:['01'[i in S]for i in t]
doesn't do what the code originally does but ok
oh
how's this
Thanks, I hate it. Source?
won't run in 3.11 or later, I still have to learn the new bytecode stuff for it
lmao gaslight python
that's not even the hardest part
the internal layout of the code object changed
so overwriting code.co_code will never work because it'll just be a cached object instead of the real thing
but overwriting frame.f_code may work
I love it!!!
jeez, i thought it was just some owo esolang until i looked closer
well done
in unrelated news, pger spotted in the wild
Hey, how could I pass a class to a function in python? Something like this
def accept_classes(first_class : class, second_class : class):
pass
its just type
Nvm
Yes
Okay, but I see python doesn't force types. It's just for decoration right?
python doesnt at runtime but tools do
you can always enforce it yourself in simple cases by just doing if not isinstance(first_class, type): raise TypeError()
ok Thanks
I haven't been in the community in a long time but I still have a birb lol
i added labels too
man i thought stack was really the evaluator stack
I wish something like that was possible
oh god
it's 3.11 though
3.10 and 3.12 are vastly different
so the stack can be found in the frame object?
I don't think that's in 3.10 but I'll investigate in a bit
or probably just figure out 3.11 stuff already
it's really damn hard to figure out how to get the evaluator stack right
even up to now i still have some edge cases i haven't fixed
single line while loop?
Include/cpython/frameobject.h line 49
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */```
probably?
well not in 3.10
but in 3.11 that's possible since the thing with the stack is a pointer
now it is
it's actually valid syntax, @ is the matrix multiply operator
oh DAMn
haiii <3 is just < 3 (smaller than 3)
how do you use @
you can overload it on classes
or use fishhook
to use it on builtins
some linear algebra thing https://en.wikipedia.org/wiki/Matrix_multiplication
I don't do that though
I rewrite the bytecode of whatever script imports that module
whats the dunder for it
__matmul__ i think
how do o, w and all the other things not get called out for nameerror
you aren't importing those names, you're just importing a file
yep
they're probably added to __main__
import __main__
__main__.somevar = somevalue
that would be inside the imported module
or something similar
no
i rewrite the compiled code of whatever imports the thing
ah
that's a more fun way to do it
that sounds annoying
the code for it is a little messy but it basically does this:
ยท get the outer frame, then get the previous frames until it's outside importlib
ยท check for the header (otherwise i crash your python interpreter immediately)
ยท create a new bytearray
ยท repeat until the entire bytecode is read:
ยท if any of the custom instructions match, append the generated code into the array (e.g. it checks for LOAD_NAME o, LOAD_NAME w, BINARY_XOR, ...)
ยท otherwise just append the current instruction as-is (so you can still write normal code in the middle of that mess)
ยท overwrite the frame's code's co_code with our own bytearray
and then when the script returns execution, there are no errors
by overwriting i mean literally just copying the entire bytes object in memory into the frame's (not just the actual content)
what is the best place to compare the bytecode differences between python versions? Not only talking about new opcodes but also different compiler behaviour
no idea i just reverse-engineered things
reading the source code helps sometimes but since I'm not that familiar with the codebase it's a bit hard to find things
when I get home I'm going to check that out
yeah I was hoping for some written documentation
yea and also doesn't clearly state which opcodes are different from before, you'd have to differentiate them to find the changes
maybe that's not such a bad solution
there's also misdocumented things so you might want to double-check (e.g. description for YIELD_VALUE says it only pops a value, but it actually pops one and pushes another (which if you don't know you'll mess up your stack))
2 questions
- why enforce the header (just for fun I assume)?
- what stops them from evading the header if they want to?
makes sense
if you don't include the header
hmm
I see
one thing you might want to do is not print the exception?
just, print "ure a meanie, explod" and then segfault?
since then it'll only print "segmentation fault, core dumped", which gives them a lot less clues as to what happened
segfaults are fun
basically just
the IOT instruction (core dumped) happens on the second line, the third one is never reached
but it's there
looks like this is exactly what I need
ljust and rjust
there's also zfill, which is just rjust except character is 0 and not a kwarg
the output of bin is already str, btw
!e
def binary(LEN, VAL): return bin(VAL)[2:].zfill(LEN)
print(binary(4, 7))```
Great, thanks!
alternatively, ```py
binary=lambda l,v:f"{v:0>{l}b}"
def _bin(val, LEN): return f'{val:0>{LEN}b}'
def _list(LEN):
pos = []
for LEN in list(range(1, LEN+1)):
v = 2**LEN-1
for VAL in range(0, v+1):
pos.append(_bin(VAL, LEN))
return pos ```
Just curious how you could shorten _list().
hm?
you can also zfill to the nearest byte (multiple of 8)
binary=lambda n:bin(n)[2:].zfill((len(bin(n)[2:])//8+1)*8)
actually that one is wrong slightly
a number with 8 bits will get rounded to 2 bytes
I think this fixes it
binary=lambda n:bin(n)[2:].zfill(((len(bin(n)[2:])-1)//8+1)*8)
something like ```py
def _bin(val, LEN): return f'{val:0>{LEN}b}'
def _list(i): return[_bin(u,-~i)for i in range(i)for u in range(2**-~i)]
it works for 0 too
~ is the best way to write negative numbers
imo
~9 is shorter than -10, saves a char
etc
Why don't computers count like this?
0
1
00
01
10
11
000
001
010
011
100
101
110
111
0000
because then how do you tell if 00000000 is 00000 and then 000 or if it's 0000 and 0000
for example
By counting the length of the array.
so you would have them be null terminated arrays?
0 is 0
but
00 is 2
000 is 6
ok, so how do you store 2 numbers next to each other in memory?
if the length is variable, you need to be very careful about how you manage it
Hm, maybe set a certain sequence as seperator.
Yes I know that could lead to confusion.
so, analogous to a null terminated array in c?
well its binary so how are you going to separate it ? you can't use one 0 or one 1
let's say your number is 01101011
then you'd have a sequence something like 01001, for example, to say "that number is done"
is that right?
Numbers next to each other must not add up to the seperator.
E.g. if Seperator = 000000
Strings a + b must not add up to a:000000:b.
This can be prevented if all stings end with 1.
that removes half of all possible representations in binary
0110101110000001101110..
which is more than having one extra possibility per length of bits gains
also, to check for this would be expensive, computation-wise rather than just always reading 8 bits (or whatever the size of the data type is) at a time
I just wrote a simple to understand solution. I know its not optimal in this case.
that's ok
the problem here is that it doesn't gain very many representations (makes a length of binary represent (2**n)+n instead of 2**n possibilities)
Currently information is stored in bytes. Always 8 bits.
if storage is a problem, you can bitpack or use bitfields (which is basically just syntactic sugar for bitpacking)
it's faster for the processor to always read a fixed amount of bytes rather than worrying about variant lengths
Well you could also try to store exactly a number that is represented in 8 bits.
That would also solve the issue.
Only issue is that the last 8 bits have no meaning.
bitpacking!
let's say you have some booleans (True or False)
normally, each will take up 1 byte
but, to save space, you can put them into the same byte, then access them with &
for example, if I have 5 booleans
I can put each one into the byte like this 01011
then pad the extra 0s in
to get 00001011
then to access boolean 3, for example, I can do 00001011&00000100
bitfields are basically syntactic sugar to do this for you in c/c++
you can do
struct bools {
bool unpacked = false; // takes 1 byte
bool packed :1 = true; // takes 1 bit
bool packed2 :1 = false; // also takes 1 bit
bool packed3 :14 = true; // takes 14 bits (more than a byte)
};
then at the end, 0s are padded to make it a multiple of 8
(this is ignoring compiler optimizations such as reordering the struct or bitpacking for you)
basically, there are already some cool ways to make data not take up as much space
so that space isn't wasted
(it is really annoying that a bool takes 1 byte though, I totally agree)
however, because this is #esoteric-python and not about c/c++, I'm going to go try to implement your idea in python
where in 0b int literals, 00 is 2, etc
Interesting, thank you. ๐
I'll start once I get home
:)
keep in mind that while I'm saying it wouldn't work, that's only after a surface level of thought about it and considering only the existing technology that has been designed to work with fixed length bytes
with enough time to optimize, the idea could be viable
either way, it's a really fun thought experiment
thank you for suggesting this
now, I'm gonna go read the cpython source for parsing ints
byee
See you. ๐
@solar tulip look into Huffman encoding
using variable width bitstrings to represent specific values is very much what that's about
thinking of what else I could implement into my abomination now
inline lisp?
no idea how that would work
hm that would need to manipulate the parser so probably not
ye, everything needs to be valid syntax
does your github repo have a list of features?
not yet
there's some examples there though
well I guess documenting stuff now is a good idea
I'll do that
yeah, Huffman encoding is cool
Thanks, very helpful!
could you implement unions, from C/C++, and have multiple objects in the same memory?
I'm thinking of maybe adding other objects or functions into the frame's locals to mess with memory
the stack thing is done like that
frame.f_locals["STACK"] = Stack(frame)
altering locals at runtime is hard, it would be easier to make a global STACK variable that just gets the frame on access ie: ```py
def getitem(self, idx):
frame = sys._getframe(1)
do stuff to get stack item
but that already works perfectly
not sure what you mean
this won't work on every frame? or at least it shouldn't?
ohh true I still haven't done anything about inner frames in functions
!e ```py
import sys
def make_loc(name, val):
frame = sys._getframe(1)
frame.f_locals[name] = val
def foo():
make_loc('a', 1)
print(locals())
print(a)
foo()```
I mean I would probably have to apply the same patches to them so just assigning to locals is still fine
@rugged sparrow :x: Your 3.11 eval job has completed with return code 1.
001 | {'a': 1}
002 | Traceback (most recent call last):
003 | File "<string>", line 12, in <module>
004 | File "<string>", line 10, in foo
005 | NameError: name 'a' is not defined
wait wtf
locals() is returning the dict created by frame.f_locals access (despite that not being live locals)
assigning to locals prob wont work unless you recompile/alter the code object so it knows about the STACK local var and makes space for it
I'm overwriting frame.f_code.co_code entirely
and for functions the presence of STACK inside the code already pushes it to co_names
wait, duh, the frame objects for the functions don't exist until they're running
I see what you meant now, sorry lol
Hi.
[pos.append(0) for _ in range(LEN-len(pos))]```
Is there a better way to do this?
if by better you mean shorter and more unreadable
pos.extend(bytes(LEN-len(pos)))
Why bytes?
because bytes(x) when x is an integer creates a bytes object with that length
and initialised to all zeroes
Ah interesting.
Wait no way. I'll try.
Thanks a lot!
you forgot about +=
my first attempt actually was ```py
[(pos:=pos+[0]) for _ in range(LEN-len(pos))]
and i forgot about that afterwards lol
!e import sys print(sys.version_info)
@vague cairn :white_check_mark: Your 3.10 eval job has completed with return code 0.
sys.version_info(major=3, minor=10, micro=6, releaselevel='final', serial=0)
!e ```py
import sys
def make_loc(name, val):
frame = sys._getframe(1)
frame.f_locals[name] = val
def foo():
make_loc('a', 1)
print(locals())
print(a)
return
a=0
foo()
@vague cairn :x: Your 3.11 eval job has completed with return code 1.
001 | {}
002 | Traceback (most recent call last):
003 | File "<string>", line 14, in <module>
004 | File "<string>", line 10, in foo
005 | UnboundLocalError: cannot access local variable 'a' where it is not associated with a value
!e ```py
import sys
def make_loc(name, val):
frame = sys._getframe(1)
frame.f_locals[name] = val
def foo():
make_loc('a', 1)
print(locals())
print(a)
foo()```
@vague cairn :x: Your 3.10 eval job has completed with return code 1.
001 | {'a': 1}
002 | Traceback (most recent call last):
003 | File "<string>", line 12, in <module>
004 | File "<string>", line 10, in foo
005 | NameError: name 'a' is not defined
Ok, that's even weirder than I thought, ok.
ok so im stupid
using that method lets you have a maximum value of 2(2**n)-3, not (2**n)+n
use PyFrame_LocalsToFast
!e ```py
import sys
import ctypes
ltf = ctypes.pythonapi.PyFrame_LocalsToFast
ltf.argtypes = [ctypes.py_object, ctypes.c_int]
def make_loc(name, val):
frame = sys._getframe(1)
frame.f_locals[name] = val
ltf(ctypes.py_object(frame), 0)
def foo():
a: None # type hint so it's a varname
make_loc('a', 1)
print(locals())
print(a)
foo()
@quartz wave :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | {'a': 1}
002 | 1
Yeah, we discussed that last week, I was just shocked that having no local variables made a difference how .f_locals and locals() behave...
if it's not a local variable it's a global variable (without using global/nonlocal)
that's basically how python works
Right, I've known how scoping is intended to be used since 2.7, I was talking about how the differences in foo() above changed the behavior of the various introspection mechanisms.
i don't get what you just said but ok
guys is better use recursion or loop in big programs?
I would use loops for big programs since recursion would be very expensive when it comes to more stuff
It's also easier to mess up recursion than it is to mess up loops imo
recursion which is easier to read in some cases and if you don't nest too much calls into the call stack
loop if either there could be too much calls into the call stack or it's much more readable
an unconditional benefit of loops is that they have less overhead than recursion when done right
yes
is there a way to make a class subscriptable without inheritance? im trying to change the bases but somehow it still remembers it's a type ๐ฆ
__class_getitem__?
Can you create object, such that: sys.getrefcount(x) == x ?
class X:
def __eq__(self, other):
return True
x = X()
>>> from sys import getrefcount as rc
>>> n = 300
>>> a = (-rc(n) + n) * [n]
>>> # a = [n] * (n - rc(n) + 2) # also works
>>> print(rc(n) == n)
True
>>> print(n == rc(n) - 1)
True
Is there anyway I could make this more compact?
def ntype(x):
(x:=str(x));(stotal:=0);(astotal:=0);(_:=__import__('math').factorial);
for n in x:stotal+=_(int(n))
if stotal==int(x):return(True, "Strong")
for n in x:astotal+=int(n)**3
if astotal==int(x):return(True, "Armstrong")
if astotal!=int(x) and stotal!=int(x):return("Integer")
>>> import sys
>>> obj = __build_class__(lambda:locals().update(__eq__=lambda*_:True),":trolleybus:")()
>>> sys.getrefcount(obj) == obj
True
you can also use metaclasses :p
How do you turn radian format to degree form without radian formula
It keeps meaning my calculations for my projectile parabola
ntype=lambda x:(s:=str(x),t:=sum(map(__import__("math").factorial,map(int,s))),a:=(None,(1>0,"Strong"))[t==int(s)],T:=sum(int(d)**3 for d in s),b:=(a,(1>0,"Armstrong"))[T==int(s)],c:=(b,"Integer")[int(s)not in(T,t)],(a or b)or c)[-1]
you can use the math module
math.degrees converts from radians to degrees
https://docs.python.org/3/library/math.html#angular-conversion
whoops already answered in a help channel
Um
I tried that
But its making it different
Um
what are you trying to do?
๐
ntype=lambda x:sum(__import__("math").factorial(int(n))for n in str(x))==x and(True,"Strong")or sum(int(n)**3 for n in str(x))==x and(True,"Armstrong")or"Integer"
is there a way to access the variables in the
__main__```
namespace from a module?
I want to loop using
```py
from sys import modules
del modules['{filename}']
import __main__
but I can't seem to pass variables like that
it basically just returns itself but in a module format
yea but it runs the file to make it happen
it doesn't need to do that i'm pretty sure
just retrieve the namespace and the name and put it in a module
print('a')
from sys import modules
try:
del modules['fiboBadNoParan2']
except:
pass
import fiboBadNoParan2
assuming the file fiboBadNoParan2 this prints a untill you reach the reacurtion limit
let's say I want it to print 1,2,3,4,5,6...
im kinda stuck
what id want to do is make a combined "global" scope for all my imports but I can't find a way to access values from a function that is importing a module
try:
import sys
a = getattr(sys, 'a', 0)
b = getattr(sys, 'b', 1)
a, b = b, a + b
try:
del sys.modules['_']
except KeyError:
pass
print(a)
sys.a, sys.b = a, b
import _
except:
pass
@simple sphinx
save it into _.py
put it into try-except
try:
import sys
try:
a, b = sys.a, sys.b
except AttributeError:
a, b = 0, 1
a, b = b, a + b
try:
del sys.modules['_']
except KeyError:
pass
print(a)
sys.a, sys.b = a, b
import _
except:
pass
outermost try-except is not requred, but it silences some weird errors
nvm, this also works:
import sys
try:
a, b = sys.a, sys.b
except AttributeError:
a, b = 0, 1
a, b = b, a + b
try:
del sys.modules['_']
except KeyError:
pass
print(a)
sys.a, sys.b = a, b
try:
import _
except:
pass
yes
this is like the main part for the third option I thought about
this is so clean... my code looks like a trainwreck lol
your file name is solution btw
from functools import lru_cache
@lru_cache
def fibo(n):
if n in {0, 1}:
return n
return fibo(n - 2) + fibo(n - 1)
ah
didnt work, because ( on last line
yea the question is about no loops and no parentheses, I theory crafted using imports to save the result in a variable and return it
but I couldn't write it
there are simpler solutions if you just want to 'pass it'
whats wrong?
i think it is good to have only one (
from functools import lru_cache
@type.__call__
class fibo:
@lru_cache
def fibo(self, n):
if n in {0, 1}:
return n
return self[n - 2] + self[n - 1]
__getitem__ = __call__ = fibo
__class_getitem__ = object.__init__
the ( is only for the line
def fibo(
so that people won't have to make it a lambda, it won't let you put it inside a scope
mostly a checking limitation on my part as I don't want to write a lexer to check exactly if what someone is doing is ok like you or not
from functools import lru_cache
@lru_cache
def fibo(self, n):
if n in {0, 1}:
return n
return self[n - 2] + self[n - 1]
@type.__call__
class fibo:
__getitem__ = __call__ = fibo
__class_getitem__ = object.__init__
it works
from functools import lru_cache
@lru_cache
@lambda x: lambda self, n: n if n in {0, 1} else self[n - 2] + self[n - 1]
class fibo:
...
@type.__call__
class fibo:
__getitem__ = __call__ = fibo
__class_getitem__ = object.__init__
``` no `(` nor `def ...` at all
yea, there are a few solutions already if you want to look
you can also do it without "class"
but I didn't want to start cutting stuff to the minimum
what is py @type.__call__ Why type
no +,[{*/| can also be done
this one is super pretty can you submit it?
no ([{+*/| def class, right?
done
but I wanted to leave more then 3 solutions
ty
how to call it? you will need (, right? like fib(6)
@simple sphinx my implementation of brainfuck interpreter without : symbol
yes
but im not calling it, it is called by testing system, so i dont care about it
that does not violate the ( ?
lol, same energy
how to turn this attempt to working solution? it has no public fibo var, so it doesnt work. And i dont know how to implement it with callable
what is py @type.__call__ Why type, never seen this.
im working on it myself right now, but the idea is that you can declare a function without it running, and only run the recursion if you are imported from fibo
short way of doing ```py
class fibo:
...
fibo = fibo()
google does not tell me what type is.
it's the base class/type for objects
thanks
!e print(type(1))
@fleet bridge :white_check_mark: Your 3.11 eval job has completed with return code 0.
<class 'int'>
!e print(type)
@fleet bridge :white_check_mark: Your 3.11 eval job has completed with return code 0.
<class 'type'>
I guess type is a very bad name. Should had a better name.
it is good name, because it is base class for all classes, and "class" is very similar to "type"
look at the C "static" name lol
it can basically mean anything you want kek
look at any part of C++ ๐
<<
X Y(Z);
lol
even base is better. oh well.
no base is something else
no, base is not a built-in or keyword
im wrong, type is class of all classes
object is base class for all classes
type is a base type of all classes
object is a base type of all objects
now it would be very hard to explain what base actually refers to here
that is why I think it is a bad name. anyway.
"but they're both bases, so why does base only refer to one of them here?"
class a:
pass
class b(a):
pass
print(b.__base__)
there is no better name
"base" is weird
it's just object
class can have base. What does it mean for base of object. Very confusing concepts. Any way.
yes
very confusing
that's why base isn't a better name
def fibo(n):
a,m = 2<<n,n+1
t,z = 1,a*a-a-1
if m&1: t=t*a%z
if m&2: t=t*a**2%z
if m&4: t=t*a**4%z
if m&8: t=t*a**8%z
if m&16: t=t*a**16%z
if m&32: t=t*a**32%z
if m&64: t=t*a**64%z
b,m = a**128%z, m//128
if m&1: t=t*b%z
if m&2: t=t*b**2%z
if m&4: t=t*b**4%z
if m&8: t=t*b**8%z
if m&16: t=t*b**16%z
if m&32: t=t*b**32%z
if m&64: t=t*b**64%z
return t%a
``` bruh, this guy implemented floating point number exponentiation in integer arithmetic
type is the next best tradeoff for shortness and clearness between class (a keyword) and base_class (a little long)
if object cannot have base, then base is a good name. I still don't know what is base of obj.
base of object is object
base of type is also object
but type of object is type
and type of type is type
yea he people warned me he will code golf it somehow
too good to remove imo
any python doc on this? thanks.
Meant to reply to this
or code. Code is fine too.
!d type
class type(object, /)``````py
class type(name, bases, dict, /, **kwds)```
With one argument, return the type of an *object*. The return value is a type object and generally the same object as returned by [`object.__class__`](https://docs.python.org/3/library/stdtypes.html#instance.__class__ "instance.__class__").
The [`isinstance()`](https://docs.python.org/3/library/functions.html#isinstance "isinstance") built-in function is recommended for testing the type of an object, because it takes subclasses into account.
I still can't seem to write the import solution T_T want to join forces?
I have an old solution that assumes a global context
but I can't wrap my mind around the locality of the data
>>> isinstance(object, object)
True
>>> isinstance(object, type)
True
>>> isinstance(type, object)
True
>>> isinstance(type, type)
True
>>>
>>> issubclass(object, object)
True
>>> issubclass(object, type)
False
>>> issubclass(type, object)
True
>>> issubclass(type, type)
True
I know this one. But I dont' know how get all the conbination mentioned above by @quartz wave
im going to figure it out myself
!d code
Source code: Lib/code.py
The code module provides facilities to implement read-eval-print loops in Python. Two classes and convenience functions are included which can be used to build applications which provide an interactive interpreter prompt.
there's also the code type
Thanks. Have to think about it.
so it's already taken
ok. this is a module, not a built-in.
built-in module
could be. I need to import first.
Python really uses the same name for too many things ๐
are you sure you submited the solutions? you need to attempt and then press submit. I don't see them
!d types.CodeType
class types.CodeType(**kwargs)```
The type for code objects such as returned by [`compile()`](https://docs.python.org/3/library/functions.html#compile "compile").
Raises an [auditing event](https://docs.python.org/3/library/sys.html#auditing) `code.__new__` with arguments `code`, `filename`, `name`, `argcount`, `posonlyargcount`, `kwonlyargcount`, `nlocals`, `stacksize`, `flags`.
Note that the audited arguments may not match the names or positions required by the initializer. The audit event only occurs for direct instantiation of code objects, and is not raised for normal compilation.
smh that isn't the funny docstring
hmm, wait
!eval ```py
print((lambda:0/0).code.doc)
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Create a code object. Not for the faint of heart.
i dont know what im doing wrong
after you press attempt the button goes green to submit
you need to press it again
maybe it wants you to have an account now that I think about it, not sure
Why did you choose such a cursed lambda ๐ 0/0
sometimes you need to scare the interpreter a bit, just so he knows who's who if ya get what I mean
true, usually reduces the amount of segfaults I get
I think I broke codewars. Still a fun kata though
don't think it like sys.settrace jumps
from functools import lru_cache
@type.__call__
class fibo:
@lru_cache
def __getitem__(self, item):
item if item in {0, 1} else self[item - 2] + self[item - 1]
does that work?
or does it have to be a function
yes, it should be callable like fibo(n)
aw
Failed: ?
oh, does it just have a lot of tests and thus requires a fast impl?
probably some library that ships with fib numbers
lmao, still too slow
i passed all tests but the one that disabled parentheses on line 1
this.. is an interesting question
exec("fibo=lambda n,c={0:0,1:1}:c[n] if n in c else c.setdefault\x28n,fibo\x28n-2\x29+fibo\x28n-1\x29\x29")
this is my code
i think this works, since now its callable?
from functools import lru_cache
@type.__call__
class fibo:
@lru_cache
def __call__(n):
return self[n]
__getitem__ = lambda item: item if item in {0, 1} else self[item - 2] + self[item - 1]
no, because you are not allowed to use (
it said you are allowed to use one
you can use it only in line def fibo(* (no spaces at beginning)
oh
im getting 1000-1360 passed tests on the same solution
i think this works
from functools import lru_cache
@type.__call__
class f:
__getitem__ = lambda item: item if item in {0, 1} else self[item - 2] + self[item - 1]
@lru_cache
def fibo(n):
return f[n]
i think i got the cache onto the intermediate ones now
from functools import lru_cache
@lru_cache
def fibo(self, n):
return n if n in {0, 1} else self[n - 2] + self[n - 1]
@type.__call__
class f:
__getitem__ = fibo
__call__ = fibo
fibo = f
n instead of item?
it can be used like fibo(someint)
the intermediate results should be cached
only 1 paren, and its used like def fibo(
hi im back
other than that looks good
it is very similar to my solution
copied it rom the earlier __getitem__ definition lol
you can also just use the base cache, the runtime requirements are very forgiving
i could construct my own cache using a dict and a lambda...
it has fibonacci implemented in it
ok
but doesn't it need calling
i stopped paying attention to what everyone else was doing after this one ๐
was scrolling through message history, saw this, and my brain went: "well, if no parens are allowed, why not overload the dunder for brackets, since brackets and parens are different" and i went off doing that for like 15 minutes
yea but
from gmpy2 import fib as fibo
is not in the spirit of the challenge
codewars has gmpy2 preinstalled?
yea
hmmm
I sort of disabled it but you can actually still use it if you really want to
@simple sphinx how much tests are there? i passed 1360 tests
about 1500, ill prob lower it to 1000
*it was 2000, ill lower it to 1000
not really meant to be a performance question
i cant pass more than 1400 tests with my import-based solution
try to reload the page, I changed some stuff about testing
removed some repeated tests
I only wrote it yesterday so it's still a bit wonky
submitted
from sys import modules as m
import builtins as b
def fibo(n):
b.n = n
del m['solution']
import solution
return fibos[n]
try:
fibos
except:
b.fibos = {-2: -1, -1: 1}
else:
n = n
try:
fibos[n - 1]
except:
b.n = n - 1
del m['solution']
import solution
fibos[n] = fibos[n - 2] + fibos[n - 1]
nice lol
i love and hate it
I wrote the kata because I originally had fun writing this thing
and this
so import is the next logical step
Thatโs terrifying
kinda cursed to have 2
in the same file ngl
__class_getitem__ = object.__init__ is useless here, it works without this line
why is ( disabled when i do ```py
exec("aldokwaokosdkwa")
no ( are allowed in the kata
this is just a thing I wrote
not a solution
I give one ( specifically in the line
def fibo(```
and only on the start of the line
for convenience
n = n is significant for this solution ๐
yea, recursion over files are always funny
import sys
cache = {0:0, 1:1, 2: 1}
def fibo(n, fr=None, ev=None, _=None):
global nn
if fr is not None:
if fr.f_code == fibo.__code__ and fr.f_lineno == 25:
fr.f_lineno = 15
return n
return n if fr.f_code == fibo.__code__ else None
if n in cache:
return cache[n]
queue = [None]*n + [n]
i = n
pass
if n in cache: return cache[n]
top = queue[i]
if top in cache: queue[i]=None;i += 1
else:
half = top // 2
if half in cache and half + 1 in cache: cache[top] = cache[half] ** 2 + cache[half + 1] ** 2 if top % 2 else 2 * cache[half] * cache[half + 1] - cache[half] ** 2; queue[i]=None;i += 1
else:
if half not in cache: i -= 1; queue[i] = half
if half + 1 not in cache: i -= 1; queue[i] = half + 1
pass
@sys.settrace
class X:
__new__ = fibo
``` don't think this one will ever pass due to the runtime restriction, but it was still fun to make.

im not sure what im seeing but how many tests are you passing?
2k-ish
reload the page and try again
using effectively a debugger to jump for looping
only 1000 tests with the new version you will prob pass it
yeah, that works
even with the 1k the iterative solution is too slow funnily enough, you do actually have to use the smarter recursive formula
line tracing is sloooow
but here is one very iterative solution
https://www.codewars.com/kata/reviews/637d17f603109e00640a2eb8/groups/637e0934873eab00015eee6f
oops wrong one
ok now it's the right one
you know it's good because I import tkinter to calculate fibonacci numbers
Can you send the source code for the people without an account
import tkinter
#is this front end development?
tkinter.Widget.__class_getitem__ = chr
paran = tkinter.Widget[40]
arr = [0,1]
code = f"""
global arr
arr = [0,1]
{'f'}or i in range{paran}2,100000):
arr.append{paran}arr[i-1] + arr[i-2])
"""
tkinter.Widget.__class_getitem__ = exec
tkinter.Widget[code]
fibo = arr.__getitem__
that's the "intended" solution
but there are a few more ways
this is what I wrote as the "referance"
import functools
class a: pass
a.__class_getitem__ = lambda n: n if n<2 else b[n-1] + b[n-2]
@functools.cache
def fibo(n):
return a[n]
class b: pass
b.__class_getitem__ = fibo
oh wait I think I have a fun one
i broke it
fibo = print
d = dict
import gc
import builtins as b
import sys
@lambda x:x[0]
@gc.get_referents
@lambda x:object.__dict__
class d1:...
@lambda x:x[0]
@gc.get_referents
@lambda x:type.__dict__
class d2:...
@lambda x:x.__dict__
@lambda x:b
class d3:...
@d.clear
@lambda x:d3
class _:...
b.__build_class__ = fibo
@d.clear
@lambda x:d2
class _:...
@d.clear
@lambda x:d1
class _:...