Python metaprogramming
python #metaprogramming
Examples from my codebases https://github.com/barisozmen/python-cookbook/blob/main/metaclasses.py ```python from clisupport import gracefulkeyboardinterrupt, debuggeron_error
class SingletonMetaclass(type): instances = {} def _call(cls, args, *kwargs): if cls not in cls.instances: cls.instances[cls] = super().call_(args, *kwargs) return cls.instances[cls]
class GracefulInterruptMetaclass(type): def new(cls, name, bases, attrs): # Wrap all public methods with gracefulkeyboardinterrupt for key, value in attrs.items(): if callable(value) and not key.startswith(''): attrs[key] = gracefulkeyboardinterrupt(value) return super().new_(cls, name, bases, attrs)
class DebuggerOnErrorMetaclass(type): def new(cls, name, bases, attrs): for key, value in attrs.items(): if callable(value) and not key.startswith(''): attrs[key] = debuggeronerror(value) return super().new_(cls, name, bases, attrs)
class LoggedMetaclass(type): """Metaclass that logs all method calls for a class""" def new(cls, name, bases, attrs): # Wrap callable methods with logging for key, value in attrs.items(): if callable(value) and not key.startswith(''): attrs[key] = cls.logcall(value) return super().new(cls, name, bases, attrs)
@staticmethod
def log_call(func):
def wrapper(*args, **kwargs):
print(f'Calling: {func.__name__}')
result = func(*args, **kwargs)
print(f'Finished: {func.__name__}')
return result
return wrapper
class StaticMethodsByDefault(type): def new(cls, name, bases, attrs): # Make all methods static by default, except special methods for key, value in attrs.items(): if callable(value) and not key.startswith(''): attrs[key] = staticmethod(value) return super().new__(cls, name, bases, attrs)
https://github.com/barisozmen/python-cookbook/blob/main/cli_support.py
```python
import os
import sys
from functools import wraps
def graceful_keyboard_interrupt(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except KeyboardInterrupt:
print("\n\nKeyboard interrupt detected. Exiting...")
print("\nGoodbye! 👋\n")
sys.exit(1)
return wrapper
def debugger_on_error(func):
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
import pdb; pdb.set_trace()
raise e
return wrapper
https://github.com/barisozmen/python-cookbook/blob/main/singletons.py ```python from metaclasses import SingletonMetaclass
class Counter(metaclass=SingletonMetaclass): def init(self): self.count = 0
@property
def next_id(self):
self.count += 1
return self.count
class Config(metaclass=SingletonMetaclass): def init(self): self._settings = {}
def set(self, key, value):
self._settings[key] = value
def get(self, key, default=None):
return self._settings.get(key, default)
- David Beazley - Reinventing the Parser Generator - PyCon 2018 (archived) — Writing lexers and parsers is a complex problem that often involves the use of special tools and domain specific lang...
- Write a Compiler Course - Warmup Project — - his another lib is PLY, he developed SLY for enabling new [[Python metaprogramming]] features (see [[David Beazley ...