Howard B. Golden wrote:
> On Wednesday December 30, 2009, you wrote:
>> Thank you. Very helpful!!! I have used the following code:
>>
>> go http://www.google.com/voice#trash
>> fv 1 Email email
>> fv 1 Passwd passwd
>> submit
>> run "b=get_browser();b.result.page=b.result.page.replace('<br/>','<br
>>  />');"
>>
>> It works as I can confirm with a save_html. However, when doing a 
> showforms I still get:
>>>> showforms
>> Traceback (most recent call last):
>>   File "/usr/bin/twill-sh", line 20, in <module>
>>     twill.shell.main()
>>   File "/var/lib/python-support/python2.5/twill/shell.py", line 387,
>>  in main shell.cmdloop(welcome_msg)
>>   File "/usr/lib/python2.5/cmd.py", line 142, in cmdloop
>>     stop = self.onecmd(line)
>>   File "/usr/lib/python2.5/cmd.py", line 219, in onecmd
>>     return func(arg)
>>   File "/var/lib/python-support/python2.5/twill/shell.py", line 42,
>>  in do_cmd print '\nERROR: %s\n' % (str(e),)
>>   File "/usr/lib/python2.5/HTMLParser.py", line 59, in __str__
>>     result = self.msg
>> AttributeError: 'ParseError' object has no attribute 'msg'
>>
>> Any idea how I can figure out what's causing this? I'd like to avoid
>>  sending the HTML to a public list, but will gladly send over
>>  personal (individual) email.
> 
> If you look at the traceback, it is _very_ strange. The error occurred 
> in HTMLParser.py line 59, which is part of the HTMLParseError class. 
> However, it was called from shell.py line 42, which is an exception 
> handler for a twill.parse.execute_command (or at least is _should_ be). 
> But based on the traceback, somehow, the _str_() method of 
> HTMLParseError is being executed instead.
> 
> I'm not sure what is going on, but I suspect it may have to do with 
> Titus's manipulation of the global and local dictionaries in shell.py 
> line 25. If my suspicion is correct, the "parse" in line 42 is referring 
> to an HTMLParser object instead of a twill.parse object.
> 
> As far as how to proceed, you could step through shell.py right there 
> (in the do_cmd method) and see what type is being used. Another approach 
> that might be easier is to put "twill." in front of "parse." on lines 
> 30, 31 and 37 of shell.py. This will make sure that the right "parse" is 
> being used. If it corrects the problem, then it supports my hypothesis.
> 
> Howard

Ok no luck with your theory. I added an import twill at the top (I am a Python 
newbie - completely) and added
twill. in front of lines 30, 31, and 37 of shell.py (see attached). Still 
getting same error

mi...@misha-d630:~/personal/web/googlevoice$ cat gvtrashempty | twill-sh

 -= Welcome to twill! =-

current page:  *empty page* 
>> current page:  *empty page* 
>> ==> at 
>> https://www.google.com/accounts/ServiceLogin?passive=true&service=grandcentral&ltmpl=bluebar&continue=https%3A%2F%2Fwww.google.com%2Fvoice%2Faccount%2Fsignin%2F%3Fprev%3D%252F&gsessionid=WMJMv0xJwU--eHRZeHbddQ
current page: 
https://www.google.com/accounts/ServiceLogin?passive=true&service=grandcentral&ltmpl=bluebar&continue=https%3A%2F%2Fwww.google.com%2Fvoice%2Faccount%2Fsignin%2F%3Fprev%3D%252F&gsessionid=WMJMv0xJwU--eHRZeHbddQ
>> current page: 
>> https://www.google.com/accounts/ServiceLogin?passive=true&service=grandcentral&ltmpl=bluebar&continue=https%3A%2F%2Fwww.google.com%2Fvoice%2Faccount%2Fsignin%2F%3Fprev%3D%252F&gsessionid=WMJMv0xJwU--eHRZeHbddQ
>> current page: 
>> https://www.google.com/accounts/ServiceLogin?passive=true&service=grandcentral&ltmpl=bluebar&continue=https%3A%2F%2Fwww.google.com%2Fvoice%2Faccount%2Fsignin%2F%3Fprev%3D%252F&gsessionid=WMJMv0xJwU--eHRZeHbddQ
>> Note: submit is using submit button: name="signIn", value="Sign in"
current page: https://www.google.com/voice/?gsessionid=3r_m3iQXq_x0Ka_aL0Exqg
>> current page: https://www.google.com/voice/?gsessionid=3r_m3iQXq_x0Ka_aL0Exqg
>> Traceback (most recent call last):
  File "/usr/bin/twill-sh", line 20, in <module>
    twill.shell.main()
  File "/var/lib/python-support/python2.5/twill/shell.py", line 388, in main
    shell.cmdloop(welcome_msg)
  File "/usr/lib/python2.5/cmd.py", line 142, in cmdloop
    stop = self.onecmd(line)
  File "/usr/lib/python2.5/cmd.py", line 219, in onecmd
    return func(arg)
  File "/var/lib/python-support/python2.5/twill/shell.py", line 43, in do_cmd
    print '\nERROR: %s\n' % (str(e),)
  File "/usr/lib/python2.5/HTMLParser.py", line 59, in __str__
    result = self.msg
AttributeError: 'ParseError' object has no attribute 'msg'

Any ideas?

I don't know how to trace through I'm afraid. Any suggestions. I'm on Hardy 
Heron 8.04

Thank you
Misha Koshelev

"""
A command-line interpreter for twill.

This is an implementation of a command-line interpreter based on the
'Cmd' class in the 'cmd' package of the default Python distribution.
"""

import twill
import cmd
from twill import commands, parse, __version__
import namespaces

try:
    import readline
except:
    readline = None

def make_cmd_fn(cmd):
    """
    Dynamically define a twill shell command function based on an imported
    function name.  (This is where the twill.commands functions actually
    get executed.)
    """
    
    def do_cmd(rest_of_line, cmd=cmd):
        global_dict, local_dict = namespaces.get_twill_glocals()

        args = []
        if rest_of_line.strip() != "":
            try:
                args = twill.parse.arguments.parseString(rest_of_line)[0]
                args = twill.parse.process_args(args, global_dict,local_dict)
            except Exception, e:
                print '\nINPUT ERROR: %s\n' % (str(e),)
                return

        try:
            twill.parse.execute_command(cmd, args, global_dict, local_dict,
                                  "<shell>")
        except SystemExit:
            raise
        except Exception, e:
            print '\nERROR: %s\n' % (str(e),)

    return do_cmd

def make_help_cmd(cmd, docstring):
    """
    Dynamically define a twill shell help function for the given
    command/docstring.
    """
    def help_cmd(message=docstring, cmd=cmd):
        print '=' * 15
        print '\nHelp for command %s:\n' % (cmd,)
        print message.strip()
        print ''
        print '=' * 15
        print ''
        
    return help_cmd

###

class Singleton(object):
    def __new__(cls, *args, **kwds):
        it = cls.__dict__.get("__it__")
        if it is not None:
            return it
        cls.__it__ = it = object.__new__(cls)
        it.init(*args, **kwds)
        return it
    
    def init(self, *args, **kwds):
        pass

#
# TwillCommandLoop
#

def add_command(cmd, docstring):
    x = get_command_shell()
    if x:
        x.add_command(cmd, docstring)
        
def get_command_shell():
    return getattr(TwillCommandLoop, '__it__', None)

class TwillCommandLoop(Singleton, cmd.Cmd):
    """
    Command-line interpreter for twill commands.  Singleton object: you
    can't create more than one of these at a time.

    Note: most of the do_ and help_ functions are dynamically created
    by the metaclass.
    """
    def init(self, **kw):
        if kw.has_key('stdin'):
            cmd.Cmd.__init__(self, None, stdin=kw['stdin'])
            self.use_rawinput = False
        else:
            cmd.Cmd.__init__(self)

        # initialize a new local namespace.
        namespaces.new_local_dict()

        # The history file name is located in the home directory of
        # the user
        import os
        self._history_file = os.environ.has_key("HOME") and \
            os.path.join(os.environ["HOME"], ".twill_history") or \
            None

        # import readline history, if available.
        if self._history_file and readline:
            try:
                readline.read_history_file(self._history_file)
            except IOError:
                pass

        # fail on unknown commands? for test-shell, primarily.
        self.fail_on_unknown = kw.get('fail_on_unknown', False)

        # handle initial URL argument
        if kw.get('initial_url'):
            commands.go(kw['initial_url'])
            
        self._set_prompt()

        self.names = []
        
        global_dict, local_dict = namespaces.get_twill_glocals()

        ### add all of the commands from twill.
        for command in parse.command_list:
            fn = global_dict.get(command)
            self.add_command(command, fn.__doc__)

    def add_command(self, command, docstring):
        """
        Add the given command into the lexicon of all commands.
        """
        do_name = 'do_%s' % (command,)
        do_cmd = make_cmd_fn(command)
        setattr(self, do_name, do_cmd)

        if docstring:
            help_cmd = make_help_cmd(command, docstring)
            help_name = 'help_%s' % (command,)
            setattr(self, help_name, help_cmd)

        self.names.append(do_name)

    def get_names(self):
        """
        Return the list of commands.
        """
        return self.names

    def complete_formvalue(self, text, line, begin, end):
        # formvalue <formname> <field> <value>
        cmd, args = parse.parse_command(line + '.', {}, {})
        place = len(args)
        if place == 1:
            return self.provide_formname(text)
        elif place == 2:
            formname = args[0]
            return self.provide_field(formname, text)
        return []
    complete_fv = complete_formvalue

    def provide_formname(self, prefix):
        names = []
        forms = commands.browser._browser.forms()
        for f in forms:
            id = f.attrs.get('id')
            if id and id.startswith(prefix):
                names.append(id)
                continue
            name = f.name
            if name and name.startswith(prefix):
                names.append(name)
        return names

    def provide_field(self, formname, prefix):
        names = []
        form = commands.browser.get_form(formname)
        if not form:
            return []
        for c in form.controls:
            id = c.id
            if id and id.startswith(prefix):
                names.append(id)
                continue
            name = c.name
            if name and name.startswith(prefix):
                names.append(name)
        return names

    def _set_prompt(self):
        "Set the prompt to the current page."
        url = commands.browser.get_url()
        if url is None:
            url = " *empty page* "
        self.prompt = "current page: %s\n>> " % (url,)

    def precmd(self, line):
        "Run before each command; save."
        return line

    def postcmd(self, stop, line):
        "Run after each command; set prompt."
        self._set_prompt()
        
        return stop

    def default(self, line):
        "Called when unknown command is executed."

        # empty lines ==> emptyline(); here we just want to remove
        # leading whitespace.
        line = line.strip()

        # look for command
        global_dict, local_dict = namespaces.get_twill_glocals()
        cmd, args = parse.parse_command(line, global_dict, local_dict)

        # ignore comments & empty stuff
        if cmd is None:
            return

        try:
            parse.execute_command(cmd, args, global_dict, local_dict,
                                  "<shell>")
        except SystemExit:
            raise
        except Exception, e:
            print '\nERROR: %s\n' % (str(e),)
            if self.fail_on_unknown:
                raise

    def emptyline(self):
        "Ignore empty lines."
        pass

    def do_EOF(self, *args):
        "Exit on CTRL-D"
        if self._history_file and readline:
            readline.write_history_file(self._history_file)
            
        raise SystemExit()

    def help_help(self):
        print "\nWhat do YOU think the command 'help' does?!?\n"

    def do_version(self, *args):
        print "\ntwill version %s.\n" % (__version__,)
        print "See http://www.idyll.org/~t/www-tools/twill/ for more info."
        print ""

    def help_version(self):
        print "\nPrint version information.\n"

    def do_exit(self, *args):
        raise SystemExit()

    def help_exit(self):
        print "\nExit twill.\n"

    do_quit = do_exit
    help_quit = help_exit

####

twillargs = []                          # contains sys.argv *after* last '--'
interactive = False                     # 'True' if interacting with user
def main():
    global twillargs, interactive
    
    import sys
    from twill import TwillCommandLoop, execute_file, __version__
    from twill.utils import gather_filenames
    from optparse import OptionParser
    from cStringIO import StringIO

    ###
    # make sure that the current working directory is in the path.  does this
    # work on Windows??

    if not '.' in sys.path:
        sys.path.append('.')
    ###

    #### OPTIONS

    parser = OptionParser()

    parser.add_option('-q', '--quiet', action="store_true", dest="quiet",
                      help = 'do not show normal output')

    parser.add_option('-i', '--interactive', action="store_true", dest="interact",
              help = 'drop into an interactive shell after running files (if any)')

    parser.add_option('-f', '--fail', action="store_true", dest="fail",
                      help = 'fail exit on first file to fail')

    parser.add_option('-n', '--never-fail', action="store_true",
                      dest="never_fail",
                      help = 'continue executing scripts past errors')

    parser.add_option('-v', '--version', action="store_true", dest="show_version",
                      help = 'show version information and exit')

    parser.add_option('-u', '--url', nargs=1, action="store", dest="url",
                      help="start at the given URL before each script")

    ####

    # parse arguments.
    sysargs = sys.argv[1:]
    if '--' in sysargs:
        found = False
        for last in range(len(sysargs) - 1, -1, -1):
            if sysargs[last] == '--':
                found = True
                break

        if found:
            twillargs = sysargs[last + 1:]
            sysargs = sysargs[:last]

    (options, args) = parser.parse_args(sysargs)

    if options.show_version:
        print 'twill version %s.' % (__version__,)
        sys.exit(0)

    if options.quiet:
        assert not options.interact, "interactive mode is incompatible with -q"
        assert args, "interactive mode is incompatible with -q"

        old_stdout = sys.stdout
        sys.stdout = StringIO()

    # If run from the command line, find & run any scripts put on the command
    # line.  If none, drop into an interactive AutoShell.

    failed = False
    if len(args):
        success = []
        failure = []

        filenames = gather_filenames(args)

        for filename in filenames:
            print '>> EXECUTING FILE', filename

            try:
                interactive = False
                execute_file(filename,
                             initial_url=options.url,
                             never_fail=options.never_fail)
                success.append(filename)
            except Exception, e:
                if options.fail:
                    raise
                else:
                    print '** UNHANDLED EXCEPTION:', str(e)
                    failure.append(filename)

        print '--'
        print '%d of %d files SUCCEEDED.' % (len(success),
                                             len(success) + len(failure),)
        if len(failure):
            print 'Failed:\n\t',
            print "\n\t".join(failure)
            failed = True

    if not args or options.interact:
        welcome_msg = ""
        if not args:
            welcome_msg = "\n -= Welcome to twill! =-\n"

        interactive = True
        shell = TwillCommandLoop(initial_url=options.url)

        while 1:
            try:
                shell.cmdloop(welcome_msg)
            except KeyboardInterrupt:
                sys.stdout.write('\n')
            except SystemExit:
                raise

            welcome_msg = ""

    if failed:
        sys.exit(1)
    sys.exit(0)

_______________________________________________
twill mailing list
[email protected]
http://lists.idyll.org/listinfo/twill

Reply via email to