Repository: dynaconf/dynaconf

Issue:
[bug] environments can no longer have `_` in their name
**Describe the bug**
Environments cannot have an underscore in their name since 3.1.12

**To Reproduce**
Steps to reproduce the behavior:

1. Create appropriate config files for environment `unittesting` and `unit_testing`
2. Use dynaconf 3.1.11
3. Attempt `Config.setenv("unittesting")`, it will succeed
4. Attempt `Config.setenv("unit_testing")`, it will succeed
5. Use dynaconf 3.1.12 or later
6. Attempt `Config.setenv("unittesting")`, it will succeed
7. Attempt `Config.setenv("unit_testing")`, it will fail

**Expected behavior**
Prior `unit_testing` environment should load without error

**Environment (please complete the following information):**
 - OS: Ubuntu 22.04
 - Dynaconf Version 3.2.3

**Additional context**
The change in behavior was added in #830, it's unclear why that changed both an error type and validation as part of CI onboarding for py3.11. The docs address [spaces in keys](https://www.dynaconf.com/#spaces-in-keys) explicitly to suggest "use an underscore", so it should be allowed in environment names as well. TOML, YAML, JSON and Python all support underscores in section/key names, INI may or may not depending on the parser.

If the change is intentional, docs should ideally be updated to state as much.


Discussion:

Resolving patch:
diff --git a/dynaconf/base.py b/dynaconf/base.py
--- a/dynaconf/base.py
+++ b/dynaconf/base.py
@@ -812,8 +812,8 @@ def setenv(self, env=None, clean=True, silent=True, filename=None):
         """
         env = env or self.ENV_FOR_DYNACONF
 
-        if not isinstance(env, str) or "_" in env or " " in env:
-            raise ValueError("env should be a string without _ or spaces")
+        if not isinstance(env, str) or " " in env:
+            raise ValueError("env should be a string without spaces")
 
         env = env.upper()
 


Test patch:
diff --git a/tests/test_base.py b/tests/test_base.py
--- a/tests/test_base.py
+++ b/tests/test_base.py
@@ -210,9 +210,9 @@ def test_env_should_be_string(settings):
         settings.setenv(123456)
 
 
-def test_env_should_not_have_underline(settings):
-    with pytest.raises(ValueError):
-        settings.setenv("COOL_env")
+def test_env_should_allow_underline(settings):
+    settings.setenv("COOL_env")
+    assert settings.current_env == "COOL_ENV"
 
 
 def test_path_for(settings):
diff --git a/tests_functional/issues/1011_env_with_underline/app.py b/tests_functional/issues/1011_env_with_underline/app.py
new file mode 100644
--- /dev/null
+++ b/tests_functional/issues/1011_env_with_underline/app.py
@@ -0,0 +1,21 @@
+from __future__ import annotations
+
+from dynaconf import Dynaconf
+
+
+settings = Dynaconf(
+    settings_files=["settings.toml"],
+    environments=["unit_testing", "dev_coding", "prod_server"],
+)
+
+unit_settings = settings.from_env("unit_testing")
+dev_settings = settings.from_env("dev_coding")
+prod_settings = settings.from_env("prod_server")
+
+assert settings.name == "default"
+assert unit_settings.name == "unit"
+assert dev_settings.name == "dev"
+assert prod_settings.name == "prod"
+
+settings.setenv("prod_server")
+assert settings.name == "prod"
diff --git a/tests_functional/issues/1011_env_with_underline/settings.toml b/tests_functional/issues/1011_env_with_underline/settings.toml
new file mode 100644
--- /dev/null
+++ b/tests_functional/issues/1011_env_with_underline/settings.toml
@@ -0,0 +1,8 @@
+[default]
+name = "default"
+[unit_testing]
+name = "unit"
+[dev_coding]
+name = "dev"
+[prod_server]
+name = "prod"