jenkins-bot submitted this change.

View Change


Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
[IMPR] Let user the choice which section to be copied

This patch enables to select all wanted sections step by step or in two
bulks for the section types related to the framework and related to the
scripts.

A help option is provided to get more information about a section or a
section type.

generate_user_files.py:
- New SCRIPT_SECTION to differentiate between script and framework
settings
- Let user the choice which which sections to include. copy_sections()
now calls input_sections to get the wanted sections
- input_sections() asks which section to be included. Framework
sections and scripts section could be included or excluded in bulk or
each section step by step. Help options are provided to show the
section of the given section type and a short help message for each
section to be processed. input_sections also add the selected section
to a list; this mutable is hold by copy_sections.
- Default response for bulk inclusion is [n]one, default answer of
section selection is [n]o.
- default parameters of input_sections and copy_sections are for tests
purposes only
- tests suite doesn't copy the whole sections of user-config.py any
longer but uses the SMALL_CONFIG part with its modifications by the
batch script. The force parameter is used by the test suite.

generate_user_files_tests.py
- tests modified and added

Bug: T145372
Change-Id: I68a04e9198dc179f06c6245f1c1aec518603bd34
---
M tests/generate_user_files_tests.py
M pywikibot/scripts/generate_user_files.py
2 files changed, 134 insertions(+), 21 deletions(-)

diff --git a/pywikibot/scripts/generate_user_files.py b/pywikibot/scripts/generate_user_files.py
index 6d4018e..5cfaa09 100755
--- a/pywikibot/scripts/generate_user_files.py
+++ b/pywikibot/scripts/generate_user_files.py
@@ -2,7 +2,9 @@
"""Script to create user-config.py. Other file names are not supported.

.. versionchanged:: 7.0
- moved to pywikibot.scripts folder
+ moved to pywikibot.scripts folder.
+.. versionchanged:: 8.0
+ let user the choice which section to be copied.
"""
#
# (C) Pywikibot team, 2010-2022
@@ -18,7 +20,7 @@
from textwrap import fill
from typing import Optional

-from pywikibot.backports import Tuple
+from pywikibot.backports import Callable, List, Tuple
from pywikibot.scripts import _import_with_no_user_config


@@ -33,6 +35,12 @@
OBSOLETE_SECTIONS = {
'ACCOUNT SETTINGS', # already set
}
+SCRIPT_SECTIONS = {
+ 'INTERWIKI SETTINGS',
+ 'SOLVE_DISAMBIGUATION SETTINGS',
+ 'WEBLINK CHECKER SETTINGS',
+ 'REPLICATION BOT SETTINGS',
+}

# Disable user-config usage as we are creating it here
pywikibot = _import_with_no_user_config('pywikibot')
@@ -221,6 +229,9 @@
{botpasswords}"""


+ConfigSection = namedtuple('ConfigSection', 'head, info, section')
+
+
def parse_sections() -> list:
"""Parse sections from config.py file.

@@ -230,7 +241,6 @@
:return: a list of ConfigSection named tuples.
"""
data = []
- ConfigSection = namedtuple('ConfigSection', 'head, info, section')

config_path = Path(__file__).resolve().parents[1].joinpath('config.py')
with codecs.open(config_path, 'r', 'utf-8') as config_f:
@@ -250,19 +260,84 @@
return data


-def copy_sections() -> str:
+def copy_sections(force: bool = False, default: str = 'n') -> str:
"""Take config sections and copy them to user-config.py.

+ .. versionchanged:: 8.0
+ *force* and *default* options were added.
+
+ :param force: Copy all sections if force is True
+ :param default: Default answer for input_sections.
+ Should be 'a' for all or 'n' for none to copy.
:return: config text of all selected sections.
"""
- result = []
sections = parse_sections()
- # copy settings
- for section in filter(lambda x: x.head not in (DISABLED_SECTIONS
- | OBSOLETE_SECTIONS),
- sections):
- result.append(section.section)
- return ''.join(result)
+ if not sections: # Something is wrong with the regex
+ return None
+
+ # copy framework settings
+ copies = input_sections(
+ 'framework', sections, force=force, default=default,
+ skip=lambda x: x.head not in (DISABLED_SECTIONS
+ | OBSOLETE_SECTIONS
+ | SCRIPT_SECTIONS))
+
+ # copy scripts settings
+ copies += input_sections(
+ 'scripts', sections, force=force, default=default,
+ skip=lambda x: x.head in SCRIPT_SECTIONS)
+
+ return ''.join(copies)
+
+
+def input_sections(variant: str,
+ sections: List['ConfigSection'],
+ skip: Optional[Callable] = None,
+ force: bool = False,
+ default: str = 'n') -> None:
+ """Ask for settings to copy.
+
+ .. versionadded:: 8.0
+
+ :param variant: Variant of the setting section. Either 'framework'
+ or 'scripts'
+ :param sections: A sections list previously read from the config file
+ :param skip: a filter function
+ :param force: Force input if True
+ """
+ # First ask what to do which the whole section type variant
+ select = 'h'
+ answers = [('Yes', 'y'), ('All', 'a'), ('None', 'n'), ('Help', 'h')]
+ while select == 'h':
+ select = pywikibot.input_choice(
+ f'Do you want to select {variant} setting sections?',
+ answers, default=default, force=force, automatic_quit=False)
+ if select == 'h':
+ answers.pop(-1)
+ pywikibot.info(
+ f'The following {variant} setting sections are provided:')
+ for item in filter(skip, sections):
+ pywikibot.output(item.head)
+
+ copies = []
+ # Now ask for a single section of the given variant
+ # or use all or none of them
+ choice = {'a': 'all', 'n': 'none', 'y': 'h'}[select] # mapping
+ for item in filter(skip, sections):
+ answers = [('Yes', 'y'), ('No', 'n'), ('Help', 'h')]
+ while choice == 'h':
+ choice = pywikibot.input_choice(
+ f'Do you want to add {item.head} section?',
+ answers, default='n', force=force, automatic_quit=False)
+ if choice == 'h':
+ answers.pop(-1)
+ pywikibot.info(fill(item.info))
+ if choice in ('all', 'y'):
+ copies.append(item.section) # Fill the mutable directly
+ if choice not in ('all', 'none'):
+ choice = 'h'
+
+ return copies


def create_user_config(
@@ -331,7 +406,7 @@
"('{}', BotPassword('{}', {!r}))".format(*botpassword)
for botpassword in botpasswords)

- config_text = copy_sections()
+ config_text = copy_sections(force=force)
if config_text:
config_content = EXTENDED_CONFIG
else:
diff --git a/tests/generate_user_files_tests.py b/tests/generate_user_files_tests.py
index f5e20bd..770ace4 100755
--- a/tests/generate_user_files_tests.py
+++ b/tests/generate_user_files_tests.py
@@ -84,25 +84,24 @@

def test_copy_sections_not_found(self):
"""Test copy_sections function for sections not in config text."""
- config_text = guf.copy_sections()
+ config_text = guf.copy_sections(force=True, default='a')
for section in guf.DISABLED_SECTIONS | guf.OBSOLETE_SECTIONS:
self.assertNotIn(section, config_text)

def test_copy_sections_found(self):
"""Test copy_sections function for sections found in config text."""
- config_text = guf.copy_sections()
+ config_text = guf.copy_sections(force=True, default='a')
self.assertIsNotNone(config_text)
- for section in ('LOGFILE SETTINGS',
- 'EXTERNAL SCRIPT PATH SETTINGS',
- 'INTERWIKI SETTINGS',
- 'FURTHER SETTINGS',
- 'HTTP SETTINGS',
- 'REPLICATION BOT SETTINGS',
- ):
+ for section in guf.SCRIPT_SECTIONS:
self.assertIn(section, config_text)
lines = config_text.splitlines()
self.assertGreater(len(lines), 200)

+ def test_copy_sections_none(self):
+ """Test read_sections function."""
+ config_text = guf.copy_sections(force=True)
+ self.assertEqual(config_text, '')
+

if __name__ == '__main__': # pragma: no cover
with suppress(SystemExit):

To view, visit change 309965. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I68a04e9198dc179f06c6245f1c1aec518603bd34
Gerrit-Change-Number: 309965
Gerrit-PatchSet: 29
Gerrit-Owner: Xqt <info@gno.de>
Gerrit-Reviewer: Dalba <dalba.wiki@gmail.com>
Gerrit-Reviewer: Dvorapa <dvorapa@seznam.cz>
Gerrit-Reviewer: Framawiki <framawiki@tools.wmflabs.org>
Gerrit-Reviewer: John Vandenberg <jayvdb@gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw@arctus.nl>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: Zhuyifei1999 <zhuyifei1999@gmail.com>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged