prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Indent JSON data while exporting it as Python code
  I was testing out a web API and used the "Export flow as Python code" feature for the first time as user, and noticed an improvement.
  
  Currently we just export the `flow.request.body` as is (independent of it's content type) but mitmproxy's interface is smart and renders different bodies differently (for eg. it indents JSON)
  
  I think we could add this indent behaviour while exporting things as code too.
  
  
  </issue>
  <code>
  [start of mitmproxy/flow_export.py]
  1 import urllib
  2 import netlib.http
  3 from textwrap import dedent
  4 
  5 
  6 def curl_command(flow):
  7     data = "curl "
  8 
  9     for k, v in flow.request.headers.fields:
  10         data += "-H '%s:%s' " % (k, v)
  11 
  12     if flow.request.method != "GET":
  13         data += "-X %s " % flow.request.method
  14 
  15     full_url = flow.request.scheme + "://" + flow.request.host + flow.request.path
  16     data += "'%s'" % full_url
  17 
  18     if flow.request.content:
  19         data += " --data-binary '%s'" % flow.request.content
  20 
  21     return data
  22 
  23 
  24 def python_code(flow):
  25     code = dedent("""
  26         import requests
  27 
  28         url = '{url}'
  29         {headers}{params}{data}
  30         response = requests.request(
  31             method='{method}',
  32             url=url,{args}
  33         )
  34 
  35         print(response.text)
  36     """).strip()
  37 
  38     components = map(lambda x: urllib.quote(x, safe=""), flow.request.path_components)
  39     url = flow.request.scheme + "://" + flow.request.host + "/" + "/".join(components)
  40 
  41     args = ""
  42     headers = ""
  43     if flow.request.headers:
  44         lines = ["    '%s': '%s',\n" % (k, v) for k, v in flow.request.headers.fields]
  45         headers += "\nheaders = {\n%s}\n" % "".join(lines)
  46         args += "\n    headers=headers,"
  47 
  48     params = ""
  49     if flow.request.query:
  50         lines = ["    '%s': '%s',\n" % (k, v) for k, v in flow.request.query]
  51         params = "\nparams = {\n%s}\n" % "".join(lines)
  52         args += "\n    params=params,"
  53 
  54     data = ""
  55     if flow.request.body:
  56         data = "\ndata = '''%s'''\n" % flow.request.body
  57         args += "\n    data=data,"
  58 
  59     code = code.format(
  60         url=url,
  61         headers=headers,
  62         params=params,
  63         data=data,
  64         method=flow.request.method,
  65         args=args,
  66     )
  67 
  68     return code
  69 
  70 
  71 def raw_request(flow):
  72     data = netlib.http.http1.assemble_request(flow.request)
  73     return data
  74
  [end of mitmproxy/flow_export.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/mitmproxy/flow_export.py b/mitmproxy/flow_export.py
  --- a/mitmproxy/flow_export.py
  +++ b/mitmproxy/flow_export.py
  @@ -1,7 +1,10 @@
  +import json
   import urllib
  -import netlib.http
   from textwrap import dedent
   
  +import netlib.http
  +from netlib.utils import parse_content_type
  +
   
   def curl_command(flow):
       data = "curl "
  @@ -53,8 +56,16 @@
   
       data = ""
       if flow.request.body:
  -        data = "\ndata = '''%s'''\n" % flow.request.body
  -        args += "\n    data=data,"
  +        json_obj = is_json(flow.request.headers, flow.request.body)
  +        if json_obj:
  +            # Without the separators field json.dumps() produces
  +            # trailing white spaces: https://bugs.python.org/issue16333
  +            data = json.dumps(json_obj, indent=4, separators=(',', ': '))
  +            data = "\njson = %s\n" % data
  +            args += "\n    json=json,"
  +        else:
  +            data = "\ndata = '''%s'''\n" % flow.request.body
  +            args += "\n    data=data,"
   
       code = code.format(
           url=url,
  @@ -71,3 +82,14 @@
   def raw_request(flow):
       data = netlib.http.http1.assemble_request(flow.request)
       return data
  +
  +
  +def is_json(headers, content):
  +    if headers:
  +        ct = parse_content_type(headers.get("content-type", ""))
  +        if ct and "%s/%s" % (ct[0], ct[1]) == "application/json":
  +            try:
  +                return json.loads(content)
  +            except ValueError:
  +                return False
  +    return False
  
verification_info: {"golden_diff": "diff --git a/mitmproxy/flow_export.py b/mitmproxy/flow_export.py\n--- a/mitmproxy/flow_export.py\n+++ b/mitmproxy/flow_export.py\n@@ -1,7 +1,10 @@\n+import json\n import urllib\n-import netlib.http\n from textwrap import dedent\n \n+import netlib.http\n+from netlib.utils import parse_content_type\n+\n \n def curl_command(flow):\n     data = \"curl \"\n@@ -53,8 +56,16 @@\n \n     data = \"\"\n     if flow.request.body:\n-        data = \"\\ndata = '''%s'''\\n\" % flow.request.body\n-        args += \"\\n    data=data,\"\n+        json_obj = is_json(flow.request.headers, flow.request.body)\n+        if json_obj:\n+            # Without the separators field json.dumps() produces\n+            # trailing white spaces: https://bugs.python.org/issue16333\n+            data = json.dumps(json_obj, indent=4, separators=(',', ': '))\n+            data = \"\\njson = %s\\n\" % data\n+            args += \"\\n    json=json,\"\n+        else:\n+            data = \"\\ndata = '''%s'''\\n\" % flow.request.body\n+            args += \"\\n    data=data,\"\n \n     code = code.format(\n         url=url,\n@@ -71,3 +82,14 @@\n def raw_request(flow):\n     data = netlib.http.http1.assemble_request(flow.request)\n     return data\n+\n+\n+def is_json(headers, content):\n+    if headers:\n+        ct = parse_content_type(headers.get(\"content-type\", \"\"))\n+        if ct and \"%s/%s\" % (ct[0], ct[1]) == \"application/json\":\n+            try:\n+                return json.loads(content)\n+            except ValueError:\n+                return False\n+    return False\n", "issue": "Indent JSON data while exporting it as Python code\nI was testing out a web API and used the \"Export flow as Python code\" feature for the first time as user, and noticed an improvement.\n\nCurrently we just export the `flow.request.body` as is (independent of it's content type) but mitmproxy's interface is smart and renders different bodies differently (for eg. it indents JSON)\n\nI think we could add this indent behaviour while exporting things as code too.\n\n", "before_files": [{"content": "import urllib\nimport netlib.http\nfrom textwrap import dedent\n\n\ndef curl_command(flow):\n    data = \"curl \"\n\n    for k, v in flow.request.headers.fields:\n        data += \"-H '%s:%s' \" % (k, v)\n\n    if flow.request.method != \"GET\":\n        data += \"-X %s \" % flow.request.method\n\n    full_url = flow.request.scheme + \"://\" + flow.request.host + flow.request.path\n    data += \"'%s'\" % full_url\n\n    if flow.request.content:\n        data += \" --data-binary '%s'\" % flow.request.content\n\n    return data\n\n\ndef python_code(flow):\n    code = dedent(\"\"\"\n        import requests\n\n        url = '{url}'\n        {headers}{params}{data}\n        response = requests.request(\n            method='{method}',\n            url=url,{args}\n        )\n\n        print(response.text)\n    \"\"\").strip()\n\n    components = map(lambda x: urllib.quote(x, safe=\"\"), flow.request.path_components)\n    url = flow.request.scheme + \"://\" + flow.request.host + \"/\" + \"/\".join(components)\n\n    args = \"\"\n    headers = \"\"\n    if flow.request.headers:\n        lines = [\"    '%s': '%s',\\n\" % (k, v) for k, v in flow.request.headers.fields]\n        headers += \"\\nheaders = {\\n%s}\\n\" % \"\".join(lines)\n        args += \"\\n    headers=headers,\"\n\n    params = \"\"\n    if flow.request.query:\n        lines = [\"    '%s': '%s',\\n\" % (k, v) for k, v in flow.request.query]\n        params = \"\\nparams = {\\n%s}\\n\" % \"\".join(lines)\n        args += \"\\n    params=params,\"\n\n    data = \"\"\n    if flow.request.body:\n        data = \"\\ndata = '''%s'''\\n\" % flow.request.body\n        args += \"\\n    data=data,\"\n\n    code = code.format(\n        url=url,\n        headers=headers,\n        params=params,\n        data=data,\n        method=flow.request.method,\n        args=args,\n    )\n\n    return code\n\n\ndef raw_request(flow):\n    data = netlib.http.http1.assemble_request(flow.request)\n    return data\n", "path": "mitmproxy/flow_export.py"}]}