#esoteric-python

1 messages · Page 66 of 1

brisk zenith
#

so, not perfect. still, good attempt. :D

rugged sparrow
#

damnit

#

ill find a better one

brisk zenith
#

None: True.__dir__().__class__().sort()

rugged sparrow
#

nice

brisk zenith
#

reckon there's a way to get Ellipsis? i believe it's only referenced a couple times in the standard library. i think for sure that's gonna be the hardest one if we try for it.

rugged sparrow
#

lets get the rest of them first lol

brisk zenith
#
>>> ....__class__
<class 'ellipsis'>
>>> 

this is still trippy to type :D

rugged sparrow
#

weird af

#

what is it even used for?

brisk zenith
#

in the standard library, pretty much fuck-all. it's used to represent a list that contains itself. it's also very common in numpy for array indexing

#

!eval ```py
a = []
a.append(a)
print(a)

night quarryBOT
#

@brisk zenith Your eval job has completed.

[[...]]
rugged sparrow
#

oh for printing recursive stuff out?

brisk zenith
#

i'm not sure if it actually uses an ellipsis object for that and if there's any way to get it from that, but i've heard that python2 crashed when you printed a list containing itself cause ellipsis wasn't a thing then

#

yeah, it works for tuples too. (don't ask how you get a tuple inside of itself :D)

rugged sparrow
#

wait

#

how tf would you do that

brisk zenith
#

short answer: ctypes.pythonapi.PyTuple_SetItem

rugged sparrow
#

ah. ctypes

brisk zenith
#

long answer: ```py

from ctypes import c_void_p,c_ssize_t,pythonapi
a = (0,)
pythonapi.PyTuple_SetItem(c_void_p(id(a)),c_ssize_t(0),c_void_p(id(a)))
a
((...),)
a[0] is a
True

rugged sparrow
#

the magic wand of python

brisk zenith
#

code stolen from @pine edge

#

but yeah, PyTuple_SetItem is used internally when building tuples from literals, for example. they don't just appear out of nowhere after all.

#

just so happens that it's a public function in the pythonapi :D

rugged sparrow
#

nice

pine edge
#

i'm pretty sure you can then pickle, then restore that fucked up tuple

brisk zenith
#

sounds reasonable enough. wonder what the __reduce__ method of these types looks like

#

would be interesting to see if they handle it specially or if it just seems to work

#

i'm betting on the latter

rugged sparrow
#
>>> a = (0,)
>>> pythonapi.PyTuple_SetItem(c_void_p(id(a)),c_ssize_t(0),c_void_p(id(a)))
0
>>> a
((...),)
>>> a.__reduce__
<built-in method __reduce__ of tuple object at 0x030F8690>
>>> a.__reduce__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\chilaxan\AppData\Local\Programs\Python\Python37-32\lib\copyreg.py", line 65, in _reduce_ex
    raise TypeError("can't pickle %s objects" % base.__name__)
TypeError: can't pickle tuple objects
>>>```
brisk zenith
#

huh

#
>>> import pickle
>>> pickle.dumps(())
b'\x80\x03).'
>>> 
#
>>> import pickle
>>> pickle.dumps(())
b'\x80\x03).'
>>> from ctypes import c_void_p,c_ssize_t,pythonapi
>>> a = (0,)
>>> pythonapi.PyTuple_SetItem(c_void_p(id(a)),c_ssize_t(0),c_void_p(id(a)))
0
>>> pickle.dumps(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while pickling an object
>>> 

fascinating :D

rugged sparrow
#

thats weird

brisk zenith
#

i just found a builtin so mysterious that i've never heard of

#

in 3.7.2, object.__subclasses__()[45]

#

PyCapsule

#
Capsule objects let you wrap a C "void *" pointer in a Python
object.  They´re a way of passing data through the Python interpreter
without creating your own custom type.

Capsules are used for communication between extension modules.
They provide a way for an extension module to export a C interface
to other extension modules, so that extension modules can use the
Python import mechanism to link to one another.
rugged sparrow
#

what

#

thats cool

brisk zenith
#

TIL

rugged sparrow
#

@brisk zenith do you think you could do anything tricky with it?

brisk zenith
#

well, you can't make instances of it, but i'll look up how to use it.

#

of course i've never seen it, i haven't read through the entire c-api docs yet

#

wow that makes me actually seem like i try to be relatively smart

rugged sparrow
#

hahaha

brisk zenith
#

when in fact i just procrastinate actually being smart

#

exams in a month? nah, ctypes and segfaults.

#

👌

rugged sparrow
#

hey ive got finals soon to

brisk zenith
#

here's an interesting: golfed segfault

#

wow i'm a new breed of tired, "here's an interesting"

rugged sparrow
#

lmao

#

go to sleep then

brisk zenith
#

nah it's good i've got people to talk to

rugged sparrow
#

nevermind then

brisk zenith
#

:D

#

__import__("ctypes").string_at(0)
this is, i suppose, the naïve first approach. it's hella short but could it be shorter? maybe.

rugged sparrow
#

prob

brisk zenith
#

haha

#

import os;os.kill(os.getpid(),11)

#

exact same length

#

but i don't count that as being a valid attempt as it's not a true segfault

rugged sparrow
#

true

brisk zenith
#

it's telling the interpreter that it's segfaulted and should probably fuck off, rather than actually segfaulting

rugged sparrow
#

quote of the day right there

brisk zenith
#

thank you

#

when i'm tired my vernacular comes out and i use a lot of colourful language :D

rugged sparrow
#

btw your first one didnt segfault my interpreter

brisk zenith
#

did it not? it really should have.

rugged sparrow
#
>>> __import__("ctypes").string_at(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\chilaxan\AppData\Local\Programs\Python\Python37-32\lib\ctypes\__init__.py", line 497, in string_at
    return _string_at(ptr, size)
OSError: exception: access violation reading 0x00000000
>>>```
#

the wonders of windows

brisk zenith
#

ah

#

segfault == access violation

#

it'll suffice

rugged sparrow
#

didnt crash the interpreter tho lol

brisk zenith
#

doesn't matter, still a segfault :D

rugged sparrow
#

aight lol

brisk zenith
#

if we wanted to crash the interp-- wait no that would crash the entire computer

#

i suppose crashing the computer would also crash the interpreter :D

rugged sparrow
#

that would be a top-notch golf

#

would a fork bomb count?

brisk zenith
#

absolutely :D

#

but let's not post any of those here haha

#

now that sounds like an otname

rugged sparrow
#

haha

#

true

#

@brisk zenith yo do you want to continue getting all the classes from True?

brisk zenith
#

sure in a bit, just gonna hop into bed and procrastinate sleeping. give me a moment :D

rugged sparrow
#

cause i say we allow using more than one True

#

aight

brisk zenith
#

well then what's stopping us from doing what we did yesterday?

#

i think one True is a good restriction

rugged sparrow
#

we cant use forloops

brisk zenith
#

i wanna see how far we can get first :D

rugged sparrow
#

aight

#

how many do we currently have?

brisk zenith
#
bool: True.__class__
int: True.__class__.__base__
str: True.__doc__.__class__
float: True.__float__().__class__
object: True.__class__.__base__.__base__
tuple: True.__class__.__bases__.__class__
list: True.__dir__().__class__
bytes: True.__doc__.encode().__class__

# not types but still significant bits and bobs:
False: True.imag.__bool__()
NotImplemented: True.__subclasshook__()
None: True.__dir__().__class__().sort()
rugged sparrow
#

complex
set
frozenset
dict
module
function
method
code

#

we still need these from our original list then

brisk zenith
#

yup

#

just tested all of our current ones on pydroid, they work fine

rugged sparrow
#

nice

#

@brisk zenith tbh we should get NoneType instead of None

#

True.__class__.__class__ -> type

sick hound
#

import ctyes as c;c.string_at(0) @brisk zenith made it shorter 😛

#

nevermind I can't spell

snow beacon
#

from ctypes import*;string_at(0)

#

Same length, but no typo

snow beacon
#

Oh, and dict is True.__class__.__prepare__().__class__

snow beacon
#

Are we trying to golf this?

grave rover
#

Are we trying to get every builtin from True?

grave rover
#
>>> True.__class__.__class__(True.__repr__(), True.__class__.__bases__, True.__class__.__prepare__())
<class '__main__.True'>```

Custom classes: check
#

I doubt we can get a function/method tho

#

With result we also can't get code/module

#

Actually

#

Nvm, True.__class__.__class__.mro.__class__ said method but it's a method_descriptor

#

True.__class__.__dict__.__class__ for mappingproxy

snow beacon
#

I don't think we can use more than one True

#

And we only care about the main builtins

grave rover
#

Trying to use these to get others :p

snow beacon
#

I made a test script that I hope checks every possibility. Any class not in {'dict', 'bool', 'list_reverseiterator', 'int', 'builtin_function_or_method', 'bytes', 'str_iterator', 'tuple_iterator', 'str', 'method_descriptor', 'NotImplementedType', 'method-wrapper', 'list', 'object', 'mappingproxy', 'wrapper_descriptor', 'list_iterator', 'type', 'tuple', 'NoneType'} takes at least two attribute accesses.

#

If anyone wants to use my terrible quality code, ```python
unchecked = [True]
checked = []
checked_classes = []

def thorough_dir(cls):
#creates a list of attributes a class implements
#does not support arbitrary objects, only types
#unlike dir(), does not sort the results
#(stolen from another project which is why it has comments)
attributes_found = []
all_superclasses = cls.mro
for superclass in all_superclasses:
#appends the keys of dict to the list
attributes_found += superclass.dict
return attributes_found

for i in range(5):
print(unchecked)
to_check_after = []
for value in unchecked:
print(value)
dir = thorough_dir(value.class)
for attribute in dir:
try:
print("", attribute)
result = value.class.getattribute(value, attribute)
to_check_after.append(result)
if hasattr(result, "call"):
called = result()
to_check_after.append(called)
except Exception as e:
print(i,"!", e)
checked += [value for value
in unchecked
if value not in checked and value.class not in checked_classes]
checked_classes = [obj.class for obj in checked]
unchecked = to_check_after
print({type(x).name for x in checked})``` I'm going to bed.

desert garden
#

In order to fudge something, I've done ```py
sys.modules[name] = instance_of_a_class

#

Is there a way to make that work for from .. import * though?

rugged sparrow
#

@desert garden you'd need to mess with __import__

desert garden
#

In what way?

rugged sparrow
#

dunno

#

would need to research it

desert garden
#

Okay, found a bodge that does what I need for this context

#

I just iterated the object, and anything that didn't start with _ I defined onto builtins

rugged sparrow
#

nice

calm rampart
#

@desert garden you could probably make the instance's __dict__ globals()

#

however

desert garden
#

globals() is bound to the module so you'd have to apply it from within the importing code

calm rampart
#

import * still won't give you bound methods... maybe if you add their names to __all__

desert garden
#

I just did ```py
def apply(object):
import builtins
for i in dir(object):
if i.startswith('_'):
continue
setattr(builtins, i, getattr(object, i))

robot = Robot()
apply(robot)
sys.modules[name] = robot

calm rampart
#

ok i think you're not quite getting what i'm suggesting

desert garden
#

Then I can ```py
import robot

enableControls() # Works
robot.enableControls() # Also works

calm rampart
#

ok wait

#

maybe you can...

#

ok if your type is layout-compatible with module (i.e. no __slots__, not a ctypes struct, not a subclass of most built-in types)...

#

you can do this: ```py
import types
import sys

class RobotModule(types.ModuleType):
def new(self):
raise Exception("RobotModule type not intended to be used this way")
def enableControls(self):
print("enabled controls")

_self = sys.modules[name]
self.class = RobotModule
for method in dir(RobotModule):
if not method.startswith('
'):
globals()[method] = getattr(_self, method)

#

then you can do py from robot import * enableControls()

#

you can also simply add enableControls to __all__

#

actually, adding it to __all__ works in all cases for import *, e.g. ```py
import sys

class RobotModule:
def init(self):
self.all = ['enableControls']
def enableControls(self):
print("enabled controls")

_self = sys.modules[name] = RobotModule()

#

making the instance the real module (if it is compatible with the module type), or sharing its __dict__ with globals() (for any other type) would be a viable way to get other top-level things defined in the file to show up.

#

if you do define __all__ you'd need to add all of the other names to it as well

#
import sys

class RobotModule:
    def __init__(self):
        self.__dict__ = globals()
    def enableControls(self):
        pass

def global_function():
    pass

_self = sys.modules[__name__] = RobotModule()
__all__ = [x for x in dir(_self) if not x.startswith('_')]
#

@desert garden any thoughts?

desert garden
#

Oh right, I see what you mean

#

In that second one, would global_function be exported too?

calm rampart
#

yes

desert garden
#

I don't want that, but I take it the first one doesn't?

calm rampart
#

well

#

if you don't want it you could define it with an _

#

or have an explicit __all__ that doesn't include it

#

tbh the normal way to do what you're trying to do is probably to simply define __all__ with the names you want, and define them all at the top level. A custom module class is normally only used if you want to be able to do e.g. operator overload on the module (to be able to treat a single-function module like a function, for example)

desert garden
#

Yeah, I'm pretty sure what I'm doing is a horrible anti-pattern 😄

#

Said robot object then has stuff like robot.drive(left, right), robot.reverse(robot.left), etc., and I'm just trying to avoid having a load of globals to store state

calm rampart
#

ok well

#

what i might do in that case is

#

see what you're doing right now limits you to one robot object, so you don't really get the benefit of not having globals

#

hold on

#

Something like this... ```py
import sys

class Robot:
def init(self):
self.dict = globals()
def drive(self, direction):
pass
def reverse(self, direction):
pass
def enableControls(self):
pass
# etc

_default_instance = Robot()
def wrap(methodname):
return getattr(_default_instance, methodname)

for methodname in dir(deault_instance):
if methodname.startswith('
'):
continue
globals()[methodname] = wrap(methodname)


Then you *can* create an instance of the class, or you can just use the ones from the module and they'll be from the default instance
desert garden
#

Given that the robot refers to a literal hardware robot connected to the raspberry pi running it over GPIO, I don't have any plans to support more than one at once MarisaWink

calm rampart
#

ah

grave rover
#

does anyone know how to parse a long dumped by marshal.dumps?

#
>>> import marshal
>>> marshal.dumps(10**10)
b'\xec\x03\x00\x00\x00\x00d\x17(\t\x00'
>>> data = _
>>> long_ident = data[:1]
>>> long_data = data[1:]
>>> long_ident, long_data
(b'\xec', b'\x03\x00\x00\x00\x00d\x17(\t\x00')
#

first byte is datatype identifier

#

rest is the data

brisk zenith
#

might be related to how python stores ints as chunks of numbers less than 2**15 or 2**30

grave rover
#

I looked at the code and it just did bitshifts and bitwise and

brisk zenith
#

iirc you can see the longobject struct at /Include/cpython/longintrepr.h

#

might have comments explaining how they're stored

grave rover
#

but sadly I cant read C nor are there any comments about it

brisk zenith
#

hmm, what if you try using an int above 2**64?

#

also sorry @rugged sparrow i fell asleep lmao

#

are you trying to encode or decode?

grave rover
#

Trying to decode

#

Also can't open that cause it crashes phone

#

Basically what I need is some_function(long_bytes) -> value

brisk zenith
#

let's start with simple integers: ```py
b'\xe9\x00\x00\x00\x00' # marshal.dumps(0)

---- ---------------

size int value

---- ---------------

b'\xe9\x01\x00\x00\x00' # marshal.dumps(1)

#
>>> marshal.dumps((2 ** 31) - 1)
b'\xe9\xff\xff\xff\x7f'
>>> marshal.dumps((2 ** 31))
b'\xec\x03\x00\x00\x00\x00\x00\x00\x00\x02\x00'
>>> 
grave rover
#

Integers are easy, they're just struct.unpack("i")

#

But longs are 10 bytes somehow

brisk zenith
#

because they have arbitrary size.

#

lemme see if i can figure it out

grave rover
#

Oh?

brisk zenith
#

python longs (aka ints) can be as big as they want

#

(within reason)

grave rover
#

I thought they'd be 8-12 bits as described in struct docs

brisk zenith
#

!e ```py
import marshal
print(marshal.dumps(2 << 2048))

night quarryBOT
#

@brisk zenith Your eval job has completed.

b'\xec\x89\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x
... (truncated - too long)

Full output: https://paste.pythondiscord.com/pogucukixe

grave rover
#

Wew

#

First bit denotes something about size

brisk zenith
#

yes

#

the \xec probably means "hey this is a python integer"

grave rover
#

!e `import struct; print(struct.unpack("i", b"\x89\x00\x00\x00"))

night quarryBOT
#
Nah.

Sorry, but you may only use this command within #bot-commands.

grave rover
#

:(

brisk zenith
#

\x89\x00\x00\x00 is likely the size

grave rover
#

I'd expect it to be two, and have the actual data be a multiple of 4/8

brisk zenith
#

the first 5 bytes are type and size

#

so we can ignore those

#

the size of that int is apparently \x89 which is 137

#

the amount of bytes after the size is 274

#

137 * 2

#
/* We assume that Python ints are stored internally in base some power of
   2**15; for the sake of portability we'll always read and write them in base
   exactly 2**15. */
#

aha, as i suspected

grave rover
#

Wat

brisk zenith
#

which is why the length of the integer bytes on a 64 bit python is double the given size as i mentioned

#

on 64-bit machines a python integer is stored internally as chunks of less than 2**30

#

on 32 bit, that's 2 ** 15

grave rover
#

Hm

#

So 10**25 would be either (0, 5120, 1313, 12448, 22865, 264) if using 6H or (0, 0, 0, 20, 33, 5, 160, 48, 81, 89, 8, 1) if using 12B

brisk zenith
#

not sure

#

so, the value of python integers are stored as an array of C ints internally, yeah?

#

the marshal code constructs the pyobject by writing to that array. we can't do that without a bit of fuckery.

#

actually that's the wrong link maybe

#

(wow i'm tired) but yeah, you need to figure out how to get the value of that array as a python integer.

#

basically, python integers are far more complicated than you'd expect and probably requires quite a bit of strong brainthink

#

as for the marshalled bytes, that looks like an array of C shorts, perhaps.

rugged sparrow
#

@brisk zenith it's all good

grave rover
#

Six shorts it is then

grave rover
#

I got it Pog

grave rover
#

now I need to actually get shit to work right

#

specifically code objects

desert garden
#

I've got an environment that's had del __builtins__.__import__

#

Is there a way to import anyway?

#

_ is a filtered char that can't be used

#

Actually, the whole blacklist is ()[]{}_.#"'\ABCDEFGHIJKLMNOPQRSTUVWXYZ

#

Looking at it, things like lambda: ... are fine, but there's no way to then call that lambda

#

If this weren't a challenge to break out of the sandbox I'd want to say that evaling a string after that blacklist is safe, but clearly I'm wrong

sick hound
#

that's probably impossible

grave rover
#

What's a good way to reverse-engineer data packets from packets and partial expected data format?

brisk zenith
grave rover
#

I mean this is the only place that covers parsing bytes as useful data

#

¯_(ツ)_/¯

rugged sparrow
#

@brisk zenith i have a pretty decent challenge for you

#

make a function makeKeyword(keyWordName,keyWordValue) that returns nothing, but makes a new keyword that has the value given to it in the makeKeyword function that behaves like any keyword in python (like True)

#

ex: python makeKeyword('hello','hi there') print(hello) #prints hi there hello = 1 #throws an error about assigning to keywords or any error, so long as it isnt successful

rugged sparrow
#

its kinda like the Maybe challenge but doesnt have to have a random value

supple jasper
#

how heavily can you actually hack the production of bytecode? Could you make a keyword that changes, or introduces new functionality, and plays along with the other tokens that are close by? Something like... create a const keyword which would make it so that if you typed const a = 4 - then "a" would be a new keyword like you defined above?

snow beacon
#

Nah, that doesn't compile properly.

desert garden
#

If it gets through syntax processing and is built into the AST, the sky's the limit

#

As you can see, const: a = 4 would likely be workable because it got through syntax parsing

sick hound
#

wha-oh right, annotations

desert garden
#

Problem here is that annotations don't carry though into bytecode

sick hound
#

yes they do ```py

dis.dis('const: a = 4')
1 0 SETUP_ANNOTATIONS
2 LOAD_CONST 0 (4)
4 STORE_NAME 0 (const)
6 LOAD_NAME 1 (a)
8 STORE_ANNOTATION 0 (const)
10 LOAD_CONST 1 (None)
12 RETURN_VALUE```

grave rover
#

I could probably make use of that in BytePatches

grave rover
#

Like addAnnotationHandler

#

It rewrites the code into a LOAD_CONST(4) STORE_NAME(a) instead and runs annotation_funcs["const"]("a", 4, all_func_ops)

desert garden
#

It's important to actually dis a function itself because that's the form you're going to be getting your code objects in

brisk zenith
#

i wonder how you get the annotations from that then

desert garden
#

I'll have a look

#

There's probably a method in inspect

brisk zenith
#

you could dis the function source

desert garden
#

Thinking about it actually, the more "pythionic" way to do consts would be ```py
a: Const[int] = 5

#

And embrace the fucking awful type annotation syntax that they decided on

#

(Sidenote: Which dev looked at that and though "That looks nice, let's use that"??)

brisk zenith
#

probably some C# bellend

tropic gulch
#

how would you have done it instead?

desert garden
#

int a = 5

#

And instead of from typing import List, just modify the standard list object to work as a type annotation

#

And then probably do list<int> a = 5

tropic gulch
#

from __future__ import annotations kinda solves that

desert garden
#

Instead of the hell that is replacing List.__getitem__ and then doing a: List[int] = 5

brisk zenith
#

i thought the future import only allowed postponed evaluation of type annotations

tropic gulch
#

yeah, but then you can do things like a: list[int] apparently

brisk zenith
#

huh

desert garden
#

That seems like it would really fuck with a badly written interpreter

#

Because list.__getitem__ now do two different things

tropic gulch
#

🤷 or I might be wrong, but at least it doesn't complain about it

desert garden
#

It never has complained about it

#

It just doesn't actually work if you use a lower case l

tropic gulch
#
>>> a: list[int]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'type' object is not subscriptable
>>> from __future__ import annotations
>>> a: list[int]
brisk zenith
#

list.__getitem__ isn't the same as list().__getitem__

#

so i don't see the problem

sick hound
#

List[int], Dict[str, str] etc. uses

#

__class_getitem__ protocol

wild cairn
#
>>> a = lambda a: print(a)
>>> a.__annotations__["a"] = str
``` xD
lone ruin
#
from typing import NamedTuple, NamedTupleMeta

class ComponentTupleMeta(NamedTupleMeta):
    def __new__(mcls, typename, bases, ns):
        if NamedTuple not in bases:
            base = super().__new__(mcls, '_base_' + typename, (NamedTuple,)+bases, ns)
        else:
            base = super().__new__(mcls, '_base_' + typename, bases, ns)
        bases = (base, *(b for b in bases if not isinstance(b, NamedTuple)))
        return super(NamedTupleMeta, mcls).__new__(mcls, typename, bases, ns)

    def __add__(self, other):
        return f'{self.__name__} {other.__name__}'

class Component(metaclass=ComponentTupleMeta):
    pass


class Vector(Component):
    x: int
    y: int

    def __add__(self, other):
      return Vector(self.x+other.x, self.y+other.y)

a = Vector(1,1)
b = Vector(5,5)

print( (Vector + Vector) )

print( a + b )```

Vector Vector
Vector(x=6, y=6)

#

there are so many restrictions on what you can do with namedtuple subclasses but i managed to get operator overloads working on sub meta classes of namedtuple

#

also without having to make stuff like Vector inherit directly from namedtuple or have to specify a metaclass

brazen geyser
#

im taking baby steps towards writing a python vm

#

so far observing dis results to figure out how the instructions work

#

and i've already hit a bit of a block

#
>>> dis.dis("a = 1")
  1           0 LOAD_CONST               0 (1)
              2 STORE_NAME               0 (a)
              4 LOAD_CONST               1 (None)
              6 RETURN_VALUE
>>> dis.dis("a = 0")
  1           0 LOAD_CONST               0 (0)
              2 STORE_NAME               0 (a)
              4 LOAD_CONST               1 (None)
              6 RETURN_VALUE
>>> dis.dis("a = 12")
  1           0 LOAD_CONST               0 (12)
              2 STORE_NAME               0 (a)
              4 LOAD_CONST               1 (None)
              6 RETURN_VALUE
>>> dis.dis("a = '12'")
  1           0 LOAD_CONST               0 ('12')
              2 STORE_NAME               0 (a)
              4 LOAD_CONST               1 (None)
              6 RETURN_VALUE
>>> 
#

how does LOAD_CONST work in these examples? where are the constants stored? there's nothing in the bytecode that indicates how or why those particular values are the constant at index 0

sick hound
#

constants and names are stored on separate attributes of the code object

brisk zenith
#

as tuples

sick hound
#
>>> compile('a = 12', '<example>', 'exec').co_consts
(12, None)
>>> compile('a = 0', '<example>', 'exec').co_consts
(0, None)```
brazen geyser
#

hmm i see

#

so what about pycs?

brisk zenith
#

those are marshalled

#

you'd do marshal.loads(pyc_content[16:] i believe

#

the first 16 bytes are metadata

#

i think it's 8 or 12 bytes on python versions below 3.7 or something like that

brazen geyser
#

ohhh ok i see. since im gonna forego writing a compiler it's jus gonna work with pycs for now. so i guess ill have to write a marshal deserializer too

brisk zenith
#

not really

#

mashal.load and marshal.dump works just fine

brazen geyser
#

(not writing it in python)

brisk zenith
#

ah okay

#

@grave rover was doing exactly that (but in python) recently

#

but implementing it himself

brazen geyser
#

cool cool

brisk zenith
brazen geyser
#

ty

#

eep D:

brisk zenith
#

yeah it's pretty scary haha

brazen geyser
#

ok, i think instead of using pycs ill use some other easier to parse format

#

maybe some kind of pyc to json translator

brisk zenith
#

interesting.

calm rampart
#

is there a disassembler for the marshal format like pickletools.dis for pickle?

sick hound
#
>>> marshal.loads(b'\xfb\xdb\x00\x00\x00\x00\xda\x01b')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'```
brazen geyser
#
  2           0 LOAD_CONST               0 (<code object test at 0x0000024DC36FE030, file "<dis>", line 2>)
              2 LOAD_CONST               1 ('test')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (test)

  5           8 LOAD_NAME                0 (test)
             10 LOAD_CONST               2 ('poop')
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 LOAD_CONST               3 (None)
             18 RETURN_VALUE

Disassembly of <code object test at 0x0000024DC36FE030, file "<dis>", line 2>:
  3           0 LOAD_GLOBAL              0 (print)
              2 LOAD_CONST               1 ('lol')
              4 LOAD_FAST                0 (a)
              6 LOAD_CONST               2 ('whats up?')
              8 CALL_FUNCTION            3
             10 POP_TOP
             12 LOAD_CONST               0 (None)
             14 RETURN_VALUE
#

dis of this:

test_code = '''
def test(a):
    print('lol', a, 'whats up?')

test('poop')
'''
#

insert yo-dawg xzibit meme here

grave rover
#

@brazen geyser yo sup

#

parsing pyc is a pain

brazen geyser
#

heyy

#

yea i just noped the fuck out 😄

grave rover
#

I can send over my code for it later today

brazen geyser
#

ty, i appreciate it

#

for now what im doing is this instead of using pycs:

def code_to_json(code: str):
    compiled_code = compile(code, '<script>', 'exec')

    result = {
        'argcount': compiled_code.co_argcount,
        'cellvars': compiled_code.co_cellvars,
        'code': list(compiled_code.co_code),
        'consts': compiled_code.co_consts,
        'filename': compiled_code.co_filename,
        'firstlineno': compiled_code.co_firstlineno,
        'flags': compiled_code.co_flags,
        'freevars': compiled_code.co_freevars,
        'kwonlyargcount': compiled_code.co_kwonlyargcount,
        'lnotab': list(compiled_code.co_lnotab),
        'name': compiled_code.co_name,
        'names': compiled_code.co_names,
        'nlocals': compiled_code.co_nlocals,
        'stacksize': compiled_code.co_stacksize,
        'varnames': compiled_code.co_varnames
    }


    return json.dumps(result, indent=4)
#

but then it turns out you get code objects inside your code objects 😄

#

wow fun

brisk zenith
#

you certainly do, but i'm pretty sure they're only found in co_consts

#

so just iterate over that and apply it recursively if you find any code objects there.

brazen geyser
#

ye

#

hey what happens if you have more than 256 consts?

#

or names

brisk zenith
#

you get onto extended arguments

brazen geyser
#

oh geeze

brisk zenith
#

and you can have infinitely many of them in a row if you need to

#

also, lnotab isn't a list is it? it's a bytes object with special formatting

brazen geyser
#

it's bytes but json cant serialize bytes

sick hound
#

yes, but he listified it so it could be jsoned

brazen geyser
#

ye

brisk zenith
#

ah very well

sick hound
#
>>> vars
'aa,ab,ac,ad,ae,af,ag,ah,ai,aj,ak,al,am,an,ao,ap,aq,ar,(...),zs,zt,zu,zv,zw,zx,zy,zz'
>>> dis.dis(vars)
  1           0 LOAD_NAME                0 (aa)
              2 LOAD_NAME                1 (ab)
              4 LOAD_NAME                2 (ac)
              6 LOAD_NAME                3 (ad)
              8 LOAD_NAME                4 (ae)
             10 LOAD_NAME                5 (af)
             12 LOAD_NAME                6 (ag)
# ...
            500 LOAD_NAME              250 (ju)
            502 LOAD_NAME              251 (jv)
            504 LOAD_NAME              252 (jw)
            506 LOAD_NAME              253 (jx)
            508 LOAD_NAME              254 (jy)
            510 LOAD_NAME              255 (jz)
            512 EXTENDED_ARG             1
            514 LOAD_NAME              256 (ka)
            516 EXTENDED_ARG             1
            518 LOAD_NAME              257 (kb)
            520 EXTENDED_ARG             1
            522 LOAD_NAME              258 (kc)
# ...
           1524 EXTENDED_ARG             1
           1526 LOAD_NAME              509 (tu)
           1528 EXTENDED_ARG             1
           1530 LOAD_NAME              510 (tv)
           1532 EXTENDED_ARG             1
           1534 LOAD_NAME              511 (tw)
           1536 EXTENDED_ARG             2
           1538 LOAD_NAME              512 (tx)
           1540 EXTENDED_ARG             2
           1542 LOAD_NAME              513 (ty)
           1544 EXTENDED_ARG             2
# ...
           2164 EXTENDED_ARG             2
           2166 LOAD_NAME              669 (zy)
           2168 EXTENDED_ARG             2
           2170 LOAD_NAME              670 (zz)
           2172 EXTENDED_ARG             2
           2174 BUILD_TUPLE            671
           2176 RETURN_VALUE```
brazen geyser
#

how does that work? o.o

#

EXTENDED_ARG 2 means it's got 2 extra bytes right?

#

where are those stored?

sick hound
#

no

#
           2164 EXTENDED_ARG             2
           2166 LOAD_NAME              669 (zy)```
brazen geyser
#

ohhhh

#

you're loading it into the extended arg

#

i get it

#

... right?

#

ok nevermind

#

third time's the charm

sick hound
#

the actual bytes that do that are \x90\x02e\x9d

#
EXTENDED_ARG 2
LOAD_NAME 157```
#

so the bytes of the integer for the name that actually gets loaded are 2 157

#

(2 << 8) + 157 == 669

#

and 669 is the index of the name to actually load

#

the EXTENDED_ARG extends the argument of the next instruction

#

@brazen geyser

brazen geyser
#

OH i see

#

that's clever

brazen geyser
#

where is the code class located? is it possible to import it?

sick hound
#
from types import CodeType```
#

@brazen geyser

#

it also takes 13 arguments, i'll quickly find out what they are so you don't have to...

#

co_argcount, co_kwonlyargcount, co_nlocals, co_stacksize, co_flags, co_code, co_consts, co_names, co_varnames, co_filename, co_name, co_firstlineno, co_lnotab

#

if you want to create one

brazen geyser
#

cheers pastebin 😃

sick hound
#

also here's juan's code for "modifying" code objects ```py
def _patch_code(code: CodeType, **kwargs):
"""Create a new CodeType object with modified attributes."""

code_attrs = {}

# Collect the original CodeType attributes
for attr in dir(code):
    if "__" not in attr:
        code_attrs[attr] = getattr(code, attr)

# Patch the new attributes over the original ones
code_attrs.update(kwargs)

new_object = CodeType(
    code_attrs["co_argcount"],
    code_attrs["co_kwonlyargcount"],
    code_attrs["co_nlocals"],
    code_attrs["co_stacksize"],
    code_attrs["co_flags"],
    code_attrs["co_code"],
    code_attrs["co_consts"],
    code_attrs["co_names"],
    code_attrs["co_varnames"],
    code_attrs["co_filename"],
    code_attrs["co_name"],
    code_attrs["co_firstlineno"],
    code_attrs["co_lnotab"]
)

return new_object```
brisk zenith
#

god you must have really searched deep for that, surely.

#

last time i saw that was with my C++ I/O in python hack

sick hound
#

i googled for your C++ I/O in python hack :P

brisk zenith
#

hahaha

#

very well.

sick hound
brazen geyser
#

hmm couldnt you do like

import copy
def patch_code(code, **kwargs):
    new_code = copy.copy(code)
    for key, value in kwargs.items():
        setattr(new_code, key, value)
    return new_code
brisk zenith
#

can't setattr

#

read-only attributes

brazen geyser
#

ah rip

brisk zenith
#

i wish it was that easy though

#

my cpystructs stuff would allow you to force it though, but that's a bit too hacky

#

may as well just create a new object

brazen geyser
#

do read-only attributes prevent access to __dict__ directly too?

brisk zenith
#

__dict__ isn't implemented for code objects anyways, i don't think

sick hound
#
>>> (lambda:0).__code__.__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'code' object has no attribute '__dict__'```
brazen geyser
#

lame

brisk zenith
#

yeah, the only way i can think of modifying code objects by force is by writing to their memory space

#

using ctypes or something

#

but that's not reliable i'd imagine

calm rampart
#

what if you have more than 65536 locals

grave rover
#

doesnt python throw an error at that point

calm rampart
#

apparently not

#

well, not locals, but names of accessed globals, as in pastebin's post above

#
 65676         393816 EXTENDED_ARG             1
               393818 EXTENDED_ARG           256
               393820 LOAD_NAME            65675 (dtdz)
               393822 POP_TOP

 65677         393824 EXTENDED_ARG             1
               393826 EXTENDED_ARG           256
               393828 LOAD_NAME            65676 (dtea)
               393830 POP_TOP```
grave rover
#

huh

#

TIL

calm rampart
#

(For the record) ```py

az = string.ascii_lowercase
dis.dis('\n'.join([x for x in map(''.join,itertools.product(az,az,az,az)) if x not in ('elif','else','from','with')]))```

#

should have used uppercase to avoid the keywords 😛 oh well

brisk zenith
#

yeah pastebean showed me the same sort of thing a while ago

brazen geyser
#

DUP_TOP
Duplicates the reference on top of the stack.

New in version 3.2.

DUP_TOP_TWO
Duplicates the two references on top of the stack, leaving them in the same order.

New in version 3.2.
#

bit confued about these two

#

wouldn't dup_top already leave them in the same order?

#

or does it place the duplicate before the original?

#

oh, the two references on top of the stack

#

nvm, i can't read 😄

sick hound
#

        case TARGET(DUP_TOP): {
            PyObject *top = TOP();
            Py_INCREF(top);
            PUSH(top);
            FAST_DISPATCH();
        }

        case TARGET(DUP_TOP_TWO): {
            PyObject *top = TOP();
            PyObject *second = SECOND();
            Py_INCREF(top);
            Py_INCREF(second);
            STACK_GROW(2);
            SET_TOP(top);
            SET_SECOND(second);
            FAST_DISPATCH();
    }
brazen geyser
#

nice, which file are these in?

sick hound
#

ceval.c => evaluation

brisk zenith
#

yup

sick hound
#

compile.c => bytecode compilation

brisk zenith
#

ceval.c has a switch/case for each bytecode instruction

#

pretty fun

calm rampart
#

dup_top_two is like "pick 2nd item" twice [i don't know if the python stack has an nth item operation]

sick hound
#

@brisk zenith as Larry said "a big for loop that iterates over instructions 😄 "

brazen geyser
#

switch/cases are nice and simple. no need to overcomplicate this

sick hound
#

Python also uses Labels as values if

#

the compiler is GCC

#

it is faster than this for loop thingy

calm rampart
#

apparently python used to have a DUP_TOPX instruction, that DUP_TOP and DUP_TOP_TWO replaced because nothing else was ever used

tropic night
#

well.. the python bytecode instructions are crazy long 😄

sick hound
brazen geyser
#

why is ceval_gil just a header file

sick hound
#

This cool to if you want to know more about

brazen geyser
#

interesting, thanks

#
/* XXX TO DO:
   XXX speed up searching for keywords by using a dictionary
   XXX document it!
   */

at the top of ceval.c

#

what kind of keywords are they talking about here?

#

just for/else/return etc?

#

lol it's been there since 1995

sick hound
#

@brazen geyser i think they meant keyword arguments

brazen geyser
#

huh i see

brazen geyser
#
HAVE_ARGUMENT¶
This is not really an opcode. It identifies the dividing line between opcodes which don’t use their argument and those that do (< HAVE_ARGUMENT and >= HAVE_ARGUMENT, respectively).

Changed in version 3.6: Now every instruction has an argument, but opcodes < HAVE_ARGUMENT ignore it. Before, only opcodes >= HAVE_ARGUMENT had an argument.
#
>>> dis.opmap['HAVE_ARGUMENT']
Traceback (most recent call last):
  File "<pyshell#72>", line 1, in <module>
    dis.opmap['HAVE_ARGUMENT']
KeyError: 'HAVE_ARGUMENT'
#

is this a bug?

desert garden
#

No

#

It's not an "opcode"

#

It's a constant on the opcodes module

#

3.6 changed a lot of how bytecode was parsed changed

brazen geyser
#
Pushes a new function object on the stack. From bottom to top, the consumed stack must consist of values if the argument carries a specified flag value

0x01 a tuple of default values for positional-only and positional-or-keyword parameters in positional order
0x02 a dictionary of keyword-only parameters’ default values
0x04 an annotation dictionary
0x08 a tuple containing cells for free variables, making a closure
the code associated with the function (at TOS1)
the qualified name of the function (at TOS)
#

how do these flags work? how are they set? are they passed along as part of the instruction's argument?

#

is it literally just if arg & 0x01 then second popped value will be tuple of default values, etc?

#

oh wait that doesnt make sense, since it'd mess up the value of argc

#

oh, or maybe it just takes that into account

#

let's see what ceval.c has to say

#

oh im just really confused, nevermind, it all makes sense now. ignore me 😅

grave rover
#

@brazen geyser feel free to help out with bytepatches btw, it has horrible parsing so far

brazen geyser
#

the project im working on atm is inteded to be a python vm in another language but if i come across anything that applies to your project as well ill give a shout

grave rover
#

Yee

#

Ah

brazen geyser
#

im thinking the if/elifs in parse_bytecode might be better off as lambdas at indexes in a list

grave rover
#

I mean you're pretty much using bytecode :p

#

Hm

#

But not all of them work as lambdas

brazen geyser
#

oh and then- ye

#

just saw 132

grave rover
#

Maybe a nodevisitor would work but eh

#

It's slower when looking at the bytecode

brazen geyser
#

how do you mean

#

im fairly new to this lower level part of the language so youll have to excuse my ignorance

#

e.g. im not sure what a nodevisitor is 😛

grave rover
#

It's uhh

#

Check the ast module

desert garden
#

You know what you need to do?

#

Define a switch statement, then use that

brazen geyser
#

im trying to get the output of a dis as a string and so im passing a StringIO as the file param
unfortunately though it seems like there aren't any newlines in the output?
what am i missing

def dis_string(code):
    result = io.StringIO()
    dis.dis(code, file=result)
    return result.getvalue()
#

nevermind, it was my mistake with qt's text edit widget

desert garden
#

Why not just use return dis.Bytecode(code).dis()?

#

@brazen geyser

brazen geyser
#

because I didn't know it existed 😄

#

thanks!

snow beacon
#

I figured out a way to get the builtins, including e.g. __import__ after running globals().clear(), but it's definitely cheating.

#
__builtins__, nothing = __builtins__, globals().clear()
import this```
brazen geyser
thorny granite
#

what are you trying to find?

brazen geyser
#

just want to see what python37.dll looks like inside

calm rampart
#

how does type construction work when you don't override __new__, considering object.__new__ accepts no arguments?

#

like, I figured construction is basically like this: ```py
def ...(cls, *args, **kwargs): # pseudo code for type.call
obj = cls.new(*args, **kwargs)
if isinstance(obj, cls):
obj.init(*args, **kwargs)
return obj

but that doesn't work because it passes args/kwargs to `object.__new__`
thorny granite
#

it checks if __init__ is defined

calm rampart
#

it looks like the relevant line for my question is L3767 a few lines up but

#

why is it !=

#

oh wait

thorny granite
#

probably if you call super().__new__ in your own new

calm rampart
#

for super().__n

#

yeah

#

so it ignores the arguments if the class has its own init

#

but if the class has its own new, that is expected to handle the arguments itself and, if it calls object.__new__ at all, do so without arguments

#

checks out: ```py

class C:
... def init(self): pass
...
object.new(C, 1, 2)
<main.C object at 0x0000000002AD0DA0>```

desert garden
#

Compiling bytecode is really trivial

sick hound
#

I like the next thing in the thread; the -> arrow for callables

#
strongly against it either. What I would like to add here is that if we
will go with the replacement:

Callable[[X, Y], Z] becomes (X, Y) -> Z

then we should also go with

Union[X, Y] becomes X | Y
Tuple[X, Y] becomes (X, Y)
Optional[X] becomes X?
(Intersection[X, Y] when added becomes X & Y)

The current syntax (although really verbose) is consistent, so if we want
to improve it I would like to keep consistency.
Also if we are going forward with this, should we allow mixing old and new
syntax? Will the old syntax be deprecated after we introduce the new one?```
wet dagger
#

Alrighty I'm working on a project that has to do with image recognition. I've got a bunch of collecters cards that have set images on them. What I want to do is take a picture of a card or present 1 and indentify which set that card came from.
I'm writing it in python and am thinking of using open-cv and a haars cascade algorithm. The issue is that requires 100's of positive and negative images. I can get the negative but IDK how I could get so many positive for each set or even an individual set. Is there another auggestion anyone could reccomend with tensorflow or any other python application?

sick hound
#

this is not a good place to ask for actual help with python

ripe axle
#

Folks, apologies if this is not the right channel. Inside a primary jupyter notebook, i'm trying to load other ipython notebooks one by one and run them and capture any pandas dataframes that get generated and write them out to disk. Is there any way to get a secondary ipython shell context within an ipython context (just to keep the variable namespaces seperate)?

#

This seemed to be "esoteric" python to me, so I thought I'd ask here.

sick hound
#

Is it possible to suppress errors in a one liner? Or a lambda

#

I mean I could do a exec

gleaming path
#

one line is a no, two is a yes

#

something tells me you could probably force it to one line, but it would be really damn horrendous to look at lol

supple jasper
#

with contextlib.suppress(Exception): expression

sick hound
#

nope ```py

with contextlib.suppress(Exception): raise BaseException
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BaseException```

brisk zenith
#

well then suppress baseexception :D

sick hound
#

yep, that works ```py

with import('contextlib').suppress(BaseException): raise BaseException
...

sick hound
#

ofc it works

sick hound
#

That doesn't work the way I want it to

#

Since in a one liner now everything else you type will be in that

#

Since semi colons

#
while id:r=input("Enter temperature and units: (e.g. 32 F)\n");id=1if r else 0;s=iter(r.split(" "));t=next(s,"");e="No temperature was entered;quitting."if t==""else 0;exec("try:t=float(t)\nexcept:t=0");e=e or("Invalid temperature."if hasattr(t,"__or__")else 0);u=next(s,"").lower();e=e or("No unit specified."if u==""else 0);z={"f":lambda x:(x-32)*5/9,"c":lambda x:x*9/5+32};c=z.get(u,lambda x:0)(t);e=e or("Invalid unit."if c is 0else 0);y="C"if u=="f"else"F";print(f"[ANS] {c} degrees {y}\n")if id and not e else 0;print(e+"\n")if all((id,e))else 0

One liner with instructions. I have expanded version and much shorter version (which uses 1 and 0 instead of true/false and a bunch of other things, and does not contain instructions for what to do)

burnt pasture
sick hound
#

I'll add it to my watch list
Which is about 200 videos long

#

For just coding videos

burnt pasture
#

it's a "tool" that can automatically convert programs into one-liners. she figures out all sorts of horrible tricks to make it work

sick hound
#

But half the fun is doing it yourself

#

Why would you use a tool

burnt pasture
#

sure 😃

sick hound
#

I mean there's sense in making it

#

Not using it

burnt pasture
#

well, it's an extra-level challenge to write a program to modify your programs.

#

in the video, she explains things like how to get try/except in a one-liner

sick hound
#

I'll still watch it of course. Be nice.

burnt pasture
#

sorry, was i not nice?

#

@sick hound ^^ ?

sick hound
#

No, so sorry. I'm saying the video will be nice

#

@burnt pasture

burnt pasture
#

ah, ok! 😃

brazen geyser
#
>>> dis.cmp_op
('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is', 'is not', 'exception match', 'BAD')
#

what is BAD?

brisk zenith
#

probably used in place of an invalid operator or something

brazen geyser
#

wouldnt that raise a syntax error during compilation?

brisk zenith
#

/shrug

gilded orchid
#

For the maybe keyword challenge does it have to be 100% random, or could the value just change to random.choice([True, False] 100 times a second or something like that

brisk zenith
#

that's up to you. :D

honest lotus
#

Hey guys, I was wondering if it was possible to import and use a modual within something that looks like this

#

print(eval("lambda x: x*2")(eval("int(input(\"Enter a value:\\n\"))")))

#

its just an example

#

So basically I need to use the modual in the lambda function

#

and It needs to be in one line, should have started with that

#

sorry for the hassel

#

Actually, heres the whole code

#
print(eval("lambda x: \"Correct\" if random.randint(1, 10) == x else \"Incorrect\"")(eval("int(input(\"Enter a number:\\n\"))")))```
#

Is it possible to oneline?

honest lotus
#

Oh, forgot semicolans existed, wow. Well if anyone figure out any way to do it without semicolans let me know

rugged sparrow
#
print((lambda x,random=__import__('random'):'Correct' if random.randint(1,10) == x else 'Incorrect')(int(input('Enter a number:'))))``` @honest lotus
honest lotus
#

wow

#

Its so much more elegant

#

than the evals

#

Thanks @rugged sparrow

rugged sparrow
#

np

#

@honest lotus tbh you could move the import cause you only use random once

honest lotus
#

What do you mean move the import? I'm kinda new to esoteric stuff

#

hence all the evals

rugged sparrow
#

Gimme a min I'll show you

honest lotus
#

ok

rugged sparrow
#
print((lambda x:'Correct' if __import__('random').randint(1,10) == x else 'Incorrect')(int(input('Enter a number:'))))```
#

@honest lotus

honest lotus
#

Thats interesting, didn't know you could call a method of a module in the command where you import it

#

Esoteric python is full of wonders

rugged sparrow
#

Yeah lol

#
(lambda x:x(x,(lambda x:[[[0]*len(x[i])for i in range(len(x))],x])((lambda a:(lambda x,y:[[[[x[r].pop(c),x[r].insert(c,'*')]if y[0][r][c]else[x[r].pop(c),x[r].insert(c,y[1][r][c])]for c in range(1,a-1)]for r in range(1,a-1)],x][-1])([a*[0]for x in range(a)],(lambda x:[[[[[(lambda x,y:[y.append(x[1][r][c]),x[1][r].pop(c),x[1][r].insert(c,y[0]+1)])(x,[])if x[0][l][j]else 0for j in range(c-1,c+2)]for l in range(r-1,r+2)]for c in range(1,a-1)]for r in range(1,a-1)],x][-1])((lambda x:[[[[x[0][r].pop(c),x[0][r].insert(c,int.from_bytes(open('/dev/urandom','rb').read(1),'big')/10>20)]for c in range(1,a-1)]for r in range(1,a-1)],x][-1])([[a*[0]for x in range(a)]for x in range(2)]))))((lambda i:i if i>2and i<12else exit())(int(input('Board Size (max 9): '))+2)))))((lambda x,y,p=(lambda x:[print('\x1b[1;32m ',*range(1,len(x[0])-1),sep=' '),[[[print(f'\x1b[1;32m{r}\x1b[0m',end='') if c == 0 else [print(' ',end=''),print(['■','F'][x[0][r][c]], end='')if x[0][r][c]!=2else print(x[1][r][c],end='')]for c in range(len(x[0])-1)],print()]for r in range(1,len(x[0])-1)],x][-1]),i=(lambda f,i:[f[0][int(i.split(',')[0])].pop(int(i.split(',')[1])),f[0][int(i.split(',')[0])].insert(int(i.split(',')[1]),{'f':1,'c':2}[i.split(',')[2].lower()]),[print('You Lose'),exit()]if f[1][int(i.split(',')[0])][int(i.split(',')[1])]=='*'and i.split(',')[2].lower()=='c'else f][-1]),q=[]:[p(y),q.append(i(y,input('Type Row,Column,[(F)lag or (C)lear]: '))),x(x,q[0])if not (lambda y,q=[],w=[]:[[[q.append(y[0][r][c]==1and'*'==y[1][r][c])for c in range(len(y[0][r]))]for r in range(len(y[0]))],q][-1].count(1)==[[[w.append(y[1][r][c]=='*')for c in range(len(y[1][r]))]for r in range(len(y[1]))],w][-1].count(1))(y)else print('You Flagged All The Bombs!')]))``` This is one line minesweeper i did a while ago. input is (Row),(Column),(F for flag or C for clear) ex: 1,1,C @honest lotus
#

itll look weird if you run it on windows tho

sick hound
#

actually it won't work on windows

#
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
  File "<stdin>", line 1, in <lambda>
  File "<stdin>", line 1, in <lambda>
  File "<stdin>", line 1, in <listcomp>
  File "<stdin>", line 1, in <listcomp>
FileNotFoundError: [Errno 2] No such file or directory: '/dev/urandom'```
rugged sparrow
#

Oh right

#

Cause I didn't import random

gilded orchid
#

Is there a way to assign variables in lambdas without causing a syntax error?

sick hound
#

maybe locals()?

limpid osprey
#

If you need to assign variables, you should probably just use a regular function instead

rugged sparrow
#

@gilded orchid python globals().update({'varName':"value"}) works

#

locals wont

limpid osprey
#

Oh I just scrolled up and saw the lambda XD

rugged sparrow
#

Yeah lmao

#

Tbh I didn't even use hacky global vars for that

gilded orchid
#

Also, is there a way to change the value of an argument of a lambda without raising an error?

rugged sparrow
#

example?

gilded orchid
#

eg: lambda x: x += 1 without raising an error

rugged sparrow
#

one sec

#

testing something

#

lambda x: locals().update({'x':x+1})

#

@gilded orchid

gilded orchid
#

oh wow, thanks

rugged sparrow
#

np

#

hmm

#

wait

#

@gilded orchid lambda seems to ignore .update on its locals

#

it doesnt error, but wont work

gilded orchid
#

ah nvm then

rugged sparrow
#

however there is a hacky way of doing it

#

lambda i,x=[0]:[x.pop(),x.append(i),x[0]][2] returns i

#

but you could do lambda i,x=[0]:[x.pop(),x.append(i+1),x[0]][2]

#

which would return i+1

#

and you could use x later in the program

#

also, if you have lists as defaults in a lambda, you have some fun properties

#
x = lambda i=None,x=[]:x.append(i) if i else x
x(9) #returns nothing
x() #returns [9]
x(10) #returns nothing
x() #returns [9,10]``` @gilded orchid
#

btw that works with any mutable variable as a default

#

so dict works too

#
newCard = type(
    'Card', (object,),{
        '__init__':lambda self,card,suit:[
            setattr(self,'card',card),
            setattr(self,'suit',suit),
            setattr(self,'visible',False),
            None
        ][3],
        'setVisible':lambda self,o=1:setattr(self,'visible',o),
        'getSuit':lambda self,c=0:[f'\x1b[1;{31 if self.suit <= 1 else 0}m' if c else ''][0] + '♥♦♣♠'[self.suit] + ['\x1b[0m' if c else ''][0],
        'fullCard':lambda self,f=0:self.getSuit(self.visible or f)+self.card if self.visible or f else '[]',
        'getValue':lambda self:'A23456789XJQK'.index(self.card),
        'getColor':lambda self:'red' if self.suit <= 1 else 'white'
    }
)``` in case you ever want to make a class without ``class`` keyword (can also be condensed to one line)
keen moth
brisk zenith
#

@rugged sparrow that stuff with mutable default args in a lambda applies to regular functions too.

honest lotus
#

@rugged sparrow could you explain why there is a [3] on the init and a [0] on the getsuit?

rugged sparrow
#

@brisk zenith didn't know that, but it makes sense when I think about it

#

@honest lotus there is a [3] on __init__ because __init__ has to return None

#

There is a [0] on getSuit because I used list comprehension to separate operations, and that gets the value out of the list

honest lotus
#

@rugged sparrow is there like a guide or something for that?

#

Seems pretty interesting

rugged sparrow
#

probably? i figured it out by messing around till it worked

#

¯_(ツ)_/¯

rugged sparrow
#
(lambda _,__,___,____:getattr(getattr(__import__(True.__class__.__doc__[(_*____*_)]+True.__doc__[(___*_)**_+__*___]+True.__class__.__doc__[____*(True+__)]),__import__(True.__doc__[True-___]+True.__class__.__doc__[(___*_**_+__)*___]+True.__doc__[(_+__)*____+True]).__doc__[int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___))):int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___)))+_*__]),getattr(__import__(chr((___*_)**_+__*___)+True.__doc__[(___*_**_+__)*___]+True.__class__.__doc__[True-___]),__import__(chr((___*_**_+__)*___)+True.__class__.__doc__[(___*_)**_+__*___]+True.__doc__[(_+__)*____+True]).__doc__[int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___))):int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___)))+_*__]).__doc__[int(True.__int__().__str__()+str(True*__)+False.__int__().__str__()+str(__*__)):int(True.__int__().__str__()+str(True*__)+False.__int__().__str__()+str(__*__))+___]+getattr(__import__(chr((___*_)**_+__*___)+True.__doc__[int(True.__int__().__str__()+True.__int__().__str__()+str(___))]+chr((___*_)**_+__*___)),__import__(chr(int(True.__int__().__str__()+True.__int__().__str__()+str(___)))+True.__doc__[int(True.__int__().__str__()+True.__int__().__str__()+str(___))]+True.__class__.__doc__[____*(___-True)]).__doc__[int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___))):int(chr(_+(_*___*___)+_)+chr(_+(_*___*___)+_*_)+chr(_+(_*___*___)))+_*__]).__doc__[((__*__-__**__)+_*_)*____:(__*__-__**__)*____]+True.__class__.__doc__[____*_**_])(True.__doc__[_**___-True].upper()+True.__class__.__doc__[__**__-__*__]+True.__class__.__doc__[__]*_+True.__doc__[True]+True.__class__.__doc__[_^___]+chr((_**___+_**_*_)*_+___^_)+chr(___*___*_**_+_*___+True)+chr((_*(___*_)*___)+_**_+___*_)+True.__doc__[__]+chr((___*_)**_)+True.__class__.__doc__[__*___]))(True<<True,(True<<True)+True,(True<<True<<True)+True,True.__class__.__doc__.find(chr(False)))```
#

@gilded orchid i made my own (it was an obfuscated hello world

#

@brisk zenith i saw that obfuscated hello world in the pins and decided to make my own

honest lotus
#

I noticed a lot of the one liners have nested lambdas within [] and make use of and and or. Would someone mind explaining it a bit?

snow beacon
#

and and or can be used as conditionals instead of if because of something called short circuiting. Basically, if you check False and some_func(), then Python will get to the False then realise that the other argument doesn't matter because there's no way for the statement to return True, so it doesn't bother to call the function on the right. So if the left value is falsy it returns that value. Note that it doesn't always return False, it just copies the left value. The left value could be 0, and empty string or list, None, etc. Python already knows it's falsy. If the left value is truthy, it returns the right value instead, whatever it may be, because Python knows the right value in that case has the same value as the whole and clause. So, in effect, a and b is a if not a else b. A similar thing happens for or

honest lotus
#

What about lambdas within other lambdas using []

gilded orchid
#

Would (True) be considered true-ey? @snow beacon

snow beacon
#

Oh, sorry, did I say it wasn't?

#

True is truthy, false is falsy.

#

Most objects are truthy, exceptions being None, False, 0, empty sequences, empty dicts, empty sets, and probably a bunch of other things I'm forgetting.

tepid glacier
#

yeah that pretty much covers it

#

excluding things that override __bool__ like Decimal and range

sick hound
#

mostly, anything that's 0y or emptyy is falsey, and anything else is truthy

fast torrent
#

Here;s a challenge guys

#

A python oneliner that says "hello world" but looks like the word "Hello" in markdown

rugged sparrow
#

@fast torrent example?

fast torrent
#

I have no idea if its possible

rugged sparrow
#

ah

#

@fast torrent ['Hello World'](print(f'Hello{chr(32)}World')) this will do it

#

but will throw an error after printing Hello World

fast torrent
#

I mean the code looks like "Hello World"

#
H         H          i
h h h h H
h           H
h          H 
rugged sparrow
#

Oh

#

lmao

#

thought you wanted it in markdown

fast torrent
#

Ohhh

#

hahaha

sick hound
#

@fast torrent ```py
p = print ; s =' ';
h = 'h ' ; r =
'rep' 'lac' ; r = r\

  • r [ 1 ] ; (
    ) ; eval( 'p('+ '"hell o".'
    \
  • r +('(" " , "")+'
    ) + ' " " [ 0
    ]+"wo rld". ' + r +
    ' ( " " [ 0 ]
    , " "*0))');1+1 +1+1+ 1+1+1
brisk zenith
#

that's really fun actually

sick hound
#

there aren't enough consecutive non-spaces for "replace" or "getattr" so I put the whole thing in an eval

fast torrent
#

Hahaha it is possible

#

Nice!

brisk zenith
#

there's a bit of unnecessary code at the end and that sort of thing but that's all cool, it does the job.

rugged sparrow
#
['  ',  print(  '',  'H' +'ello'
,   ''  ,''     '',   '' ,    ''
),111,  print(  '',  'W' +   'o'
+   ''  +       ''+  ''  +    ''
+   ''  +'rld'  ,''  ,'' ,'' ),]```
#

this works

#

@fast torrent

fast torrent
#

Cool.

stray needleBOT
brisk zenith
#

challenge 07 is upon us: code art!

we're changing things up today (as always, really). your submission may do whatever you want it to, but it must do something and follow the theme of code art, like the messages(s) just above this one :D

i hope we get some really unique submissions this time around, it's very open-ended. more details and examples can be found on the repository here: https://github.com/python-discord/esoteric-python-challenges/tree/master/challenges/07-code-art

#

i'm always nervous about getting something wrong when doing that :D i don't think i did this time though.. 👀

fast torrent
#

@brisk zenith lol I came up with something

#

Wheres my contributor role ;^)

brisk zenith
#

wat

fast torrent
#

The code art

#

unless you planned it beforehand smh

brisk zenith
#

i'm still confused.

fast torrent
#

@brisk zenith I mentioned the code art idea a few days ago

#

Then you made challenge 7

brisk zenith
#

oh, i see. i had the idea in my head quite a while ago but didn't know how well it'd work until you mentioned it.

fast torrent
#

OK

#

Make sense

sick hound
#

@spice wing check out this challange

rugged sparrow
#
print(['No '   +'One'    ,'X','O'    ][(  lambda    x=\
(    lambda    f:[f(    )      for   _ in   range(9)]
)(   lambda    b=[*  range     (9)   ],u=     [' ']\
*9,f=[0,1]:  [(lambda    p:[p(u),    p(b)  ])(    lambda\
               a,p=                 print\
:[p('_'*7),[p('\x1b[4m',*a[x:x+3],'\x1b[0m',sep='|')for \
              x in[                 0,3,6\
              ]]]),                (lambda  i: [ u.pop(i),
            u.insert(              i,'XO'   [f[1]      -1])
              ])((                  lambda  c=[0]:    [c.pop\
              (),[_                 for _   in iter(lambda:\
             (lambda               i=input(\
'XO'[f[1]-1]+': '):0if[any([0if x in map(chr,range(48,58))else\
              1for                  x in i]\
)if     len  (i)else               1][0]else  [c.append     (int(i)),
  1][1]if   int(i)>=0               and int      (i)<=8   and' '\
   ==u[      int(i)]                else 0          )(),1)],c[0]]\
   [2])       ()),(                 lambda:      [f.pop       (0),\
[],   [],   f.insert(               0,f[0])]  if 1in            [all(
[u[  int(x)   ]=='XO'               [f[1]-1] for x in            str([\
\
*map(ord,'ÒřʦɶơĂ͈ö')    ][y])])\
for y in    range(8)]  else 0)(),
f.append(   [0,2,1]\
[f.pop(1)   ])]if 0\
 ==f[0]      else f[   0]):0if x\
 [-1]not in[1,2]else   x[-1])()],'Wins')```
#

@brisk zenith would this be a valid submission to the newest challenge?

cold mirage
#

lol

#

do you need help?

rugged sparrow
#

@cold mirage its tictactoe

cold mirage
#

im not questioning what it is, im questioning your sanity

rugged sparrow
#

oh then definitely

autumn yew
#

I question his sanity 24/7... he refuses help

grave rover
#

@brisk zenith can I resubmit my heart code but in the shape of the word "heart"

brisk zenith
#

@grave rover of course you can :D

#

but don't forget, words aren't the only form of art. it would be nice to get some other creative submissions too ^~^

grave rover
#

resubmits heart code

brisk zenith
#

haha, the main idea of this challenge is to be unique and interesting

rugged sparrow
#

@brisk zenith did my submission go thru?

brisk zenith
#

i mean, it certainly can if you want me to merge. it does look a little wonky though! haha :D

#

i think you've got a really good idea though

#

tic tac toe written in code that looks like tic tac toe. pretty neat for sure.

rugged sparrow
#

it is a tad wonky

#

ill neaten it up a bit

brisk zenith
#

i think it would look really cool if you managed to make the grid line up properly and all that. it's perfectly fine if you can't manage that, but it's nice to make it a little more challenging for people who enter submissions so quickly :D

rugged sparrow
#

lol sounds good

rugged sparrow
#
print(['No '    +  'One'    ,'X','O'    ] [  (  lambda     x=
 (    lambda    f:[   f(   )      for   _   in     range(9)]
 )(   lambda    b  =  [*  range    (9)  ],  u=       [' ']\
 *9,f=[0,1]:    [(lambda    p:[p(u),    p  (b)    ])(     lambda
                a,    p=                print
 :[p('_' * 7),[p('\x1b[4m',*a[x: x + 3] ,'\x1b[0m', sep='|')for
                x in   [                0,3, 6
                ] ] ]),(                lambda     i:[u.pop(i),
                u.insert                (i,'XO'  [f[1]      -1])
                ] ) (  (                lambda   c=[0]:   [c.pop(
                ),[_ for                _   in     iter(lambda:(
                lambda i                =input(
 'XO'[f[1]-1]+': '):0if[any([0if x in map(chr,range(48,58))else
                1    for                x in i]
  )if    len(i  )else 1]                [0]else    [c.append       (int(i)),
    1][1]if     int(i)>=0               and int        (i)<=8      and' '
     == u[      int(i) ]                else 0)          (),1)],c[0]]
      [2]       )() ), (                lambda:       [f.pop       (0 ),
   ['/'  ],f    .insert(                0,f[0])     ]if 1           in[all(
 [u[      int(  x)]=='XO'               [f[1]-1   ]for x             in str([


 *map(ord,'ÒřʦɶơĂ͈ö')    ][y])])for y in    range(8)] else 0)
        (),f.               append        ([0,
        2,1][               f.pop(        1)])
        ]if 0               ==f[0]        else
        f[0])               :0if x         [-1]not in[1,2]else 
                       x[-1])()],'Wins')```
#

@brisk zenith i straightened it up a bunch, and made the stuff at the bottom something other than a random blob lmao

#

i think i might change that last row and make the last x a bit smaller tho

brisk zenith
#

looks quite a lot better, actually! feel free to make any new commits to your PR and let me know when you think you've done the best you can so i can merge it in.

rugged sparrow
#

Sounds good, will do

stray needleBOT
rugged sparrow
#

@brisk zenith its done now

brisk zenith
#

oh neat, looks great! thanks for submitting your code, i'll merge it now

rugged sparrow
#

thanks

brisk zenith
#

@keen moth that's really cool, and it's shaped so perfectly too. good job! is it ready for merging?

keen moth
#

Yes, it is

#

Thanks

brisk zenith
#

okay! thanks for participating :D

#

oh and of course, i think i'll allow people to give multiple submissions for a challenge if they so wish. i don't see why not ^~^

gilded orchid
#
print(__import__('random').choice(
[(                             '1'
)+      chr(int(ord('ǂ')/       10
))    +chr(            5*17      )
+     chr(2            *56)      ,
''    +chr(            7*11      )
+     chr(             5*23     +2
)+                 chr(5*       23
)+            chr(10*           10
+4            )+chr(            5*
22            +2*2)+            ''
+             chr(2*            56
-1            )+chr(            37
*                                3
)+            chr(99             +                         
10            ),chr(            83
)+                              ''
+chr(4*29)+chr(4*24+1)+chr(114)]))

Finally finished this mario question mark block, that outputs 'Star', 'Mushroom' or '1-Up'

#

How do I submit it to the github solutions thing? (I haven't used github before)

brisk zenith
#

but if you still need a hand with it, i can help you :)

#

looks like a wonderful solution, by the way.

grave rover
#

I had a fun idea but I doubt it's doable

#

Does anyone here know Tupper's self-referential formula?

whole kiln
#

I know of it but that's about it

#

can't it actually graph as any image?

brisk zenith
rugged sparrow
#

@grave rover what's you idea for it?

grave rover
#

Write code in that shape that outputs that shape

whole kiln
#

That formula is kinda "cheaty" since it uses a constant which is what actually affects what the output looks like

#

So you could write code that works on the same principle

sick hound
#

https://cdn.discordapp.com/attachments/470884583684964352/574028065873723403/DVMnaKkUMAAfLQ0.jpeg
in that image, k is (i think) 960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719

gilded orchid
#

hoping I did that right

brisk zenith
#

@gilded orchid yup, looks good. that's a really cool submission, i'll merge it when i get on my computer at some point later today :D

gilded orchid
#

ok, thanks 😃

gilded orchid
#

(lambda x: (print('1'),print('2')))(1) Is there a way to stop this from printing (None, None)?

sick hound
#

try not running it in a python REPL

gilded orchid
#

oh oops, thanks

#

Is there a way to use a while loop in a lambda?

sick hound
#

not exactly

#

you can't use an actual while loop because that's a statement

#

but you can use py [whatever for _ in iter(lambda: condition, True)]

gilded orchid
#

If you changed that True to False would it function like while not:?

sick hound
#

yes

gilded orchid
#

oh ok, makes sense

sick hound
#

except the condition has to evaluate to either True or False

#
[whatever for _ in iter(lambda: bool(condition), True)]``` would be more accurate
gilded orchid
#

wow, my next thing for the code art challenge is bigger then my screen at the moment

#

I've had to lower the font size

#

also, could 'whatever' be a list/tuple of code? @sick hound

sick hound
#

yes

#

it could be anything

gilded orchid
#

ok, thanks for the help

brazen geyser
#

that formula is amazing

#

how do you even come up with something like that

#

dark sorcery

sick hound
#

oh wait

#

@gilded orchid i got that the wrong way round

#

it should be iter(lambda: bool(condition), False)

gilded orchid
#

its been like 3 hours

rugged sparrow
#

@gilded orchid what are you doing?

gilded orchid
#

Trying to make a simulator for a Pokemon battle, that spells out the word Pokemon

#

for the code art challenge

rugged sparrow
#

That's amazing

#

@gilded orchid if it would make it easier, you can make legit classes (with self) in one line using type()

brisk zenith
#

yup, type(class_name, bases, attributes).

example: ```py

class Dog(Animal):

Dog = type("Dog", (Animal,), {

# set a class-level attribute like this:
"BASIC_COLOURS": ["black", "brown", "white"],

# def __init__(self, colour):
#     self._colour = colour
#
"__init__": lambda self, colour: setattr(self, "_colour", colour),

# @staticmethod
# def make_sound():
#     print("woof")
#
"make_sound": staticmethod(lambda: print("woof")),

# @classmethod
# def new_random(cls):
#     return cls(random.choice(cls.BASIC_COLOURS))
#
"new_random": classmethod(
    lambda cls: cls(random.choice(cls.BASIC_COLOURS))
),

# @property
# def colour(self):
#     return self._colour
#
"colour": property(lambda self: self._colour) 

})

#

i actually think that's a really nice demonstration of manual type initialisation

#

and of course, with comments and newlines removed, you get this: ```py
Dog = type("Dog", (Animal,), {"BASIC_COLOURS": ["black", "brown", "white"], "init": lambda self, colour: setattr(self, "_colour", colour), "make_sound": staticmethod(lambda: print("woof")), "new_random": classmethod(lambda cls: cls(random.choice(cls.BASIC_COLOURS))), "colour": property(lambda self: self._colour)})

#

it looks like chaos but it really does make a lot of sense if you just break it down and comment it properly as i've shown.

inner temple
#

that is a very nice example of using type()

brisk zenith
#

allows you to have fully object-oriented programs in one line. perfect for #esoteric-python.

#

in fact, for one of the first challenges submitted here (polish notation evaluator) i built a full stack class manually in one line because lists were prohibited. i believe basically anything is possible in one line if you break it down enough

rugged sparrow
#

oh definitely

#
globals.update({'Dog':type('Dog', (Animal,), {...})})``` you can even add it to globals in one line
brisk zenith
#

yup

rugged sparrow
#

@brisk zenith did you ever figure out how to do oneline'd try,except?

brisk zenith
#

nope, but i'd be lying if i said i tried :D

#

been quite busy recently so it's not a priority for me at the moment

rugged sparrow
#

ah makes sense

#

ill prob give it a shot tonight

rugged sparrow
#

@brisk zenith py try_except = lambda t,e,x=Exception:[exec('def q(t,e,x):\n\ttry:return t()\n\texcept x as p:return e(p)'),eval('q(t,e,x)')][1] ik this is cheating, but it does work

#

¯_(ツ)_/¯

rugged sparrow
#
try_except = lambda t,e,x=Exception:[(lambda:0).__class__(compile('def q(t,e,x):\n\ttry:return t()\n\texcept x as p:return e(p)','','exec'),globals())(),q(t,e,x)][1]``` doesnt use exec() or eval() now
#

technically

sick hound
#

but it's not technically on one line either

#

it also technically uses exec

rugged sparrow
#

thats why i put the technically

#

@sick hound do you have any ideas?

sick hound
#

I was thinking of manually using contextlib.suppress
however it only works in with statements

#

I did do the same thing as above when I had to

rugged sparrow
#

there has to be some way to do it

sick hound
#

yeah

#

I'm gonna go searching through stdlib for a function which has try/except in it

rugged sparrow
#

smart

sick hound
#

arbitrary function that handles errors

rugged sparrow
#

thats perfect

sick hound
#

you just need some boilerplate

rugged sparrow
#

also thats only in cpython

sick hound
#

what's wrong with that

#

If I'm searching through stdlib it's probably only gonna be cpython

rugged sparrow
#

thats true

#

but i think itd be best if our solution is universal

sick hound
#

Go through the documentation then

#

I'm fine with it working just in cpython

rugged sparrow
#

i am

#

this can do it

#

@sick hound

sick hound
#

wait actually that won't even work

#

the thing I found

#

actually

#

uhh

#

sorta

#

you'd have to create a queue objet which the put method does the actual function
ie. it can raise an error

rugged sparrow
#

ah

#

dang

sick hound
#

darn it I was looking at contextlib before

rugged sparrow
#

dang

sick hound
#

same thing but not heroku lol

rugged sparrow
#

lol

sick hound
#

doesn't do python 3 tho

rugged sparrow
#

yah

#

i noticed

tepid beacon
#
compile('def q(t,e,x):\n\ttry:return t()\n\texcept x as p:return e(p)','','exec')```
#

"doesnt use exec"

#

mfw

rugged sparrow
#

@tepid beacon i said technically

tepid beacon
#

if anything it uses is technically

rugged sparrow
#

¯_(ツ)_/¯

#

do you have any ideas for try except in a lambda?

sick hound
#

PEP0463 😦

gilded orchid
#

Are there any code editors that help when making one liner stuff? E.g: a pretty view option

#

I'm getting kind of annoyed using Idle

whole kiln
#

Can you go into more detail? What is it you're looking for from an editor regarding one liners?

rugged sparrow
#

@sick hound i solved it

#
tryExcept = type('tryExcept',(__import__('contextlib').ContextDecorator,),{
   "__init__":lambda self,f=lambda:None,e=Exception:[setattr(self,'e',e),setattr(self,'f',f)][0],
   "__enter__":lambda self:None,
   "__exit__":lambda self, *args:[[True,self.f()][0] if self.e in args[0].__mro__ else False][0] if args[0] != None else False
})```
#

tryExcept()(lambda:1/0)() ^ no crash

#

tryExcept(e=KeyError)(lambda:1/0)() ^ crash, cause we are checking for KeyError

#

tryExcept(f=lambda:print('i tried to divide by zero'),e=ZeroDivisionError)(lambda:1/0)()

#

^ runs f, as a ZeroDivisionError was called

#

@brisk zenith ^^

sick hound
#

lambda's don't do kwargs

rugged sparrow
#

yes they do

sick hound
rugged sparrow
#

what

sick hound
rugged sparrow
#

also obv the second would crash

sick hound
#

well yes demonstrating the difference between kwarg and arg

rugged sparrow
#

what version of python?

sick hound
#

3.6.1
actually they do

#

???

#

oh ic

#

you edited it lol

#

you turned x into e

rugged sparrow
#

yea i thought it made more sense

#

@sick hound i should prob sleep now

#

its 2 am here

#

🙃

sick hound
#

ha

#

@rugged sparrow ```py
from contextlib import suppress, ContextDecorator
suppress = type("suppress", (suppress, ContextDecorator), {})
suppress(ZeroDivisionError)(lambda: 0/0)()

#

there we go
using contextlib.suppress
doesn't have the default Exception but it does support mutltiple exceptions

rugged sparrow
#

@sick hound but can it do except

sick hound
#

good point it can't

rugged sparrow
#

dont get me wrong, my implementation can def be improved, and probably isnt the best way to do it

sick hound
#

yeah there's some defo shortens yours can do

#

I'm adding a finally too to yours

rugged sparrow
#

aight

#

im gonna sleep now

sick hound
#

also you have lots of [statement][0] for no reason

rugged sparrow
#

thats to make sure stuff happens in the right order

#

also __init__ has to return None

sick hound
#

but just use (statement)

rugged sparrow
#

and setattr returns None

#

ah true

#

2 am remember?

sick hound
#

init does not have to return None?

#

that's just style

rugged sparrow
#

well now its 3 am

#

really?

#

last i checked it was enforced

#
>>> class d():
...     def __init__(self):
...             return 1
... 
>>> d()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None, not 'int'
>>> 
``` @sick hound
sick hound
#

okay

#

never knew that

#

or maybe I did

rugged sparrow
#

lol

sick hound
#

eh

#

patchy memory

rugged sparrow
#

same here

#

espescially when im substituting caffine for sleep

#

also spelling left

sick hound
#

are you agianst semicolons

rugged sparrow
#

yes

#

this is for onelineing

sick hound
#

yup

rugged sparrow
#

and semicolons are against that spirit

#

for your finally, just add it to exit

#

but remember that __exit__ has to return True

#

if you want the exception to be ignored

sick hound
#

yup

#

actually is there any point to finally

#

I don't think since we can't do return

sick hound
#

please ignore my extremely dodgy testing method

brisk zenith
#

ah yes, i've considered using contextlib for it but i wanted to see if i could get it to work with no imports :D still, subclassing it is definitely something i didn't think of, so it's a nice solution anyways.

sick hound
#
type(exit).__call__.__globals__['sys'].modules['contextlib']```
#

@brisk zenith technically no imports :P

tepid glacier
#

interesting

sick hound
#

I don't think people really know what technically means
Because technically it has had to have imported it in the first place

sick hound
#

but the code doesn't import it

#

if you want no imports then don't use python at all

brisk zenith
#

but doesn't sys.modules['contextlib'] need contextlib to have been imported elsewhere first?

sick hound
#

yes, it does

#

but contextlib has already been imported somewhere when the interpreter starts

#
C:\>python
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> type(exit).__call__.__globals__['sys'].modules['contextlib']
<module 'contextlib' from 'C:\\Users\\Aaay\\AppData\\Local\\Programs\\Python\\Python36\\lib\\contextlib.py'>
>>>```
#
C:\>python
Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 17:00:18) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> type(exit).__call__.__globals__['sys'].modules.keys()
dict_keys(['builtins', 'sys', '_frozen_importlib', '_imp', '_warnings', '_thread', '_weakref', '_frozen_importlib_external', '_io', 'marshal', 'nt', 'winreg', 'zipimport', 'encodings', 'codecs', '_codecs', 'encodings.aliases', 'encodings.utf_8', '_signal', '__main__', 'encodings.latin_1', 'io', 'abc', '_weakrefset', 'site', 'os', 'errno', 'stat', '_stat', 'ntpath', 'genericpath', 'os.path', '_collections_abc', '_sitebuiltins', 'sysconfig', '_bootlocale', '_locale', 'encodings.cp1252', 'types', 'functools', '_functools', 'collections', 'operator', '_operator', 'keyword', 'heapq', '_heapq', 'itertools', 'reprlib', '_collections', 'weakref', 'collections.abc', 'importlib', 'importlib._bootstrap', 'importlib._bootstrap_external', 'warnings', 'importlib.util', 'importlib.abc', 'importlib.machinery', 'contextlib', 'mpl_toolkits', 'atexit'])
>>>``` all of those modules have already been imported by something
#

@brisk zenith

#

(i included the cmd command and startup message to show that I haven't done anything else)

brisk zenith
#

well yeah i know that. let me rephrase then, "without stdlib modules used".

#

or other modules

sick hound
#

what about builtins

#

or __main__

brisk zenith
#

stop being pedantic.

sick hound
#

Yeah I'm not sure how you would do try/except without stdlib

brisk zenith
#

it's an interesting challenge

sick hound
#

*or exec/eval (technically this is not one liner as it has \n)

#

(...are we allowed non-stdlib modules? :P)

#

i don't think there's any way to do that

#

unless you allow codetype/functiontype

#

it uses contextlib

#

seriously?

#
(lambda __contextlib, __print: (lambda __out: (lambda __ctx: [__ctx.__enter__(), __ctx.__exit__(None, None, None), __out[0](lambda: None)][2])(__contextlib.nested(type('except', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: __exctype is not None and (issubclass(__exctype, Exception) and [True for __out[0] in [((__print('b'), lambda after: after())[1])]][0])})(), type('try', (), {'__enter__': lambda self: None, '__exit__': lambda __self, __exctype, __value, __traceback: [False for __out[0] in [((__print('a'), (lambda __after: __after()))[1])]][0]})())))([None]))(__import__('contextlib', level=0), __import__('__builtin__', level=0).__dict__['print'])```
#

yes

#

oh yeah
Just read source rather than checking try/except \🤦

#
type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\nd\x00\x83\x00\x01\x00W\x00n*\x04\x00e\x00k\nr4\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda:1/0,lambda e:print(e),None),('BaseException','e'),(),'','',0,b''),globals())()```
#

@brisk zenith @sick hound is that cheating?...

#

does it use try/except... by evaluating

#

and it uses \n so no

#

what

#

why are you not allowing \n

#

it doesn't make any sense to disallow it there

#

because it's a newline?

#

If you're allowed to craete text newliens you can just eval it

#

All you're dooing it making it more abstract evals

#
type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:1/0,lambda e:print(e),None),('BaseException','e'),(),'','',0,b''),globals())()```
#

@sick hound there, there aren't any newlines anymore. happy?!

rugged sparrow
#

@sick hound cant get return value, and can it do except?

sick hound
#

it can do except, but it catches all exceptions and you have to decide yourself which exceptions you want and rethrow the ones you don't

rugged sparrow
#

ah

sick hound
#
(lambda f,e,l=[]:(type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:l.append(f()),lambda x:l.append(e(x)),None),('BaseException','e'),(),'','',0,b''),globals())(),l.pop())[1])```
#

now it can get the return value

rugged sparrow
#

nice

rugged sparrow
#

@sick hound is that just the bytecode for try except?

sick hound
#

yes

rugged sparrow
#

ah

sick hound
#
>>> import dis
>>> dis.dis(type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:l.append(f()),lambda x:l.append(e(x)),None),('BaseException','e'),(),'','',0,b''),globals()))
  0           0 SETUP_EXCEPT            12 (to 14)
              2 LOAD_CONST               0 (<function <lambda> at 0x000001FEE2FA1E18>)
              4 LOAD_CONST               0 (<function <lambda> at 0x000001FEE2FA1E18>)
              6 CALL_FUNCTION            1
              8 POP_TOP
             10 POP_BLOCK
             12 JUMP_FORWARD            42 (to 56)
        >>   14 DUP_TOP
             16 LOAD_NAME                0 (BaseException)
             18 COMPARE_OP              10 (exception match)
             20 POP_JUMP_IF_FALSE       54
             22 POP_TOP
             24 STORE_NAME               1 (e)
             26 POP_TOP
             28 SETUP_FINALLY           14 (to 44)
             30 LOAD_CONST               1 (<function <lambda> at 0x000001FEE4F75510>)
             32 LOAD_NAME                1 (e)
             34 CALL_FUNCTION            1
             36 POP_TOP
             38 POP_BLOCK
             40 POP_EXCEPT
             42 LOAD_CONST               2 (None)
        >>   44 LOAD_CONST               2 (None)
             46 STORE_NAME               1 (e)
             48 DELETE_NAME              1 (e)
             50 END_FINALLY
             52 JUMP_FORWARD             2 (to 56)
        >>   54 END_FINALLY
        >>   56 LOAD_CONST               2 (None)
             58 RETURN_VALUE```
rugged sparrow
#

im trying to figure out a way to do mine without imports

rugged sparrow
#
tryExcept = type('tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
   "__init__":lambda self,f=lambda:None,e=Exception:[setattr(self,'e',e),setattr(self,'f',f)][0],
   "__enter__":lambda self:None,
   "__exit__":lambda self, *args:([True,self.f()][0] if self.e in args[0].__mro__ else False) if args[0] != None else False
})
``` @brisk zenith would you count this as no imports?
brisk zenith
#

i suppose so :D

rugged sparrow
#

sweet

#

yay for oneline try/except

#

now to neaten it up a ton

sick hound
#

@brisk zenith is this no imports? py (lambda f,e,l=[]:(type(lambda:0)(type((lambda:0).__code__)(0,0,0,16,0,b'y\x0cd\x00d\x00\x83\x01\x01\x00W\x00n*\x04\x00e\x00k\nr6\x01\x00Z\x01\x01\x00z\x0ed\x01e\x01\x83\x01\x01\x00W\x00Y\x00d\x02d\x02Z\x01[\x01X\x00n\x02X\x00d\x02S\x00',(lambda _:l.append(f()),lambda x:l.append(e(x)),None),('BaseException','e'),(),'','',0,b''),globals())(),l.pop())[1])

rugged sparrow
#
tryExcept = type('tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
   "__init__":lambda self,f=lambda:None,e=Exception:[setattr(self,'f',f),setattr(self,'e',e if isinstance(e,list) else [e])][0],
   "__enter__":lambda self:None,
   "__exit__":lambda self, *args:[True,self.f()] if args[0] != None and any([e in args[0].__mro__ for e in self.e]) else False
})``` neaten'd up a bit, also can now take a list of exception types
#
tryExcept = type('tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
   "__init__":lambda self,f=lambda:None,e=Exception,p=False:[setattr(self,'f',f),setattr(self,'e',e if isinstance(e,list) else [e]),setattr(self,'p',p)][0],
   "__enter__":lambda self:None,
   "__exit__":lambda self, *args:[True,self.f(args[1]) if self.p else self.f()] if args[0] != None and any([e in args[0].__mro__ for e in self.e]) else False
})``` and now it has the optional flag ``p`` which will make it give the exception instance to the ``except`` lambda (``f``)
gilded orchid
#

Could there be a folder on the GitHub just for silly workarounds that people find for the limitations of lambdas?

#

E.g: that try/except thing, the while loop thing from a while ago and defining globals

rugged sparrow
#

@gilded orchid you mean while loop with iter()?

gilded orchid
#

yeah

rugged sparrow
#

i think we should have that

gilded orchid
#
e.update({'h':b[int(input(''+f'1:{b[5][0]} '+f'2:{b[6][0]}'+' '+f' 3:{b[7][0]}) 4:{b[8][0]}'))+4]})

I keep on getting errors that I'm giving update 2 arguments instead of just one (e is globals() and b is a tuple)

#

(also this is part of my code art thing which is why it looks so weird)

#

(also that input thing is pretty much just 1 2 3 or 4)

brisk zenith
#

@sick hound i guess so, but i feel like that's some sort of cheating. you're just doing eval but with bytecode, more or less. still, that's an interesting way of doing it for sure :D

rugged sparrow
#

@gilded orchid idk why that would say your giving it 2 args

#

but do you want my input handler that i wrote for my tictactoe?

gilded orchid
#

nvm, turns out I missed out a comma earlier and it took me 10 minuites to work that out

rugged sparrow
#

it makes sure input is a number in a range

gilded orchid
#

I think it's fine as it is, I'm kind of running out of space to finish this off so I don't really want to add anything else in the earlier bits of my code

rugged sparrow
#

ah makes sense

#

@brisk zenith what do you think about making a github repo for workarounds like this?

gilded orchid
#

(1.5 if h[1] in b[1:3] else 1)
Is there a way I could get this to work with a new line between [1:3] and else?

#

nvm turns out I can put the newline before the last square bracket for it to work

rugged sparrow
#
tryExceptRet = lambda t,args=[None],f=lambda e=0:None, e=Exception,r=[],y=[]:[
   y.clear(),
   y.append(type(
         'tryExcept',(*(lambda d=[]:[[d.append(c) if c.__name__=='ContextDecorator' else None for c in object.__subclasses__()],d][1])(),),{
            "__init__":lambda self,f=lambda:None,e=Exception,p=False:[setattr(self,'f',f),setattr(self,'e',e if isinstance(e,list) else [e]),setattr(self,'p',p)][0],
            "__enter__":lambda self:None,
            "__exit__":lambda self, *args:[True,r.append(self.f(args[1])) if self.p else r.append(self.f())] if args[0] != None and any([e in args[0].__mro__ for e in self.e]) else False
         }
      )
   ),
   r.clear(),
   r.append(y[0](f=f,e=e,p=f.__code__.co_argcount == 1)(t)(*args) if t.__code__.co_argcount else y[0](f=f,e=e,p=f.__code__.co_argcount == 1)(t)()),
   r[0]
][4]``` now the return value is either try or except lambda respectivly, and its one call that looks like ```py
tryExceptRet(t=lambda a:a/0,args=[1],f=lambda: 'error',e=ZeroDivisionError)```
#

args is passed to try lambda with *args

#
tryExceptRet(t=lambda a:a/0,args=[1],f=lambda err: f'error:{err}',e=ZeroDivisionError)``` and all you have to do to get exception passed to except lambda is make it have one arg
gilded orchid
#

globals().update({'a':1, 'b': a+1}) Is there a way to get something like this to work without using a second update?

rugged sparrow
#

@gilded orchid wdym

#

whats the context?

gilded orchid
#

It gives an error saying that a is not defined

#

That's just an example of it since posting my actual code would be a nightmare

rugged sparrow
#

oooh

#

cause a doesnt exist yet?

gilded orchid
#

nvm then