#esoteric-python
1 messages ยท Page 87 of 1
so does zip doesnt it?
zip([1], my_generator_which_has_1000_elements)
!e py gen = (x for x in range(10)) print(*zip([1],gen)) print(*gen)
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | (1, 0)
002 | 1 2 3 4 5 6 7 8 9
damn
Implementing such zip would lead to an implementation of next
yea. i wonder how next could be implemented
no statements?
next = lambda i:[*(1/0for e in i)]
This shifts an iterator by one, but it obviously blows up
Implementing any of next, zip or list.append (or any mutation apart from qutables) would lead to the implementation of all three and possibly much more.
i dont know if they are possible with the current limitations
somehow implementing nonlocal or exception catching/silencing is in the same category
yea
because
mutable = lambda x=None:(lambda[nonlocal x] y: (x:=y), lambda[nonlocal x]: x)
setter, getter = mutable()
The only mutability mechanism that allows some sort of detection is exhausting an iterator and checking if it wasn't empty or if it was equal to someting.
Maybe lazy (head, lambda:tail)-lists can work as generators, but how do you make them mutable.
oh, wait, I have an idea
You can combine lazy lists with quantum mutables!
>>> qutable = lambda:(1for i in(1))
>>> observe = lambda q:[*q]==[1]
>>> a = qutable() # unobserved (U)
>>> observe(a) # unobserved (U) -> observed (O)
True
>>> observe(a) # O
False
>>> observe(a) # O
False
Then you can create a lazy (or greedy) linked list like this
The 'qutable' will be unobserved only when a given element hasn't been generated yet.
I don't know how that would work with lazy lists, but it's easy with greedy ones.
Basically, it allows you to remember the position in a list
im curious if we could find a way to unexhause the qutable
I don't think it's possible. But maybe it's possible to create mutability from the ground up using qutables and lazy lists (although I'll have to do it with greedy ones first).
its prob possible to remake mutablity
For example, you can recreate a natural number that can only be incremented.
and other extremely useless things!
like most of the things made here
absolutely
what if we allow non-dunder methods
so .append is allowed but .__next__ wouldnt be
that's too easy
fair
!e
Q = lambda:(1for i in[1])
obs = lambda q:[*q]==[1]
a = ("lorem", Q(),
("ipsum", Q(),
("dolor", Q(),
("sit", Q(),
("amet", Q(),
None
)))))
qnext = lambda qlist: (
None if qlist is None
else (lambda e, q, rest:
e if obs(q) else qnext(rest)
)(*qlist)
)
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | lorem
002 | ipsum
003 | dolor
004 | sit
005 | amet
006 | None
007 | None
Maybe it can be rewritten as a loop, but this will work for <1000 elements
thats clever
we have found The Quantum Loophole!
Now we need somehow to make it work with lazy lists
Maybe it's possible with default arguments
Like, it can be [q1] for the first element, then [q1, q2] for the second one and so on. Or something
f = lambda a:((d:={'a':a}),lambda a:d.__setitem__('a',a),lambda:d.__getitem__('a'))[1:]
``` if only
we need some setitem(l:list,i:int,o:object) primitive
otherwise its not possible for us to do much more
@formal sandal slight modification to the rule set. allow def func():
def next(i):
for o in i:
return o``` cause then we can do this
theres a difference between too easy and making a challenge possible
while would still be forbidden
Anyone here any good with pythonnet or IronPython?
wrong channel
this channel is more for strange uses of python/ weird coding/ abusing syntax
i guess
has anyone come up with a properly infinite generator yet?
(i.e. one that won't stop working past a certain multiple of the recursion limit)
depends on how much you like your memory lambda: (y:=[0], (x for x in y if not y.append(0)))[1]
Played around with graphs a bit, how does python allocate memory for it to have spikes like this with the above generator? https://paste.fuelrats.com/gesapijezi.txt
They might correspond to local variables leaving scope and being garbage collected.
Wouldn't that be a gradual rise and then a sudden dropoff?
Unless it allocates in advance.
CPython doesn't allocate in advance AFAIK
lambda: (y:=[0], (x for x in y if not y.append(0)))[1]
append
append isn't allowed :<
ah thought it was only dunders
is it possible then? Believe that only leaves recursion as we don't get normal usable loops
Yes.
I think we can allow changing the recursion limit.
But we can pretend that the stack is infinite!
that'll crash fairly quickly at the c level
a truly infinite one might not be possible but something like this is probably close enough py r=lambda l=500:((yield from x(l-1))for x in[lambda l:[0],r,r])if l else[1]
You can't yield in a generator expression, can you?
!e
r=lambda l=500:((yield from x(l-1))for x in[lambda l:[0],r,r])if l else[1]
@formal sandal :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | SyntaxError: 'yield' inside generator expression
...huh
in python 3.7 you can
but apparently not in python 3.8
although this does work in 3.8 py r=lambda l=500:((yield 0),(yield from r(l-1)),(yield from r(l-1)))if l else[1]
and given that the length of the list basically doubles(ish) every time you increase l by 1, by 500 you're dealing with about 2^500 which is 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376
which is probably too big to worry about
yield works in lambdas?
huh
Is this like the Ackermann function?
no, that's something completely different
oh, I got it
it's literally just recursively calling itself twice
yep
Have you seen the mutable finite generator implementation?
I've been thinking about infinite (or just lazy) generators.
Maybe the easiest way of implementing them is to ship each generator with a really long linked list (from my implementation) of qutables.
Like this
The 'next element' function can also take a boolean argument -- whether it is called the first time or not.
Otherwise, you won't be able to create generators that produce side-effects.
So the lazy part of a lazy list of natural numbers can be defined as:
_inat = lambda n=0:lambda first:(n, _inat(n+1)) + ()*bool(print(n) if first else 0)
Then you would have a special lazy list runtime that would accept a lazy list together with a greedy companion list.
Imagine a beginner opening this channel by accident...
(lambda f: f(f, 0))(lambda f: (
x := x + 1,
print(x),
f(f, x)
))```
do_while = lambda condition, callback: (
(lambda f: (
f(f)
))(lambda f: (
(
callback(),
f(f)
) if condition() else None
))
)
What's the first snippet supposed to do?
the first snippet is just an infinite counter that prints each value
0 then 1 then 2 etc
Doesn't look valid to me
it works when I try it
well there's one bug
(lambda f: f(f, 0))(lambda f, x: (
x := x + 1,
print(x),
f(f, x)
))
but then it works
that's better
and do_while uses a similar mechanism
but won't it just stop at the recursion llimit?
where it just recursively calls itself and its callback until the condition is false
and that's true
i don't see another way though
you could always increase the recursion limit
can't go over a few thousand
someone should make http://www.onelinerizer.com/ for python 3
Convert any Python 2 script into a single line. No newlines allowed. No semicolons, either. No silly file I/O tricks, or eval or exec. Just good, old-fashioned lambda.
question
how could i make take_while access the scope of the higher function like so
(lambda: (
do_while := (lambda condition, callback: (
(lambda f: (
f(f)
))(lambda f: (
(
callback(),
f(f)
) if condition() else None
))
)),
x := 1,
do_while(lambda: 5 > x, lambda: (
x := x + 1
))
))()
I don't think you can do that easily.
You can wrap the value in a list and then pass that list.
@hollow patrol that is for py2
i meant py3
if we want to implement all the builtins we can without redefining mutables and such, we need to figure out next and a setval primitive
alright
@rugged sparrow i made a do_while function above, but how can I edit higher variable scopes with lambdas like I tried to there
you cant cause lambdas cant bind nonlocal
should I make some sort of variable dictionary and use that?
But you can pass a list containing that value
thats why we need to figure out altering mutables
With current conditions, proper next and setval are probably impossible, but with built-in methods it's trivial.
next that works with generators properly
!e print(next(iter('abc')))
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
a
next calls __next__ on the arg by default
can also be given a second arg that is returned if the generator is exhaused
how does next not work properly with generators already?
our rules dont let us call dunders
just use next?
oh
if we could def then next is easy
i'm working on a py3 onelinerizer for python 3.8
Or if we could catch an exception somehow.
why aren't you allowing yourself to call dunders
catching an exception requires __import__ in py3.8
@hollow patrol Because that'd make everyting way easier
no builtins, including builtin dunders
send is a builtin
oh
and where's the builtin method in this ```py
import dis
dis.dis('(x for x in [1, 2, 3])')
1 0 LOAD_CONST 0 (<code object <genexpr> at 0x000002B9BA979240, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<genexpr>')
4 MAKE_FUNCTION 0
6 LOAD_CONST 2 ((1, 2, 3))
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE
Disassembly of <code object <genexpr> at 0x000002B9BA979240, file "<dis>", line 1>:
1 0 LOAD_FAST 0 (.0)
>> 2 FOR_ITER 10 (to 14)
4 STORE_FAST 1 (x)
6 LOAD_FAST 1 (x)
8 YIELD_VALUE
10 POP_TOP
12 JUMP_ABSOLUTE 2
>> 14 LOAD_CONST 0 (None)
16 RETURN_VALUE```
you guys are making this very hard on yourselves
thats the point lol
you're removing basically every useful method in Python
A builtin in this context is a name of an object or a method that is accessed directly and defined at startup. (True and such are keywords, not builtins)
not "basically every useful method", every method
every function and method is banned
excluding things we define ourself
alright
type = lambda o:o.__class__
type(type(()))('a',(),{})``` would this be allowed?
__class__ is a dunder
but we arent directly calling it
ah thats true
would something like lambda x: x.__class__.__name__ be allowed?
since it's not calling anything
that can be rewritten as x.__getattr__('__class__').__getattr__('__name__')
right?
That still feels like cheating, since it's a built-in attribute
What it's actually doing isn't important, since we're not calling it directly
well you can rewrite a call to include __call__ but that doesn't mean you're cheating by calling something
some of these issues would be solved if we allow def
def mutable():
x = None
def setter(y):
nonlocal x
x = y
return x
def getter():
return x
return (getter, setter)
cant you just x = y now?
and x = None
yes, my version would actually be illegal
we can create hacky class-like's now
are we still banning actual classes?
yes
def mutable():
x = None
sentinel = {"__sentinel__"}
def f(arg=sentinel):
nonlocal x
if arg is not sentinel:
x = arg
return x
return f
yes now they are
Actually, now mutability is too easy
right but now we can focus on actually writing challenging stuff
instead of being stuck on one hurdle
what things are there that we haven't done yet and want to do
def zip(a, b):
ia = (i for i in a)
ib = (i for i in b)
try:
while True:
yield (next(ia), next(ib))
except:
return
But it might have an off-by-one error
Maybe we could add some silly constraints, like 'no more than 5 vowels per function'
no more than 5 vowels per function
...what
zip takes any number of iterators
Yep
im not sure what it returns
it still returns a module
fromlist afaik only matters when you are importing from a package in a package
yea you're right
i guess i'll just translate
from MODULE import NAME1, NAME2
as
(
__mod := __IMPORT__('MODULE'),
NAME1 := __mod.NAME1,
NAME2 := __mod.NAME2
)
ye, that is simplest
how should I do from MODULE import *
you cannot dynamically create names in the local scope as far as I know without some really complicated hacks
the imports are only in the locals there
and that's true
i guess I'll deal with globals then
@hollow patrol you could __import__(mod).__dict__ and loop thru the items to do from mod import *
true
you still need to modify globals to create a string name, no?
i thought you were using a dict namespace
oh, i'm using :=
if you are using a dict, you may as well just .update
globals().update(__import__(mod).__dict__) cursed
i'm doing globals().update(vars(__import__('module')))
i would filter out dunder vars
alright
some modules define mod.__all__ with a list of imports used for * imports
i'll add that in later
return ast.Call(
func = ast.Attribute(
attr = 'update',
value = ast.Call(
func = ast.Name(
id = 'globals',
),
args = [],
keywords = []
)
),
args = [
],
keywords = []
)
that's what I'm at so far
i've used __all__ to iterate through namespaces too
how can I convert classes to type calls
with their bodies having logic
eg.
class x:
y = 3
if True:
z = 4
__build_class__ takes the body of the class compiled + a couple other args like the class name
yea
and that's easy since I already have code that converts bodies to expressions
like for loops and ifs to list comprehensions
and I can just put that in a lambda
how are you planning on handling try:except:finally
you can use a context decorator to emulate a try except
how can I do a while loop while maintaining variable context
like ```py
x = 0
while True:
x += 1
is there a py3 way of doing try/except as an expression? onelinerizer needs some deprecated contextlib functions
you use contextlib.ContextDecorator
@proper vault how?
(lambda f:type('',(__import__('contextlib').ContextDecorator,),dict(
__enter__ = lambda *_: None,
__exit__ = lambda s, ex, *_: ex and f() or 1))()(f)())(lambda: print(int(input())*2))
```something like this
you essentially use it to run a context manager inline
x = (
lambda f: type(
'',
(__import__('contextlib').ContextDecorator,),
dict(
__enter__ = lambda *_: None,
__exit__ = lambda s, ex, *_: ex and f() or 1
)
)
()
(f)
()
)
(lambda: print(int(input())*2))``` what is the `__exit__` function doing, and why do you call they type 3 times? @proper vault
are you familiar with context managers?
) #close the type declaration
() #create an instance of the ContextDecorator subclass
(f) #apply the decorator
() #call the decorated function
oh i see
i know how context managers work, im not sure why you do ex and f() or 1 though
well ex is None if there was no exception, so the and short circuits and stops the function
if there was an exception, f() get evaluated, and therefore called. or 1 is just to make sure True is returned from the context manager, as that means the exception was handled
it could be rewritten (f() or True) if ex is not None else None
okay, so f is the hander function (and the body of try can go in __enter__ right?)
why do you have to return 1?
because if you return false from a context manager, it raises the exception. Body of the try is the f. What I wrote is essentially
def f():
print(int(input())*2)
try:
f()
except:
f()
the body of the try is the decorated function
the body of except/finally (depending on how you write the exit function) is in __exit__. __enter__ is just a noop here
ah ok. can i have a callback that is run if f raises an exception?
oh right, i just run something else in __exit__
ye
and f is the wrapped function
ye, I also used it in the except body here, which on second thought made it a lot loss clear, my apologies
I have an idea
Instead of
do_while(lambda: True, lambda: (
))
I can do
(
x := 0,
[
(x := x + 1) for _ in do_while(lambda: True)
]
)```
How do you catch and raise errors in lambdas?
#esoteric-python message just answered it
(()for()in()).throw(ValueError) IIRC
ah, thanks
I have a question
with __build_class__, does the function return a dict
the first argument for the function
does the func return a dict
or are its locals used
I'm a bit disappointed that I can't do i[0] := 1 or i.x := 1
@hollow patrol the first arg of build class returns None
__build_class__ returns the class object
the lambda passed in needs a load_name op with the arg of the class name
and use setattrs
i know
my question is how does it get the lambda body
does the lambda return a dict
x = (
lambda f: type(
'',
(__import__('contextlib').ContextDecorator,),
dict(
__enter__ = lambda *_: None,
__exit__ = lambda s, ex, *_: ex and f() or 1
)
)
()
(f)
()
)
(lambda: print(int(input())*2))
hmm
trying to see how to use that for try except
how would I do a finally?
also how would I maintain scope?
how can I set variables in the inner function that apply to the outer
how can you do global, nonlocal and local?
Finally you do the same way, just without checking for truthy ex
why is this channel named esoteric python?
I plan on being more active on this server soon...just finishing up a network+ certification
It's about Python, hence the word Python, but it's unconventional, hence the 'esoteric'.
Basically the goal of this channel is to make GvR have an heart attack the quickest possible if he come here
so we try to use the most anti-pattern possible to achieve this goal
A lot of it is lipgrams, like "no parentheses" or "only lambdas".
Or no line breaks
or single expression only
Or we try to shorten code disgustingly much.
or we make 2 + 2 == 5
apart from modifying bytecode, I don't see a way
I feel like at this point this is a valid solution haha
maybe you could pass the locals() dict into the inner function
oh wait, you cant change things in it either
!e
exec(__import__("gzip").decompress(__import__("base64").b85decode(b'ABzY8{o%`A0{`7sO>dkq5WVv&9C|S+Lg{tY<WMz-s%llKxvf?fVNGH!UoxO%yW+oh#(WvuY?COb`oOO7_<7#E@eE#)#dS^CZGO+QOw^Bj|0S;Z#v?FTQWkY1+oUNaE8?7Q2uwZC+w+w0c?ZR{kic6}h(?q}(C_cDHRvC_iD`4J_+Wqou^5xQl8n)sXQ{S^L-MAT1xbDVz!MrqmVXzr3(0Br1LlG6xqYD~=aA&!p0c|(eAZmD&Lr0ae_qe0l4bRIv%;h!n~lljrl&no8jv(!2Wj&7z;(nmeLfH*H?h9Z0>zjDxrewgGypD6-2@yG7YR=ud2$#Chh%)~rcM_xafo`{LB~I#m6L(BEiU%cQISI!Lm3=__gbM8#7boPpy-KX$L)U!nMn0B=UfVjkr<0GF}jGC!LAQT!JnouJR24`@QR(SHr9?IYUr3!C}N5pW8@?8Fa3}#{0FcA%0?H^=YcEF&aiE(?A_>I#`2+dP=@0(UQo44F0R$Yy1o|cSk#={0pD9G;nq8iaQNSfq?D2;4S^HdoEHsA$`+n!DSLuMOAX%%6ug5@cd+A(NXipUpEaHD+*GYHnEEGGTceZc0KZX!yLMt21Ui5T3HOEY0-_}2hSNWyTBL)L$VLekC3?&bsLy@6{BCp9=@+yBE}LVo=U5&@Gv!AWOAv?cMFOs%@0#?gacBk*OKr9^b2TcpFjIl$pJg$WI&`H>2Pd3~XYZaTlhJ`6VPWzhs;f*i)Q|jN`)RjIWDDDNu+P$O0$OI3_pfR`wcN4Y&K=gE(cSo_Mqj}rif#p~Dw)ExASw-_$tqYELxapk4Hf5MLWL-3pimLu#rA3!3BXqeEUN&Pm1@W*KsPdMz?{#AI~Muy#8VbHXtMPgi}#Jfs~Pimqa^wv&SvRa=h^r{xvW&*`LQol$_FFt=BHvGqY4CuM1dIfX`t#S{9GQMj7o}%u{jP(MWxeZF%iVvMQe*SESx$si<GJ7y`i5wd-)ss`1u~LU$UzmcJ%%Wb11H!QK4RRZ%zw{j*N3HTAg)q==@crX*$4H@Y?$eU^)i!eGC8q')))
class MaybeInt(SumType):
Just.of( int )
Nothing.of( () )
print(MaybeInt)
x = MaybeInt.Just(42)
print(f"{x=}, {type(x)=}, {MaybeInt.Just}")
assert isinstance(x, int) and isinstance(x, MaybeInt) and isinstance(x, MaybeInt.Just) and not isinstance(x, MaybeInt.Nothing)
n = MaybeInt.Nothing()
print(f"{n=}, {type(n)=}, {MaybeInt.Nothing}")
assert isinstance(n, tuple) and isinstance(n, MaybeInt) and isinstance(n, MaybeInt.Nothing) and not isinstance(n, MaybeInt.Just)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | MaybeInt {'Just': <:MaybeInt.Just :: <class 'int'>>, 'Nothing': <:MaybeInt.Nothing :: ()>}
002 | x=42, type(x)=embellished('MaybeInt.Just', <class 'int'>), MaybeInt.Just
003 | n=(), type(n)=embellished('MaybeInt.Nothing', ()), MaybeInt.Nothing
@marsh void That's the module with a function that creates a class, a metaclass and a metametaclass dynamically.
Here's the code (make_constructor at line 18) https://gist.github.com/decorator-factory/b2fd85ef8248c9230835461c1ec24597
(if you can't read base85)
Abstract art code haha
what does << do?
bit shift left
ye
0b001100 << 2 == \
0b110000
0b001100 >> 2 == \
0b000011
ye, you can override it to make it whatever you need, from monadic bind to function composition (as long as you use a custom class for the function)
!e
import sys
class FlushOnWrite:
def __init__(self, text):
self.text = text
def __ostream__(self, file):
file.write(self.text)
file.flush()
endl = FlushOnWrite("\n")
class OStream:
def __init__(self, file):
self.file = file
def __lshift__(self, obj):
if hasattr(obj, "__ostream__"):
obj.__ostream__(self.file)
else:
self.file.write(str(obj))
return self
cout = OStream(sys.stdout)
cout << "Your age is: " << 42 << "!" << endl;
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
Your age is: 42!
@real galleon
yeeass?
I even put a ; to make it clear that I'm doing something ugly.
anyone got a bytes alpha bet xd
ahh nvm i forgot i can just look up sommat like ascii characters
You can create a function rewriter that mutates the __code__ of a lambda.
[
(
#HANDLE EXCEPTION
)
for e in catch_errors(lambda: ())
]
and I don't want to do that
I'm trying to output ast
oh
I really have two choices
Either I have to switch my variables to use a dictionary system
or I have to find a way to do a try and catch with scope
just like I did with while
[ ( ... ) for _ in do_while(lambda: ...) ]
another option would be use globals only and mangle names depending on scope
You can apply the code rewriter anonymously and inline...fully?
that means the bytecode rewriter would have to be anonymous as well
yep
I'm not sure how to write bytecode though
@proper vault That will not work if you have several instances of a closured function
ah, good point
So maybe you'll have to assign some 'call id' to each function
Then maintain a scope for each call id
I want to differentiate between lambdas with separate scopes
And lambda sharing the parent scope
Basically, nonlocals in lambdas
Well, you can do that by defining some stuff in these scopes.
scope[1234] = {"__parent_scope__": 256, "__nonlocal__": ["x", "y"], "__global__": ["CONSTANT1"], "__local__": {...}}
You'll have to wrap everything in a scope manager function. That will produce lots of noise, though.
Why can't I only wrap functions that I need to manage scope in the function
(
f := lambda x, y: print(x, y), #f doesn't share scope
y := parent_scope(lambda a, b: print(a, b)), #y does share scope
)
where parent_scope modifies bytecode
Maybe you could somehow use inspect, but I'm not sure
and I think it's cheating to use exec('nonlocal x') inside of the lambdas
It shouldn't work
nonlocal is a declaration AFAIK
!e
import dis
def f():
x = 1
def g():
nonlocal x
return x
return g
G = f()
dis.dis(G)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | 6 0 LOAD_DEREF 0 (x)
002 | 2 RETURN_VALUE
!e
import dis
def g():
return x
dis.dis(g)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | 3 0 LOAD_GLOBAL 0 (x)
002 | 2 RETURN_VALUE
Yep, it's a totally different instruction.
But you could simply replace that in bytecode
hold on
how would I add in LOAD_DEREF to lambdas
how do you edit bytecode at all?
You use f.__code__.replace(co_code=...)
!e
import dis
def f():
x = 1
return x
dis.dis(f)
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 3 0 LOAD_CONST 1 (1)
002 | 2 STORE_FAST 0 (x)
003 |
004 | 4 4 LOAD_FAST 0 (x)
005 | 6 RETURN_VALUE
!e
def f():
x = 1
def g():
nonlocal x
return x
return g
def g():
return x
G = f()
print(f"{G.__code__.co_code=}")
print(f"{g.__code__.co_code=}")
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | G.__code__.co_code=b'\x88\x00S\x00'
002 | g.__code__.co_code=b't\x00S\x00'
!e
import dis
def f():
x = 1
def g():
nonlocal x
x = 1
return x
return g
G = f()
dis.dis(G)
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 6 0 LOAD_CONST 1 (1)
002 | 2 STORE_DEREF 0 (x)
003 |
004 | 7 4 LOAD_DEREF 0 (x)
005 | 6 RETURN_VALUE
!e
def f():
x = 1
def g():
nonlocal x
return x
return g
def g():
return x
G = f()
print([*map(hex, G.__code__.co_code)])
print([*map(hex, g.__code__.co_code)])
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | ['0x88', '0x0', '0x53', '0x0']
002 | ['0x74', '0x0', '0x53', '0x0']
Yes
You'll need to replace b'\x74\x00' with b'\x88\x00'
and what about b'\x53\x00' ?
not really always \x00
Any ideas on this (im just messing around rn)
yes, x just happend to be the variable 0
@real galleon you forgot an operator
!e
def f():
x = 1
def g():
nonlocal x
x = 2
return x
return g
def g():
x = 2
return x
G = f()
print([*map(hex, G.__code__.co_code)])
print([*map(hex, g.__code__.co_code)])
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | ['0x64', '0x1', '0x89', '0x0', '0x88', '0x0', '0x53', '0x0']
002 | ['0x64', '0x1', '0x7d', '0x0', '0x7c', '0x0', '0x53', '0x0']
between c and (a ^ a)
just seen aha thank you
so I replace x74 with x88
yep
!e
import dis
def g():
return x
g.__code__ = g.__code__.replace(co_code=g.__code__.co_code.replace(b'\x74\x00', b'\x88\x00'))
g()
@formal sandal :warning: Your eval job has completed with return code 139 (SIGSEGV).
[No output]
as intended
and what about the other one
my favourite error
I have to do LOAD_DEFER and STORE_DEFER right
any reasons why it wouldn't strip the numbers?
s=7;print(s);msg=' g 5 2 3 3 3 3 2 5 2 52 5 2 5\
522 232 o 21 3 67 52 837 623 498 7 od\
ay sir';msg=msg.strip('5');msg=msg.strip('2');msg=msg.strip('3');msg=msg.strip('1');msg=msg.strip('6');msg=msg.strip('7');msg=msg.strip('8');msg=msg.strip('9');msg=msg.strip('4');msg=msg.strip('52');msg=msg.strip('522');msg=msg.strip('232');msg=msg.strip('21');msg=msg.strip('67');msg=msg.strip('837');msg=msg.strip('623');msg=msg.strip('498');msg=msg.strip(' ');print(msg)
This channel isn't really for general help questions, check out #โ๏ฝhow-to-get-help
oki
@formal sandal you're only replacing x74 with x88
This channel is for stuff that will make you want to unsee it, so
does this account for both
Yes, STORE will have to be replaced as well manually
storing and loading
strip removes numbers from ends
alright
why not
g.__code__ = g.__code__.replace(co_code=g.__code__.co_code.replace(b'\x74', b'\x88'))
why do you need the \x00
sorry, I'm new to bytecode editing
alright
so then I could do something like
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88'))
return f
and then
If you want to take all variables from the parent scope, then... maybe
yep, all of them from the direct parent scope
this is equal to
parent_scope := (
lambda f: (
f.__setattr__(
"__code__",
f.__code__.replace(
co_code=f.__code__.co_code.replace(b"t", b"\x88")
),
),
f,
None,
)[(-1)]
)
right?
oh yep
except the return
But \x74 could potentially refer to something else, so you'll have to experiment
actually
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74\x00', b'\x88\x00'))
return f
parent_scope := (
lambda f: (
f.__setattr__(
"__code__",
f.__code__.replace(
co_code=f.__code__.co_code.replace(b"t\x00", b"\x88\x00")
),
),
f
)[(-1)]
)
so like this?
yes, and you'll also need to change the store
wait, those are separate instructions?
!e
import dis
def f():
x, y = 1, 2
def g():
nonlocal x, y
return x + y
return g
dis.dis(f())
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | 7 0 LOAD_DEREF 0 (x)
002 | 2 LOAD_DEREF 1 (y)
003 | 4 BINARY_ADD
004 | 6 RETURN_VALUE
!e
def f():
x, abc = 1, 2
def g():
nonlocal x, abc
return x + abc
return g
print(*map(hex, f().__code__.co_code))
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
0x88 0x1 0x88 0x0 0x17 0x0 0x53 0x0
Here, 0x88 is the instruction, and 0x1 and 0x0 are its arguments
so is that like the variable index?
yes
alright
so why not just replace all 0x88
with that account for any variables like that too
with the 88 index
88 corresponds to the LOAD_DEREF instruction, which fetches a variable from the local scope of the parent closure.
!e
def f():
x, abc = 1, 2
def g():
nonlocal x, abc
x, abc = 1
return g
print(*map(hex, f().__code__.co_code))
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
0x64 0x1 0x5c 0x2 0x89 0x1 0x89 0x0 0x64 0x0 0x53 0x0
!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!*
!e
import dis
def f():
x, abc = 1, 2
def g():
nonlocal x, abc
x, abc = 1
return g
dis.dis(f())
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
001 | 6 0 LOAD_CONST 1 (1)
002 | 2 UNPACK_SEQUENCE 2
003 | 4 STORE_DEREF 1 (x)
004 | 6 STORE_DEREF 0 (abc)
005 | 8 LOAD_CONST 0 (None)
006 | 10 RETURN_VALUE
!e
def f():
x, abc = 1, 2
def g():
nonlocal x, abc
x, abc = 1
return g
#print(*map(hex, f().__code__.co_code))
dis.dis(f)
@hollow patrol :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 9, in <module>
003 | NameError: name 'dis' is not defined
it must be UNPACK_SEQUENCE
oh hold on
maybe
!e
import dis
def f():
x, abc = 1, 2
def g():
nonlocal x, abc
x = abc
return g
dis.dis(f())
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 6 0 LOAD_DEREF 0 (abc)
002 | 2 STORE_DEREF 1 (x)
003 | 4 LOAD_CONST 0 (None)
004 | 6 RETURN_VALUE
!e
import dis
def f():
x, abc = 1, 2
def g():
nonlocal x, abc
x = abc
return g
print(*map(hex, f().__code__.co_code))
#dis.dis(f())
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
0x88 0x0 0x89 0x1 0x64 0x0 0x53 0x0
if you're interested, I made a reddit post about writing a function in bytecode using hax: https://www.reddit.com/r/Python/comments/gkzcoy/adding_tuples_a_bit_faster_by_writing_raw_bytecode/
LOAD_DEREF 0x88
LOAD_FAST 0x74
alright
so
LOAD_DEREF 0x88
LOAD_FAST 0x74
STORE_DEREF 0x89
I think STORE_FAST is 0x75
so
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
return f
!e
import dis
print(dis.opmap)
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
{'POP_TOP': 1, 'ROT_TWO': 2, 'ROT_THREE': 3, 'DUP_TOP': 4, 'DUP_TOP_TWO': 5, 'ROT_FOUR': 6, 'NOP': 9, 'UNARY_POSITIVE': 10, 'UNARY_NEGATIVE': 11, 'UNARY_NOT': 12, 'UNARY_INVERT': 15, 'BINARY_MATRIX_MULTIPLY': 16, 'INPLACE_MATRIX_MULTIPLY': 17, 'BINARY_POWER': 19, 'BINARY_MULTIPLY': 20, 'BINARY_MODULO': 22, 'BINARY_ADD': 23, 'BINARY_SUBTRACT': 24, 'BINARY_SUBSCR': 25, 'BINARY_FLOOR_DIVIDE': 26, 'BINARY_TRUE_DIVIDE': 27, 'INPLACE_FLOOR_DIVIDE': 28, 'INPLACE_TRUE_DIVIDE': 29, 'GET_AITER': 50, 'GET_ANEXT': 51, 'BEFORE_ASYNC_WITH': 52, 'BEGIN_FINALLY': 53, 'END_ASYNC_FOR': 54, 'INPLACE_ADD': 55, 'INPLACE_SUBTRACT': 56, 'INPLACE_MULTIPLY': 57, 'INPLACE_MODULO': 59, 'STORE_SUBSCR': 60, 'DELETE_SUBSCR': 61, 'BINARY_LSHIFT': 62, 'BINARY_RSHIFT': 63, 'BINARY_AND': 64, 'BINARY_XOR': 65, 'BINARY_OR': 66, 'INPLACE_POWER': 67, 'GET_ITER': 68, 'GET_YIELD_FROM_ITER': 69, 'PRINT_EXPR': 70, 'LOAD_BUILD_CLASS': 71, 'YIELD_FROM': 72, 'GET_AWAITABLE': 73, 'INPLACE_LSHIFT': 75, 'INPLACE_RSHIFT': 76, 'INPLAC
... (truncated - too long)
Full output: too long to upload
There's also https://www.reddit.com/r/Python/comments/gkzcoy/adding_tuples_a_bit_faster_by_writing_raw_bytecode/
!e
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
inner()
print(x)
@hollow patrol :warning: Your eval job has completed with return code 0.
[No output]
you didn't call outer
!e
!e
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
inner()
print(x)
outer()
@hollow patrol :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | !e
003 | ^
004 | SyntaxError: invalid syntax
!e
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
inner()
print(x)
outer()
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
3
what?
!e
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
inner()
print(x)
outer()
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
3
but I replaced the instructions?
!e
import dis
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
dis.dis(inner)
outer()
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 11 0 LOAD_CONST 1 (4)
002 | 2 STORE_FAST 0 (x)
003 | 4 LOAD_CONST 0 (None)
004 | 6 RETURN_VALUE
what is going on?
!e
import dis
def parent_scope(f):
print(dis.dis(f))
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
print(dis.dis(f))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
outer()
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 13 0 LOAD_CONST 1 (4)
002 | 2 STORE_FAST 0 (x)
003 | 4 LOAD_CONST 0 (None)
004 | 6 RETURN_VALUE
005 | None
006 | 13 0 LOAD_CONST 1 (4)
007 | 2 STORE_FAST 0 (x)
008 | 4 LOAD_CONST 0 (None)
009 | 6 RETURN_VALUE
010 | None
nothing changed
!e
import dis
def parent_scope(f):
print(dis.dis(f))
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
print(dis.dis(f))
return f
def outer():
x = 3
@parent_scope
def inner():
print(x)
outer()
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 13 0 LOAD_GLOBAL 0 (print)
002 | 2 LOAD_DEREF 0 (x)
003 | 4 CALL_FUNCTION 1
004 | 6 POP_TOP
005 | 8 LOAD_CONST 0 (None)
006 | 10 RETURN_VALUE
007 | None
008 | 13 0 LOAD_DEREF 0 (x)
009 | 2 LOAD_DEREF 0 (x)
010 | 4 CALL_FUNCTION 1
011 | 6 POP_TOP
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/resubutehi
wtf
hold on
nothing changed
except it switched to LOAD_DEREF?
import dis
def outer():
x = 3
@parent_scope
def inner():
nonlocal x
y = x
x = 3
outer()
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
return inner
dis.dis(outer())
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
return inner
dis.dis(outer())
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 7 0 LOAD_DEREF 0 (x)
002 | 2 STORE_FAST 0 (y)
003 |
004 | 8 4 LOAD_CONST 1 (3)
005 | 6 STORE_DEREF 0 (x)
006 | 8 LOAD_CONST 0 (None)
007 | 10 RETURN_VALUE
001 | 13 0 LOAD_GLOBAL 0 (print)
002 | 2 LOAD_DEREF 0 (x)
003 | 4 CALL_FUNCTION 1
004 | 6 POP_TOP
005 | 8 LOAD_CONST 0 (None)
006 | 10 RETURN_VALUE
007 | None
008 | 13 0 LOAD_DEREF 0 (x)
009 | 2 LOAD_DEREF 0 (x)
010 | 4 CALL_FUNCTION 1
011 | 6 POP_TOP
Well, it used to load a global constant by the name 0 where 0 refers to the index in co_const (where 0 => print ), and now it loads a nonlocal variable by the name 0
I wish dis.dis showed you the bytecodes
I replaced LOAD_FAST not LOAD_GLOBAL though
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
dis.dis(outer())
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 7 0 LOAD_DEREF 0 (x)
002 | 2 STORE_FAST 0 (y)
003 |
004 | 8 4 LOAD_CONST 1 (3)
005 | 6 STORE_DEREF 0 (x)
006 |
007 | 9 8 LOAD_FAST 0 (y)
008 | 10 STORE_FAST 1 (z)
009 | 12 LOAD_CONST 0 (None)
010 | 14 RETURN_VALUE
so that has all of our targets
LOAD_FAST, STORE_FAST, LOAD_CONST, STORE_CONST
not STORE_CONST
LOAD_FAST, LOAD_DEFER, STORE_FAST, STORE_DEREF
yes, STORE_CONST would be a strange instruction...
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
print(*map(lambda i: (hex(i), dis.op_map[int(hex(i), 16)]), f().__code__.co_code))
@hollow patrol :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 12, in <module>
003 | AttributeError: 'NoneType' object has no attribute '__code__'
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
print(f)
print(*map(lambda i: (hex(i), dis.op_map[int(hex(i), 16)]), f().__code__.co_code))
@hollow patrol :x: Your eval job has completed with return code 1.
001 | <function outer.<locals>.inner at 0x7f35468a1940>
002 | Traceback (most recent call last):
003 | File "<string>", line 13, in <module>
004 | AttributeError: 'NoneType' object has no attribute '__code__'
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
name = dis.opmap[int(hex(x), 16)]
ashex = hex(x)
return name, ashex
print(map(instruction, f.__code__.co_code))
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
<map object at 0x7f36eaa08df0>
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
name = dis.opmap[int(hex(x), 16)]
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
@hollow patrol :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 16, in <module>
003 | File "<string>", line 13, in instruction
004 | KeyError: 136
!e
msg = bytes([(True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << (True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << True ^ True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True)))]);import hashlib;msg=hashlib.md5(msg);msg=msg.hexdigest();output = lambda a, b, c, d, e, f: (a * b - c ^ e << (d * f)) if msg == "5d41402abc4b2a76b9719d911017c592" else 'no';c=print;_4883=str;output_ = c(_4883(output(1, 5, 6, 4, 3, 2)) if output == "<function <lambda> at 0x000001C135F25E18>" else "no"
@real galleon :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | msg = bytes([(True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << (True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << True ^ True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True)))]);import hashlib;msg=hashlib.md5(msg);msg=msg.hexdigest();output = lambda a, b, c, d, e, f: (a * b - c ^ e << (d * f)) if msg == "5d41402abc4b2a76b9719d911017c592" else 'no';c=print;_4883=str;output_ = c(_4883(output(1, 5, 6
... (truncated - too long)
Full output: too long to upload
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
print(hex(x), int(hex(x), 16))
name = dis.opmap[int(hex(x), 16)]
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
@hollow patrol :x: Your eval job has completed with return code 1.
001 | 0x88 136
002 | Traceback (most recent call last):
003 | File "<string>", line 17, in <module>
004 | File "<string>", line 14, in instruction
005 | KeyError: 136
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
print(hex(x), int(hex(x), 10))
name = dis.opmap[int(hex(x), 10)]
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.code.co_code)))
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
print(hex(x), int(hex(x), 10))
name = dis.opmap[int(hex(x), 10)]
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
@hollow patrol :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 17, in <module>
003 | File "<string>", line 13, in instruction
004 | ValueError: invalid literal for int() with base 10: '0x88'
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
print(hex(x), int(hex(x), 16))
name = dis.opmap[int(hex(x), 16)]
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
@hollow patrol :x: Your eval job has completed with return code 1.
001 | 0x88 136
002 | Traceback (most recent call last):
003 | File "<string>", line 17, in <module>
004 | File "<string>", line 14, in instruction
005 | KeyError: 136
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
print(hex(x), int(hex(x), 16))
name = dis.opmap.get(int(hex(x), 16), "INVALID")
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
!e
msg = bytes([(True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << (True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << True ^ True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True)))]);import hashlib;msg=hashlib.md5(msg);msg=msg.hexdigest();output = lambda a, b, c, d, e, f: (a * b - c ^ e << (d * f)) if msg == "5d41402abc4b2a76b9719d911017c592" else 'no';c=print;_4883=str;output_ = c(_4883(output(1, 5, 6, 4, 3, 2)) if output == "<function <lambda> at 0x000001C135F25E18>" else "no";
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | 0x88 136
002 | 0x0 0
003 | 0x7d 125
004 | 0x0 0
005 | 0x64 100
006 | 0x1 1
007 | 0x89 137
008 | 0x0 0
009 | 0x7c 124
010 | 0x0 0
011 | 0x7d 125
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ehuyovameb
!e
import dis
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
name = dis.opmap.get(int(hex(x), 16), "INVALID")
ashex = hex(x)
print(name, ashex)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | INVALID 0x88
002 | INVALID 0x0
003 | INVALID 0x7d
004 | INVALID 0x0
005 | INVALID 0x64
006 | INVALID 0x1
007 | INVALID 0x89
008 | INVALID 0x0
009 | INVALID 0x7c
010 | INVALID 0x0
011 | INVALID 0x7d
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/apipulitav
huh?
guys, let's try to not flood this chat with evals
thanks, either that or #bot-commands is okay
np
LOAD_DEREF 0x88
STORE_FAST 0x7d
LOAD_CONST 0x64
POP_TOP 0x1
STORE_DEREF 0x89
LOAD_FAST 0x7c
STORE_FAST 0x7d
POP_TOP 0x1
LOAD_CONST 0x64
RETURN_VALUE 0x53```
I got it good
LOAD_DEREF 0x88
STORE_FAST 0x7d
STORE_DEREF 0x89
LOAD_FAST 0x7c
these are what we need
@formal sandal I think I know why I'm wrong now
we replaced the wrong codes
or I did
and it wasn't 0x74 but 0x7c
and not 0x75 but 0x7d
oh
so if we try it now it should work
you really should use dis.opmap
I did
import dis
opmap = dis.opmap
opmap = dict(zip(opmap.values(), opmap.keys()))
def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
name = opmap.get(int(hex(x), 16), "INVALID")
ashex = hex(x)
if name != "INVALID":
print(name, ashex)
return name, ashex
print(list(map(instruction, f.__code__.co_code)))
I should've used None over "INVALID" but it doesn't matter
!e
def parent_scope(f):
f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x7c', b'\x88').replace(b'\x7d', b'\x89'))
return f
def outer():
x = 3
@parent_scope
def inner():
x = 4
inner()
print(x)
outer()
@hollow patrol :warning: Your eval job has completed with return code 139 (SIGSEGV).
[No output]
uh
that's weird
the reason is something to do with setting STORE_FAST to STORE_DEFER
actually no
it's something to do with the fact that i'm replacing bytecode i guess
I'm getting an IndexError: tuple index out of range
!e
import dis
opmap = dis.opmap
def func_replace(**instructions):
def inner(f):
co_code = f.__code__.co_code
for k, v in instructions.items():
print(co_code)
print(bytes([opmap[k]]), bytes([opmap[v]]))
co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
print()
f.__code__.replace(co_code = co_code)
print('GENERATED CO_CODE', co_code)
print('NEW CO_CODE', f.__code__.co_code)
return f
return inner
def outer():
x = 4
@func_replace(LOAD_FAST = 'LOAD_DEREF', STORE_FAST = 'STORE_DEREF')
def inner():
x = 24
dis.dis(inner)
inner()
print()
print('x =', x)
outer()
@hollow patrol :white_check_mark: Your eval job has completed with return code 0.
001 | b'd\x01}\x00d\x00S\x00'
002 | b'|' b'\x88'
003 | b'd\x01}\x00d\x00S\x00'
004 | b'}' b'\x89'
005 |
006 | GENERATED CO_CODE b'd\x01\x89\x00d\x00S\x00'
007 | NEW CO_CODE b'd\x01}\x00d\x00S\x00'
008 | 22 0 LOAD_CONST 1 (24)
009 | 2 STORE_FAST 0 (x)
010 | 4 LOAD_CONST 0 (None)
011 | 6 RETURN_VALUE
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/ewejuyusem
@formal sandal for some reason, .replace(co_code = new_co_code) won't work
I think I'm going to have to either set a new code object, or generate a new function
oh
code objects are immutable
so ```py
f.code = f.code.replace(co_code = co_code)
oh
import dis
opmap = dis.opmap
def func_replace(**instructions):
def inner(f):
co_code = f.__code__.co_code
for k, v in instructions.items():
print(co_code)
print(bytes([opmap[k]]), bytes([opmap[v]]))
co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
print()
f.__code__ = f.__code__.replace(co_code = co_code)
print('GENERATED CO_CODE', co_code)
print('NEW CO_CODE', f.__code__.co_code)
return f
return inner
def outer():
x = 4
@func_replace(LOAD_FAST = 'LOAD_DEREF', STORE_FAST = 'STORE_FAST')
def inner():
print('yay')
print(x)
#dis.dis(inner)
print('its k time')
#inner()
print()
print('x =', x)
outer()
what is going on?
for some reason
the nonlocal version
and the co_code replaced version
even though they have the same co_code
they still execute differently
import dis
opmap = dis.opmap
def func_replace(**instructions):
def inner(f):
co_code = f.__code__.co_code
for k, v in instructions.items():
#print(co_code)
#print(bytes([opmap[k]]), bytes([opmap[v]]))
co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
#print()
#print('GENERATED CO_CODE', co_code)
#print('OLD CO_CODE', f.__code__.co_code)
#print("WANTED CO_CODE", b'd\x01\x89\x00d\x00S\x00')
f.__code__ = f.__code__.replace(co_code = co_code)
return f
return inner
def outer():
x = 4
@func_replace(STORE_FAST = 'STORE_DEREF')
def inner():
x = 3
def other():
nonlocal x
x = 3
print(inner.__code__.co_code)
print(other.__code__.co_code)
#inner()
print()
print('x =', x)
outer()
not on my side
inner is the decorated
other isn't
and they both have the same co_code
other executes without error
Oh, wait
inner has an error
of course they have the same code
then why does only one work
the original function already accesses the nonlocal x
there are other things on the code object other than co_code
they're two different functions with the same code except one is replaced
yes, but I'm only changing the co_code
>>> (lambda:x).__code__.co_code
b't\x00S\x00'
>>> (lambda:y).__code__.co_code
b't\x00S\x00'``` look, same code, why are they different??
they access dif variables
but this code
they access the same variables
@func_replace(STORE_FAST = 'STORE_DEREF')
def inner():
x = 3
def other():
nonlocal x
x = 3
and have the same co_code
dis.dis handles the second one just fine
but the first one raises an IndexError
yeah of course it does, because there are things on the code object other than co_code and dis needs them to interpret the instructions into something human-readable
but I'm not accessing anything else
what
yeah exactly
you've changed the co_code and you haven't changed the rest of the code object to match it
what would I change
STORE_FAST accesses something in co_varnames, but STORE_DEREF accesses something in co_freevars
i think
other also has a closure
alright
oh
that makes total sense.
Because otherwise where would it take closure variable names from.
f.__code__ = f.__code__.replace(co_code = co_code, co_freevars = f.__code__.co_varnames)
This doesn't seem to work?
well you still need the closure
@hollow patrol are you still trying to do try/except with maintained scope?
@rugged sparrow yep
i might be able to help
you dont need to mod bytecode
def func_replace(**instructions):
def inner(f):
co_code = f.__code__.co_code
for k, v in instructions.items():
#print(co_code)
#print(bytes([opmap[k]]), bytes([opmap[v]]))
co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
#print()
#print('GENERATED CO_CODE', co_code)
#print('OLD CO_CODE', f.__code__.co_code)
#print("WANTED CO_CODE", b'd\x01\x89\x00d\x00S\x00')
f.__code__ = f.__code__.replace(co_code = co_code)
return f
return inner
then how?
I also don't want it to be version specific
and my goal is for a function parent_scope(FUNCTION)
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(r:={}).pop(
'r',
type(
'',
(__import__('contextlib').ContextDecorator,),
{
'__enter__':int,
'__exit__':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)``` would this not work?
that doesn't keep the parent scope
so I can't set variables in the parent scope
and I don't want to use a dict
!e ```py
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(r:={}).pop(
'r',
type(
'',
(import('contextlib').ContextDecorator,),
{
'enter':int,
'exit':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)
x = lambda:((a:=1),_try(lambda:(a:=2)),a)
print(x())```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
(1, 2, 1)
nope, I'd like to use existing scopes
that way it can use := without managing a dict
thats gonna be way more difficult tho
so what?
its also gonna make the produced code much more unstable
wouldn't the goal be for the produced code to behave exactly as the original code did?
which modding bytecode would not do lol
how?
@rugged sparrow well then, is there any other way to maintain scope
the only idea I have is
use a scope dictionary
other then that
[
(
...
)
for error in catch_errors(FUNCTION)
]
but that just pushes it back
{'parent':{},'vars':{}} that sort of layout
that would be less readable when prettifying
right now you can get stuff like
(
(
do_while := (
lambda cond, c=0: (
(((yield c), (yield from do_while(cond, (c + 1)))) if cond() else None),
)
)
),
(x := 1),
(y := 2),
print((x + y)),
None,
)[(-1)]
``` as an output
not as readable as python, but decent
you could yield exceptions pretty well using a context dec
hold on
I have an idea
What if I emulate try using the decorator
but instead of handling execution in its body
I'll send out the context generator exception to the main scope
With some sort of generator
that should work. one sec, imma write a quick catch_errors
however that gives me a new problem
how do I separate the context-decorator's exception yields from yields in the try or except blocks
like
try:
x = '5' + 5
except:
yield 3
one sec
btw after we add try-except
try-except-else-finally
this makes adding returns, continues, and breaks possible
def x():
try:
try:
for i in range(5):
try:
print(i)
except ContinueError:
pass
except BreakError:
pass
return 5
except ReturnError as e:
return e.value```
!e ```py
catch_errors = lambda f, e=Exception:lambda *a,**k:(yield (r:={}).get(
'r',
type(
'',
(import('contextlib').ContextDecorator,),
{
'enter':int,
'exit':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=a[1]
)]
}
)()(f)(*a, **k))
)
print(*catch_errors(lambda:1/0)())```
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
division by zero
that yields the exception or the func result
Can I ask a question about web scraping using Pandas?
wrong channel
Which channel should I use?
maybe #โ๏ฝhow-to-get-help
!e
catch_errors = lambda f, e=Exception:lambda *a,**k:(yield (r:={}).get(
'r',
type(
'',
(__import__('contextlib').ContextDecorator,),
{
'__enter__':int,
'__exit__':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=a[1]
)]
}
)()(f)(*a, **k))
)()
@hollow patrol :warning: Your eval job has completed with return code 0.
[No output]
@hollow patrol that func takes in the try func, and a tuple of Exception types to catch
remove the isinstance(a[1],e) and
ยฏ_(ใ)_/ยฏ
that handles exceptios
i dont really know how to best fix scoping
also youre not gonna want your try func to catch everything
I do want it to
cause nested try/excepts
that way it yields it
@rugged sparrow it catches everything that is in the criteria
and handles each thing differently depending on instance
then raising again otherwise if nothing detected it
scoping is always going to be an issue cause lambdas dont provide a good way to handle scoping
all I want is a workaround to avoid scoping
like for whiles I avoided scoping by using a do_while generator
i dont know if there is a workaround
varlist.__setitem__('x', 3) is so much less readable then x := 3
scope.update({'x',3}) or scope.setdefault({'x',3})
or create a simple scope cls with set and get
!e
x = 4
@latent bronze :warning: Your eval job has completed with return code 0.
[No output]
!e
print(f'coronavirus')
@latent bronze :white_check_mark: Your eval job has completed with return code 0.
coronavirus
!e return print('ok')
@latent bronze :x: Your eval job has completed with return code 1.
001 | File "<string>", line 1
002 | SyntaxError: 'return' outside function
use #bot-commands
@rugged sparrow the reason I'm so hesitant to create a custom scope is that it would mean I have to recursively look at every expression in the AST
just to find a name
and then convert the name to a dictionary attribute
that shouldnt be too bad
and it'll look a lot more ugly
mapping.__setitem__('x', 1) isn't as nice to look at as x := 1
why are you doing mapping.__setitem__ instead of .setdefault
oh wait
setv, getv = (d:={}).__setitem__, d.get
just do that
obv needs more to do nested scoping
but you get it
alright
can anyone explain why this happens? ```py
def foo(): print("hello world!")
...
foo2 = types.FunctionType(foo.code, {})
foo2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
NameError: name 'print' is not defined
exec(foo2.code)
hello world!
oh i get it ```py
foo2 = types.FunctionType(foo.code, {"builtins": globals()["builtins"]})
foo2()
hello world!
You're welcome 
You can also mutate the function if you want.
foo.__code__ = foo.__code__.replace(...)
import inspect
def name(val):
frame = inspect.currentframe()
while (frame := frame.f_back):
for k, v in frame.f_locals.items():
if val is v:
return k
Hm, I agree that this usage of := is probably clearer than
frame = inspect.currentframe()
for frame in iter(lambda: frame.f_back, None):
yea i really like := for loops like that
@zealous widget want to help me add switch to python? im gonna try to use a __build_class__ hook or a metaclass
i have a close solution already kind of, it was something else though
what was your solution?
i used a metaclass to bind functions to properties in a class def --- you could just change it from properties to something else
In [304]: def observer(instance, name, old, new):
...: print(f'{name} from {instance} changed from {old} to {new}')
...: class Relay(Dispatcher):
...: property_: observer
In [305]: Relay().property_ = 10
property_ from Relay(<property_=10, [observer]>) changed from None to 10
looks kinda like this
i mean like ```py
switch(val):
case 1:
<code>
break
yeah, you could do:
class Switch(switchcase):
case_1: func1
case_2: func2
that would be too easy
val = 1
class switch(val):
case:1
##code
'break'```
maybe like that
switches need multiple cases
yes, but you need to inherit from some class to get all the metaclass hacks
you can define the cases in the class body
im gonna hook __build_class__ and alter bytecode
replace LOAD_CONST 'break' with RETURN_VALUE and STORE_NAME 'ret' with RETURN_VALUE as well
i think it should work
noice
Interesting!
bet i got basic switch working
>>> class switch(val):
... case: 1
... print(val + 1)
... case: 2
... print(val + 2)
... ret = val
... case: 'default'
... ret = None
...
2
3
>>> switch
1
>>>```
fall thru works
and ret = {val} stores val into switch
Can you not use the return keyword in there?
it wont compile so sadly no
It might look cleaner to do switch = ... instead of ret.
true
why not use []
hook into a metaclass with __getitem__
then do
or actually
make a switch class that takes in a single argument that hooks into __getitem__
and do
switch (value, none = lambda: print('nothing found')) [
1: lambda: print('we got a 1'),
2: lambda: print('we also got a two')
]
how would you specify to fall thru or return?
What about context managers? If you also use __iter__(), you can break seamlessly.
for s in switch(val):
with s.case(1):
...
with s.case(2):
...
break
ohhhhhhh thats clever
It might not be possible to skip execution of a with block, though. Maybe by raising from within __enter__?
@earnest wing It is, I've done it before
I made some code that turns a function into a context manager that receives a body
I think you have to use sys.settrace to raise an exception and catch it in __exit__
That is probably necessary, because __exit__ only suppresses exceptions raised during the body.
from collections import ChainMap
_name_to_cases = {}
class SwitchMeta(type):
def __call__(cls, value):
return _name_to_cases[cls.__name__][value]()
def __prepare__(name, *args):
cases = {}
_name_to_cases[name] = cases
def case(val):
def deco(func):
cases[val] = func
return func
return deco
return ChainMap({}, {'case': case})
def __new__(meta, name, bases, methods):
methods = methods.maps[0]
return super().__new__(meta, name, bases, methods)
class switch(metaclass=SwitchMeta): pass
class myswitch(switch):
@case(1)
def _():
print(1)
@case(2)
def _():
print(2)
@case('a')
def _():
print('a')
In [425]: myswitch(1)
1
In [426]: myswitch(2)
2
In [427]: myswitch('a')
a
switches have fall thru tho
like case 1: case 2: print(12) 1 and 2 both run print(12)
oh, you can double decorate
class myswitch(switch):
@case(1)
@case(2)
def _():
print(1)
like case 1: print(1) case 2: print(12) 1 and 2 both run print(12) while 1 runs both prints
oh, well dicts are ordered so that's not a problem either
class SwitchMeta(type):
def __call__(cls, value):
funcs = _name_to_cases[cls.__name__].get(value, (lambda: None, ))
for func in funcs:
func()
def __prepare__(name, *args):
cases = {}
_name_to_cases[name] = cases
def case(val):
def deco(func):
cases[val] = []
for case in cases:
cases[case].append(func)
return func
return deco
return ChainMap({}, {'case': case})
@earnest wing i liked your idea ```py
class switch:
def init(self, val):
self.val = val
self.cascading = False
self.default = True
def case(self, val):
if val == self.val or self.cascading:
self.cascading = True
return True
return False
def __iter__(self):
yield self
for s in switch(3):
if s.case(2):
print(2)
if s.case(3):
print(3)
if s.case(4):
print(4)
break
if s.default:
print('default')
rn it can fall thru into default but that can be changed pretty easily
wait are you silencing exceptions with sys.settrace
thats clever tho
it's based on an old troll implementation of goto iirc
i use yield:
class myswitch(switch):
@case(1)
def _():
print(1)
yield
@case(3)
def _():
print(2)
@case('a')
def _():
print('a')
as a break?
yeah
it's not so much sys.settrace moreso than setting f_trace for individual frames btw
we could return
though you need something in sys.settrace for that to work
frame.f_trace = self.skip yah im reading thru it rn
there's another version that uses with case(b == 2): rather than with case(lambda a, b, c: b == 2):
just checking the bool value at the end
cant find it
been a while
vaguely remember there was one by @grave rover which i really liked and thought was really pretty
lol
i wonder if it would be possible to actually add switch val: without modding cpython
is this seem right: https://github.com/salt-die/Snippets/blob/master/switch.py
i was working on the continuous range dicts, but now i could apply it to continous range cases
Oh god not the nested metaclasses again haha
I donโt get why people are going with doing all of this if there is a simpler and cleaner way haha
# coding: cases
n = 13
switch n:
case 1:
case 2:
n += 10
break
case 13:
n = 0``` with some thought can be transformed to ```py
n = 13
while True:
if n == 1 or n == 2:
n += 10
break
if n == 13:
n = 0
break```
Solutions for cases I have seen are indeed fun, but this one to me seems to have the smallest overhead
there is a lot of noise in the second snippet
indeed there is, and it can be optimized
How does default work in switch though?
it runs if no cases were run, right?
it is the label it jumps to if no case matches
okay this one would be harder
simplest solution would be to say default = False in every case snippet
what I meant is on user end, switch will look nice and work just as expected
too bad tokens don't match expressions haha
@marsh void Because coding circumvents the fun of abusing the Python interpreter. Why else would #esoteric-python exist?
Oh, I think I've misunderstood. Still, this point applies.
To me, this is what abusing python is
# cases.pth
import cases # add encoding
import sys
sys.stdin.close()
sys.stdin = open(0, encoding="cases")``` @bitter iris showed me this and I was amazed, haha
@brazen geyser sup
I remember using the current frame info to basically use jumps lol
Python VM languages?
Hy, dogelang and such I would assume
Don't forget xmllang http://github.com/isidentical-archive/xmllang
if we had jump offset and jump bytecodes
you could make a jumptable in python bytecode
and then switches could be O(1) in some cases
but you can also implement that behavior with a list of lambdas
@marsh void if you want a switch implementation here's one i made
def switch(s):
return lambda **a: a.get(s, a.get("default", bool))() or s != "default" and switch([*a][[*a].index(s) + 1])(**a)
it allows for multiple case executions and default
how exactly do you stop multiple case execution
boolean test on the case
you use it like that
test = "a"
switch(test)(
b = lambda: "no",
a = lambda: print("hi"),
c = lambda: print("hello"),
d = lambda: not print("stop"),
default = lambda: print("default")
)
``` or with functions, they can return a boolean or not
makes sense
(this will print hi, hello and stop)
python goto when
yes but i wanted to use no module, my iterative version uses itertools.takewhile tho, for performance reasons
goto theoretically has no overhead
there are some other way to optimize it already tho, like adding a counter but ye goto would be the better way
wanted to do it on one line too ^^
this goto module rewrites bytecode
so it's basically undefined behavior across future versions and implementations
sad
nonetheless
since it's bytecode manipulation instead of c extension
you don't need a module
just write a goto
</s>
i think a c extension exists
That's all I have to say haha
On a more serious note, a goto in an higher language will have some overhead for sure, because of context switching mainly
How does that introduce a context switch?
If you leak the previous locals into the goto target you'll segfault at the speed of light
@pine edge those byte code instructions exist. We have JUMP_ABSOLUTE and JUMP_FORWARD
very good
are there any circumstances under which those byte code are actually generated by the interpreter
or are they purely for shenanigans
jmp_absolute is used for while loops and maybe some for loops
I've never seen a jmp_forward generated, but I also don't disassemble every func I write
!e ```
import dis
dis.dis('while 1:pass')
@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.
001 | 1 >> 0 JUMP_ABSOLUTE 0
002 | 2 LOAD_CONST 0 (None)
003 | 4 RETURN_VALUE
also if I use a dict
then it won't show the vars in globals
so it won't work for importing it
I've never seen a jmp_forward generated, but I also don't disassemble every func I write
disappointing haha
Where does jmp_forward typically show up?
In [38]: dis.dis("if a: print(4)\nelse: print(5)")
1 0 LOAD_NAME 0 (a)
2 POP_JUMP_IF_FALSE 14
4 LOAD_NAME 1 (print)
6 LOAD_CONST 0 (4)
8 CALL_FUNCTION 1
10 POP_TOP
12 JUMP_FORWARD 8 (to 22)
2 >> 14 LOAD_NAME 1 (print)
16 LOAD_CONST 1 (5)
18 CALL_FUNCTION 1
20 POP_TOP
>> 22 LOAD_CONST 2 (None)
24 RETURN_VALUE
```seems like skipping else branches of ifs
Maybe it would be a fun project to make a simple VM runtime in C.
Or in other low-level language like Go. But it's probably going to be less fun, since you won't get segfaults.
In general, SIGSEGV is much more fun to debug. A high-level language will give you a more or less helpful message on what went wrong. But with C, you'll have to conspire with an external tool like valgrind to start a long investigation.
And it's very rewarding to finally fix that null pointer dereferencing or off-by-one error.
programming in rust is more fun than debugging segfaults unless the segfaults are from ctypes fuckery.
I refuse to believe that there's something more fun than a segfault.
Fatal system errors produced by your program?
You might have a point there.
Segfault is like a punchline in a long joke. You've been working hard on your problem, and now you're ready to launch your masterpiece. But the act of you programming in C is just a part of a cruel irony set up by the computer. Filled with hope, you run your successfully compiled program. After running for a few seconds, it breaks down and displays a short error message, saying: "Haha, you failed".
The quarantine must have impacted me in a wrong way.
nah the most fun is when you segfault another program
these are all lies
the most fun i've had is getting python to cause a SIGBUS from doing print("hello world!")
i actually don't know, but it was after i did some messing around with memory-related stuff in ctypes
so perhaps the hello world was just the tipping point of stability
i bet if you interned "hello world!" and then derefed it
well wouldn't that just be a segfault?
since even though it's dereferenced, it's still an addressable part of memory (otherwise how would it have been interned there in the first place)
Tbh I forget what causes a sigbus
ohhh so i need to change the interned string to point at the wrong addr
not just a wrong address, but an address that doesn't physically exist
makes sense
On the last staff meeting I attended, I consistently received SIGBUS in my browser when pressing Ctrl+C
wut
I have no idea
Every time I pressed Ctrl+C, my tab would freeze. When I reloaded a tab, it displayed an error message complaining about SIGBUS.
thats bizzare