jenkins-bot has submitted this change and it was merged.
Change subject: Bug 54726 - Add Windows unicode cmd argument support ......................................................................
Bug 54726 - Add Windows unicode cmd argument support
Instead of working with the encoded sys.argv, we now use the unicode pywikibot.argvu, which is set by the active userinterface. The UI knows how to get the correct unicode argv (depending on OS).
pwb.py is adapted to use pwb.argvu in addition to sys.argv
Change-Id: Ifde7e42587f4a4493ca3c5d8f5ed1ab06bbd806b --- M pwb.py M pywikibot/bot.py M pywikibot/userinterfaces/terminal_interface_base.py M pywikibot/userinterfaces/terminal_interface_win32.py M tests/ui_tests.py 5 files changed, 46 insertions(+), 32 deletions(-)
Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
diff --git a/pwb.py b/pwb.py index 04eb17e..08e586e 100644 --- a/pwb.py +++ b/pwb.py @@ -23,12 +23,11 @@ import sys
-def run_python_file(filename, args): +def run_python_file(filename, argv, argvu): """Run a python file as if it were the main program on the command line.
`filename` is the path to the file to execute, it need not be a .py file. - `args` is the argument array to present as sys.argv, including the first - element representing the file being executed. + `args` is the argument array to present as sys.argv, as unicode strings.
""" # Create a module to serve as __main__ @@ -40,8 +39,11 @@
# Set sys.argv and the first path element properly. old_argv = sys.argv + old_argvu = pwb.argvu old_path0 = sys.path[0] - sys.argv = args + + sys.argv = argv + pwb.argvu = argvu sys.path[0] = os.path.dirname(filename)
try: @@ -54,6 +56,7 @@ # Restore the old argv and path sys.argv = old_argv sys.path[0] = old_path0 + pwb.argvu = old_argvu
#### end of snippet
@@ -87,9 +90,11 @@ print "Please follow the prompts to create it:" run_python_file('generate_user_files.py', ['generate_user_files.py'])
+import pywikibot as pwb if len(sys.argv) > 1: fn = sys.argv[1] - args = sys.argv[1:] + argv = sys.argv[1:] + argvu = pwb.argvu[1:]
if not os.path.exists(fn): testpath = os.path.join(os.path.split(__file__)[0], 'scripts', fn) @@ -101,4 +106,4 @@ fn = testpath else: raise Exception("%s not found!" % fn) - run_python_file(fn, args) + run_python_file(fn, argv, argvu) diff --git a/pywikibot/bot.py b/pywikibot/bot.py index 45c1098..bb793c8 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -40,10 +40,10 @@ % config.userinterface, fromlist=['UI']) ui = uiModule.UI() +argvu = ui.argvu()
# Logging module configuration - class RotatingFileHandler(logging.handlers.RotatingFileHandler):
def doRollover(self): @@ -493,8 +493,6 @@
# Command line parsing and help - - def calledModuleName(): """Return the name of the module calling this function.
@@ -503,35 +501,17 @@
""" # get commandline arguments - called = sys.argv[0].strip() + called = argvu[0].strip() if ".py" in called: # could end with .pyc, .pyw, etc. on some platforms # clip off the '.py?' filename extension called = called[:called.rindex('.py')] return os.path.basename(called)
-def _decodeArg(arg): - if sys.platform == 'win32': - if config.console_encoding in ('cp437', 'cp850'): - # Western Windows versions give parameters encoded as windows-1252 - # even though the console encoding is cp850 or cp437. - return unicode(arg, 'windows-1252') - elif config.console_encoding == 'cp852': - # Central/Eastern European Windows versions give parameters encoded - # as windows-1250 even though the console encoding is cp852. - return unicode(arg, 'windows-1250') - else: - return unicode(arg, config.console_encoding) - else: - # Linux uses the same encoding for both. - # I don't know how non-Western Windows versions behave. - return unicode(arg, config.console_encoding) - - def handleArgs(*args): """Handle standard command line arguments, return the rest as a list.
- Takes the commandline arguments, converts them to Unicode, processes all + Takes the commandline arguments as Unicode strings, processes all global parameters such as -lang or -log. Returns a list of all arguments that are not global. This makes sure that global arguments are applied first, regardless of the order in which the arguments were given. @@ -541,7 +521,10 @@ """ # get commandline arguments if necessary if not args: - args = sys.argv[1:] + # it's the version in pywikibot.__init__ that is changed by scripts, + # not the one in pywikibot.bot. + from pywikibot import argvu + args = argvu[1:] # get the name of the module calling this function. This is # required because the -help option loads the module's docstring and because # the module name will be used for the filename of the log. @@ -552,7 +535,6 @@ username = None do_help = False for arg in args: - arg = _decodeArg(arg) if arg == '-help': do_help = True elif arg.startswith('-family:'): diff --git a/pywikibot/userinterfaces/terminal_interface_base.py b/pywikibot/userinterfaces/terminal_interface_base.py index 84f7102..b1fcbe1 100755 --- a/pywikibot/userinterfaces/terminal_interface_base.py +++ b/pywikibot/userinterfaces/terminal_interface_base.py @@ -45,6 +45,7 @@ self.stdin = sys.stdin self.stdout = sys.stdout self.stderr = sys.stderr + self.argv = sys.argv self.encoding = config.console_encoding self.transliteration_target = config.transliteration_target
@@ -262,6 +263,9 @@ return wikipedia.input( u'What is the solution of the CAPTCHA at this url ?')
+ def argvu(self): + return [s.decode(self.encoding) for s in self.argv] +
class TerminalHandler(logging.Handler): """A handler class that writes logging records, appropriately formatted, to diff --git a/pywikibot/userinterfaces/terminal_interface_win32.py b/pywikibot/userinterfaces/terminal_interface_win32.py index 3507701..3b8cea1 100755 --- a/pywikibot/userinterfaces/terminal_interface_win32.py +++ b/pywikibot/userinterfaces/terminal_interface_win32.py @@ -48,10 +48,11 @@ class Win32CtypesUI(Win32BaseUI): def __init__(self): Win32BaseUI.__init__(self) - from win32_unicode import stdin, stdout, stderr + from win32_unicode import stdin, stdout, stderr, argv self.stdin = stdin self.stdout = stdout self.stderr = stderr + self.argv = argv self.encoding = 'utf-8'
def printColorized(self, text, targetStream): diff --git a/tests/ui_tests.py b/tests/ui_tests.py index 5f49727..ad8f8be 100644 --- a/tests/ui_tests.py +++ b/tests/ui_tests.py @@ -456,6 +456,28 @@
self.assertEqual(returned, u"Заглавная_страница")
+ class TestWindowsTerminalUnicodeArguments(WindowsTerminalTestCase): + @classmethod + def setUpClass(cls): + import inspect + cls.setUpProcess(["cmd", "/k", "echo off"]) + + @classmethod + def tearDownClass(cls): + cls.tearDownProcess() + pass + + def testOutputUnicodeText_no_transliterate(self): + self.sendstdin(u"""python -c "import os, pywikibot; os.system('cls'); pywikibot.output(u'\n'.join(pywikibot.handleArgs()))" Alpha Bετα Гамма دلتا\n""") + while(True): + lines = self.getstdouterr().split("\n") + if len(lines) >= 4 and lines[0] == "Alpha": + break + time.sleep(1) + + # empty line is the new command line + self.assertEqual(lines, [u"Alpha", u"Bετα", u"Гамма", u"دلتا", u""]) + try: try: unittest.main()
pywikibot-commits@lists.wikimedia.org