jenkins-bot has submitted this change and it was merged.

Change subject: [FIX] Editor: Support spaces, delete always and warn on \n (etc)
......................................................................


[FIX] Editor: Support spaces, delete always and warn on \n (etc)

This support spaces in the editor file name and warns if it contains a
string literal like \n with Windows because the backslash was used as a
path delimiter without escaping them.

The pywikibot.editor.TextEditor.command method has been deprecated,
because outside scripts don't require access anyway and this makes it
possible to return a list of command segments.

This now deletes the temporary file on any case, also when there were no
changes done. And it uses the more secure 'mkstemp' function.

Bug: T86481
Change-Id: If7e9feee49acd1147c5554cdd74a7ad0758397c5
---
M pywikibot/config2.py
M pywikibot/editor.py
2 files changed, 58 insertions(+), 32 deletions(-)

Approvals:
  John Vandenberg: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/pywikibot/config2.py b/pywikibot/config2.py
index e7df241..6e1a27e 100644
--- a/pywikibot/config2.py
+++ b/pywikibot/config2.py
@@ -886,6 +886,17 @@
 elif transliteration_target in ('None', 'none'):
     transliteration_target = None
 
+if sys.platform == 'win32' and editor:
+    # single character string literals from
+    # https://docs.python.org/2/reference/lexical_analysis.html#string-literals
+    # encode('unicode-escape') also changes Unicode characters
+    if set(editor) & set('\a\b\f\n\r\t\v'):
+        print('WARNING: The editor path contains probably invalid escaped '
+              'characters. Make sure to use a raw-string (r"..." or r\'...\'), 
'
+              'forward slashs as a path delimiter or to escape the normal '
+              'path delimiter.')
+
+
 # Fix up default site
 if family == 'wikipedia' and mylang == 'language':
     print("WARNING: family and mylang are not set.\n"
diff --git a/pywikibot/editor.py b/pywikibot/editor.py
index d3e268a..b928dc7 100644
--- a/pywikibot/editor.py
+++ b/pywikibot/editor.py
@@ -11,50 +11,64 @@
 __version__ = '$Id$'
 #
 
-import os
-import tempfile
 import codecs
+import os
+import subprocess
+import tempfile
+
 import pywikibot
 from pywikibot import config
+from pywikibot.tools import deprecated
 
 
 class TextEditor(object):
 
     """Text editor."""
 
-    def command(self, tempFilename, text, jumpIndex=None):
+    def _command(self, file_name, text, jump_index=None):
         """Return editor selected in user-config.py."""
-        command = config.editor
-        if jumpIndex:
+        if jump_index:
             # Some editors make it possible to mark occurrences of substrings,
             # or to jump to the line of the first occurrence.
             # TODO: Find a better solution than hardcoding these, e.g. a config
             # option.
-            line = text[:jumpIndex].count('\n')
-            column = jumpIndex - (text[:jumpIndex].rfind('\n') + 1)
+            line = text[:jump_index].count('\n')
+            column = jump_index - (text[:jump_index].rfind('\n') + 1)
         else:
             line = column = 0
         # Linux editors. We use startswith() because some users might use
         # parameters.
         if config.editor.startswith('kate'):
-            command += " -l %i -c %i" % (line + 1, column + 1)
+            command = ['-l', '%i' % (line + 1), '-c', '%i' % (column + 1)]
         elif config.editor.startswith('gedit'):
-            command += " +%i" % (line + 1)  # seems not to support columns
+            command = ['+%i' % (line + 1)]  # seems not to support columns
         elif config.editor.startswith('emacs'):
-            command += " +%i" % (line + 1)  # seems not to support columns
+            command = ['+%i' % (line + 1)]  # seems not to support columns
         elif config.editor.startswith('jedit'):
-            command += " +line:%i" % (line + 1)  # seems not to support columns
+            command = ['+line:%i' % (line + 1)]  # seems not to support columns
         elif config.editor.startswith('vim'):
-            command += " +%i" % (line + 1)  # seems not to support columns
+            command = ['+%i' % (line + 1)]  # seems not to support columns
         elif config.editor.startswith('nano'):
-            command += " +%i,%i" % (line + 1, column + 1)
+            command = ['+%i,%i' % (line + 1, column + 1)]
         # Windows editors
         elif config.editor.lower().endswith('notepad++.exe'):
-            command += " -n%i" % (line + 1)  # seems not to support columns
+            command = ['-n%i' % (line + 1)]  # seems not to support columns
+        else:
+            command = []
 
-        command += ' %s' % tempFilename
-        pywikibot.log(u'Running editor: %s' % command)
+        command = [config.editor] + command + [file_name]
+        pywikibot.log(u'Running editor: %s' % TextEditor._concat(command))
         return command
+
+    @staticmethod
+    def _concat(command):
+        return ' '.join("'{0}'".format(part) if ' ' in part else part
+                        for part in command)
+
+    @deprecated('_command (should not be used from the outside)')
+    def command(self, tempFilename, text, jumpIndex=None):
+        """Return editor selected in user-config.py."""
+        return TextEditor._concat(self._command(tempFilename, text, jumpIndex))
 
     def edit(self, text, jumpIndex=None, highlight=None):
         """
@@ -73,24 +87,25 @@
         @rtype: unicode or None
         """
         if config.editor:
-            tempFilename = '%s.%s' % (tempfile.mktemp(),
+            tempFilename = '%s.%s' % (tempfile.mkstemp()[1],
                                       config.editor_filename_extension)
-            with codecs.open(tempFilename, 'w',
-                             encoding=config.editor_encoding) as tempFile:
-                tempFile.write(text)
-            creationDate = os.stat(tempFilename).st_mtime
-            command = self.command(tempFilename, text, jumpIndex)
-            os.system(command)
-            lastChangeDate = os.stat(tempFilename).st_mtime
-            if lastChangeDate == creationDate:
-                # Nothing changed
-                return None
-            else:
-                with codecs.open(tempFilename, 'r',
-                                 encoding=config.editor_encoding) as temp_file:
-                    newcontent = temp_file.read()
+            try:
+                with codecs.open(tempFilename, 'w',
+                                 encoding=config.editor_encoding) as tempFile:
+                    tempFile.write(text)
+                creationDate = os.stat(tempFilename).st_mtime
+                subprocess.call(self._command(tempFilename, text, jumpIndex))
+                lastChangeDate = os.stat(tempFilename).st_mtime
+                if lastChangeDate == creationDate:
+                    # Nothing changed
+                    return None
+                else:
+                    with codecs.open(tempFilename, 'r',
+                                     encoding=config.editor_encoding) as 
temp_file:
+                        newcontent = temp_file.read()
+                    return newcontent
+            finally:
                 os.unlink(tempFilename)
-                return newcontent
 
         try:
             import gui  # noqa

-- 
To view, visit https://gerrit.wikimedia.org/r/184241
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: If7e9feee49acd1147c5554cdd74a7ad0758397c5
Gerrit-PatchSet: 4
Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Owner: XZise <[email protected]>
Gerrit-Reviewer: John Vandenberg <[email protected]>
Gerrit-Reviewer: Ladsgroup <[email protected]>
Gerrit-Reviewer: Merlijn van Deen <[email protected]>
Gerrit-Reviewer: XZise <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to