prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  feature: Support authenticating to Azure state backend without a connection string
  ### Feature scope
  
  State backend
  
  ### Description
  
  https://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python?tabs=managed-identity%2Croles-azure-portal%2Csign-in-azure-cli#sign-in-and-connect-your-app-code-to-azure-using-defaultazurecredential
  
  See request in
  
  * Slack: https://meltano.slack.com/archives/CMN8HELB0/p1692386533863739?thread_ts=1692366917.319929&cid=CMN8HELB0
  * Linen: https://www.linen.dev/s/meltano/t/15516560/hey-i-m-a-bit-confused-how-to-set-the-state-id-when-using-me#d65c3bd0-9e62-48dd-a616-90d4d7246d33
  
  --- 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/meltano/core/state_store/azure.py`
  Content:
  ```
  1 """StateStoreManager for Azure Blob storage backend."""
  2 from __future__ import annotations
  3 
  4 from collections.abc import Iterator
  5 from contextlib import contextmanager
  6 from functools import cached_property
  7 
  8 from meltano.core.error import MeltanoError
  9 from meltano.core.state_store.filesystem import (
  10     CloudStateStoreManager,
  11 )
  12 
  13 AZURE_INSTALLED = True
  14 
  15 try:
  16     from azure.storage.blob import BlobServiceClient
  17 except ImportError:
  18     AZURE_INSTALLED = False
  19 
  20 
  21 class MissingAzureError(Exception):
  22     """Raised when azure is required but no installed."""
  23 
  24     def __init__(self):
  25         """Initialize a MissingAzureError."""
  26         super().__init__(
  27             "azure required but not installed. Install meltano[azure] to use Azure Blob Storage as a state backend.",  # noqa: E501
  28         )
  29 
  30 
  31 @contextmanager
  32 def requires_azure():
  33     """Raise MissingAzureError if azure is required but missing in context.
  34 
  35     Raises:
  36         MissingAzureError: if azure is not installed.
  37 
  38     Yields:
  39         None
  40     """
  41     if not AZURE_INSTALLED:
  42         raise MissingAzureError
  43     yield
  44 
  45 
  46 class AZStorageStateStoreManager(CloudStateStoreManager):
  47     """State backend for Azure Blob Storage."""
  48 
  49     label: str = "Azure Blob Storage"
  50 
  51     def __init__(
  52         self,
  53         connection_string: str | None = None,
  54         prefix: str | None = None,
  55         **kwargs,
  56     ):
  57         """Initialize the BaseFilesystemStateStoreManager.
  58 
  59         Args:
  60             connection_string: connection string to use in authenticating to Azure
  61             prefix: the prefix to store state at
  62             kwargs: additional keyword args to pass to parent
  63 
  64         Raises:
  65             MeltanoError: If container name is not included in the URI.
  66         """
  67         super().__init__(**kwargs)
  68         self.connection_string = connection_string
  69 
  70         if not self.parsed.hostname:
  71             raise MeltanoError(
  72                 f"Azure state backend URI must include a container name: {self.uri}",
  73                 "Verify state backend URI. Must be in the form of azure://<container>/<prefix>",  # noqa: E501
  74             )
  75 
  76         self.container_name = self.parsed.hostname
  77         self.prefix = prefix or self.parsed.path
  78 
  79     @staticmethod
  80     def is_file_not_found_error(err: Exception) -> bool:
  81         """Check if err is equivalent to file not being found.
  82 
  83         Args:
  84             err: the err to check
  85 
  86         Returns:
  87             True if error represents file not being found, else False
  88         """
  89         from azure.core.exceptions import ResourceNotFoundError
  90 
  91         return (
  92             isinstance(err, ResourceNotFoundError)
  93             and "ErrorCode:BlobNotFound" in err.args[0]
  94         )
  95 
  96     @cached_property
  97     def client(self) -> BlobServiceClient:
  98         """Get an authenticated azure.storage.blob.BlobServiceClient.
  99 
  100         Returns:
  101             An authenticated azure.storage.blob.BlobServiceClient
  102 
  103         Raises:
  104             MeltanoError: If connection string is not provided.
  105         """
  106         with requires_azure():
  107             if self.connection_string:
  108                 return BlobServiceClient.from_connection_string(self.connection_string)
  109 
  110             raise MeltanoError(
  111                 "Azure state backend requires a connection string",
  112                 "Read https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string for more information.",  # noqa: E501
  113             )
  114 
  115     def delete(self, file_path: str):
  116         """Delete the file/blob at the given path.
  117 
  118         Args:
  119             file_path: the path to delete.
  120 
  121         Raises:
  122             Exception: if error not indicating file is not found is thrown
  123         """
  124         blob_client = self.client.get_blob_client(
  125             container=self.container_name,
  126             blob=file_path,
  127         )
  128         try:
  129             blob_client.delete_blob()
  130         except Exception as e:
  131             if not self.is_file_not_found_error(e):
  132                 raise e
  133 
  134     def list_all_files(self) -> Iterator[str]:
  135         """List all files in the backend.
  136 
  137         Yields:
  138             The next file in the backend.
  139         """
  140         container_client = self.client.get_container_client(self.container_name)
  141         for blob in container_client.list_blobs(  # noqa: WPS526
  142             name_starts_with=self.prefix.lstrip("/"),
  143         ):
  144             yield blob.name
  145 
  146     def copy_file(self, src: str, dst: str) -> None:
  147         """Copy a file from one location to another.
  148 
  149         Args:
  150             src: the source path
  151             dst: the destination path
  152         """
  153         container_client = self.client.get_container_client(self.container_name)
  154         src_blob_client = container_client.get_blob_client(src)
  155         dst_blob_client = container_client.get_blob_client(dst)
  156         dst_blob_client.start_copy_from_url(src_blob_client.url)
  157
  ```
  --- 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/meltano/core/state_store/azure.py b/src/meltano/core/state_store/azure.py
  --- a/src/meltano/core/state_store/azure.py
  +++ b/src/meltano/core/state_store/azure.py
  @@ -52,6 +52,7 @@
           self,
           connection_string: str | None = None,
           prefix: str | None = None,
  +        storage_account_url: str | None = None,
           **kwargs,
       ):
           """Initialize the BaseFilesystemStateStoreManager.
  @@ -59,6 +60,7 @@
           Args:
               connection_string: connection string to use in authenticating to Azure
               prefix: the prefix to store state at
  +            storage_account_url: url of the azure stroga account
               kwargs: additional keyword args to pass to parent
   
           Raises:
  @@ -66,6 +68,7 @@
           """
           super().__init__(**kwargs)
           self.connection_string = connection_string
  +        self.storage_account_url = storage_account_url
   
           if not self.parsed.hostname:
               raise MeltanoError(
  @@ -104,11 +107,21 @@
               MeltanoError: If connection string is not provided.
           """
           with requires_azure():
  +            if self.storage_account_url:
  +                from azure.identity import DefaultAzureCredential
  +
  +                default_credential = DefaultAzureCredential()
  +                return BlobServiceClient(
  +                    self.storage_account_url,
  +                    credential=default_credential,
  +                )
  +
               if self.connection_string:
                   return BlobServiceClient.from_connection_string(self.connection_string)
   
               raise MeltanoError(
  -                "Azure state backend requires a connection string",
  +                "Azure state backend requires a connection string "
  +                "or an account URL to use host credentials",
                   "Read https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string for more information.",  # noqa: E501
               )
  
verification_info: {"golden_diff": "diff --git a/src/meltano/core/state_store/azure.py b/src/meltano/core/state_store/azure.py\n--- a/src/meltano/core/state_store/azure.py\n+++ b/src/meltano/core/state_store/azure.py\n@@ -52,6 +52,7 @@\n         self,\n         connection_string: str | None = None,\n         prefix: str | None = None,\n+        storage_account_url: str | None = None,\n         **kwargs,\n     ):\n         \"\"\"Initialize the BaseFilesystemStateStoreManager.\n@@ -59,6 +60,7 @@\n         Args:\n             connection_string: connection string to use in authenticating to Azure\n             prefix: the prefix to store state at\n+            storage_account_url: url of the azure stroga account\n             kwargs: additional keyword args to pass to parent\n \n         Raises:\n@@ -66,6 +68,7 @@\n         \"\"\"\n         super().__init__(**kwargs)\n         self.connection_string = connection_string\n+        self.storage_account_url = storage_account_url\n \n         if not self.parsed.hostname:\n             raise MeltanoError(\n@@ -104,11 +107,21 @@\n             MeltanoError: If connection string is not provided.\n         \"\"\"\n         with requires_azure():\n+            if self.storage_account_url:\n+                from azure.identity import DefaultAzureCredential\n+\n+                default_credential = DefaultAzureCredential()\n+                return BlobServiceClient(\n+                    self.storage_account_url,\n+                    credential=default_credential,\n+                )\n+\n             if self.connection_string:\n                 return BlobServiceClient.from_connection_string(self.connection_string)\n \n             raise MeltanoError(\n-                \"Azure state backend requires a connection string\",\n+                \"Azure state backend requires a connection string \"\n+                \"or an account URL to use host credentials\",\n                 \"Read https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string for more information.\",  # noqa: E501\n             )\n", "issue": "feature: Support authenticating to Azure state backend without a connection string\n### Feature scope\r\n\r\nState backend\r\n\r\n### Description\r\n\r\nhttps://learn.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-python?tabs=managed-identity%2Croles-azure-portal%2Csign-in-azure-cli#sign-in-and-connect-your-app-code-to-azure-using-defaultazurecredential\r\n\r\nSee request in\r\n\r\n* Slack: https://meltano.slack.com/archives/CMN8HELB0/p1692386533863739?thread_ts=1692366917.319929&cid=CMN8HELB0\r\n* Linen: https://www.linen.dev/s/meltano/t/15516560/hey-i-m-a-bit-confused-how-to-set-the-state-id-when-using-me#d65c3bd0-9e62-48dd-a616-90d4d7246d33\n", "before_files": [{"content": "\"\"\"StateStoreManager for Azure Blob storage backend.\"\"\"\nfrom __future__ import annotations\n\nfrom collections.abc import Iterator\nfrom contextlib import contextmanager\nfrom functools import cached_property\n\nfrom meltano.core.error import MeltanoError\nfrom meltano.core.state_store.filesystem import (\n    CloudStateStoreManager,\n)\n\nAZURE_INSTALLED = True\n\ntry:\n    from azure.storage.blob import BlobServiceClient\nexcept ImportError:\n    AZURE_INSTALLED = False\n\n\nclass MissingAzureError(Exception):\n    \"\"\"Raised when azure is required but no installed.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize a MissingAzureError.\"\"\"\n        super().__init__(\n            \"azure required but not installed. Install meltano[azure] to use Azure Blob Storage as a state backend.\",  # noqa: E501\n        )\n\n\n@contextmanager\ndef requires_azure():\n    \"\"\"Raise MissingAzureError if azure is required but missing in context.\n\n    Raises:\n        MissingAzureError: if azure is not installed.\n\n    Yields:\n        None\n    \"\"\"\n    if not AZURE_INSTALLED:\n        raise MissingAzureError\n    yield\n\n\nclass AZStorageStateStoreManager(CloudStateStoreManager):\n    \"\"\"State backend for Azure Blob Storage.\"\"\"\n\n    label: str = \"Azure Blob Storage\"\n\n    def __init__(\n        self,\n        connection_string: str | None = None,\n        prefix: str | None = None,\n        **kwargs,\n    ):\n        \"\"\"Initialize the BaseFilesystemStateStoreManager.\n\n        Args:\n            connection_string: connection string to use in authenticating to Azure\n            prefix: the prefix to store state at\n            kwargs: additional keyword args to pass to parent\n\n        Raises:\n            MeltanoError: If container name is not included in the URI.\n        \"\"\"\n        super().__init__(**kwargs)\n        self.connection_string = connection_string\n\n        if not self.parsed.hostname:\n            raise MeltanoError(\n                f\"Azure state backend URI must include a container name: {self.uri}\",\n                \"Verify state backend URI. Must be in the form of azure://<container>/<prefix>\",  # noqa: E501\n            )\n\n        self.container_name = self.parsed.hostname\n        self.prefix = prefix or self.parsed.path\n\n    @staticmethod\n    def is_file_not_found_error(err: Exception) -> bool:\n        \"\"\"Check if err is equivalent to file not being found.\n\n        Args:\n            err: the err to check\n\n        Returns:\n            True if error represents file not being found, else False\n        \"\"\"\n        from azure.core.exceptions import ResourceNotFoundError\n\n        return (\n            isinstance(err, ResourceNotFoundError)\n            and \"ErrorCode:BlobNotFound\" in err.args[0]\n        )\n\n    @cached_property\n    def client(self) -> BlobServiceClient:\n        \"\"\"Get an authenticated azure.storage.blob.BlobServiceClient.\n\n        Returns:\n            An authenticated azure.storage.blob.BlobServiceClient\n\n        Raises:\n            MeltanoError: If connection string is not provided.\n        \"\"\"\n        with requires_azure():\n            if self.connection_string:\n                return BlobServiceClient.from_connection_string(self.connection_string)\n\n            raise MeltanoError(\n                \"Azure state backend requires a connection string\",\n                \"Read https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string for more information.\",  # noqa: E501\n            )\n\n    def delete(self, file_path: str):\n        \"\"\"Delete the file/blob at the given path.\n\n        Args:\n            file_path: the path to delete.\n\n        Raises:\n            Exception: if error not indicating file is not found is thrown\n        \"\"\"\n        blob_client = self.client.get_blob_client(\n            container=self.container_name,\n            blob=file_path,\n        )\n        try:\n            blob_client.delete_blob()\n        except Exception as e:\n            if not self.is_file_not_found_error(e):\n                raise e\n\n    def list_all_files(self) -> Iterator[str]:\n        \"\"\"List all files in the backend.\n\n        Yields:\n            The next file in the backend.\n        \"\"\"\n        container_client = self.client.get_container_client(self.container_name)\n        for blob in container_client.list_blobs(  # noqa: WPS526\n            name_starts_with=self.prefix.lstrip(\"/\"),\n        ):\n            yield blob.name\n\n    def copy_file(self, src: str, dst: str) -> None:\n        \"\"\"Copy a file from one location to another.\n\n        Args:\n            src: the source path\n            dst: the destination path\n        \"\"\"\n        container_client = self.client.get_container_client(self.container_name)\n        src_blob_client = container_client.get_blob_client(src)\n        dst_blob_client = container_client.get_blob_client(dst)\n        dst_blob_client.start_copy_from_url(src_blob_client.url)\n", "path": "src/meltano/core/state_store/azure.py"}], "after_files": [{"content": "\"\"\"StateStoreManager for Azure Blob storage backend.\"\"\"\nfrom __future__ import annotations\n\nfrom collections.abc import Iterator\nfrom contextlib import contextmanager\nfrom functools import cached_property\n\nfrom meltano.core.error import MeltanoError\nfrom meltano.core.state_store.filesystem import (\n    CloudStateStoreManager,\n)\n\nAZURE_INSTALLED = True\n\ntry:\n    from azure.storage.blob import BlobServiceClient\nexcept ImportError:\n    AZURE_INSTALLED = False\n\n\nclass MissingAzureError(Exception):\n    \"\"\"Raised when azure is required but no installed.\"\"\"\n\n    def __init__(self):\n        \"\"\"Initialize a MissingAzureError.\"\"\"\n        super().__init__(\n            \"azure required but not installed. Install meltano[azure] to use Azure Blob Storage as a state backend.\",  # noqa: E501\n        )\n\n\n@contextmanager\ndef requires_azure():\n    \"\"\"Raise MissingAzureError if azure is required but missing in context.\n\n    Raises:\n        MissingAzureError: if azure is not installed.\n\n    Yields:\n        None\n    \"\"\"\n    if not AZURE_INSTALLED:\n        raise MissingAzureError\n    yield\n\n\nclass AZStorageStateStoreManager(CloudStateStoreManager):\n    \"\"\"State backend for Azure Blob Storage.\"\"\"\n\n    label: str = \"Azure Blob Storage\"\n\n    def __init__(\n        self,\n        connection_string: str | None = None,\n        prefix: str | None = None,\n        storage_account_url: str | None = None,\n        **kwargs,\n    ):\n        \"\"\"Initialize the BaseFilesystemStateStoreManager.\n\n        Args:\n            connection_string: connection string to use in authenticating to Azure\n            prefix: the prefix to store state at\n            storage_account_url: url of the azure stroga account\n            kwargs: additional keyword args to pass to parent\n\n        Raises:\n            MeltanoError: If container name is not included in the URI.\n        \"\"\"\n        super().__init__(**kwargs)\n        self.connection_string = connection_string\n        self.storage_account_url = storage_account_url\n\n        if not self.parsed.hostname:\n            raise MeltanoError(\n                f\"Azure state backend URI must include a container name: {self.uri}\",\n                \"Verify state backend URI. Must be in the form of azure://<container>/<prefix>\",  # noqa: E501\n            )\n\n        self.container_name = self.parsed.hostname\n        self.prefix = prefix or self.parsed.path\n\n    @staticmethod\n    def is_file_not_found_error(err: Exception) -> bool:\n        \"\"\"Check if err is equivalent to file not being found.\n\n        Args:\n            err: the err to check\n\n        Returns:\n            True if error represents file not being found, else False\n        \"\"\"\n        from azure.core.exceptions import ResourceNotFoundError\n\n        return (\n            isinstance(err, ResourceNotFoundError)\n            and \"ErrorCode:BlobNotFound\" in err.args[0]\n        )\n\n    @cached_property\n    def client(self) -> BlobServiceClient:\n        \"\"\"Get an authenticated azure.storage.blob.BlobServiceClient.\n\n        Returns:\n            An authenticated azure.storage.blob.BlobServiceClient\n\n        Raises:\n            MeltanoError: If connection string is not provided.\n        \"\"\"\n        with requires_azure():\n            if self.storage_account_url:\n                from azure.identity import DefaultAzureCredential\n\n                default_credential = DefaultAzureCredential()\n                return BlobServiceClient(\n                    self.storage_account_url,\n                    credential=default_credential,\n                )\n\n            if self.connection_string:\n                return BlobServiceClient.from_connection_string(self.connection_string)\n\n            raise MeltanoError(\n                \"Azure state backend requires a connection string \"\n                \"or an account URL to use host credentials\",\n                \"Read https://learn.microsoft.com/en-us/azure/storage/common/storage-configure-connection-string for more information.\",  # noqa: E501\n            )\n\n    def delete(self, file_path: str):\n        \"\"\"Delete the file/blob at the given path.\n\n        Args:\n            file_path: the path to delete.\n\n        Raises:\n            Exception: if error not indicating file is not found is thrown\n        \"\"\"\n        blob_client = self.client.get_blob_client(\n            container=self.container_name,\n            blob=file_path,\n        )\n        try:\n            blob_client.delete_blob()\n        except Exception as e:\n            if not self.is_file_not_found_error(e):\n                raise e\n\n    def list_all_files(self) -> Iterator[str]:\n        \"\"\"List all files in the backend.\n\n        Yields:\n            The next file in the backend.\n        \"\"\"\n        container_client = self.client.get_container_client(self.container_name)\n        for blob in container_client.list_blobs(  # noqa: WPS526\n            name_starts_with=self.prefix.lstrip(\"/\"),\n        ):\n            yield blob.name\n\n    def copy_file(self, src: str, dst: str) -> None:\n        \"\"\"Copy a file from one location to another.\n\n        Args:\n            src: the source path\n            dst: the destination path\n        \"\"\"\n        container_client = self.client.get_container_client(self.container_name)\n        src_blob_client = container_client.get_blob_client(src)\n        dst_blob_client = container_client.get_blob_client(dst)\n        dst_blob_client.start_copy_from_url(src_blob_client.url)\n", "path": "src/meltano/core/state_store/azure.py"}]}