import requests
import bs4
from six.moves import urllib
from six import string_types
from .form import Form


class Browser:

    def __init__(self, session=None):
        self.session = session or requests.Session()

    @staticmethod
    def add_soup(response):
        if 'text/html' in response.headers.get('Content-Type', ''):
            try:
                response.soup = bs4.BeautifulSoup(response.content)
            except:
                pass

    def request(self, *args, **kwargs):
        response = self.session.request(*args, **kwargs)
        Browser.add_soup(response)
        return response

    def get(self, *args, **kwargs):
        response = self.session.get(*args, **kwargs)
        Browser.add_soup(response)
        return response

    def post(self, *args, **kwargs):
        response = self.session.post(*args, **kwargs)
        Browser.add_soup(response)
        return response

    def _build_request(self, form, url=None, **kwargs):
        method = form['method']
        action = form['action']
        url = urllib.parse.urljoin(url, action)

        # read http://www.w3.org/TR/html5/forms.html
        data = kwargs.get('data') or dict()
        files = kwargs.get('files') or dict()

        for input in form.select("input"):
            name = input.get('name')
            # web browsers use empty string for inputs with missing values
            value = input.get('value', '')
            if not name:
                continue

            if input.get('type') in ('radio', 'checkbox') and 'checked' not in input.attrs:
                continue

            if input.get('type') == 'checkbox':
                if not name in data:
                    data[name] = list()
                data[name].append(value)

            elif input.get('type') == 'file':
                # read http://www.cs.tut.fi/~jkorpela/forms/file.html
                # in web browsers, file upload only happens if the form's (or
                # submit button's) enctype attribute is set to
                # 'multipart/form-data'. we don't care, simplify.
                if not value:
                    continue
                if isinstance(value, string_types):
                    value = open(value, 'rb')
                files[name] = value

            else:
                data[name] = value

        for textarea in form.select("textarea"):
            name = textarea.get('name')
            if not name:
                continue
            data[name] = textarea.text

        for select in form.select("select"):
            name = select.get('name')
            if not name:
                continue
            for i, option in enumerate(select.select("option")):
                if i == 0 or "selected" in option.attrs:
                    data[name] = option.get('value', '')

        return requests.Request(method, url, data=data, files=files, **kwargs)

    def _prepare_request(self, form, url=None, **kwargs):
        request = self._build_request(form, url, **kwargs)
        return self.session.prepare_request(request)

    def submit(self, form, url=None, **kwargs):
        if isinstance(form, Form):
            form = form.form
        request = self._prepare_request(form, url, **kwargs)
        response = self.session.send(request)
        Browser.add_soup(response)
        return response

@@ -268,17 +268,17 @@
      if 
-'
+%22
 text/htm
@@ -278,17 +278,17 @@
 ext/html
-'
+%22
  in resp
@@ -304,17 +304,17 @@
 ers.get(
-'
+%22
 Content-
@@ -317,21 +317,21 @@
 ent-Type
-', ''
+%22, %22%22
 ):%0A     
@@ -991,16 +991,16 @@
 orm%5B
-'
+%22
 method
-'
+%22
 %5D%0A  
@@ -1023,16 +1023,16 @@
 orm%5B
-'
+%22
 action
-'
+%22
 %5D%0A  
@@ -1161,14 +1161,14 @@
 get(
-'
+%22
 data
-'
+%22
 ) or
@@ -1206,15 +1206,15 @@
 get(
-'
+%22
 files
-'
+%22
 ) or
@@ -1290,30 +1290,30 @@
 = input.get(
-'
+%22
 name
-'
+%22
 )%0A          
@@ -1407,27 +1407,27 @@
 put.get(
-'
+%22
 value
-', ''
+%22, %22%22
 )%0A      
@@ -1500,38 +1500,38 @@
 get(
-'
+%22
 type
-'
+%22
 ) in (
-'
+%22
 radio
-', '
+%22, %22
 checkbox
 ') a
@@ -1530,24 +1530,24 @@
 kbox
-'
+%22
 ) and 
-'
+%22
 checked
-'
+%22
  not
@@ -1618,28 +1618,28 @@
 get(
-'
+%22
 type
-'
+%22
 ) == 
-'
+%22
 checkbox
 ':%0A 
@@ -1634,17 +1634,17 @@
 checkbox
-'
+%22
 :%0A      
@@ -1787,25 +1787,25 @@
 get(
-'
+%22
 type
-'
+%22
 ) == 
-'
+%22
 file
-'
+%22
 :%0A  
@@ -1943,17 +1943,17 @@
 the form
-'
+%22
 s (or%0A  
@@ -1981,17 +1981,17 @@
 t button
-'
+%22
 s) encty
@@ -2031,17 +2031,17 @@
       # 
-'
+%22
 multipar
@@ -2055,17 +2055,17 @@
 data
-'
+%22
 . we don
 't c
@@ -2060,17 +2060,17 @@
 . we don
-'
+%22
 t care, 
@@ -2234,12 +2234,12 @@
 ue, 
-'rb'
+%22rb%22
 )%0A  
@@ -2404,30 +2404,30 @@
 extarea.get(
-'
+%22
 name
-'
+%22
 )%0A          
@@ -2585,14 +2585,14 @@
 get(
-'
+%22
 name
-'
+%22
 )%0A  
@@ -2809,19 +2809,19 @@
 get(
-'
+%22
 value
-', ''
+%22, %22%22
 )%0A%0A 

Replace ' with " to make style more consistent