prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [psycopg2] The quote_ident function requires psycopg2.extensions.connection.
  This is very related to https://github.com/DataDog/dd-trace-py/issues/383.
  
  To reproduce:
  ```
  from ddtrace import patch_all
  patch_all()
  
  import psycopg2
  from psycopg2.extensions import quote_ident
  
  conn = psycopg2.connect(dbname="test")
  quote_ident('foo', conn) # Fails with TypeError: argument 2 must be a connection or a cursor
  ```
  
  
  [psycopg2] The prepare functions require psycopg2.extensions.connection.
  Here is an example:
  
  ```
  from ddtrace import patch_all
  
  patch_all()
  
  import psycopg2
  from psycopg2.extensions import adapt
  
  conn = psycopg2.connect(dbname="test")
  
  items = adapt([1, 2, 3])
  items.prepare(conn) # Fails here
  
  binary = adapt(b'12345')
  binary.prepare(conn) # and here.
  ```
  
  ```
  $ python example.py
  Traceback (most recent call last):
    File "example.py", line 11, in <module>
      items.prepare(conn)
  TypeError: argument 1 must be psycopg2.extensions.connection, not TracedConnection
  ```
  
  This could probably be solved in a similar manner to #96 .
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `ddtrace/contrib/psycopg/patch.py`
  Content:
  ```
  1 # 3p
  2 import psycopg2
  3 import wrapt
  4 
  5 # project
  6 from ddtrace import Pin
  7 from ddtrace.contrib import dbapi
  8 from ddtrace.ext import sql, net, db
  9 
  10 # Original connect method
  11 _connect = psycopg2.connect
  12 
  13 
  14 def patch():
  15     """ Patch monkey patches psycopg's connection function
  16         so that the connection's functions are traced.
  17     """
  18     if getattr(psycopg2, '_datadog_patch', False):
  19         return
  20     setattr(psycopg2, '_datadog_patch', True)
  21 
  22     wrapt.wrap_function_wrapper(psycopg2, 'connect', patched_connect)
  23     _patch_extensions(_psycopg2_extensions)  # do this early just in case
  24 
  25 
  26 def unpatch():
  27     if getattr(psycopg2, '_datadog_patch', False):
  28         setattr(psycopg2, '_datadog_patch', False)
  29         psycopg2.connect = _connect
  30 
  31 
  32 def patch_conn(conn, traced_conn_cls=dbapi.TracedConnection):
  33     """ Wrap will patch the instance so that it's queries are traced."""
  34     # ensure we've patched extensions (this is idempotent) in
  35     # case we're only tracing some connections.
  36     _patch_extensions(_psycopg2_extensions)
  37 
  38     c = traced_conn_cls(conn)
  39 
  40     # fetch tags from the dsn
  41     dsn = sql.parse_pg_dsn(conn.dsn)
  42     tags = {
  43         net.TARGET_HOST: dsn.get("host"),
  44         net.TARGET_PORT: dsn.get("port"),
  45         db.NAME: dsn.get("dbname"),
  46         db.USER: dsn.get("user"),
  47         "db.application" : dsn.get("application_name"),
  48     }
  49 
  50     Pin(
  51         service="postgres",
  52         app="postgres",
  53         app_type="db",
  54         tags=tags).onto(c)
  55 
  56     return c
  57 
  58 
  59 def _patch_extensions(_extensions):
  60     # we must patch extensions all the time (it's pretty harmless) so split
  61     # from global patching of connections. must be idempotent.
  62     for _, module, func, wrapper in _extensions:
  63         if not hasattr(module, func) or isinstance(getattr(module, func), wrapt.ObjectProxy):
  64             continue
  65         wrapt.wrap_function_wrapper(module, func, wrapper)
  66 
  67 
  68 def _unpatch_extensions(_extensions):
  69     # we must patch extensions all the time (it's pretty harmless) so split
  70     # from global patching of connections. must be idempotent.
  71     for original, module, func, _ in _extensions:
  72         setattr(module, func, original)
  73 
  74 
  75 #
  76 # monkeypatch targets
  77 #
  78 
  79 def patched_connect(connect_func, _, args, kwargs):
  80     conn = connect_func(*args, **kwargs)
  81     return patch_conn(conn)
  82 
  83 
  84 def _extensions_register_type(func, _, args, kwargs):
  85     def _unroll_args(obj, scope=None):
  86         return obj, scope
  87     obj, scope = _unroll_args(*args, **kwargs)
  88 
  89     # register_type performs a c-level check of the object
  90     # type so we must be sure to pass in the actual db connection
  91     if scope and isinstance(scope, wrapt.ObjectProxy):
  92         scope = scope.__wrapped__
  93 
  94     return func(obj, scope) if scope else func(obj)
  95 
  96 
  97 def _extensions_adapt(func, _, args, kwargs):
  98     adapt = func(*args, **kwargs)
  99     if hasattr(adapt, 'prepare'):
  100         return AdapterWrapper(adapt)
  101     return adapt
  102 
  103 
  104 class AdapterWrapper(wrapt.ObjectProxy):
  105     def prepare(self, *args, **kwargs):
  106         func = self.__wrapped__.prepare
  107         if not args:
  108             return func(*args, **kwargs)
  109         conn = args[0]
  110 
  111         # prepare performs a c-level check of the object type so
  112         # we must be sure to pass in the actual db connection
  113         if isinstance(conn, wrapt.ObjectProxy):
  114             conn = conn.__wrapped__
  115 
  116         return func(conn, *args[1:], **kwargs)
  117 
  118 
  119 # extension hooks
  120 _psycopg2_extensions = [
  121     (psycopg2.extensions.register_type,
  122      psycopg2.extensions, 'register_type',
  123      _extensions_register_type),
  124     (psycopg2._psycopg.register_type,
  125      psycopg2._psycopg, 'register_type',
  126      _extensions_register_type),
  127     (psycopg2.extensions.adapt,
  128      psycopg2.extensions, 'adapt',
  129      _extensions_adapt),
  130 ]
  131 
  132 # `_json` attribute is only available for psycopg >= 2.5
  133 if getattr(psycopg2, '_json', None):
  134     _psycopg2_extensions += [
  135         (psycopg2._json.register_type,
  136          psycopg2._json, 'register_type',
  137          _extensions_register_type),
  138     ]
  139
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/ddtrace/contrib/psycopg/patch.py b/ddtrace/contrib/psycopg/patch.py
  --- a/ddtrace/contrib/psycopg/patch.py
  +++ b/ddtrace/contrib/psycopg/patch.py
  @@ -93,6 +93,17 @@
   
       return func(obj, scope) if scope else func(obj)
   
  +def _extensions_quote_ident(func, _, args, kwargs):
  +    def _unroll_args(obj, scope=None):
  +        return obj, scope
  +    obj, scope = _unroll_args(*args, **kwargs)
  +
  +    # register_type performs a c-level check of the object
  +    # type so we must be sure to pass in the actual db connection
  +    if scope and isinstance(scope, wrapt.ObjectProxy):
  +        scope = scope.__wrapped__
  +
  +    return func(obj, scope) if scope else func(obj)
   
   def _extensions_adapt(func, _, args, kwargs):
       adapt = func(*args, **kwargs)
  @@ -136,3 +147,11 @@
            psycopg2._json, 'register_type',
            _extensions_register_type),
       ]
  +
  +# `quote_ident` attribute is only available for psycopg >= 2.7
  +if getattr(psycopg2, 'extensions', None) and getattr(psycopg2.extensions,
  +                                                     'quote_ident', None):
  +    _psycopg2_extensions += [(psycopg2.extensions.quote_ident,
  +     psycopg2.extensions, 'quote_ident',
  +     _extensions_quote_ident),
  +    ]
  
verification_info: {"golden_diff": "diff --git a/ddtrace/contrib/psycopg/patch.py b/ddtrace/contrib/psycopg/patch.py\n--- a/ddtrace/contrib/psycopg/patch.py\n+++ b/ddtrace/contrib/psycopg/patch.py\n@@ -93,6 +93,17 @@\n \n     return func(obj, scope) if scope else func(obj)\n \n+def _extensions_quote_ident(func, _, args, kwargs):\n+    def _unroll_args(obj, scope=None):\n+        return obj, scope\n+    obj, scope = _unroll_args(*args, **kwargs)\n+\n+    # register_type performs a c-level check of the object\n+    # type so we must be sure to pass in the actual db connection\n+    if scope and isinstance(scope, wrapt.ObjectProxy):\n+        scope = scope.__wrapped__\n+\n+    return func(obj, scope) if scope else func(obj)\n \n def _extensions_adapt(func, _, args, kwargs):\n     adapt = func(*args, **kwargs)\n@@ -136,3 +147,11 @@\n          psycopg2._json, 'register_type',\n          _extensions_register_type),\n     ]\n+\n+# `quote_ident` attribute is only available for psycopg >= 2.7\n+if getattr(psycopg2, 'extensions', None) and getattr(psycopg2.extensions,\n+                                                     'quote_ident', None):\n+    _psycopg2_extensions += [(psycopg2.extensions.quote_ident,\n+     psycopg2.extensions, 'quote_ident',\n+     _extensions_quote_ident),\n+    ]\n", "issue": "[psycopg2] The quote_ident function requires psycopg2.extensions.connection.\nThis is very related to https://github.com/DataDog/dd-trace-py/issues/383.\r\n\r\nTo reproduce:\r\n```\r\nfrom ddtrace import patch_all\r\npatch_all()\r\n\r\nimport psycopg2\r\nfrom psycopg2.extensions import quote_ident\r\n\r\nconn = psycopg2.connect(dbname=\"test\")\r\nquote_ident('foo', conn) # Fails with TypeError: argument 2 must be a connection or a cursor\r\n```\r\n\r\n\n[psycopg2] The prepare functions require psycopg2.extensions.connection.\nHere is an example:\r\n\r\n```\r\nfrom ddtrace import patch_all\r\n\r\npatch_all()\r\n\r\nimport psycopg2\r\nfrom psycopg2.extensions import adapt\r\n\r\nconn = psycopg2.connect(dbname=\"test\")\r\n\r\nitems = adapt([1, 2, 3])\r\nitems.prepare(conn) # Fails here\r\n\r\nbinary = adapt(b'12345')\r\nbinary.prepare(conn) # and here.\r\n```\r\n\r\n```\r\n$ python example.py\r\nTraceback (most recent call last):\r\n  File \"example.py\", line 11, in <module>\r\n    items.prepare(conn)\r\nTypeError: argument 1 must be psycopg2.extensions.connection, not TracedConnection\r\n```\r\n\r\nThis could probably be solved in a similar manner to #96 .\n", "before_files": [{"content": "# 3p\nimport psycopg2\nimport wrapt\n\n# project\nfrom ddtrace import Pin\nfrom ddtrace.contrib import dbapi\nfrom ddtrace.ext import sql, net, db\n\n# Original connect method\n_connect = psycopg2.connect\n\n\ndef patch():\n    \"\"\" Patch monkey patches psycopg's connection function\n        so that the connection's functions are traced.\n    \"\"\"\n    if getattr(psycopg2, '_datadog_patch', False):\n        return\n    setattr(psycopg2, '_datadog_patch', True)\n\n    wrapt.wrap_function_wrapper(psycopg2, 'connect', patched_connect)\n    _patch_extensions(_psycopg2_extensions)  # do this early just in case\n\n\ndef unpatch():\n    if getattr(psycopg2, '_datadog_patch', False):\n        setattr(psycopg2, '_datadog_patch', False)\n        psycopg2.connect = _connect\n\n\ndef patch_conn(conn, traced_conn_cls=dbapi.TracedConnection):\n    \"\"\" Wrap will patch the instance so that it's queries are traced.\"\"\"\n    # ensure we've patched extensions (this is idempotent) in\n    # case we're only tracing some connections.\n    _patch_extensions(_psycopg2_extensions)\n\n    c = traced_conn_cls(conn)\n\n    # fetch tags from the dsn\n    dsn = sql.parse_pg_dsn(conn.dsn)\n    tags = {\n        net.TARGET_HOST: dsn.get(\"host\"),\n        net.TARGET_PORT: dsn.get(\"port\"),\n        db.NAME: dsn.get(\"dbname\"),\n        db.USER: dsn.get(\"user\"),\n        \"db.application\" : dsn.get(\"application_name\"),\n    }\n\n    Pin(\n        service=\"postgres\",\n        app=\"postgres\",\n        app_type=\"db\",\n        tags=tags).onto(c)\n\n    return c\n\n\ndef _patch_extensions(_extensions):\n    # we must patch extensions all the time (it's pretty harmless) so split\n    # from global patching of connections. must be idempotent.\n    for _, module, func, wrapper in _extensions:\n        if not hasattr(module, func) or isinstance(getattr(module, func), wrapt.ObjectProxy):\n            continue\n        wrapt.wrap_function_wrapper(module, func, wrapper)\n\n\ndef _unpatch_extensions(_extensions):\n    # we must patch extensions all the time (it's pretty harmless) so split\n    # from global patching of connections. must be idempotent.\n    for original, module, func, _ in _extensions:\n        setattr(module, func, original)\n\n\n#\n# monkeypatch targets\n#\n\ndef patched_connect(connect_func, _, args, kwargs):\n    conn = connect_func(*args, **kwargs)\n    return patch_conn(conn)\n\n\ndef _extensions_register_type(func, _, args, kwargs):\n    def _unroll_args(obj, scope=None):\n        return obj, scope\n    obj, scope = _unroll_args(*args, **kwargs)\n\n    # register_type performs a c-level check of the object\n    # type so we must be sure to pass in the actual db connection\n    if scope and isinstance(scope, wrapt.ObjectProxy):\n        scope = scope.__wrapped__\n\n    return func(obj, scope) if scope else func(obj)\n\n\ndef _extensions_adapt(func, _, args, kwargs):\n    adapt = func(*args, **kwargs)\n    if hasattr(adapt, 'prepare'):\n        return AdapterWrapper(adapt)\n    return adapt\n\n\nclass AdapterWrapper(wrapt.ObjectProxy):\n    def prepare(self, *args, **kwargs):\n        func = self.__wrapped__.prepare\n        if not args:\n            return func(*args, **kwargs)\n        conn = args[0]\n\n        # prepare performs a c-level check of the object type so\n        # we must be sure to pass in the actual db connection\n        if isinstance(conn, wrapt.ObjectProxy):\n            conn = conn.__wrapped__\n\n        return func(conn, *args[1:], **kwargs)\n\n\n# extension hooks\n_psycopg2_extensions = [\n    (psycopg2.extensions.register_type,\n     psycopg2.extensions, 'register_type',\n     _extensions_register_type),\n    (psycopg2._psycopg.register_type,\n     psycopg2._psycopg, 'register_type',\n     _extensions_register_type),\n    (psycopg2.extensions.adapt,\n     psycopg2.extensions, 'adapt',\n     _extensions_adapt),\n]\n\n# `_json` attribute is only available for psycopg >= 2.5\nif getattr(psycopg2, '_json', None):\n    _psycopg2_extensions += [\n        (psycopg2._json.register_type,\n         psycopg2._json, 'register_type',\n         _extensions_register_type),\n    ]\n", "path": "ddtrace/contrib/psycopg/patch.py"}], "after_files": [{"content": "# 3p\nimport psycopg2\nimport wrapt\n\n# project\nfrom ddtrace import Pin\nfrom ddtrace.contrib import dbapi\nfrom ddtrace.ext import sql, net, db\n\n# Original connect method\n_connect = psycopg2.connect\n\n\ndef patch():\n    \"\"\" Patch monkey patches psycopg's connection function\n        so that the connection's functions are traced.\n    \"\"\"\n    if getattr(psycopg2, '_datadog_patch', False):\n        return\n    setattr(psycopg2, '_datadog_patch', True)\n\n    wrapt.wrap_function_wrapper(psycopg2, 'connect', patched_connect)\n    _patch_extensions(_psycopg2_extensions)  # do this early just in case\n\n\ndef unpatch():\n    if getattr(psycopg2, '_datadog_patch', False):\n        setattr(psycopg2, '_datadog_patch', False)\n        psycopg2.connect = _connect\n\n\ndef patch_conn(conn, traced_conn_cls=dbapi.TracedConnection):\n    \"\"\" Wrap will patch the instance so that it's queries are traced.\"\"\"\n    # ensure we've patched extensions (this is idempotent) in\n    # case we're only tracing some connections.\n    _patch_extensions(_psycopg2_extensions)\n\n    c = traced_conn_cls(conn)\n\n    # fetch tags from the dsn\n    dsn = sql.parse_pg_dsn(conn.dsn)\n    tags = {\n        net.TARGET_HOST: dsn.get(\"host\"),\n        net.TARGET_PORT: dsn.get(\"port\"),\n        db.NAME: dsn.get(\"dbname\"),\n        db.USER: dsn.get(\"user\"),\n        \"db.application\" : dsn.get(\"application_name\"),\n    }\n\n    Pin(\n        service=\"postgres\",\n        app=\"postgres\",\n        app_type=\"db\",\n        tags=tags).onto(c)\n\n    return c\n\n\ndef _patch_extensions(_extensions):\n    # we must patch extensions all the time (it's pretty harmless) so split\n    # from global patching of connections. must be idempotent.\n    for _, module, func, wrapper in _extensions:\n        if not hasattr(module, func) or isinstance(getattr(module, func), wrapt.ObjectProxy):\n            continue\n        wrapt.wrap_function_wrapper(module, func, wrapper)\n\n\ndef _unpatch_extensions(_extensions):\n    # we must patch extensions all the time (it's pretty harmless) so split\n    # from global patching of connections. must be idempotent.\n    for original, module, func, _ in _extensions:\n        setattr(module, func, original)\n\n\n#\n# monkeypatch targets\n#\n\ndef patched_connect(connect_func, _, args, kwargs):\n    conn = connect_func(*args, **kwargs)\n    return patch_conn(conn)\n\n\ndef _extensions_register_type(func, _, args, kwargs):\n    def _unroll_args(obj, scope=None):\n        return obj, scope\n    obj, scope = _unroll_args(*args, **kwargs)\n\n    # register_type performs a c-level check of the object\n    # type so we must be sure to pass in the actual db connection\n    if scope and isinstance(scope, wrapt.ObjectProxy):\n        scope = scope.__wrapped__\n\n    return func(obj, scope) if scope else func(obj)\n\ndef _extensions_quote_ident(func, _, args, kwargs):\n    def _unroll_args(obj, scope=None):\n        return obj, scope\n    obj, scope = _unroll_args(*args, **kwargs)\n\n    # register_type performs a c-level check of the object\n    # type so we must be sure to pass in the actual db connection\n    if scope and isinstance(scope, wrapt.ObjectProxy):\n        scope = scope.__wrapped__\n\n    return func(obj, scope) if scope else func(obj)\n\ndef _extensions_adapt(func, _, args, kwargs):\n    adapt = func(*args, **kwargs)\n    if hasattr(adapt, 'prepare'):\n        return AdapterWrapper(adapt)\n    return adapt\n\n\nclass AdapterWrapper(wrapt.ObjectProxy):\n    def prepare(self, *args, **kwargs):\n        func = self.__wrapped__.prepare\n        if not args:\n            return func(*args, **kwargs)\n        conn = args[0]\n\n        # prepare performs a c-level check of the object type so\n        # we must be sure to pass in the actual db connection\n        if isinstance(conn, wrapt.ObjectProxy):\n            conn = conn.__wrapped__\n\n        return func(conn, *args[1:], **kwargs)\n\n\n# extension hooks\n_psycopg2_extensions = [\n    (psycopg2.extensions.register_type,\n     psycopg2.extensions, 'register_type',\n     _extensions_register_type),\n    (psycopg2._psycopg.register_type,\n     psycopg2._psycopg, 'register_type',\n     _extensions_register_type),\n    (psycopg2.extensions.adapt,\n     psycopg2.extensions, 'adapt',\n     _extensions_adapt),\n]\n\n# `_json` attribute is only available for psycopg >= 2.5\nif getattr(psycopg2, '_json', None):\n    _psycopg2_extensions += [\n        (psycopg2._json.register_type,\n         psycopg2._json, 'register_type',\n         _extensions_register_type),\n    ]\n\n# `quote_ident` attribute is only available for psycopg >= 2.7\nif getattr(psycopg2, 'extensions', None) and getattr(psycopg2.extensions,\n                                                     'quote_ident', None):\n    _psycopg2_extensions += [(psycopg2.extensions.quote_ident,\n     psycopg2.extensions, 'quote_ident',\n     _extensions_quote_ident),\n    ]\n", "path": "ddtrace/contrib/psycopg/patch.py"}]}