jenkins-bot submitted this change.

View Change

Approvals: Xqt: Looks good to me, approved jenkins-bot: Verified
[bugfix] postpone hte cached output implementation

Bug: T282962
Change-Id: I0dc8cee5512840b559c76458c02533d598a93c24
---
M ROADMAP.rst
M pywikibot/userinterfaces/terminal_interface_base.py
M tests/i18n_tests.py
3 files changed, 61 insertions(+), 93 deletions(-)

diff --git a/ROADMAP.rst b/ROADMAP.rst
index eb79753..c39575b 100644
--- a/ROADMAP.rst
+++ b/ROADMAP.rst
@@ -5,7 +5,6 @@
-------------------------

* Fix iterating of SizedKeyCollection (T282865)
-* The cached output functionality from compat relase was re-implemented (T151727, T73646, T74942, T132135, T144698, T196039, T280466)
* An abstract base user interface module was added
* APISite method pagelanglinks() may skip links with empty titles (T223157)
* Fix Page.getDeletedRevision() method which always returned an empty list
diff --git a/pywikibot/userinterfaces/terminal_interface_base.py b/pywikibot/userinterfaces/terminal_interface_base.py
index 4adcac6..1b12f26 100755
--- a/pywikibot/userinterfaces/terminal_interface_base.py
+++ b/pywikibot/userinterfaces/terminal_interface_base.py
@@ -13,7 +13,7 @@

import pywikibot
from pywikibot import config
-from pywikibot.backports import Sequence, SimpleQueue
+from pywikibot.backports import Sequence
from pywikibot.bot_choice import (
ChoiceException,
Option,
@@ -22,7 +22,7 @@
StandardOption,
)
from pywikibot.logging import INFO, INPUT, STDOUT, VERBOSE, WARNING
-from pywikibot.tools import deprecated_args, RLock
+from pywikibot.tools import deprecated_args
from pywikibot.userinterfaces import transliteration
from pywikibot.userinterfaces._interface_base import ABUIC

@@ -77,9 +77,6 @@
self.encoding = config.console_encoding
self.transliteration_target = config.transliteration_target

- self.cache = SimpleQueue()
- self.lock = RLock()
-
def init_handlers(self, root_logger, default_stream='stderr'):
"""Initialize the handlers for user output.

@@ -188,38 +185,12 @@
self.encounter_color(color_stack[-1], target_stream)

def output(self, text, targetStream=None):
- """Forward text to cache and flush if output is not locked.
-
- All input methods locks the output to a stream but collect them
- in cache. They will be printed with next unlocked output call or
- at termination time.
- """
- self.cache_output(text, targetStream=targetStream)
- if not self.lock.locked():
- self.flush()
-
- def flush(self):
- """Output cached text."""
- while not self.cache.empty():
- args, kwargs = self.cache.get_nowait()
- self.stream_output(*args, **kwargs)
-
- def cache_output(self, *args, **kwargs):
- """Put text to cache.
-
- *New in version 6.2*
- """
- self.cache.put_nowait((args, kwargs))
-
- def stream_output(self, text, targetStream=None):
"""
Output text to a stream.

If a character can't be displayed in the encoding used by the user's
terminal, it will be replaced with a question mark or by a
transliteration.
-
- *New in version 6.2*
"""
if config.transliterate:
# Encode our unicode string in the encoding used by the user's
@@ -305,26 +276,26 @@
question += end_marker

# lock stream output
- with self.lock:
- if force:
- self.stream_output(question + '\n')
+ # with self.lock: (T282962)
+ 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
+ while True:
+ self.output(question + ' ')
+ text = self._input_reraise_cntl_c(password)
+
+ if text is None:
+ continue
+
+ if text:
+ return text
+
+ if default is not None:
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
- while True:
- self.stream_output(question + ' ')
- text = self._input_reraise_cntl_c(password)
-
- if text is None:
- continue
-
- 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."""
@@ -377,7 +348,7 @@
"""Print an OutputOption before or after question."""
if isinstance(option, OutputOption) \
and option.before_question is before_question:
- self.stream_output(option.out + '\n')
+ self.output(option.out + '\n')

if force and default is None:
raise ValueError('With no default option it cannot be forced')
@@ -402,24 +373,24 @@
handled = False

# lock stream output
- with self.lock:
- while not handled:
- for option in options:
- output_option(option, before_question=True)
- output = Option.formatted(question, options, default)
- if force:
- self.stream_output(output + '\n')
- answer = default
- else:
- answer = self.input(output) or default
- # something entered or default is defined
- if answer:
- for index, option in enumerate(options):
- if option.handled(answer):
- answer = option.result(answer)
- output_option(option, before_question=False)
- handled = option.stop
- break
+ # with self.lock: (T282962)
+ while not handled:
+ for option in options:
+ output_option(option, before_question=True)
+ output = Option.formatted(question, options, default)
+ if force:
+ self.output(output + '\n')
+ answer = default
+ else:
+ answer = self.input(output) or default
+ # something entered or default is defined
+ if answer:
+ for index, option in enumerate(options):
+ if option.handled(answer):
+ answer = option.result(answer)
+ output_option(option, before_question=False)
+ handled = option.stop
+ break

if isinstance(answer, ChoiceException):
raise answer
@@ -440,33 +411,31 @@
@return: Return a single Sequence entry.
"""
# lock stream output
- with self.lock:
- if not force:
- line_template = '{{0: >{}}}: {{1}}'.format(
- len(str(len(answers))))
- for i, entry in enumerate(answers, start=1):
- self.stream_output(line_template.format(i, entry))
+ # with self.lock: (T282962)
+ if not force:
+ line_template = '{{0: >{}}}: {{1}}'.format(len(str(len(answers))))
+ for i, entry in enumerate(answers, start=1):
+ self.output(line_template.format(i, entry))

- while True:
- choice = self.input(question, default=default, force=force)
+ while True:
+ choice = self.input(question, default=default, force=force)

- try:
- choice = int(choice) - 1
- except (TypeError, ValueError):
- if choice in answers:
- return choice
- choice = -1
+ try:
+ choice = int(choice) - 1
+ except (TypeError, ValueError):
+ if choice in answers:
+ return choice
+ choice = -1

- # User typed choice number
- if 0 <= choice < len(answers):
- return answers[choice]
+ # User typed choice number
+ if 0 <= choice < len(answers):
+ return answers[choice]

- if force:
- raise ValueError(
- 'Invalid value "{}" for default during force.'
- .format(default))
+ if force:
+ raise ValueError('Invalid value "{}" for default during force.'
+ .format(default))

- pywikibot.error('Invalid response')
+ pywikibot.error('Invalid response')

def editText(self, text: str, jumpIndex: Optional[int] = None,
highlight: Optional[str] = None):
diff --git a/tests/i18n_tests.py b/tests/i18n_tests.py
index b80d6fb..74c2be5 100644
--- a/tests/i18n_tests.py
+++ b/tests/i18n_tests.py
@@ -342,7 +342,7 @@
self.orig_raw_input = bot.ui._raw_input
self.orig_output = bot.ui.output
bot.ui._raw_input = lambda *args, **kwargs: 'dummy input'
- bot.ui.stream_output = self._capture_output
+ bot.ui.output = self._capture_output
self.old_cc_setting = config.cosmetic_changes_mylang_only

def tearDown(self):

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

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I0dc8cee5512840b559c76458c02533d598a93c24
Gerrit-Change-Number: 696497
Gerrit-PatchSet: 3
Gerrit-Owner: Xqt <info@gno.de>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: jenkins-bot
Gerrit-MessageType: merged