diff options
author | Joris Roovers <jroovers@cisco.com> | 2016-12-27 17:07:50 +0100 |
---|---|---|
committer | Joris Roovers <jroovers@cisco.com> | 2016-12-27 17:07:50 +0100 |
commit | d28dba35bc3deea12402d5810f6dac221553984c (patch) | |
tree | c3923f4eee40fb804ed5189709b7cba86d8a4f32 | |
parent | 8f6cd8cfcc5346a47565c74cc6042ba1785082a2 (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-- | .pylintrc | 2 | ||||
-rw-r--r-- | gitlint/cli.py | 14 | ||||
-rw-r--r-- | gitlint/config.py | 56 | ||||
-rw-r--r-- | gitlint/options.py | 16 | ||||
-rw-r--r-- | gitlint/tests/base.py | 13 | ||||
-rw-r--r-- | gitlint/tests/expected/debug_output1 | 2 | ||||
-rw-r--r-- | gitlint/tests/samples/config/gitlintconfig | 6 | ||||
-rw-r--r-- | gitlint/tests/samples/config/invalid-option-value | 2 | ||||
-rw-r--r-- | gitlint/tests/samples/config/nonexisting-option | 2 | ||||
-rw-r--r-- | gitlint/tests/samples/config/nonexisting-rule | 2 | ||||
-rw-r--r-- | gitlint/tests/test_cli.py | 68 | ||||
-rw-r--r-- | gitlint/tests/test_config.py | 47 | ||||
-rw-r--r-- | gitlint/tests/test_config_builder.py | 54 | ||||
-rw-r--r-- | gitlint/tests/test_user_rules.py | 3 | ||||
-rw-r--r-- | gitlint/utils.py | 15 | ||||
-rwxr-xr-x | run_tests.sh | 3 |
16 files changed, 174 insertions, 131 deletions
@@ -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 -*- |