terminal_interface.py :  » Network » Python-Wikipedia-Robot-Framework » pywikipedia » userinterfaces » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » Python Wikipedia Robot Framework 
Python Wikipedia Robot Framework » pywikipedia » userinterfaces » terminal_interface.py
# -*- coding: utf-8 -*-
#
# (C) Pywikipedia bot team, 2003-2007
#
# Distributed under the terms of the MIT license.
#
__version__ = '$Id: terminal_interface.py 7214 2009-09-06 14:16:31Z alexsh $'

import config, transliteration
import traceback, re, sys
import wikipedia

try:
    import ctypes
    ctypes_found = True
except ImportError:
    ctypes_found = False

transliterator = transliteration.transliterator()

def getDefaultTextColorInWindows():
    """
    This method determines the default text color and saves its color
    code inside the variable windowsColors['default'].

    Based on MIT-licensed code by Andre Burgaud published at
    http://starship.python.net/crew/theller/wiki/ColorConsole
    """
    if sys.platform != 'win32' or not ctypes_found:
        return -1
    SHORT = ctypes.c_short
    WORD = ctypes.c_ushort

    # wincon.h
    class COORD(ctypes.Structure):
        _fields_ = [
            ("X", SHORT),
            ("Y", SHORT)
        ]

    class SMALL_RECT(ctypes.Structure):
        _fields_ = [
            ("Left", SHORT),
            ("Top", SHORT),
            ("Right", SHORT),
            ("Bottom", SHORT)
        ]

    class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
        _fields_ = [
            ("dwSize", COORD),
            ("dwCursorPosition", COORD),
            ("wAttributes", WORD),
            ("srWindow", SMALL_RECT),
            ("dwMaximumWindowSize", COORD)
        ]

    std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11)
    csbi = CONSOLE_SCREEN_BUFFER_INFO()
    ctypes.windll.kernel32.GetConsoleScreenBufferInfo(std_out_handle, ctypes.byref(csbi))
    return (csbi.wAttributes & 0x000f)

# TODO: other colors:
         #0 = Black
         #1 = Blue
         #2 = Green
         #3 = Aqua
         #4 = Red
         #5 = Purple
         #6 = Yellow
         #7 = White
         #8 = Gray
         #9 = Light Blue
        #10 = Light Green
        #11 = Light Aqua
        #12 = Light Red
        #13 = Light Purple
        #14 = Light Yellow
        #15 = Bright White

unixColors = {
    'default':     chr(27) + '[0m',     # Unix end tag to switch back to default
    'lightblue':   chr(27) + '[94;1m',  # Light Blue start tag
    'lightgreen':  chr(27) + '[92;1m',  # Light Green start tag
    'lightaqua':   chr(27) + '[36;1m',  # Light Aqua start tag
    'lightred':    chr(27) + '[91;1m',  # Light Red start tag
    'lightpurple': chr(27) + '[35;1m',  # Light Purple start tag
    'lightyellow': chr(27) + '[33;1m',  # Light Yellow start tag
}

windowsColors = {
    'default':     7,
    'black':       0,
    'blue':        1,
    'green':       2,
    'aqua':        3,
    'red':         4,
    'purple':      5,
    'yellow':      6,
    'lightgray':   7,
    'gray':        8,
    'lightblue':   9,
    'lightgreen':  10,
    'lightaqua':   11,
    'lightred':    12,
    'lightpurple': 13,
    'lightyellow': 14,
    'white':       15,
}

colorTagR = re.compile('\03{(?P<name>%s)}' % '|'.join(windowsColors.keys()))

class UI:
    def __init__(self):
        pass

    def printColorizedInUnix(self, text, targetStream):
        lastColor = None
        for key, value in unixColors.iteritems():
            text = text.replace('\03{%s}' % key, value)
        # just to be sure, reset the color
        text += unixColors['default']

        targetStream.write(text.encode(config.console_encoding, 'replace'))

    def printColorizedInWindows(self, text, targetStream):
        """
        This only works in Python 2.5 or higher.
        """
        if ctypes_found:
            std_out_handle = ctypes.windll.kernel32.GetStdHandle(-11)
            # Color tags might be cascaded, e.g. because of transliteration.
            # Therefore we need this stack.
            colorStack = []
            tagM = True
            while tagM:
                tagM = colorTagR.search(text)
                if tagM:
                    # print the text up to the tag.
                    targetStream.write(text[:tagM.start()].encode(config.console_encoding, 'replace'))
                    newColor = tagM.group('name')
                    if newColor == 'default':
                        if len(colorStack) > 0:
                            colorStack.pop()
                            if len(colorStack) > 0:
                                lastColor = colorStack[-1]
                            else:
                                lastColor = 'default'
                            ctypes.windll.kernel32.SetConsoleTextAttribute(std_out_handle, windowsColors[lastColor])
                    else:
                        colorStack.append(newColor)
                        # set the new color
                        ctypes.windll.kernel32.SetConsoleTextAttribute(std_out_handle, windowsColors[newColor])
                    text = text[tagM.end():]
            # print the rest of the text
            targetStream.write(text.encode(config.console_encoding, 'replace'))
            # just to be sure, reset the color
            ctypes.windll.kernel32.SetConsoleTextAttribute(std_out_handle, windowsColors['default'])
        else:
            # ctypes is only available since Python 2.5, and we won't
            # try to colorize without it. Instead we add *** after the text as a whole
            # if anything needed to be colorized.
            lines = text.split('\n')
            for line in lines:
                line, count = colorTagR.subn('', line)
                if count > 0:
                    line += '***'
                line += '\n'
                targetStream.write(line.encode(config.console_encoding, 'replace'))

    def printColorized(self, text, targetStream):
        if config.colorized_output:
            if sys.platform == 'win32':
                self.printColorizedInWindows(text, targetStream)
            else:
                self.printColorizedInUnix(text, targetStream)
        else:
            targetStream.write(text.encode(config.console_encoding, 'replace'))

    def output(self, text, toStdout = False):
        """
        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.
        """
        if config.transliterate:
            # Encode our unicode string in the encoding used by the user's console,
            # and decode it back to unicode. Then we can see which characters
            # can't be represented in the console encoding.
            codecedText = text.encode(config.console_encoding, 'replace').decode(config.console_encoding)
            transliteratedText = ''
            # Note: A transliteration replacement might be longer than the original
            # character, e.g.  is transliterated to ch.
            prev = "-"
            for i in xrange(len(codecedText)):
                # work on characters that couldn't be encoded, but not on
                # original question marks.
                if codecedText[i] == '?' and text[i] != u'?':
                    try:
                        transliterated = transliterator.transliterate(text[i], default = '?', prev = prev, next = text[i+1])
                    except IndexError:
                        transliterated = transliterator.transliterate(text[i], default = '?', prev = prev, next = ' ')
                    # transliteration was successful. The replacement
                    # could consist of multiple letters.
                    # mark the transliterated letters in yellow.
                    transliteratedText += '\03{lightyellow}%s\03{default}' % transliterated
                    transLength = len(transliterated)
                    # memorize if we replaced a single letter by multiple letters.
                    if len(transliterated) > 0:
                        prev = transliterated[-1]
                else:
                    # no need to try to transliterate.
                    transliteratedText += codecedText[i]
                    prev = codecedText[i]
            text = transliteratedText

        if toStdout:
            targetStream = sys.stdout
        else:
            targetStream = sys.stderr
        self.printColorized(text, targetStream)

    def input(self, question, password = False):
        """
        Works like raw_input(), but returns a unicode string instead of ASCII.

        Unlike raw_input, this function automatically adds a space after the
        question.
        """

        # 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 + ' ')
        if password:
            import getpass
            text = getpass.getpass('')
        else:
            text = raw_input()
        text = unicode(text, config.console_encoding)
        return text

    def inputChoice(self, question, options, hotkeys, default = None):
        options = options[:] # we don't want to edit the passed parameter
        for i in range(len(options)):
            option = options[i]
            hotkey = hotkeys[i]
            # try to mark a part of the option name as the hotkey
            m = re.search('[%s%s]' % (hotkey.lower(), hotkey.upper()), option)
            if hotkey == default:
                caseHotkey = hotkey.upper()
            else:
                caseHotkey = hotkey
            if m:
                pos = m.start()
                options[i] = '%s[%s]%s' % (option[:pos], caseHotkey, option[pos+1:])
            else:
                options[i] = '%s [%s]' % (option, caseHotkey)
        # loop until the user entered a valid choice
        while True:
            prompt = '%s (%s)' % (question, ', '.join(options))
            answer = self.input(prompt)
            if answer.lower() in hotkeys or answer.upper() in hotkeys:
                return answer
            elif default and answer=='':        # empty string entered
                return default

    def editText(self, text, jumpIndex = None, highlight = None):
        """
        Uses a Tkinter edit box because we don't have a console editor
        
        Parameters:
            * text      - a Unicode string
            * jumpIndex - an integer: position at which to put the caret
            * highlight - a substring; each occurence will be highlighted
        """
        try:
            import gui
        except ImportError, e:
            print 'Could not load GUI modules: %s' % e
            return text
        editor = gui.EditBoxWindow()
        return editor.edit(text, jumpIndex = jumpIndex, highlight = highlight)

    def askForCaptcha(self, url):
        try:
            import webbrowser
            wikipedia.output(u'Opening CAPTCHA in your web browser...')
            if webbrowser.open(url):
                return wikipedia.input(u'What is the solution of the CAPTCHA that is shown in your web browser?')
            else:
                raise
        except:
            wikipedia.output(u'Error in opening web browser: %s' % sys.exc_info()[0])
            wikipedia.output(u'Please copy this url to your web browser and open it:\n %s' % url)
            return wikipedia.input(u'What is the solution of the CAPTCHA at this url ?')
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.