nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: zalando/patroni
Pull request #2970 (2023-12-01 10:06:59)

Don't let replica restore initialize key when DCS was wiped
It was happening from the branch where Patroni was supposed to be complain about converting standalone PG cluster to be governed by Patroni and exit.

hughcapet: 👍 
CyberDem0n: :+1: 

Patch:
diff --git a/patroni/ha.py b/patroni/ha.py
index ab1bc433..0d3e05a4 100644
--- a/patroni/ha.py
+++ b/patroni/ha.py
@@ -1849,10 +1849,9 @@ class Ha(object):
                             logger.fatal('system ID mismatch, node %s belongs to a different cluster: %s != %s',
                                          self.state_handler.name, self.cluster.initialize, data_sysid)
                             sys.exit(1)
-                elif self.cluster.is_unlocked() and not self.is_paused():
+                elif self.cluster.is_unlocked() and not self.is_paused() and not self.state_handler.cb_called:
                     # "bootstrap", but data directory is not empty
-                    if not self.state_handler.cb_called and self.state_handler.is_running() \
-                            and not self.state_handler.is_primary():
+                    if self.state_handler.is_running() and not self.state_handler.is_primary():
                         self._join_aborted = True
                         logger.error('No initialize key in DCS and PostgreSQL is running as replica, aborting start')
                         logger.error('Please first start Patroni on the node running as primary')


Test patch:
diff --git a/tests/test_ha.py b/tests/test_ha.py
index 40063018..5b1d4562 100644
--- a/tests/test_ha.py
+++ b/tests/test_ha.py
@@ -1585,6 +1585,11 @@ class TestHa(PostgresInit):
         self.p.is_primary = false
         self.ha.run_cycle()
         exit_mock.assert_called_once_with(1)
+        self.p.set_role('replica')
+        self.ha.dcs.initialize = Mock()
+        with patch.object(Postgresql, 'cb_called', PropertyMock(return_value=True)):
+            self.assertEqual(self.ha.run_cycle(), 'promoted self to leader by acquiring session lock')
+        self.ha.dcs.initialize.assert_not_called()
 
     @patch.object(Cluster, 'is_unlocked', Mock(return_value=False))
     def test_after_pause(self):
Repository: zalando/patroni
Pull request #3079 (2024-06-13 07:35:56)

Standby cluster can't have synchronous nodes
`synchronous_standby_names` and synchronous replication only work on a real primary node and in case of cascading replication simply ignored by Postgres.
This fact was already addressed by `global_config.is_synchronous_mode`, but in case if in a standby cluster the `/sync` key in DCS is not empty, `patronictl list` and `GET /cluster` were falsely reporting some nodes as synchronous because this check was missing.

Close https://github.com/zalando/patroni/issues/3078

guanglin1994: 这是来自QQ邮箱的假期自动回复邮件。
 
您好，我最近正在休假中，无法亲自回复您的邮件。我将在假期结束后，尽快给您回复。
coveralls: ## Pull Request Test Coverage Report for [Build 9495604928](https://coveralls.io/builds/68061240)


### Details

* **1** of **1**   **(100.0%)**  changed or added relevant line in **1** file are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **99.862%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/68061240/badge)](https://coveralls.io/builds/68061240) |
| :-- | --: |
| Change from base [Build 9481745624](https://coveralls.io/builds/68039544): |  0.0% |
| Covered Lines: | 13757 |
| Relevant Lines: | 13776 |

---
##### 💛  - [Coveralls](https://coveralls.io)

hughcapet: 👍 
CyberDem0n: :+1:

Patch:
diff --git a/patroni/utils.py b/patroni/utils.py
index c40e1248..560d2570 100644
--- a/patroni/utils.py
+++ b/patroni/utils.py
@@ -952,7 +952,7 @@ def cluster_as_json(cluster: 'Cluster') -> Dict[str, Any]:
     for m in cluster.members:
         if m.name == leader_name:
             role = 'standby_leader' if config.is_standby_cluster else 'leader'
-        elif cluster.sync.matches(m.name):
+        elif config.is_synchronous_mode and cluster.sync.matches(m.name):
             role = 'sync_standby'
         else:
             role = 'replica'


Test patch:
diff --git a/tests/test_ctl.py b/tests/test_ctl.py
index 5b56c93a..d5d83740 100644
--- a/tests/test_ctl.py
+++ b/tests/test_ctl.py
@@ -503,6 +503,14 @@ class TestCtl(unittest.TestCase):
         assert '2100' in result.output
         assert 'Scheduled restart' in result.output
 
+    def test_list_standby_cluster(self):
+        cluster = get_cluster_initialized_without_leader(leader=True, sync=('leader', 'other'))
+        cluster.config.data.update(synchronous_mode=True, standby_cluster={'port': 5433})
+        with patch('patroni.dcs.AbstractDCS.get_cluster', Mock(return_value=cluster)):
+            result = self.runner.invoke(ctl, ['list'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertNotIn('Sync Standby', result.output)
+
     def test_topology(self):
         cluster = get_cluster_initialized_with_leader()
         cluster.members.append(Member(0, 'cascade', 28,
Repository: zalando/patroni
Pull request #3081 (2024-06-13 17:12:44)

Adjust allow_in_place_tablespaces availability
`allow_in_place_tablespaces` was actually backpatched to PG10-PG14 

coveralls: ## Pull Request Test Coverage Report for [Build 9503898948](https://coveralls.io/builds/68074060)


### Details

* **0** of **0**   changed or added relevant lines in **0** files are covered.
* No unchanged relevant lines lost coverage.
* Overall coverage remained the same at **99.862%**

---



|  Totals | [![Coverage Status](https://coveralls.io/builds/68074060/badge)](https://coveralls.io/builds/68074060) |
| :-- | --: |
| Change from base [Build 9481745624](https://coveralls.io/builds/68039544): |  0.0% |
| Covered Lines: | 13757 |
| Relevant Lines: | 13776 |

---
##### 💛  - [Coveralls](https://coveralls.io)

CyberDem0n: :+1:

Patch:
diff --git a/patroni/postgresql/available_parameters/0_postgres.yml b/patroni/postgresql/available_parameters/0_postgres.yml
index a633b44e..a745084c 100644
--- a/patroni/postgresql/available_parameters/0_postgres.yml
+++ b/patroni/postgresql/available_parameters/0_postgres.yml
@@ -4,7 +4,7 @@ parameters:
     version_from: 170000
   allow_in_place_tablespaces:
   - type: Bool
-    version_from: 150000
+    version_from: 100000
   allow_system_table_mods:
   - type: Bool
     version_from: 90300
diff --git a/patroni/utils.py b/patroni/utils.py
index c40e1248..560d2570 100644
--- a/patroni/utils.py
+++ b/patroni/utils.py
@@ -952,7 +952,7 @@ def cluster_as_json(cluster: 'Cluster') -> Dict[str, Any]:
     for m in cluster.members:
         if m.name == leader_name:
             role = 'standby_leader' if config.is_standby_cluster else 'leader'
-        elif cluster.sync.matches(m.name):
+        elif config.is_synchronous_mode and cluster.sync.matches(m.name):
             role = 'sync_standby'
         else:
             role = 'replica'


Test patch:
diff --git a/tests/test_ctl.py b/tests/test_ctl.py
index 5b56c93a..d5d83740 100644
--- a/tests/test_ctl.py
+++ b/tests/test_ctl.py
@@ -503,6 +503,14 @@ class TestCtl(unittest.TestCase):
         assert '2100' in result.output
         assert 'Scheduled restart' in result.output
 
+    def test_list_standby_cluster(self):
+        cluster = get_cluster_initialized_without_leader(leader=True, sync=('leader', 'other'))
+        cluster.config.data.update(synchronous_mode=True, standby_cluster={'port': 5433})
+        with patch('patroni.dcs.AbstractDCS.get_cluster', Mock(return_value=cluster)):
+            result = self.runner.invoke(ctl, ['list'])
+            self.assertEqual(result.exit_code, 0)
+            self.assertNotIn('Sync Standby', result.output)
+
     def test_topology(self):
         cluster = get_cluster_initialized_with_leader()
         cluster.members.append(Member(0, 'cascade', 28,
Repository: tox-dev/pipdeptree
Pull request #379 (2024-06-12 22:29:02)

Print resolved interpreter when using env detection
Good evening,

This is a super quick fix for #372

<img width="625" alt="image" src="https://github.com/tox-dev/pipdeptree/assets/6159524/2c90c570-0184-4ce9-a133-c7e52b58a203">

> One thing that could be useful is to display the resolved environment when --python auto is used (or maybe even every time regardless?)

What I did was create a new param, `log_resolved.` If True, print the resolved Python path.


I have only activated this to the `--python auto` option.


stasfilin: @kemzeb Good evening,
Please review this MR when you have time. 

Thanks

Patch:
diff --git a/src/pipdeptree/__main__.py b/src/pipdeptree/__main__.py
index d5881a0..0edf246 100644
--- a/src/pipdeptree/__main__.py
+++ b/src/pipdeptree/__main__.py
@@ -26,7 +26,9 @@ def main(args: Sequence[str] | None = None) -> None | int:
     warning_printer.warning_type = options.warn
 
     if options.python == "auto":
-        options.python = detect_active_interpreter()
+        resolved_path = detect_active_interpreter()
+        options.python = resolved_path
+        print(f"(resolved python: {resolved_path})", file=sys.stderr)  # noqa: T201
 
     pkgs = get_installed_distributions(
         interpreter=options.python, local_only=options.local_only, user_only=options.user_only


Test patch:
diff --git a/tests/test_pipdeptree.py b/tests/test_pipdeptree.py
index 967b71c..4a5472a 100644
--- a/tests/test_pipdeptree.py
+++ b/tests/test_pipdeptree.py
@@ -1,11 +1,17 @@
 from __future__ import annotations
 
 import sys
-from subprocess import check_call  # noqa: S404
+from subprocess import CompletedProcess, check_call  # noqa: S404
 from typing import TYPE_CHECKING
 
+from pipdeptree.__main__ import main
+
 if TYPE_CHECKING:
+    from pathlib import Path
+
+    import pytest
     from pytest_console_scripts import ScriptRunner
+    from pytest_mock import MockFixture
 
 
 def test_main() -> None:
@@ -15,3 +21,21 @@ def test_main() -> None:
 def test_console(script_runner: ScriptRunner) -> None:
     result = script_runner.run(["pipdeptree", "--help"])
     assert result.success
+
+
+def test_main_log_resolved(tmp_path: Path, mocker: MockFixture, capsys: pytest.CaptureFixture[str]) -> None:
+    mocker.patch("sys.argv", ["", "--python", "auto"])
+    mocker.patch("pipdeptree.__main__.detect_active_interpreter", return_value=str(tmp_path))
+    mock_subprocess_run = mocker.patch("subprocess.run")
+    valid_sys_path = str([str(tmp_path)])
+    mock_subprocess_run.return_value = CompletedProcess(
+        args=["python", "-c", "import sys; print(sys.path)"],
+        returncode=0,
+        stdout=valid_sys_path,
+        stderr="",
+    )
+
+    main()
+
+    captured = capsys.readouterr()
+    assert captured.err.startswith(f"(resolved python: {tmp_path!s}")
Repository: tox-dev/sphinx-autodoc-typehints
Pull request #221 (2022-02-16 23:03:32)

Handle UnionType

bryanforbes: @gaborbernat done

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6240a3b..33bddef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
 ## 1.18.0
 
 - Support and require `nptyping>=2`
+- Handle `UnionType`
 
 ## 1.17.1
 
diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py
index 9ec89cf..cde0720 100644
--- a/src/sphinx_autodoc_typehints/__init__.py
+++ b/src/sphinx_autodoc_typehints/__init__.py
@@ -175,6 +175,8 @@ def format_annotation(annotation: Any, config: Config) -> str:  # noqa: C901 # t
         formatted_args = f"\\[\\[{', '.join(fmt[:-1])}], {fmt[-1]}]"
     elif full_name == "typing.Literal":
         formatted_args = f"\\[{', '.join(repr(arg) for arg in args)}]"
+    elif full_name == "types.UnionType":
+        return " | ".join([format_annotation(arg, config) for arg in args])
 
     if args and not formatted_args:
         try:


Test patch:
diff --git a/tests/roots/test-dummy/dummy_module_future_annotations.py b/tests/roots/test-dummy/dummy_module_future_annotations.py
index a84934d..5cc16cb 100644
--- a/tests/roots/test-dummy/dummy_module_future_annotations.py
+++ b/tests/roots/test-dummy/dummy_module_future_annotations.py
@@ -1,7 +1,9 @@
 from __future__ import annotations
 
 
-def function_with_py310_annotations(self, x: bool, y: int, z: str | None = None) -> str:  # noqa: U100
+def function_with_py310_annotations(
+    self, x: bool | None, y: int | str | float, z: str | None = None  # noqa: U100
+) -> str:
     """
     Method docstring.
 
diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py
index b87f73a..b5f0a00 100644
--- a/tests/test_sphinx_autodoc_typehints.py
+++ b/tests/test_sphinx_autodoc_typehints.py
@@ -370,6 +370,8 @@ def set_python_path() -> None:
 def maybe_fix_py310(expected_contents: str) -> str:
     if PY310_PLUS:
         for old, new in [
+            ("*bool** | **None*", '"bool" | "None"'),
+            ("*int** | **str** | **float*", '"int" | "str" | "float"'),
             ("*str** | **None*", '"Optional"["str"]'),
             ("(*bool*)", '("bool")'),
             ("(*int*", '("int"'),
@@ -704,9 +706,9 @@ def test_sphinx_output_future_annotations(app: SphinxTestApp, status: StringIO)
            Method docstring.
 
            Parameters:
-              * **x** (*bool*) -- foo
+              * **x** (*bool** | **None*) -- foo
 
-              * **y** (*int*) -- bar
+              * **y** (*int** | **str** | **float*) -- bar
 
               * **z** (*str** | **None*) -- baz
Repository: tox-dev/sphinx-autodoc-typehints
Pull request #288 (2023-01-14 05:57:00)

Put Literal args in code blocks
This is a pretty minor change, but I think it improves the visual consistency of the types.

#### Before:
![Screenshot from 2023-01-13 21-40-15](https://user-images.githubusercontent.com/8739626/212457866-1fb7600e-d487-4793-8505-73e36f73c2c8.png)

#### After:
![Screenshot from 2023-01-13 21-40-23](https://user-images.githubusercontent.com/8739626/212457874-798f0522-120c-434a-95c7-55e18cbc3494.png)




Patch:
diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py
index 7788c68..84de30e 100644
--- a/src/sphinx_autodoc_typehints/__init__.py
+++ b/src/sphinx_autodoc_typehints/__init__.py
@@ -181,7 +181,7 @@ def format_annotation(annotation: Any, config: Config) -> str:  # noqa: C901 # t
         fmt = [format_annotation(arg, config) for arg in args]
         formatted_args = f"\\[\\[{', '.join(fmt[:-1])}], {fmt[-1]}]"
     elif full_name == "typing.Literal":
-        formatted_args = f"\\[{', '.join(repr(arg) for arg in args)}]"
+        formatted_args = "\\[{}]".format(", ".join(f"``{arg!r}``" for arg in args))
     elif full_name == "types.UnionType":
         return " | ".join([format_annotation(arg, config) for arg in args])
 


Test patch:
diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py
index 73b3dcf..c6aa046 100644
--- a/tests/test_sphinx_autodoc_typehints.py
+++ b/tests/test_sphinx_autodoc_typehints.py
@@ -360,7 +360,7 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str
     [
         ("ClassVar", int, ":py:data:`~typing.ClassVar`\\[:py:class:`int`]"),
         ("NoReturn", None, ":py:data:`~typing.NoReturn`"),
-        ("Literal", ("a", 1), ":py:data:`~typing.Literal`\\['a', 1]"),
+        ("Literal", ("a", 1), ":py:data:`~typing.Literal`\\[``'a'``, ``1``]"),
         ("Type", None, ":py:class:`~typing.Type`"),
         ("Type", (A,), f":py:class:`~typing.Type`\\[:py:class:`~{__name__}.A`]"),
     ],
Repository: tox-dev/sphinx-autodoc-typehints
Pull request #290 (2023-01-15 01:28:39)

Put rtype before examples or usage section
Sometimes a function's documentation will contain a section like 'Usage' or 'Examples', warnings about edge cases, etc. These sections are introduced with a `.. directive::`. This makes it so that sphinx-autodoc-typehints inserts the return type ahead of these sections, rather than after them.


Patch:
diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py
index a4b474f..8aa7d4d 100644
--- a/src/sphinx_autodoc_typehints/__init__.py
+++ b/src/sphinx_autodoc_typehints/__init__.py
@@ -625,6 +625,10 @@ def _inject_types_to_docstring(
                     insert_index = None
                     break
                 insert_index = at
+            elif line.startswith(".."):
+                # Make sure that rtype comes before any usage or examples section
+                insert_index = at
+                break
 
         if insert_index is not None and app.config.typehints_document_rtype:
             if insert_index == len(lines):  # ensure that :rtype: doesn't get joined with a paragraph of text


Test patch:
diff --git a/tests/roots/test-dummy/dummy_module.py b/tests/roots/test-dummy/dummy_module.py
index a3c9fcc..ab84c96 100644
--- a/tests/roots/test-dummy/dummy_module.py
+++ b/tests/roots/test-dummy/dummy_module.py
@@ -276,3 +276,13 @@ def mocked_import(x: Mailbox):  # noqa: U100
 
     :param x: function
     """
+
+
+def func_with_examples() -> int:
+    """
+    A docstring.
+
+    .. rubric:: Examples
+
+    Here are a couple of examples of how to use this function.
+    """
diff --git a/tests/roots/test-dummy/index.rst b/tests/roots/test-dummy/index.rst
index fac0186..d4eadb9 100644
--- a/tests/roots/test-dummy/index.rst
+++ b/tests/roots/test-dummy/index.rst
@@ -38,3 +38,5 @@ Dummy Module
 .. autodecorator:: dummy_module.Decorator
 
 .. autofunction:: dummy_module.mocked_import
+
+.. autofunction:: dummy_module.func_with_examples
diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py
index 330dd06..acb483b 100644
--- a/tests/test_sphinx_autodoc_typehints.py
+++ b/tests/test_sphinx_autodoc_typehints.py
@@ -748,6 +748,17 @@ def test_sphinx_output(
 
            Parameters:
               **x** ("Mailbox") -- function
+
+        dummy_module.func_with_examples()
+
+           A docstring.
+
+           Return type:
+              "int"
+
+           -[ Examples ]-
+
+           Here are a couple of examples of how to use this function.
         """
         expected_contents = dedent(expected_contents).format(**format_args).replace("–", "--")
         assert text_contents == maybe_fix_py310(expected_contents)
Repository: tox-dev/tox
Pull request #382 (2016-10-13 09:52:41)

Add support for Python 3.7
This allows testing on Travis CI 'nightly'.
Also add Travis CI testing on '3.6-dev',
and enable Travis CI fast finishing as
problems with 3.6-dev are likely to also
occur with nightly (3.7-dev)


Patch:
diff --git a/.travis.yml b/.travis.yml
index 98a30c1e..5bf8719f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,10 +5,15 @@ python:
 - '3.3'
 - '3.4'
 - '3.5'
+- 3.6-dev
+- nightly
 - pypy
 
 matrix:
+  fast_finish: true
   allow_failures:
+  - python: 3.6-dev
+  - python: nightly
   - python: pypy
 cache: python
 install: pip install tox
diff --git a/CHANGELOG b/CHANGELOG
index b15f81d7..b18708b0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,9 +1,3 @@
-2.4.1
------
-
-- fix issue380: properly perform substitution again. Thanks Ian
-  Cordasco.
-
 2.4.0
 -----
 
diff --git a/setup.py b/setup.py
index 051f98ba..6db3f4e3 100644
--- a/setup.py
+++ b/setup.py
@@ -48,7 +48,7 @@ def main():
         description='virtualenv-based automation of test activities',
         long_description=open("README.rst").read(),
         url='https://tox.readthedocs.org/',
-        version='2.4.1',
+        version='2.4.0',
         license='http://opensource.org/licenses/MIT',
         platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
         author='holger krekel',
diff --git a/tox/__init__.py b/tox/__init__.py
index b202fe59..c91d4b9c 100644
--- a/tox/__init__.py
+++ b/tox/__init__.py
@@ -1,5 +1,5 @@
 #
-__version__ = '2.4.1'
+__version__ = '2.4.0'
 
 from .hookspecs import hookspec, hookimpl  # noqa
 
diff --git a/tox/config.py b/tox/config.py
index c1d894a1..f3fa3950 100644
--- a/tox/config.py
+++ b/tox/config.py
@@ -22,7 +22,7 @@ iswin32 = sys.platform == "win32"
 
 default_factors = {'jython': 'jython', 'pypy': 'pypy', 'pypy3': 'pypy3',
                    'py': sys.executable}
-for version in '26,27,32,33,34,35,36'.split(','):
+for version in '26,27,32,33,34,35,36,37'.split(','):
     default_factors['py' + version] = 'python%s.%s' % tuple(version)
 
 hookimpl = pluggy.HookimplMarker("tox")


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
index 9c10c387..c26063eb 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1468,7 +1468,7 @@ class TestGlobalOptions:
         assert str(env.basepython) == sys.executable
 
     def test_default_environments(self, tmpdir, newconfig, monkeypatch):
-        envs = "py26,py27,py32,py33,py34,py35,py36,jython,pypy,pypy3"
+        envs = "py26,py27,py32,py33,py34,py35,py36,py37,jython,pypy,pypy3"
         inisource = """
             [tox]
             envlist = %s
Repository: tox-dev/tox
Pull request #402 (2016-11-05 17:39:10)

Add {:} -> os.pathsep substitute
Alternative approach to PR #397


Patch:
diff --git a/CHANGELOG b/CHANGELOG
index 89b8fcd4..c1f98b54 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -21,6 +21,7 @@ unreleased
 
 - make "-h" and "--help-ini" options work even if there is no tox.ini
 
+- add {:} substitution, which is replaced with os-specific path separator
 
 2.4.1
 -----
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index a4c13e32..8eb5af1e 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -33,3 +33,4 @@ Eugene Yunak
 Mark Hirota
 Itxaka Serrano
 Alex Grönholm
+Lukasz Rogalski
diff --git a/doc/config.txt b/doc/config.txt
index dab7777c..c656b1b5 100644
--- a/doc/config.txt
+++ b/doc/config.txt
@@ -362,6 +362,10 @@ Globally available substitutions
     (DEPRECATED) the directory where sdist-packages will be copied to so that
     they may be accessed by other processes or tox runs.
 
+``{:}``
+    OS-specific path separator (``:`` os *nix family, ``;`` on Windows). May be used in `setenv`,
+    when target variable is path variable (e.g. PATH or PYTHONPATH).
+
 substitutions for virtualenv-related sections
 +++++++++++++++++++++++++++++++++++++++++++++
 
diff --git a/tox/config.py b/tox/config.py
index e1e65278..e5b6b007 100644
--- a/tox/config.py
+++ b/tox/config.py
@@ -1051,6 +1051,10 @@ class Replacer:
             start, end = match.span()
             return match.string[start:end]
 
+        # special case: all empty values means ":" which is os.pathsep
+        if not any(g.values()):
+            return os.pathsep
+
         # special case: opts and packages. Leave {opts} and
         # {packages} intact, they are replaced manually in
         # _venv.VirtualEnv.run_install_command.


Test patch:
diff --git a/tests/test_config.py b/tests/test_config.py
index 6445a099..d7f8b121 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1888,6 +1888,28 @@ class TestIndexServer:
         assert config.indexserver['local1'].url == config.indexserver['default'].url
 
 
+class TestConfigConstSubstitutions:
+    @pytest.mark.parametrize('pathsep', [':', ';'])
+    def test_replace_pathsep_unix(self, monkeypatch, newconfig, pathsep):
+        monkeypatch.setattr('os.pathsep', pathsep)
+        config = newconfig("""
+        [testenv]
+        setenv =
+            PATH = dira{:}dirb{:}dirc
+        """)
+        envconfig = config.envconfigs["python"]
+        assert envconfig.setenv["PATH"] == pathsep.join(["dira", "dirb", "dirc"])
+
+    def test_pathsep_regex(self):
+        """Sanity check for regex behavior for empty colon."""
+        regex = tox.config.Replacer.RE_ITEM_REF
+        match = next(regex.finditer("{:}"))
+        mdict = match.groupdict()
+        assert mdict['sub_type'] is None
+        assert mdict['substitution_value'] == ""
+        assert mdict['default_value'] == ""
+
+
 class TestParseEnv:
 
     def test_parse_recreate(self, newconfig):