#esoteric-python
1 messages · Page 12 of 1
hmm...
didnt noticed P parameter
in index method, you can pass start and end
it also doesnt work
wdym?
imagine we have this data: x 0 0 y 0 0
x 0 is one char, 0 y is other char, 0 0 is our terminating char
they are null characters, so we should continue reading string
but in your approach it founds 0 0 and stops at this position. And then .decode throws this: UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x47 in position 4: truncated data
im working with characters of size 2
you said a null terminated string
meaning the string ends on first occurrence of \0
null terminated but characters are 2 byte long
so NULL in our case is b'\0\0', not b'\0'
also doesnt work
x 0 0 y 0 0
^^^ first
^^^ second
^^^ last NULL
^^^ your code finds this
^^^ but i need this
characters must be aligned
ah
alignment
your code works fine for regular strings, but not for wide string
wide strings are scary
in 3.11 try-except is really zero-cost if no errors occured
but if exception was raised, handling time depends on length of exception table
so, if you have function with a lot of try-except's or with's, exception handling will be very slow
here try-except was 18 times slower because i was running it inside huge function with a lot of context managers
ah
How do you access the members defined in a class from self in a method definition in the metaclass? Do you do vars(self)['…'] or something?
turns out that works
self.attr
or
self.__class__.attr
oh OK
can I hide a function that is defined inside the class body from instances?
specifically I want to make a metaclass that can be used to define a __call__ in the class body to be available on the class itself but not on the instances
or is a metaclass the wrong tool for that?
yeah metaclass is correct for that
though a call for the class itself sounds like __new__
so you probably could get the same behavior by defining new
but metaclass is more fun :]
so even more specifically I want to make a subclass of ABCMeta that allows its instances to define a __call__ inside their body to override the (impossible) constructor functionality of ABCMeta
is that possible?
would I need to override __new__ on the class object for that?
(to hide the __call__ from instances)
I haven't looked at ABC a lot, so idk what it does
to hide the function? you could just override getattribute on the class, no?
I’m not that familiar with metaclasses, so I don’t know—what if the instance defines its own getattribute?
getattribute on the instance would get stuff from the instance
whereas on the class would be the classes attributes
oh
metaclass is the class of a class
a class is an instance of a metaclass
yeah that much I know :)
k
I thought about making a classonlymethod decorator that would raise if it was called from an instance
ABC overrides object construction by raising if any of the methods in the subclass are marked as abstract via @abstractmethod
!e
class meta(type):
def __getattribute__(cls, attr):
print(f"class __getattribute__ {attr}")
return object.__getattribute__(cls, attr)
class nonmeta(metaclass=meta):
def __getattribute__(self, attr):
print(f"instance __getattribute__ {attr}")
return object.__getattribute__(self, attr)
nonmeta.__dict__
nonmeta().__dict__
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | class __getattribute__ __dict__
002 | instance __getattribute__ __dict__
I see
interesting
it would be for the purpose of handling multiple inheritances?
google has lied to me!
but I’m not multiply inheriting
I meant, ABC in general
if defined in their body, it would be the instances __call__
probably better to use __class_call__, similar to __class_getitem__
I see
so that way theres no name conflicts
if you want to define a __call__ for the instance
yeah good idea
or class_call
because using dunders is not good
ok
hm
it's not a good practice, but it communicates what it's doing better because it's similar to __class_getitem__, so anyone who knows what that does will understand what this does better
it all comes down to preference
wait what
I just looked into the implementation to see how it’s done
and it seems like the error gets raised by the Python interpreter itself as a builtin feature
that would explain why manually setting .__call__ = foo after the class definition doesn’t work
no wait that’s just not how you do that I guess?
but still
there’s no place the error gets raised in the actual abc module
:incoming_envelope: :ok_hand: applied mute to @bronze perch until <t:1670374396:f> (10 minutes) (reason: duplicates rule: sent 4 duplicated messages in 10s).
The <@&831776746206265384> have been alerted for review.
!e
dis('for i in "abcde": print(i)')
@umbral pagoda :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | NameError: name 'dis' is not defined. Did you mean: 'dir'?
(from dis import dis)
ok
!e
import dis
dis.dis('for i in "abcde": print(i)')
@languid hare :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0 0 RESUME 0
002 |
003 | 1 2 LOAD_CONST 0 ('abcde')
004 | 4 GET_ITER
005 | >> 6 FOR_ITER 13 (to 34)
006 | 8 STORE_NAME 0 (i)
007 | 10 PUSH_NULL
008 | 12 LOAD_NAME 1 (print)
009 | 14 LOAD_NAME 0 (i)
010 | 16 PRECALL 1
011 | 20 CALL 1
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/hagucufuxa.txt?noredirect
thx
np
1665964800000 how to convert this format of date into python datetime
seems pretty expected
it's already slower for {*()} vs set() so why should it be faster here
wrong channel
#❓|how-to-get-help
unless you want an esoteric answer
I have some code in day time it is running well but while code is running I put laptop on sleep mode now same code is not working can anyone help me to fix this problem
pretty sure discussions are against the rules
#esoteric-python is not the right place.
!rule 5 6 7
@rustic storm
5. Do not provide or request help on projects that may break laws, breach terms of services, or are malicious or inappropriate.
6. Do not post unapproved advertising.
7. Keep discussions relevant to the channel topic. Each channel's description tells you the topic.
@quartz wave I finally figured out why hooking type.__new__behaves so weirdly. The reason the rest of the dunders work so smoothly is because I grab the wrapper_descriptor object and setattr has special cases for those that sets slot pointers correctly. But type.__new__ is only ever available as a builtin_function_or_method
So setattr doesn't set slot pointers correctly, and orig freaks out
An alternative is hooking type.__call__ and just using issubclass on self to make sure its a subclass of type
fastest way to get the number 1 using only dunders?
__name__.__class__.__bases__.__len__()
😔
fixed
i dont think you can use less dunders
this works if you need it to be an int specifically
__name__.__eq__(__name__).__int__()
but since bool acts like int, this works in most cases
__name__.__eq__(__name__)
In [4]: dunders = 1
...: print(f"The fastest way to get the number 1 using only dunders: {dunders}")
The fastest way to get the number 1 using only dunders: 1
I think i won. 😁
(dunders:=1)
my way is less chars
Ok, you won.
:P
fastest way to get 1034 in dunders
uh
good question
there's probably something that has a __sizeof__ that's close to that
so my guess would be doing something with that
or maybe len of a very long builtin iterable
__builtins__.__dir__().__sizeof__().__sub__(__import__.__dir__().__sizeof__()).__add__(__name__.__sizeof__()).__add__(__name__.__len__()).__invert__().__neg__()
I'm sure there's a shorter way but that's my first attempt
will improve it in a bit
since I gtg rn
you are using 4 dunders here, not 1
import zlib, codecs
IllIIlIIlIIIllllIIlIIIIllIllII = ['Obfuscated with KarrotPY']
eval((lambda n: ''.join(chr(ord(c) - n) for c in ''.join(i for i in ['턲','텅','턲','터'] if exec!=print)))(-29099748+14986150+72274553-58107502))(codecs.decode(zlib.decompress(bytes(b'x\xda\x8dP\xcdn\xc20\x0c\xbe\xf3\x14\x19;,Q\x9b\x92\xa4\xf9\x9d\xb4\x07\xe0\xb6;\xea\xa1\x83 \xb2\x95\xb6J;\x06{\xfa9\xc0aH\x1bP\xc5\x91k\xc7\xdf\x8f\x1fQ\x7f\xe8\xde\x8ao\x7fh\xbb}\xb1\xfel\x11E\xaf\x8d\xaf\x07\x8fV]\xfb4\xa2\xe8\xb7\xdd\xce\xa3q\xe3\xd1W=\xfa\xb8\xad\xe3\xc7l\x19\xfd*\x8cC1\tk4o\x9a\xf9\xfct =\xff\xa4\xf4\xd8X\xb0\xea\xe1e:-\xde\xbb\xd0\xe2\xe5&\xe2@\xd0\xba\x8b(\xa0\xd0\xa2\x85q\xb9\xb39g"\xe7\xdc@\xa8\xdcA%e\x1a\xaa\x1c\x82\xe5ej:H\xd5\xb9,S\xc9\xa8\xd3;y\x0e~lZ\x96[W\x91\xe7\t\x82\xaf\x8f\xa1\x1d\xf1\xbf\xdc\x89\xf88j\x12fE\xc8q\xc8\xef\xc3\x88\xc9\xc47\x83?\xa1\\\xb7W,aW\x11\x06n<\xab\xfb\xde\xb7\xabK1 .\xcc8#\xbfE\x81S\x96\xdc\xa4\xcb\xb1$\xea>`\xbf\xab\x9b\xbf\xd0\xf9%\xbaH\xcb\x14*\xb9V\xb0N\x91x\x84\xd1\xc0s\x8bhQ\xbf\r\x98b*\x8cu\xca\xcaL\xd9RH\xae2\xceK&\xa4\xa4\x92\x1b!\x9c%\xb4\xf1-\xbe\x0eE\xb2Rh)uf\xb4\x15"\xe3\x82\x81\x04\xaa\x04\xdc\x9aT\xf8.\x1d\\j\'e&\x19\x17Ve\xdaj\xae$\x05{\xa5r\xe6>\r\x14\xf6k\xac1\x99r\x96\x95V\x83\x8e\xd29\x03F\x9c2\xdc\x92\x8a\xfc\x00\x82\xcc\xde\xb3'))))```
rate 1-10

you can add exec = lambda x: print(x) at the beginning to see the actual obf code
i added this layer just to compress the file
!e
print(__import__('builtins').__dir__().__sizeof__().__add__(__import__.__dir__().__sizeof__()).__add__(int.__add__.__dir__().__sizeof__()).__add__(int.__add__.__dir__().__sizeof__()).__sub__(type.__dir__.__sizeof__()).__invert__().__neg__().__add__(__import__('builtins').__dir__().__getitem__(__import__('builtins').slice(1,16, None)).__len__()))
@rugged owl :white_check_mark: Your 3.11 eval job has completed with return code 0.
2048
yeah ik
I never said that it was less than 4 dunders?
__import__('builtins').__dir__().__sizeof__().__add__(__import__('builtins').__dir__().__sizeof__()).__sub__(object.__init__.__dir__().__sizeof__()).__sub__(object.__init__.__dir__().__sizeof__()).__add__(int(2).__sizeof__().__sub__(__name__.__len__()).__sub__(__name__.__len__()).__add__(__import__('sys').__name__.__len__().__invert__().__neg__())).__add__(__import__('faulthandler').__name__.__len__().__add__(__import__('sys').__name__.__len__().__invert__().__neg__()))
Python bot is evaluating this as 1968 while my python version is evaluating it as 2048, why? 
Python 3.10.4 (main, Nov 29 2022, 20:00:25) [GCC 9.4.0] on linux
>>> 2048
Your 3.11 eval job has completed with return code 0.
1968
Your 3.10 eval job has completed with return code 0.
1952
there's a whole lot of differences between version 3.11.0, 3.10.8, and 3.10.4
especially since 3.10.4 isn't the latest 3.10 version

codespaces outdated then
not python's, but there are scopes
i did this as a joke with a little too much effort so the code is kinda messy but https://github.com/dzshn/lispy/blob/main/lispy/__init__.py#L125-L149
mm this is more interesting at closer inspection, since the inner statements are evaluated first the def is technically last
ill have to look at this later, nice (cursed) work
there a good way to make module level properties such that autodoc and type checkers won't be a big problem?
- define it as function (possibly decorated)
- create subclass of ModuleType
- add property to this class
- change class of your module
You can typecheck that by using if TYPE_CHECKING: and defining your property as regular variable inside that if
Hmm i have an idea
import typing as t
import collections.abc as t_abc
import sys
import types
T = t.TypeVar('T')
def moduleproperty(func: t_abc.Callable[[types.ModuleType], T]) -> T:
# assert isinstance(func, types.FunctionType)
module = sys.modules[func.__module__]
name = func.__name__
if type(module) is not types.ModuleType:
setattr(module.__class__, name, property(func))
else:
module = type(module.__class__.__name__, (module.__class__,),{name:property(func)})(module.__name__,module.__doc__)
sys.modules[func.__module__] = module
return func # type: ignore[return-value]
@moduleproperty
def x(this: types.ModuleType) -> int:
return 42
# reveal_type(x) # Revealed type is "builtins.int"
If you do module.x, then it will call x with module as argument and return result
If you do from module import x module.x will be called once and result will be cached
If you do x inside this module, you will see original function x
Typeheckers will think that x is int, not a function or property. It is good if you are accessing x from outside, but bad otherwise because x is not int actually
code is not tested for all cases, and it doesnt support property.setter now. But it works
oh wow
I am going with this
__all__ = ["singleton"]
class _Singleton:
@property
def prop(self) -> int:
return 42
@prop.setter
def prop(self, value: int) -> None:
...
singleton = _Singleton()
So end user is supposed to use singleton instance for all their needs
but they need to do module.singleton.prop, not module.prop
why is Callable in t_abc?
because stuff in collections.abc is preferred over stuff in typing
Callable is abstract class, so it is in collections.abc
ĸ
like Iterator, Hashable, Sequence, etc
I see, so all predefined ABCs are in collections.abc?
Anyways I managed to do the metaclass thing I was trying to do
class CallableABCMetaDict(
dict[str, object],
):
_class_call: object | None
def __init__(self, *args: object, **kwargs: object) -> None:
self._class_call = None
super().__init__(self, *args, **kwargs)
def __setitem__(self, key: str, value: object, /) -> None:
if key == "_class_call":
self._class_call = value
super().__setitem__(key, value)
class CallableABCMeta(ABCMeta):
_class_call: object | None
@classmethod
def __prepare__(
cls, __name: str, __bases: tuple[type, ...], **kwds: object
) -> CallableABCMetaDict:
return CallableABCMetaDict()
def __init__(
self, name: str, bases: tuple[type, ...], namespace: CallableABCMetaDict
) -> None:
self._class_call = namespace._class_call
super().__init__(name, bases, namespace)
def __call__(self, *args: object, **kwds: object) -> object:
_class_call = self._class_call
if _class_call is not None and callable(_class_call):
try:
# Try to catch incorrect args early to hide __class_call__
sig = signature(_class_call)
sig.bind(*args, **kwds)
except ValueError: # Signature does not exist
pass
return _class_call(*args, **kwds)
return super().__call__(*args, **kwds)
class CallableABC(metaclass=CallableABCMeta):
pass
now I can do
class Example(CallableABC):
@abstractmethod
def abc():
pass
@classmethod
def _class_call(cls, x):
return x
class StillAbstract(Example):
pass
class Concrete(StillAbstract):
def abc():
print("abc")
if __name__ == "__main__":
print(Example(2))
try:
StillAbstract()
except TypeError:
print("Can’t instantiate StillAbstract")
Concrete().abc()
Where is that said?
typing.Callable```
Callable type; `Callable[[int], str]` is a function of (int) -> str.
The subscription syntax must always be used with exactly two values: the argument list and the return type. The argument list must be a list of types or an ellipsis; the return type must be a single type.
There is no syntax to indicate optional or keyword arguments; such function types are rarely used as callback types. `Callable[..., ReturnType]` (literal ellipsis) can be used to type hint a callable taking any number of arguments and returning `ReturnType`. A plain [`Callable`](https://docs.python.org/3/library/typing.html#typing.Callable "typing.Callable") is equivalent to `Callable[..., Any]`, and in turn to [`collections.abc.Callable`](https://docs.python.org/3/library/collections.abc.html#collections.abc.Callable "collections.abc.Callable").
Instead of dividing properties into modules i divide them by singletons, ultimately the qualified name looks the same.
Considering that module here is a part of a package
not if you define the module __getattr__ to return the attribute on the singleton
!e
print("".join("deHlorW! "[0 if i == 10 else 1 if i == 1 else 2 if i == 0 else 3 if i in [2,3,9] else 4 if i in [4,7] else 5 if i == 8 else 6 if i == 6 else 7 if i == 11 else 8 ] for i in range(12)))
@zenith geode :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello World!
!e
print(__import__('builtins').__dir__().__sizeof__().__add__(__import__('builtins').__dir__().__sizeof__()).__sub__(object.__init__.__dir__().__sizeof__()).__sub__(object.__init__.__dir__().__sizeof__()).__add__(int(2).__sizeof__().__sub__(__name__.__len__()).__sub__(__name__.__len__()).__add__(__import__('sys').__name__.__len__().__invert__().__neg__())).__add__(__import__('faulthandler').__name__.__len__().__add__(__import__('sys').__name__.__len__().__invert__().__neg__())))
@zenith geode :white_check_mark: Your 3.11 eval job has completed with return code 0.
1968
So cool, how does it work? Are you using import hooks to read & execute the non-python code?
when lispy is imported, it re-reads the file and reparses it as lisp, executes it there, and sys.exits so the rest of the script doesn't execute
reparses? Do you edit the ast.Module?
I use tokenizer.tokenize and make an ast myself
Ah okay
Are you using importlib for this?
if I used ast it would get rid of some parenthesis probably
nope
Oh, how are you getting it to reparse on import?
I get the running frame with sys._getframe and get the outer frames until they're outside of importlib actually
and then it's just frame.f_code.co_filename
Oh thats neat
I've never thought about using frames
I've only every used importlib or the runpy stuff
I should've probably used importlib or inspect tbh but this is funnier
I'm not taking it really seriously lol
for context I made this as a joke cuz my friend said I'd develop a serious lisp from using lisp-like languages on aoc
👄
Are you gonna add more features or just what you got right now?
Like mangling or something
(not a huge lisp person myself)
I probably will add something from time to time
this was actually made in a single day
Is it full inter-op with python?
i wonder if you could get it to work where it does it at runtime so that you can just let python build the control flow for you, then it would work in the native repl (and you would get python interop for free)
(and before u ask I am aware of hy)
Make it inter-op then bootstrap it :trolface:
We do a lil trolling
my other cursed lib with code manipulation interops with python https://github.com/dzshn/uwu
wtf lmao
yop
I really should learn how to manipulate bytecode and stuff lol
would unlock so much cursed stuff for me
it's really fun
unfortunately u will just suffer every time there's major bytecode changes
cuz it's not meant to have a stable api at all
I still haven't learned 3.11 stuff
every year
possibly even every few months for the same python major version
smort👌
yea one of the reasons I tried to not do any bytecode stuff
Do you have any resources where you learned about bytecode
I'll read up
the builtin dis module is really useful
for all the bytecode that won't change much though, it's fun and all
also reading source code
this is why i like to stick to doing cursed stuff using typeobjects
Time to fresh up on my C?
I simply don't update 🚎
do you think that'll be stable when they start optimizing internal structures for JITing?
but yes those are really fun too
in theory yes because its part of the stable ABI
oh nice
So to edit bytecode it's through co_code right?
yes
but if they hardcode JIT for internal types like int then it will probably start to break
when it's fine to return a new code object (like modifying user_func.__code__ or python <3.11), yes
like if stuff like int.__add__ jit ends up special cased that will make fishhook trickier to implement, and I would probably go with a different hooking route (i call it the nuclear option lmao because it involves swapping out all the internal pointers to builtin types to ones fishhook controls)
I have a module for helping with bytecode stuff a bit https://github.com/dzshn/ike
INPLACE_POWER
good old days when python didn't have all binary operators in one opcode
What's the x00d for?
somehow fishhook worked on 3.11 with no edits, i got lucky
(although I did rewrite it anyways)
it's the opcode argument
\x00 is a null byte
d is another byte
\x00 is an argument to the previous opcode (\x01 or POP_TOP)
d is LOAD_CONST
d\0s\0, the magic bytes
I don't usually look at the raw binary data so I don't really remember their values
except in reverse
The argument comes before the opcode?
no
\x00 is an argument to the previous byte/opcode which is the \x01 before it
opcode arguments used to be optional (iirc in python 3.5)
that was probably hell
but now bytecode always has 2n bytes
wait what
so like python 2 still has those no-argument opcodes?
I lied
also guhh bytes being == strings
The argument for LOAD_CONST is stored in co_consts right? Not the co_code?
Ohh okay, I'm understanding a bit better now
So, d => LOAD_CONST, then the next byte is the index for co_consts?
ye
Sorry for ping, but how do I replace co_code once I change the bytes?
Do I need to create a new function with all the co_
u can replace the function's __code__
code objects have a .replace method
which allows you to only replace some of the attributes and return a copy
so you can func.__code__ = func.__code__.replace(co_code=...)
if you want to replace co_code in-place that's another story though
probably not what you want here but in case you're curious ```py
def overwrite(victim: object, value: object):
# don't overwrite the reference count (immediate explosion otherwise)
start = ctypes.sizeof(ctypes.c_int)
arr = ctypes.c_ubyte * (value.sizeof() - start)
arr.from_address(id(victim) + start)[:] = arr.from_address(id(value) + start)
thank u dzshn
then u can overwrite(code.co_code, new_bytecode)
no problem you can ask me anytime
I was stuck until I realised this for some time 😔
I compared two of them together with different strings and I was so confused as too why it was the same
then I noticed co_consts
Probably a bad idea to edit bytes objects, on 3.11 that’ll confuse the quickening machinery, just make new code objects.
does it really matter if I'm doing horribly cursed things with it anyway
Are manually constructed code objects still eligible for quickening?
altered_bytecode = modify.__code__.co_code[:8] + bytes([dis.opmap['LOAD_FAST'], 0, dis.opmap['RETURN_VALUE']])
code = type(modify.__code__)
function = type(modify)
ocode = modify.__code__
new_modify = function(
code(ocode.co_argcount, ocode.co_kwonlyargcount, ocode.co_nlocals, ocode.co_stacksize,
ocode.co_flags, altered_bytecode,
ocode.co_consts, ocode.co_names, ocode.co_varnames, ocode.co_filename,
'new_modify', ocode.co_firstlineno, ocode.co_lnotab, ocode.co_freevars,
ocode.co_cellvars),
modify.__globals__, 'new_modify', modify.__defaults__, modify.__closure__)
new_modify()
>>> TypeError: code expected at least 16 arguments, got 15
What value am I missing in code(...)
help(code)
posonlyargcount, second parameter
is that 3.10
Should be 3.11 let me check
then you've got the wrong type for argument 16
unless a tuple is valid bytes
ok i think it's gonna be 4n in 3.12 https://github.com/python/cpython/pull/100106/
huh interesting
i saw that too
was gonna say something

Maybe it was causing an issue and it took them forever to trace it back to that 1?
off by one errors be like that
it's the worst thing all programmers face
apart from like the hours of debugging to make a code that runs in under a second work
and all the other stuff
it's only a draft though
seems to be related to https://github.com/faster-cpython/ideas/issues/485
Has there been any efforts to writing GIL alternatives
I heard about something like that a while back but never followed up
I used lispy to solve aoc day 9
it's... terribly inefficient lol
it ate 250 mb of memory and took 10 minutes to run
I have no idea how long part 2 will take
ooh register based cpython
it runs in 4 seconds now with two pretty simple fixes
mm
So I'm working on if expression extraction```py
def foo():
print("Bar")
foo()
if "Test":
print("Hello, World!")
if False:
print("Hello, World!")
Is converted into
```py
def foo():
print('Bar')
foo()
print('Hello, World!')
I still want function body extraction
Wdym function body extraction
Inlining?
Doesnt seem eosteric, but good job 👍🏼
What if the person overwrites the function later on, then there will be unexpected consequences
Nobody cares
estoeric doesnt care about any consequences
basically ```py
@inline
def x():
print('Hi!')
for i in range(0, 100):
x()
topy
for i in range(0, 100):
print("Hi!")
Ah, i think I know a way to do this
I did something like it awhile ago
Well couldnt find my project, but did find this: https://github.com/orf/inliner You could look through the code, and devlop a cleaner way
I can be waaay cleaner
I have access to all python files in someones project
as my project is basically what typescript is to javascript for python
adding generics, compile-time execution (meant to do complex maths), and more!
class SomeClass[K, V]:
def __init__(k: K, v: V):
self.k = k
self.v = v
There is a pep about that feature, but it uses [K, V] instead of <K, V>
okay
ill add it
anyways ill need to make my own python parser
<K, V> matches c++ templates though
you can always use the poc branch for pep 695
I like class Spam[T]:
proof of concept
but what about subclasses
!pep 695
it looks so weird
howd you do it?
no idea
So we need to duplicate typevar every time we subclass generic class (if we want to make subclass generic too)
def func[T](a: T, b: T) -> T:
...
this is so weird too
yeah
() after []
I love more current syntax for subclassing generics, it doesnt need duplicating typevar every time
But is is not possible to implement in pep695 :(
How pep695 suggests to declare typevar with bound?
So we still need to declare protocol if we want some specific behaviour from object
yes
also not gonna admit to be being a time traveller but it is weird how similar this is to pep 695 https://gist.github.com/Gobot1234/4683b61800769a681d96cae70ece2366/ce4d4fbe477696b8375eb071240696e2bcc5e3b6#better-typevar-syntax
In c++ there is some good idea about requiring some behavior from object (iirc it is called require)
If some code compiles then type is good for this function, if it isnt - type is not good
I live all these ideas, but i dont understand PhantomType. Can you give some examples?
itd just be a subclassable version of Annotated you could use at typechecking time
I dont see why it can be useful
its something that d.py could use idr what use case i had for it
ideally the range class would just be
class Range[MinT, MaxT](PhantomType[int, MinT, MaxT]): ...
Ok got it
It requires 1 to be a valid type so you can do Range[1] instead of something like Range[Literal[1]]
No
would also probably be useful for https://github.com/antonagestam/phantom-types
Annotated accepts any expressions, not only types
actually it wouldnt be useful here anymore cause discord added str to the list of types that work with this
pythons generic syntax is ugly
i made an Include function which adds a object or module to the scope
there's also a repl which only uses python's tokenizer, so you don't need the junk operators to make the syntax work
@old socket what about this for interop lol
??
you're probably looking for #❓|how-to-get-help
This is poggers
Now finish all the stuff you need to bootstrap
Wait is Hy bootstrapped?
Or was that another PVM language
wonderful
excellent! do you also plan for using custom codecs to make that work for script files?
how so? I'm curious how that would work
you can load a codec, and then import your "main" script that has # coding: mycodec
oh huh
and it could be added to site-packages for autoloading the codec
lol thats actually pretty cool
you also don't need to even worry about the lexer
although that's not a problem since it just creates error tokens on invalid input
I'll definitely look into that later
my current parsing function is actually pretty simple
def lispy_parse(readline: Callable[[], bytes]) -> Node:
root = Node([], None)
node = root
for token in tokenize.tokenize(readline):
type_, string, *_ = token
if type_ == tokenize.OP and string == "(":
new = Node([], node)
node.children.append(new)
node = new
if type_ == tokenize.OP and string == ")":
assert node.parent
node = node.parent
if type_ == tokenize.NAME:
node.children.append(Name(string))
if type_ in {tokenize.NUMBER, tokenize.STRING}:
node.children.append(Const(ast.literal_eval(string)))
return root
@quartz wave @fleet bridge I just pushed a bunch of fixes to fishhook, including hooking class variables, staticmethods, and classmethods. pushed as version 0.2.8.post2
nice
means that you can hook __class_getitem__ much easier now
>>> @hook(list)
... @classmethod
... def __class_getitem__(cls, arg):
... print(cls, arg)
... return orig(cls, arg)
...
>>> list[int]
<class 'list'> <class 'int'>
list[int]
a personal favorite for this is that I can do this now: ```py
from fishhook import *
from ctypes import c_char@hook.cls(memoryview)
... class extend_memoryview:
... @classmethod
... def from_address(cls, addr, size):
... return cls((c_char * size).from_address(addr)).cast('b')
... @classmethod
... def from_object(cls, obj):
... addr = id(obj)
... size = type(obj).sizeof(obj)
... return cls.from_address(addr, size)
...
x = bytearray(8)
mem_x = memoryview.from_object(x)
mem_x[:-9].cast('P').tolist()
[1, 4424715984, 8, 9, 4418720080, 4418720080, 0]```
aoc day 9 using lispy https://github.com/dzshn/aoc2022/blob/main/09/pt2.lpy
I love how it sort of grew into somewhat of an actual language lol
I didn't do it the python import way cuz I already did python and it would technically be python
still its not hard to convert
decided to do that so I can post it
pyright loves it
works
awfully slow but works
Nice
Hello there,
Apologies for the possibly non-sense question, but I'd like to understand if there is an explicit (decent method) to determine whether my args[0] is the self object.
I'm building a decorator to parse the inputs and I'm now got into this challenge.
you're decorating a function and trying to determine whether the function is a member function?
like maybe at decoration time?
check if the function has a __func__ or __self__ attribute
if it does, its bound to an instance
you can also check its type
No, I'm creating a decorator that has a much bigger breath of work behind.
I built it and it works smoothly up and until it's used with plain functions.
However, when the decorator is used within a class, being the arg[0] the self with reference to the object, I got a behaviour which I didn't think about at first.
if its type is <class 'method'>, its bound to an instance
if its type is <class 'function'>, its unbound
A type check returns me the str or in any case the representation of the object. I cannot create infinite cases ... that's why I was hoping for something smart
My bad ... I mean __repr__
it still doesnt...
.
type(obj) returns obj.__class__
if you print that, it will call repr or str
but by itself, it doesn't do either of those
code
!e ```py
def decorator(f):
if hasattr(f, 'self'): print(f.self)
def inner(*a, **k):
return f(*a, **k)
return inner
@decorator
def decorated(*a, **k):
print(a, k)
class Whatever:
@decorator
def decorated(*a, **k):
print(a, k)
decorated("test", ktest=1)
Whatever.decorated("test", ktest=2)
w = Whatever()
w.decorated("test", ktest=3)
d = decorator(w.decorated)
d("test", ktest=4)
@vague cairn :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | ('test',) {'ktest': 1}
002 | ('test',) {'ktest': 2}
003 | (<__main__.Whatever object at 0x7fdd3894c910>, 'test') {'ktest': 3}
004 | <__main__.Whatever object at 0x7fdd3894c910>
005 | (<__main__.Whatever object at 0x7fdd3894c910>, 'test') {'ktest': 4}
it only has a .__self__ when you decorate it after it's bound to an instance.
Ok ... let me post the code that is giving me some troubles.
def _get_signature(*args, **kwargs):
"""Build the signatures from the callee."""
sig = []
vals = []
# Positional args
try:
for arg in args:
sig.append(type(arg).__name__)
vals.append(arg)
except:
pass
# Keywords args
try:
for name, val in kwargs.items():
sig.append(name)
vals.append(val)
except:
pass
return tuple(sig), tuple(vals)
so why does this cause troubles?
here I'm literally parsing the arguments of the callee.
To return both the type and the value in a single line.
Now, I later use sig and vals for some parsing ... but the whole point is that here I should avoid args[0] being the "self" to added to my list
I can see @vague cairn having posted something, and I need to explore that, but my function _get_signature is not recalled immediately
And I might have already lost the reference to the callee at this stage
why not just:
def dec(func=None, method=False):
if method:
def innerdec(func):
# do decorator stuff
def inner(*args, **kwargs):
# do inner func stuff
return inner
return innerdec
# do decorator stuff
def inner(*args, **kwargs):
# do normal func stuff
return inner
then, if its a method that you're using dec on
@dec(method=True)
def somemethod(self):
pass
otherwise, just use as normal
@dec
def somefunc():
pass
seems a lot simpler than trying to introspect after the fact and figure out whats happening
But that's what I am doing. An introspector 🙂
In fact ... it's a dispatcher, introspecting parameter to determine what to call
Given a series of arguments... it can call func1 or func2, just to simplify
So cannot really change the logic pretending the user to tell me whether the decorator is used withing a class
Oh, my! we're talking method overloading?
I'm afraid yes. And I have done quite a good piece of work to date .. everything seems to work with functions. But now I've this small challenge of the "I'm in a class"
I can perhaps modify the args before recalling the wrapper
in that case, my suggestion would be to check the frames
If I delete completely the reference, I should be able to walk away
But how is it possible the decorated method within Whatever not to have the first argument being self
it looks to me like you cannot determine that you're in a class by looking at what dunders are defined for a function at decoration time. I'd guess that they are entirely normal functions until the class block ends and they get packaged.
Under normal circumstances it's first argument will still be self, just not named that, how much do you trust your users to name their self args according to tradition?
can you not just do
if hasattr(args[0], func.__name__) and getattr(args[0], func.__name__) is func:
# first arg is cls/self
where func is the function the decorator is used on
That's probably ideal, most users are sane (population of current chat context are an outlier and should not have been counted)
as long as they aren't doing something super stupid such as overloading their __getattribute__ to hide the attr, it should work
better yet, you can use object.__getattribute__
try:
fnc = object.__getattribute__(args[0], func.__name__)
if fnc is func:
# args[0] is self/cls
else:
raise Exception
except:
# not self/cls
something like that
Definitely not that insane 🙂
so this one is probably safer
Better safe than sorry, I agree
mhm
let me check ... putting togeter a small test because that doesn't sound like I have access to f.
give me a moment, pls
ok, I've repurposed the example of before and left two comments in between
from functools import wraps
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
# Is args[0] a self????
print(f'args: {args}, kwargs: {kwargs}')
return wrapper
@decorator
def decorated(*a, **k):
print(a, k)
class Whatever:
@decorator
def decorated(self, *a, **k):
# That's the incriminated method ... the self here
print(a, k)
decorated("test", ktest=1)
Whatever.decorated("test", ktest=2)
w = Whatever()
w.decorated("test", ktest=3)
d = decorator(w.decorated)
d("test", ktest=4)
When I'm inside the wrapper ... I don't have anymore access to func.
yes, you do
unless I don't declare with a nonlocal
unless you're manually deleting it, its still around
the example above is exactly what I'm testing, and I don't see func exsposed whe I'm in wrapper
I have outside .. as I said, if I declare with nonlocal it works though
>>> def f(a):
... def inner():
... print(a)
... return inner
...
>>> i = f(5)
>>> i()
5
>>>
discord/utils.py line 1147
def is_inside_class(func: Callable[..., Any]) -> bool:```
look at that
because the variable existed in the namespace where the function was declared, and it was never removed, it can be used inside the function
Ok, I'm back: It looks like calling sys._getframe(1) does give a different result for the code context that the decorator is being called from, its definitely possible to tell a module level call from a call inside a class or function, but it's not clear to me that we can tell that we're in a class block specifically, as opposed to inside a function or whatever.
Nice!
That's what we're looking for.
I'm indeed not deleting... Just check my example modified from @vague cairn's code above.
yes. in that case, func should still be available inside wrapper
Thanks ... though not sure what I'm looking at now ... I have to admit I've my limits, eh
well ok, yes ... now I wonder why in the debug console I couldn't get it
do doubt that decorators are mind bending.
Gotcha what the util.py function is doing ... I would say that I'm on the right track then
!e ```py
def decorator(f):
print(f.qualname , f.name)
def inner(*a, **k):
return f(*a, **k)
return inner
def Whatever2(*stuff, **other_stuff):
@decorator
def decorated(*a, **k):
print(a, k)
decorated(stuff, **other_stuff)
Whatever2("test", ktest=5)
@vague cairn :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | Whatever2.<locals>.decorated decorated
002 | (('test',),) {'ktest': 5}
I have to admit ... I started with a simple dictionary ... and then I was never satisfied how rigid that dictionary was.
Here I am ... I built an overloading decorator
in case that helps you build recognition code to play with .__qualname__
Silly question ... to get the color coding here that !e at the beginning doing the trick?
!e
def test():
pass
ah .. !e it's evaluation from the bot
```py
like this
```
works with any supported language
for example, C
struct whatever {
...
};
what they said, I can't type that fast
Well thanks for your support @versed eagle @vague cairn @astral rover
Really appreciated
welcome
np
Ok, just played around with staticmethod and classmethod
Here are my results:
def decorator(f):
###############################################
#with this code at the start of your decorator
if isinstance(f, (staticmethod, classmethod)):
reclass = type(f)
f = f.__func__
abstract_type_name = reclass.__name__
else:
reclass = lambda a:a
abstract_type_name = 'normal'
#
###############################################
qs = f.__qualname__.split('.')
qs.pop()
if qs: #not in module level
if qs[-1] == '<locals>':
print(f.__name__, 'local sub function of:', '.'.join(qs[:-1]))
else:
print(f.__name__, abstract_type_name, 'method of', '.'.join(qs))
else:
print(f.__name__,"module global function")
@wraps(f)
def inner(*a, **k):
return f(*a, **k)
##############################################
# and this code at the end
return reclass(inner)
# you can also decorate staticmethods and classmethods with no problem
# otherwise @staticmethod or @classmethod must be applied outermost in order to still be callable
##############################################
I noticed that the __qualname__ is matching also with your case 2 to 4 before ... and that doesn't make the approach suitable.
At least not for what I'm trying to do
I believe the easiest, and so far working approach, is the hasattr(args[0], func.__name__)
I mean, definitely do what you're comfortable with, and will accomplish what you need, I was sort of just filing a research report on getting around the error codes I found while poking around with adjacent possibilities...
!e very quick and dirty dispatch table ```py
import sys, inspect
def get_signature(frame):
argvals = inspect.getargvalues(frame)
args = tuple(argvals.locals.get(name) for name in argvals.args if name in (func.kwdefaults) or {})
+ argvals.locals.get(argvals.varargs) if argvals.varargs else ()
kwargs = argvals.locals.get(argvals.keywords) if argvals.keywords else {}
for name in argvals.args:
if name in func.__kwdefaults__:
kwargs[name] = argvals.locals.get(name)
return tuple(map(type, args)), tuple((k, type(v)) for k, v in kwargs.items())
_dispatch_table = {}
def dispatch(*args, **kwargs):
def dispatch_inner(func):
func_table = _dispatch_table.setdefault(func.name, {})
func_table[args, tuple(kwargs.items())] = func
def inner(*a, **k):
signature = get_signature(sys._getframe())
return func_table[signature](*a, **k)
return inner
return dispatch_inner
@dispatch(int, a=int)
def foo(*args, **kwargs):
print('t1', args, kwargs)
@dispatch(str, b=str)
def foo(*args, **kwargs):
print('t2', args, kwargs)
foo(1, a=2)
foo('a', b='val')
foo("A", a=3) # fails, no match
@rugged sparrow :x: Your 3.11 eval job has completed with return code 1.
001 | t1 (1,) {'a': 2}
002 | t2 ('a',) {'b': 'val'}
003 | Traceback (most recent call last):
004 | File "<string>", line 35, in <module>
005 | File "<string>", line 21, in inner
006 | KeyError: ((<class 'str'>,), (('a', <class 'int'>),))
basically that I was previously getting exceptions calling bar() in inner() with this setup:
class Foo:
@decorator
@classmethod
def bar(cls, value):
print(value)
nice
could obv have a more complex match system for generic dispatch
Hey @sick hound!
You either uploaded a .txt file or entered a message that was too long. Please use our paste bin instead.
crazy
More or less what I did, though I went for the method argument introspection rahter then the decorator one.
And I tried to implement some logic to "guess" what's the best signature I should use if a match is not found and methods with default arguments exist
Surely if I was getting paid for this, I should have not wasted all the time I did ... but it was a funny exercise to get me back into the Python coding
fair. actually, if you are doing it inside a class I wonder if a custom __prepare__ namespace would let you do some funky stuff
I'm sure there are tons of things that can be done to improve my code.
So far it's very "complex" but not necessarily very Pythonic. At least I believe so
I might end up sharing, and let you have a look if you are interested
After a lot of permutations and investigations I've determined that the only way to support @terse totem is to attempt dispatching to both signatures.
Otherwise we could test is_inside_class(func) and isinstance(func, classmethod) and do the right thing on the first try, but if we get wrapped with staticmethod after we've already processed dropping the unwanted reference to self or the reverse then we are dispatching on the wrong signature.
And we can't count on the user to put all a method's decorators in the same order every time.
I suppose we could state that "we aren't supporting @terse totem"
Or we could get around it by coming up with a format for declaring what class we're expecting for self, even though, in the middle of a class block, that isn't yet referable.
sure he does
thats why bro was benched for more than half the game
and the entire game last to last game
☠️
Off-topic channel: #ot2-never-nester’s-nightmare
Please read our off-topic etiquette before participating in conversations.
crazy
@rugged owlyou play chess?
Yes
Off-topic channel: #ot2-never-nester’s-nightmare
Please read our off-topic etiquette before participating in conversations.
Hahaha put esoteric code on main branch https://github.com/HRLO77/website/blob/main/backend.py#L79
backend.py line 79
<p>{('</p><p>'.join(c[:5])) + (lambda: f'<p><a href="{WEBSITE}/post/{id}" style="text-decoration:none;font-size:medium;font-family:sans-serif;color:cadetblue">Read more...</a></p>' if len(c) > 5 else (lambda: f'<br><br><p style="font-family:sans-serif">Attachment:<br> <a href="{WEBSITE}/resource/{file}">{file[53:]}</a></p>' if file is not None else '')())() if shortened else '</p><p>'.join(c) + (lambda: f'<br><br><p style="font-family:sans-serif">Attachment:<br> <a href="{WEBSITE}/resource/{file}">{file[53:]}</a></p>' if file is not None else '')()}</p>```

game_class.py line 31
print(f'\033[{self.cube}A\033[0m{self.TO_CHAR}\n' + f"\033[0m".join(f"\033[0m".join(i) for i in np.array(tuple(self.position.values()), dtype=str)[:self.cube**2].reshape((self.cube, self.cube))), end='\r'```
Can you run help() on the file where you call help?
ie call help on a module from within a module
Hello all,
I'm working on some introspection using the inspect module and the signature class.
In doing so, I'm storying the type of the parameter to later do an isinstance(obj, classtype). This means that my isinstance is not done within the method where the object is declared, but later on some other parts of the code.
As far as I can see, if my test is done against primitive objects (e.g. int, string) ... all works fine.
The problem arose when I'm trying to introspect compound objects like enumeration/enum that are stored in referenced modules.
In that case, I got an Exception for an unknown class. Any idea how to best use the isinstance for checking the adherence between a given variable and its belonging class?
from enum import Enum
class data_state(Enum):
ALL = "all"
FINAL = "final"
from inspect import signature
def foo(test: data_state):
print(type(test))
print(isinstance(test, Enum))
foo(data_state.ALL)
print(isinstance(data_state, Enum))
>>> True
>>> False
issubclass
code
!e ```py
from enum import Enum
class s(Enum):
p = 'foo'
print(issubclass(s, Enum))```
@rugged sparrow :white_check_mark: Your 3.11 eval job has completed with return code 0.
True
Thanks @rugged sparrow, my only other challenge now is that the code above is run within one module.
In my circumstance, I have the piece of code, referencing enums elsewhere, so when I'm testing for it the type of the class is always returning an Unknown error type.
Unless passing a reference to the original Enum, which I still don't know how to do it, do you see any other option?
I would need to see how your code works
yeah, quite challenging
That's what I'm going to get as an input
a Parameter for which I lost already all the reference to the type
No chances to Eval it too ... as the code does not know anything about where - in this case - the gsc_wrapper is .. or what it is
The parameter object doesn't hold a reference to the actual variable?
apparently not, unless I'm missing something
I wonder, if I used the wraps decorator, if I can get access to the parent
But I have access to the calling function ... so I might be able to traverse the arguments from there. But at this stage, I think I went already too far away from my knowledge
all I want, in fact, is verify whether a given value is within that Enum ...
1 in AnIntEnum doesn't work although it should
Idk if that got changed in 3.11
If you're trying to tell whether 1 is a value of AnIntEnum then you'd have to do something likepy 1 in [member.value for member in AnIntEnum.__members__.values()]
Subclassing IntEnum to do what that code does is a better idea
What is meant to do pyflp in this context?
It seems a parser but for particular files???
Haven't opened my IDE yet, is this anintenum part of the native Python?
!pypi pyflp
My library
@nimble mirage getting lost, sorry
import math,copy
i=0
forbidden_properties = ["__name__","__doc__","__loader__","__spec__","__package__"]
math_dict_copy = copy.deepcopy(math.__dict__)
for k,v in math_dict_copy.items():
if k not in forbidden_properties:
math.__dict__[f"func_{i}"]=v
math.__dict__.pop(k)
i+=1
print(math.func_10(1))
slight bit of trolling
lmao you can use spaces
oops messed up slightly
fixed
you can use any string, even if it has operators or whatever
but then it's impossible to retrieve the value using .
but you can setattr/getattr
You can use not strings too
!e ```py
class bruh:
pass
bruh = bruh()
setattr(bruh, 0, 4)
print(getattr(bruh, 0))
@gleaming timber :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 5, in <module>
003 | TypeError: attribute name must be string, not 'int'
@fleet bridge ^
!e
class bruh:
pass
@type.__call__
class Ü:
def __ror__(self, other):
return other
(bruh.__dict__ | Ü)[0] = 4
print(bruh.__dict__[0])
@restive void :white_check_mark: Your 3.11 eval job has completed with return code 0.
4
getattr still refuses to work though
do you need to use bruh.__dict__ | Ü
Yes, because bruh.__dict__ is a a mappingproxy which doesn't support item assignment.
and using __ror__ solves the problem?
Yes. There's a bug with the reflected operator dunders that makes them leak the underlying dict.
other should be the same mappingproxy, but it's a dict.
so thats just an exploit lmao
!e ```py
@type.call
class bruh:
pass
dict(bruh.dict)[(1, 2, 3)] = 4
print(bruh.dict[1, 2, 3])
@gleaming timber :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 7, in <module>
003 | KeyError: (1, 2, 3)
what
You are just creating a new dict from the class dict.
bruh
On an instance you can just normally assign to the __dict__
it is, because you @type.__call__ed it
!e ```py
class X:...
x=X()
x.a = 'b'
x.dict[0]=1
print(x.dict)
@fleet bridge :white_check_mark: Your 3.11 eval job has completed with return code 0.
{'a': 'b', 0: 1}
funny way to deduplicate lists
!e ```py
lst = [1, 2, 2, 3, 3, 2]
print([*{*lst}])
@gleaming timber :white_check_mark: Your 3.11 eval job has completed with return code 0.
[1, 2, 3]
If you want to keep order: [*dict.fromkeys(lst)]
!e
x = [1,45,2,4,1,3,2,5,1,3,4,2,56,1]
print([*{*x}])
print([*dict.fromkeys(x)])
@restive void :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | [1, 2, 3, 4, 5, 45, 56]
002 | [1, 45, 2, 4, 3, 5, 56]
<@&831776746206265384> ^
!cban 874571720185511957 racism
:ok_hand: applied ban to @daring granite permanently.
So many people are racist in eosteric 
Hey @visual crest!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
3.14/10
Hey @sick hound!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com
!e
print("Hi")
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hi
!e
_=lambda x:''.join(chr(int(''.join(str(len(k)-1)for k in o.split('͏'))))for o in x.split('͏'*2))
__builtins__.__dict__[_('͏͏͏͏͏͏͏͏͏͏͏͏͏')](_('͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏'))
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | Hello, World!Traceback (most recent call last):
002 | File "<string>", line 2, in <module>
003 | File "<string>", line 1, in <module>
004 | EOFError: EOF when reading a line
!e ```py
getattr(builtins, import("base64").b64decode(b"cHJpbnQ="))("Hi")
@gleaming timber :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | KeyError: b'print'
invisible characters?
yeah lol
nice
its supposed to print hello world, not gonna work with this bot
!e ```py
getattr(builtins, str(import("base64").b64decode(b"cHJpbnQ=")))("Hi")
but it works :))
@gleaming timber :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | AttributeError: module 'builtins' has no attribute 'b'print''
ill do non invis characters
Python Obfuscator>py pyo -i message.py -o message_3.py
[INFO] [20:57:09] [__main__.py:74] Obfuscating target file: message.py
[INFO] [20:57:09] [__main__.py:78] Output: message_3.py
``` a little obfuscator i made for it too
!e
_=lambda x:''.join(chr(int(''.join(str(len(k)-1)for k in o.split('_'))))for o in x.split('_'*2));__builtins__.__dict__[_('.._._..__.._..._.__.._._..__.........._..........')](_('.._._......__.._.._.__.._.._...__.._.._........__.._.._.......__....._.__...._.....__........_...__.._._..__.._._.........__.._._.........__.._.._..__....._.....__...._...__........._........__.._.._..__.._.._.....__.._._.........__.._._.__...._....__...._.....__....._..'))
o wait i know why
is it morse code
no, morse code would not support obfuscation of python files. morse code only supports a-z characters
this is the best way i could find
extended morse code?
no
here ill help explain
exec
101 120 101 99
.._._..__.._..._.__.._._..__.........._..........
converts "exec" to its binary numbers. then for each digit in each number, will add 1 dot multiplied by how big that digit is, then it will add another dot so it can also count the digit 0. through each digit it will add 1 underscore to end the set digit. then when the entire number is done, will add 2 underscores.
thats the encoding
!e
_=lambda x:''.join(chr(int(''.join(str(len(k)-1)for k in o.split('͏'))))for o in x.split('͏'*2));__builtins__.__dict__[_('͏͏͏͏͏͏͏͏͏͏͏͏͏')](_('͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏͏'))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello, World!
see, works with invis characters now :))
binary is fun :)
if you want to disguise that you're using print, there's a better way to do it
:p
!e
((_:=__builtins__).__getattribute__(_.__dir__().__getitem__((___:=__loader__.__bases__.__getitem__((__:=__spec__.__sizeof__().__class__().__invert__()))).__sizeof__(___.__subclasses__().__class__()).__invert__().__add__(__).__neg__()))("hello world"))
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
hello world

though that way is still obvious I'm printing stuff bc the string, that can be relatively easily turned into dunders by indexing into the names of dunders+builtins
you extract letters from them?
yep
well
I don't
but that's what you could do
!e
print((0).__add__.__name__[2])
!e ```py
print(repr.name[2:]+type(0).name)
@gleaming timber :white_check_mark: Your 3.11 eval job has completed with return code 0.
print
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
a
!e ```py
builtins.dictsum((().class.name[2], ''.class.name[2], (0).class.name))
@gleaming timber :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | TypeError: unsupported operand type(s) for +: 'int' and 'str'
!e
__=lambda _:''.join(chr(int(''.join(str('abcdefghij'.index(j))for j in i)))for i in _.split('_'));__builtins__.__dict__[__('bab_bca_bab_jj')](__('bbc_bbe_baf_bba_bbg_ea_de_hc_bab_bai_bai_bbb_ee_dc_ih_bbb_bbe_bai_baa_dd_de_eb'))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello, World!
i came up with a new method :))
heyo
i'm shit at this but can you guys help work your magic
i'll jot down as text real fast hold on..
def print_stars(rows,stars):
for i in range(rows):
if i % 2 == 0:
for j in range(1, stars+1):
print('* ', end = '')
print()
else:
for j in range(1, stars):
print(' *', end = '')
print()
def main():
stars = int(input("Enter stars: "))
rows = int(input("Enter rows: "))
print_stars(rows, stars)
main()
probably the fact taht esoteric causes people to go mental
whatchu want
hi sleepy
hi
i just want help obfuscating that to shit lol
hm
unreadable is what i'm talking 
wanna use my obfuscator?
but i'm not too good at it
this is what my obfuscator does
it doesnt' encode to bytes and then decode with a wonky slice right
__=lambda _:''.join(chr(int(''.join(str('͏'.index(j))for j in i)))for i in _.split(''));__builtins__.__dict__[__('')](__('͏͏͏͏͏'))
oop
!e
code
!e
__=lambda _:''.join(chr(int(''.join(str('͏'.index(j))for j in i)))for i in _.split(''));__builtins__.__dict__[__('')](__('͏͏͏͏͏'))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello, World!
that one line of code prints hello world
are there invisible characters within the strings?
yeah lol
without invis characters, it looks like this
my friend made this
and it does a similar
but the code can be revealed by just printing the string
mine better
ye
my interest is straying further away from esoteric python and more into internals
happens to the best of us
ah
you're here
i was waiting for you to come online since I didn't want to ping you
I've made a mostly working expression generator
given a value, it generates an expression that is equivalent to that value
for example:
Obfuscator(taken=False).ge(type("", (), {}))
creates the following output
Hey @versed eagle!
You either uploaded a .txt file or entered a message that was too long. Please use our paste bin instead.
@versed eagle i like it
:P
with things like mine, anyone could just replace exec with print
i just like to take a more compact approach, nothing that takes up so much space like yours lol
anyways im heading to bed, gn!
gn
the obfuscator is open source :)
it's written mostly by cereal (hes one of the few who actually know stuff about things, along with chilaxan, death.py, and a few others)
https://github.com/thatbirdguythatuknownot/sniplections/blob/main/obfuscator.py
well i mean you could ping me any time and i'd always look into it
ah
alr
some people aren't ok with being pinged randomly so i thought better safe than sorry lol
so i'm gonna have at least 2 weeks of vacation so the majority of the time i'll be active from 11 pm - 6 am (possibly much later too) and 10 am - 1 pm GMT (7 am - 2 pm, 6 pm - 9 pm local time)
alr
oh same actually
@quartz wave the pull has been requested now
also includes the fix for that one error in gdci
kk
Not obfuscated but golfed ```py
print('\n'.join(['* '(n := int(input('Enter stars: '))), ' '(n-1)](int(input('Enter rows: ')))//2))
i=input:print('\n'.join(['* '*(n:=int(i('Enter stars: '))),' *'*(n-1)]*(int(i('Enter rows: ')))//2))
i=input:print
How does that work? @versed eagle
I know that i now becomes a shortcut for input but what is this :print
that's mean to be a semicolon
I just typed it wrong
mb
though, you can do this
i:print('\n'.join(['* '*(n:=int(i('Enter stars: '))),' *'*(n-1)]*(int(i('Enter rows: ')))//2))=input
because annotations
!e
_:__import__('sys').stdout.write('Hello, World!\n')=exec
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello, World!
cool
Iirc you don't even need the =exec
20 million characters to print hello world
@vague cairn @rugged sparrow
So that's the code I was working on and for which you helped me figure out the latest bits.
https://paste.pythondiscord.com/ayuyugifas
I don't expect the code to be super perfect, but it works for the given cases and even in conjunction with a class usage. Haven't shared the cases here.
Likewise, I don't expect the code to be neat and clean (or super Pythonic), but it's my first attempt to write something more than a parser.
Anything that can be improved, feel free to suggest.
I will be creating a public git at some point.
After all I've load to learn.
Nice!
Very cool
First attempt at making hello world in dunders, anything I can improve?
(_:=object);print(_.__hash__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__()).__add__(_.__eq__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__())).__add__(_.__lt__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__()).__add__(_.__lt__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__()))).__add__(_.__or__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__())).__add__(' ').__add__(int.__pow__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__().__invert__().__neg__().__invert__().__neg__())).__add__(_.__or__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__())).__add__(_.__or__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__().__invert__().__neg__())).__add__(_.__lt__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__())).__add__(_.__dir__.__name__.__getitem__(__name__.__eq__(__name__).__invert__().__neg__())))
@rugged owl :white_check_mark: Your 3.11 eval job has completed with return code 0.
hello world
Was it the first comment after the review, or nice... Thanks for sharing I'll look at it 😂
get object and int using dunders
and print
and dont use a string literal
3 things
they're all minor changes though, since they're relatively easy to fix
overall, pretty good
one thing that you could do is not use a semicolon, but its good either way, semicolons or not are really more of a stylistic preference
The space ' '?
yeah
kk thank you
:)
Whats something I could use instead? 
__name__.__class__(__loader__.__base__).__getitem__(__annotations__.__ge__.__name__.__len__())
its just str(object)[6] lol
though I have just thought of a shorter way to do it
__import__.__doc__.__getitem__(__doc__.__le__(__spec__).__sizeof__())
!e ```py
print(debug.doc.getitem(name.len().sub(debug)))
@old socket :warning: Your 3.11 eval job has completed with return code 0.
1 Character shorter I think
relies on __name__ being a specific string, won't work in modules :P
!e
print(len("__import__.__doc__.__getitem__(__name__.__le__(__doc__).__sizeof__())"))
print(len("__debug__.__doc__.__getitem__(__name__.__len__().__sub__(__debug__))"))
@versed eagle :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 69
002 | 68
yours is shorter... but at what cost
Looking better? #bot-commands message
still need to get int, and probably replace object with something else
yes, very nice
But then using your logic as well __doc__ wouldn't work in certain modules
For example, you code doesn't work in Ipython
Yea
But it's really just a nit-pick
Oh wait, it's on __import__.__doc__
I'm getting an = though
huh
Oh
that would happen if __doc__ and __name__ are both strs
fixed it
now that i made it use __spec__ it should always return 16
which is the size of NotImplemented on CPython (and also None but thats not important)
Okay that fixed it
Wait, when is either of those two not a str? Is it None when not added
__doc__ defaults to None
Oh right
does it return ' ' on ipython now?
Yep
almost got a shorter one
this one is 70
__builtins__.__doc__.__getitem__(__name__.__rmod__.__name__.__len__())
this one is 71
i keep getting close
__annotations__.__doc__.__getitem__(__name__.__ge__.__name__.__len__())
!e (:=object);print(.hash.name.getitem(name.eq(name).invert().neg()).add(.eq.name.getitem(name.eq(name).invert().neg())).add(.lt.name.getitem(name.eq(name).invert().neg()).add(.lt.name.getitem(name.eq(name).invert().neg()))).add(.or.name.getitem(name.eq(name).invert().neg())).add(' ').add(int.pow.name.getitem(name.eq(name).invert().neg().invert().neg().invert().neg())).add(.or.name.getitem(name.eq(name).invert().neg())).add(.or.name.getitem(name.eq(name).invert().neg().invert().neg())).add(.lt.name.getitem(name.eq(name).invert().neg())).add(.dir.name.getitem(name.eq(name).invert().neg())))
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
hello world
Is it possible to call a python function without adding frames to the stack?
you want tail call optimization?
then no
i wonder how hard it would be
i wrote a very basic tail call optimizer at one point, worked by transforming specific CALL_FUNCTIONs to JUMP_ABSOLUTEs
the hard part would be transforming arbitrary recursive functions into optimizable ones
would probably be easier to do with a import hook + ast then using bytecode
to deal with arbitrary recursive functions you need to use specialized tailcall opcodes
for that you can only dream 😢
Python?
@versed eagle forgot to mention you here too. Sorry pal
not if you wrote a system that could take an AST and build a control flow graph from it. then you can rearrange all of the segments the same way that compilers like GCC do tail call optimization
i think greyblue92 made one of these a while ago
aren’t control flow self contained in each function
you can’t jump from one function to another
or am i wrong about how it work?
You can analyze them and merge them
It will require some hefty compiler techniques though
so basically if f1 calls f2 and f2 calls f3 then we can inline f2 and f3 in f1?
this quickly became #internals-and-peps talk lol
maybe but that's a little hard to do or to find out when to do
what font
How do I get started with creating words with dunders
I wrote a TCO decorator that doesn't mod bytecodes, it merely walks the stack until it finds either a call that was not a tail call, in which case it calls the wrapped function as normal, or if it finds a copy of itself, it raises a custom error with the function and args needed to continue processing, then that previous copy of itself catches the exception and trampolines to the wrapped function.
This does not strictly fit the question 'without adding frames to the stack' but it can fit the accounting of 'has a chance to remove lots of irrelevant frames from the stack'
I'm not seeing my polished code in my archive, but here's my lab notebook on the topic, and I haven't updated it to deal with 3.10 and 3.11 bytecode changes if any. https://paste.pythondiscord.com/eyapiheqij
how does this work? are you just getting the first letter of these functions and adding them together?
Especially since there are so many dynamic ways you can call those functions
hm? i was just testing something
ye
def f():
def a():
return 1
return 2
def m():
...
is there any way to access a from m?
well no
the function is recreated each time f() is called
so you only get the code object somewhere in co_consts
search for the code object in f.__code__.co_consts
would be easier if it was the first or last (or only) function in f() which would have you search the first code object from left or right respectively
okay got it ty
another alternative is yk just return a()
since when was (:=object) valid
i thought it only would be valid if its (VARNAME:=VALUE)
lol
There's probably an undercover used
It will have just disappeared as markdown formatting
yeah
cause they didn't put backticks around the code
it's not
i see
👍 thanks for clearing up confusion
np
my code* 
ah
they reposted your code
edited
is this faster than print??
_:__import__('sys').stdout.write('Hello, World!\n')=exec
@rugged owl :white_check_mark: Your 3.11 timeit job has completed with return code 0.
500000 loops, best of 5: 516 nsec per loop
!timeit
_:__import__('sys').stdout.write('Hello, World!\n')
@sick hound :white_check_mark: Your 3.11 timeit job has completed with return code 0.
20000000 loops, best of 5: 12.1 nsec per loop
👀
Wth
@versed eagle 
doesn't need to deal with flushing maybe
impressive ngl
wut
nvm 
@sick hound :white_check_mark: Your 3.11 timeit job has completed with return code 0.
10000000 loops, best of 5: 24.4 nsec per loop
code
!timeit
def f():
_:__import__('sys').stdout.write('Hello, World!\n')
f()```
@sick hound :white_check_mark: Your 3.11 timeit job has completed with return code 0.
2000000 loops, best of 5: 162 nsec per loop
yeah cause it doesn't have to flush buffers until the end
also, it doesn't have to actually import sys, just has to retrieve it from memory since sys is already internally imported iirc
well yeah having to call a function each time would make it slower
though there its defining the function each time as well
probably better to define the function in setup
i found a terrifying discovery
i found a way to hide python code completely in notepad, it doesnt show up unless u delete the hidden characters
i tried to google and see if anyone has found out this exist but couldnt find anything
its a unicode character that will hide an entire line from being seen. but u can see it in ides and editors such as notepad++, atom, visual studio
anyways
!e
from inspect import getsourcelines as a,currentframe as b;exec(a(b())[0][0][82:])#print("Hello, World!")
@sick hound :x: Your 3.11 eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | File "/usr/local/lib/python3.11/inspect.py", line 1252, in getsourcelines
004 | lines, lnum = findsource(object)
005 | ^^^^^^^^^^^^^^^^^^
006 | File "/usr/local/lib/python3.11/inspect.py", line 1081, in findsource
007 | raise OSError('could not get source code')
008 | OSError: could not get source code
o wait forgot
!e py import dis def outer(x): def inner(): return x return inner dis.dis(outer)
@magic wraith :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | 0 MAKE_CELL 0 (x)
002 |
003 | 2 2 RESUME 0
004 |
005 | 3 4 LOAD_CLOSURE 0 (x)
006 | 6 BUILD_TUPLE 1
007 | 8 LOAD_CONST 1 (<code object inner at 0x7f6c194d4ab0, file "<string>", line 3>)
008 | 10 MAKE_FUNCTION 8 (closure)
009 | 12 STORE_FAST 1 (inner)
010 |
011 | 5 14 LOAD_FAST 1 (inner)
... (truncated - too many lines)
Full output: https://paste.pythondiscord.com/inoqewitin.txt?noredirect
!e
"""Hello"""
print(__doc__)
@sick hound :white_check_mark: Your 3.11 eval job has completed with return code 0.
Hello
Micro optimization on another level 👀
>>> dir(__name__).__sizeof__()
696
>>> __name__.__dir__().__sizeof__()
688
Victor Mono Nerd patched
Do you know why those two are different? Shouldn't it be the same
Running this on my end is 680 bytes for both, is this 3.11 or 3.10
No clue, would have to look in deeper.
They don't return the same thing either; dir() sorts the output. I'm guessing it might create a list and fill it with the (sorted) contents of __dir__(), thereby slightly overallocating..
yeah because dir sorts it
oh nvm L3v already said that
!e ```py
print(name.dir() == dir(name))
print(sorted(name.dir()) == dir(name))
print(sorted(name.dir()).sizeof())
print(dir(name).sizeof())
@old socket :white_check_mark: Your 3.11 eval job has completed with return code 0.
001 | False
002 | True
003 | 696
004 | 696
Oh I see

yeah
it is a bit weird to me that dir() isn't just a wrapper to its dunder like the other methods
for example, repr returns __repr__
doesn't change any of it
weird that dir doesn't do the same
does .__dict__sort?
iirc vars() is the equivilant of .__dict__()
Until told I have no clue dir even sorted
Yea I thought it was just like repr and repr
yeah vars just returns .__dict__
dir is an outlier
you know what they should do?
they should make the sorting be part of object.__dir__
so that dir is just like the other methods, where its simply a wrapper for the dunder
it would be much more consistent with the others
Would make sense overall too
yeah
since no one (except for us esoteric nerds) is using the __dir__ directly, they're all using dir()
so it wouldn't break any existing code
I'm not familiar with how the dot-notation searches through an objects namespace but, does sorting __dict__ somehow make it faster or
Oh never no that was a stupid question lol
Ignore that
I was confusing a few of the words since they look close
Has anyone written something that automatically converts stuff into dunders?
Im trying to make one, but it takes like 60 seconds for 1 number 
i've contributed to his thing also
lemme give you a link
brb
So he manually caches small stuff like 0, 1, True, etc.
yep
pretty neat, ill have to look into it more
when you get something it stores it in a cache

