jenkins-bot has submitted this change and it was merged.
Change subject: generate_user_files: command line arguments ......................................................................
generate_user_files: command line arguments
Allow generate_user_files to be automated with command line arguments, either quietly or verbosely with -v
Added env PYWIKIBOT2_NO_USER_CONFIG=2 support to config2, so it doesnt emit warnings when generate_user_files is run without a user-config.
Fixed the extended user-config extraction regex, and add checks and fallbacks to simple user-config.
Add unicode_literals to generated user-config.
Remove user-config.py if an error occurred while generating it so the error is reproducible.
Removed use of locals(), added main(), moved imports to top.
Several improvements to bot input methods, such as defaults and force params, and a list selection function moved from generate_user_files into the main library for reuse.
generate_user_files is now used by jenkins so that the site test:test is explicitly used for nose tests, avoiding pwb emitting warnings that user-config does not exist. As a result, it is now easier do exact comparisons on the script output.
jenkins uses verbose extended user-config, and errors if the extended user-config cant be generated.
Change-Id: I7356d0fa38032fbbd18b72cfe267c36ee57eb7a7 --- M generate_user_files.py M pywikibot/bot.py M pywikibot/config2.py M pywikibot/userinterfaces/terminal_interface_base.py M tests/i18n_tests.py M tests/ui_tests.py M tox.ini 7 files changed, 308 insertions(+), 127 deletions(-)
Approvals: XZise: Looks good to me, approved jenkins-bot: Verified
diff --git a/generate_user_files.py b/generate_user_files.py index 825f948..57a3f60 100644 --- a/generate_user_files.py +++ b/generate_user_files.py @@ -1,23 +1,35 @@ +#!/usr/bin/python # -*- coding: utf-8 -*- """Script to create user files (user-config.py, user-fixes.py).""" # -# (C) Pywikibot team, 2010-2014 +# (C) Pywikibot team, 2010-2015 # # Distributed under the terms of the MIT license. # +from __future__ import unicode_literals __version__ = '$Id$' -#
-import os -import sys -import re import codecs -import math +import os +import re +import shutil +import sys + +from textwrap import wrap +from warnings import warn
# Disable user-config usage as we are creating it here -os.environ['PYWIKIBOT2_NO_USER_CONFIG'] = '1' +_orig_no_user_config = os.environ.get('PYWIKIBOT2_NO_USER_CONFIG') # noqa +os.environ['PYWIKIBOT2_NO_USER_CONFIG'] = '2' # noqa + import pywikibot
+from pywikibot import config + +if not _orig_no_user_config: + del os.environ['PYWIKIBOT2_NO_USER_CONFIG'] +else: + os.environ['PYWIKIBOT2_NO_USER_CONFIG'] = _orig_no_user_config
base_dir = pywikibot.config2.base_dir console_encoding = sys.stdout.encoding @@ -26,40 +38,6 @@
if console_encoding is None or sys.platform == 'cygwin': console_encoding = "iso-8859-1" - - -def listchoice(clist, message=None, default=None): - """Ask the user to select one entry from a list of entries.""" - if not message: - message = u"Select" - - if default: - message += u" (default: %s)" % default - - message += u": " - - line_template = u"{{0: >{0}}}: {{1}}".format(int(math.log10(len(clist)) + 1)) - for n, i in enumerate(clist): - pywikibot.output(line_template.format(n + 1, i)) - - while True: - choice = pywikibot.input(message) - - if choice == '' and default: - return default - try: - choice = int(choice) - 1 - except ValueError: - try: - choice = clist.index(choice) - except IndexError: - choice = -1 - - # User typed choice number - if 0 <= choice < len(clist): - return clist[choice] - else: - pywikibot.error("Invalid response")
def change_base_dir(): @@ -89,13 +67,13 @@ if new_base == pywikibot.config2.get_base_dir(new_base): # config would find that file return new_base - from textwrap import wrap + msg = wrap(u"""WARNING: Your user files will be created in the directory '%(new_base)s' you have chosen. To access these files, you will either have to use the argument "-dir:%(new_base)s" every time you run the bot, or set the environment variable "PYWIKIBOT2_DIR" equal to this directory name in your operating system. See your operating system documentation for how to -set environment variables.""" % locals(), width=76) +set environment variables.""" % {'new_base': new_base}, width=76) for line in msg: pywikibot.output(line) if pywikibot.input_yn('Is this OK?', default=False, automatic_quit=False): @@ -113,7 +91,7 @@
def get_site_and_lang(default_family='wikipedia', default_lang='en', - default_username=None): + default_username=None, force=False): """ Ask the user for the family, language and username.
@@ -130,10 +108,12 @@ known_families = sorted(pywikibot.config2.family_files.keys()) if default_family not in known_families: default_family = None - fam = listchoice(known_families, - u"Select family of sites we are working on, " - u"just enter the number or name", - default=default_family) + fam = pywikibot.bot.input_list_choice( + u"Select family of sites we are working on, " + u"just enter the number or name", + known_families, + force=force, + default=default_family) fam = pywikibot.family.Family.load(fam) if hasattr(fam, "langs"): if hasattr(fam, "languages_by_size"): @@ -163,12 +143,10 @@ else: default_lang = None message = "The language code of the site we're working on" - if default_lang: - message += " (default: '{0}')".format(default_lang) - message += ":" + mylang = None while not mylang: - mylang = pywikibot.input(message) or default_lang + mylang = pywikibot.input(message, default=default_lang, force=force) if known_langs and mylang and mylang not in known_langs: if not pywikibot.input_yn("The language code {0} is not in the " "list of known languages. Do you want " @@ -176,22 +154,15 @@ default=False, automatic_quit=False): mylang = None
- username = None message = u"Username on {0}:{1}".format(mylang, fam.name) - if default_username: - message += " (default: '{0}')".format(default_username) - message += ":" - while not username: - username = pywikibot.input(message) or default_username - if not username: - pywikibot.error('The username may not be empty.') - if sys.version_info == 2: - username = username.decode(console_encoding) + username = pywikibot.input(message, default=default_username, force=force) # Escape ''s - username = username.replace("'", "\'") + if username: + username = username.replace("'", "\'") return fam.name, mylang, username
EXTENDED_CONFIG = u"""# -*- coding: utf-8 -*- +from __future__ import unicode_literals
# This is an automatically generated file. You can find more configuration # parameters in 'config.py' file. @@ -238,40 +209,58 @@ {config_text}"""
SMALL_CONFIG = (u"# -*- coding: utf-8 -*-\n" + u"from __future__ import unicode_literals\n" u"family = '{main_family}'\n" u"mylang = '{main_lang}'\n" u"{usernames}\n")
-def create_user_config(): +def create_user_config(args=None, force=False): """Create a user-config.py in base_dir.""" _fnc = os.path.join(base_dir, "user-config.py") - if not file_exists(_fnc): - main_family, main_lang, main_username = get_site_and_lang() + if file_exists(_fnc): + return
+ if args and force and not config.verbose_output: + # main_username may be None, which is used in the next block + main_family, main_lang, main_username = args + usernames = [args] + else: + main_family, main_lang, main_username = get_site_and_lang(*args, + force=force) usernames = [(main_family, main_lang, main_username)] + while pywikibot.input_yn("Do you want to add any other projects?", + force=force, default=False, automatic_quit=False): usernames += [get_site_and_lang(main_family, main_lang, main_username)]
+ if not main_username: + usernames = "# usernames['{0}']['{1}'] = u'MyUsername'".format( + main_family, main_lang) + else: usernames = '\n'.join( u"usernames['{0}']['{1}'] = u'{2}'".format(*username) for username in usernames)
- extended = pywikibot.input_yn("Would you like the extended version of " - "user-config.py, with explanations " - "included?", automatic_quit=False) + config_text = '' + config_content = SMALL_CONFIG
- if extended: + if ((force and not config.verbose_output) or + pywikibot.input_yn('Would you like the extended version of ' + 'user-config.py, with explanations ' + 'included?', automatic_quit=False, + default=True, force=force)): + try: # config2.py will be in the pywikibot/ directory relative to this # script (generate_user_files) install = os.path.dirname(os.path.abspath(__file__)) with codecs.open(os.path.join(install, "pywikibot", "config2.py"), "r", "utf-8") as config_f: - config = config_f.read() + config_file = config_f.read()
- res = re.findall("^(############## (?:" + res = re.findall("^(# ############# (?:" "LOGFILE|" "INTERWIKI|" "SOLVE_DISAMBIGUATION|" @@ -282,16 +271,41 @@ "SEARCH ENGINE|" "COPYRIGHT|" "FURTHER" - ") SETTINGS .*?)^(?=#####|# =====)", - config, re.MULTILINE | re.DOTALL) - config_text = '\n'.join(res) - config_content = EXTENDED_CONFIG - else: - config_content = SMALL_CONFIG + ") SETTINGS .*)^(?=#####|# =====)", + config_file, re.MULTILINE | re.DOTALL)
+ if not res: + warn('Extended config extraction failed', UserWarning) + + config_text = '\n'.join(res) + if len(config_text.splitlines()) < 350: + warn('Extended config extraction too short: %d' + % len(config_text.splitlines()), + UserWarning) + + config_content = EXTENDED_CONFIG + except Exception as e: + # If the warning was explicitly enabled, raise + if isinstance(e, UserWarning): + raise + pywikibot.output('Exception while creating extended user-config; ' + 'falling back to simple user-config.') + pywikibot.exception() + + try: with codecs.open(_fnc, "w", "utf-8") as f: - f.write(config_content.format(**locals())) + f.write(config_content.format(main_family=main_family, + main_lang=main_lang, + usernames=usernames, + config_text=config_text)) + pywikibot.output(u"'%s' written." % _fnc) + except: + try: + os.remove(_fnc) + except: + pass + raise
def create_user_fixes(): @@ -318,11 +332,42 @@ """) pywikibot.output(u"'%s' written." % _fnf)
-if __name__ == "__main__": - while True: + +def main(*args): + """ + Process command line arguments and generate user-config. + + If args is an empty list, sys.argv is used. + + @param args: command line arguments + @type args: list of unicode + """ + global base_dir + # Force default + if config.family == 'wikipedia' and config.mylang == 'language': + config.mylang = 'en' + + default_args = (config.family, config.mylang, None) + + local_args = pywikibot.handle_args(args) + if local_args: + pywikibot.output('Unknown arguments: %s' % ' '.join(local_args)) + return False + + username = config.usernames[config.family].get(config.mylang) + args = (config.family, config.mylang, username) + + if args != default_args: + force = True + pywikibot.output(u'Automatically generating user-config.py') + else: + force = False + + while not force or config.verbose_output: pywikibot.output(u'\nYour default user directory is "%s"' % base_dir) if pywikibot.input_yn("Do you want to use that directory?", - default=False, automatic_quit=False): + default=True, automatic_quit=False, + force=force): break else: new_base = change_base_dir() @@ -332,12 +377,13 @@
copied_config = False copied_fixes = False - while True: + while not force or config.verbose_output: if os.path.exists(os.path.join(base_dir, "user-config.py")): break if pywikibot.input_yn( "Do you want to copy user files from an existing Pywikibot " "installation?", + default=False, force=force, automatic_quit=False): oldpath = pywikibot.input("Path to existing user-config.py?") if not os.path.exists(oldpath): @@ -349,7 +395,6 @@ if not os.path.isfile(os.path.join(oldpath, "user-config.py")): pywikibot.error("No user_config.py found in that directory") continue - import shutil shutil.copyfile(os.path.join(oldpath, "user-config.py"), os.path.join(base_dir, "user-config.py")) copied_config = True @@ -362,16 +407,23 @@ else: break if not os.path.isfile(os.path.join(base_dir, "user-config.py")): - if pywikibot.input_yn('Create user-config.py file? Required for ' - 'running bots.', - default=False, automatic_quit=False): - create_user_config() + if ((force and not config.verbose_output) or + pywikibot.input_yn('Create user-config.py file? Required for ' + 'running bots.', + default=True, automatic_quit=False, + force=force)): + create_user_config(args, force=force) elif not copied_config: pywikibot.output("user-config.py already exists in the directory") if not os.path.isfile(os.path.join(base_dir, "user-fixes.py")): - if pywikibot.input_yn('Create user-fixes.py file? Optional and for ' - 'advanced users.', - default=False, automatic_quit=False): + if ((force and not config.verbose_output) or + pywikibot.input_yn('Create user-fixes.py file? Optional and ' + 'for advanced users.', + force=force, + default=False, automatic_quit=False)): create_user_fixes() elif not copied_fixes: pywikibot.output("user-fixes.py already exists in the directory") + +if __name__ == '__main__': + main() diff --git a/pywikibot/bot.py b/pywikibot/bot.py index 580f760..446e8e1 100644 --- a/pywikibot/bot.py +++ b/pywikibot/bot.py @@ -241,15 +241,17 @@ warnings_logger = logging.getLogger("py.warnings") warnings_logger.setLevel(DEBUG)
- if hasattr(logging, 'captureWarnings'): - logging.captureWarnings(True) # introduced in Python >= 2.7 - else: - backports.captureWarnings(True) + # If there are command line warnings options, do not override them + if not sys.warnoptions: + if hasattr(logging, 'captureWarnings'): + logging.captureWarnings(True) # introduced in Python >= 2.7 + else: + backports.captureWarnings(True)
- if config.debug_log or 'deprecation' in config.log: - warnings.filterwarnings("always") - elif config.verbose_output: - warnings.filterwarnings("module") + if config.debug_log or 'deprecation' in config.log: + warnings.filterwarnings("always") + elif config.verbose_output: + warnings.filterwarnings("module")
root_logger.handlers = [] # remove any old handlers
@@ -531,7 +533,7 @@ # User input functions
-def input(question, password=False): +def input(question, password=False, default='', force=False): """Ask the user a question, return the user's answer.
@param question: a string that will be shown to the user. Don't add a @@ -539,18 +541,24 @@ @type question: unicode @param password: if True, hides the user's input (for password entry). @type password: bool + @param default: The default answer if none was entered. None to require + an answer. + @type default: basestring + @param force: Automatically use the default + @type force: bool + @rtype: unicode @rtype: unicode """ # make sure logging system has been initialized if not _handlers_initialized: init_handlers()
- data = ui.input(question, password) + data = ui.input(question, password=password, default=default, force=force) return data
def input_choice(question, answers, default=None, return_shortcut=True, - automatic_quit=True): + automatic_quit=True, force=False): """ Ask the user the question and return one of the valid answers.
@@ -569,6 +577,8 @@ @param automatic_quit: Adds the option 'Quit' ('q') and throw a L{QuitKeyboardInterrupt} if selected. @type automatic_quit: bool + @param force: Automatically use the default + @type force: bool @return: The selected answer shortcut or index. Is -1 if the default is selected, it does not return the shortcut and the default is not a valid shortcut. @@ -579,10 +589,10 @@ init_handlers()
return ui.input_choice(question, answers, default, return_shortcut, - automatic_quit) + automatic_quit=automatic_quit, force=force)
-def input_yn(question, default=None, automatic_quit=True): +def input_yn(question, default=None, automatic_quit=True, force=False): """ Ask the user a yes/no question and returns the answer as a bool.
@@ -594,6 +604,8 @@ @param automatic_quit: Adds the option 'Quit' ('q') and throw a L{QuitKeyboardInterrupt} if selected. @type automatic_quit: bool + @param force: Automatically use the default + @type force: bool @return: Return True if the user selected yes and False if the user selected no. If the default is not None it'll return True if default is True or 'y' and False if default is False or 'n'. @@ -607,7 +619,7 @@ assert default in ['y', 'Y', 'n', 'N', None]
return input_choice(question, [('Yes', 'y'), ('No', 'n')], default, - automatic_quit=automatic_quit) == 'y' + automatic_quit=automatic_quit, force=force) == 'y'
@deprecated('input_choice') @@ -639,6 +651,30 @@ automatic_quit=False)
+def input_list_choice(question, answers, default=None, + automatic_quit=True, force=False): + """ + Ask the user the question and return one of the valid answers. + + @param question: The question asked without trailing spaces. + @type question: basestring + @param answers: The valid answers each containing a full length answer. + @type answers: Iterable of basestring + @param default: The result if no answer was entered. It must not be in the + valid answers and can be disabled by setting it to None. + @type default: basestring + @param force: Automatically use the default + @type force: bool + @return: The selected answer. + @rtype: basestring + """ + if not _handlers_initialized: + init_handlers() + + return ui.input_list_choice(question, answers, default=default, + force=force) + + # Command line parsing and help def calledModuleName(): """Return the name of the module calling this function. diff --git a/pywikibot/config2.py b/pywikibot/config2.py index 4610e72..db23c5e 100644 --- a/pywikibot/config2.py +++ b/pywikibot/config2.py @@ -1,11 +1,26 @@ # -*- coding: utf-8 -*- """ -Module to define and load pywikibot configuration. +Module to define and load pywikibot configuration default and user preferences.
-Provides two family class methods which can be used in +User preferences are loaded from a python file called user-config.py, which +may be located in directory specified by the environment variable +PYWIKIBOT2_DIR, or the same directory as pwb.py, or in a directory within +the users home. See get_base_dir for more information. + +If user-config.py can not be found in any of those locations, this module +will fail to load unless the environment variable PYWIKIBOT2_NO_USER_CONFIG +is set to a value other than '0'. i.e. PYWIKIBOT2_NO_USER_CONFIG=1 will +allow config to load without a user-config.py. However, warnings will be +shown if user-config.py was not loaded. +To prevent these warnings, set PYWIKIBOT2_NO_USER_CONFIG=2. + +Provides two functions to register family classes which can be used in the user-config: - register_family_file - register_families_folder + +Other functions made available to user-config: + - user_home_path
Sets module global base_dir and provides utility methods to build paths relative to base_dir: @@ -37,6 +52,10 @@ # occur directly after the imports. At that point globals() only contains the # names and some magic variables (like __name__) _imports = frozenset(name for name in globals() if not name.startswith('_')) + +_no_user_config = os.environ.get('PYWIKIBOT2_NO_USER_CONFIG') +if _no_user_config == '0': + _no_user_config = None
class _ConfigurationDeprecationWarning(UserWarning): @@ -179,6 +198,11 @@ ignore_file_security_warnings = False
+def user_home_path(path): + """Return a file path to a file in the user home.""" + return os.path.join(os.path.expanduser('~'), path) + + def get_base_dir(test_directory=None): r"""Return the directory in which user-specific information is stored.
@@ -266,8 +290,9 @@ # check if user-config.py is in base_dir if not exists(base_dir): exc_text = "No user-config.py found in directory '%s'.\n" % base_dir - if os.environ.get('PYWIKIBOT2_NO_USER_CONFIG', '0') == '1': - print(exc_text) + if _no_user_config: + if _no_user_config != '2': + print(exc_text) else: exc_text += " Please check that user-config.py is stored in the correct location.\n" exc_text += " Directory where user-config.py is searched is determined as follows:\n\n" @@ -587,12 +612,12 @@ # Example for a pywikibot running on wmflabs: # db_hostname = 'enwiki.labsdb' # db_name_format = '{0}_p' -# db_connect_file = '~/replica.my.cnf' +# db_connect_file = user_home_path('replica.my.cnf') db_hostname = 'localhost' db_username = '' db_password = '' db_name_format = '{0}' -db_connect_file = os.path.expanduser('~/.my.cnf') +db_connect_file = user_home_path('.my.cnf')
# ############# SEARCH ENGINE SETTINGS ##############
@@ -844,8 +869,9 @@
# Get the user files _thislevel = 0 -if os.environ.get('PYWIKIBOT2_NO_USER_CONFIG', '0') == '1': - print("WARNING: Skipping loading of user-config.py.") +if _no_user_config: + if _no_user_config != '2': + print("WARNING: Skipping loading of user-config.py.") _fns = [] else: _fns = [os.path.join(_base_dir, "user-config.py")] @@ -934,7 +960,7 @@
# Fix up default site -if family == 'wikipedia' and mylang == 'language': +if family == 'wikipedia' and mylang == 'language' and _no_user_config != '2': print("WARNING: family and mylang are not set.\n" "Defaulting to family='test' and mylang='test'.") family = mylang = 'test' diff --git a/pywikibot/userinterfaces/terminal_interface_base.py b/pywikibot/userinterfaces/terminal_interface_base.py index 5a4c4b9..968a14b 100755 --- a/pywikibot/userinterfaces/terminal_interface_base.py +++ b/pywikibot/userinterfaces/terminal_interface_base.py @@ -11,6 +11,7 @@
import getpass import logging +import math import re import sys
@@ -198,20 +199,56 @@ else: return raw_input() # noqa
- def input(self, question, password=False): + def input(self, question, password=False, default='', force=False): """ Ask the user a question and return the answer.
Works like raw_input(), but returns a unicode string instead of ASCII.
- Unlike raw_input, this function automatically adds a space after the - question. + Unlike raw_input, this function automatically adds a colon and space + after the question if they are not already present. Also recognises + a trailing question mark. + + @param question: The question, without trailing whitespace. + @type question: basestring + @param password: if True, hides the user's input (for password entry). + @type password: bool + @param default: The default answer if none was entered. None to require + an answer. + @type default: basestring + @param force: Automatically use the default + @type force: bool + @rtype: unicode """ + assert(not password or not default) + end_marker = ':' + question = question.strip() + if question[-1] == ':': + question = question[:-1] + elif question[-1] == '?': + question = question[:-1] + end_marker = '?' + if default: + question = question + ' (default: %s)' % default + question = question + end_marker + if force: + self.output(question + '\n') + return default # sound the terminal bell to notify the user if config.ring_bell: sys.stdout.write('\07') # TODO: make sure this is logged as well - self.output(question + ' ') + while True: + self.output(question + ' ') + text = self._input_reraise_cntl_c(password) + if text: + return text + + if default is not None: + return default + + def _input_reraise_cntl_c(self, password): + """Input and decode, and re-raise Control-C.""" try: if password: # Python 3 requires that stderr gets flushed, otherwise is the @@ -227,7 +264,7 @@ return text
def input_choice(self, question, options, default=None, return_shortcut=True, - automatic_quit=True): + automatic_quit=True, force=False): """ Ask the user and returns a value from the options.
@@ -248,6 +285,8 @@ doesn't add the option but throw the exception when the option was selected. @type automatic_quit: bool or int + @param force: Automatically use the default + @type force: bool @return: If return_shortcut the shortcut of options or the value of default (if it's not None). Otherwise the index of the answer in options. If default is not a shortcut, it'll return -1. @@ -295,7 +334,10 @@ question = u'{0} ({1})'.format(question, ', '.join(formatted_options)) answer = None while answer is None: - answer = self.input(question) + if force: + self.output(question + '\n') + else: + answer = self.input(question) if default and not answer: # nothing entered answer = default_index else: @@ -324,6 +366,31 @@ default=default, return_shortcut=True, automatic_quit=False)
+ def input_list_choice(self, question, answers, default=None, force=False): + """Ask the user to select one entry from a list of entries.""" + message = question + clist = answers + + line_template = u"{{0: >{0}}}: {{1}}".format(int(math.log10(len(clist)) + 1)) + for n, i in enumerate(clist): + pywikibot.output(line_template.format(n + 1, i)) + + while True: + choice = self.input(message, default=default, force=force) + try: + choice = int(choice) - 1 + except ValueError: + try: + choice = clist.index(choice) + except IndexError: + choice = -1 + + # User typed choice number + if 0 <= choice < len(clist): + return clist[choice] + else: + pywikibot.error("Invalid response") + def editText(self, text, jumpIndex=None, highlight=None): """Return the text as edited by the user.
diff --git a/tests/i18n_tests.py b/tests/i18n_tests.py index c116abb..0634181 100644 --- a/tests/i18n_tests.py +++ b/tests/i18n_tests.py @@ -386,7 +386,7 @@ rv = i18n.input('pywikibot-enter-category-name', fallback_prompt='dummy output') self.assertEqual(rv, 'dummy input') - self.assertIn('dummy output ', self.output_text) + self.assertIn('dummy output: ', self.output_text)
if __name__ == '__main__': diff --git a/tests/ui_tests.py b/tests/ui_tests.py index 79fe078..eea9256 100644 --- a/tests/ui_tests.py +++ b/tests/ui_tests.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Tests for the user interface.""" # -# (C) Pywikibot team, 2008-2014 +# (C) Pywikibot team, 2008-2015 # # Distributed under the terms of the MIT license. # @@ -318,7 +318,7 @@
"""Terminal input tests."""
- input_choice_output = 'question ([A]nswer 1, a[n]swer 2, an[s]wer 3) ' + input_choice_output = 'question ([A]nswer 1, a[n]swer 2, an[s]wer 3): '
def testInput(self): newstdin.write('input to read\n') @@ -327,7 +327,7 @@ returned = pywikibot.input('question')
self.assertEqual(newstdout.getvalue(), '') - self.assertEqual(newstderr.getvalue(), 'question ') + self.assertEqual(newstderr.getvalue(), 'question: ')
self.assertIsInstance(returned, unicode) self.assertEqual(returned, u'input to read') @@ -455,7 +455,7 @@ self.assertEqual(newstdout.getvalue(), '') self.assertEqual( newstderr.getvalue(), - self._encode(u'Википедию? ', 'utf-8')) + self._encode(u'Википедию? ', 'utf-8'))
self.assertIsInstance(returned, unicode) self.assertEqual(returned, u'Заглавная_страница') diff --git a/tox.ini b/tox.ini index 0dfda1d..21635da 100644 --- a/tox.ini +++ b/tox.ini @@ -116,8 +116,8 @@ flake8-docstrings
[testenv:nose] -setenv = PYWIKIBOT2_NO_USER_CONFIG=1 commands = + python -W error::UserWarning -m generate_user_files -family:test -lang:test -v nosetests --version nosetests --with-doctest --with-doctest-ignore-unicode -v -a "!net" tests pywikibot {[params]nose_skip} deps = @@ -127,8 +127,8 @@
[testenv:nose34] basepython = python3 -setenv = PYWIKIBOT2_NO_USER_CONFIG=1 commands = + python -W error::UserWarning -m generate_user_files -family:test -lang:test -v nosetests --version nosetests --with-doctest --with-doctest-ignore-unicode -v -a "!net" tests pywikibot {[params]nose_skip} deps =
pywikibot-commits@lists.wikimedia.org