Abiel
Abiel

Reputation: 5465

mechanize cannot read form with SubmitControl that is disabled and has no value

I'm attempting to use mechanize (v0.2.5) to work with a form on a page that has a disabled image as one of the form elements. When I try to select the form, mechanize raises an AttributeError: control 'test' is disabled where test is the name of the disabled control. For example,

br = mechanize.Browser(factory=mechanize.RobustFactory())
br.open("http://whatever...")
br.select_form(nr=0)

Leads to this stack trace:

    br.select_form(nr=0)
  File "build\bdist.win32\egg\mechanize\_mechanize.py", line 499, in select_form
  File "build\bdist.win32\egg\mechanize\_html.py", line 544, in __getattr__
  File "build\bdist.win32\egg\mechanize\_html.py", line 557, in forms
  File "build\bdist.win32\egg\mechanize\_html.py", line 237, in forms
  File "build\bdist.win32\egg\mechanize\_form.py", line 844, in ParseResponseEx
  File "build\bdist.win32\egg\mechanize\_form.py", line 1017, in _ParseFileEx
  File "build\bdist.win32\egg\mechanize\_form.py", line 2735, in new_control
  File "build\bdist.win32\egg\mechanize\_form.py", line 2336, in __init__
  File "build\bdist.win32\egg\mechanize\_form.py", line 1221, in __setattr__
AttributeError: control 'test' is disabled

Examining the mechanize source code, it looks as if this error will always be raised when there is any form element that evaluates to a mechanize.SubmitControl and that has no pre-defined value attribute. For example, the following form would raise the same error:

<form action="http://whatever" method="POST">
    <input name="test" type="submit" disabled="disabled" />
</form>

I'm not sure if this should count as a bug, but in any case is there a workaround? For instance, is there a way I can alter the HTML of the target page to enable the disabled controls before I call br.select_form()?

EDIT

I've submitted a patch to mechanize that fixes this problem.

Upvotes: 9

Views: 2786

Answers (2)

intgr
intgr

Reputation: 20476

Sadly it's been more than a year and the mechanize upstream has still not merged the pull request.

Meanwhile you can use this monkey-patch I wrote to work around the bug without needing to manually install a patched version. Hopefully this bug will be resolved when (if) 0.2.6 is released, so the patch only applies to versions 0.2.5 and earlier.

def monkeypatch_mechanize():
    """Work-around for a mechanize 0.2.5 bug. See: https://github.com/jjlee/mechanize/pull/58"""
    import mechanize
    if mechanize.__version__ < (0, 2, 6):
        from mechanize._form import SubmitControl, ScalarControl

        def __init__(self, type, name, attrs, index=None):
            ScalarControl.__init__(self, type, name, attrs, index)
            # IE5 defaults SUBMIT value to "Submit Query"; Firebird 0.6 leaves it
            # blank, Konqueror 3.1 defaults to "Submit".  HTML spec. doesn't seem
            # to define this.
            if self.value is None:
                if self.disabled:
                    self.disabled = False
                    self.value = ""
                    self.disabled = True
                else:
                    self.value = ""
            self.readonly = True

        SubmitControl.__init__ = __init__

Upvotes: 8

pfalcon
pfalcon

Reputation: 6987

This is definitely a bug, reporting it upstream, making a patch, submitting it upstream and using patched version in the meantime is fairly right way to deal with it. (Thanks for choosing that way.)

As you mentioned, another approach is working it around by pre-processing source HTML (that may be useful if you're in hurry, or can't/don't want to use patched version for some reason, but note that workarounds doesn't help the community). For post-processing, any suitable method can be used - ranging from str.replace() to DOM-level processing with BeautifulSoup or lxml.

Upvotes: 0

Related Questions