Create a gist now

Instantly share code, notes, and snippets.

pythonic monkey patching built-in types
# found this from Armin R. on Twitter, what a beautiful gem ;)
import ctypes
from types import DictProxyType, MethodType
# figure out side of _Py_ssize_t
if hasattr(ctypes.pythonapi, 'Py_InitModule4_64'):
_Py_ssize_t = ctypes.c_int64
else:
_Py_ssize_t = ctypes.c_int
# regular python
class _PyObject(ctypes.Structure):
pass
_PyObject._fields_ = [
('ob_refcnt', _Py_ssize_t),
('ob_type', ctypes.POINTER(_PyObject))
]
# python with trace
if object.__basicsize__ != ctypes.sizeof(_PyObject):
class _PyObject(ctypes.Structure):
pass
_PyObject._fields_ = [
('_ob_next', ctypes.POINTER(_PyObject)),
('_ob_prev', ctypes.POINTER(_PyObject)),
('ob_refcnt', _Py_ssize_t),
('ob_type', ctypes.POINTER(_PyObject))
]
class _DictProxy(_PyObject):
_fields_ = [('dict', ctypes.POINTER(_PyObject))]
def reveal_dict(proxy):
if not isinstance(proxy, DictProxyType):
raise TypeError('dictproxy expected')
dp = _DictProxy.from_address(id(proxy))
ns = {}
ctypes.pythonapi.PyDict_SetItem(ctypes.py_object(ns),
ctypes.py_object(None),
dp.dict)
return ns[None]
def get_class_dict(cls):
d = getattr(cls, '__dict__', None)
if d is None:
raise TypeError('given class does not have a dictionary')
if isinstance(d, DictProxyType):
return reveal_dict(d)
return d
def test():
from random import choice
d = get_class_dict(str)
d['foo'] = lambda x: ''.join(choice((c.upper, c.lower))() for c in x)
print "and this is monkey patching str".foo()
if __name__ == '__main__':
test()
@lgastako

Sicko.

@pawelgalazka

Cool. But I found this on: http://docs.python.org/3.3/c-api/typeobj.html#PyTypeObject.tp_dict
Warning It is not safe to use PyDict_SetItem() on or otherwise modify tp_dict with the dictionary C-API.

@fatiherikli

I was looking for it. Thanks.

@thedrow

@pawelgalazka What exactly do you mean by unsafe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment