def __new__(clsarg, *args, **kwargs): cls = super(_Signals, clsarg).__new__(clsarg, *args, **kwargs) for signal in cls._signals: (on, sig) = _handler_factory(signal) setattr(cls, on.__name__, types.UnboundMethodType(on, None, cls)) setattr(cls, sig.__name__, types.UnboundMethodType(sig, None, cls)) return cls
def setup_logging(self): # we replace the formatTime() method of the log observer that # twistd set up for us, with a method that uses our preferred # timestamp format. for o in twlog.theLogPublisher.observers: # o might be a FileLogObserver's .emit method if type(o) is type(self.setup_logging): # bound method ob = o.im_self if isinstance(ob, twlog.FileLogObserver): newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__) ob.formatTime = newmeth # TODO: twisted >2.5.0 offers maxRotatedFiles=50 lgfurl_file = os.path.join(self.basedir, "private", "logport.furl").encode( get_filesystem_encoding()) if os.path.exists(lgfurl_file): os.remove(lgfurl_file) self.log_tub.setOption("logport-furlfile", lgfurl_file) lgfurl = self.config.get_config("node", "log_gatherer.furl", "") if lgfurl: # this is in addition to the contents of log-gatherer-furlfile self.log_tub.setOption("log-gatherer-furl", lgfurl) self.log_tub.setOption("log-gatherer-furlfile", os.path.join(self.basedir, "log_gatherer.furl")) incident_dir = os.path.join(self.basedir, "logs", "incidents") foolscap.logging.log.setLogDir( incident_dir.encode(get_filesystem_encoding())) twlog.msg("Foolscap logging initialized") twlog.msg("Note to developers: twistd.log does not receive very much.") twlog.msg( "Use 'flogtool tail -c NODEDIR/private/logport.furl' instead") twlog.msg("and read docs/logging.rst")
def setup_logging(self): # we replace the formatTime() method of the log observer that # twistd set up for us, with a method that uses our preferred # timestamp format. for o in twlog.theLogPublisher.observers: # o might be a FileLogObserver's .emit method if type(o) is type(self.setup_logging): # bound method ob = o.im_self if isinstance(ob, twlog.FileLogObserver): newmeth = types.UnboundMethodType(formatTimeTahoeStyle, ob, ob.__class__) ob.formatTime = newmeth # TODO: twisted >2.5.0 offers maxRotatedFiles=50 lgfurl_file = os.path.join(self.basedir, "private", "logport.furl").encode(get_filesystem_encoding()) self.tub.setOption("logport-furlfile", lgfurl_file) lgfurl = self.get_config("node", "log_gatherer.furl", "") if lgfurl: # this is in addition to the contents of log-gatherer-furlfile self.tub.setOption("log-gatherer-furl", lgfurl) self.tub.setOption("log-gatherer-furlfile", os.path.join(self.basedir, "log_gatherer.furl")) self.tub.setOption("bridge-twisted-logs", True) incident_dir = os.path.join(self.basedir, "logs", "incidents") # this doesn't quite work yet: unit tests fail foolscap.logging.log.setLogDir(incident_dir.encode(get_filesystem_encoding()))
def poisonSpam(): old = Spam.update def newUpdate(self): old(self) print('poison whole class') Spam.update = types.UnboundMethodType(newUpdate, None, Spam)
def test_methodtype(): import types class A: def foo(self): return "ok" assert types.UnboundMethodType(A.foo, A())() == "ok" assert types.MethodType(A.foo, A())() == "ok"
def __init__(cls, name, bases, dict): type.__init__(cls, name, bases, dict) def change_method(self, *args, **kwargs): raise NotImplementedError, name + ' instances cannot be changed.' if cls.register: ContainerRegistry.append((cls, cls.containing_classes)) for meth in cls.change_methods: setattr(cls, meth, types.UnboundMethodType(change_method, None, cls)) cls.register=False
def setfunc(self, hookfunc): name = self.ref.__name__ if self.type == 1: setattr(self.ctx, name, hookfunc) return hookfunc if self.type == 2: if self.is_static: newfunc = staticmethod(hookfunc) else: newfunc = hookfunc setattr(self.ctx, name, newfunc) return newfunc if self.type == 3: newmethod = types.UnboundMethodType(hookfunc, None, self.ctx) setattr(self.ctx, name, newmethod) return newmethod obj = self.ctx() newmethod = weakmethod(hookfunc, self.ctx) setattr(obj, name, newmethod) return newmethod
def make_cffi(cls): """Decorator to add CFFI versions of each test method.""" try: import zstd_cffi except ImportError: return cls # If CFFI version is available, dynamically construct test methods # that use it. for attr in dir(cls): fn = getattr(cls, attr) if not inspect.ismethod(fn) and not inspect.isfunction(fn): continue if not fn.__name__.startswith('test_'): continue name = '%s_cffi' % fn.__name__ # Replace the "zstd" symbol with the CFFI module instance. Then copy # the function object and install it in a new attribute. if isinstance(fn, types.FunctionType): globs = dict(fn.__globals__) globs['zstd'] = zstd_cffi new_fn = types.FunctionType(fn.__code__, globs, name, fn.__defaults__, fn.__closure__) new_method = new_fn else: globs = dict(fn.__func__.func_globals) globs['zstd'] = zstd_cffi new_fn = types.FunctionType(fn.__func__.func_code, globs, name, fn.__func__.func_defaults, fn.__func__.func_closure) new_method = types.UnboundMethodType(new_fn, fn.im_self, fn.im_class) setattr(cls, name, new_method) return cls
def __new__(cls, name, bases, dct): cls_obj = type.__new__(cls, name, bases, dct) if cls_obj.label is not None: for kls in cls_obj._addable_from: if cls_obj._is_setter: function_name = 'set_%s' % cls_obj.label else: function_name = 'add_%s' % cls_obj.label if not getattr(kls, function_name, None): def add_thing(self, *args, **kwargs): if isinstance(self, Pyrehol): kwargs['root'] = self else: kwargs['root'] = self.root if cls_obj._is_setter and getattr( self, 'did_set_%s' % cls_obj.label, False): raise ValueError( 'Cannot set %s on the same block more than once' % cls_obj.label) o = cls_obj(*args, **kwargs) setattr(self, 'set_%s' % cls_obj.label, True) self.contents.append(o) return o add_thing.__name__ = function_name add_thing.__doc__ = '%s %s on this %s. Returns the %s.\n\n' % ( 'Set the' if cls_obj._is_setter else 'Add a new', cls_obj.label, kls.__name__, name.replace('_', '', 1), ) if cls_obj.__init__.__doc__: add_thing.__doc__ += cls_obj.__init__.__doc__ setattr(kls, function_name, types.UnboundMethodType(add_thing, None, kls)) return cls_obj
def Mock(bases=(), *initargs, **kw): """ Simple factory for dummy classes that can be used as replacement for the real implementation in tests. Base classes for the mock can be specified using the first parameter, which must be either a tuple of class objects or a single class object. If the bases parameter is omitted, the base class of the mock will be object. So to create a mock that is derived from the builtin dict type, you can do: >>> mock = Mock(dict) >>> mock['foo'] = 'bar' >>> mock['foo'] 'bar' Attributes of the class are provided by any additional keyword parameters. >>> mock = Mock(foo='bar') >>> mock.foo 'bar' Objects produces by this function have the special feature of not requiring the 'self' parameter on methods, because you should keep data at the scope of the test function. So you can just do: >>> mock = Mock(add=lambda x,y: x+y) >>> mock.add(1, 1) 2 To access attributes from the mock object from inside a lambda function, just access the mock itself: >>> mock = Mock(dict, do=lambda x: 'going to the %s' % mock[x]) >>> mock['foo'] = 'bar' >>> mock.do('foo') 'going to the bar' Because assignments or other types of statements don't work in lambda functions, assigning to a local variable from a mock function requires some extra work: >>> myvar = [None] >>> mock = Mock(set=lambda x: myvar.__setitem__(0, x)) >>> mock.set(1) >>> myvar[0] 1 """ if not isinstance(bases, tuple): bases = (bases, ) # if base classes have abstractmethod and abstractproperty, # create dummy methods for abstracts attrs = {} def dummyfn(self, *args, **kwargs): raise NotImplementedError for base in bases: if getattr(base, '__metaclass__', None) is not abc.ABCMeta: continue fn = types.UnboundMethodType(dummyfn, None, base) for name, attr in inspect.getmembers(base): if name in attrs: continue if isinstance(attr, abc.abstractproperty) or \ isinstance(attr, types.UnboundMethodType) and \ getattr(attr, '__isabstractmethod__', False) is True: attrs[name] = fn cls = type('Mock', bases, attrs) mock = cls(*initargs) for k, v in kw.items(): setattr(mock, k, v) return mock
def _bind(cls, fn): return types.UnboundMethodType(fn, None, cls)
def make_cffi(cls): """Decorator to add CFFI versions of each test method.""" # The module containing this class definition should # `import zstandard as zstd`. Otherwise things may blow up. mod = inspect.getmodule(cls) if not hasattr(mod, 'zstd'): raise Exception('test module does not contain "zstd" symbol') if not hasattr(mod.zstd, 'backend'): raise Exception('zstd symbol does not have "backend" attribute; did ' 'you `import zstandard as zstd`?') # If `import zstandard` already chose the cffi backend, there is nothing # for us to do: we only add the cffi variation if the default backend # is the C extension. if mod.zstd.backend == 'cffi': return cls old_env = dict(os.environ) os.environ['PYTHON_ZSTANDARD_IMPORT_POLICY'] = 'cffi' try: try: mod_info = imp.find_module('zstandard') mod = imp.load_module('zstandard_cffi', *mod_info) except ImportError: return cls finally: os.environ.clear() os.environ.update(old_env) if mod.backend != 'cffi': raise Exception('got the zstandard %s backend instead of cffi' % mod.backend) # If CFFI version is available, dynamically construct test methods # that use it. for attr in dir(cls): fn = getattr(cls, attr) if not inspect.ismethod(fn) and not inspect.isfunction(fn): continue if not fn.__name__.startswith('test_'): continue name = '%s_cffi' % fn.__name__ # Replace the "zstd" symbol with the CFFI module instance. Then copy # the function object and install it in a new attribute. if isinstance(fn, types.FunctionType): globs = dict(fn.__globals__) globs['zstd'] = mod new_fn = types.FunctionType(fn.__code__, globs, name, fn.__defaults__, fn.__closure__) new_method = new_fn else: globs = dict(fn.__func__.func_globals) globs['zstd'] = mod new_fn = types.FunctionType(fn.__func__.func_code, globs, name, fn.__func__.func_defaults, fn.__func__.func_closure) new_method = types.UnboundMethodType(new_fn, fn.im_self, fn.im_class) setattr(cls, name, new_method) return cls
def patch_model(model_to_patch, class_to_patch_with): """ Adapted from https://gist.github.com/1402045 Monkey patch a django model with additional or replacement fields and methods. - All fields and methods that didn't exist previously are added. - Existing methods with the same names are renamed with <methodname>__overridden, so there are still accessible, then the new ones are added. - Existing fields with the same name are deleted and replaced with the new fields. The class used to patch the model MUST be an old-style class (so this may not work with Python 3). Example (in your models.py): from django.contrib.auth.models import User from django_quicky.models import patch_model class UserOverride: # we don't need to inherit from anything email = models.EmailField(_('e-mail address'), unique=True) new_field = models.CharField(_('new field'), max_length=10) def save(self, *args, **kwargs): # Call original save() method self.save__overridden(*args, **kwargs) # More custom save patch_model(User, UserOverride) """ from django.db.models.fields import Field # The _meta attribute is where the definition of the fields is stored in # django model classes. patched_meta = getattr(model_to_patch, '_meta') field_lists = (patched_meta.local_fields, patched_meta.local_many_to_many) for name, obj in class_to_patch_with.__dict__.iteritems(): # If the attribute is a field, delete any field with the same name. if isinstance(obj, Field): for field_list in field_lists: match = ((i, f) for i, f in enumerate(field_list) if f.name == name) try: i, field = match.next() # The creation_counter is used by django to know in # which order the database columns are declared. We # get it to ensure that when we override a field it # will be declared in the same position as before. obj.creation_counter = field.creation_counter field_list.pop(i) finally: break # Add "__overridden" to method names if they already exist. elif isinstance( obj, (types.FunctionType, property, staticmethod, classmethod)): # rename the potential old method attr = getattr(model_to_patch, name, None) if attr: setattr(model_to_patch, name + '__overridden', attr) # bind the new method to the object if isinstance(obj, types.FunctionType): obj = types.UnboundMethodType(obj, None, model_to_patch) # Add the new field/method name and object to the model. model_to_patch.add_to_class(name, obj)
raise return StrictExceptionIOLoop def patch_http_client(): """Patch a simple_httpclient instance to raise exceptions generated in callbacks. See https://github.com/facebook/tornado/pull/652 """ @contextlib.contextmanager def better_cleanup(self): try: yield except Exception, e: if self.final_callback: self._run_callback(HTTPResponse(self.request, 599, error=e, request_time=time.time() - self.start_time, )) if hasattr(self, "stream"): self.stream.close() else: # If our callback has already been called, we are probably # catching an exception that is not caused by us but rather # some child of our callback. Rather than drop it on the floor, # pass it along. raise _HTTPConnection.cleanup = types.UnboundMethodType(better_cleanup, None, _HTTPConnection)
def patch_model(model_to_patch, class_to_patch_with): """ Adapted from http://www.ravelsoft.com/blog/2010/patchmodel-hacky-solution-extending-authuser-class Monkey patch a django model with additional or replacement fields and methods. All fields and methods that didn't exist previously are added. Existing methods with the same name are replaced with <methodname>__overridden. Existing fields with the same name are deleted and replaced with the new field. The class used to patch the model must be an old-style class. Example: from django.contrib.auth.models import User from compatriot.utils import patch_model class UserOverride: email = models.EmailField(_('e-mail address'), unique=True) new_field = models.CharField(_('new field'), max_length=10) def save(self, *args, **kwargs): # Custom save # Call original save() method self.save__overridden(*args, **kwargs) # More custom save patch_model(User, UserOverride) @param model_to_patch: Class to patch @param class_to_patch_with: Class with definitions of new fields and methods. """ # The _meta attribute is where the definition of the fields is stored in # django model classes. patched_meta = getattr(model_to_patch, '_meta') for name, obj in class_to_patch_with.__dict__.items(): # If the attribute is a field, delete it if it already exists. if isinstance(obj, Field): index = -1 for field_table in (patched_meta.local_fields, patched_meta.local_many_to_many): for i in xrange(0, len(field_table)): field = field_table[i] if field.name == name: index = i # The creation_counter is used by django to know in # which order the database columns are declared. We # get it to ensure that when we override a field it # will be declared in the same position as before. creation_counter = field_table[i].creation_counter break if index != -1: field_table.pop(index) obj.creation_counter = creation_counter break # Add "__overridden" to method names if they already exist. elif isinstance(obj, types.FunctionType) or isinstance(obj, property): if getattr(model_to_patch, name, None): setattr(model_to_patch, name + '__overridden', getattr(model_to_patch, name)) if isinstance(obj, types.FunctionType): obj = types.UnboundMethodType(obj, None, model_to_patch) # Add the new field/method name and object to the model. model_to_patch.add_to_class(name, obj)