##// END OF EJS Templates
Migrate to Mergely 3.3.4....
Migrate to Mergely 3.3.4. RhodeCode 2.2.5 distributed Mergely 3.3.4 with some of the changes that Mergely 3.3.3 in RhodeCode 1.7.2 also had. That do however not seem to be changes we want for Kallithea this way and we take the 3.3.4 files as they are. I've also included the Mergely license file, as downloaded from: http://www.mergely.com/license.php That LICENSE file is kept in HTML just as it was downloaded from their website. While it's a bit annoying to keep the license file in HTML, this is the way it came from upstream so we'll leave it that way. Since the Javascript code is used with other GPLv3 Javascript, we are using the GPL option of Mergely's tri-license. Finally, note that previously, this was incorrectly called "mergerly", so the opportunity is taken here to correct the name. That required changes to diff_2way.html. As commands:: $ wget -N --output-document LICENSE-MERGELY.html http://www.mergely.com/license.php $ hg add LICENSE-MERGELY.html $ hg mv rhodecode/public/css/mergerly.css rhodecode/public/css/mergely.css $ hg mv rhodecode/public/js/mergerly.js rhodecode/public/js/mergely.js $ sed -i 's,mergerly\.,mergely,g' rhodecode/templates/files/diff_2way.html $ ( cd /tmp; \ wget -N http://www.mergely.com/releases/mergely-3.3.4.zip; \ unzip mergely-3.3.4.zip ) $ sha256sum /tmp/mergely-3.3.4.zip 87415d30494bbe829c248881aa7cdc0303f7e70b458a5f687615564d4498cc82 mergely-3.3.4.zip $ cp /tmp/mergely-3.3.4/lib/mergely.js rhodecode/public/js/mergely.js $ cp /tmp/mergely-3.3.4/lib/mergely.css rhodecode/public/css/mergely.css $ sed -i -e '/^ \* Version/a\ *\n * NOTE by bkuhn@sfconservancy.org for Kallithea:\n * Mergely license appears at http://www.mergely.com/license.php and in LICENSE-MERGELY.html' rhodecode/public/js/mergely.js rhodecode/public/css/mergely.css

File last commit:

r3643:2a7cbc53 beta
r4125:aa3b5594 rhodecode-2.2.5-gpl
Show More
nose_parametrized.py
238 lines | 8.1 KiB | text/x-python | PythonLexer
import re
import new
import inspect
import logging
import logging.handlers
from functools import wraps
from nose.tools import nottest
from unittest import TestCase
def _terrible_magic_get_defining_classes():
""" Returns the set of parent classes of the class currently being defined.
Will likely only work if called from the ``parameterized`` decorator.
This function is entirely @brandon_rhodes's fault, as he suggested
the implementation: http://stackoverflow.com/a/8793684/71522
"""
stack = inspect.stack()
if len(stack) <= 4:
return []
frame = stack[3]
code_context = frame[4][0].strip()
if not code_context.startswith("class "):
return []
_, parents = code_context.split("(", 1)
parents, _ = parents.rsplit(")", 1)
return eval("[" + parents + "]", frame[0].f_globals, frame[0].f_locals)
def parameterized(input):
""" Parameterize a test case:
>>> add1_tests = [(1, 2), (2, 3)]
>>> class TestFoo(object):
... @parameterized(add1_tests)
... def test_add1(self, input, expected):
... assert_equal(add1(input), expected)
>>> @parameterized(add1_tests)
... def test_add1(input, expected):
... assert_equal(add1(input), expected)
>>>
"""
if not hasattr(input, "__iter__"):
raise ValueError("expected iterable input; got %r" % (input,))
def parameterized_helper(f):
attached_instance_method = [False]
parent_classes = _terrible_magic_get_defining_classes()
if any(issubclass(cls, TestCase) for cls in parent_classes):
raise Exception("Warning: '@parameterized' tests won't work "
"inside subclasses of 'TestCase' - use "
"'@parameterized.expand' instead")
@wraps(f)
def parameterized_helper_method(self=None):
if self is not None and not attached_instance_method[0]:
# confusingly, we need to create a named instance method and
# attach that to the class...
cls = self.__class__
im_f = new.instancemethod(f, None, cls)
setattr(cls, f.__name__, im_f)
attached_instance_method[0] = True
for args in input:
if isinstance(args, basestring):
args = [args]
# ... then pull that named instance method off, turning it into
# a bound method ...
if self is not None:
args = [getattr(self, f.__name__)] + list(args)
else:
args = [f] + list(args)
# ... then yield that as a tuple. If those steps aren't
# followed precicely, Nose gets upset and doesn't run the test
# or doesn't run setup methods.
yield tuple(args)
f.__name__ = "_helper_for_%s" % (f.__name__,)
parameterized_helper_method.parameterized_input = input
parameterized_helper_method.parameterized_func = f
return parameterized_helper_method
return parameterized_helper
def to_safe_name(s):
return re.sub("[^a-zA-Z0-9_]", "", s)
def parameterized_expand_helper(func_name, func, args):
def parameterized_expand_helper_helper(self=()):
if self != ():
self = (self,)
return func(*(self + args))
parameterized_expand_helper_helper.__name__ = str(func_name)
return parameterized_expand_helper_helper
def parameterized_expand(input):
""" A "brute force" method of parameterizing test cases. Creates new test
cases and injects them into the namespace that the wrapped function
is being defined in. Useful for parameterizing tests in subclasses
of 'UnitTest', where Nose test generators don't work.
>>> @parameterized.expand([("foo", 1, 2)])
... def test_add1(name, input, expected):
... actual = add1(input)
... assert_equal(actual, expected)
...
>>> locals()
... 'test_add1_foo_0': <function ...> ...
>>>
"""
def parameterized_expand_wrapper(f):
stack = inspect.stack()
frame = stack[1]
frame_locals = frame[0].f_locals
base_name = f.__name__
for num, args in enumerate(input):
name_suffix = "_%s" % (num,)
if len(args) > 0 and isinstance(args[0], basestring):
name_suffix += "_" + to_safe_name(args[0])
name = base_name + name_suffix
new_func = parameterized_expand_helper(name, f, args)
frame_locals[name] = new_func
return nottest(f)
return parameterized_expand_wrapper
parameterized.expand = parameterized_expand
def assert_contains(haystack, needle):
if needle not in haystack:
raise AssertionError("%r not in %r" % (needle, haystack))
def assert_not_contains(haystack, needle):
if needle in haystack:
raise AssertionError("%r in %r" % (needle, haystack))
def imported_from_test():
""" Returns true if it looks like this module is being imported by unittest
or nose. """
import re
import inspect
nose_re = re.compile(r"\bnose\b")
unittest_re = re.compile(r"\bunittest2?\b")
for frame in inspect.stack():
file = frame[1]
if nose_re.search(file) or unittest_re.search(file):
return True
return False
def assert_raises(func, exc_type, str_contains=None, repr_contains=None):
try:
func()
except exc_type, e:
if str_contains is not None and str_contains not in str(e):
raise AssertionError("%s raised, but %r does not contain %r"
% (exc_type, str(e), str_contains))
if repr_contains is not None and repr_contains not in repr(e):
raise AssertionError("%s raised, but %r does not contain %r"
% (exc_type, repr(e), repr_contains))
return e
else:
raise AssertionError("%s not raised" % (exc_type,))
log_handler = None
def setup_logging():
""" Configures a log handler which will capure log messages during a test.
The ``logged_messages`` and ``assert_no_errors_logged`` functions can be
used to make assertions about these logged messages.
For example::
from ensi_common.testing import (
setup_logging, teardown_logging, assert_no_errors_logged,
assert_logged,
)
class TestWidget(object):
def setup(self):
setup_logging()
def teardown(self):
assert_no_errors_logged()
teardown_logging()
def test_that_will_fail(self):
log.warning("this warning message will trigger a failure")
def test_that_will_pass(self):
log.info("but info messages are ok")
assert_logged("info messages are ok")
"""
global log_handler
if log_handler is not None:
logging.getLogger().removeHandler(log_handler)
log_handler = logging.handlers.BufferingHandler(1000)
formatter = logging.Formatter("%(name)s: %(levelname)s: %(message)s")
log_handler.setFormatter(formatter)
logging.getLogger().addHandler(log_handler)
def teardown_logging():
global log_handler
if log_handler is not None:
logging.getLogger().removeHandler(log_handler)
log_handler = None
def logged_messages():
assert log_handler, "setup_logging not called"
return [(log_handler.format(record), record) for record in log_handler.buffer]
def assert_no_errors_logged():
for _, record in logged_messages():
if record.levelno >= logging.WARNING:
# Assume that the nose log capture plugin is being used, so it will
# show the exception.
raise AssertionError("an unexpected error was logged")
def assert_logged(expected_msg_contents):
for msg, _ in logged_messages():
if expected_msg_contents in msg:
return
raise AssertionError("no logged message contains %r"
% (expected_msg_contents,))