Skip to content

Instantly share code, notes, and snippets.

@bricef
Last active May 16, 2024 03:31
Show Gist options
  • Save bricef/1b0389ee89bd5b55113c7f3f3d6394ae to your computer and use it in GitHub Desktop.
Save bricef/1b0389ee89bd5b55113c7f3f3d6394ae to your computer and use it in GitHub Desktop.
Monkey patching of builtins in Python3
# found this from Armin R. on Twitter, what a beautiful gem ;)
import ctypes
from types import MappingProxyType, 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, MappingProxyType):
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, MappingProxyType):
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()
@jamespreed
Copy link

You need parenthesis around the print arguments for this to work in Python 3. ;)

@bricef
Copy link
Author

bricef commented Feb 10, 2020

Thanks @jamespreed will fix :)

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