diff --git a/ChangeLog b/ChangeLog index 754392a27f..7654860519 100644 --- a/ChangeLog +++ b/ChangeLog @@ -52,6 +52,11 @@ Release date: TBA Closes #3282 +* The ``unspecified-encoding`` checker now also checks calls to ``pathlib.Path().read_text()`` + and ``pathlib.Path().write_text()`` + + Closes #4945 + What's New in Pylint 2.10.3? ============================ diff --git a/doc/whatsnew/2.11.rst b/doc/whatsnew/2.11.rst index 8a9161c710..6a22d5ba7a 100644 --- a/doc/whatsnew/2.11.rst +++ b/doc/whatsnew/2.11.rst @@ -60,3 +60,8 @@ Other Changes * Fix false positive ``dict-iter-missing-items`` for dictionaries only using tuples as keys Closes #3282 + +* The ``unspecified-encoding`` checker now also checks calls to ``pathlib.Path().read_text()`` + and ``pathlib.Path().write_text()`` + + Closes #4945 diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py index b7a6e031b7..f11cbac988 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -47,7 +47,7 @@ from pylint.interfaces import IAstroidChecker OPEN_FILES_MODE = ("open", "file") -OPEN_FILES_ENCODING = ("open",) +OPEN_FILES_ENCODING = ("open", "read_text", "write_text") UNITTEST_CASE = "unittest.case" THREADING_THREAD = "threading.Thread" COPY_COPY = "copy.copy" @@ -55,7 +55,7 @@ ENV_GETTERS = ("os.getenv",) SUBPROCESS_POPEN = "subprocess.Popen" SUBPROCESS_RUN = "subprocess.run" -OPEN_MODULE = "_io" +OPEN_MODULE = {"_io", "pathlib"} DEBUG_BREAKPOINTS = ("builtins.breakpoint", "sys.breakpointhook", "pdb.set_trace") @@ -515,7 +515,7 @@ def visit_call(self, node: nodes.Call) -> None: for inferred in utils.infer_all(node.func): if inferred is astroid.Uninferable: continue - if inferred.root().name == OPEN_MODULE: + if inferred.root().name in OPEN_MODULE: if ( isinstance(node.func, nodes.Name) and node.func.name in OPEN_FILES_MODE diff --git a/tests/functional/u/unspecified_encoding_py38.py b/tests/functional/u/unspecified_encoding_py38.py index 20d2d7be1c..1b3ae37958 100644 --- a/tests/functional/u/unspecified_encoding_py38.py +++ b/tests/functional/u/unspecified_encoding_py38.py @@ -2,6 +2,7 @@ # pylint: disable=consider-using-with import io import locale +from pathlib import Path FILENAME = "foo.bar" open(FILENAME, "w", encoding="utf-8") @@ -53,3 +54,21 @@ LOCALE_ENCODING = None with io.open(FILENAME, encoding=LOCALE_ENCODING) as f: # [unspecified-encoding] pass + +LOCALE_ENCODING = locale.getlocale()[1] +Path(FILENAME).read_text(encoding=LOCALE_ENCODING) +Path(FILENAME).read_text(encoding="utf8") + +LOCALE_ENCODING = None +Path(FILENAME).read_text() # [unspecified-encoding] +Path(FILENAME).read_text(encoding=None) # [unspecified-encoding] +Path(FILENAME).read_text(encoding=LOCALE_ENCODING) # [unspecified-encoding] + +LOCALE_ENCODING = locale.getlocale()[1] +Path(FILENAME).write_text("string", encoding=LOCALE_ENCODING) +Path(FILENAME).write_text("string", encoding="utf8") + +LOCALE_ENCODING = None +Path(FILENAME).write_text("string") # [unspecified-encoding] +Path(FILENAME).write_text("string", encoding=None) # [unspecified-encoding] +Path(FILENAME).write_text("string", encoding=LOCALE_ENCODING) # [unspecified-encoding] diff --git a/tests/functional/u/unspecified_encoding_py38.txt b/tests/functional/u/unspecified_encoding_py38.txt index cde7f22383..45bf15f5a9 100644 --- a/tests/functional/u/unspecified_encoding_py38.txt +++ b/tests/functional/u/unspecified_encoding_py38.txt @@ -1,15 +1,21 @@ -unspecified-encoding:10:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:11:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:12:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:13:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:14:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:23:5::"Using open without explicitly specifying an encoding" -unspecified-encoding:26:5::"Using open without explicitly specifying an encoding" -unspecified-encoding:30:5::"Using open without explicitly specifying an encoding" -unspecified-encoding:35:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:36:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:37:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:38:0::"Using open without explicitly specifying an encoding" -unspecified-encoding:47:5::"Using open without explicitly specifying an encoding" -unspecified-encoding:50:5::"Using open without explicitly specifying an encoding" -unspecified-encoding:54:5::"Using open without explicitly specifying an encoding" +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: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:63:0::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:72: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