Skip to content

Instantly share code, notes, and snippets.

@badocelot
Last active March 22, 2018 02:57
Show Gist options
  • Save badocelot/26b4a7e994ccffd39e396c9d6cc1936e to your computer and use it in GitHub Desktop.
Save badocelot/26b4a7e994ccffd39e396c9d6cc1936e to your computer and use it in GitHub Desktop.
Class for weakly-typed objects that obfuscate the wrapped object's type
import operator
__all__ = ['weak']
def apply_operator(op, a, b):
types = lambda x: x, float, int, complex
for a_type in types:
for b_type in types:
try:
return op(a_type(a), b_type(b))
except (TypeError, ValueError):
pass
return str(a) + str(b)
def try_conversion(cls, value):
try:
return cls(value)
except (TypeError, ValueError):
return cls()
class weak:
__slots__ = ()
def __new__(cls, value):
# don't telescope weak wrappers
if isinstance(value, weak):
return value
obj = value
class inner(cls):
__slots__ = ()
def __call__(self, *args, **kwargs):
try:
return weak(obj(*args, **kwargs))
except TypeError:
return self if len(args) == 0 and len(kwargs) == 0 else None
def __repr__(self):
return '<weakly-typed object>'
# attribute operations
def __delattr__(self, name):
try:
obj.__delattr__(name)
except AttributeError:
return
def __getattribute__(self, name):
try:
return weak(obj.__getattribute__(name))
except AttributeError:
return None
def __setattr__(self, name, value):
try:
obj.__setattr__(name, value)
except AttributeError:
return
def __dir__(self):
return ()
# iterator operations
def __iter__(self):
try:
return iter(weak(x) for x in obj)
except TypeError:
return iter((self,))
def __next__(self):
try:
return weak(next(obj))
except TypeError:
return self
# container operations
def __delitem__(self, key):
try:
del obj[key]
except TypeError:
return
def __getitem__(self, key):
try:
return weak(obj[key])
except TypeError:
return self if key == 0 else None
def __len__(self):
try:
return len(obj)
except TypeError:
return 1
def __setitem__(self, key, value):
try:
obj[key] = value
except TypeError:
return
# conversion operations
def __bool__(self):
return try_conversion(bool, obj)
def __complex__(self):
return try_conversion(complex, obj)
def __float__(self):
return try_conversion(float, obj)
def __int__(self):
return try_conversion(int, obj)
def __round__(self, ndigits = None):
try:
return round(obj, ndigits)
except TypeError:
return 0
def __str__(self):
return try_conversion(str, obj)
# comparison operations
def __eq__(self, other):
return weak(apply_operator(operator.eq, obj, other))
def __ge__(self, other):
return weak(apply_operator(operator.ge, obj, other))
def __gt__(self, other):
return weak(apply_operator(operator.gt, obj, other))
def __le__(self, other):
return weak(apply_operator(operator.le, obj, other))
def __lt__(self, other):
return weak(apply_operator(operator.le, obj, other))
def __ne__(self, other):
return weak(apply_operator(operator.ne, obj, other))
# arithmetic operations
def __add__(self, other):
return weak(apply_operator(operator.add, obj, other))
def __divmod__(self, other):
return weak(apply_operator(divmod, obj, other))
def __floordiv__(self, other):
return weak(apply_operator(operator.floordiv, obj, other))
def __lshift__(self, other):
return weak(apply_operator(operator.lshift, obj, other))
def __matmul__(self, other):
return weak(apply_operator(operator.mathmul, obj, other))
def __mod__(self, other):
return weak(apply_operator(operator.mod, obj, other))
def __mul__(self, other):
return weak(apply_operator(operator.mul, obj, other))
def __pow__(self, other):
return weak(apply_operator(operator.pow, obj, other))
def __rshift__(self, other):
return weak(apply_operator(operator.rshift, obj, other))
def __sub__(self, other):
return weak(apply_operator(operator.sub, obj, other))
def __truediv__(self, other):
return weak(apply_operator(operator.truediv, obj, other))
# right-hand arithmetic operations
def __radd__(self, other):
return weak(apply_operator(operator.add, other, obj))
def __rdivmod__(self, other):
return weak(apply_operator(divmod, other, obj))
def __rfloordiv__(self, other):
return weak(apply_operator(operator.floordiv, other, obj))
def __rlshift__(self, other):
return weak(apply_operator(operator.lshift, other, obj))
def __rmatmul__(self, other):
return weak(apply_operator(operator.matmul, other, obj))
def __rmod__(self, other):
return weak(apply_operator(operator.mod, other, obj))
def __rmul__(self, other):
return weak(apply_operator(operator.mul, other, obj))
def __rpow__(self, other):
return weak(apply_operator(operator.pow, other, obj))
def __rrshift__(self, other):
return weak(apply_operator(operator.rshift, other, obj))
def __rsub__(self, other):
return weak(apply_operator(operator.sub, other, obj))
def __rtruediv__(self, other):
return weak(apply_operator(operator.truediv, other, obj))
# bitwise operations
def __and__(self, other):
return weak(apply_operator(operator.and_, obj, other))
def __or__(self, other):
return weak(apply_operator(operator.or_, obj, other))
def __xor__(self, other):
return weak(apply_operator(operator.xor, obj, other))
# right-hand bitwise operations
def __rand__(self, other):
return weak(apply_operator(operator.and_, other, obj))
def __ror__(self, other):
return weak(apply_operator(operator.or_, other, obj))
def __rxor__(self, other):
return weak(apply_operator(operator.xor, other, obj))
# unary arithmetic operations
def __abs__(self):
try:
return weak(abs(obj))
except TypeError:
return self
def __invert__(self):
try:
return weak(~obj)
except TypeError:
return self
def __neg__(self):
try:
return weak(-obj)
except TypeError:
return self
def __pos__(self):
try:
return weak(+obj)
except TypeError:
return self
return object.__new__(inner)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment