We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Deprecation warning raised by hvac
**Describe the bug**
Using the latest version of dynaconf along with the Hashicorp Vault integration, we get the following deprecation warning.
```
/opt/app-root/lib64/python3.11/site-packages/dynaconf/loaders/vault_loader.py:101: DeprecationWarning: The raise_on_deleted parameter will change its default value to False in hvac v3.0.0. The current default of True will presere previous behavior. To use the old behavior with no warning, explicitly set this value to True. See https://github.com/hvac/hvac/pull/907
      data = client.secrets.kv.v2.read_secret_version(
```

**To Reproduce**
Steps to reproduce the behavior:
Create a LazySettings object using the Vault integration.


**Expected behavior**
no deprecation warning

**Environment (please complete the following information):**
hvac==1.0.2
dynaconf==3.1.12

**Additional context**
This is not exactly a bug, but something that should be addressed before hvac 3.0.0 gets out


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dynaconf/loaders/redis_loader.py`
Content:
```
1 from __future__ import annotations
2 
3 from dynaconf.loaders.base import SourceMetadata
4 from dynaconf.utils import build_env_list
5 from dynaconf.utils import upperfy
6 from dynaconf.utils.parse_conf import parse_conf_data
7 from dynaconf.utils.parse_conf import unparse_conf_data
8 
9 try:
10     from redis import StrictRedis
11 except ImportError:
12     StrictRedis = None
13 
14 IDENTIFIER = "redis"
15 
16 
17 def load(obj, env=None, silent=True, key=None, validate=False):
18     """Reads and loads in to "settings" a single key or all keys from redis
19 
20     :param obj: the settings instance
21     :param env: settings env default='DYNACONF'
22     :param silent: if errors should raise
23     :param key: if defined load a single key, else load all in env
24     :return: None
25     """
26     if StrictRedis is None:
27         raise ImportError(
28             "redis package is not installed in your environment. "
29             "`pip install dynaconf[redis]` or disable the redis loader with "
30             "export REDIS_ENABLED_FOR_DYNACONF=false"
31         )
32 
33     redis = StrictRedis(**obj.get("REDIS_FOR_DYNACONF"))
34     prefix = obj.get("ENVVAR_PREFIX_FOR_DYNACONF")
35     # prefix is added to env_list to keep backwards compatibility
36     env_list = [prefix] + build_env_list(obj, env or obj.current_env)
37     for env_name in env_list:
38         holder = f"{prefix.upper()}_{env_name.upper()}"
39         try:
40             source_metadata = SourceMetadata(IDENTIFIER, "unique", env_name)
41             if key:
42                 value = redis.hget(holder.upper(), key)
43                 if value:
44                     parsed_value = parse_conf_data(
45                         value, tomlfy=True, box_settings=obj
46                     )
47                     if parsed_value:
48                         obj.set(
49                             key,
50                             parsed_value,
51                             validate=validate,
52                             loader_identifier=source_metadata,
53                         )
54             else:
55                 data = {
56                     key: parse_conf_data(value, tomlfy=True, box_settings=obj)
57                     for key, value in redis.hgetall(holder.upper()).items()
58                 }
59                 if data:
60                     obj.update(
61                         data,
62                         loader_identifier=source_metadata,
63                         validate=validate,
64                     )
65         except Exception:
66             if silent:
67                 return False
68             raise
69 
70 
71 def write(obj, data=None, **kwargs):
72     """Write a value in to loader source
73 
74     :param obj: settings object
75     :param data: vars to be stored
76     :param kwargs: vars to be stored
77     :return:
78     """
79     if obj.REDIS_ENABLED_FOR_DYNACONF is False:
80         raise RuntimeError(
81             "Redis is not configured \n"
82             "export REDIS_ENABLED_FOR_DYNACONF=true\n"
83             "and configure the REDIS_*_FOR_DYNACONF variables"
84         )
85     client = StrictRedis(**obj.REDIS_FOR_DYNACONF)
86     holder = obj.get("ENVVAR_PREFIX_FOR_DYNACONF").upper()
87     # add env to holder
88     holder = f"{holder}_{obj.current_env.upper()}"
89 
90     data = data or {}
91     data.update(kwargs)
92     if not data:
93         raise AttributeError("Data must be provided")
94     redis_data = {
95         upperfy(key): unparse_conf_data(value) for key, value in data.items()
96     }
97     client.hmset(holder.upper(), redis_data)
98     load(obj)
99 
100 
101 def delete(obj, key=None):
102     """
103     Delete a single key if specified, or all env if key is none
104     :param obj: settings object
105     :param key: key to delete from store location
106     :return: None
107     """
108     client = StrictRedis(**obj.REDIS_FOR_DYNACONF)
109     holder = obj.get("ENVVAR_PREFIX_FOR_DYNACONF").upper()
110     # add env to holder
111     holder = f"{holder}_{obj.current_env.upper()}"
112 
113     if key:
114         client.hdel(holder.upper(), upperfy(key))
115         obj.unset(key)
116     else:
117         keys = client.hkeys(holder.upper())
118         client.delete(holder.upper())
119         obj.unset_all(keys)
120
```

Path: `dynaconf/loaders/vault_loader.py`
Content:
```
1 # docker run -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -p 8200:8200 vault
2 # pip install hvac
3 from __future__ import annotations
4 
5 from dynaconf.loaders.base import SourceMetadata
6 from dynaconf.utils import build_env_list
7 from dynaconf.utils.parse_conf import parse_conf_data
8 
9 try:
10     import boto3
11 except ImportError:
12     boto3 = None
13 
14 try:
15     from hvac import Client
16     from hvac.exceptions import InvalidPath, Forbidden
17 except ImportError:
18     raise ImportError(
19         "vault package is not installed in your environment. "
20         "`pip install dynaconf[vault]` or disable the vault loader with "
21         "export VAULT_ENABLED_FOR_DYNACONF=false"
22     )
23 
24 
25 IDENTIFIER = "vault"
26 
27 
28 # backwards compatibility
29 _get_env_list = build_env_list
30 
31 
32 def get_client(obj):
33     client = Client(
34         **{k: v for k, v in obj.VAULT_FOR_DYNACONF.items() if v is not None}
35     )
36     if obj.VAULT_ROLE_ID_FOR_DYNACONF is not None:
37         client.auth.approle.login(
38             role_id=obj.VAULT_ROLE_ID_FOR_DYNACONF,
39             secret_id=obj.get("VAULT_SECRET_ID_FOR_DYNACONF"),
40         )
41     elif obj.VAULT_ROOT_TOKEN_FOR_DYNACONF is not None:
42         client.token = obj.VAULT_ROOT_TOKEN_FOR_DYNACONF
43     elif obj.VAULT_USERNAME_FOR_DYNACONF is not None:
44         client.auth.userpass.login(
45             username=obj.VAULT_USERNAME_FOR_DYNACONF,
46             password=obj.VAULT_PASSWORD_FOR_DYNACONF,
47         )
48 
49     elif obj.VAULT_AUTH_WITH_IAM_FOR_DYNACONF:
50         if boto3 is None:
51             raise ImportError(
52                 "boto3 package is not installed in your environment. "
53                 "`pip install boto3` or disable the VAULT_AUTH_WITH_IAM"
54             )
55 
56         session = boto3.Session()
57         credentials = session.get_credentials()
58         client.auth.aws.iam_login(
59             credentials.access_key,
60             credentials.secret_key,
61             credentials.token,
62             role=obj.VAULT_AUTH_ROLE_FOR_DYNACONF,
63         )
64     assert client.is_authenticated(), (
65         "Vault authentication error: is VAULT_TOKEN_FOR_DYNACONF or "
66         "VAULT_ROLE_ID_FOR_DYNACONF defined?"
67     )
68     client.secrets.kv.default_kv_version = obj.VAULT_KV_VERSION_FOR_DYNACONF
69     return client
70 
71 
72 def load(obj, env=None, silent=None, key=None, validate=False):
73     """Reads and loads in to "settings" a single key or all keys from vault
74 
75     :param obj: the settings instance
76     :param env: settings env default='DYNACONF'
77     :param silent: if errors should raise
78     :param key: if defined load a single key, else load all in env
79     :return: None
80     """
81     client = get_client(obj)
82     try:
83         if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:
84             dirs = client.secrets.kv.v2.list_secrets(
85                 path=obj.VAULT_PATH_FOR_DYNACONF,
86                 mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,
87             )["data"]["keys"]
88         else:
89             dirs = client.secrets.kv.v1.list_secrets(
90                 path=obj.VAULT_PATH_FOR_DYNACONF,
91                 mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,
92             )["data"]["keys"]
93     except InvalidPath:
94         # The given path is not a directory
95         dirs = []
96     except Forbidden:
97         # The given token does not have permission to list the given path
98         dirs = []
99     # First look for secrets into environments less store
100     if not obj.ENVIRONMENTS_FOR_DYNACONF:
101         # By adding '', dynaconf will now read secrets from environments-less
102         # store which are not written by `dynaconf write` to Vault store
103         env_list = [obj.MAIN_ENV_FOR_DYNACONF.lower(), ""]
104     # Finally, look for secret into all the environments
105     else:
106         env_list = dirs + build_env_list(obj, env)
107     for env in env_list:
108         path = "/".join([obj.VAULT_PATH_FOR_DYNACONF, env])
109         try:
110             if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:
111                 data = client.secrets.kv.v2.read_secret_version(
112                     path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF
113                 )
114             else:
115                 data = client.secrets.kv.read_secret(
116                     "data/" + path,
117                     mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,
118                 )
119         except InvalidPath:
120             # If the path doesn't exist, ignore it and set data to None
121             data = None
122         except Forbidden:
123             data = None
124         if data:
125             # There seems to be a data dict within a data dict,
126             # extract the inner data
127             data = data.get("data", {}).get("data", {})
128         try:
129             source_metadata = SourceMetadata(IDENTIFIER, "unique", env)
130             if (
131                 obj.VAULT_KV_VERSION_FOR_DYNACONF == 2
132                 and obj.ENVIRONMENTS_FOR_DYNACONF
133                 and data
134             ):
135                 data = data.get("data", {})
136             if data and key:
137                 value = parse_conf_data(
138                     data.get(key), tomlfy=True, box_settings=obj
139                 )
140                 if value:
141                     obj.set(
142                         key,
143                         value,
144                         validate=validate,
145                         loader_identifier=source_metadata,
146                     )
147             elif data:
148                 obj.update(
149                     data,
150                     loader_identifier=source_metadata,
151                     tomlfy=True,
152                     validate=validate,
153                 )
154         except Exception:
155             if silent:
156                 return False
157             raise
158 
159 
160 def write(obj, data=None, **kwargs):
161     """Write a value in to loader source
162 
163     :param obj: settings object
164     :param data: vars to be stored
165     :param kwargs: vars to be stored
166     :return:
167     """
168     if obj.VAULT_ENABLED_FOR_DYNACONF is False:
169         raise RuntimeError(
170             "Vault is not configured \n"
171             "export VAULT_ENABLED_FOR_DYNACONF=true\n"
172             "and configure the VAULT_FOR_DYNACONF_* variables"
173         )
174     data = data or {}
175     data.update(kwargs)
176     if not data:
177         raise AttributeError("Data must be provided")
178     data = {"data": data}
179     client = get_client(obj)
180     if obj.VAULT_KV_VERSION_FOR_DYNACONF == 1:
181         mount_point = obj.VAULT_MOUNT_POINT_FOR_DYNACONF + "/data"
182     else:
183         mount_point = obj.VAULT_MOUNT_POINT_FOR_DYNACONF
184     path = "/".join([obj.VAULT_PATH_FOR_DYNACONF, obj.current_env.lower()])
185     client.secrets.kv.create_or_update_secret(
186         path, secret=data, mount_point=mount_point
187     )
188     load(obj)
189 
190 
191 def list_envs(obj, path=""):
192     """
193     This function is a helper to get a list of all the existing envs in
194     the source of data, the use case is:
195         existing_envs = vault_loader.list_envs(settings)
196         for env in exiting_envs:
197             with settings.using_env(env):  # switch to the env
198             # do something with a key of that env
199 
200     :param obj: settings object
201     :param path: path to the vault secrets
202     :return: list containing all the keys at the given path
203     """
204     client = get_client(obj)
205     path = path or obj.get("VAULT_PATH_FOR_DYNACONF")
206     try:
207         return client.list(f"/secret/metadata/{path}")["data"]["keys"]
208     except TypeError:
209         return []
210
```
--- 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()

```

diff --git a/dynaconf/loaders/redis_loader.py b/dynaconf/loaders/redis_loader.py
--- a/dynaconf/loaders/redis_loader.py
+++ b/dynaconf/loaders/redis_loader.py
@@ -94,7 +94,7 @@
     redis_data = {
         upperfy(key): unparse_conf_data(value) for key, value in data.items()
     }
-    client.hmset(holder.upper(), redis_data)
+    client.hset(holder.upper(), mapping=redis_data)
     load(obj)
 
 
diff --git a/dynaconf/loaders/vault_loader.py b/dynaconf/loaders/vault_loader.py
--- a/dynaconf/loaders/vault_loader.py
+++ b/dynaconf/loaders/vault_loader.py
@@ -109,7 +109,9 @@
         try:
             if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:
                 data = client.secrets.kv.v2.read_secret_version(
-                    path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF
+                    path,
+                    mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,
+                    raise_on_deleted_version=True,  # keep default behavior
                 )
             else:
                 data = client.secrets.kv.read_secret(

{"golden_diff": "diff --git a/dynaconf/loaders/redis_loader.py b/dynaconf/loaders/redis_loader.py\n--- a/dynaconf/loaders/redis_loader.py\n+++ b/dynaconf/loaders/redis_loader.py\n@@ -94,7 +94,7 @@\n     redis_data = {\n         upperfy(key): unparse_conf_data(value) for key, value in data.items()\n     }\n-    client.hmset(holder.upper(), redis_data)\n+    client.hset(holder.upper(), mapping=redis_data)\n     load(obj)\n \n \ndiff --git a/dynaconf/loaders/vault_loader.py b/dynaconf/loaders/vault_loader.py\n--- a/dynaconf/loaders/vault_loader.py\n+++ b/dynaconf/loaders/vault_loader.py\n@@ -109,7 +109,9 @@\n         try:\n             if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:\n                 data = client.secrets.kv.v2.read_secret_version(\n-                    path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF\n+                    path,\n+                    mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n+                    raise_on_deleted_version=True,  # keep default behavior\n                 )\n             else:\n                 data = client.secrets.kv.read_secret(\n", "issue": "Deprecation warning raised by hvac\n**Describe the bug**\r\nUsing the latest version of dynaconf along with the Hashicorp Vault integration, we get the following deprecation warning.\r\n```\r\n/opt/app-root/lib64/python3.11/site-packages/dynaconf/loaders/vault_loader.py:101: DeprecationWarning: The raise_on_deleted parameter will change its default value to False in hvac v3.0.0. The current default of True will presere previous behavior. To use the old behavior with no warning, explicitly set this value to True. See https://github.com/hvac/hvac/pull/907\r\n      data = client.secrets.kv.v2.read_secret_version(\r\n```\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\nCreate a LazySettings object using the Vault integration.\r\n\r\n\r\n**Expected behavior**\r\nno deprecation warning\r\n\r\n**Environment (please complete the following information):**\r\nhvac==1.0.2\r\ndynaconf==3.1.12\r\n\r\n**Additional context**\r\nThis is not exactly a bug, but something that should be addressed before hvac 3.0.0 gets out\r\n\n", "before_files": [{"content": "from __future__ import annotations\n\nfrom dynaconf.loaders.base import SourceMetadata\nfrom dynaconf.utils import build_env_list\nfrom dynaconf.utils import upperfy\nfrom dynaconf.utils.parse_conf import parse_conf_data\nfrom dynaconf.utils.parse_conf import unparse_conf_data\n\ntry:\n    from redis import StrictRedis\nexcept ImportError:\n    StrictRedis = None\n\nIDENTIFIER = \"redis\"\n\n\ndef load(obj, env=None, silent=True, key=None, validate=False):\n    \"\"\"Reads and loads in to \"settings\" a single key or all keys from redis\n\n    :param obj: the settings instance\n    :param env: settings env default='DYNACONF'\n    :param silent: if errors should raise\n    :param key: if defined load a single key, else load all in env\n    :return: None\n    \"\"\"\n    if StrictRedis is None:\n        raise ImportError(\n            \"redis package is not installed in your environment. \"\n            \"`pip install dynaconf[redis]` or disable the redis loader with \"\n            \"export REDIS_ENABLED_FOR_DYNACONF=false\"\n        )\n\n    redis = StrictRedis(**obj.get(\"REDIS_FOR_DYNACONF\"))\n    prefix = obj.get(\"ENVVAR_PREFIX_FOR_DYNACONF\")\n    # prefix is added to env_list to keep backwards compatibility\n    env_list = [prefix] + build_env_list(obj, env or obj.current_env)\n    for env_name in env_list:\n        holder = f\"{prefix.upper()}_{env_name.upper()}\"\n        try:\n            source_metadata = SourceMetadata(IDENTIFIER, \"unique\", env_name)\n            if key:\n                value = redis.hget(holder.upper(), key)\n                if value:\n                    parsed_value = parse_conf_data(\n                        value, tomlfy=True, box_settings=obj\n                    )\n                    if parsed_value:\n                        obj.set(\n                            key,\n                            parsed_value,\n                            validate=validate,\n                            loader_identifier=source_metadata,\n                        )\n            else:\n                data = {\n                    key: parse_conf_data(value, tomlfy=True, box_settings=obj)\n                    for key, value in redis.hgetall(holder.upper()).items()\n                }\n                if data:\n                    obj.update(\n                        data,\n                        loader_identifier=source_metadata,\n                        validate=validate,\n                    )\n        except Exception:\n            if silent:\n                return False\n            raise\n\n\ndef write(obj, data=None, **kwargs):\n    \"\"\"Write a value in to loader source\n\n    :param obj: settings object\n    :param data: vars to be stored\n    :param kwargs: vars to be stored\n    :return:\n    \"\"\"\n    if obj.REDIS_ENABLED_FOR_DYNACONF is False:\n        raise RuntimeError(\n            \"Redis is not configured \\n\"\n            \"export REDIS_ENABLED_FOR_DYNACONF=true\\n\"\n            \"and configure the REDIS_*_FOR_DYNACONF variables\"\n        )\n    client = StrictRedis(**obj.REDIS_FOR_DYNACONF)\n    holder = obj.get(\"ENVVAR_PREFIX_FOR_DYNACONF\").upper()\n    # add env to holder\n    holder = f\"{holder}_{obj.current_env.upper()}\"\n\n    data = data or {}\n    data.update(kwargs)\n    if not data:\n        raise AttributeError(\"Data must be provided\")\n    redis_data = {\n        upperfy(key): unparse_conf_data(value) for key, value in data.items()\n    }\n    client.hmset(holder.upper(), redis_data)\n    load(obj)\n\n\ndef delete(obj, key=None):\n    \"\"\"\n    Delete a single key if specified, or all env if key is none\n    :param obj: settings object\n    :param key: key to delete from store location\n    :return: None\n    \"\"\"\n    client = StrictRedis(**obj.REDIS_FOR_DYNACONF)\n    holder = obj.get(\"ENVVAR_PREFIX_FOR_DYNACONF\").upper()\n    # add env to holder\n    holder = f\"{holder}_{obj.current_env.upper()}\"\n\n    if key:\n        client.hdel(holder.upper(), upperfy(key))\n        obj.unset(key)\n    else:\n        keys = client.hkeys(holder.upper())\n        client.delete(holder.upper())\n        obj.unset_all(keys)\n", "path": "dynaconf/loaders/redis_loader.py"}, {"content": "# docker run -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -p 8200:8200 vault\n# pip install hvac\nfrom __future__ import annotations\n\nfrom dynaconf.loaders.base import SourceMetadata\nfrom dynaconf.utils import build_env_list\nfrom dynaconf.utils.parse_conf import parse_conf_data\n\ntry:\n    import boto3\nexcept ImportError:\n    boto3 = None\n\ntry:\n    from hvac import Client\n    from hvac.exceptions import InvalidPath, Forbidden\nexcept ImportError:\n    raise ImportError(\n        \"vault package is not installed in your environment. \"\n        \"`pip install dynaconf[vault]` or disable the vault loader with \"\n        \"export VAULT_ENABLED_FOR_DYNACONF=false\"\n    )\n\n\nIDENTIFIER = \"vault\"\n\n\n# backwards compatibility\n_get_env_list = build_env_list\n\n\ndef get_client(obj):\n    client = Client(\n        **{k: v for k, v in obj.VAULT_FOR_DYNACONF.items() if v is not None}\n    )\n    if obj.VAULT_ROLE_ID_FOR_DYNACONF is not None:\n        client.auth.approle.login(\n            role_id=obj.VAULT_ROLE_ID_FOR_DYNACONF,\n            secret_id=obj.get(\"VAULT_SECRET_ID_FOR_DYNACONF\"),\n        )\n    elif obj.VAULT_ROOT_TOKEN_FOR_DYNACONF is not None:\n        client.token = obj.VAULT_ROOT_TOKEN_FOR_DYNACONF\n    elif obj.VAULT_USERNAME_FOR_DYNACONF is not None:\n        client.auth.userpass.login(\n            username=obj.VAULT_USERNAME_FOR_DYNACONF,\n            password=obj.VAULT_PASSWORD_FOR_DYNACONF,\n        )\n\n    elif obj.VAULT_AUTH_WITH_IAM_FOR_DYNACONF:\n        if boto3 is None:\n            raise ImportError(\n                \"boto3 package is not installed in your environment. \"\n                \"`pip install boto3` or disable the VAULT_AUTH_WITH_IAM\"\n            )\n\n        session = boto3.Session()\n        credentials = session.get_credentials()\n        client.auth.aws.iam_login(\n            credentials.access_key,\n            credentials.secret_key,\n            credentials.token,\n            role=obj.VAULT_AUTH_ROLE_FOR_DYNACONF,\n        )\n    assert client.is_authenticated(), (\n        \"Vault authentication error: is VAULT_TOKEN_FOR_DYNACONF or \"\n        \"VAULT_ROLE_ID_FOR_DYNACONF defined?\"\n    )\n    client.secrets.kv.default_kv_version = obj.VAULT_KV_VERSION_FOR_DYNACONF\n    return client\n\n\ndef load(obj, env=None, silent=None, key=None, validate=False):\n    \"\"\"Reads and loads in to \"settings\" a single key or all keys from vault\n\n    :param obj: the settings instance\n    :param env: settings env default='DYNACONF'\n    :param silent: if errors should raise\n    :param key: if defined load a single key, else load all in env\n    :return: None\n    \"\"\"\n    client = get_client(obj)\n    try:\n        if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:\n            dirs = client.secrets.kv.v2.list_secrets(\n                path=obj.VAULT_PATH_FOR_DYNACONF,\n                mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n            )[\"data\"][\"keys\"]\n        else:\n            dirs = client.secrets.kv.v1.list_secrets(\n                path=obj.VAULT_PATH_FOR_DYNACONF,\n                mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n            )[\"data\"][\"keys\"]\n    except InvalidPath:\n        # The given path is not a directory\n        dirs = []\n    except Forbidden:\n        # The given token does not have permission to list the given path\n        dirs = []\n    # First look for secrets into environments less store\n    if not obj.ENVIRONMENTS_FOR_DYNACONF:\n        # By adding '', dynaconf will now read secrets from environments-less\n        # store which are not written by `dynaconf write` to Vault store\n        env_list = [obj.MAIN_ENV_FOR_DYNACONF.lower(), \"\"]\n    # Finally, look for secret into all the environments\n    else:\n        env_list = dirs + build_env_list(obj, env)\n    for env in env_list:\n        path = \"/\".join([obj.VAULT_PATH_FOR_DYNACONF, env])\n        try:\n            if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:\n                data = client.secrets.kv.v2.read_secret_version(\n                    path, mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF\n                )\n            else:\n                data = client.secrets.kv.read_secret(\n                    \"data/\" + path,\n                    mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n                )\n        except InvalidPath:\n            # If the path doesn't exist, ignore it and set data to None\n            data = None\n        except Forbidden:\n            data = None\n        if data:\n            # There seems to be a data dict within a data dict,\n            # extract the inner data\n            data = data.get(\"data\", {}).get(\"data\", {})\n        try:\n            source_metadata = SourceMetadata(IDENTIFIER, \"unique\", env)\n            if (\n                obj.VAULT_KV_VERSION_FOR_DYNACONF == 2\n                and obj.ENVIRONMENTS_FOR_DYNACONF\n                and data\n            ):\n                data = data.get(\"data\", {})\n            if data and key:\n                value = parse_conf_data(\n                    data.get(key), tomlfy=True, box_settings=obj\n                )\n                if value:\n                    obj.set(\n                        key,\n                        value,\n                        validate=validate,\n                        loader_identifier=source_metadata,\n                    )\n            elif data:\n                obj.update(\n                    data,\n                    loader_identifier=source_metadata,\n                    tomlfy=True,\n                    validate=validate,\n                )\n        except Exception:\n            if silent:\n                return False\n            raise\n\n\ndef write(obj, data=None, **kwargs):\n    \"\"\"Write a value in to loader source\n\n    :param obj: settings object\n    :param data: vars to be stored\n    :param kwargs: vars to be stored\n    :return:\n    \"\"\"\n    if obj.VAULT_ENABLED_FOR_DYNACONF is False:\n        raise RuntimeError(\n            \"Vault is not configured \\n\"\n            \"export VAULT_ENABLED_FOR_DYNACONF=true\\n\"\n            \"and configure the VAULT_FOR_DYNACONF_* variables\"\n        )\n    data = data or {}\n    data.update(kwargs)\n    if not data:\n        raise AttributeError(\"Data must be provided\")\n    data = {\"data\": data}\n    client = get_client(obj)\n    if obj.VAULT_KV_VERSION_FOR_DYNACONF == 1:\n        mount_point = obj.VAULT_MOUNT_POINT_FOR_DYNACONF + \"/data\"\n    else:\n        mount_point = obj.VAULT_MOUNT_POINT_FOR_DYNACONF\n    path = \"/\".join([obj.VAULT_PATH_FOR_DYNACONF, obj.current_env.lower()])\n    client.secrets.kv.create_or_update_secret(\n        path, secret=data, mount_point=mount_point\n    )\n    load(obj)\n\n\ndef list_envs(obj, path=\"\"):\n    \"\"\"\n    This function is a helper to get a list of all the existing envs in\n    the source of data, the use case is:\n        existing_envs = vault_loader.list_envs(settings)\n        for env in exiting_envs:\n            with settings.using_env(env):  # switch to the env\n            # do something with a key of that env\n\n    :param obj: settings object\n    :param path: path to the vault secrets\n    :return: list containing all the keys at the given path\n    \"\"\"\n    client = get_client(obj)\n    path = path or obj.get(\"VAULT_PATH_FOR_DYNACONF\")\n    try:\n        return client.list(f\"/secret/metadata/{path}\")[\"data\"][\"keys\"]\n    except TypeError:\n        return []\n", "path": "dynaconf/loaders/vault_loader.py"}], "after_files": [{"content": "from __future__ import annotations\n\nfrom dynaconf.loaders.base import SourceMetadata\nfrom dynaconf.utils import build_env_list\nfrom dynaconf.utils import upperfy\nfrom dynaconf.utils.parse_conf import parse_conf_data\nfrom dynaconf.utils.parse_conf import unparse_conf_data\n\ntry:\n    from redis import StrictRedis\nexcept ImportError:\n    StrictRedis = None\n\nIDENTIFIER = \"redis\"\n\n\ndef load(obj, env=None, silent=True, key=None, validate=False):\n    \"\"\"Reads and loads in to \"settings\" a single key or all keys from redis\n\n    :param obj: the settings instance\n    :param env: settings env default='DYNACONF'\n    :param silent: if errors should raise\n    :param key: if defined load a single key, else load all in env\n    :return: None\n    \"\"\"\n    if StrictRedis is None:\n        raise ImportError(\n            \"redis package is not installed in your environment. \"\n            \"`pip install dynaconf[redis]` or disable the redis loader with \"\n            \"export REDIS_ENABLED_FOR_DYNACONF=false\"\n        )\n\n    redis = StrictRedis(**obj.get(\"REDIS_FOR_DYNACONF\"))\n    prefix = obj.get(\"ENVVAR_PREFIX_FOR_DYNACONF\")\n    # prefix is added to env_list to keep backwards compatibility\n    env_list = [prefix] + build_env_list(obj, env or obj.current_env)\n    for env_name in env_list:\n        holder = f\"{prefix.upper()}_{env_name.upper()}\"\n        try:\n            source_metadata = SourceMetadata(IDENTIFIER, \"unique\", env_name)\n            if key:\n                value = redis.hget(holder.upper(), key)\n                if value:\n                    parsed_value = parse_conf_data(\n                        value, tomlfy=True, box_settings=obj\n                    )\n                    if parsed_value:\n                        obj.set(\n                            key,\n                            parsed_value,\n                            validate=validate,\n                            loader_identifier=source_metadata,\n                        )\n            else:\n                data = {\n                    key: parse_conf_data(value, tomlfy=True, box_settings=obj)\n                    for key, value in redis.hgetall(holder.upper()).items()\n                }\n                if data:\n                    obj.update(\n                        data,\n                        loader_identifier=source_metadata,\n                        validate=validate,\n                    )\n        except Exception:\n            if silent:\n                return False\n            raise\n\n\ndef write(obj, data=None, **kwargs):\n    \"\"\"Write a value in to loader source\n\n    :param obj: settings object\n    :param data: vars to be stored\n    :param kwargs: vars to be stored\n    :return:\n    \"\"\"\n    if obj.REDIS_ENABLED_FOR_DYNACONF is False:\n        raise RuntimeError(\n            \"Redis is not configured \\n\"\n            \"export REDIS_ENABLED_FOR_DYNACONF=true\\n\"\n            \"and configure the REDIS_*_FOR_DYNACONF variables\"\n        )\n    client = StrictRedis(**obj.REDIS_FOR_DYNACONF)\n    holder = obj.get(\"ENVVAR_PREFIX_FOR_DYNACONF\").upper()\n    # add env to holder\n    holder = f\"{holder}_{obj.current_env.upper()}\"\n\n    data = data or {}\n    data.update(kwargs)\n    if not data:\n        raise AttributeError(\"Data must be provided\")\n    redis_data = {\n        upperfy(key): unparse_conf_data(value) for key, value in data.items()\n    }\n    client.hset(holder.upper(), mapping=redis_data)\n    load(obj)\n\n\ndef delete(obj, key=None):\n    \"\"\"\n    Delete a single key if specified, or all env if key is none\n    :param obj: settings object\n    :param key: key to delete from store location\n    :return: None\n    \"\"\"\n    client = StrictRedis(**obj.REDIS_FOR_DYNACONF)\n    holder = obj.get(\"ENVVAR_PREFIX_FOR_DYNACONF\").upper()\n    # add env to holder\n    holder = f\"{holder}_{obj.current_env.upper()}\"\n\n    if key:\n        client.hdel(holder.upper(), upperfy(key))\n        obj.unset(key)\n    else:\n        keys = client.hkeys(holder.upper())\n        client.delete(holder.upper())\n        obj.unset_all(keys)\n", "path": "dynaconf/loaders/redis_loader.py"}, {"content": "# docker run -e 'VAULT_DEV_ROOT_TOKEN_ID=myroot' -p 8200:8200 vault\n# pip install hvac\nfrom __future__ import annotations\n\nfrom dynaconf.loaders.base import SourceMetadata\nfrom dynaconf.utils import build_env_list\nfrom dynaconf.utils.parse_conf import parse_conf_data\n\ntry:\n    import boto3\nexcept ImportError:\n    boto3 = None\n\ntry:\n    from hvac import Client\n    from hvac.exceptions import InvalidPath, Forbidden\nexcept ImportError:\n    raise ImportError(\n        \"vault package is not installed in your environment. \"\n        \"`pip install dynaconf[vault]` or disable the vault loader with \"\n        \"export VAULT_ENABLED_FOR_DYNACONF=false\"\n    )\n\n\nIDENTIFIER = \"vault\"\n\n\n# backwards compatibility\n_get_env_list = build_env_list\n\n\ndef get_client(obj):\n    client = Client(\n        **{k: v for k, v in obj.VAULT_FOR_DYNACONF.items() if v is not None}\n    )\n    if obj.VAULT_ROLE_ID_FOR_DYNACONF is not None:\n        client.auth.approle.login(\n            role_id=obj.VAULT_ROLE_ID_FOR_DYNACONF,\n            secret_id=obj.get(\"VAULT_SECRET_ID_FOR_DYNACONF\"),\n        )\n    elif obj.VAULT_ROOT_TOKEN_FOR_DYNACONF is not None:\n        client.token = obj.VAULT_ROOT_TOKEN_FOR_DYNACONF\n    elif obj.VAULT_USERNAME_FOR_DYNACONF is not None:\n        client.auth.userpass.login(\n            username=obj.VAULT_USERNAME_FOR_DYNACONF,\n            password=obj.VAULT_PASSWORD_FOR_DYNACONF,\n        )\n\n    elif obj.VAULT_AUTH_WITH_IAM_FOR_DYNACONF:\n        if boto3 is None:\n            raise ImportError(\n                \"boto3 package is not installed in your environment. \"\n                \"`pip install boto3` or disable the VAULT_AUTH_WITH_IAM\"\n            )\n\n        session = boto3.Session()\n        credentials = session.get_credentials()\n        client.auth.aws.iam_login(\n            credentials.access_key,\n            credentials.secret_key,\n            credentials.token,\n            role=obj.VAULT_AUTH_ROLE_FOR_DYNACONF,\n        )\n    assert client.is_authenticated(), (\n        \"Vault authentication error: is VAULT_TOKEN_FOR_DYNACONF or \"\n        \"VAULT_ROLE_ID_FOR_DYNACONF defined?\"\n    )\n    client.secrets.kv.default_kv_version = obj.VAULT_KV_VERSION_FOR_DYNACONF\n    return client\n\n\ndef load(obj, env=None, silent=None, key=None, validate=False):\n    \"\"\"Reads and loads in to \"settings\" a single key or all keys from vault\n\n    :param obj: the settings instance\n    :param env: settings env default='DYNACONF'\n    :param silent: if errors should raise\n    :param key: if defined load a single key, else load all in env\n    :return: None\n    \"\"\"\n    client = get_client(obj)\n    try:\n        if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:\n            dirs = client.secrets.kv.v2.list_secrets(\n                path=obj.VAULT_PATH_FOR_DYNACONF,\n                mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n            )[\"data\"][\"keys\"]\n        else:\n            dirs = client.secrets.kv.v1.list_secrets(\n                path=obj.VAULT_PATH_FOR_DYNACONF,\n                mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n            )[\"data\"][\"keys\"]\n    except InvalidPath:\n        # The given path is not a directory\n        dirs = []\n    except Forbidden:\n        # The given token does not have permission to list the given path\n        dirs = []\n    # First look for secrets into environments less store\n    if not obj.ENVIRONMENTS_FOR_DYNACONF:\n        # By adding '', dynaconf will now read secrets from environments-less\n        # store which are not written by `dynaconf write` to Vault store\n        env_list = [obj.MAIN_ENV_FOR_DYNACONF.lower(), \"\"]\n    # Finally, look for secret into all the environments\n    else:\n        env_list = dirs + build_env_list(obj, env)\n    for env in env_list:\n        path = \"/\".join([obj.VAULT_PATH_FOR_DYNACONF, env])\n        try:\n            if obj.VAULT_KV_VERSION_FOR_DYNACONF == 2:\n                data = client.secrets.kv.v2.read_secret_version(\n                    path,\n                    mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n                    raise_on_deleted_version=True,  # keep default behavior\n                )\n            else:\n                data = client.secrets.kv.read_secret(\n                    \"data/\" + path,\n                    mount_point=obj.VAULT_MOUNT_POINT_FOR_DYNACONF,\n                )\n        except InvalidPath:\n            # If the path doesn't exist, ignore it and set data to None\n            data = None\n        except Forbidden:\n            data = None\n        if data:\n            # There seems to be a data dict within a data dict,\n            # extract the inner data\n            data = data.get(\"data\", {}).get(\"data\", {})\n        try:\n            source_metadata = SourceMetadata(IDENTIFIER, \"unique\", env)\n            if (\n                obj.VAULT_KV_VERSION_FOR_DYNACONF == 2\n                and obj.ENVIRONMENTS_FOR_DYNACONF\n                and data\n            ):\n                data = data.get(\"data\", {})\n            if data and key:\n                value = parse_conf_data(\n                    data.get(key), tomlfy=True, box_settings=obj\n                )\n                if value:\n                    obj.set(\n                        key,\n                        value,\n                        validate=validate,\n                        loader_identifier=source_metadata,\n                    )\n            elif data:\n                obj.update(\n                    data,\n                    loader_identifier=source_metadata,\n                    tomlfy=True,\n                    validate=validate,\n                )\n        except Exception:\n            if silent:\n                return False\n            raise\n\n\ndef write(obj, data=None, **kwargs):\n    \"\"\"Write a value in to loader source\n\n    :param obj: settings object\n    :param data: vars to be stored\n    :param kwargs: vars to be stored\n    :return:\n    \"\"\"\n    if obj.VAULT_ENABLED_FOR_DYNACONF is False:\n        raise RuntimeError(\n            \"Vault is not configured \\n\"\n            \"export VAULT_ENABLED_FOR_DYNACONF=true\\n\"\n            \"and configure the VAULT_FOR_DYNACONF_* variables\"\n        )\n    data = data or {}\n    data.update(kwargs)\n    if not data:\n        raise AttributeError(\"Data must be provided\")\n    data = {\"data\": data}\n    client = get_client(obj)\n    if obj.VAULT_KV_VERSION_FOR_DYNACONF == 1:\n        mount_point = obj.VAULT_MOUNT_POINT_FOR_DYNACONF + \"/data\"\n    else:\n        mount_point = obj.VAULT_MOUNT_POINT_FOR_DYNACONF\n    path = \"/\".join([obj.VAULT_PATH_FOR_DYNACONF, obj.current_env.lower()])\n    client.secrets.kv.create_or_update_secret(\n        path, secret=data, mount_point=mount_point\n    )\n    load(obj)\n\n\ndef list_envs(obj, path=\"\"):\n    \"\"\"\n    This function is a helper to get a list of all the existing envs in\n    the source of data, the use case is:\n        existing_envs = vault_loader.list_envs(settings)\n        for env in exiting_envs:\n            with settings.using_env(env):  # switch to the env\n            # do something with a key of that env\n\n    :param obj: settings object\n    :param path: path to the vault secrets\n    :return: list containing all the keys at the given path\n    \"\"\"\n    client = get_client(obj)\n    path = path or obj.get(\"VAULT_PATH_FOR_DYNACONF\")\n    try:\n        return client.list(f\"/secret/metadata/{path}\")[\"data\"][\"keys\"]\n    except TypeError:\n        return []\n", "path": "dynaconf/loaders/vault_loader.py"}]}