prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Fix Jinja2 async integration
  Since https://github.com/pallets/jinja/issues/765 , Jinja2 only lazily imports and adds the `render_async` function that we instrument (since #398).
  
  We need to update to only instrument at the point the `render_async` method becomes available.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/scout_apm/instruments/jinja2.py`
  Content:
  ```
  1 # coding=utf-8
  2 from __future__ import absolute_import, division, print_function, unicode_literals
  3 
  4 import logging
  5 
  6 import wrapt
  7 
  8 from scout_apm.core.tracked_request import TrackedRequest
  9 
  10 try:
  11     from jinja2 import Template
  12 except ImportError:  # pragma: no cover
  13     Template = None
  14 
  15 # The async_ module can only be shipped on Python 3.6+
  16 try:
  17     from scout_apm.async_.instruments.jinja2 import wrapped_render_async
  18 except ImportError:
  19     wrapped_render_async = None
  20 
  21 
  22 logger = logging.getLogger(__name__)
  23 
  24 
  25 have_patched_template_render = False
  26 have_patched_template_render_async = False
  27 
  28 
  29 def ensure_installed():
  30     global have_patched_template_render
  31     global have_patched_template_render_async
  32 
  33     logger.info("Ensuring Jinja2 instrumentation is installed.")
  34 
  35     if Template is None:
  36         logger.info("Unable to import jinja2.Template")
  37         return
  38 
  39     if not have_patched_template_render:
  40         try:
  41             Template.render = wrapped_render(Template.render)
  42         except Exception as exc:
  43             logger.warning(
  44                 "Unable to instrument jinja2.Template.render: %r", exc, exc_info=exc
  45             )
  46         else:
  47             have_patched_template_render = True
  48 
  49     if not have_patched_template_render_async and wrapped_render_async is not None:
  50         try:
  51             Template.render_async = wrapped_render_async(Template.render_async)
  52         except Exception as exc:
  53             logger.warning(
  54                 "Unable to instrument jinja2.Template.render_async: %r",
  55                 exc,
  56                 exc_info=exc,
  57             )
  58         else:
  59             have_patched_template_render_async = True
  60 
  61 
  62 @wrapt.decorator
  63 def wrapped_render(wrapped, instance, args, kwargs):
  64     tracked_request = TrackedRequest.instance()
  65     span = tracked_request.start_span(operation="Template/Render")
  66     span.tag("name", instance.name)
  67     try:
  68         return wrapped(*args, **kwargs)
  69     finally:
  70         tracked_request.stop_span()
  71
  ```
  --- 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/src/scout_apm/instruments/jinja2.py b/src/scout_apm/instruments/jinja2.py
  --- a/src/scout_apm/instruments/jinja2.py
  +++ b/src/scout_apm/instruments/jinja2.py
  @@ -2,11 +2,17 @@
   from __future__ import absolute_import, division, print_function, unicode_literals
   
   import logging
  +import sys
   
   import wrapt
   
   from scout_apm.core.tracked_request import TrackedRequest
   
  +try:
  +    from jinja2 import Environment
  +except ImportError:  # pragma: no cover
  +    Environment = None
  +
   try:
       from jinja2 import Template
   except ImportError:  # pragma: no cover
  @@ -22,13 +28,14 @@
   logger = logging.getLogger(__name__)
   
   
  +have_patched_environment_init = False
   have_patched_template_render = False
   have_patched_template_render_async = False
   
   
   def ensure_installed():
  +    global have_patched_environment_init
       global have_patched_template_render
  -    global have_patched_template_render_async
   
       logger.info("Ensuring Jinja2 instrumentation is installed.")
   
  @@ -36,27 +43,27 @@
           logger.info("Unable to import jinja2.Template")
           return
   
  -    if not have_patched_template_render:
  +    if not have_patched_environment_init:
           try:
  -            Template.render = wrapped_render(Template.render)
  +            Environment.__init__ = wrapped_environment_init(Environment.__init__)
           except Exception as exc:
               logger.warning(
  -                "Unable to instrument jinja2.Template.render: %r", exc, exc_info=exc
  +                "Unable to instrument jinja2.Environment.__init__: %r",
  +                exc,
  +                exc_info=exc,
               )
           else:
  -            have_patched_template_render = True
  +            have_patched_environment_init = True
   
  -    if not have_patched_template_render_async and wrapped_render_async is not None:
  +    if not have_patched_template_render:
           try:
  -            Template.render_async = wrapped_render_async(Template.render_async)
  +            Template.render = wrapped_render(Template.render)
           except Exception as exc:
               logger.warning(
  -                "Unable to instrument jinja2.Template.render_async: %r",
  -                exc,
  -                exc_info=exc,
  +                "Unable to instrument jinja2.Template.render: %r", exc, exc_info=exc
               )
           else:
  -            have_patched_template_render_async = True
  +            have_patched_template_render = True
   
   
   @wrapt.decorator
  @@ -68,3 +75,33 @@
           return wrapped(*args, **kwargs)
       finally:
           tracked_request.stop_span()
  +
  +
  +@wrapt.decorator
  +def wrapped_environment_init(wrapped, instance, args, kwargs):
  +    """
  +    Delayed wrapping of render_async(), since Template won't have this method
  +    until after jinja2.asyncsupport is imported, which since Jinja2 2.11.0 is
  +    done conditionally in Environment.__init__:
  +    https://github.com/pallets/jinja/issues/765
  +    """
  +    global have_patched_template_render_async
  +    result = wrapped(*args, **kwargs)
  +
  +    if (
  +        wrapped_render_async is not None
  +        and not have_patched_template_render_async
  +        and "jinja2.asyncsupport" in sys.modules
  +    ):
  +        try:
  +            Template.render_async = wrapped_render_async(Template.render_async)
  +        except Exception as exc:
  +            logger.warning(
  +                "Unable to instrument jinja2.Template.render_async: %r",
  +                exc,
  +                exc_info=exc,
  +            )
  +        else:
  +            have_patched_template_render_async = True
  +
  +    return result
  
verification_info: {"golden_diff": "diff --git a/src/scout_apm/instruments/jinja2.py b/src/scout_apm/instruments/jinja2.py\n--- a/src/scout_apm/instruments/jinja2.py\n+++ b/src/scout_apm/instruments/jinja2.py\n@@ -2,11 +2,17 @@\n from __future__ import absolute_import, division, print_function, unicode_literals\n \n import logging\n+import sys\n \n import wrapt\n \n from scout_apm.core.tracked_request import TrackedRequest\n \n+try:\n+    from jinja2 import Environment\n+except ImportError:  # pragma: no cover\n+    Environment = None\n+\n try:\n     from jinja2 import Template\n except ImportError:  # pragma: no cover\n@@ -22,13 +28,14 @@\n logger = logging.getLogger(__name__)\n \n \n+have_patched_environment_init = False\n have_patched_template_render = False\n have_patched_template_render_async = False\n \n \n def ensure_installed():\n+    global have_patched_environment_init\n     global have_patched_template_render\n-    global have_patched_template_render_async\n \n     logger.info(\"Ensuring Jinja2 instrumentation is installed.\")\n \n@@ -36,27 +43,27 @@\n         logger.info(\"Unable to import jinja2.Template\")\n         return\n \n-    if not have_patched_template_render:\n+    if not have_patched_environment_init:\n         try:\n-            Template.render = wrapped_render(Template.render)\n+            Environment.__init__ = wrapped_environment_init(Environment.__init__)\n         except Exception as exc:\n             logger.warning(\n-                \"Unable to instrument jinja2.Template.render: %r\", exc, exc_info=exc\n+                \"Unable to instrument jinja2.Environment.__init__: %r\",\n+                exc,\n+                exc_info=exc,\n             )\n         else:\n-            have_patched_template_render = True\n+            have_patched_environment_init = True\n \n-    if not have_patched_template_render_async and wrapped_render_async is not None:\n+    if not have_patched_template_render:\n         try:\n-            Template.render_async = wrapped_render_async(Template.render_async)\n+            Template.render = wrapped_render(Template.render)\n         except Exception as exc:\n             logger.warning(\n-                \"Unable to instrument jinja2.Template.render_async: %r\",\n-                exc,\n-                exc_info=exc,\n+                \"Unable to instrument jinja2.Template.render: %r\", exc, exc_info=exc\n             )\n         else:\n-            have_patched_template_render_async = True\n+            have_patched_template_render = True\n \n \n @wrapt.decorator\n@@ -68,3 +75,33 @@\n         return wrapped(*args, **kwargs)\n     finally:\n         tracked_request.stop_span()\n+\n+\n+@wrapt.decorator\n+def wrapped_environment_init(wrapped, instance, args, kwargs):\n+    \"\"\"\n+    Delayed wrapping of render_async(), since Template won't have this method\n+    until after jinja2.asyncsupport is imported, which since Jinja2 2.11.0 is\n+    done conditionally in Environment.__init__:\n+    https://github.com/pallets/jinja/issues/765\n+    \"\"\"\n+    global have_patched_template_render_async\n+    result = wrapped(*args, **kwargs)\n+\n+    if (\n+        wrapped_render_async is not None\n+        and not have_patched_template_render_async\n+        and \"jinja2.asyncsupport\" in sys.modules\n+    ):\n+        try:\n+            Template.render_async = wrapped_render_async(Template.render_async)\n+        except Exception as exc:\n+            logger.warning(\n+                \"Unable to instrument jinja2.Template.render_async: %r\",\n+                exc,\n+                exc_info=exc,\n+            )\n+        else:\n+            have_patched_template_render_async = True\n+\n+    return result\n", "issue": "Fix Jinja2 async integration\nSince https://github.com/pallets/jinja/issues/765 , Jinja2 only lazily imports and adds the `render_async` function that we instrument (since #398).\r\n\r\nWe need to update to only instrument at the point the `render_async` method becomes available.\n", "before_files": [{"content": "# coding=utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\n\nimport wrapt\n\nfrom scout_apm.core.tracked_request import TrackedRequest\n\ntry:\n    from jinja2 import Template\nexcept ImportError:  # pragma: no cover\n    Template = None\n\n# The async_ module can only be shipped on Python 3.6+\ntry:\n    from scout_apm.async_.instruments.jinja2 import wrapped_render_async\nexcept ImportError:\n    wrapped_render_async = None\n\n\nlogger = logging.getLogger(__name__)\n\n\nhave_patched_template_render = False\nhave_patched_template_render_async = False\n\n\ndef ensure_installed():\n    global have_patched_template_render\n    global have_patched_template_render_async\n\n    logger.info(\"Ensuring Jinja2 instrumentation is installed.\")\n\n    if Template is None:\n        logger.info(\"Unable to import jinja2.Template\")\n        return\n\n    if not have_patched_template_render:\n        try:\n            Template.render = wrapped_render(Template.render)\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument jinja2.Template.render: %r\", exc, exc_info=exc\n            )\n        else:\n            have_patched_template_render = True\n\n    if not have_patched_template_render_async and wrapped_render_async is not None:\n        try:\n            Template.render_async = wrapped_render_async(Template.render_async)\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument jinja2.Template.render_async: %r\",\n                exc,\n                exc_info=exc,\n            )\n        else:\n            have_patched_template_render_async = True\n\n\n@wrapt.decorator\ndef wrapped_render(wrapped, instance, args, kwargs):\n    tracked_request = TrackedRequest.instance()\n    span = tracked_request.start_span(operation=\"Template/Render\")\n    span.tag(\"name\", instance.name)\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n", "path": "src/scout_apm/instruments/jinja2.py"}], "after_files": [{"content": "# coding=utf-8\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nimport logging\nimport sys\n\nimport wrapt\n\nfrom scout_apm.core.tracked_request import TrackedRequest\n\ntry:\n    from jinja2 import Environment\nexcept ImportError:  # pragma: no cover\n    Environment = None\n\ntry:\n    from jinja2 import Template\nexcept ImportError:  # pragma: no cover\n    Template = None\n\n# The async_ module can only be shipped on Python 3.6+\ntry:\n    from scout_apm.async_.instruments.jinja2 import wrapped_render_async\nexcept ImportError:\n    wrapped_render_async = None\n\n\nlogger = logging.getLogger(__name__)\n\n\nhave_patched_environment_init = False\nhave_patched_template_render = False\nhave_patched_template_render_async = False\n\n\ndef ensure_installed():\n    global have_patched_environment_init\n    global have_patched_template_render\n\n    logger.info(\"Ensuring Jinja2 instrumentation is installed.\")\n\n    if Template is None:\n        logger.info(\"Unable to import jinja2.Template\")\n        return\n\n    if not have_patched_environment_init:\n        try:\n            Environment.__init__ = wrapped_environment_init(Environment.__init__)\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument jinja2.Environment.__init__: %r\",\n                exc,\n                exc_info=exc,\n            )\n        else:\n            have_patched_environment_init = True\n\n    if not have_patched_template_render:\n        try:\n            Template.render = wrapped_render(Template.render)\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument jinja2.Template.render: %r\", exc, exc_info=exc\n            )\n        else:\n            have_patched_template_render = True\n\n\n@wrapt.decorator\ndef wrapped_render(wrapped, instance, args, kwargs):\n    tracked_request = TrackedRequest.instance()\n    span = tracked_request.start_span(operation=\"Template/Render\")\n    span.tag(\"name\", instance.name)\n    try:\n        return wrapped(*args, **kwargs)\n    finally:\n        tracked_request.stop_span()\n\n\n@wrapt.decorator\ndef wrapped_environment_init(wrapped, instance, args, kwargs):\n    \"\"\"\n    Delayed wrapping of render_async(), since Template won't have this method\n    until after jinja2.asyncsupport is imported, which since Jinja2 2.11.0 is\n    done conditionally in Environment.__init__:\n    https://github.com/pallets/jinja/issues/765\n    \"\"\"\n    global have_patched_template_render_async\n    result = wrapped(*args, **kwargs)\n\n    if (\n        wrapped_render_async is not None\n        and not have_patched_template_render_async\n        and \"jinja2.asyncsupport\" in sys.modules\n    ):\n        try:\n            Template.render_async = wrapped_render_async(Template.render_async)\n        except Exception as exc:\n            logger.warning(\n                \"Unable to instrument jinja2.Template.render_async: %r\",\n                exc,\n                exc_info=exc,\n            )\n        else:\n            have_patched_template_render_async = True\n\n    return result\n", "path": "src/scout_apm/instruments/jinja2.py"}]}