[wwwsearch-commits] r17963 - wwwsearch/ClientForm/trunk
jjlee at codespeak.net
jjlee at codespeak.net
Thu Sep 29 01:58:47 CEST 2005
Author: jjlee
Date: Thu Sep 29 01:58:46 2005
New Revision: 17963
Modified:
wwwsearch/ClientForm/trunk/ClientForm.py
wwwsearch/ClientForm/trunk/README.html.in
wwwsearch/ClientForm/trunk/test.py
Log:
Finish off backwards_compat stuff; Make most tests run with backwards_compat=False
Modified: wwwsearch/ClientForm/trunk/ClientForm.py
==============================================================================
--- wwwsearch/ClientForm/trunk/ClientForm.py (original)
+++ wwwsearch/ClientForm/trunk/ClientForm.py Thu Sep 29 01:58:46 2005
@@ -28,11 +28,8 @@
# XXXX
# Move Item.__str__ back into ListControl? Don't like str(item) ATM...
-# Turn backwards_compat into general backwards-compat option?
-# -ignore ambiguity
-# -item label matching is strict
-# -turning off individual items allowed even if disabled
-# Check old test suite passes!
+# Label matching in backwards_compat mode: compression of text??
+# Check old test suite passes in backwards_compat mode.
# Deprecate by_label in set/get_value()
# Add .set/get_value_by_label() to HTMLForm
# Remove by_label arg from .get() and add label arg
@@ -941,6 +938,7 @@
def __str__(self):
return '<Label(id=%r, text=%r)>' % (self.id, self.text)
+
def _getLabel(attrs):
label = attrs.get("__label")
if label is not None:
@@ -1565,10 +1563,12 @@
if not isstringlike(label):
raise TypeError("item label must be string-like")
items = [] # order is important
+ compat = self._form.backwards_compat
for o in self.items:
if not exclude_disabled or not o.disabled:
for l in o.get_labels():
- if l.text.find(label) >= 0:
+ if ((compat and l.text == label) or
+ (not compat and l.text.find(label) > -1)):
items.append(o)
break
return items
@@ -2858,7 +2858,6 @@
(id is None) and (label is None) and (nr is None)):
raise ValueError(
"at least one argument must be supplied to specify control")
- if nr is None: nr = 0
return self._find_control(name, type, kind, id, label,
is_listcontrol, nr)
Modified: wwwsearch/ClientForm/trunk/README.html.in
==============================================================================
--- wwwsearch/ClientForm/trunk/README.html.in (original)
+++ wwwsearch/ClientForm/trunk/README.html.in Thu Sep 29 01:58:46 2005
@@ -36,24 +36,24 @@
<p>Simple example:
@{colorize(r"""
- from urllib2 import urlopen
- from ClientForm import ParseResponse
+from urllib2 import urlopen
+from ClientForm import ParseResponse
- forms = ParseResponse(urlopen("http://www.example.com/form.html"))
- form = forms[0]
- print form
- form["author"] = "Gisle Aas"
-
- # form.click() returns a urllib2.Request object
- # (see HTMLForm.click.__doc__ if you don't have urllib2)
- response = urlopen(form.click("Thanks"))
+forms = ParseResponse(urlopen("http://www.example.com/form.html"))
+form = forms[0]
+print form
+form["author"] = "Gisle Aas"
+
+# form.click() returns a urllib2.Request object
+# (see HTMLForm.click.__doc__ if you don't have urllib2)
+response = urlopen(form.click("Thanks"))
""")}
<p>A more complicated example (<em><strong>Note</strong>: this example makes
use of the ClientForm 0.2 API; refer to the README.html file in the latest 0.1
release for the corresponding code for that version.</em>):
-@{colorize(" "+" ".join(open("examples/example.py").readlines()[2:]))}
+@{colorize("".join(open("examples/example.py").readlines()[2:]))}
<p>All of the standard control types are supported: <code>TEXT</code>,
<code>PASSWORD</code>, <code>HIDDEN</code>, <code>TEXTAREA</code>,
@@ -76,16 +76,63 @@
pickling.</strong>
<p>Python 2.0 or above is required. To run the tests, you need the
-<code>unittest</code> module (from <a href="http://pyunit.sourceforge.net/">PyUnit</a>).
-<code>unittest</code> is a standard library module with Python 2.1 and
-above.
+<code>unittest</code> module (from <a
+href="http://pyunit.sourceforge.net/">PyUnit</a>). <code>unittest</code> is a
+standard library module with Python 2.1 and above.
<p>For full documentation, see the docstrings in ClientForm.py.
-<p><em><strong>Note: this page describes the 0.1.x interface. See <a
-href="./src/README_0_0_15.html">here</a> for the old 0.0.x interface.</strong>
-</em>
+<p><em><strong>Note: this page describes the 0.2 (development release)
+interface. See <a href="./src/README_0_1_18.html">here</a> for the stable
+0.1 interface.</strong> </em>
+
+
+<a name="compat"></a>
+<h2>Backwards-compatibility mode</h2>
+
+<p>ClientForm 0.2 includes three minor backwards-incompatible interface
+changes.
+
+<p>To make upgrading from 0.1 easier, and to allow me to stop supporting
+version 0.1 sooner, version 0.1 contains support for operating in a
+backwards-compatible mode, under which code written for 0.1 should work without
+modification. This is done on a per-<code>HTMLForm</code> basis via the
+<code>.backwards_compat</code> attribute, but for convenience the
+ParseResponse() and ParseFile() factory functions accept
+<code>backwards_compat</code> arguments. The default is to operate in
+backwards-compatible mode. To run with backwards compatible mode turned
+<em><strong>OFF</strong></em>:
+@{colorize(r"""
+from urllib2 import urlopen
+from ClientForm import ParseResponse
+forms = ParseResponse(urlopen("http://example.com/"), backwards_compat=False)
+# ...
+""")}
+
+<p>The backwards-incompatible changes are:
+
+<ul>
+<li><p>Ambiguous specification of controls or items now results in
+AmbiguityError. If you want the old behaviour, explicitly pass
+<code>nr=0</code> to indicate you want the first matching control or item.
+
+<li><p>Item label matching is now done by substring, not by strict
+string-equality. (Control label matching is always done by substring.)
+
+<li><p>Handling of disabled list items has changed. First, note that handling
+of disabled list items in 0.1 (and in 0.2's backwards-compatibility mode!) is
+buggy: disabled items are successful (ie. disabled item names are sent back to
+the server). As a result, there was no distinction to be made between
+successful items and selected items. In 0.2, the bug is fixed, so this is no
+longer the case, and it is important to note that list controls'
+<code>.value</code> attribute contains only the <em>successful</em> item names;
+items that are <em>selected </em> but not successful (because disabled) are not
+included in <code>.value</code>. Second, disabled list items may no longer be
+deselected: AttributeError is raised in 0.2, whereas deselection was allowed in
+0.1. The bug in 0.1 and in 0.2's backwards-compatibility mode will not be
+fixed, to preserve compatibility and to encourage people to upgrade to the new
+0.2 <code>backwards_compat=True</code> behaviour. </ul>
<a name="credits"></a>
<h2>Credits</h2>
@@ -104,21 +151,16 @@
<p>For installation instructions, see the INSTALL file included in the
distribution.
-<p><em>Development release.</em>. There has been one minor
-backwards-incompatible interface change since 0.1.x. I recommend upgrading if
-and only if you pay attention to this incompatible change:
-
-<p>Disabled list items may no longer be deselected: AttributeError is raised
-in 0.2.x, whereas deselection was allowed in 0.1.x. In 0.2.x, either simply
-set <code>item.disabled = False</code> first (or call
-<code>control.set_all_items_disabled(False)</code>), or check if the item is
-disabled before attempting to select or deselect it. Note also that handling
-of disabled list items in 0.1.x was buggy: disabled items were successful
-(ie. disabled item names got sent back to the server).
-
-<p>0.2.x includes better support for labels, and a redesigned,
-simpler, interface (all the old methods are still there. but some have
-been deprecated).
+<p><span class="spanhdr">Development release</span> There have been three
+fairly minor backwards-incompatible interface changes since version 0.1 (see <a
+href="./#compat">above</a>), but by default the code operates in a
+backwards-compatible mode so that code written for 0.1 should work without
+changes.
+
+<p>0.2 includes better support for labels, and a simpler interface (all the old
+methods are still there, but some have been deprecated and a few added).
+
+<p>This is an alpha release: expect bugs, and possibly interface changes.
<ul>
@{version = "0.2.0a"}
@@ -131,11 +173,12 @@
<br>
-<p><em>Stable release.</em>. There have been many interface changes since
-0.0.x, so I don't recommend upgrading old code from 0.0.x unless you want the
-new features.
+<p><span class="spanhdr">Stable release</span> There have been many interface changes since 0.0,
+so I don't recommend upgrading old code from 0.0 unless you want the new
+features. Note that the stable release will soon become unmaintained: I
+reccommend upgrading to 0.2 when that's stable.
-<p>0.1.x includes <code>FILE</code> control support for file upload, handling
+<p>0.1 includes <code>FILE</code> control support for file upload, handling
of disabled list items, and a redesigned interface.
<ul>
@{version = "0.1.17"}
@@ -148,7 +191,7 @@
<br>
-<p><em>Old release.</em> No longer maintained. You don't want this.
+<p><span class="spanhdr">Old release</span> No longer maintained. You don't want this.
<ul>
@{version = "0.0.16"}
@{win_version = release.win_version(version)}
@@ -245,12 +288,12 @@
<li>I have a control containing a list of integers. How do I select the one
whose value is nearest to the one I want?
<p>@{colorize(r"""
- import bisect
- def closest_int_value(form, ctrl_name, value):
- values = map(int, [item.name for item in form.find_control(ctrl_name).items])
- return str(values[bisect.bisect(values, value) - 1])
+import bisect
+def closest_int_value(form, ctrl_name, value):
+ values = map(int, [item.name for item in form.find_control(ctrl_name).items])
+ return str(values[bisect.bisect(values, value) - 1])
- form["distance"] = [closest_int_value(form, "distance", 23)]
+form["distance"] = [closest_int_value(form, "distance", 23)]
""")}
</li>
<li>Where can I find out more about the HTML and HTTP standards?
Modified: wwwsearch/ClientForm/trunk/test.py
==============================================================================
--- wwwsearch/ClientForm/trunk/test.py (original)
+++ wwwsearch/ClientForm/trunk/test.py Thu Sep 29 01:58:46 2005
@@ -63,7 +63,7 @@
self._forms = []
self._labels = []
self._id_to_labels = {}
- self.backwards_compat = True
+ self.backwards_compat = False
self.controls = []
def find_control(self, name, type):
@@ -88,7 +88,8 @@
class LWPFormTests(TestCase):
"""The original tests from libwww-perl 5.64."""
def testEmptyParse(self):
- forms = ClientForm.ParseFile(StringIO(""), "http://localhost")
+ forms = ClientForm.ParseFile(StringIO(""), "http://localhost",
+ backwards_compat=False)
self.assert_(len(forms) == 0)
def _forms(self):
@@ -99,7 +100,8 @@
</form>
""")
- return ClientForm.ParseFile(file, "http://localhost/")
+ return ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
def testParse(self):
forms = self._forms()
@@ -129,7 +131,7 @@
</form>
""")
base_uri = "http://localhost/"
- forms = ClientForm.ParseFile(f, base_uri)
+ forms = ClientForm.ParseFile(f, base_uri, backwards_compat=False)
form = forms[0]
for ctl in form.controls:
self.assert_(isinstance(ctl, ClientForm.TextControl))
@@ -142,7 +144,7 @@
""")
base_uri = "http://localhost/"
try:
- ClientForm.ParseFile(f, base_uri)
+ ClientForm.ParseFile(f, base_uri, backwards_compat=False)
except ClientForm.ParseError, e:
self.assert_(e.base_uri == base_uri)
else:
@@ -156,7 +158,8 @@
<input type="submit"></input>
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
self.assert_(form.action == "http://example.com/abc")
@@ -165,7 +168,8 @@
<input type="submit"></input>
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
self.assert_(form.action == "http://localhost/abc")
@@ -186,12 +190,13 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
self.assert_(form.name is None)
self.assertEqual(form.action, "http://localhost/abc&d")
- control = form.find_control(type="textarea")
+ control = form.find_control(type="textarea", nr=0)
self.assert_(control.name is None)
self.assert_(control.value == "blah, blah,\nRhubarb.\n\n")
@@ -219,7 +224,8 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
@@ -249,7 +255,8 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
self.assert_(form.name == "myform")
control = form.find_control(name="b")
@@ -269,7 +276,8 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
control = form.find_control(type="isindex")
self.assert_(control.type == "isindex")
@@ -291,7 +299,8 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
control0 = form.find_control(type="select", nr=0)
control1 = form.find_control(type="select", nr=1)
@@ -395,7 +404,8 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
self.assert_(form.controls[0].name is None)
@@ -421,7 +431,8 @@
<input type="submit" name="submit">
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
hide_deprecations()
self.assert_(form.possible_items("foo") == ["on"])
@@ -450,7 +461,8 @@
<input type="submit" name="submit">
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
hide_deprecations()
self.assert_(form.possible_items("spam") == ["1", "2"])
@@ -477,7 +489,8 @@
</form>
""")
- forms = ClientForm.ParseFile(file, "http://localhost/")
+ forms = ClientForm.ParseFile(file, "http://localhost/",
+ backwards_compat=False)
form = forms[0]
control = form.find_control("a")
self.assert_(control.value == [])
@@ -486,10 +499,10 @@
file.seek(0)
forms = ClientForm.ParseFile(file, "http://localhost/",
- select_default=1)
+ select_default=1, backwards_compat=False)
form = forms[0]
# select_default only affects *multiple* selection select controls
- control = form.find_control(type="select")
+ control = form.find_control(type="select", nr=0)
self.assert_(control.value == ["1"])
single_control = form.find_control(type="select", nr=1)
self.assert_(single_control.value == ["1"])
@@ -550,8 +563,10 @@
def get_control(name, file=file, compat=compat):
file.seek(0)
+ hide_deprecations()
forms = ClientForm.ParseFile(file, "http://localhost/",
backwards_compat=compat)
+ reset_deprecations()
form = forms[0]
return form.find_control(name)
@@ -762,8 +777,10 @@
</form>
""")
+ hide_deprecations()
forms = ClientForm.ParseFile(file, "http://localhost/",
backwards_compat=compat)
+ reset_deprecations()
form = forms[0]
for name, control_disabled, item_disabled in [
("foo", False, False),
@@ -822,8 +839,10 @@
<input type="checkbox" name="baz" value="3" disabled></input>
</form>""")
+ hide_deprecations()
forms = ClientForm.ParseFile(file, "http://localhost/",
backwards_compat=compat)
+ reset_deprecations()
form = forms[0]
for name, control_disabled, item_disabled in [
("foo", False, False),
@@ -1807,7 +1826,8 @@
<input type="password" id="pswd2" name="password" value="123" />
</form>
""")
- form = ClientForm.ParseFile(f, "http://example.com/")[0]
+ form = ClientForm.ParseFile(f, "http://example.com/",
+ backwards_compat=False)[0]
for compat in True, False:
form.backwards_compat = compat
fc = form.find_control
@@ -1819,6 +1839,7 @@
else:
self.assertRaises(AmbiguityError, fc, "password")
self.assertEqual(fc("password", id="pswd2").id, "pswd2")
+ self.assertEqual(fc("password", nr=0).id, "pswd1")
self.assertRaises(ControlNotFoundError, fc, "form.title", nr=1)
self.assertRaises(ControlNotFoundError, fc, nr=50)
self.assertRaises(ValueError, fc, nr=-1)
@@ -1841,7 +1862,10 @@
def test_deselect_disabled(self):
def get_new_form(f, compat):
f.seek(0)
- form = ClientForm.ParseFile(f, "http://example.com/")[0]
+ hide_deprecations()
+ form = ClientForm.ParseFile(f, "http://example.com/",
+ backwards_compat=False)[0]
+ reset_deprecations()
form.backwards_compat = compat
return form
@@ -1888,8 +1912,7 @@
# disallowed for disabled items.
ctl, a = new_form()
- self.assertRaises(AttributeError,
- setattr, a, "selected", True)
+ self.assertRaises(AttributeError, setattr, a, "selected", True)
ctl, a = new_form()
self.assertRaises(AttributeError, setattr, ctl, "value", ["a"])
ctl, a = new_form()
@@ -1953,7 +1976,8 @@
<input type="submit" name="bar"></input>
</form>
""")
- form = ClientForm.ParseFile(file, "http://blah/")[0]
+ form = ClientForm.ParseFile(file, "http://blah/",
+ backwards_compat=False)[0]
self.assertRaises(ControlNotFoundError, form.click, nr=2)
self.assert_(form.click().get_full_url() == "http://blah/abc?foo=")
self.assert_(form.click(name="bar").get_full_url() == "http://blah/abc?bar=")
@@ -1966,7 +1990,8 @@
</form>
""" % method)
# " (this line is here for emacs)
- form = ClientForm.ParseFile(file, "http://blah/")[0]
+ form = ClientForm.ParseFile(file, "http://blah/",
+ backwards_compat=False)[0]
if method == "GET":
url = "http://blah/abc?foo="
else:
@@ -1975,7 +2000,8 @@
def testAuth(self):
file = open("./testdata/Auth.html", "r")
- forms = ClientForm.ParseFile(file, self.base_uri)
+ forms = ClientForm.ParseFile(file, self.base_uri,
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
self.assert_(form.action ==
@@ -2013,7 +2039,8 @@
def testSearchType(self):
file = open("./testdata/SearchType.html", "r")
- forms = ClientForm.ParseFile(file, self.base_uri)
+ forms = ClientForm.ParseFile(file, self.base_uri,
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
@@ -2039,7 +2066,8 @@
def testGeneralSearch(self):
file = open("./testdata/GeneralSearch.html", "r")
- forms = ClientForm.ParseFile(file, self.base_uri)
+ forms = ClientForm.ParseFile(file, self.base_uri,
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
@@ -2066,16 +2094,16 @@
for i in range(len(keys)):
name = keys[i]
type = types[i]
- self.assertEqual(fc(name).value, form.get_value(name))
- self.assertEqual(fc(name).value, values[i])
- self.assertEqual(fc(name).type, type)
- self.assertEqual(fc(name, type).name, name)
- self.assert_(fc(type="hidden").name == "SID")
- self.assert_(fc(type="image").name == "Home")
+ self.assertEqual(fc(name, nr=0).value, form.get_value(name, nr=0))
+ self.assertEqual(fc(name, nr=0).value, values[i])
+ self.assertEqual(fc(name, nr=0).type, type)
+ self.assertEqual(fc(name, type, nr=0).name, name)
+ self.assert_(fc(type="hidden", nr=0).name == "SID")
+ self.assert_(fc(type="image", nr=0).name == "Home")
self.assert_(fc(nr=6).name == "Search")
self.assertRaises(ControlNotFoundError, fc, nr=50)
self.assertRaises(ValueError, fc, nr=-1)
- self.assert_(fc("Search", "image").name == "Search")
+ self.assert_(fc("Search", "image", nr=0).name == "Search")
self.assertRaises(ControlNotFoundError, fc, "Search", "hidden")
s0 = fc("Search", "image", nr=0)
s0b = fc("Search", "image", nr=0)
@@ -2195,7 +2223,9 @@
({"backwards_compat": True}, True),
({"backwards_compat": False}, False),
]:
+ hide_deprecations()
form = ClientForm.ParseFile(f, "http://localhost/", **kwds)[0]
+ reset_deprecations()
f.seek(0)
c = form.find_control("form.grocery")
#for item in c.items:
@@ -2309,7 +2339,8 @@
<input type="submit" value="Submit" />
</form>
""")
- form = ClientForm.ParseFile(f, "http://localhost/")[0]
+ form = ClientForm.ParseFile(f, "http://localhost/",
+ backwards_compat=False)[0]
# basic tests
self.assertEqual(form.find_control(label="Title").value,
@@ -2334,9 +2365,12 @@
# attribute is True, so ambiguity is ignored. For instance, notice
# that the form.grocery checkboxes include some loaves of bread and
# a loaf of challah. The code just guesses what you mean:
+ form.backwards_compat = True
c = form.find_control("form.grocery")
- self.assertEqual(c.get("Loaf", True), c.items[0])
- c.set_value_by_label(["Loaf"])
+ # label substring matching is turned off for compat mode
+ self.assertRaises(ItemNotFoundError, c.get, "Loaf", True)
+ self.assertEqual(c.get("Loaf of Bread", True), c.items[0])
+ c.set_value_by_label(["Loaf of Bread"])
self.assertEqual(c.get_value_by_label(), ["Loaf of Bread"])
self.assertEqual(c.items[0].id, "1")
# However, if the form's backwards_compat attribute is False, Ambiguity
@@ -2434,7 +2468,8 @@
def testResults(self):
file = open("./testdata/Results.html", "r")
- forms = ClientForm.ParseFile(file, self.base_uri)
+ forms = ClientForm.ParseFile(file, self.base_uri,
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
@@ -2468,7 +2503,7 @@
for i in range(len(keys)):
key = keys[i]
- control = form.find_control(key)
+ control = form.find_control(key, nr=0)
self.assert_(control.value == values[i])
self.assert_(control.type == types[i])
@@ -2480,7 +2515,8 @@
def testMarkedResults(self):
file = open("./testdata/MarkedResults.html", "r")
- forms = ClientForm.ParseFile(file, self.base_uri)
+ forms = ClientForm.ParseFile(file, self.base_uri,
+ backwards_compat=False)
self.assert_(len(forms) == 1)
form = forms[0]
@@ -2530,7 +2566,8 @@
<input type="checkbox" name="e" value="1"></input>
</form>
""")
- return ClientForm.ParseFile(f, "http://blah/")[0]
+ return ClientForm.ParseFile(f, "http://blah/",
+ backwards_compat=False)[0]
def test_value(self):
form = self.make_form()
@@ -2710,7 +2747,8 @@
"""
return ClientForm.ParseFile(StringIO(html),
- "http://localhost/cgi-bin/upload.cgi")[0]
+ "http://localhost/cgi-bin/upload.cgi",
+ backwards_compat=False)[0]
def test_file_request(self):
import cgi
@@ -2802,7 +2840,7 @@
forms = ClientForm.ParseFile(StringIO("""<html>
<form method="POST" action="./weird.html" enctype="multipart/form-data">
<input type="submit" name="submit"></input>
-</form></html>"""), ".")
+</form></html>"""), ".", backwards_compat=False)
form = forms[0]
data = form.click().get_data()
lines = string.split(data, "\r\n")
More information about the wwwsearch-commits
mailing list