Skip to content

Instantly share code, notes, and snippets.

@jorenham
Created December 21, 2020 03:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorenham/67c6f3f2055a53e849de4a2583ed007e to your computer and use it in GitHub Desktop.
Save jorenham/67c6f3f2055a53e849de4a2583ed007e to your computer and use it in GitHub Desktop.
Ridiculous syntax for class creation with extra parameters in pure python
"""
This is valid (but ridiculous) syntax:
spam_with_eggs = Spam<<'eggs'>>('ham', 'bacon')
"""
class _TraitAlias:
__slots__ = ('__origin__', '__traits__')
def __init__(self, cls, traits):
self.__origin__ = cls
self.__traits__ = traits
def __call__(self, *args, **kwargs):
raise SyntaxError("trait definition is missing the closing '>'")
def __rshift__(self, args):
print(
f"{self.__origin__.__name__}"
f"<<{','.join(map(repr, self.__traits__))}>>"
f"({', '.join(map(repr, args))})"
)
# TODO: generic subscript [...]
if isinstance(args, tuple):
instance = self.__origin__(*args)
instance.__origin_class__ = self
instance.__origin__ = self.__origin__
instance.__traits__ = self.__traits__
return instance
elif isinstance(args, list):
if not len(args):
raise SyntaxError('empty generics list')
# wut, star expressions don't work for __class_getitem__?
cls = self.__origin__[args[0] if len(args) == 1 else tuple(args)]
return _TraitAlias(cls, self.__traits__)
else:
raise SyntaxError(f"'(' or '[' expected, got {args}")
__gt__ = __rshift__
class TraitType(type):
def __lshift__(cls, traits):
_traits = traits if isinstance(traits, tuple) else (traits,)
print('<', cls.__name__, traits)
return _TraitAlias(cls, _traits)
__lt__ = __lshift__
class Trait(metaclass=TraitType):
...
if __name__ == '__main__':
class Spam(Trait):
def __init__(self, *args):
self.args = args
spam = Spam<<'eggs'>>('ham', 'bacon')
print("spam args:", spam.args)
print("spam traits:", spam.__traits__)
# to illustrate why used shifts instead of lt/gt:
spam2 = Spam<'eggs'>('ham', 'bacon')
print("spam2 args:", spam2.args)
print("spam2 traits:", spam2.__traits__)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment