diff options
author | Joris Roovers <jroovers@cisco.com> | 2017-04-25 13:02:20 +0200 |
---|---|---|
committer | Joris Roovers <jroovers@cisco.com> | 2017-04-25 13:02:20 +0200 |
commit | f45eb745561184cef63d9abfa3f951f1ae2505b1 (patch) | |
tree | 114805d3960ce712820128f0f50e119cec278352 | |
parent | 644210c2b428e871da96d4fd98e433fa0d4dcbbd (diff) |
Extra tests for --extra-path accepting file names + doc updates
Added some extra tests for the new PathOption which is used by
--extra-path. Also added support for the 'file' type for PathOption's.
Additional changes:
- Moved LOGFORMAT to gitlint/utils.py because having it in
gitlint/cli.py broke the ability to run individual test cases via
run_tests.sh
- Updated the CHANGELOG for the upcoming 0.8.2 release.
- Updated docs based on changes in this commit
-rw-r--r-- | CHANGELOG.md | 13 | ||||
-rw-r--r-- | docs/index.md | 38 | ||||
-rw-r--r-- | docs/user_defined_rules.md | 2 | ||||
-rw-r--r-- | gitlint/cli.py | 4 | ||||
-rw-r--r-- | gitlint/options.py | 9 | ||||
-rw-r--r-- | gitlint/tests/base.py | 12 | ||||
-rw-r--r-- | gitlint/tests/test_cli.py | 10 | ||||
-rw-r--r-- | gitlint/tests/test_options.py | 39 | ||||
-rw-r--r-- | gitlint/tests/test_user_rules.py | 5 | ||||
-rw-r--r-- | gitlint/user_rules.py | 2 | ||||
-rw-r--r-- | gitlint/utils.py | 1 |
11 files changed, 96 insertions, 39 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b5421d..e2b4c4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog # +## v0.8.1 (2017-04-25) ## + +The 0.8.2 release brings minor improvements, bugfixes and some under-the-hood changes. Special thanks to +[tommyip](https://github.com/tommyip) for his contributions. +- ```--extra-path``` now also accepts a file path (in the past only directory paths where accepted). +Thanks to [tommyip](https://github.com/tommyip) for implementing this! +- gitlint will now show more information when using the ```--debug``` flag. This is initial work and will continue to +be improved upon in later releases. +- Bugfixes: + - [#24: --commits doesn't take commit specific config into account](https://github.com/jorisroovers/gitlint/issues/24) + - [#27: --commits returns the wrong exit code](https://github.com/jorisroovers/gitlint/issues/27) +- Development: better unit and integration test coverage for ```--commits``` + ## v0.8.1 (2017-03-16) ## The 0.8.1 release brings minor tweaks and some experimental features. Special thanks to diff --git a/docs/index.md b/docs/index.md index ce1bc54..c1060f3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -81,29 +81,29 @@ The default verbosity is ```-vvv```. Other commands and variations: -``` +```no-highlight Usage: gitlint [OPTIONS] COMMAND [ARGS]... Git lint tool, checks your git commit messages for styling issues Options: - --target DIRECTORY Path of the target git repository. [default: - current working directory] - -C, --config PATH Config file location [default: .gitlint] - -c TEXT Config flags in format <rule>.<option>=<value> - (e.g.: -c T1.line-length=80). Flag can be used - multiple times to set multiple config values. - --commits TEXT The range of commits to lint. [default: HEAD] - -e, --extra-path DIRECTORY Path to a directory with extra user-defined - rules - --ignore TEXT Ignore rules (comma-separated by id or name). - -v, --verbose Verbosity, more v's for more verbose output - (e.g.: -v, -vv, -vvv). [default: -vvv] - -s, --silent Silent mode (no output). Takes precedence over - -v, -vv, -vvv. - -d, --debug Enable debugging output. - --version Show the version and exit. - --help Show this message and exit. + --target DIRECTORY Path of the target git repository. [default: current + working directory] + -C, --config PATH Config file location [default: .gitlint] + -c TEXT Config flags in format <rule>.<option>=<value> (e.g.: + -c T1.line-length=80). Flag can be used multiple + times to set multiple config values. + --commits TEXT The range of commits to lint. [default: HEAD] + -e, --extra-path PATH Path to a directory or python module with extra user- + defined rules + --ignore TEXT Ignore rules (comma-separated by id or name). + -v, --verbose Verbosity, more v's for more verbose output (e.g.: + -v, -vv, -vvv). [default: -vvv] + -s, --silent Silent mode (no output). Takes precedence over -v, + -vv, -vvv. + -d, --debug Enable debugging output. + --version Show the version and exit. + --help Show this message and exit. Commands: generate-config Generates a sample gitlint config file. @@ -154,7 +154,7 @@ future versions of gitlint might fix this. ## Linting a range of commits ## _Experimental support introduced in gitlint v0.8.1, known issues:_ -_[#23](https://github.com/jorisroovers/gitlint/pull/23), [#24](https://github.com/jorisroovers/gitlint/pull/24)_ +_[#23](https://github.com/jorisroovers/gitlint/pull/23)_ Gitlint allows users to commit a number of commits at once like so: diff --git a/docs/user_defined_rules.md b/docs/user_defined_rules.md index f873bac..04e1c36 100644 --- a/docs/user_defined_rules.md +++ b/docs/user_defined_rules.md @@ -260,7 +260,7 @@ StrOption | Strings IntOption | Integers. ```IntOption``` takes an optional ```allow_negative``` parameter if you want to allow negative integers. BoolOption | Booleans. Valid values: true, false. Case-insensitive. ListOption | List of strings. Comma separated. -PathOption | Directory or file path. Takes an optional ```type``` parameter for specifying path type (```dir``` \| ```both```). +PathOption | Directory or file path. Takes an optional ```type``` parameter for specifying path type (```file```, ```dir``` (=default) or ```both```). !!! note Gitlint currently does not support options for all possible types (e.g. float, filepath, list of int, etc). diff --git a/gitlint/cli.py b/gitlint/cli.py index 09daeb4..5955640 100644 --- a/gitlint/cli.py +++ b/gitlint/cli.py @@ -25,7 +25,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 +from gitlint.utils import ustr, LOG_FORMAT DEFAULT_CONFIG_FILE = ".gitlint" @@ -40,7 +40,7 @@ def setup_logging(): root_log = logging.getLogger("gitlint") root_log.propagate = False # Don't propagate to child loggers, the gitlint root logger handles everything handler = logging.StreamHandler() - formatter = logging.Formatter('%(levelname)s: %(name)s %(message)s') + formatter = logging.Formatter(LOG_FORMAT) handler.setFormatter(formatter) root_log.addHandler(handler) root_log.setLevel(logging.ERROR) diff --git a/gitlint/options.py b/gitlint/options.py index bff76f6..34bc389 100644 --- a/gitlint/options.py +++ b/gitlint/options.py @@ -90,7 +90,7 @@ class ListOption(RuleOption): class PathOption(RuleOption): """ Option that accepts either a directory or both a directory and a file. """ - def __init__(self, name, value, description, type='dir'): + def __init__(self, name, value, description, type=u"dir"): self.type = type super(PathOption, self).__init__(name, value, description) @@ -102,11 +102,16 @@ class PathOption(RuleOption): if self.type == 'dir': if not os.path.isdir(value): error_msg = u"Option {0} must be an existing directory (current value: '{1}')".format(self.name, value) - + elif self.type == 'file': + if not os.path.isfile(value): + error_msg = u"Option {0} must be an existing file (current value: '{1}')".format(self.name, value) elif self.type == 'both': if not os.path.isdir(value) and not os.path.isfile(value): error_msg = (u"Option {0} must be either an existing directory or file " u"(current value: '{1}')").format(self.name, value) + else: + error_msg = u"Option {0} type must be one of: 'file', 'dir', 'both' (current: '{1}')".format(self.name, + self.type) if error_msg: raise RuleOptionError(error_msg) diff --git a/gitlint/tests/base.py b/gitlint/tests/base.py index fc48bc4..245105c 100644 --- a/gitlint/tests/base.py +++ b/gitlint/tests/base.py @@ -3,7 +3,7 @@ import os import unittest2 from gitlint.git import GitContext -from gitlint.utils import ustr +from gitlint.utils import ustr, LOG_FORMAT # unittest2's assertRaisesRegex doesn't do unicode comparison. # Let's monkeypatch the str() function to point to unicode() so that it does :) @@ -25,14 +25,16 @@ class BaseTestCase(unittest2.TestCase): def setUp(self): self.logcapture = LogCapture() - # Make sure that the format used by our test logger is the same as used by gitlint itself - formatter = logging.getLogger('gitlint').handlers[0].formatter - self.logcapture.setFormatter(formatter) + self.logcapture.setFormatter(logging.Formatter(LOG_FORMAT)) logging.getLogger('gitlint').handlers = [self.logcapture] @staticmethod def get_sample_path(filename=""): - return os.path.join(BaseTestCase.SAMPLES_DIR, filename) + # Don't join up empty files names because this will add a trailing slash + if filename == "": + return ustr(BaseTestCase.SAMPLES_DIR) + + return ustr(os.path.join(BaseTestCase.SAMPLES_DIR, filename)) @staticmethod def get_sample(filename=""): diff --git a/gitlint/tests/test_cli.py b/gitlint/tests/test_cli.py index dcfbe81..c385021 100644 --- a/gitlint/tests/test_cli.py +++ b/gitlint/tests/test_cli.py @@ -191,6 +191,7 @@ class CLITests(BaseTestCase): def test_extra_path(self): """ Test for --extra-path flag """ + # Test extra-path pointing to a directory 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=u"Test tïtle\n") @@ -199,6 +200,15 @@ class CLITests(BaseTestCase): self.assertEqual(stderr.getvalue(), expected_output) self.assertEqual(result.exit_code, 2) + # Test extra-path pointing to a file + with patch('gitlint.display.stderr', new=StringIO()) as stderr: + extra_path = self.get_sample_path("user_rules/my_commit_rules.py") + result = self.cli.invoke(cli.cli, ["--extra-path", extra_path, "--debug"], input=u"Test tïtle\n") + expected_output = u"1: UC1 Commit violåtion 1: \"Contënt 1\"\n" + \ + "3: B6 Body message is missing\n" + self.assertEqual(stderr.getvalue(), expected_output) + self.assertEqual(result.exit_code, 2) + def test_config_file(self): """ Test for --config option """ with patch('gitlint.display.stderr', new=StringIO()) as stderr: diff --git a/gitlint/tests/test_options.py b/gitlint/tests/test_options.py index 7c5c16d..346bb0a 100644 --- a/gitlint/tests/test_options.py +++ b/gitlint/tests/test_options.py @@ -116,22 +116,51 @@ class RuleOptionTests(BaseTestCase): option.set(123) self.assertListEqual(option.value, ["123"]) - def test_dir_option(self): - option = PathOption("test-directory", ".", u"Test Description") + def test_path_option(self): + option = PathOption("test-directory", ".", u"Test Description", type=u"dir") self.assertEqual(option.value, os.getcwd()) self.assertEqual(option.name, "test-directory") self.assertEqual(option.description, u"Test Description") + self.assertEqual(option.type, u"dir") # re-set value option.set(self.SAMPLES_DIR) self.assertEqual(option.value, self.SAMPLES_DIR) + # set to int + expected = u"Option test-directory must be an existing directory \(current value: '1234'\)" + with self.assertRaisesRegex(RuleOptionError, expected): + option.set(1234) + # set to non-existing directory expected = u"Option test-directory must be an existing directory \(current value: '/föo/bar'\)" with self.assertRaisesRegex(RuleOptionError, expected): option.set(u"/föo/bar") - # set to int - expected = u"Option test-directory must be an existing directory \(current value: '1234'\)" + # set to a file, should raise exception since option.type = dir + sample_path = self.get_sample_path("commit_message/sample1") + expected = u"Option test-directory must be an existing directory \(current value: '{0}'\)".format(sample_path) with self.assertRaisesRegex(RuleOptionError, expected): - option.set(1234) + option.set(sample_path) + + # set option.type = file, file should now be accepted, directories not + option.type = u"file" + option.set(sample_path) + self.assertEqual(option.value, sample_path) + expected = u"Option test-directory must be an existing file \(current value: '{0}'\)".format( + self.get_sample_path()) + with self.assertRaisesRegex(RuleOptionError, expected): + option.set(self.get_sample_path()) + + # set option.type = both, files and directories should now be accepted + option.type = u"both" + option.set(sample_path) + self.assertEqual(option.value, sample_path) + option.set(self.get_sample_path()) + self.assertEqual(option.value, self.get_sample_path()) + + # Expect exception if path type is invalid + option.type = u'föo' + expected = u"Option test-directory type must be one of: 'file', 'dir', 'both' \(current: 'föo'\)" + with self.assertRaisesRegex(RuleOptionError, expected): + option.set("haha") diff --git a/gitlint/tests/test_user_rules.py b/gitlint/tests/test_user_rules.py index 0be4627..3c24b95 100644 --- a/gitlint/tests/test_user_rules.py +++ b/gitlint/tests/test_user_rules.py @@ -79,10 +79,7 @@ class UserRuleTests(BaseTestCase): find_rule_classes(user_rule_path) def test_find_rule_classes_nonexisting_path(self): - # When searching an non-existing path, we expect an OSError. That's fine because this case will be caught by - # the CLI (you cannot specify a non-existing directory). What we do here is just assert that we indeed - # get an OSError (so we guard against regressions). - with self.assertRaisesRegex(OSError, "No such file or directory"): + with self.assertRaisesRegex(UserRuleError, u"Invalid extra-path: föo/bar"): find_rule_classes(u"föo/bar") def test_assert_valid_rule_class(self): diff --git a/gitlint/user_rules.py b/gitlint/user_rules.py index a61d26f..b061b24 100644 --- a/gitlint/user_rules.py +++ b/gitlint/user_rules.py @@ -33,7 +33,7 @@ def find_rule_classes(extra_path): files = os.listdir(extra_path) directory = extra_path else: - raise OSError('No such file or directory') + raise UserRuleError(u"Invalid extra-path: {0}".format(extra_path)) # Filter out files that are not python modules for filename in files: diff --git a/gitlint/utils.py b/gitlint/utils.py index 2f9ae3f..7a6fed4 100644 --- a/gitlint/utils.py +++ b/gitlint/utils.py @@ -4,6 +4,7 @@ import sys from locale import getpreferredencoding DEFAULT_ENCODING = getpreferredencoding() or "UTF-8" +LOG_FORMAT = '%(levelname)s: %(name)s %(message)s' def ustr(obj): |