class Calculator: def eval(self, string): return eval(string) calc = Calculator() calc.eval('3+4') import random from patched import PatchSuite, patch class BrokenCalc(PatchSuite): @patch(parent=Calculator) def eval(self, string): value = eval(string) random_inacuracy = 0.01 * value * random.random() return value + 0.01 + random_inacuracy with BrokenCalc(): print( calc.eval('3+4')) import collections collections.Counter('animal') from patched import wrappers @patch(parent=collections, attribute='Counter') class MyCounter(collections.Counter): def __init__(self, *args, **kw): c = collections.Counter(*args, **kw) zeros_dict = dict.fromkeys(c.keys(), 0) super().__init__(zeros_dict) with PatchSuite([MyCounter.make_patch()]): print( collections.Counter('animal')) type(MyCounter) == patch MyCounter MyCounter.make_patch() type(_) load -r 31-35 ../patched/patching/wrappers.py patch.off() try: return self.run(*args, **kwargs) finally: patch.on() class StopCounting(PatchSuite): class Meta: parent = collections.Counter @patch(wrapper_type=wrappers.Hook) def _subtract_self(self, *args, _subtract=collections.Counter.subtract, **kw): _subtract(self, **self) @patch() def _return_self(self, *args, **kw): return self __init__ = update = subtract = _subtract_self __add__ = __sub__ = __or__ = __and__ = _return_self del _subtract_self, _return_self with StopCounting(): c = collections.Counter('animal') c c2 = collections.Counter('elephant') c2 with StopCounting(): print('union gives %s' % (c | c2)) class StopCounting(PatchSuite): class Meta: parent = collections.Counter @patch(wrapper_type=wrappers.Hook) def _subtract_self(self, *args, _subtract=collections.Counter.subtract, **kw): _subtract(self, **self) @patch(pass_event=True) def _return_counter(self, *args, event, _subtract=collections.Counter.subtract, **kw): ret = event.wrapped_func(self, *args, **kw) _subtract(ret, **ret) return ret __init__ = update = subtract = _subtract_self __add__ = __sub__ = __or__ = __and__ = _return_counter del _subtract_self, _return_counter c2 = collections.Counter('elephant') c = collections.Counter('animal') with StopCounting(): print('union gives %s' % (c | c2)) from patched.core.threadlocal import ThreadLocalMixin class MyGlobal(ThreadLocalMixin): global_name = "yet_another_global" instance = MyGlobal.instance() instance.var = 5 print( MyGlobal.instance().var) MyGlobal.instance() == MyGlobal() from patched import get_storage get_storage()['some.parameter'] = {'default': True} get_storage()['some'] from patched.core.objects import Logger new = Logger() load -r 5-18 ../patched/tools/ipython.py @magics_class class BlackMagics(Magics): @line_magic def events(self, line): logger = Logger.instance() if not line: return logger event = logger[int(line)] return event def load_ipython_extension(ip): ip.register_magics(BlackMagics) load_ext patched.tools.ipython import os os.chdir('../examples/rest-tutorial') os.environ['DJANGO_SETTINGS_MODULE'] = 'tutorial.settings' import django # if it's django >= 1.7, you need the next 2 lines django.setup() from rest_framework.test import APIClient client = APIClient() client.login(username='vitalii', password='123') resp = client.post('/snippets/', {'title': 'my title', 'code': 'True = False'}) resp.data from rest_framework import serializers as rest_serializers, fields as rest_fields class SerializerPatch(PatchSuite): from_native = patch(parent=rest_serializers.Serializer) with SerializerPatch(): resp = client.post('/snippets/', {'title': 'my title', 'code': 'True = False'}) print(resp.data) events events 0 _.rv.code class WritableFieldPatch(PatchSuite): field_from_native = patch(parent=rest_fields.WritableField, log_prefix='-> ') Logger() with SerializerPatch() + WritableFieldPatch(): resp = client.post('/snippets/', {'title': 'my title', 'code': 'True = False'}) print(resp.data) events events 3 from patched.patching.events import HookFunctionExecuted from patched.patching import wrappers from IPython.lib.pretty import pretty class FieldFromNativeEvent(HookFunctionExecuted): def _log_pretty_(self, p, cycle): if cycle: p.text('HookFunction(..)') return with p.group(len(self.log_prefix), self.log_prefix): p.text( pretty(self.field_value)) p.text(' was set into ') p.breakable() p.text(self.field_name) class WritableFieldPatch(PatchSuite): @patch(wrapper_type=wrappers.Hook, event_class=FieldFromNativeEvent, parent=rest_fields.WritableField, pass_event=True, log_prefix='-> ', ) def field_from_native(self, data, files, field_name, into, return_value, event): event.field_name = field_name event.field_value = into.get(field_name) from patched.core.objects import Logger Logger() with SerializerPatch() + WritableFieldPatch(): resp = client.post('/snippets/', {'title': 'my title', 'code': 'True = False'}) print(resp.data) events