summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2021-11-20 13:21:28 +0100
committerGitHub <noreply@github.com>2021-11-20 13:21:28 +0100
commitbcdb98a68407f57243b509dd35ab24c418485138 (patch)
tree2efc3ba8e7f34d8e355a7eb679875db1ab47aa69
parentb7a2ce0e9eb8db7e8ac579a5c16f5e04f87813eb (diff)
downloadpylint-git-bcdb98a68407f57243b509dd35ab24c418485138.tar.gz
Fix crash on ``open()`` calls for non-string ``mode`` arguments (#5332)
Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com>
-rw-r--r--ChangeLog4
-rw-r--r--doc/whatsnew/2.12.rst4
-rw-r--r--pylint/checkers/stdlib.py7
-rw-r--r--tests/functional/u/unspecified_encoding_py38.py64
-rw-r--r--tests/functional/u/unspecified_encoding_py38.txt32
5 files changed, 93 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index 478b5587a..221065a72 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -187,6 +187,10 @@ Release date: TBA
* Make yn validator case insensitive, to allow for ``True`` and ``False`` in config files.
+* Fix crash on ``open()`` calls when the ``mode`` argument is not a simple string.
+
+ Partially closes #5321
+
What's New in Pylint 2.11.2?
============================
diff --git a/doc/whatsnew/2.12.rst b/doc/whatsnew/2.12.rst
index f39c3f56f..9e8bfbb30 100644
--- a/doc/whatsnew/2.12.rst
+++ b/doc/whatsnew/2.12.rst
@@ -194,3 +194,7 @@ Other Changes
* Added the ``--enable-all-extensions`` command line option. It will load all available extensions
which can be listed by running ``--list-extensions``
+
+* Fix crash on ``open()`` calls when the ``mode`` argument is not a simple string.
+
+ Partially closes #5321
diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py
index 0eb47296e..d1fc49eb7 100644
--- a/pylint/checkers/stdlib.py
+++ b/pylint/checkers/stdlib.py
@@ -626,7 +626,12 @@ class StdlibChecker(DeprecatedMixin, BaseChecker):
if mode_arg:
mode_arg = utils.safe_infer(mode_arg)
- if not mode_arg or "b" not in mode_arg.value:
+
+ if (
+ not mode_arg
+ or isinstance(mode_arg, nodes.Const)
+ and "b" not in mode_arg.value
+ ):
encoding_arg = None
try:
if open_module == "pathlib" and node.func.attrname == "read_text":
diff --git a/tests/functional/u/unspecified_encoding_py38.py b/tests/functional/u/unspecified_encoding_py38.py
index 79c974bc2..ce5f3e816 100644
--- a/tests/functional/u/unspecified_encoding_py38.py
+++ b/tests/functional/u/unspecified_encoding_py38.py
@@ -1,8 +1,10 @@
"""Warnings for using open() without specifying an encoding"""
-# pylint: disable=consider-using-with
+# pylint: disable=consider-using-with, too-few-public-methods
+import dataclasses
import io
import locale
from pathlib import Path
+from typing import Optional
FILENAME = "foo.bar"
open(FILENAME, "w", encoding="utf-8")
@@ -81,3 +83,63 @@ Path(FILENAME).open("wt") # [unspecified-encoding]
Path(FILENAME).open("w+") # [unspecified-encoding]
Path(FILENAME).open("w", encoding=None) # [unspecified-encoding]
Path(FILENAME).open("w", encoding=LOCALE_ENCODING)
+
+
+# Tests for storing data about open calls.
+# Most of these are regression tests for a crash
+# reported in https://github.com/PyCQA/pylint/issues/5321
+
+# -- Constants
+MODE = "wb"
+open(FILENAME, mode=MODE)
+
+
+# -- Functions
+def return_mode_function():
+ """Return a mode for open call"""
+ return "wb"
+
+open(FILENAME, mode=return_mode_function())
+
+
+# -- Classes
+class IOData:
+ """Class that returns mode strings"""
+
+ mode = "wb"
+
+ def __init__(self):
+ self.my_mode = "wb"
+
+ @staticmethod
+ def my_mode_method():
+ """Returns a pre-defined mode"""
+ return "wb"
+
+ @staticmethod
+ def my_mode_method_returner(mode: str) -> str:
+ """Returns the supplied mode"""
+ return mode
+
+
+open(FILENAME, mode=IOData.mode)
+open(FILENAME, mode=IOData().my_mode)
+open(FILENAME, mode=IOData().my_mode_method())
+open(FILENAME, mode=IOData().my_mode_method_returner("wb"))
+# Invalid value but shouldn't crash, reported in https://github.com/PyCQA/pylint/issues/5321
+open(FILENAME, mode=IOData)
+
+
+# -- Dataclasses
+@dataclasses.dataclass
+class IOArgs:
+ """Dataclass storing information about how to open a file"""
+
+ encoding: Optional[str]
+ mode: str
+
+
+args_good_one = IOArgs(encoding=None, mode="wb")
+
+# Test for crash reported in https://github.com/PyCQA/pylint/issues/5321
+open(FILENAME, args_good_one.mode, encoding=args_good_one.encoding)
diff --git a/tests/functional/u/unspecified_encoding_py38.txt b/tests/functional/u/unspecified_encoding_py38.txt
index a83165421..118df7a8b 100644
--- a/tests/functional/u/unspecified_encoding_py38.txt
+++ b/tests/functional/u/unspecified_encoding_py38.txt
@@ -1,25 +1,25 @@
-unspecified-encoding:11:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:12:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:13:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:14:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:15:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:24:5::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:27:5::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:31:5::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:36:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:37:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:16:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:17:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:26:5::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:29:5::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:33:5::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:38:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:39:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:48:5::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:51:5::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:55:5::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:64:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:65:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:40:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:41:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:50:5::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:53:5::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:57:5::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:66:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:73:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:74:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:67:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:68:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:75:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:79:0::Using open without explicitly specifying an encoding:HIGH
-unspecified-encoding:80:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:76:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:77:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:81:0::Using open without explicitly specifying an encoding:HIGH
unspecified-encoding:82:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:83:0::Using open without explicitly specifying an encoding:HIGH
+unspecified-encoding:84:0::Using open without explicitly specifying an encoding:HIGH