summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoris Roovers <jroovers@cisco.com>2016-12-27 17:07:50 +0100
committerJoris Roovers <jroovers@cisco.com>2016-12-27 17:07:50 +0100
commitd28dba35bc3deea12402d5810f6dac221553984c (patch)
treec3923f4eee40fb804ed5189709b7cba86d8a4f32
parent8f6cd8cfcc5346a47565c74cc6042ba1785082a2 (diff)
More unicode-related changes
This commit adds more changes for proper unicode support: - Introduce of the utils module with the ustr function that is now used everywhere where we used str() before. ustr() is smart enough to convert handle unicode in both python 2 and 3. - Monkeypatch of unittest2.case.str to deal with lack of unicode support for assertRaisesRegex in unittest2 - handle_option_error decorator for gitlint.config to deal with configuration errors for general options more elegantly - flake8 errors are now printed in red color when running run_tests.sh - Multiple test cases have been updated so that they also test unicode compatibility: test_cli.py, test_config.py, test_config_builder.py Additional tests will be updated to include better unicode coverage in the follow-up commits.
-rw-r--r--.pylintrc2
-rw-r--r--gitlint/cli.py14
-rw-r--r--gitlint/config.py56
-rw-r--r--gitlint/options.py16
-rw-r--r--gitlint/tests/base.py13
-rw-r--r--gitlint/tests/expected/debug_output12
-rw-r--r--gitlint/tests/samples/config/gitlintconfig6
-rw-r--r--gitlint/tests/samples/config/invalid-option-value2
-rw-r--r--gitlint/tests/samples/config/nonexisting-option2
-rw-r--r--gitlint/tests/samples/config/nonexisting-rule2
-rw-r--r--gitlint/tests/test_cli.py68
-rw-r--r--gitlint/tests/test_config.py47
-rw-r--r--gitlint/tests/test_config_builder.py54
-rw-r--r--gitlint/tests/test_user_rules.py3
-rw-r--r--gitlint/utils.py15
-rwxr-xr-xrun_tests.sh3
16 files changed, 174 insertions, 131 deletions
diff --git a/.pylintrc b/.pylintrc
index cc707f3..891107e 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -11,7 +11,7 @@
# R0801: Similar lines in files
# I0011: Informational: locally disabled pylint
# I0013: Informational: Ignoring entire file
-disable=C0111,W0511,W0142,W0622,W0223,W0212,R0901,R0801,I0011,I0013
+disable=C0111,W0511,W0142,W0622,W0223,W0212,R0901,R0801,I0011,I0013,anomalous-backslash-in-string
[Format]
max-line-length=120
diff --git a/gitlint/cli.py b/gitlint/cli.py
index 0ece968..0e8f48b 100644
--- a/gitlint/cli.py
+++ b/gitlint/cli.py
@@ -8,6 +8,7 @@ from gitlint.lint import GitLinter
from gitlint.config import LintConfigBuilder, LintConfigError, LintConfigGenerator
from gitlint.git import GitContext, GitContextError
from gitlint import hooks
+from gitlint.utils import ustr
DEFAULT_CONFIG_FILE = ".gitlint"
@@ -53,11 +54,11 @@ def build_config(ctx, target, config_path, c, extra_path, ignore, verbose, silen
config = config_builder.build()
if debug:
- click.echo(str(config), nl=True)
+ click.echo(ustr(config), nl=True)
return config, config_builder
except LintConfigError as e:
- click.echo(u"Config Error: {0}".format(str(e)))
+ click.echo(u"Config Error: {0}".format(ustr(e)))
ctx.exit(CONFIG_ERROR_CODE) # return CONFIG_ERROR_CODE on config error
@@ -104,11 +105,10 @@ def lint(ctx):
else:
stdin_str = sys.stdin.read()
if sys.version_info[0] == 2:
- stdin_str = unicode(stdin_str, 'utf-8') # pylint: disable=undefined-variable
-
+ stdin_str = unicode(stdin_str, 'utf-8') # noqa # pylint: disable=undefined-variable
gitcontext = GitContext.from_commit_msg(stdin_str)
except GitContextError as e:
- click.echo(str(e))
+ click.echo(ustr(e))
ctx.exit(GIT_CONTEXT_ERROR_CODE)
config_builder = ctx.obj[1]
@@ -137,7 +137,7 @@ def install_hook(ctx):
click.echo(u"Successfully installed gitlint commit-msg hook in {0}".format(hook_path))
ctx.exit(0)
except hooks.GitHookInstallerError as e:
- click.echo(str(e), err=True)
+ click.echo(ustr(e), err=True)
ctx.exit(GIT_CONTEXT_ERROR_CODE)
@@ -153,7 +153,7 @@ def uninstall_hook(ctx):
click.echo(u"Successfully uninstalled gitlint commit-msg hook from {0}".format(hook_path))
ctx.exit(0)
except hooks.GitHookInstallerError as e:
- click.echo(str(e), err=True)
+ click.echo(ustr(e), err=True)
ctx.exit(GIT_CONTEXT_ERROR_CODE)
diff --git a/gitlint/config.py b/gitlint/config.py
index a941ed5..47f9570 100644
--- a/gitlint/config.py
+++ b/gitlint/config.py
@@ -16,11 +16,25 @@ except ImportError: # pragma: no cover
# python 2.4-2.6
from ordereddict import OrderedDict # pragma: no cover
+from gitlint.utils import ustr
from gitlint import rules # For some weird reason pylint complains about this, pylint: disable=unused-import
from gitlint import options
from gitlint import user_rules
+def handle_option_error(func):
+ """ Decorator that calls given method/function and handles any RuleOptionError gracefully by converting it to a
+ LintConfigError. """
+
+ def wrapped(*args):
+ try:
+ return func(*args)
+ except options.RuleOptionError as e:
+ raise LintConfigError(ustr(e))
+
+ return wrapped
+
+
class LintConfigError(Exception):
pass
@@ -63,46 +77,38 @@ class LintConfig(object):
return self._target.value if self._target else None
@target.setter
+ @handle_option_error
def target(self, value):
- try:
- return self._target.set(value)
- except options.RuleOptionError as e:
- raise LintConfigError(str(e))
+ return self._target.set(value)
@property
def verbosity(self):
return self._verbosity.value
@verbosity.setter
+ @handle_option_error
def verbosity(self, value):
- try:
- self._verbosity.set(value)
- if self.verbosity < 0 or self.verbosity > 3:
- raise LintConfigError("Option 'verbosity' must be set between 0 and 3")
- except options.RuleOptionError as e:
- raise LintConfigError(str(e))
+ self._verbosity.set(value)
+ if self.verbosity < 0 or self.verbosity > 3:
+ raise LintConfigError("Option 'verbosity' must be set between 0 and 3")
@property
def ignore_merge_commits(self):
return self._ignore_merge_commits.value
@ignore_merge_commits.setter
+ @handle_option_error
def ignore_merge_commits(self, value):
- try:
- return self._ignore_merge_commits.set(value)
- except options.RuleOptionError as e:
- raise LintConfigError(str(e))
+ return self._ignore_merge_commits.set(value)
@property
def debug(self):
return self._debug.value
@debug.setter
+ @handle_option_error
def debug(self, value):
- try:
- return self._debug.set(value)
- except options.RuleOptionError as e:
- raise LintConfigError(str(e))
+ return self._debug.set(value)
@property
def extra_path(self):
@@ -132,7 +138,7 @@ class LintConfig(object):
self._rules[rule_class.id] = rule_obj
except (options.RuleOptionError, user_rules.UserRuleError) as e:
- raise LintConfigError(str(e))
+ raise LintConfigError(ustr(e))
@property
def ignore(self):
@@ -151,6 +157,7 @@ class LintConfig(object):
def get_rule(self, rule_id_or_name):
# try finding rule by id
+ rule_id_or_name = ustr(rule_id_or_name) # convert to unicode first
rule = self._rules.get(rule_id_or_name)
# if not found, try finding rule by name
if not rule:
@@ -158,6 +165,8 @@ class LintConfig(object):
return rule
def _get_option(self, rule_name_or_id, option_name):
+ rule_name_or_id = ustr(rule_name_or_id) # convert to unicode first
+ option_name = ustr(option_name)
rule = self.get_rule(rule_name_or_id)
if not rule:
raise LintConfigError(u"No such rule '{0}'".format(rule_name_or_id))
@@ -181,9 +190,8 @@ class LintConfig(object):
try:
option.set(option_value)
except options.RuleOptionError as e:
- raise LintConfigError(
- u"'{0}' is not a valid value for option '{1}.{2}'. {3}.".format(option_value, rule_name_or_id,
- option_name, str(e)))
+ msg = u"'{0}' is not a valid value for option '{1}.{2}'. {3}."
+ raise LintConfigError(msg.format(option_value, rule_name_or_id, option_name, ustr(e)))
def set_general_option(self, option_name, option_value):
attr_name = option_name.replace("-", "_")
@@ -278,10 +286,10 @@ class LintConfigBuilder(object):
for section_name in parser.sections():
for option_name, option_value in parser.items(section_name):
- self.set_option(section_name, option_name, option_value)
+ self.set_option(section_name, option_name, ustr(option_value))
except ConfigParserError as e:
- raise LintConfigError(str(e))
+ raise LintConfigError(ustr(e))
def build(self, config=None):
""" Build a real LintConfig object by normalizing and validating the options that were previously set on this
diff --git a/gitlint/options.py b/gitlint/options.py
index c24e5d7..3768830 100644
--- a/gitlint/options.py
+++ b/gitlint/options.py
@@ -1,11 +1,7 @@
from abc import abstractmethod
import os
-# see if we have a unicode function (=python 2), if not, we have python 3: just declare unicode as being str():
-try:
- unicode("")
-except NameError:
- unicode = str # pylint: disable=invalid-name
+from gitlint.utils import ustr
class RuleOptionError(Exception):
@@ -42,7 +38,7 @@ class RuleOption(object):
class StrOption(RuleOption):
def set(self, value):
- self.value = unicode(value)
+ self.value = ustr(value)
class IntOption(RuleOption):
@@ -69,7 +65,7 @@ class IntOption(RuleOption):
class BoolOption(RuleOption):
def set(self, value):
- value = unicode(value).strip().lower()
+ value = ustr(value).strip().lower()
if value not in ['true', 'false']:
raise RuleOptionError(u"Option '{0}' must be either 'true' or 'false'".format(self.name))
self.value = value == 'true'
@@ -83,14 +79,14 @@ class ListOption(RuleOption):
if isinstance(value, list):
the_list = value
else:
- the_list = unicode(value).split(",")
+ the_list = ustr(value).split(",")
- self.value = [unicode(item.strip()) for item in the_list if item.strip() != ""]
+ self.value = [ustr(item.strip()) for item in the_list if item.strip() != ""]
class DirectoryOption(RuleOption):
def set(self, value):
- value = unicode(value)
+ value = ustr(value)
if not os.path.isdir(value):
msg = u"Option {0} must be an existing directory (current value: '{1}')".format(self.name, value)
raise RuleOptionError(msg)
diff --git a/gitlint/tests/base.py b/gitlint/tests/base.py
index 1046ee2..423272e 100644
--- a/gitlint/tests/base.py
+++ b/gitlint/tests/base.py
@@ -1,11 +1,20 @@
import os
import sys
+import unittest2
-from unittest2 import TestCase
from gitlint.git import GitContext
+# unittest2's assertRaisesRegex doesn't do unicode comparison.
+# Let's monkeypatch the str() function to point to unicode() so that it does :)
+# For reference, this is where this patch is required:
+# https://hg.python.org/unittest2/file/tip/unittest2/case.py#l227
+try:
+ unittest2.case.str = unicode
+except NameError:
+ pass # python 3
-class BaseTestCase(TestCase):
+
+class BaseTestCase(unittest2.TestCase):
""" Base class of which all gitlint unit test classes are derived. Provides a number of convenience methods. """
# In case of assert failures, print the full error message
diff --git a/gitlint/tests/expected/debug_output1 b/gitlint/tests/expected/debug_output1
index 0cd2494..f3569fa 100644
--- a/gitlint/tests/expected/debug_output1
+++ b/gitlint/tests/expected/debug_output1
@@ -14,7 +14,7 @@ target: {target}
T3: title-trailing-punctuation
T4: title-hard-tab
T5: title-must-not-contain-word
- words=WIP
+ words=WIP,bögus
T7: title-match-regex
regex=.*
B1: body-max-line-length
diff --git a/gitlint/tests/samples/config/gitlintconfig b/gitlint/tests/samples/config/gitlintconfig
index 3e7d02a..8c93f71 100644
--- a/gitlint/tests/samples/config/gitlintconfig
+++ b/gitlint/tests/samples/config/gitlintconfig
@@ -7,7 +7,9 @@ debug = false
[title-max-length]
line-length=20
-
[B1]
# B1 = body-max-line-length
-line-length=30 \ No newline at end of file
+line-length=30
+
+[title-must-not-contain-word]
+words=WIP,bögus \ No newline at end of file
diff --git a/gitlint/tests/samples/config/invalid-option-value b/gitlint/tests/samples/config/invalid-option-value
index 21f3c23..92015aa 100644
--- a/gitlint/tests/samples/config/invalid-option-value
+++ b/gitlint/tests/samples/config/invalid-option-value
@@ -3,7 +3,7 @@ ignore=title-trailing-whitespace,B2
verbosity = 1
[title-max-length]
-line-length=foo
+line-length=föo
[B1]
diff --git a/gitlint/tests/samples/config/nonexisting-option b/gitlint/tests/samples/config/nonexisting-option
index b0a4b9f..6964c77 100644
--- a/gitlint/tests/samples/config/nonexisting-option
+++ b/gitlint/tests/samples/config/nonexisting-option
@@ -3,7 +3,7 @@ ignore=title-trailing-whitespace,B2
verbosity = 1
[title-max-length]
-foobar=foo
+föobar=foo
[B1]
diff --git a/gitlint/tests/samples/config/nonexisting-rule b/gitlint/tests/samples/config/nonexisting-rule
index f6a811f..c0f0d2b 100644
--- a/gitlint/tests/samples/config/nonexisting-rule
+++ b/gitlint/tests/samples/config/nonexisting-rule
@@ -2,7 +2,7 @@
ignore=title-trailing-whitespace,B2
verbosity = 1
-[foobar]
+[föobar]
line-length=20
diff --git a/gitlint/tests/test_cli.py b/gitlint/tests/test_cli.py
index d359c81..9fb7275 100644
--- a/gitlint/tests/test_cli.py
+++ b/gitlint/tests/test_cli.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
import os
try:
@@ -36,33 +38,33 @@ class CLITests(BaseTestCase):
sys.stdin.isatty.return_value = True
def git_log_side_effect(*args, **_kwargs):
- return_values = {'--pretty=%B': "commit-title\n\ncommit-body", '--pretty=%aN': "test author",
- '--pretty=%aE': "test-email@foo.com", '--pretty=%ai': "2016-12-03 15:28:15 01:00",
- '--pretty=%P': "abc"}
+ return_values = {'--pretty=%B': u"commït-title\n\ncommït-body", '--pretty=%aN': u"test åuthor",
+ '--pretty=%aE': u"test-email@föo.com", '--pretty=%ai': "2016-12-03 15:28:15 01:00",
+ '--pretty=%P': u"åbc"}
return return_values[args[1]]
sh.git.log.side_effect = git_log_side_effect
- sh.git.return_value = "file1.txt\npath/to/file2.txt\n"
+ sh.git.return_value = u"file1.txt\npåth/to/file2.txt\n"
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
result = self.cli.invoke(cli.cli)
- self.assertEqual(stderr.getvalue(), '3: B5 Body message is too short (11<20): "commit-body"\n')
+ self.assertEqual(stderr.getvalue(), u'3: B5 Body message is too short (11<20): "commït-body"\n')
self.assertEqual(result.exit_code, 1)
def test_input_stream(self):
- expected_output = "1: T2 Title has trailing whitespace: \"WIP: title \"\n" + \
- "1: T5 Title contains the word 'WIP' (case-insensitive): \"WIP: title \"\n" + \
- "3: B6 Body message is missing\n"
+ expected_output = u"1: T2 Title has trailing whitespace: \"WIP: tïtle \"\n" + \
+ u"1: T5 Title contains the word 'WIP' (case-insensitive): \"WIP: tïtle \"\n" + \
+ u"3: B6 Body message is missing\n"
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
- result = self.cli.invoke(cli.cli, input='WIP: title \n')
+ result = self.cli.invoke(cli.cli, input=u'WIP: tïtle \n')
self.assertEqual(stderr.getvalue(), expected_output)
self.assertEqual(result.exit_code, 3)
self.assertEqual(result.output, "")
def test_silent_mode(self):
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
- result = self.cli.invoke(cli.cli, ["--silent"], input='WIP: title \n')
+ result = self.cli.invoke(cli.cli, ["--silent"], input=u"WIP: tïtle \n")
self.assertEqual(stderr.getvalue(), "")
self.assertEqual(result.exit_code, 3)
self.assertEqual(result.output, "")
@@ -71,7 +73,7 @@ class CLITests(BaseTestCase):
# We only test -v and -vv, more testing is really not required here
# -v
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
- result = self.cli.invoke(cli.cli, ["-v"], input='WIP: title \n')
+ result = self.cli.invoke(cli.cli, ["-v"], input=u"WIP: tïtle \n")
self.assertEqual(stderr.getvalue(), "1: T2\n1: T5\n3: B6\n")
self.assertEqual(result.exit_code, 3)
self.assertEqual(result.output, "")
@@ -82,14 +84,14 @@ class CLITests(BaseTestCase):
"3: B6 Body message is missing\n"
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
- result = self.cli.invoke(cli.cli, ["-vv"], input='WIP: title \n')
+ result = self.cli.invoke(cli.cli, ["-vv"], input=u"WIP: tïtle \n")
self.assertEqual(stderr.getvalue(), expected_output)
self.assertEqual(result.exit_code, 3)
self.assertEqual(result.output, "")
# -vvvv: not supported -> should print a config error
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
- result = self.cli.invoke(cli.cli, ["-vvvv"], input='WIP: title \n')
+ result = self.cli.invoke(cli.cli, ["-vvvv"], input=u'WIP: tïtle \n')
self.assertEqual(stderr.getvalue(), "")
self.assertEqual(result.exit_code, CLITests.CONFIG_ERROR_CODE)
self.assertEqual(result.output, "Config Error: Option 'verbosity' must be set between 0 and 3\n")
@@ -97,7 +99,7 @@ class CLITests(BaseTestCase):
def test_debug(self):
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
config_path = self.get_sample_path("config/gitlintconfig")
- result = self.cli.invoke(cli.cli, ["--config", config_path, "--debug"], input="WIP: test")
+ result = self.cli.invoke(cli.cli, ["--config", config_path, "--debug"], input=u"WIP: tëst")
expected = self.get_expected('debug_output1', {'config_path': config_path,
'target': os.path.abspath(os.getcwd())})
@@ -108,7 +110,7 @@ class CLITests(BaseTestCase):
def test_extra_path(self):
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
extra_path = self.get_sample_path("user_rules")
- result = self.cli.invoke(cli.cli, ["--extra-path", extra_path, "--debug"], input='Test title\n')
+ result = self.cli.invoke(cli.cli, ["--extra-path", extra_path, "--debug"], input=u"Test tïtle\n")
expected_output = "1: UC1 Commit violation 1: \"Content 1\"\n" + \
"3: B6 Body message is missing\n"
self.assertEqual(stderr.getvalue(), expected_output)
@@ -117,7 +119,7 @@ class CLITests(BaseTestCase):
def test_config_file(self):
with patch('gitlint.display.stderr', new=StringIO()) as stderr:
config_path = self.get_sample_path("config/gitlintconfig")
- result = self.cli.invoke(cli.cli, ["--config", config_path], input="WIP: test")
+ result = self.cli.invoke(cli.cli, ["--config", config_path], input=u"WIP: tëst")
self.assertEqual(result.output, "")
self.assertEqual(stderr.getvalue(), "1: T5\n3: B6\n")
self.assertEqual(result.exit_code, 2)
@@ -126,15 +128,15 @@ class CLITests(BaseTestCase):
# Directory as config file
config_path = self.get_sample_path("config")
result = self.cli.invoke(cli.cli, ["--config", config_path])
- expected_string = "Error: Invalid value for \"-C\" / \"--config\": Path \"{0}\" is a directory.".format(
+ expected_string = u"Error: Invalid value for \"-C\" / \"--config\": Path \"{0}\" is a directory.".format(
config_path)
self.assertEqual(result.output.split("\n")[2], expected_string)
self.assertEqual(result.exit_code, self.USAGE_ERROR_CODE)
# Non existing file
- config_path = self.get_sample_path("foo")
+ config_path = self.get_sample_path(u"föo")
result = self.cli.invoke(cli.cli, ["--config", config_path])
- expected_string = "Error: Invalid value for \"-C\" / \"--config\": Path \"{0}\" does not exist.".format(
+ expected_string = u"Error: Invalid value for \"-C\" / \"--config\": Path \"{0}\" does not exist.".format(
config_path)
self.assertEqual(result.output.split("\n")[2], expected_string)
self.assertEqual(result.exit_code, self.USAGE_ERROR_CODE)
@@ -156,33 +158,33 @@ class CLITests(BaseTestCase):
def test_target_negative(self):
# try setting a non-existing target
- result = self.cli.invoke(cli.cli, ["--target", "/foo/bar"])
+ result = self.cli.invoke(cli.cli, ["--target", u"/föo/bar"])
self.assertEqual(result.exit_code, self.USAGE_ERROR_CODE)
- expected_msg = "Error: Invalid value for \"--target\": Directory \"/foo/bar\" does not exist."
+ expected_msg = u"Error: Invalid value for \"--target\": Directory \"/föo/bar\" does not exist."
self.assertEqual(result.output.split("\n")[2], expected_msg)
# try setting a file as target
target_path = self.get_sample_path("config/gitlintconfig")
result = self.cli.invoke(cli.cli, ["--target", target_path])
self.assertEqual(result.exit_code, self.USAGE_ERROR_CODE)
- expected_msg = "Error: Invalid value for \"--target\": Directory \"{0}\" is a file.".format(target_path)
+ expected_msg = u"Error: Invalid value for \"--target\": Directory \"{0}\" is a file.".format(target_path)
self.assertEqual(result.output.split("\n")[2], expected_msg)
@patch('gitlint.config.LintConfigGenerator.generate_config')
def test_generate_config(self, generate_config):
- result = self.cli.invoke(cli.cli, ["generate-config"], input="testfile\n")
+ result = self.cli.invoke(cli.cli, ["generate-config"], input=u"tëstfile\n")
self.assertEqual(result.exit_code, 0)
- expected_msg = "Please specify a location for the sample gitlint config file [.gitlint]: testfile\n" + \
- "Successfully generated {0}\n".format(os.path.abspath("testfile"))
+ expected_msg = u"Please specify a location for the sample gitlint config file [.gitlint]: tëstfile\n" + \
+ u"Successfully generated {0}\n".format(os.path.abspath(u"tëstfile"))
self.assertEqual(result.output, expected_msg)
- generate_config.assert_called_once_with(os.path.abspath("testfile"))
+ generate_config.assert_called_once_with(os.path.abspath(u"tëstfile"))
def test_generate_config_negative(self):
# Non-existing directory
- result = self.cli.invoke(cli.cli, ["generate-config"], input="/foo/bar")
+ result = self.cli.invoke(cli.cli, ["generate-config"], input=u"/föo/bar")
self.assertEqual(result.exit_code, self.USAGE_ERROR_CODE)
- expected_msg = "Please specify a location for the sample gitlint config file [.gitlint]: /foo/bar\n" + \
- "Error: Directory '/foo' does not exist.\n"
+ expected_msg = u"Please specify a location for the sample gitlint config file [.gitlint]: /föo/bar\n" + \
+ u"Error: Directory '/föo' does not exist.\n"
self.assertEqual(result.output, expected_msg)
# Existing file
@@ -226,11 +228,11 @@ class CLITests(BaseTestCase):
expected_config.target = self.SAMPLES_DIR
install_hook.assert_called_once_with(expected_config)
- @patch('gitlint.hooks.GitHookInstaller.install_commit_msg_hook', side_effect=hooks.GitHookInstallerError("test"))
+ @patch('gitlint.hooks.GitHookInstaller.install_commit_msg_hook', side_effect=hooks.GitHookInstallerError(u"tëst"))
def test_install_hook_negative(self, install_hook):
result = self.cli.invoke(cli.cli, ["install-hook"])
self.assertEqual(result.exit_code, self.GIT_CONTEXT_ERROR_CODE)
- self.assertEqual(result.output, "test\n")
+ self.assertEqual(result.output, u"tëst\n")
expected_config = config.LintConfig()
expected_config.target = os.path.abspath(os.getcwd())
install_hook.assert_called_once_with(expected_config)
@@ -246,11 +248,11 @@ class CLITests(BaseTestCase):
expected_config.target = os.path.abspath(os.getcwd())
uninstall_hook.assert_called_once_with(expected_config)
- @patch('gitlint.hooks.GitHookInstaller.uninstall_commit_msg_hook', side_effect=hooks.GitHookInstallerError("test"))
+ @patch('gitlint.hooks.GitHookInstaller.uninstall_commit_msg_hook', side_effect=hooks.GitHookInstallerError(u"tëst"))
def test_uninstall_hook_negative(self, uninstall_hook):
result = self.cli.invoke(cli.cli, ["uninstall-hook"])
self.assertEqual(result.exit_code, self.GIT_CONTEXT_ERROR_CODE)
- self.assertEqual(result.output, "test\n")
+ self.assertEqual(result.output, u"tëst\n")
expected_config = config.LintConfig()
expected_config.target = os.path.abspath(os.getcwd())
uninstall_hook.assert_called_once_with(expected_config)
diff --git a/gitlint/tests/test_config.py b/gitlint/tests/test_config.py
index aedaaa7..1168f21 100644
--- a/gitlint/tests/test_config.py
+++ b/gitlint/tests/test_config.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
from mock import patch
from gitlint import rules
@@ -21,7 +23,7 @@ class LintConfigTests(BaseTestCase):
self.assertEqual(rule, expected2)
# get non-existing
- rule = config.get_rule('foo')
+ rule = config.get_rule(u'föo')
self.assertIsNone(rule)
def test_set_rule_option(self):
@@ -38,20 +40,20 @@ class LintConfigTests(BaseTestCase):
config = LintConfig()
# non-existing rule
- expected_error_msg = "No such rule 'foobar'"
+ expected_error_msg = u"No such rule 'föobar'"
with self.assertRaisesRegex(LintConfigError, expected_error_msg):
- config.set_rule_option('foobar', 'line-length', 60)
+ config.set_rule_option(u'föobar', u'lïne-length', 60)
# non-existing option
- expected_error_msg = "Rule 'title-max-length' has no option 'foobar'"
+ expected_error_msg = u"Rule 'title-max-length' has no option 'föobar'"
with self.assertRaisesRegex(LintConfigError, expected_error_msg):
- config.set_rule_option('title-max-length', 'foobar', 60)
+ config.set_rule_option('title-max-length', u'föobar', 60)
# invalid option value
- expected_error_msg = "'foo' is not a valid value for option 'title-max-length.line-length'. " + \
- r"Option 'line-length' must be a positive integer \(current value: 'foo'\)."
+ expected_error_msg = u"'föo' is not a valid value for option 'title-max-length.line-length'. " + \
+ u"Option 'line-length' must be a positive integer \(current value: 'föo'\)."
with self.assertRaisesRegex(LintConfigError, expected_error_msg):
- config.set_rule_option('title-max-length', 'line-length', "foo")
+ config.set_rule_option('title-max-length', 'line-length', u"föo")
def test_set_general_option(self):
config = LintConfig()
@@ -113,8 +115,8 @@ class LintConfigTests(BaseTestCase):
config = LintConfig()
# incorrect extra_path
with self.assertRaisesRegex(LintConfigError,
- r"Option extra-path must be an existing directory \(current value: 'foo/bar'\)"):
- config.extra_path = "foo/bar"
+ u"Option extra-path must be an existing directory \(current value: 'föo/bar'\)"):
+ config.extra_path = u"föo/bar"
# extra path contains classes with errors
with self.assertRaisesRegex(LintConfigError,
@@ -124,18 +126,19 @@ class LintConfigTests(BaseTestCase):
def test_set_general_option_negative(self):
config = LintConfig()
+ # Note that we should't test whether we can set unicode because python just doesn't allow unicode attributes
with self.assertRaisesRegex(LintConfigError, "'foo' is not a valid gitlint option"):
- config.set_general_option("foo", "bar")
+ config.set_general_option("foo", u"bår")
# try setting _config_path, this is a real attribute of LintConfig, but the code should prevent it from
# being set
with self.assertRaisesRegex(LintConfigError, "'_config_path' is not a valid gitlint option"):
- config.set_general_option("_config_path", "bar")
+ config.set_general_option("_config_path", u"bår")
# invalid verbosity`
- incorrect_values = [-1, "foo"]
+ incorrect_values = [-1, u"föo"]
for value in incorrect_values:
- expected_msg = r"Option 'verbosity' must be a positive integer \(current value: '{0}'\)".format(value)
+ expected_msg = u"Option 'verbosity' must be a positive integer \(current value: '{0}'\)".format(value)
with self.assertRaisesRegex(LintConfigError, expected_msg):
config.verbosity = value
@@ -145,25 +148,25 @@ class LintConfigTests(BaseTestCase):
config.verbosity = value
# invalid ignore_merge_commits
- incorrect_values = [-1, 4, "foo"]
+ incorrect_values = [-1, 4, u"föo"]
for value in incorrect_values:
with self.assertRaisesRegex(LintConfigError,
- r"Option 'ignore-merge-commits' must be either 'true' or 'false'"):
+ "Option 'ignore-merge-commits' must be either 'true' or 'false'"):
config.ignore_merge_commits = value
# invalid ignore -> not here because ignore is a ListOption which converts everything to a string before
# splitting which means it it will accept just about everything
# invalid debug
- with self.assertRaisesRegex(LintConfigError, r"Option 'debug' must be either 'true' or 'false'"):
- config.debug = "foobar"
+ with self.assertRaisesRegex(LintConfigError, "Option 'debug' must be either 'true' or 'false'"):
+ config.debug = u"föobar"
# extra-path has its own negative test
# invalid target
with self.assertRaisesRegex(LintConfigError,
- r"Option target must be an existing directory \(current value: 'foo/bar'\)"):
- config.target = "foo/bar"
+ u"Option target must be an existing directory \(current value: 'föo/bar'\)"):
+ config.target = u"föo/bar"
def test_ignore_independent_from_rules(self):
# Test that the lintconfig rules are not modified when setting config.ignore
@@ -179,5 +182,5 @@ class LintConfigGeneratorTests(BaseTestCase):
@staticmethod
@patch('gitlint.config.shutil.copyfile')
def test_install_commit_msg_hook_negative(copy):
- LintConfigGenerator.generate_config("foo/bar/test")
- copy.assert_called_with(GITLINT_CONFIG_TEMPLATE_SRC_PATH, "foo/bar/test")
+ LintConfigGenerator.generate_config(u"föo/bar/test")
+ copy.assert_called_with(GITLINT_CONFIG_TEMPLATE_SRC_PATH, u"föo/bar/test")
diff --git a/gitlint/tests/test_config_builder.py b/gitlint/tests/test_config_builder.py
index a20bb7a..239c4fc 100644
--- a/gitlint/tests/test_config_builder.py
+++ b/gitlint/tests/test_config_builder.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-