Repository: tox-dev/tox

Issue:
tox4: substituting values from other sections seems to not work
Hi, I gave a try new tox alpha release (tox-4.0.0a6) and I found one issue with tox not respecting values substitution from other sections. I do not see any references to this section in the documentation anymore so maybe it is something you want to get rid of... 

Anyway - this is how it looks like:
```
$ tox -rvv
ROOT: 217 D setup logging to DEBUG on pid 86537 [tox/report.py:211]
Traceback (most recent call last):
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/main.py", line 51, in get_env
    return self._env_to_set[item]
KeyError: 'py'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/mrusi/venv/bin/tox4", line 8, in <module>
    sys.exit(run())
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/run.py", line 22, in run
    result = main(sys.argv[1:] if args is None else args)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/run.py", line 47, in main
    result = handler(state)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/session/cmd/legacy.py", line 104, in legacy
    return run_sequential(state)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/session/cmd/run/sequential.py", line 20, in run_sequential
    return execute(state, max_workers=1, has_spinner=False, live=True)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/session/cmd/run/common.py", line 172, in execute
    if state.tox_env(env).active:
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/session/state.py", line 64, in tox_env
    self.conf.get_env(name)  # the lookup here will trigger register_config_set, which will build it
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/main.py", line 61, in get_env
    self.register_config_set(item, env)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/session/state.py", line 76, in register_config_set
    self._build_run_env(config_set)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/session/state.py", line 91, in _build_run_env
    env: RunToxEnv = builder(env_conf, self.conf.core, self.options, journal, self.log_handler)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/virtual_env/runner.py", line 26, in __init__
    super().__init__(conf, core, options, journal, log_handler)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/virtual_env/api.py", line 35, in __init__
    super().__init__(conf, core, options, journal, log_handler)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/runner.py", line 25, in __init__
    super().__init__(conf, core, options, journal, log_handler)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/api.py", line 79, in __init__
    super().__init__(conf, core, options, journal, log_handler)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/runner.py", line 27, in __init__
    super().__init__(conf, core, options, journal, log_handler)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/api.py", line 40, in __init__
    self.register_config()
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/virtual_env/api.py", line 38, in register_config
    super().register_config()
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/runner.py", line 29, in register_config
    super().register_config()
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/api.py", line 82, in register_config
    super().register_config()
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/runner.py", line 77, in register_config
    self.has_package = self.add_package_conf()
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/tox_env/python/virtual_env/runner.py", line 38, in add_package_conf
    develop_mode = self.conf["usedevelop"] or getattr(self.options, "develop", False)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/sets.py", line 86, in __getitem__
    return self.load(item)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/sets.py", line 97, in load
    return config_definition(self._conf, item, self.loaders, chain)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/of_type.py", line 99, in __call__
    value = loader.load(key, self.of_type, self.kwargs, conf, self.env_name, chain)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/loader/api.py", line 98, in load
    converted = self.to(prepared, of_type, kwargs)
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/loader/convert.py", line 31, in to
    return self.to_bool(raw)  # type: ignore[return-value]
  File "/Users/mrusi/venv/lib/python3.8/site-packages/tox/config/loader/str_convert.py", line 90, in to_bool
    raise TypeError(f"value {value} cannot be transformed to bool, valid: {', '.join(StrConvert.VALID_BOOL)}")
TypeError: value {[project-info]develop} cannot be transformed to bool, valid: , 0, 1, false, no, off, on, true, yes

$ cat tox.ini
[project-info]
develop = false
[testenv]
deps=-rrequirements.txt
usedevelop = {[project-info]develop}
commands=echo "commands"
```

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=h1) Report
> Merging [#2000](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=desc) (3f2eec8) into [rewrite](https://codecov.io/gh/tox-dev/tox/commit/00723c507f37e99bd78edc82aa389c5af396b762?el=desc) (00723c5) will **increase** coverage by `0.16%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/tox-dev/tox/pull/2000/graphs/tree.svg?width=650&height=150&src=pr&token=DYodAwDCZ5)](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=tree)

```diff
@@             Coverage Diff              @@
##           rewrite     #2000      +/-   ##
============================================
+ Coverage    99.83%   100.00%   +0.16%     
============================================
  Files          147       146       -1     
  Lines         8276      8181      -95     
  Branches       823       798      -25     
============================================
- Hits          8262      8181      -81     
+ Misses           3         0       -3     
+ Partials        11         0      -11     
```

| Flag | Coverage Δ | |
|---|---|---|
| tests | `100.00% <100.00%> (+0.16%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/tox/config/loader/ini/replace.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC9jb25maWcvbG9hZGVyL2luaS9yZXBsYWNlLnB5) | `100.00% <ø> (ø)` | |
| [.../config/loader/ini/replace/test\_replace\_tox\_env.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-dGVzdHMvY29uZmlnL2xvYWRlci9pbmkvcmVwbGFjZS90ZXN0X3JlcGxhY2VfdG94X2Vudi5weQ==) | `100.00% <100.00%> (ø)` | |
| [src/tox/tox\_env/api.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC90b3hfZW52L2FwaS5weQ==) | `100.00% <0.00%> (ø)` | |
| [src/tox/execute/request.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC9leGVjdXRlL3JlcXVlc3QucHk=) | `100.00% <0.00%> (ø)` | |
| [src/tox/util/pep517/backend.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC91dGlsL3BlcDUxNy9iYWNrZW5kLnB5) | `100.00% <0.00%> (ø)` | |
| [...ecute/local\_sub\_process/read\_via\_thread\_windows.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC9leGVjdXRlL2xvY2FsX3N1Yl9wcm9jZXNzL3JlYWRfdmlhX3RocmVhZF93aW5kb3dzLnB5) | | |
| [src/tox/tox\_env/python/api.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC90b3hfZW52L3B5dGhvbi9hcGkucHk=) | `100.00% <0.00%> (+0.77%)` | :arrow_up: |
| [src/tox/config/loader/str\_convert.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC9jb25maWcvbG9hZGVyL3N0cl9jb252ZXJ0LnB5) | `100.00% <0.00%> (+1.47%)` | :arrow_up: |
| [src/tox/util/spinner.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC91dGlsL3NwaW5uZXIucHk=) | `100.00% <0.00%> (+2.27%)` | :arrow_up: |
| [src/tox/execute/local\_sub\_process/\_\_init\_\_.py](https://codecov.io/gh/tox-dev/tox/pull/2000/diff?src=pr&el=tree#diff-c3JjL3RveC9leGVjdXRlL2xvY2FsX3N1Yl9wcm9jZXNzL19faW5pdF9fLnB5) | `100.00% <0.00%> (+4.32%)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=footer). Last update [00723c5...3f2eec8](https://codecov.io/gh/tox-dev/tox/pull/2000?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/docs/changelog/1985.bugfix.rst b/docs/changelog/1985.bugfix.rst
new file mode 100644
index 00000000..62d49a53
--- /dev/null
+++ b/docs/changelog/1985.bugfix.rst
@@ -0,0 +1,2 @@
+Enable replacements (a.k.a section substitions) for section names containing a dash in sections
+without the ``testenv:`` prefix - by :user:`jugmac00`, :user:`obestwalter`, :user:`eumiro`.
diff --git a/src/tox/config/loader/ini/replace.py b/src/tox/config/loader/ini/replace.py
index 6b16ef71..898d7dbe 100644
--- a/src/tox/config/loader/ini/replace.py
+++ b/src/tox/config/loader/ini/replace.py
@@ -89,7 +89,7 @@ def _replace_match(
 
 _REPLACE_REF = re.compile(
     rf"""
-    (\[(?P<full_env>{BASE_TEST_ENV}(:(?P<env>[^]]+))?|(?P<section>\w+))\])? # env/section
+    (\[(?P<full_env>{BASE_TEST_ENV}(:(?P<env>[^]]+))?|(?P<section>[-\w]+))\])? # env/section
     (?P<key>[a-zA-Z0-9_]+) # key
     (:(?P<default>.*))? # default value
 """,


Test patch:
diff --git a/tests/config/loader/ini/replace/test_replace_tox_env.py b/tests/config/loader/ini/replace/test_replace_tox_env.py
index a111495a..1116214b 100644
--- a/tests/config/loader/ini/replace/test_replace_tox_env.py
+++ b/tests/config/loader/ini/replace/test_replace_tox_env.py
@@ -151,3 +151,18 @@ def test_replace_from_tox_other_tox_section_same_name(tox_ini_conf: ToxIniCreato
     conf_a = tox_ini_conf("[testenv:a]\nx={[testenv:b]c}\nc=d\n[testenv:b]}").get_env("a")
     conf_a.add_config(keys="x", of_type=str, default="", desc="d")
     assert conf_a["x"] == "{[testenv:b]c}"
+
+
+@pytest.mark.parametrize(
+    ("env_name", "exp"),
+    [
+        ("testenv:foobar", "1"),
+        ("testenv:foo-bar", "1"),
+        ("foo-bar", "1"),
+        ("foobar", "1"),
+    ],
+)
+def test_replace_valid_section_names(tox_ini_conf: ToxIniCreator, env_name: str, exp: str) -> None:
+    conf_a = tox_ini_conf(f"[{env_name}]\na={exp}\n[testenv:a]\nx = {{[{env_name}]a}}").get_env("a")
+    conf_a.add_config(keys="x", of_type=str, default="o", desc="o")
+    assert conf_a["x"] == exp