Repository: dynaconf/dynaconf

Issue:
[feature] opt-out for warning about missing environments
**Is your feature request related to a problem? Please describe.**

in a project where environments are used and plugins supply their own default settings in the global section,
the warnings about missing other environments are misleading/unneeded

additionally the warnings only apply to the currently used environment, so different setup raise different warnings

**Describe the solution you'd like**

A way to opt out of the warnings for either a subset of the files or all of them

**Describe alternatives you've considered**

no longer warning about missing envs

**Additional context**
```
$ ENV_FOR_DYNACONF=prod iqe
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: prod env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/iqe-tests/iqe/conf/settings.polarion.yaml
  warnings.warn(message)
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: prod env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/iqe-tests/iqe/conf/settings.default.yaml
  warnings.warn(message)
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: prod env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/advisor/iqe_advisor/conf/settings.default.yaml
  warnings.warn(message)
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: prod env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/clientv3/iqe_clientv3/conf/settings.default.yaml
....

$ iqe
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: qa env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/iqe-tests/iqe/conf/settings.polarion.yaml
  warnings.warn(message)
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: qa env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/iqe-tests/iqe/conf/settings.default.yaml
  warnings.warn(message)
/home/rpfannsc/Projects/insights-qe/venv-iqe/lib/python3.8/site-packages/dynaconf/loaders/base.py:145: UserWarning: yaml_loader: qa env notdefined in /home/rpfannsc/Projects/insights-qe/checkouts/advisor/iqe_advisor/conf/settings.default.yaml
  warnings.warn(message)
```



Discussion:

Resolving patch:
diff --git a/dynaconf/loaders/base.py b/dynaconf/loaders/base.py
--- a/dynaconf/loaders/base.py
+++ b/dynaconf/loaders/base.py
@@ -59,14 +59,14 @@ def load(self, filename=None, key=None, silent=True):
         else:  # it is already a list/tuple
             files = filename
 
-        source_data = self.get_source_date(files)
+        source_data = self.get_source_data(files)
 
         if self.obj.get("ENVIRONMENTS_FOR_DYNACONF") is False:
             self._envless_load(source_data, silent, key)
         else:
             self._load_all_envs(source_data, silent, key)
 
-    def get_source_date(self, files):
+    def get_source_data(self, files):
         """Reads each file and returns source data for each file
         {"path/to/file.ext": {"key": "value"}}
         """
@@ -99,15 +99,13 @@ def get_source_date(self, files):
 
     def _envless_load(self, source_data, silent=True, key=None):
         """Load all the keys from each file without env separation"""
-        for source_file, file_data in source_data.items():
-            self._set_data_to_obj(
-                file_data, self.identifier, source_file, key=key
-            )
+        for file_data in source_data.values():
+            self._set_data_to_obj(file_data, self.identifier, key=key)
 
     def _load_all_envs(self, source_data, silent=True, key=None):
         """Load configs from files separating by each environment"""
 
-        for source_file, file_data in source_data.items():
+        for file_data in source_data.values():
 
             # env name is checked in lower
             file_data = {k.lower(): value for k, value in file_data.items()}
@@ -115,35 +113,18 @@ def _load_all_envs(self, source_data, silent=True, key=None):
             # is there a `dynaconf_merge` on top level of file?
             file_merge = file_data.get("dynaconf_merge")
 
-            # all lower case for comparison
-            base_envs = [
-                # DYNACONF or MYPROGRAM
-                (self.obj.get("ENVVAR_PREFIX_FOR_DYNACONF") or "").lower(),
-                # DEFAULT
-                self.obj.get("DEFAULT_ENV_FOR_DYNACONF").lower(),
-                # default active env unless ENV_FOR_DYNACONF is changed
-                "development",
-                # backwards compatibility for global
-                "dynaconf",
-                # global that rules all
-                "global",
-            ]
-
             for env in build_env_list(self.obj, self.env):
                 env = env.lower()  # lower for better comparison
                 data = {}
+
                 try:
                     data = file_data[env] or {}
                 except KeyError:
-                    if env not in base_envs:
-                        message = (
-                            f"{self.identifier}_loader: {env} env not"
-                            f"defined in {source_file}"
-                        )
-                        if silent:
-                            warnings.warn(message)
-                        else:
-                            raise KeyError(message)
+                    if silent:
+                        continue
+                    raise
+
+                if not data:
                     continue
 
                 if env != self.obj.get("DEFAULT_ENV_FOR_DYNACONF").lower():
@@ -151,18 +132,10 @@ def _load_all_envs(self, source_data, silent=True, key=None):
                 else:
                     identifier = self.identifier
 
-                self._set_data_to_obj(
-                    data, identifier, source_file, file_merge, key, env
-                )
+                self._set_data_to_obj(data, identifier, file_merge, key)
 
     def _set_data_to_obj(
-        self,
-        data,
-        identifier,
-        source_file,
-        file_merge=None,
-        key=False,
-        env=False,
+        self, data, identifier, file_merge=None, key=False,
     ):
         """Calls setttings.set to add the keys"""
 


Test patch:
diff --git a/tests/test_yaml_loader.py b/tests/test_yaml_loader.py
--- a/tests/test_yaml_loader.py
+++ b/tests/test_yaml_loader.py
@@ -284,16 +284,6 @@ def test_explicit_local_files(tmpdir):
     assert conf.get("music.current.even.inner.element") is True
 
 
-def test_empty_env(tmpdir):
-    """Assert empty env is not crashing on load."""
-    settings_file_yaml = """
-    default: ~
-    """
-    tmpdir.join("settings.yaml").write(settings_file_yaml)
-    settings = LazySettings(environments=True)
-    settings.reload()
-
-
 def test_envless():
     settings = LazySettings()
     _yaml = """
@@ -305,3 +295,27 @@ def test_envless():
     assert settings.a == "a,b"
     assert settings.COLORS.white.code == "#FFFFFF"
     assert settings.COLORS.white.name == "white"
+
+
+def test_empty_env():
+    settings = LazySettings(environments=True)
+    _yaml = """
+    default:
+        foo: bar
+    development:
+    """
+    load(settings, filename=_yaml)
+    assert settings.FOO == "bar"
+
+
+def test_empty_env_from_file(tmpdir):
+    """Assert empty env is not crashing on load."""
+    settings_file_yaml = """
+    default:
+        foo: bar
+    development: ~
+    """
+    tmpdir.join("settings.yaml").write(settings_file_yaml)
+    settings = LazySettings(environments=True, settings_file="settings.yaml")
+    settings.reload()
+    assert settings.FOO == "bar"