Issue2209

classification
Title: built-in function help() doesn't work and gets stuck
Type: Severity: normal
Components: Core Versions: Jython 2.7
Milestone:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: zyasoft Nosy List: girish946, kanglecjr, zyasoft
Priority: high Keywords:

Created on 2014-09-13.02:56:53 by kanglecjr, last changed 2015-01-26.21:56:48 by zyasoft.

Files
File name Uploaded Description Edit Remove
2014-9-13_help.png kanglecjr, 2014-09-13.02:56:52
pydoc.py girish946, 2014-09-19.18:41:57
Messages
msg8997 (view) Author: Jonathan (kanglecjr) Date: 2014-09-13.02:56:52
built-in function help() doesn't work and gets stuck
msg8998 (view) Author: Jim Baker (zyasoft) Date: 2014-09-13.04:53:51
So help does work on my Unix-type systems (OS X 10.9.4 and Ubuntu 14.04), but hangs on Windows 8.1, just like this bug report. So the issue is not just Windows XP or CJK support as seen in the attached screenshot.

Probably another reason for us to upgrade to JLine 2 as requested by #2092
msg9007 (view) Author: girish joshi (girish946) Date: 2014-09-19.18:41:57
help is not being displayed because
 os.environ.get('TERM') in ('dumb', 'emacs')
in getpager() function always return False as i don't have 'dumb' or 'emacs' terminal configured in my environment and that's why the help() does nothing.
i removed the " in ('dumb' , 'emacs' ) " part and help() is working fine.

now the getpager() looks like

def getpager():
    """Decide what method to use for paging through text."""
    if type(sys.stdout) is not types.FileType:
        return plainpager
    if not sys.stdin.isatty() or not sys.stdout.isatty():
        return plainpager
    if 'PAGER' in os.environ:
        if sys.platform == 'win32': # pipes completely broken in Windows
            return lambda text: tempfilepager(plain(text), os.environ['PAGER'])
        #elif os.environ.get('TERM') in ('dumb', 'emacs'):
        elif os.environ.get('TERM'):
            return lambda text: pipepager(plain(text), os.environ['PAGER'])
        else:
            return lambda text: pipepager(text, os.environ['PAGER'])
    #if os.environ.get('TERM') in ('dumb', 'emacs'):
    if os.environ.get('TERM'):
        return plainpager
    if sys.platform == 'win32' or sys.platform.startswith('os2'):
        return lambda text: tempfilepager(plain(text), 'more <')
    if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
        return lambda text: pipepager(text, 'less')
    import tempfile
    (fd, filename) = tempfile.mkstemp()
    os.close(fd)
    try:
        if hasattr(os, 'system') and os.system('more "%s"' % filename) == 0:
            return lambda text: pipepager(text, 'more')
        else:
            return ttypager
    finally:
        os.unlink(filename)
msg9008 (view) Author: Jim Baker (zyasoft) Date: 2014-09-19.19:12:57
Girish, thanks for your debugging help here! That definitely points us to a correct solution for Jython.
msg9109 (view) Author: Jim Baker (zyasoft) Date: 2014-10-06.12:34:05
Reviewing the code below we need to do a better test of running on a Windows environment:

if sys.platform == 'win32':

will never dispatch for Windows specifically, since this always returns the underlying Java platform with version, such as 'java1.7.0_21'

Situations like this make me think how nice it would be if we wrote some pexpect tests (using CPython :) for Jython's version of the regrtest.
msg9111 (view) Author: Jim Baker (zyasoft) Date: 2014-10-06.13:13:25
Should be easy to fix (even if we won't have automated testing), so putting in for beta 4
msg9402 (view) Author: Jim Baker (zyasoft) Date: 2015-01-15.20:59:08
Unfortunately, this problem is not so easy to fix: it's not just a matter of dispatching on Windows. I also tried creating a minimal program to see if it would help:

import os
from subprocess import _cmdline2listimpl, _escape_args, _shell_command
from java.lang import IllegalArgumentException, ProcessBuilder
from java.io import File, IOException

def page(command):
    args = _cmdline2listimpl(command)
    args = _escape_args(args)
    args = _shell_command + args
    print repr(args)
    cwd = os.getcwd()
    builder = ProcessBuilder(args)
    builder.directory(File(cwd))
    builder.redirectOutput(ProcessBuilder.Redirect.INHERIT)
    try:
        proc = builder.start()
        return proc.waitFor()
    except (IOException,
            IllegalArgumentException), e:
        raise OSError(e.getMessage() or e)

page("more NEWS")

Works on posix systems, but not on Windows.

Most likely this is some bad interaction between JLine and the subprocess. I believe the way to fix this is to use JLine, by writing a pager directly against it. Should be reasonably straightforward.
msg9403 (view) Author: Jim Baker (zyasoft) Date: 2015-01-15.21:05:27
http://stackoverflow.com/a/19668347/423006 has some pertinent advice
msg9405 (view) Author: Jim Baker (zyasoft) Date: 2015-01-15.23:09:08
A simple pager in JLine 1:

import sys

def page_news():
    news = []
    with open("NEWS") as f:
        for row in f:
            news.append(row)

    reader = sys._jy_console.reader
    reader.usePagination = True
    reader.printColumns(news)

It's not very good, including the lack of screen redraw and moving back (similar to more vs less), but it seems to mostly comparable to what we get in CPython on Windows when using help.

There's a spurious extra >>> that's drawn after completing the paging:

>>> >>>

with the cursor positioned on the first > of the second group. I will see if it is possible to redraw the line properly (redrawLine doesn't do it).

Switching to JLine 2 (#2092) might make this work better, but that's a longer term proposition we have postponed to 2.7.x, x>0
msg9416 (view) Author: Jim Baker (zyasoft) Date: 2015-01-17.18:30:45
Upgraded in JLine2 (#2092) in part to fix this bug. Next step is a custom pager for Windows using JLine2, should be completed shortly
msg9426 (view) Author: Jim Baker (zyasoft) Date: 2015-01-19.16:16:32
Fixed as of https://hg.python.org/jython/rev/6e8e76987965
History
Date User Action Args
2015-01-26 21:56:48zyasoftsetstatus: pending -> closed
2015-01-19 16:16:32zyasoftsetstatus: open -> pending
resolution: accepted -> fixed
messages: + msg9426
2015-01-17 18:30:46zyasoftsetmessages: + msg9416
2015-01-15 23:09:08zyasoftsetmessages: + msg9405
2015-01-15 21:05:27zyasoftsetmessages: + msg9403
2015-01-15 20:59:09zyasoftsetmessages: + msg9402
2015-01-07 06:19:25zyasoftsetassignee: zyasoft
2014-10-06 13:13:25zyasoftsetpriority: high
messages: + msg9111
2014-10-06 12:34:05zyasoftsetmessages: + msg9109
2014-09-19 19:12:57zyasoftsetmessages: + msg9008
2014-09-19 18:42:00girish946setfiles: + pydoc.py
nosy: + girish946
messages: + msg9007
2014-09-13 04:53:51zyasoftsetresolution: accepted
messages: + msg8998
nosy: + zyasoft
2014-09-13 02:56:53kanglecjrcreate