def _iter_patch_candidates(cls): """helper to scan for monkeypatches. returns tuple containing: * object (module or class) * attribute of object * value of attribute * whether it should or should not be patched """ # XXX: this and assert_unpatched() could probably be refactored to use # the PatchManager class to do the heavy lifting. from django.contrib.auth import models, hashers user_attrs = ["check_password", "set_password"] model_attrs = ["check_password", "make_password"] hasher_attrs = [ "check_password", "make_password", "get_hasher", "identify_hasher", "get_hashers" ] objs = [ (models, model_attrs), (models.User, user_attrs), (hashers, hasher_attrs), ] for obj, patched in objs: for attr in dir(obj): if attr.startswith("_"): continue value = obj.__dict__.get( attr, UNSET) # can't use getattr() due to GAE if value is UNSET and attr not in patched: continue value = get_method_function(value) source = getattr(value, "__module__", None) if source: yield obj, attr, source, (attr in patched)
def patch(self, path, value, wrap=False): """monkeypatch object+attr at <path> to have <value>, stores original""" assert value != _UNSET current = self._get_path(path) try: orig, expected = self._state[path] except KeyError: self.log.debug("patching resource: %r", path) orig = current else: self.log.debug("modifying resource: %r", path) if not self._is_same_value(current, expected): warn("overridding resource another library has patched: %r" % path, PasslibRuntimeWarning) if wrap: assert callable(value) wrapped = orig wrapped_by = value def wrapper(*args, **kwds): return wrapped_by(wrapped, *args, **kwds) update_wrapper(wrapper, value) value = wrapper if callable(value): # needed by DjangoContextAdapter init get_method_function(value)._patched_original_value = orig self._set_path(path, value) self._state[path] = (orig, value)
def _iter_patch_candidates(cls): """helper to scan for monkeypatches. returns tuple containing: * object (module or class) * attribute of object * value of attribute * whether it should or should not be patched """ # XXX: this and assert_unpatched() could probably be refactored to use # the PatchManager class to do the heavy lifting. from django.contrib.auth import models, hashers user_attrs = ["check_password", "set_password"] model_attrs = ["check_password", "make_password"] objs = [(models, model_attrs), (models.User, user_attrs), (hashers, ["check_password", "make_password", "get_hasher", "identify_hasher"]), ] for obj, patched in objs: for attr in dir(obj): if attr.startswith("_"): continue value = obj.__dict__.get(attr, UNSET) # can't use getattr() due to GAE if value is UNSET and attr not in patched: continue value = get_method_function(value) source = getattr(value, "__module__", None) if source: yield obj, attr, source, (attr in patched)
def patch(self, path, value, wrap=False): """monkeypatch object+attr at <path> to have <value>, stores original""" assert value != _UNSET current = self._get_path(path) try: orig, expected = self._state[path] except KeyError: self.log.debug("patching resource: %r", path) orig = current else: self.log.debug("modifying resource: %r", path) if not self._is_same_value(current, expected): warn( "overridding resource another library has patched: %r" % path, PasslibRuntimeWarning, ) if wrap: assert callable(value) wrapped = orig wrapped_by = value def wrapper(*args, **kwds): return wrapped_by(wrapped, *args, **kwds) update_wrapper(wrapper, value) value = wrapper if callable(value): # needed by DjangoContextAdapter init get_method_function(value)._patched_original_value = orig self._set_path(path, value) self._state[path] = (orig, value)
class django_salted_sha1_test(HandlerCase, _DjangoHelper): """test django_salted_sha1""" handler = hash.django_salted_sha1 django_has_encoding_glitch = True known_correct_hashes = [ # test extra large salt ("password", 'sha1$123abcdef$e4a1877b0e35c47329e7ed7e58014276168a37ba' ), # test django 1.4 alphanumeric salt ("test", 'sha1$bcwHF9Hy8lxS$6b4cfa0651b43161c6f1471ce9523acf1f751ba3'), # ensures utf-8 used for unicode (UPASS_USD, 'sha1$c2e86$0f75c5d7fbd100d587c127ef0b693cde611b4ada'), (UPASS_TABLE, 'sha1$6d853$ef13a4d8fb57aed0cb573fe9c82e28dc7fd372d4'), # generic password ("MyPassword", 'sha1$54123$893cf12e134c3c215f3a76bd50d13f92404a54d3'), ] known_unidentified_hashes = [ 'md5$aa$bb', ] known_malformed_hashes = [ # checksum too short 'sha1$c2e86$0f75', ] fuzz_setting_salt_size = get_method_function( django_salted_md5_test.fuzz_setting_salt_size)
def accepts_keyword(func, key): """test if function accepts specified keyword""" params = inspect.signature(get_method_function(func)).parameters if not params: return False arg = params.get(key) if arg and arg.kind not in _VAR_ANY_SET: return True # XXX: annoying what we have to do to determine if VAR_KWDS in use. return params[list(params)[-1]].kind == _VAR_KEYWORD
def _is_same_value(left, right): """check if two values are the same (stripping method wrappers, etc)""" return get_method_function(left) == get_method_function(right)
def accepts_keyword(func, key): """test if function accepts specified keyword""" spec = inspect.getargspec(get_method_function(func)) return key in spec.args or spec.keywords is not None