prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Consider making `starlette.templating.Jinja2Templates.get_env` "protected"
  Hi,
  Thank you very much for your project! We are using it intensively through FastAPI.
  
  While I was exploring the code base and looking how to use `Jinja2Templates`, I noticed the method `get_env`. At first I thought it was a getter for the environment, but eventually realized it is only called in the constructor of the class.
  
  It would make much more sense to me if the method was called `_get_env`. This would signal that it should not be used outside of the class (or at least that the caller needs to know what she is doing).
  
  For example, if I want to add filters or globals to the environment, I should write:
  
  ```
  templates = Jinja2Templates(...)
  templates.env.globals[...] = ...
  ```
  
  instead of:
  
  ```
  templates = Jinja2Templates(...)
  templates.get_env().globals[...] = ...
  ```
  
  As of current implementation, the second snippet has no effect.
  
  Thank you very much for considering this request!
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `starlette/templating.py`
  Content:
  ```
  1 import typing
  2 
  3 from starlette.background import BackgroundTask
  4 from starlette.responses import Response
  5 from starlette.types import Receive, Scope, Send
  6 
  7 try:
  8     import jinja2
  9 
  10     # @contextfunction renamed to @pass_context in Jinja 3.0, to be removed in 3.1
  11     if hasattr(jinja2, "pass_context"):
  12         pass_context = jinja2.pass_context
  13     else:  # pragma: nocover
  14         pass_context = jinja2.contextfunction
  15 except ImportError:  # pragma: nocover
  16     jinja2 = None  # type: ignore
  17 
  18 
  19 class _TemplateResponse(Response):
  20     media_type = "text/html"
  21 
  22     def __init__(
  23         self,
  24         template: typing.Any,
  25         context: dict,
  26         status_code: int = 200,
  27         headers: dict = None,
  28         media_type: str = None,
  29         background: BackgroundTask = None,
  30     ):
  31         self.template = template
  32         self.context = context
  33         content = template.render(context)
  34         super().__init__(content, status_code, headers, media_type, background)
  35 
  36     async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
  37         request = self.context.get("request", {})
  38         extensions = request.get("extensions", {})
  39         if "http.response.template" in extensions:
  40             await send(
  41                 {
  42                     "type": "http.response.template",
  43                     "template": self.template,
  44                     "context": self.context,
  45                 }
  46             )
  47         await super().__call__(scope, receive, send)
  48 
  49 
  50 class Jinja2Templates:
  51     """
  52     templates = Jinja2Templates("templates")
  53 
  54     return templates.TemplateResponse("index.html", {"request": request})
  55     """
  56 
  57     def __init__(self, directory: str) -> None:
  58         assert jinja2 is not None, "jinja2 must be installed to use Jinja2Templates"
  59         self.env = self.get_env(directory)
  60 
  61     def get_env(self, directory: str) -> "jinja2.Environment":
  62         @pass_context
  63         def url_for(context: dict, name: str, **path_params: typing.Any) -> str:
  64             request = context["request"]
  65             return request.url_for(name, **path_params)
  66 
  67         loader = jinja2.FileSystemLoader(directory)
  68         env = jinja2.Environment(loader=loader, autoescape=True)
  69         env.globals["url_for"] = url_for
  70         return env
  71 
  72     def get_template(self, name: str) -> "jinja2.Template":
  73         return self.env.get_template(name)
  74 
  75     def TemplateResponse(
  76         self,
  77         name: str,
  78         context: dict,
  79         status_code: int = 200,
  80         headers: dict = None,
  81         media_type: str = None,
  82         background: BackgroundTask = None,
  83     ) -> _TemplateResponse:
  84         if "request" not in context:
  85             raise ValueError('context must include a "request" key')
  86         template = self.get_template(name)
  87         return _TemplateResponse(
  88             template,
  89             context,
  90             status_code=status_code,
  91             headers=headers,
  92             media_type=media_type,
  93             background=background,
  94         )
  95
  ```
  --- 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/starlette/templating.py b/starlette/templating.py
  --- a/starlette/templating.py
  +++ b/starlette/templating.py
  @@ -56,9 +56,9 @@
   
       def __init__(self, directory: str) -> None:
           assert jinja2 is not None, "jinja2 must be installed to use Jinja2Templates"
  -        self.env = self.get_env(directory)
  +        self.env = self._create_env(directory)
   
  -    def get_env(self, directory: str) -> "jinja2.Environment":
  +    def _create_env(self, directory: str) -> "jinja2.Environment":
           @pass_context
           def url_for(context: dict, name: str, **path_params: typing.Any) -> str:
               request = context["request"]
  
verification_info: {"golden_diff": "diff --git a/starlette/templating.py b/starlette/templating.py\n--- a/starlette/templating.py\n+++ b/starlette/templating.py\n@@ -56,9 +56,9 @@\n \n     def __init__(self, directory: str) -> None:\n         assert jinja2 is not None, \"jinja2 must be installed to use Jinja2Templates\"\n-        self.env = self.get_env(directory)\n+        self.env = self._create_env(directory)\n \n-    def get_env(self, directory: str) -> \"jinja2.Environment\":\n+    def _create_env(self, directory: str) -> \"jinja2.Environment\":\n         @pass_context\n         def url_for(context: dict, name: str, **path_params: typing.Any) -> str:\n             request = context[\"request\"]\n", "issue": "Consider making `starlette.templating.Jinja2Templates.get_env` \"protected\"\nHi,\r\nThank you very much for your project! We are using it intensively through FastAPI.\r\n\r\nWhile I was exploring the code base and looking how to use `Jinja2Templates`, I noticed the method `get_env`. At first I thought it was a getter for the environment, but eventually realized it is only called in the constructor of the class.\r\n\r\nIt would make much more sense to me if the method was called `_get_env`. This would signal that it should not be used outside of the class (or at least that the caller needs to know what she is doing).\r\n\r\nFor example, if I want to add filters or globals to the environment, I should write:\r\n\r\n```\r\ntemplates = Jinja2Templates(...)\r\ntemplates.env.globals[...] = ...\r\n```\r\n\r\ninstead of:\r\n\r\n```\r\ntemplates = Jinja2Templates(...)\r\ntemplates.get_env().globals[...] = ...\r\n```\r\n\r\nAs of current implementation, the second snippet has no effect.\r\n\r\nThank you very much for considering this request!\n", "before_files": [{"content": "import typing\n\nfrom starlette.background import BackgroundTask\nfrom starlette.responses import Response\nfrom starlette.types import Receive, Scope, Send\n\ntry:\n    import jinja2\n\n    # @contextfunction renamed to @pass_context in Jinja 3.0, to be removed in 3.1\n    if hasattr(jinja2, \"pass_context\"):\n        pass_context = jinja2.pass_context\n    else:  # pragma: nocover\n        pass_context = jinja2.contextfunction\nexcept ImportError:  # pragma: nocover\n    jinja2 = None  # type: ignore\n\n\nclass _TemplateResponse(Response):\n    media_type = \"text/html\"\n\n    def __init__(\n        self,\n        template: typing.Any,\n        context: dict,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n        background: BackgroundTask = None,\n    ):\n        self.template = template\n        self.context = context\n        content = template.render(context)\n        super().__init__(content, status_code, headers, media_type, background)\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        request = self.context.get(\"request\", {})\n        extensions = request.get(\"extensions\", {})\n        if \"http.response.template\" in extensions:\n            await send(\n                {\n                    \"type\": \"http.response.template\",\n                    \"template\": self.template,\n                    \"context\": self.context,\n                }\n            )\n        await super().__call__(scope, receive, send)\n\n\nclass Jinja2Templates:\n    \"\"\"\n    templates = Jinja2Templates(\"templates\")\n\n    return templates.TemplateResponse(\"index.html\", {\"request\": request})\n    \"\"\"\n\n    def __init__(self, directory: str) -> None:\n        assert jinja2 is not None, \"jinja2 must be installed to use Jinja2Templates\"\n        self.env = self.get_env(directory)\n\n    def get_env(self, directory: str) -> \"jinja2.Environment\":\n        @pass_context\n        def url_for(context: dict, name: str, **path_params: typing.Any) -> str:\n            request = context[\"request\"]\n            return request.url_for(name, **path_params)\n\n        loader = jinja2.FileSystemLoader(directory)\n        env = jinja2.Environment(loader=loader, autoescape=True)\n        env.globals[\"url_for\"] = url_for\n        return env\n\n    def get_template(self, name: str) -> \"jinja2.Template\":\n        return self.env.get_template(name)\n\n    def TemplateResponse(\n        self,\n        name: str,\n        context: dict,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n        background: BackgroundTask = None,\n    ) -> _TemplateResponse:\n        if \"request\" not in context:\n            raise ValueError('context must include a \"request\" key')\n        template = self.get_template(name)\n        return _TemplateResponse(\n            template,\n            context,\n            status_code=status_code,\n            headers=headers,\n            media_type=media_type,\n            background=background,\n        )\n", "path": "starlette/templating.py"}], "after_files": [{"content": "import typing\n\nfrom starlette.background import BackgroundTask\nfrom starlette.responses import Response\nfrom starlette.types import Receive, Scope, Send\n\ntry:\n    import jinja2\n\n    # @contextfunction renamed to @pass_context in Jinja 3.0, to be removed in 3.1\n    if hasattr(jinja2, \"pass_context\"):\n        pass_context = jinja2.pass_context\n    else:  # pragma: nocover\n        pass_context = jinja2.contextfunction\nexcept ImportError:  # pragma: nocover\n    jinja2 = None  # type: ignore\n\n\nclass _TemplateResponse(Response):\n    media_type = \"text/html\"\n\n    def __init__(\n        self,\n        template: typing.Any,\n        context: dict,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n        background: BackgroundTask = None,\n    ):\n        self.template = template\n        self.context = context\n        content = template.render(context)\n        super().__init__(content, status_code, headers, media_type, background)\n\n    async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:\n        request = self.context.get(\"request\", {})\n        extensions = request.get(\"extensions\", {})\n        if \"http.response.template\" in extensions:\n            await send(\n                {\n                    \"type\": \"http.response.template\",\n                    \"template\": self.template,\n                    \"context\": self.context,\n                }\n            )\n        await super().__call__(scope, receive, send)\n\n\nclass Jinja2Templates:\n    \"\"\"\n    templates = Jinja2Templates(\"templates\")\n\n    return templates.TemplateResponse(\"index.html\", {\"request\": request})\n    \"\"\"\n\n    def __init__(self, directory: str) -> None:\n        assert jinja2 is not None, \"jinja2 must be installed to use Jinja2Templates\"\n        self.env = self._create_env(directory)\n\n    def _create_env(self, directory: str) -> \"jinja2.Environment\":\n        @pass_context\n        def url_for(context: dict, name: str, **path_params: typing.Any) -> str:\n            request = context[\"request\"]\n            return request.url_for(name, **path_params)\n\n        loader = jinja2.FileSystemLoader(directory)\n        env = jinja2.Environment(loader=loader, autoescape=True)\n        env.globals[\"url_for\"] = url_for\n        return env\n\n    def get_template(self, name: str) -> \"jinja2.Template\":\n        return self.env.get_template(name)\n\n    def TemplateResponse(\n        self,\n        name: str,\n        context: dict,\n        status_code: int = 200,\n        headers: dict = None,\n        media_type: str = None,\n        background: BackgroundTask = None,\n    ) -> _TemplateResponse:\n        if \"request\" not in context:\n            raise ValueError('context must include a \"request\" key')\n        template = self.get_template(name)\n        return _TemplateResponse(\n            template,\n            context,\n            status_code=status_code,\n            headers=headers,\n            media_type=media_type,\n            background=background,\n        )\n", "path": "starlette/templating.py"}]}