We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`scrapy.FormRequest.from_response` observed to eliminate duplicate keys in `formdata`
This looks good:
```
In [2]: scrapy.FormRequest('http://example.com', method='GET', formdata=(('foo', 'bar'), ('foo', 'baz')))
Out[2]: <GET http://example.com?foo=bar&foo=baz>
```

While here is the issue:
```
In [3]: response = scrapy.http.TextResponse(url='http://example.com', body='<form></form>', encoding='utf8')

In [4]: scrapy.FormRequest.from_response(response, method='GET', formdata=(('foo', 'bar'), ('foo', 'baz')))
Out[4]: <GET http://example.com?foo=baz>
```

(Tested with `Scrapy 1.5.0` and `Python 3.6.5`)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scrapy/http/request/form.py`
Content:
```
1 """
2 This module implements the FormRequest class which is a more convenient class
3 (than Request) to generate Requests based on form data.
4 
5 See documentation in docs/topics/request-response.rst
6 """
7 
8 import six
9 from six.moves.urllib.parse import urljoin, urlencode
10 
11 import lxml.html
12 from parsel.selector import create_root_node
13 from w3lib.html import strip_html5_whitespace
14 
15 from scrapy.http.request import Request
16 from scrapy.utils.python import to_bytes, is_listlike
17 from scrapy.utils.response import get_base_url
18 
19 
20 class FormRequest(Request):
21 
22     def __init__(self, *args, **kwargs):
23         formdata = kwargs.pop('formdata', None)
24         if formdata and kwargs.get('method') is None:
25             kwargs['method'] = 'POST'
26 
27         super(FormRequest, self).__init__(*args, **kwargs)
28 
29         if formdata:
30             items = formdata.items() if isinstance(formdata, dict) else formdata
31             querystr = _urlencode(items, self.encoding)
32             if self.method == 'POST':
33                 self.headers.setdefault(b'Content-Type', b'application/x-www-form-urlencoded')
34                 self._set_body(querystr)
35             else:
36                 self._set_url(self.url + ('&' if '?' in self.url else '?') + querystr)
37 
38     @classmethod
39     def from_response(cls, response, formname=None, formid=None, formnumber=0, formdata=None,
40                       clickdata=None, dont_click=False, formxpath=None, formcss=None, **kwargs):
41 
42         kwargs.setdefault('encoding', response.encoding)
43 
44         if formcss is not None:
45             from parsel.csstranslator import HTMLTranslator
46             formxpath = HTMLTranslator().css_to_xpath(formcss)
47 
48         form = _get_form(response, formname, formid, formnumber, formxpath)
49         formdata = _get_inputs(form, formdata, dont_click, clickdata, response)
50         url = _get_form_url(form, kwargs.pop('url', None))
51         method = kwargs.pop('method', form.method)
52         return cls(url=url, method=method, formdata=formdata, **kwargs)
53 
54 
55 def _get_form_url(form, url):
56     if url is None:
57         action = form.get('action')
58         if action is None:
59             return form.base_url
60         return urljoin(form.base_url, strip_html5_whitespace(action))
61     return urljoin(form.base_url, url)
62 
63 
64 def _urlencode(seq, enc):
65     values = [(to_bytes(k, enc), to_bytes(v, enc))
66               for k, vs in seq
67               for v in (vs if is_listlike(vs) else [vs])]
68     return urlencode(values, doseq=1)
69 
70 
71 def _get_form(response, formname, formid, formnumber, formxpath):
72     """Find the form element """
73     root = create_root_node(response.text, lxml.html.HTMLParser,
74                             base_url=get_base_url(response))
75     forms = root.xpath('//form')
76     if not forms:
77         raise ValueError("No <form> element found in %s" % response)
78 
79     if formname is not None:
80         f = root.xpath('//form[@name="%s"]' % formname)
81         if f:
82             return f[0]
83 
84     if formid is not None:
85         f = root.xpath('//form[@id="%s"]' % formid)
86         if f:
87             return f[0]
88 
89     # Get form element from xpath, if not found, go up
90     if formxpath is not None:
91         nodes = root.xpath(formxpath)
92         if nodes:
93             el = nodes[0]
94             while True:
95                 if el.tag == 'form':
96                     return el
97                 el = el.getparent()
98                 if el is None:
99                     break
100         encoded = formxpath if six.PY3 else formxpath.encode('unicode_escape')
101         raise ValueError('No <form> element found with %s' % encoded)
102 
103     # If we get here, it means that either formname was None
104     # or invalid
105     if formnumber is not None:
106         try:
107             form = forms[formnumber]
108         except IndexError:
109             raise IndexError("Form number %d not found in %s" %
110                              (formnumber, response))
111         else:
112             return form
113 
114 
115 def _get_inputs(form, formdata, dont_click, clickdata, response):
116     try:
117         formdata = dict(formdata or ())
118     except (ValueError, TypeError):
119         raise ValueError('formdata should be a dict or iterable of tuples')
120 
121     inputs = form.xpath('descendant::textarea'
122                         '|descendant::select'
123                         '|descendant::input[not(@type) or @type['
124                         ' not(re:test(., "^(?:submit|image|reset)$", "i"))'
125                         ' and (../@checked or'
126                         '  not(re:test(., "^(?:checkbox|radio)$", "i")))]]',
127                         namespaces={
128                             "re": "http://exslt.org/regular-expressions"})
129     values = [(k, u'' if v is None else v)
130               for k, v in (_value(e) for e in inputs)
131               if k and k not in formdata]
132 
133     if not dont_click:
134         clickable = _get_clickable(clickdata, form)
135         if clickable and clickable[0] not in formdata and not clickable[0] is None:
136             values.append(clickable)
137 
138     values.extend((k, v) for k, v in formdata.items() if v is not None)
139     return values
140 
141 
142 def _value(ele):
143     n = ele.name
144     v = ele.value
145     if ele.tag == 'select':
146         return _select_value(ele, n, v)
147     return n, v
148 
149 
150 def _select_value(ele, n, v):
151     multiple = ele.multiple
152     if v is None and not multiple:
153         # Match browser behaviour on simple select tag without options selected
154         # And for select tags wihout options
155         o = ele.value_options
156         return (n, o[0]) if o else (None, None)
157     elif v is not None and multiple:
158         # This is a workround to bug in lxml fixed 2.3.1
159         # fix https://github.com/lxml/lxml/commit/57f49eed82068a20da3db8f1b18ae00c1bab8b12#L1L1139
160         selected_options = ele.xpath('.//option[@selected]')
161         v = [(o.get('value') or o.text or u'').strip() for o in selected_options]
162     return n, v
163 
164 
165 def _get_clickable(clickdata, form):
166     """
167     Returns the clickable element specified in clickdata,
168     if the latter is given. If not, it returns the first
169     clickable element found
170     """
171     clickables = [
172         el for el in form.xpath(
173             'descendant::input[re:test(@type, "^(submit|image)$", "i")]'
174             '|descendant::button[not(@type) or re:test(@type, "^submit$", "i")]',
175             namespaces={"re": "http://exslt.org/regular-expressions"})
176         ]
177     if not clickables:
178         return
179 
180     # If we don't have clickdata, we just use the first clickable element
181     if clickdata is None:
182         el = clickables[0]
183         return (el.get('name'), el.get('value') or '')
184 
185     # If clickdata is given, we compare it to the clickable elements to find a
186     # match. We first look to see if the number is specified in clickdata,
187     # because that uniquely identifies the element
188     nr = clickdata.get('nr', None)
189     if nr is not None:
190         try:
191             el = list(form.inputs)[nr]
192         except IndexError:
193             pass
194         else:
195             return (el.get('name'), el.get('value') or '')
196 
197     # We didn't find it, so now we build an XPath expression out of the other
198     # arguments, because they can be used as such
199     xpath = u'.//*' + \
200             u''.join(u'[@%s="%s"]' % c for c in six.iteritems(clickdata))
201     el = form.xpath(xpath)
202     if len(el) == 1:
203         return (el[0].get('name'), el[0].get('value') or '')
204     elif len(el) > 1:
205         raise ValueError("Multiple elements found (%r) matching the criteria "
206                          "in clickdata: %r" % (el, clickdata))
207     else:
208         raise ValueError('No clickable element matching clickdata: %r' % (clickdata,))
209
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scrapy/http/request/form.py b/scrapy/http/request/form.py
--- a/scrapy/http/request/form.py
+++ b/scrapy/http/request/form.py
@@ -114,10 +114,12 @@
 
 def _get_inputs(form, formdata, dont_click, clickdata, response):
     try:
-        formdata = dict(formdata or ())
+        formdata_keys = dict(formdata or ()).keys()
     except (ValueError, TypeError):
         raise ValueError('formdata should be a dict or iterable of tuples')
 
+    if not formdata:
+        formdata = ()
     inputs = form.xpath('descendant::textarea'
                         '|descendant::select'
                         '|descendant::input[not(@type) or @type['
@@ -128,14 +130,17 @@
                             "re": "http://exslt.org/regular-expressions"})
     values = [(k, u'' if v is None else v)
               for k, v in (_value(e) for e in inputs)
-              if k and k not in formdata]
+              if k and k not in formdata_keys]
 
     if not dont_click:
         clickable = _get_clickable(clickdata, form)
         if clickable and clickable[0] not in formdata and not clickable[0] is None:
             values.append(clickable)
 
-    values.extend((k, v) for k, v in formdata.items() if v is not None)
+    if isinstance(formdata, dict):
+        formdata = formdata.items()
+
+    values.extend((k, v) for k, v in formdata if v is not None)
     return values

{"golden_diff": "diff --git a/scrapy/http/request/form.py b/scrapy/http/request/form.py\n--- a/scrapy/http/request/form.py\n+++ b/scrapy/http/request/form.py\n@@ -114,10 +114,12 @@\n \n def _get_inputs(form, formdata, dont_click, clickdata, response):\n     try:\n-        formdata = dict(formdata or ())\n+        formdata_keys = dict(formdata or ()).keys()\n     except (ValueError, TypeError):\n         raise ValueError('formdata should be a dict or iterable of tuples')\n \n+    if not formdata:\n+        formdata = ()\n     inputs = form.xpath('descendant::textarea'\n                         '|descendant::select'\n                         '|descendant::input[not(@type) or @type['\n@@ -128,14 +130,17 @@\n                             \"re\": \"http://exslt.org/regular-expressions\"})\n     values = [(k, u'' if v is None else v)\n               for k, v in (_value(e) for e in inputs)\n-              if k and k not in formdata]\n+              if k and k not in formdata_keys]\n \n     if not dont_click:\n         clickable = _get_clickable(clickdata, form)\n         if clickable and clickable[0] not in formdata and not clickable[0] is None:\n             values.append(clickable)\n \n-    values.extend((k, v) for k, v in formdata.items() if v is not None)\n+    if isinstance(formdata, dict):\n+        formdata = formdata.items()\n+\n+    values.extend((k, v) for k, v in formdata if v is not None)\n     return values\n", "issue": "`scrapy.FormRequest.from_response` observed to eliminate duplicate keys in `formdata`\nThis looks good:\r\n```\r\nIn [2]: scrapy.FormRequest('http://example.com', method='GET', formdata=(('foo', 'bar'), ('foo', 'baz')))\r\nOut[2]: <GET http://example.com?foo=bar&foo=baz>\r\n```\r\n\r\nWhile here is the issue:\r\n```\r\nIn [3]: response = scrapy.http.TextResponse(url='http://example.com', body='<form></form>', encoding='utf8')\r\n\r\nIn [4]: scrapy.FormRequest.from_response(response, method='GET', formdata=(('foo', 'bar'), ('foo', 'baz')))\r\nOut[4]: <GET http://example.com?foo=baz>\r\n```\r\n\r\n(Tested with `Scrapy 1.5.0` and `Python 3.6.5`)\n", "before_files": [{"content": "\"\"\"\nThis module implements the FormRequest class which is a more convenient class\n(than Request) to generate Requests based on form data.\n\nSee documentation in docs/topics/request-response.rst\n\"\"\"\n\nimport six\nfrom six.moves.urllib.parse import urljoin, urlencode\n\nimport lxml.html\nfrom parsel.selector import create_root_node\nfrom w3lib.html import strip_html5_whitespace\n\nfrom scrapy.http.request import Request\nfrom scrapy.utils.python import to_bytes, is_listlike\nfrom scrapy.utils.response import get_base_url\n\n\nclass FormRequest(Request):\n\n    def __init__(self, *args, **kwargs):\n        formdata = kwargs.pop('formdata', None)\n        if formdata and kwargs.get('method') is None:\n            kwargs['method'] = 'POST'\n\n        super(FormRequest, self).__init__(*args, **kwargs)\n\n        if formdata:\n            items = formdata.items() if isinstance(formdata, dict) else formdata\n            querystr = _urlencode(items, self.encoding)\n            if self.method == 'POST':\n                self.headers.setdefault(b'Content-Type', b'application/x-www-form-urlencoded')\n                self._set_body(querystr)\n            else:\n                self._set_url(self.url + ('&' if '?' in self.url else '?') + querystr)\n\n    @classmethod\n    def from_response(cls, response, formname=None, formid=None, formnumber=0, formdata=None,\n                      clickdata=None, dont_click=False, formxpath=None, formcss=None, **kwargs):\n\n        kwargs.setdefault('encoding', response.encoding)\n\n        if formcss is not None:\n            from parsel.csstranslator import HTMLTranslator\n            formxpath = HTMLTranslator().css_to_xpath(formcss)\n\n        form = _get_form(response, formname, formid, formnumber, formxpath)\n        formdata = _get_inputs(form, formdata, dont_click, clickdata, response)\n        url = _get_form_url(form, kwargs.pop('url', None))\n        method = kwargs.pop('method', form.method)\n        return cls(url=url, method=method, formdata=formdata, **kwargs)\n\n\ndef _get_form_url(form, url):\n    if url is None:\n        action = form.get('action')\n        if action is None:\n            return form.base_url\n        return urljoin(form.base_url, strip_html5_whitespace(action))\n    return urljoin(form.base_url, url)\n\n\ndef _urlencode(seq, enc):\n    values = [(to_bytes(k, enc), to_bytes(v, enc))\n              for k, vs in seq\n              for v in (vs if is_listlike(vs) else [vs])]\n    return urlencode(values, doseq=1)\n\n\ndef _get_form(response, formname, formid, formnumber, formxpath):\n    \"\"\"Find the form element \"\"\"\n    root = create_root_node(response.text, lxml.html.HTMLParser,\n                            base_url=get_base_url(response))\n    forms = root.xpath('//form')\n    if not forms:\n        raise ValueError(\"No <form> element found in %s\" % response)\n\n    if formname is not None:\n        f = root.xpath('//form[@name=\"%s\"]' % formname)\n        if f:\n            return f[0]\n\n    if formid is not None:\n        f = root.xpath('//form[@id=\"%s\"]' % formid)\n        if f:\n            return f[0]\n\n    # Get form element from xpath, if not found, go up\n    if formxpath is not None:\n        nodes = root.xpath(formxpath)\n        if nodes:\n            el = nodes[0]\n            while True:\n                if el.tag == 'form':\n                    return el\n                el = el.getparent()\n                if el is None:\n                    break\n        encoded = formxpath if six.PY3 else formxpath.encode('unicode_escape')\n        raise ValueError('No <form> element found with %s' % encoded)\n\n    # If we get here, it means that either formname was None\n    # or invalid\n    if formnumber is not None:\n        try:\n            form = forms[formnumber]\n        except IndexError:\n            raise IndexError(\"Form number %d not found in %s\" %\n                             (formnumber, response))\n        else:\n            return form\n\n\ndef _get_inputs(form, formdata, dont_click, clickdata, response):\n    try:\n        formdata = dict(formdata or ())\n    except (ValueError, TypeError):\n        raise ValueError('formdata should be a dict or iterable of tuples')\n\n    inputs = form.xpath('descendant::textarea'\n                        '|descendant::select'\n                        '|descendant::input[not(@type) or @type['\n                        ' not(re:test(., \"^(?:submit|image|reset)$\", \"i\"))'\n                        ' and (../@checked or'\n                        '  not(re:test(., \"^(?:checkbox|radio)$\", \"i\")))]]',\n                        namespaces={\n                            \"re\": \"http://exslt.org/regular-expressions\"})\n    values = [(k, u'' if v is None else v)\n              for k, v in (_value(e) for e in inputs)\n              if k and k not in formdata]\n\n    if not dont_click:\n        clickable = _get_clickable(clickdata, form)\n        if clickable and clickable[0] not in formdata and not clickable[0] is None:\n            values.append(clickable)\n\n    values.extend((k, v) for k, v in formdata.items() if v is not None)\n    return values\n\n\ndef _value(ele):\n    n = ele.name\n    v = ele.value\n    if ele.tag == 'select':\n        return _select_value(ele, n, v)\n    return n, v\n\n\ndef _select_value(ele, n, v):\n    multiple = ele.multiple\n    if v is None and not multiple:\n        # Match browser behaviour on simple select tag without options selected\n        # And for select tags wihout options\n        o = ele.value_options\n        return (n, o[0]) if o else (None, None)\n    elif v is not None and multiple:\n        # This is a workround to bug in lxml fixed 2.3.1\n        # fix https://github.com/lxml/lxml/commit/57f49eed82068a20da3db8f1b18ae00c1bab8b12#L1L1139\n        selected_options = ele.xpath('.//option[@selected]')\n        v = [(o.get('value') or o.text or u'').strip() for o in selected_options]\n    return n, v\n\n\ndef _get_clickable(clickdata, form):\n    \"\"\"\n    Returns the clickable element specified in clickdata,\n    if the latter is given. If not, it returns the first\n    clickable element found\n    \"\"\"\n    clickables = [\n        el for el in form.xpath(\n            'descendant::input[re:test(@type, \"^(submit|image)$\", \"i\")]'\n            '|descendant::button[not(@type) or re:test(@type, \"^submit$\", \"i\")]',\n            namespaces={\"re\": \"http://exslt.org/regular-expressions\"})\n        ]\n    if not clickables:\n        return\n\n    # If we don't have clickdata, we just use the first clickable element\n    if clickdata is None:\n        el = clickables[0]\n        return (el.get('name'), el.get('value') or '')\n\n    # If clickdata is given, we compare it to the clickable elements to find a\n    # match. We first look to see if the number is specified in clickdata,\n    # because that uniquely identifies the element\n    nr = clickdata.get('nr', None)\n    if nr is not None:\n        try:\n            el = list(form.inputs)[nr]\n        except IndexError:\n            pass\n        else:\n            return (el.get('name'), el.get('value') or '')\n\n    # We didn't find it, so now we build an XPath expression out of the other\n    # arguments, because they can be used as such\n    xpath = u'.//*' + \\\n            u''.join(u'[@%s=\"%s\"]' % c for c in six.iteritems(clickdata))\n    el = form.xpath(xpath)\n    if len(el) == 1:\n        return (el[0].get('name'), el[0].get('value') or '')\n    elif len(el) > 1:\n        raise ValueError(\"Multiple elements found (%r) matching the criteria \"\n                         \"in clickdata: %r\" % (el, clickdata))\n    else:\n        raise ValueError('No clickable element matching clickdata: %r' % (clickdata,))\n", "path": "scrapy/http/request/form.py"}], "after_files": [{"content": "\"\"\"\nThis module implements the FormRequest class which is a more convenient class\n(than Request) to generate Requests based on form data.\n\nSee documentation in docs/topics/request-response.rst\n\"\"\"\n\nimport six\nfrom six.moves.urllib.parse import urljoin, urlencode\n\nimport lxml.html\nfrom parsel.selector import create_root_node\nfrom w3lib.html import strip_html5_whitespace\n\nfrom scrapy.http.request import Request\nfrom scrapy.utils.python import to_bytes, is_listlike\nfrom scrapy.utils.response import get_base_url\n\n\nclass FormRequest(Request):\n\n    def __init__(self, *args, **kwargs):\n        formdata = kwargs.pop('formdata', None)\n        if formdata and kwargs.get('method') is None:\n            kwargs['method'] = 'POST'\n\n        super(FormRequest, self).__init__(*args, **kwargs)\n\n        if formdata:\n            items = formdata.items() if isinstance(formdata, dict) else formdata\n            querystr = _urlencode(items, self.encoding)\n            if self.method == 'POST':\n                self.headers.setdefault(b'Content-Type', b'application/x-www-form-urlencoded')\n                self._set_body(querystr)\n            else:\n                self._set_url(self.url + ('&' if '?' in self.url else '?') + querystr)\n\n    @classmethod\n    def from_response(cls, response, formname=None, formid=None, formnumber=0, formdata=None,\n                      clickdata=None, dont_click=False, formxpath=None, formcss=None, **kwargs):\n\n        kwargs.setdefault('encoding', response.encoding)\n\n        if formcss is not None:\n            from parsel.csstranslator import HTMLTranslator\n            formxpath = HTMLTranslator().css_to_xpath(formcss)\n\n        form = _get_form(response, formname, formid, formnumber, formxpath)\n        formdata = _get_inputs(form, formdata, dont_click, clickdata, response)\n        url = _get_form_url(form, kwargs.pop('url', None))\n        method = kwargs.pop('method', form.method)\n        return cls(url=url, method=method, formdata=formdata, **kwargs)\n\n\ndef _get_form_url(form, url):\n    if url is None:\n        action = form.get('action')\n        if action is None:\n            return form.base_url\n        return urljoin(form.base_url, strip_html5_whitespace(action))\n    return urljoin(form.base_url, url)\n\n\ndef _urlencode(seq, enc):\n    values = [(to_bytes(k, enc), to_bytes(v, enc))\n              for k, vs in seq\n              for v in (vs if is_listlike(vs) else [vs])]\n    return urlencode(values, doseq=1)\n\n\ndef _get_form(response, formname, formid, formnumber, formxpath):\n    \"\"\"Find the form element \"\"\"\n    root = create_root_node(response.text, lxml.html.HTMLParser,\n                            base_url=get_base_url(response))\n    forms = root.xpath('//form')\n    if not forms:\n        raise ValueError(\"No <form> element found in %s\" % response)\n\n    if formname is not None:\n        f = root.xpath('//form[@name=\"%s\"]' % formname)\n        if f:\n            return f[0]\n\n    if formid is not None:\n        f = root.xpath('//form[@id=\"%s\"]' % formid)\n        if f:\n            return f[0]\n\n    # Get form element from xpath, if not found, go up\n    if formxpath is not None:\n        nodes = root.xpath(formxpath)\n        if nodes:\n            el = nodes[0]\n            while True:\n                if el.tag == 'form':\n                    return el\n                el = el.getparent()\n                if el is None:\n                    break\n        encoded = formxpath if six.PY3 else formxpath.encode('unicode_escape')\n        raise ValueError('No <form> element found with %s' % encoded)\n\n    # If we get here, it means that either formname was None\n    # or invalid\n    if formnumber is not None:\n        try:\n            form = forms[formnumber]\n        except IndexError:\n            raise IndexError(\"Form number %d not found in %s\" %\n                             (formnumber, response))\n        else:\n            return form\n\n\ndef _get_inputs(form, formdata, dont_click, clickdata, response):\n    try:\n        formdata_keys = dict(formdata or ()).keys()\n    except (ValueError, TypeError):\n        raise ValueError('formdata should be a dict or iterable of tuples')\n\n    if not formdata:\n        formdata = ()\n    inputs = form.xpath('descendant::textarea'\n                        '|descendant::select'\n                        '|descendant::input[not(@type) or @type['\n                        ' not(re:test(., \"^(?:submit|image|reset)$\", \"i\"))'\n                        ' and (../@checked or'\n                        '  not(re:test(., \"^(?:checkbox|radio)$\", \"i\")))]]',\n                        namespaces={\n                            \"re\": \"http://exslt.org/regular-expressions\"})\n    values = [(k, u'' if v is None else v)\n              for k, v in (_value(e) for e in inputs)\n              if k and k not in formdata_keys]\n\n    if not dont_click:\n        clickable = _get_clickable(clickdata, form)\n        if clickable and clickable[0] not in formdata and not clickable[0] is None:\n            values.append(clickable)\n\n    if isinstance(formdata, dict):\n        formdata = formdata.items()\n\n    values.extend((k, v) for k, v in formdata if v is not None)\n    return values\n\n\ndef _value(ele):\n    n = ele.name\n    v = ele.value\n    if ele.tag == 'select':\n        return _select_value(ele, n, v)\n    return n, v\n\n\ndef _select_value(ele, n, v):\n    multiple = ele.multiple\n    if v is None and not multiple:\n        # Match browser behaviour on simple select tag without options selected\n        # And for select tags wihout options\n        o = ele.value_options\n        return (n, o[0]) if o else (None, None)\n    elif v is not None and multiple:\n        # This is a workround to bug in lxml fixed 2.3.1\n        # fix https://github.com/lxml/lxml/commit/57f49eed82068a20da3db8f1b18ae00c1bab8b12#L1L1139\n        selected_options = ele.xpath('.//option[@selected]')\n        v = [(o.get('value') or o.text or u'').strip() for o in selected_options]\n    return n, v\n\n\ndef _get_clickable(clickdata, form):\n    \"\"\"\n    Returns the clickable element specified in clickdata,\n    if the latter is given. If not, it returns the first\n    clickable element found\n    \"\"\"\n    clickables = [\n        el for el in form.xpath(\n            'descendant::input[re:test(@type, \"^(submit|image)$\", \"i\")]'\n            '|descendant::button[not(@type) or re:test(@type, \"^submit$\", \"i\")]',\n            namespaces={\"re\": \"http://exslt.org/regular-expressions\"})\n        ]\n    if not clickables:\n        return\n\n    # If we don't have clickdata, we just use the first clickable element\n    if clickdata is None:\n        el = clickables[0]\n        return (el.get('name'), el.get('value') or '')\n\n    # If clickdata is given, we compare it to the clickable elements to find a\n    # match. We first look to see if the number is specified in clickdata,\n    # because that uniquely identifies the element\n    nr = clickdata.get('nr', None)\n    if nr is not None:\n        try:\n            el = list(form.inputs)[nr]\n        except IndexError:\n            pass\n        else:\n            return (el.get('name'), el.get('value') or '')\n\n    # We didn't find it, so now we build an XPath expression out of the other\n    # arguments, because they can be used as such\n    xpath = u'.//*' + \\\n            u''.join(u'[@%s=\"%s\"]' % c for c in six.iteritems(clickdata))\n    el = form.xpath(xpath)\n    if len(el) == 1:\n        return (el[0].get('name'), el[0].get('value') or '')\n    elif len(el) > 1:\n        raise ValueError(\"Multiple elements found (%r) matching the criteria \"\n                         \"in clickdata: %r\" % (el, clickdata))\n    else:\n        raise ValueError('No clickable element matching clickdata: %r' % (clickdata,))\n", "path": "scrapy/http/request/form.py"}]}