From 9ab8521a1c09558339900041647b2466c2709de9 Mon Sep 17 00:00:00 2001
From: "Adam J. Stewart" <ajstewart426@gmail.com>
Date: Fri, 14 Aug 2020 09:08:42 -0500
Subject: [PATCH] Python: add spack external find support (#16684)

---
 .../repos/builtin/packages/python/package.py  | 76 +++++++++++++++++++
 1 file changed, 76 insertions(+)

diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py
index 16bd621504..4282d8e014 100644
--- a/var/spack/repos/builtin/packages/python/package.py
+++ b/var/spack/repos/builtin/packages/python/package.py
@@ -224,6 +224,75 @@ class Python(AutotoolsPackage):
     # An in-source build with --enable-optimizations fails for python@3.X
     build_directory = 'spack-build'
 
+    executables = [r'^python[\d.]*[mw]?$']
+
+    @classmethod
+    def determine_version(cls, exe):
+        # Newer versions of Python support `--version`,
+        # but older versions only support `-V`
+        # Python 2 sends to STDERR, while Python 3 sends to STDOUT
+        # Output looks like:
+        #   Python 3.7.7
+        output = Executable(exe)('-V', output=str, error=str)
+        match = re.search(r'Python\s+(\S+)', output)
+        return match.group(1) if match else None
+
+    @classmethod
+    def determine_variants(cls, exes, version_str):
+        python = Executable(exes[0])
+
+        variants = ''
+        for module in ['readline', 'sqlite3', 'dbm', 'nis',
+                       'zlib', 'bz2', 'lzma', 'ctypes', 'uuid']:
+            try:
+                python('-c', 'import ' + module, error=os.devnull)
+                variants += '+' + module
+            except ProcessError:
+                variants += '~' + module
+
+        # Some variants enable multiple modules
+        try:
+            python('-c', 'import ssl', error=os.devnull)
+            python('-c', 'import hashlib', error=os.devnull)
+            variants += '+ssl'
+        except ProcessError:
+            variants += '~ssl'
+
+        try:
+            python('-c', 'import xml.parsers.expat', error=os.devnull)
+            python('-c', 'import xml.etree.ElementTree', error=os.devnull)
+            variants += '+pyexpat'
+        except ProcessError:
+            variants += '~pyexpat'
+
+        # Some modules changed names in Python 3
+        if Version(version_str) >= Version('3'):
+            try:
+                python('-c', 'import tkinter', error=os.devnull)
+                variants += '+tkinter'
+            except ProcessError:
+                variants += '~tkinter'
+
+            try:
+                python('-c', 'import tkinter.tix', error=os.devnull)
+                variants += '+tix'
+            except ProcessError:
+                variants += '~tix'
+        else:
+            try:
+                python('-c', 'import Tkinter', error=os.devnull)
+                variants += '+tkinter'
+            except ProcessError:
+                variants += '~tkinter'
+
+            try:
+                python('-c', 'import Tix', error=os.devnull)
+                variants += '+tix'
+            except ProcessError:
+                variants += '~tix'
+
+        return variants
+
     def url_for_version(self, version):
         url = "https://www.python.org/ftp/python/{0}/Python-{1}.tgz"
         return url.format(re.split('[a-z]', str(version))[0], version)
@@ -606,6 +675,13 @@ def import_tests(self):
             if '+uuid' in spec:
                 self.command('-c', 'import uuid')
 
+            # Ensure that tix module works
+            if '+tix' in spec:
+                if spec.satisfies('@3:'):
+                    self.command('-c', 'import tkinter.tix')
+                else:
+                    self.command('-c', 'import Tix')
+
     # ========================================================================
     # Set up environment to make install easy for python extensions.
     # ========================================================================
-- 
GitLab