pw_presubmit: Always rerun virtualenv setup

The virtualenv setup is now fast enough that it can always be run.

Bug: 287
Change-Id: I55c8de48bdcef53295f36d8814887134b31f87d5
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/23502
Commit-Queue: Rob Mohr <mohrr@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
index 774962a..f70c067 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/install.py
@@ -16,6 +16,7 @@
 from __future__ import print_function
 
 import glob
+import hashlib
 import os
 import re
 import subprocess
@@ -26,13 +27,21 @@
 class GnTarget(object):  # pylint: disable=useless-object-inheritance
     def __init__(self, val):
         self.directory, self.target = val.split('#', 1)
+        # hash() doesn't necessarily give the same value in new runs of Python,
+        # so compute a unique id for this object that's consistent from run to
+        # run.
+        try:
+            val = val.encode()
+        except AttributeError:
+            pass
+        self._unique_id = hashlib.md5(val).hexdigest()
 
     @property
     def name(self):
         """A reasonably stable and unique name for each pair."""
         result = '{}-{}'.format(
             os.path.basename(os.path.normpath(self.directory)),
-            hash(self.directory + self.target))
+            self._unique_id)
         return re.sub(r'[:/#_]+', '_', result)
 
 
diff --git a/pw_presubmit/py/pw_presubmit/environment.py b/pw_presubmit/py/pw_presubmit/environment.py
index 23aa347..98a935d 100644
--- a/pw_presubmit/py/pw_presubmit/environment.py
+++ b/pw_presubmit/py/pw_presubmit/environment.py
@@ -83,14 +83,12 @@
     if not gn_targets:
         gn_targets = (f'{os.environ["PW_ROOT"]}#:python.install', )
 
-    # For speed, don't build the venv if it exists. Use --clean to rebuild.
-    if not output_directory.joinpath('pyvenv.cfg').is_file():
-        call(
-            'python3',
-            virtualenv_source,
-            f'--venv_path={output_directory}',
-            f'--requirements={virtualenv_source / "requirements.txt"}',
-            *(f'--requirements={x}' for x in requirements),
-            *(f'--setup-py-root={p}' for p in setup_py_roots),
-            *(f'--gn-target={t}' for t in gn_targets),
-        )
+    call(
+        'python3',
+        virtualenv_source,
+        f'--venv_path={output_directory}',
+        f'--requirements={virtualenv_source / "requirements.txt"}',
+        *(f'--requirements={x}' for x in requirements),
+        *(f'--setup-py-root={p}' for p in setup_py_roots),
+        *(f'--gn-target={t}' for t in gn_targets),
+    )