Repository: pypa/virtualenv

Issue:
20b1 feedback: Unable to generate bash "activate" script on Windows.
Hello!

Working on Windows 10, using Git Bash as my default shell pretty much everywhere.

From my understanding, the bash activation script is not generated by default on Windows anymore.
That's going to break users in a similar solution to mine.

But the really bad news for me:
```
$ python -m virtualenv --activators bash myvirtualenv
usage: virtualenv [--version] [-v | -q] [--discovery {builtin}] [-p py] [--creator {builtin,cpython2-win}] [--seeder {app-data,none,pip}] [--without-pip] [--activators comma_separated_list]
virtualenv: error: argument --activators: the following activators are not available bash
```
`bash` is considered not available on Windows, and that's a no-go for me, or anyone using a bash equivalent on Windows.

I'd plead for keeping bash script by default on Windows.
Or at the very least, allow it as an option, although its still going to be a pain.

Cheers!




Discussion:
Does anyone have any idea how we can check if bash is available on Windows? 
Though maybe we should generate both bash and fish by default all the time 🤷‍♂ https://fishshell.com/ seems to be also available on all platforms.

Resolving patch:
diff --git a/src/virtualenv/activation/bash/__init__.py b/src/virtualenv/activation/bash/__init__.py
--- a/src/virtualenv/activation/bash/__init__.py
+++ b/src/virtualenv/activation/bash/__init__.py
@@ -6,10 +6,6 @@
 
 
 class BashActivator(ViaTemplateActivator):
-    @classmethod
-    def supports(cls, interpreter):
-        return interpreter.os != "nt"
-
     def templates(self):
         yield Path("activate.sh")
 
diff --git a/src/virtualenv/activation/fish/__init__.py b/src/virtualenv/activation/fish/__init__.py
--- a/src/virtualenv/activation/fish/__init__.py
+++ b/src/virtualenv/activation/fish/__init__.py
@@ -8,7 +8,3 @@
 class FishActivator(ViaTemplateActivator):
     def templates(self):
         yield Path("activate.fish")
-
-    @classmethod
-    def supports(cls, interpreter):
-        return interpreter.os != "nt"
diff --git a/src/virtualenv/util/subprocess/_win_subprocess.py b/src/virtualenv/util/subprocess/_win_subprocess.py
--- a/src/virtualenv/util/subprocess/_win_subprocess.py
+++ b/src/virtualenv/util/subprocess/_win_subprocess.py
@@ -4,6 +4,7 @@
 
 import ctypes
 import os
+import platform
 import subprocess
 from ctypes import Structure, WinError, byref, c_char_p, c_void_p, c_wchar, c_wchar_p, sizeof, windll
 from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LPVOID, LPWSTR, WORD
@@ -133,7 +134,10 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
         if startupinfo is None:
             startupinfo = subprocess.STARTUPINFO()
         if not isinstance(args, subprocess.types.StringTypes):
+            args = [i if isinstance(i, bytes) else i.encode('utf-8') for i in args]
             args = subprocess.list2cmdline(args)
+            if platform.python_implementation() == "CPython":
+                args = args.decode('utf-8')
         startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
         startupinfo.wShowWindow = _subprocess.SW_HIDE
         comspec = os.environ.get("COMSPEC", unicode("cmd.exe"))


Test patch:
diff --git a/tests/unit/activation/test_activation_support.py b/tests/unit/activation/test_activation_support.py
--- a/tests/unit/activation/test_activation_support.py
+++ b/tests/unit/activation/test_activation_support.py
@@ -15,7 +15,9 @@
 from virtualenv.discovery.py_info import PythonInfo
 
 
-@pytest.mark.parametrize("activator_class", [BatchActivator, PowerShellActivator, PythonActivator])
+@pytest.mark.parametrize(
+    "activator_class", [BatchActivator, PowerShellActivator, PythonActivator, BashActivator, FishActivator]
+)
 def test_activator_support_windows(mocker, activator_class):
     activator = activator_class(Namespace(prompt=None))
 
@@ -24,7 +26,7 @@ def test_activator_support_windows(mocker, activator_class):
     assert activator.supports(interpreter)
 
 
-@pytest.mark.parametrize("activator_class", [BashActivator, CShellActivator, FishActivator])
+@pytest.mark.parametrize("activator_class", [CShellActivator])
 def test_activator_no_support_windows(mocker, activator_class):
     activator = activator_class(Namespace(prompt=None))
 
diff --git a/tests/unit/activation/test_fish.py b/tests/unit/activation/test_fish.py
--- a/tests/unit/activation/test_fish.py
+++ b/tests/unit/activation/test_fish.py
@@ -1,8 +1,12 @@
 from __future__ import absolute_import, unicode_literals
 
+import pytest
+
 from virtualenv.activation import FishActivator
+from virtualenv.info import IS_WIN
 
 
+@pytest.mark.skipif(IS_WIN, reason="we have not setup fish in CI yet")
 def test_fish(activation_tester_class, activation_tester):
     class Fish(activation_tester_class):
         def __init__(self, session):
diff --git a/tests/unit/discovery/test_discovery.py b/tests/unit/discovery/test_discovery.py
--- a/tests/unit/discovery/test_discovery.py
+++ b/tests/unit/discovery/test_discovery.py
@@ -36,6 +36,6 @@ def test_discovery_via_path(monkeypatch, case, special_name_dir, caplog):
 
 
 def test_discovery_via_path_not_found(tmp_path, monkeypatch):
-    monkeypatch.setenv("PATH", str(tmp_path))
+    monkeypatch.setenv(str("PATH"), str(tmp_path))
     interpreter = get_interpreter(uuid4().hex)
     assert interpreter is None