From 70c54dc2550084ed022a2f134065a011f37f30aa Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 15 Nov 2019 01:19:03 -0500 Subject: [PATCH] upload/editor: fix bytes/string confusion The upload module tries to turn the strings into bytes before passing to EditString, but it combines bytes & strings causing an error. The return value might be bytes or string, but the caller only expects a string. Lets simplify this by sticking to strings everywhere and have EditString take care of converting to/from bytes when reading/writing the underlying files. This also avoids possible locale confusion when reading the file by forcing UTF-8 everywhere. Bug: https://crbug.com/gerrit/11929 Change-Id: I07b146170c5e8b5b0500a2c79e4213cd12140a96 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/245621 Reviewed-by: David Pursehouse Tested-by: Mike Frysinger --- editor.py | 17 +++++++------ subcmds/upload.py | 5 ---- tests/test_editor.py | 60 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 tests/test_editor.py diff --git a/editor.py b/editor.py index 19b96c37..fcf16386 100644 --- a/editor.py +++ b/editor.py @@ -68,11 +68,14 @@ least one of these before using this command.""", file=sys.stderr) def EditString(cls, data): """Opens an editor to edit the given content. - Args: - data : the text to edit + Args: + data: The text to edit. - Returns: - new value of edited text; None if editing did not succeed + Returns: + New value of edited text. + + Raises: + EditorError: The editor failed to run. """ editor = cls._GetEditor() if editor == ':': @@ -80,7 +83,7 @@ least one of these before using this command.""", file=sys.stderr) fd, path = tempfile.mkstemp() try: - os.write(fd, data) + os.write(fd, data.encode('utf-8')) os.close(fd) fd = None @@ -106,8 +109,8 @@ least one of these before using this command.""", file=sys.stderr) raise EditorError('editor failed with exit status %d: %s %s' % (rc, editor, path)) - with open(path) as fd2: - return fd2.read() + with open(path, mode='rb') as fd2: + return fd2.read().decode('utf-8') finally: if fd: os.close(fd) diff --git a/subcmds/upload.py b/subcmds/upload.py index d0dd3837..5c12aaee 100644 --- a/subcmds/upload.py +++ b/subcmds/upload.py @@ -271,11 +271,6 @@ Gerrit Code Review: https://www.gerritcodereview.com/ branches[project.name] = b script.append('') - script = [ x.encode('utf-8') - if issubclass(type(x), unicode) - else x - for x in script ] - script = Editor.EditString("\n".join(script)).split("\n") project_re = re.compile(r'^#?\s*project\s*([^\s]+)/:$') diff --git a/tests/test_editor.py b/tests/test_editor.py new file mode 100644 index 00000000..fbcfcdbd --- /dev/null +++ b/tests/test_editor.py @@ -0,0 +1,60 @@ +# -*- coding:utf-8 -*- +# +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Unittests for the editor.py module.""" + +from __future__ import print_function + +import unittest + +from editor import Editor + + +class EditorTestCase(unittest.TestCase): + """Take care of resetting Editor state across tests.""" + + def setUp(self): + self.setEditor(None) + + def tearDown(self): + self.setEditor(None) + + @staticmethod + def setEditor(editor): + Editor._editor = editor + + +class GetEditor(EditorTestCase): + """Check GetEditor behavior.""" + + def test_basic(self): + """Basic checking of _GetEditor.""" + self.setEditor(':') + self.assertEqual(':', Editor._GetEditor()) + + +class EditString(EditorTestCase): + """Check EditString behavior.""" + + def test_no_editor(self): + """Check behavior when no editor is available.""" + self.setEditor(':') + self.assertEqual('foo', Editor.EditString('foo')) + + def test_cat_editor(self): + """Check behavior when editor is `cat`.""" + self.setEditor('cat') + self.assertEqual('foo', Editor.EditString('foo'))