diff options
| author | Cosmin Poieana <cmin@ropython.org> | 2014-12-05 18:25:50 +0200 |
|---|---|---|
| committer | Cosmin Poieana <cmin@ropython.org> | 2014-12-05 18:25:50 +0200 |
| commit | 6811bafce2fc79d1d52b612321a20a0e3a1e24b8 (patch) | |
| tree | 9b8c5be26c96df00afa085194168dc60362c459c | |
| parent | ef38bc078a3732958012c192560a3fafa633db85 (diff) | |
| parent | 93b477e069dd2652d7e7e04b156e3cecf36e7d10 (diff) | |
| download | pylint-6811bafce2fc79d1d52b612321a20a0e3a1e24b8.tar.gz | |
Merge; Fix open mode bug
| -rw-r--r-- | checkers/stdlib.py | 44 | ||||
| -rw-r--r-- | test/functional/bad_open_mode.py | 12 | ||||
| -rw-r--r-- | test/functional/bad_open_mode.rc | 2 | ||||
| -rw-r--r-- | test/functional/bad_open_mode.txt | 6 | ||||
| -rw-r--r-- | test/functional/bad_open_mode_py3.py | 14 | ||||
| -rw-r--r-- | test/functional/bad_open_mode_py3.rc | 2 | ||||
| -rw-r--r-- | test/functional/bad_open_mode_py3.txt | 4 |
7 files changed, 76 insertions, 8 deletions
diff --git a/checkers/stdlib.py b/checkers/stdlib.py index d8b5fde..aafb970 100644 --- a/checkers/stdlib.py +++ b/checkers/stdlib.py @@ -16,6 +16,7 @@ """Checkers for various standard library functions.""" import re +import six import sys import astroid @@ -25,13 +26,50 @@ from pylint.interfaces import IAstroidChecker from pylint.checkers import BaseChecker from pylint.checkers import utils -_VALID_OPEN_MODE_REGEX = re.compile(r'^(r?U|[rwa]\+?b?)$') if sys.version_info >= (3, 0): OPEN_MODULE = '_io' else: OPEN_MODULE = '__builtin__' + +def _check_mode_str(mode): + # check type + if not isinstance(mode, six.string_types): + return False + # check syntax + modes = set(mode) + _mode = "rwatb+U" + creating = False + if six.PY3: + _mode += "x" + creating = "x" in modes + if modes - set(_mode) or len(mode) > len(modes): + return False + # check logic + reading = "r" in modes + writing = "w" in modes + appending = "a" in modes + updating = "+" in modes + text = "t" in modes + binary = "b" in modes + if "U" in modes: + if writing or appending or creating and six.PY3: + return False + reading = True + if text and binary: + return False + total = reading + writing + appending + (creating if six.PY3 else 0) + if total > 1: + return False + if not (reading or writing or appending or creating and six.PY3): + return False + # 2.x constraints + if not six.PY3: + return mode[0] in ("r", "w", "a", "U") + return True + + class StdlibChecker(BaseChecker): __implements__ = (IAstroidChecker,) name = 'stdlib' @@ -89,6 +127,7 @@ class StdlibChecker(BaseChecker): infered.qname() == 'datetime.time'): self.add_message('boolean-datetime', node=node) + def _check_open_mode(self, node): """Check that the mode argument of an open or file call is valid.""" try: @@ -96,7 +135,7 @@ class StdlibChecker(BaseChecker): if mode_arg: mode_arg = utils.safe_infer(mode_arg) if (isinstance(mode_arg, astroid.Const) - and not _VALID_OPEN_MODE_REGEX.match(mode_arg.value)): + and not _check_mode_str(mode_arg.value)): self.add_message('bad-open-mode', node=node, args=(mode_arg.value)) except (utils.NoSuchArgumentError, TypeError): @@ -105,4 +144,3 @@ class StdlibChecker(BaseChecker): def register(linter): """required method to auto register this checker """ linter.register_checker(StdlibChecker(linter)) - diff --git a/test/functional/bad_open_mode.py b/test/functional/bad_open_mode.py index dfbf037..8659850 100644 --- a/test/functional/bad_open_mode.py +++ b/test/functional/bad_open_mode.py @@ -4,10 +4,16 @@ open('foo.bar', 'w', 2) open('foo.bar', 'rw') # [bad-open-mode] open(name='foo.bar', buffering=10, mode='rw') # [bad-open-mode] open(mode='rw', name='foo.bar') # [bad-open-mode] -open('foo.bar', 'U+') # [bad-open-mode] -open('foo.bar', 'rb+') # [bad-open-mode] +open('foo.bar', 'U+') +open('foo.bar', 'rb+') open('foo.bar', 'Uw') # [bad-open-mode] -open('foo.bar', 2) +open('foo.bar', 2) # [bad-open-mode] open('foo.bar', buffering=2) WRITE_MODE = 'w' open('foo.bar', 'U' + WRITE_MODE + 'z') # [bad-open-mode] +open('foo.bar', 'br') # [bad-open-mode] +open('foo.bar', 'wU') # [bad-open-mode] +open('foo.bar', 'r+b') +open('foo.bar', 'r+') +open('foo.bar', 'w+') +open('foo.bar', 'xb') # [bad-open-mode] diff --git a/test/functional/bad_open_mode.rc b/test/functional/bad_open_mode.rc new file mode 100644 index 0000000..b9ab977 --- /dev/null +++ b/test/functional/bad_open_mode.rc @@ -0,0 +1,2 @@ +[testoptions]
+max_pyver=3.0
diff --git a/test/functional/bad_open_mode.txt b/test/functional/bad_open_mode.txt index d0bb8bb..775c979 100644 --- a/test/functional/bad_open_mode.txt +++ b/test/functional/bad_open_mode.txt @@ -1,7 +1,9 @@ bad-open-mode:4::"""rw"" is not a valid mode for open." bad-open-mode:5::"""rw"" is not a valid mode for open." bad-open-mode:6::"""rw"" is not a valid mode for open." -bad-open-mode:7::"""U+"" is not a valid mode for open." -bad-open-mode:8::"""rb+"" is not a valid mode for open." bad-open-mode:9::"""Uw"" is not a valid mode for open." +bad-open-mode:10::"""2"" is not a valid mode for open." bad-open-mode:13::"""Uwz"" is not a valid mode for open." +bad-open-mode:14::"""br"" is not a valid mode for open." +bad-open-mode:15::"""wU"" is not a valid mode for open." +bad-open-mode:19::"""xb"" is not a valid mode for open." diff --git a/test/functional/bad_open_mode_py3.py b/test/functional/bad_open_mode_py3.py new file mode 100644 index 0000000..7229eca --- /dev/null +++ b/test/functional/bad_open_mode_py3.py @@ -0,0 +1,14 @@ +"""Warnings for using open() with an invalid mode string."""
+
+NAME = "foo.bar"
+open(NAME, "wb")
+open(NAME, "w")
+open(NAME, "rb")
+open(NAME, "x")
+open(NAME, "br")
+open(NAME, "+r")
+open(NAME, "xb")
+open(NAME, "rwx") # [bad-open-mode]
+open(NAME, "rr") # [bad-open-mode]
+open(NAME, "+") # [bad-open-mode]
+open(NAME, "xw") # [bad-open-mode]
diff --git a/test/functional/bad_open_mode_py3.rc b/test/functional/bad_open_mode_py3.rc new file mode 100644 index 0000000..c4033f8 --- /dev/null +++ b/test/functional/bad_open_mode_py3.rc @@ -0,0 +1,2 @@ +[testoptions]
+min_pyver=3.0
diff --git a/test/functional/bad_open_mode_py3.txt b/test/functional/bad_open_mode_py3.txt new file mode 100644 index 0000000..ba3443c --- /dev/null +++ b/test/functional/bad_open_mode_py3.txt @@ -0,0 +1,4 @@ +bad-open-mode:11::"""rwx"" is not a valid mode for open."
+bad-open-mode:12::"""rr"" is not a valid mode for open."
+bad-open-mode:13::"""+"" is not a valid mode for open."
+bad-open-mode:14::"""xw"" is not a valid mode for open."
|
