prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  aiomysql: AttributeError: __aenter__
  ### Which version of dd-trace-py are you using?
  
  `ddtrace==1.2.0`
  
  ### Which version of the libraries are you using?
  
  `aiomysql==0.1.1`
  
  ### How can we reproduce your problem?
  
  ```python
  # repro.py
  import asyncio
  
  import aiomysql
  
  
  loop = asyncio.get_event_loop()
  
  
  async def go():
      pool = await aiomysql.create_pool(
          host="127.0.0.1",
          port=3306,
          user="test",
          password="test",
          db="test",
          loop=loop,
          autocommit=False,
      )
  
      async with pool.acquire() as conn:
          await conn.ping(reconnect=True)
          async with conn.cursor() as cur:
              await cur.execute("SELECT 10")
              (r,) = await cur.fetchone()
              return r
  
  
  loop.run_until_complete(go())
  ```
  
  ```
  ddtrace-run python repro.py
  ```
  
  ### What is the result that you get?
  
  ```
  ❯ ddtrace-run python repro.py
  repro.py:16: RuntimeWarning: coroutine 'AIOTracedConnection.cursor' was never awaited
    async with conn.cursor() as cur:
  RuntimeWarning: Enable tracemalloc to get the object allocation traceback
  Traceback (most recent call last):
    File "/Users/brett.langdon/datadog/dd-trace-py/repro.py", line 22, in <module>
      loop.run_until_complete(go())
    File "/Users/brett.langdon/.pyenv/versions/3.9.10/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
      return future.result()
    File "/Users/brett.langdon/datadog/dd-trace-py/repro.py", line 16, in go
      async with conn.cursor() as cur:
  AttributeError: __aenter__
  ```
  
  ### What is the result that you expected?
  No attribute error, and `async with conn.cursor()` works as expected.
  
  --- 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/aiomysql/patch.py`
  Content:
  ```
  1 import aiomysql
  2 
  3 from ddtrace import Pin
  4 from ddtrace import config
  5 from ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY
  6 from ddtrace.constants import SPAN_MEASURED_KEY
  7 from ddtrace.contrib import dbapi
  8 from ddtrace.ext import sql
  9 from ddtrace.internal.utils.wrappers import unwrap
  10 from ddtrace.vendor import wrapt
  11 
  12 from ...ext import SpanTypes
  13 from ...ext import db
  14 from ...ext import net
  15 
  16 
  17 config._add(
  18     "aiomysql",
  19     dict(_default_service="mysql"),
  20 )
  21 
  22 CONN_ATTR_BY_TAG = {
  23     net.TARGET_HOST: "host",
  24     net.TARGET_PORT: "port",
  25     db.USER: "user",
  26     db.NAME: "db",
  27 }
  28 
  29 
  30 async def patched_connect(connect_func, _, args, kwargs):
  31     conn = await connect_func(*args, **kwargs)
  32     tags = {}
  33     for tag, attr in CONN_ATTR_BY_TAG.items():
  34         if hasattr(conn, attr):
  35             tags[tag] = getattr(conn, attr)
  36 
  37     c = AIOTracedConnection(conn)
  38     Pin(tags=tags).onto(c)
  39     return c
  40 
  41 
  42 class AIOTracedCursor(wrapt.ObjectProxy):
  43     """TracedCursor wraps a aiomysql cursor and traces its queries."""
  44 
  45     def __init__(self, cursor, pin):
  46         super(AIOTracedCursor, self).__init__(cursor)
  47         pin.onto(self)
  48         self._self_datadog_name = "mysql.query"
  49 
  50     async def _trace_method(self, method, resource, extra_tags, *args, **kwargs):
  51         pin = Pin.get_from(self)
  52         if not pin or not pin.enabled():
  53             result = await method(*args, **kwargs)
  54             return result
  55         service = pin.service
  56 
  57         with pin.tracer.trace(
  58             self._self_datadog_name, service=service, resource=resource, span_type=SpanTypes.SQL
  59         ) as s:
  60             s.set_tag(SPAN_MEASURED_KEY)
  61             s.set_tag(sql.QUERY, resource)
  62             s.set_tags(pin.tags)
  63             s.set_tags(extra_tags)
  64 
  65             # set analytics sample rate
  66             s.set_tag(ANALYTICS_SAMPLE_RATE_KEY, config.aiomysql.get_analytics_sample_rate())
  67 
  68             try:
  69                 result = await method(*args, **kwargs)
  70                 return result
  71             finally:
  72                 s.set_metric(db.ROWCOUNT, self.rowcount)
  73                 s.set_metric("db.rownumber", self.rownumber)
  74 
  75     async def executemany(self, query, *args, **kwargs):
  76         result = await self._trace_method(
  77             self.__wrapped__.executemany, query, {"sql.executemany": "true"}, query, *args, **kwargs
  78         )
  79         return result
  80 
  81     async def execute(self, query, *args, **kwargs):
  82         result = await self._trace_method(self.__wrapped__.execute, query, {}, query, *args, **kwargs)
  83         return result
  84 
  85 
  86 class AIOTracedConnection(wrapt.ObjectProxy):
  87     def __init__(self, conn, pin=None, cursor_cls=AIOTracedCursor):
  88         super(AIOTracedConnection, self).__init__(conn)
  89         name = dbapi._get_vendor(conn)
  90         db_pin = pin or Pin(service=name)
  91         db_pin.onto(self)
  92         # wrapt requires prefix of `_self` for attributes that are only in the
  93         # proxy (since some of our source objects will use `__slots__`)
  94         self._self_cursor_cls = cursor_cls
  95 
  96     async def cursor(self, *args, **kwargs):
  97         cursor = await self.__wrapped__.cursor(*args, **kwargs)
  98         pin = Pin.get_from(self)
  99         if not pin:
  100             return cursor
  101         return self._self_cursor_cls(cursor, pin)
  102 
  103     async def __aenter__(self):
  104         return self.__wrapped__.__aenter__()
  105 
  106 
  107 def patch():
  108     if getattr(aiomysql, "__datadog_patch", False):
  109         return
  110     setattr(aiomysql, "__datadog_patch", True)
  111     wrapt.wrap_function_wrapper(aiomysql.connection, "_connect", patched_connect)
  112 
  113 
  114 def unpatch():
  115     if getattr(aiomysql, "__datadog_patch", False):
  116         setattr(aiomysql, "__datadog_patch", False)
  117         unwrap(aiomysql.connection, "_connect")
  118
  ```
  --- 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/aiomysql/patch.py b/ddtrace/contrib/aiomysql/patch.py
  --- a/ddtrace/contrib/aiomysql/patch.py
  +++ b/ddtrace/contrib/aiomysql/patch.py
  @@ -82,6 +82,14 @@
           result = await self._trace_method(self.__wrapped__.execute, query, {}, query, *args, **kwargs)
           return result
   
  +    # Explicitly define `__aenter__` and `__aexit__` since they do not get proxied properly
  +    async def __aenter__(self):
  +        # The base class just returns `self`, but we want the wrapped cursor so we return ourselves
  +        return self
  +
  +    async def __aexit__(self, *args, **kwargs):
  +        return await self.__wrapped__.__aexit__(*args, **kwargs)
  +
   
   class AIOTracedConnection(wrapt.ObjectProxy):
       def __init__(self, conn, pin=None, cursor_cls=AIOTracedCursor):
  @@ -93,15 +101,36 @@
           # proxy (since some of our source objects will use `__slots__`)
           self._self_cursor_cls = cursor_cls
   
  -    async def cursor(self, *args, **kwargs):
  -        cursor = await self.__wrapped__.cursor(*args, **kwargs)
  +    def cursor(self, *args, **kwargs):
  +        ctx_manager = self.__wrapped__.cursor(*args, **kwargs)
           pin = Pin.get_from(self)
           if not pin:
  -            return cursor
  -        return self._self_cursor_cls(cursor, pin)
  -
  +            return ctx_manager
  +
  +        # The result of `cursor()` is an `aiomysql.utils._ContextManager`
  +        #   which wraps a coroutine (a future) and adds async context manager
  +        #   helper functions to it.
  +        # https://github.com/aio-libs/aiomysql/blob/8a32f052a16dc3886af54b98f4d91d95862bfb8e/aiomysql/connection.py#L461
  +        # https://github.com/aio-libs/aiomysql/blob/7fa5078da31bbc95f5e32a934a4b2b4207c67ede/aiomysql/utils.py#L30-L79
  +        # We cannot swap out the result on the future/context manager so
  +        #   instead we have to create a new coroutine that returns our
  +        #   wrapped cursor
  +        # We also cannot turn `def cursor` into `async def cursor` because
  +        #   otherwise we will change the result to be a coroutine instead of
  +        #   an `aiomysql.utils._ContextManager` which wraps a coroutine. This
  +        #   will cause issues with `async with conn.cursor() as cur:` usage.
  +        async def _wrap_cursor():
  +            cursor = await ctx_manager
  +            return self._self_cursor_cls(cursor, pin)
  +
  +        return type(ctx_manager)(_wrap_cursor())
  +
  +    # Explicitly define `__aenter__` and `__aexit__` since they do not get proxied properly
       async def __aenter__(self):
  -        return self.__wrapped__.__aenter__()
  +        return await self.__wrapped__.__aenter__()
  +
  +    async def __aexit__(self, *args, **kwargs):
  +        return await self.__wrapped__.__aexit__(*args, **kwargs)
   
   
   def patch():
  
verification_info: {"golden_diff": "diff --git a/ddtrace/contrib/aiomysql/patch.py b/ddtrace/contrib/aiomysql/patch.py\n--- a/ddtrace/contrib/aiomysql/patch.py\n+++ b/ddtrace/contrib/aiomysql/patch.py\n@@ -82,6 +82,14 @@\n         result = await self._trace_method(self.__wrapped__.execute, query, {}, query, *args, **kwargs)\n         return result\n \n+    # Explicitly define `__aenter__` and `__aexit__` since they do not get proxied properly\n+    async def __aenter__(self):\n+        # The base class just returns `self`, but we want the wrapped cursor so we return ourselves\n+        return self\n+\n+    async def __aexit__(self, *args, **kwargs):\n+        return await self.__wrapped__.__aexit__(*args, **kwargs)\n+\n \n class AIOTracedConnection(wrapt.ObjectProxy):\n     def __init__(self, conn, pin=None, cursor_cls=AIOTracedCursor):\n@@ -93,15 +101,36 @@\n         # proxy (since some of our source objects will use `__slots__`)\n         self._self_cursor_cls = cursor_cls\n \n-    async def cursor(self, *args, **kwargs):\n-        cursor = await self.__wrapped__.cursor(*args, **kwargs)\n+    def cursor(self, *args, **kwargs):\n+        ctx_manager = self.__wrapped__.cursor(*args, **kwargs)\n         pin = Pin.get_from(self)\n         if not pin:\n-            return cursor\n-        return self._self_cursor_cls(cursor, pin)\n-\n+            return ctx_manager\n+\n+        # The result of `cursor()` is an `aiomysql.utils._ContextManager`\n+        #   which wraps a coroutine (a future) and adds async context manager\n+        #   helper functions to it.\n+        # https://github.com/aio-libs/aiomysql/blob/8a32f052a16dc3886af54b98f4d91d95862bfb8e/aiomysql/connection.py#L461\n+        # https://github.com/aio-libs/aiomysql/blob/7fa5078da31bbc95f5e32a934a4b2b4207c67ede/aiomysql/utils.py#L30-L79\n+        # We cannot swap out the result on the future/context manager so\n+        #   instead we have to create a new coroutine that returns our\n+        #   wrapped cursor\n+        # We also cannot turn `def cursor` into `async def cursor` because\n+        #   otherwise we will change the result to be a coroutine instead of\n+        #   an `aiomysql.utils._ContextManager` which wraps a coroutine. This\n+        #   will cause issues with `async with conn.cursor() as cur:` usage.\n+        async def _wrap_cursor():\n+            cursor = await ctx_manager\n+            return self._self_cursor_cls(cursor, pin)\n+\n+        return type(ctx_manager)(_wrap_cursor())\n+\n+    # Explicitly define `__aenter__` and `__aexit__` since they do not get proxied properly\n     async def __aenter__(self):\n-        return self.__wrapped__.__aenter__()\n+        return await self.__wrapped__.__aenter__()\n+\n+    async def __aexit__(self, *args, **kwargs):\n+        return await self.__wrapped__.__aexit__(*args, **kwargs)\n \n \n def patch():\n", "issue": "aiomysql: AttributeError: __aenter__\n### Which version of dd-trace-py are you using?\r\n\r\n`ddtrace==1.2.0`\r\n\r\n### Which version of the libraries are you using?\r\n\r\n`aiomysql==0.1.1`\r\n\r\n### How can we reproduce your problem?\r\n\r\n```python\r\n# repro.py\r\nimport asyncio\r\n\r\nimport aiomysql\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\n\r\n\r\nasync def go():\r\n    pool = await aiomysql.create_pool(\r\n        host=\"127.0.0.1\",\r\n        port=3306,\r\n        user=\"test\",\r\n        password=\"test\",\r\n        db=\"test\",\r\n        loop=loop,\r\n        autocommit=False,\r\n    )\r\n\r\n    async with pool.acquire() as conn:\r\n        await conn.ping(reconnect=True)\r\n        async with conn.cursor() as cur:\r\n            await cur.execute(\"SELECT 10\")\r\n            (r,) = await cur.fetchone()\r\n            return r\r\n\r\n\r\nloop.run_until_complete(go())\r\n```\r\n\r\n```\r\nddtrace-run python repro.py\r\n```\r\n\r\n### What is the result that you get?\r\n\r\n```\r\n\u276f ddtrace-run python repro.py\r\nrepro.py:16: RuntimeWarning: coroutine 'AIOTracedConnection.cursor' was never awaited\r\n  async with conn.cursor() as cur:\r\nRuntimeWarning: Enable tracemalloc to get the object allocation traceback\r\nTraceback (most recent call last):\r\n  File \"/Users/brett.langdon/datadog/dd-trace-py/repro.py\", line 22, in <module>\r\n    loop.run_until_complete(go())\r\n  File \"/Users/brett.langdon/.pyenv/versions/3.9.10/lib/python3.9/asyncio/base_events.py\", line 642, in run_until_complete\r\n    return future.result()\r\n  File \"/Users/brett.langdon/datadog/dd-trace-py/repro.py\", line 16, in go\r\n    async with conn.cursor() as cur:\r\nAttributeError: __aenter__\r\n```\r\n\r\n### What is the result that you expected?\r\nNo attribute error, and `async with conn.cursor()` works as expected.\n", "before_files": [{"content": "import aiomysql\n\nfrom ddtrace import Pin\nfrom ddtrace import config\nfrom ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY\nfrom ddtrace.constants import SPAN_MEASURED_KEY\nfrom ddtrace.contrib import dbapi\nfrom ddtrace.ext import sql\nfrom ddtrace.internal.utils.wrappers import unwrap\nfrom ddtrace.vendor import wrapt\n\nfrom ...ext import SpanTypes\nfrom ...ext import db\nfrom ...ext import net\n\n\nconfig._add(\n    \"aiomysql\",\n    dict(_default_service=\"mysql\"),\n)\n\nCONN_ATTR_BY_TAG = {\n    net.TARGET_HOST: \"host\",\n    net.TARGET_PORT: \"port\",\n    db.USER: \"user\",\n    db.NAME: \"db\",\n}\n\n\nasync def patched_connect(connect_func, _, args, kwargs):\n    conn = await connect_func(*args, **kwargs)\n    tags = {}\n    for tag, attr in CONN_ATTR_BY_TAG.items():\n        if hasattr(conn, attr):\n            tags[tag] = getattr(conn, attr)\n\n    c = AIOTracedConnection(conn)\n    Pin(tags=tags).onto(c)\n    return c\n\n\nclass AIOTracedCursor(wrapt.ObjectProxy):\n    \"\"\"TracedCursor wraps a aiomysql cursor and traces its queries.\"\"\"\n\n    def __init__(self, cursor, pin):\n        super(AIOTracedCursor, self).__init__(cursor)\n        pin.onto(self)\n        self._self_datadog_name = \"mysql.query\"\n\n    async def _trace_method(self, method, resource, extra_tags, *args, **kwargs):\n        pin = Pin.get_from(self)\n        if not pin or not pin.enabled():\n            result = await method(*args, **kwargs)\n            return result\n        service = pin.service\n\n        with pin.tracer.trace(\n            self._self_datadog_name, service=service, resource=resource, span_type=SpanTypes.SQL\n        ) as s:\n            s.set_tag(SPAN_MEASURED_KEY)\n            s.set_tag(sql.QUERY, resource)\n            s.set_tags(pin.tags)\n            s.set_tags(extra_tags)\n\n            # set analytics sample rate\n            s.set_tag(ANALYTICS_SAMPLE_RATE_KEY, config.aiomysql.get_analytics_sample_rate())\n\n            try:\n                result = await method(*args, **kwargs)\n                return result\n            finally:\n                s.set_metric(db.ROWCOUNT, self.rowcount)\n                s.set_metric(\"db.rownumber\", self.rownumber)\n\n    async def executemany(self, query, *args, **kwargs):\n        result = await self._trace_method(\n            self.__wrapped__.executemany, query, {\"sql.executemany\": \"true\"}, query, *args, **kwargs\n        )\n        return result\n\n    async def execute(self, query, *args, **kwargs):\n        result = await self._trace_method(self.__wrapped__.execute, query, {}, query, *args, **kwargs)\n        return result\n\n\nclass AIOTracedConnection(wrapt.ObjectProxy):\n    def __init__(self, conn, pin=None, cursor_cls=AIOTracedCursor):\n        super(AIOTracedConnection, self).__init__(conn)\n        name = dbapi._get_vendor(conn)\n        db_pin = pin or Pin(service=name)\n        db_pin.onto(self)\n        # wrapt requires prefix of `_self` for attributes that are only in the\n        # proxy (since some of our source objects will use `__slots__`)\n        self._self_cursor_cls = cursor_cls\n\n    async def cursor(self, *args, **kwargs):\n        cursor = await self.__wrapped__.cursor(*args, **kwargs)\n        pin = Pin.get_from(self)\n        if not pin:\n            return cursor\n        return self._self_cursor_cls(cursor, pin)\n\n    async def __aenter__(self):\n        return self.__wrapped__.__aenter__()\n\n\ndef patch():\n    if getattr(aiomysql, \"__datadog_patch\", False):\n        return\n    setattr(aiomysql, \"__datadog_patch\", True)\n    wrapt.wrap_function_wrapper(aiomysql.connection, \"_connect\", patched_connect)\n\n\ndef unpatch():\n    if getattr(aiomysql, \"__datadog_patch\", False):\n        setattr(aiomysql, \"__datadog_patch\", False)\n        unwrap(aiomysql.connection, \"_connect\")\n", "path": "ddtrace/contrib/aiomysql/patch.py"}], "after_files": [{"content": "import aiomysql\n\nfrom ddtrace import Pin\nfrom ddtrace import config\nfrom ddtrace.constants import ANALYTICS_SAMPLE_RATE_KEY\nfrom ddtrace.constants import SPAN_MEASURED_KEY\nfrom ddtrace.contrib import dbapi\nfrom ddtrace.ext import sql\nfrom ddtrace.internal.utils.wrappers import unwrap\nfrom ddtrace.vendor import wrapt\n\nfrom ...ext import SpanTypes\nfrom ...ext import db\nfrom ...ext import net\n\n\nconfig._add(\n    \"aiomysql\",\n    dict(_default_service=\"mysql\"),\n)\n\nCONN_ATTR_BY_TAG = {\n    net.TARGET_HOST: \"host\",\n    net.TARGET_PORT: \"port\",\n    db.USER: \"user\",\n    db.NAME: \"db\",\n}\n\n\nasync def patched_connect(connect_func, _, args, kwargs):\n    conn = await connect_func(*args, **kwargs)\n    tags = {}\n    for tag, attr in CONN_ATTR_BY_TAG.items():\n        if hasattr(conn, attr):\n            tags[tag] = getattr(conn, attr)\n\n    c = AIOTracedConnection(conn)\n    Pin(tags=tags).onto(c)\n    return c\n\n\nclass AIOTracedCursor(wrapt.ObjectProxy):\n    \"\"\"TracedCursor wraps a aiomysql cursor and traces its queries.\"\"\"\n\n    def __init__(self, cursor, pin):\n        super(AIOTracedCursor, self).__init__(cursor)\n        pin.onto(self)\n        self._self_datadog_name = \"mysql.query\"\n\n    async def _trace_method(self, method, resource, extra_tags, *args, **kwargs):\n        pin = Pin.get_from(self)\n        if not pin or not pin.enabled():\n            result = await method(*args, **kwargs)\n            return result\n        service = pin.service\n\n        with pin.tracer.trace(\n            self._self_datadog_name, service=service, resource=resource, span_type=SpanTypes.SQL\n        ) as s:\n            s.set_tag(SPAN_MEASURED_KEY)\n            s.set_tag(sql.QUERY, resource)\n            s.set_tags(pin.tags)\n            s.set_tags(extra_tags)\n\n            # set analytics sample rate\n            s.set_tag(ANALYTICS_SAMPLE_RATE_KEY, config.aiomysql.get_analytics_sample_rate())\n\n            try:\n                result = await method(*args, **kwargs)\n                return result\n            finally:\n                s.set_metric(db.ROWCOUNT, self.rowcount)\n                s.set_metric(\"db.rownumber\", self.rownumber)\n\n    async def executemany(self, query, *args, **kwargs):\n        result = await self._trace_method(\n            self.__wrapped__.executemany, query, {\"sql.executemany\": \"true\"}, query, *args, **kwargs\n        )\n        return result\n\n    async def execute(self, query, *args, **kwargs):\n        result = await self._trace_method(self.__wrapped__.execute, query, {}, query, *args, **kwargs)\n        return result\n\n    # Explicitly define `__aenter__` and `__aexit__` since they do not get proxied properly\n    async def __aenter__(self):\n        # The base class just returns `self`, but we want the wrapped cursor so we return ourselves\n        return self\n\n    async def __aexit__(self, *args, **kwargs):\n        return await self.__wrapped__.__aexit__(*args, **kwargs)\n\n\nclass AIOTracedConnection(wrapt.ObjectProxy):\n    def __init__(self, conn, pin=None, cursor_cls=AIOTracedCursor):\n        super(AIOTracedConnection, self).__init__(conn)\n        name = dbapi._get_vendor(conn)\n        db_pin = pin or Pin(service=name)\n        db_pin.onto(self)\n        # wrapt requires prefix of `_self` for attributes that are only in the\n        # proxy (since some of our source objects will use `__slots__`)\n        self._self_cursor_cls = cursor_cls\n\n    def cursor(self, *args, **kwargs):\n        ctx_manager = self.__wrapped__.cursor(*args, **kwargs)\n        pin = Pin.get_from(self)\n        if not pin:\n            return ctx_manager\n\n        # The result of `cursor()` is an `aiomysql.utils._ContextManager`\n        #   which wraps a coroutine (a future) and adds async context manager\n        #   helper functions to it.\n        # https://github.com/aio-libs/aiomysql/blob/8a32f052a16dc3886af54b98f4d91d95862bfb8e/aiomysql/connection.py#L461\n        # https://github.com/aio-libs/aiomysql/blob/7fa5078da31bbc95f5e32a934a4b2b4207c67ede/aiomysql/utils.py#L30-L79\n        # We cannot swap out the result on the future/context manager so\n        #   instead we have to create a new coroutine that returns our\n        #   wrapped cursor\n        # We also cannot turn `def cursor` into `async def cursor` because\n        #   otherwise we will change the result to be a coroutine instead of\n        #   an `aiomysql.utils._ContextManager` which wraps a coroutine. This\n        #   will cause issues with `async with conn.cursor() as cur:` usage.\n        async def _wrap_cursor():\n            cursor = await ctx_manager\n            return self._self_cursor_cls(cursor, pin)\n\n        return type(ctx_manager)(_wrap_cursor())\n\n    # Explicitly define `__aenter__` and `__aexit__` since they do not get proxied properly\n    async def __aenter__(self):\n        return await self.__wrapped__.__aenter__()\n\n    async def __aexit__(self, *args, **kwargs):\n        return await self.__wrapped__.__aexit__(*args, **kwargs)\n\n\ndef patch():\n    if getattr(aiomysql, \"__datadog_patch\", False):\n        return\n    setattr(aiomysql, \"__datadog_patch\", True)\n    wrapt.wrap_function_wrapper(aiomysql.connection, \"_connect\", patched_connect)\n\n\ndef unpatch():\n    if getattr(aiomysql, \"__datadog_patch\", False):\n        setattr(aiomysql, \"__datadog_patch\", False)\n        unwrap(aiomysql.connection, \"_connect\")\n", "path": "ddtrace/contrib/aiomysql/patch.py"}]}