Repository: pypa/virtualenv

Issue:
Broken activation in Windows for python3
virtualenv activation through `activate_this.py` is broken in Windows for python3. Check this very simple piece of code

```
import os
import subprocess
import sys
from distutils.spawn import find_executable

venv = find_executable("virtualenv")
testdir = os.path.join(os.path.curdir, 'testenv')

subprocess.check_output((venv, testdir, "-p", sys.executable))

bin_path = os.path.join(testdir, "Scripts") if sys.platform in ("win32", "cygwin") else os.path.join(testdir, "bin")

path = os.path.join(bin_path, "activate_this.py")
with open(path) as f:
    exec(f.read(), {"__file__": path})
```

This generates a `AttributeError: 'str' object has no attribute 'decode'`. Taking a look at the `activate_this.py` code:

```
for lib in "..\Lib\site-packages".split(os.pathsep):
    path = os.path.realpath(os.path.join(bin_dir, lib))
    site.addsitedir(path.decode("utf-8") if "yes" else path)
```

it's indeed normal that we get the error because we're always calling `decode()` over a str. Question is where the `__DECODE_PATH__` from https://github.com/pypa/virtualenv/blob/master/src/virtualenv/activation/python/activate_this.py#L28 is assigned to `"yes"`?


Discussion:
it comes from here (it gets replaced): https://github.com/pypa/virtualenv/blob/52e4213096eba07ce71c14f36135172ea4c4a192/src/virtualenv/activation/python/__init__.py#L23

it should probably be substituted as a boolean or `== "yes"` as a fix
actually no, it looks correct as written, that'll only be truthy in cpython2.x windows (assuming the constant is correct)
ah, but the constant is for the host python, not the destination python
Yeah so the thing is why is it "yes" when executing the above script using python3 ?
in this case it's "yes" because you used a python2.x `virtualenv` executable to create a python3.x virtualenv -- the constant shouldn't be using the host python when templating that file is the bug

you can work around by using a python3.x `virtualenv` executable to create your virtualenv
well I'm using `py -3` to execute it, not sure why is invoking the py2 `virtualenv`... my windows knowledge is pretty limitted though
right, it's not about the python that executes that script, but the python that was used to create the virtualenv

to be clear, there's a bug in virtualenv here -- but a workaround is to use the same python version when creating the virtualenv
Ah yeah, I've just skimmed through the PATH variable in windows and it turns out that py2.7 is listed before than py3 so `find_executable()` indeed locates the py2 `virtualenv` executable
Just for reference I think I can workaround it by doing something like
```
search_path = os.path.dirname(sys.executable)
find_executable('virtualenv', search_path)
```
and for the case of windows I guess I should concat `Scripts` to the `search_path`

Resolving patch:
diff --git a/src/virtualenv/activation/python/__init__.py b/src/virtualenv/activation/python/__init__.py
--- a/src/virtualenv/activation/python/__init__.py
+++ b/src/virtualenv/activation/python/__init__.py
@@ -3,7 +3,6 @@
 import os
 from collections import OrderedDict
 
-from virtualenv.info import WIN_CPYTHON_2
 from virtualenv.util.path import Path
 from virtualenv.util.six import ensure_text
 
@@ -17,10 +16,11 @@ def templates(self):
     def replacements(self, creator, dest_folder):
         replacements = super(PythonActivator, self).replacements(creator, dest_folder)
         lib_folders = OrderedDict((os.path.relpath(str(i), str(dest_folder)), None) for i in creator.libs)
+        win_py2 = creator.interpreter.platform == "win32" and creator.interpreter.version_info.major == 2
         replacements.update(
             {
                 "__LIB_FOLDERS__": ensure_text(os.pathsep.join(lib_folders.keys())),
-                "__DECODE_PATH__": ("yes" if WIN_CPYTHON_2 else ""),
+                "__DECODE_PATH__": ("yes" if win_py2 else ""),
             }
         )
         return replacements


Test patch: