From 3df320656cab547289a423bedc8d25f8bd10176a Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Fri, 25 Nov 2022 18:15:14 +1100 Subject: [PATCH 1/5] Annotate return value of unicode_to_file_data() --- rope/base/fscommands.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/rope/base/fscommands.py b/rope/base/fscommands.py index bf928eaf5..64c63ebf5 100644 --- a/rope/base/fscommands.py +++ b/rope/base/fscommands.py @@ -12,12 +12,15 @@ import subprocess import rope.base.utils.pycompat as pycompat +import typing try: unicode except NameError: unicode = str +FileContent = typing.NewType("FileContent", bytes) + def create_fscommands(root): dirlist = os.listdir(root) @@ -214,19 +217,19 @@ def _execute(args, cwd=None): return process.returncode -def unicode_to_file_data(contents, encoding=None, newlines=None): - if not isinstance(contents, unicode): +def unicode_to_file_data(contents: str, encoding=None, newlines=None) -> FileContent: + if not isinstance(contents, str): return contents if newlines and newlines != "\n": contents = contents.replace("\n", newlines) if encoding is None: encoding = read_str_coding(contents) if encoding is not None: - return contents.encode(encoding) + return FileContent(contents.encode(encoding)) try: - return contents.encode() + return FileContent(contents.encode()) except UnicodeEncodeError: - return contents.encode("utf-8") + return FileContent(contents.encode("utf-8")) def file_data_to_unicode(data, encoding=None): From 10b42eb1940b067955b1b85c80e154016f1c0929 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Fri, 25 Nov 2022 18:49:40 +1100 Subject: [PATCH 2/5] Change unicode_to_file_data() to now only take `str` Simplify handling of str/unicode distinction that had been a relic of Python 2 transition. --- rope/base/change.py | 15 ++++++++++----- rope/base/fscommands.py | 3 +-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/rope/base/change.py b/rope/base/change.py index cf1d9f3be..badd3e0f1 100644 --- a/rope/base/change.py +++ b/rope/base/change.py @@ -5,6 +5,7 @@ import rope.base.fscommands from rope.base import taskhandle, exceptions, utils +from rope.base.fscommands import FileContent class Change: @@ -329,11 +330,15 @@ def _get_fscommands(self, resource): return self.direct_commands return self.fscommands - def write_file(self, resource, contents): - data = rope.base.fscommands.unicode_to_file_data( - contents, - newlines=resource.newlines, - ) + def write_file(self, resource, contents: str | FileContent): + data: FileContent + if not isinstance(contents, bytes): + data = rope.base.fscommands.unicode_to_file_data( + contents, + newlines=resource.newlines, + ) + else: + data = contents fscommands = self._get_fscommands(resource) fscommands.write(resource.real_path, data) for observer in list(self.project.observers): diff --git a/rope/base/fscommands.py b/rope/base/fscommands.py index 64c63ebf5..3d613fd02 100644 --- a/rope/base/fscommands.py +++ b/rope/base/fscommands.py @@ -218,8 +218,7 @@ def _execute(args, cwd=None): def unicode_to_file_data(contents: str, encoding=None, newlines=None) -> FileContent: - if not isinstance(contents, str): - return contents + assert isinstance(contents, str) if newlines and newlines != "\n": contents = contents.replace("\n", newlines) if encoding is None: From f2063ffeef44d21a303c71efc2905075f49a1fc9 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Fri, 25 Nov 2022 18:54:39 +1100 Subject: [PATCH 3/5] Remove unicode->str type aliasing unicode was a relic of Python 2 transition. rope no longer support Python 2, so this is no longer needed. --- rope/base/ast.py | 7 +------ rope/base/fscommands.py | 6 +----- rope/base/pyobjectsdef.py | 7 +------ ropetest/contrib/codeassisttest.py | 9 ++------- 4 files changed, 5 insertions(+), 24 deletions(-) diff --git a/rope/base/ast.py b/rope/base/ast.py index 67c35db47..b457e2367 100644 --- a/rope/base/ast.py +++ b/rope/base/ast.py @@ -3,15 +3,10 @@ from rope.base import fscommands -try: - unicode -except NameError: - unicode = str - def parse(source, filename=""): # NOTE: the raw string should be given to `compile` function - if isinstance(source, unicode): + if isinstance(source, str): source = fscommands.unicode_to_file_data(source) if b"\r" in source: source = source.replace(b"\r\n", b"\n").replace(b"\r", b"\n") diff --git a/rope/base/fscommands.py b/rope/base/fscommands.py index 3d613fd02..f69b172e7 100644 --- a/rope/base/fscommands.py +++ b/rope/base/fscommands.py @@ -14,10 +14,6 @@ import rope.base.utils.pycompat as pycompat import typing -try: - unicode -except NameError: - unicode = str FileContent = typing.NewType("FileContent", bytes) @@ -244,7 +240,7 @@ def file_data_to_unicode(data, encoding=None): def _decode_data(data, encoding): - if isinstance(data, unicode): + if isinstance(data, str): return data if encoding is None: encoding = read_str_coding(data) diff --git a/rope/base/pyobjectsdef.py b/rope/base/pyobjectsdef.py index 2ab301910..5f6bf9271 100644 --- a/rope/base/pyobjectsdef.py +++ b/rope/base/pyobjectsdef.py @@ -17,11 +17,6 @@ ) from rope.base.utils import pycompat -try: - unicode -except NameError: - unicode = str - class PyFunction(pyobjects.PyFunction): def __init__(self, pycore, ast_node, parent): @@ -204,7 +199,7 @@ def _init_source(self, pycore, source_code, resource): source_bytes = resource.read_bytes() source_code, _ = fscommands.file_data_to_unicode(source_bytes) else: - if isinstance(source_code, unicode): + if isinstance(source_code, str): source_bytes = fscommands.unicode_to_file_data(source_code) else: source_bytes = source_code diff --git a/ropetest/contrib/codeassisttest.py b/ropetest/contrib/codeassisttest.py index 8d09e08f2..7d07bc2a0 100644 --- a/ropetest/contrib/codeassisttest.py +++ b/ropetest/contrib/codeassisttest.py @@ -16,11 +16,6 @@ ) from ropetest import testutils -try: - unicode -except NameError: - unicode = str - class CodeAssistTest(unittest.TestCase): def setUp(self): @@ -731,7 +726,7 @@ def test_get_pydoc_unicode(self): def foo(): u"юникод-объект"''') doc = get_doc(self.project, src, src.index("foo") + 1) - self.assertTrue(isinstance(doc, unicode)) + self.assertTrue(isinstance(doc, str)) self.assertTrue("юникод-объект" in doc) def test_get_pydoc_utf8_bytestring(self): @@ -740,7 +735,7 @@ def test_get_pydoc_utf8_bytestring(self): def foo(): "байтстринг"''') doc = get_doc(self.project, src, src.index("foo") + 1) - self.assertTrue(isinstance(doc, unicode)) + self.assertTrue(isinstance(doc, str)) self.assertTrue("байтстринг" in doc) def test_get_pydoc_for_functions(self): From 65ab0def7e7f410f9645ea676d7b6e5fc48d61dc Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Fri, 25 Nov 2022 18:59:31 +1100 Subject: [PATCH 4/5] Remove redundant call to _decode_data() In Python 3, ast always returns `str` here, and `_decode_data()` is basically no-op. --- rope/base/pyobjects.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rope/base/pyobjects.py b/rope/base/pyobjects.py index f0929e9cc..820fc2d1b 100644 --- a/rope/base/pyobjects.py +++ b/rope/base/pyobjects.py @@ -1,4 +1,5 @@ -from rope.base.fscommands import _decode_data +from typing import Optional + from rope.base import ast, exceptions, utils @@ -224,13 +225,14 @@ def get_module(self): current_object = current_object.parent return current_object - def get_doc(self): + def get_doc(self) -> Optional[str]: if len(self.get_ast().body) > 0: expr = self.get_ast().body[0] if isinstance(expr, ast.Expr) and isinstance(expr.value, ast.Str): docstring = expr.value.s - coding = self.get_module().coding - return _decode_data(docstring, coding) + assert isinstance(docstring, str) + return docstring + return None def _get_defined_objects(self): if self.defineds is None: From 2fe98b00b99522445b409e24cedd99723038c29d Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Fri, 25 Nov 2022 19:15:10 +1100 Subject: [PATCH 5/5] Use older Union syntax, we can't use the | syntax yet --- rope/base/change.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rope/base/change.py b/rope/base/change.py index badd3e0f1..eadb0c561 100644 --- a/rope/base/change.py +++ b/rope/base/change.py @@ -2,9 +2,10 @@ import difflib import os import time +from typing import Union import rope.base.fscommands -from rope.base import taskhandle, exceptions, utils +from rope.base import exceptions, taskhandle, utils from rope.base.fscommands import FileContent @@ -330,7 +331,7 @@ def _get_fscommands(self, resource): return self.direct_commands return self.fscommands - def write_file(self, resource, contents: str | FileContent): + def write_file(self, resource, contents: Union[str, FileContent]): data: FileContent if not isinstance(contents, bytes): data = rope.base.fscommands.unicode_to_file_data(