<commit_before># -*- coding: utf-8 -*-
"""
This module provides the necessary definitions to generate a Python Interpreter object.
"""

import os
import csv
import fnmatch
import uuid
import subprocess
try:
    import winreg
except ImportError:
    import _winreg as winreg
from pymake.register import PyRegisterable

class PymakeInterpreter(PyRegisterable):
    """
    PymakeInterpreter encapsulates the logic and data used to describe a Python interpreter or virtual environments

    :ivar GUID:                    The GUID of the Python Interpreter; if not provided one is generated automatically.
    :ivar BaseInterpreter:         The GUID of the base Python Interpreter (different if PymakeInterpreter is Virtual Environment); if not provided the value is self.GUID
    :ivar Architecture:            The architecture (either x86 or Amd64). if not provide the value is "".
    :ivar Version:                 The major.minor version string; if not provide the value is "".
    :ivar Description:             The human readable description string; if not provide the value is ""
    :ivar Path:                    The absolute path of the 'python.exe'; if not provide the value is ""
    :ivar InterpreterPath:         The relative path to self.Path of the 'python.exe'; if not provide the value is ""
    :ivar WindowsInterpreterPath:  The relative path to self.Path of the 'pythonw.exe'; if not provide the value is ""
    :ivar LibraryPath:             The relative path to self.Path of the 'Lib' folder that is part of the python.exe distribution; if not provide the value is "".
    :ivar PathEnvironmentVariable: The name of the Environment variable to be uses as PYTHONPATH; if not provide the value is "".
    """
    __registerable_name__ = "Python Interpreter"

    #: PTVS Interpreter Register Location
    regkey_name = r'Software\Microsoft\VisualStudio\{VSVersion}\PythonTools\Interpreters'

    def __init__(self, **kwargs):
        """
        Constructor.

        :param **kwargs:         List of arbitrary keyworded arguments to be processed as instance variable data
        """
        super(PymakeInterpreter, self).__init__()
        self._import(kwargs)

    @staticmethod
    def from_virtual_environment(directory, **kwargs):
        """
        Creates a PymakeInterpreter from an Python Virtual Environment in the directory.

        :param directory: The absolute path to the python installation directory.
        :param **kwargs:  List of additional keyworded arguments to be passed into the PymakeInterpreter.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'Scripts', 'python.exe'))
        if not os.path.exists(python):
            return None

        root = os.path.abspath(directory)
        origprefix = os.path.abspath(os.path.join(root, 'Lib', 'orig-prefix.txt'))
        if not os.path.exists(origprefix):
            return None
        
        with open(origprefix, 'rt') as f:
            basedir = next((line.rstrip() for line in f), None)
            baseinterpretter = PymakeInterpreter.from_python_installation(basedir,  **kwargs)
        if not baseinterpretter:
            return None

        args = kwargs.copy()
        args['Path'] = root
        args['BaseInterpreter'] = baseinterpretter.GUID
        args['InterpreterPath'] = os.path.join('Scripts', 'python.exe')
        args.setdefault('Description', '{} ({})'.format(os.path.basename(root), baseinterpretter.Description))

        if os.path.exists(os.path.join(root, 'Scripts', 'pythonw.exe')):
            args['WindowsInterpreterPath'] = os.path.join('Scripts', 'pythonw.exe')

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.decode("utf-8").rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.decode("utf-8").rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        return interpreter

    @staticmethod
    def from_python_installation(directory, **kwargs):
        """
        Creates a PymakeInterpreter from an Python Installation in the directory.

        :param directory: The absolute path to the python installation directory.
        :param **kwargs:  List of additional keyworded arguments to be passed into the PymakeInterpreter.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'python.exe'))
        if not os.path.exists(python):
            return None
        
        args = kwargs.copy()
        args['Path'] = root
        args['InterpreterPath'] = 'python.exe'
        args.setdefault('Description', os.path.basename(root))

        if os.path.exists(os.path.join(root, 'pythonw.exe')):
            args['WindowsInterpreterPath'] = 'pythonw.exe'

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.decode("utf-8").rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.decode("utf-8").rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        interpreter.resolve()
        return interpreter

    @staticmethod
    def from_registry_key(keyname):
        """
        Creates a PymakeInterpreter from a single registry key.

        :param keyname:  The keyname under HKEY_CURRENT_USER referring to the environment.       
        :return:         A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        args = {}
        try:
            regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, keyname)
            for k in ['Architecture', 'Description', 'InterpreterPath', 'LibraryPath', 'PathEnvironmentVariable', 'Version', 'WindowsInterpreterPath', 'PathEnvironmentVariable']:
                args[k] = winreg.QueryValueEx(regkey, k)[0]        
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            pass

        if 'InterpreterPath' in args:
            args['Path'] = os.path.dirname(args['InterpreterPath'])
            args['Id'] = os.path.basename(keyname)[1:-1]
            return PymakeInterpreter(**args) 
        return None

    def _import(self, datadict):
        """
        Internal method to import instance variables data from a dictionary. 

        :param datadict: The dictionary containing variables values.
        """
        self.GUID                       = datadict.get('Id', uuid.uuid1())
        self.BaseInterpreter            = datadict.get('BaseInterpreter', self.GUID)
        self.Architecture               = datadict.get('Architecture', "")
        self.Version                    = datadict.get('Version', "")
        self.Path                       = datadict.get('Path', "")
        self.Description                = datadict.get('Description', "")
        self.InterpreterPath            = datadict.get('InterpreterPath', "")
        self.InterpreterAbsPath         = datadict.get('InterpreterAbsPath', self.InterpreterPath if os.path.isabs(self.InterpreterPath) else os.path.abspath(os.path.join(self.Path, self.InterpreterPath)))
        self.WindowsInterpreterPath     = datadict.get('WindowsInterpreterPath', "")
        self.WindowsInterpreterAbsPath  = datadict.get('WindowsInterpreterAbsPath', self.WindowsInterpreterPath if os.path.isabs(self.WindowsInterpreterPath) else os.path.abspath(os.path.join(self.Path, self.WindowsInterpreterPath)))
        self.LibraryPath                = datadict.get('LibraryPath', "")
        self.LibraryAbsPath             = datadict.get('LibraryAbsPath', self.LibraryPath if os.path.isabs(self.LibraryPath) else os.path.abspath(os.path.join(self.Path, self.LibraryPath)))
        self.PathEnvironmentVariable    = datadict.get('PathEnvironmentVariable', "PYTHONPATH")
        self.VSVersion                  = datadict.get('VSVersion', None)

    def resolve(self):
        """
        'Resolves' the environment with existing environments in the windows registry.
        """
        if not self.VSVersion:
            raise ValueError('Cannot resolve interpreter with invalid Visual Studio Version')

        regkey_name = self.regkey_name.format(VSVersion=self.VSVersion)
        try:
            vs_regkey_name = os.path.dirname(regkey_name)
            winreg.OpenKey(winreg.HKEY_CURRENT_USER, vs_regkey_name)
        except WindowsError as ex:
            raise ValueError('Cannot resolve interpreter with Visual Studio %s that is not installed.' % str(self.VSVersion))

        regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, regkey_name)
        try:
            reginfo = winreg.QueryInfoKey(regkey)
            for i in range(reginfo[0]):
                interpreter_regkey_name = '{0}\\{1}'.format(regkey_name, winreg.EnumKey(regkey, i))
                interpreter = PymakeInterpreter.from_registry_key(interpreter_regkey_name)
                if interpreter and interpreter.InterpreterAbsPath == self.InterpreterAbsPath:
                    self.GUID = uuid.UUID(interpreter.GUID)
                    self.BaseInterpreter = self.GUID
                    break
        except WindowsError as ex:
            pass

    def register(self):
        """
        'Registers' the environment into the windows registry.

        :..note: https://pytools.codeplex.com/workitem/2765
        """
        if not self.VSVersion:
            raise ValueError('Cannot register interpreter with invalid Visual Studio Version')

        regkey_name = self.regkey_name.format(VSVersion=self.VSVersion)
        try:
            vs_regkey_name = os.path.dirname(regkey_name)
            winreg.OpenKey(winreg.HKEY_CURRENT_USER, vs_regkey_name)
        except WindowsError as ex:
            raise ValueError('Cannot register interpreter with Visual Studio %s that is not installed.' % str(self.VSVersion))

        interpreter_regkey_name = '{0}\\{{{1}}}'.format(regkey_name, str(self.GUID).lower())
        try:
            regkey = winreg.CreateKey(winreg.HKEY_CURRENT_USER, interpreter_regkey_name)
            winreg.SetValueEx(regkey, 'Architecture', 0, winreg.REG_SZ, self.Architecture)
            winreg.SetValueEx(regkey, 'Description', 0, winreg.REG_SZ, self.Description)
            winreg.SetValueEx(regkey, 'InterpreterPath', 0, winreg.REG_SZ, self.InterpreterAbsPath)
            winreg.SetValueEx(regkey, 'LibraryPath', 0, winreg.REG_SZ, self.LibraryAbsPath)
            winreg.SetValueEx(regkey, 'Version', 0, winreg.REG_SZ, self.Version)
            winreg.SetValueEx(regkey, 'WindowsInterpreterPath', 0, winreg.REG_SZ, self.WindowsInterpreterAbsPath)
            winreg.SetValueEx(regkey, 'PathEnvironmentVariable', 0, winreg.REG_SZ, self.PathEnvironmentVariable)
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            return False
        return True
<commit_msg>Updated exception message used for missing PTVS installations.<commit_after># -*- coding: utf-8 -*-
"""
This module provides the necessary definitions to generate a Python Interpreter object.
"""

import os
import csv
import fnmatch
import uuid
import subprocess
try:
    import winreg
except ImportError:
    import _winreg as winreg
from pymake.register import PyRegisterable

class PymakeInterpreter(PyRegisterable):
    """
    PymakeInterpreter encapsulates the logic and data used to describe a Python interpreter or virtual environments

    :ivar GUID:                    The GUID of the Python Interpreter; if not provided one is generated automatically.
    :ivar BaseInterpreter:         The GUID of the base Python Interpreter (different if PymakeInterpreter is Virtual Environment); if not provided the value is self.GUID
    :ivar Architecture:            The architecture (either x86 or Amd64). if not provide the value is "".
    :ivar Version:                 The major.minor version string; if not provide the value is "".
    :ivar Description:             The human readable description string; if not provide the value is ""
    :ivar Path:                    The absolute path of the 'python.exe'; if not provide the value is ""
    :ivar InterpreterPath:         The relative path to self.Path of the 'python.exe'; if not provide the value is ""
    :ivar WindowsInterpreterPath:  The relative path to self.Path of the 'pythonw.exe'; if not provide the value is ""
    :ivar LibraryPath:             The relative path to self.Path of the 'Lib' folder that is part of the python.exe distribution; if not provide the value is "".
    :ivar PathEnvironmentVariable: The name of the Environment variable to be uses as PYTHONPATH; if not provide the value is "".
    """
    __registerable_name__ = "Python Interpreter"

    #: PTVS Interpreter Register Location
    regkey_name = r'Software\Microsoft\VisualStudio\{VSVersion}\PythonTools\Interpreters'

    def __init__(self, **kwargs):
        """
        Constructor.

        :param **kwargs:         List of arbitrary keyworded arguments to be processed as instance variable data
        """
        super(PymakeInterpreter, self).__init__()
        self._import(kwargs)

    @staticmethod
    def from_virtual_environment(directory, **kwargs):
        """
        Creates a PymakeInterpreter from an Python Virtual Environment in the directory.

        :param directory: The absolute path to the python installation directory.
        :param **kwargs:  List of additional keyworded arguments to be passed into the PymakeInterpreter.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'Scripts', 'python.exe'))
        if not os.path.exists(python):
            return None

        root = os.path.abspath(directory)
        origprefix = os.path.abspath(os.path.join(root, 'Lib', 'orig-prefix.txt'))
        if not os.path.exists(origprefix):
            return None
        
        with open(origprefix, 'rt') as f:
            basedir = next((line.rstrip() for line in f), None)
            baseinterpretter = PymakeInterpreter.from_python_installation(basedir,  **kwargs)
        if not baseinterpretter:
            return None

        args = kwargs.copy()
        args['Path'] = root
        args['BaseInterpreter'] = baseinterpretter.GUID
        args['InterpreterPath'] = os.path.join('Scripts', 'python.exe')
        args.setdefault('Description', '{} ({})'.format(os.path.basename(root), baseinterpretter.Description))

        if os.path.exists(os.path.join(root, 'Scripts', 'pythonw.exe')):
            args['WindowsInterpreterPath'] = os.path.join('Scripts', 'pythonw.exe')

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.decode("utf-8").rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.decode("utf-8").rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        return interpreter

    @staticmethod
    def from_python_installation(directory, **kwargs):
        """
        Creates a PymakeInterpreter from an Python Installation in the directory.

        :param directory: The absolute path to the python installation directory.
        :param **kwargs:  List of additional keyworded arguments to be passed into the PymakeInterpreter.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'python.exe'))
        if not os.path.exists(python):
            return None
        
        args = kwargs.copy()
        args['Path'] = root
        args['InterpreterPath'] = 'python.exe'
        args.setdefault('Description', os.path.basename(root))

        if os.path.exists(os.path.join(root, 'pythonw.exe')):
            args['WindowsInterpreterPath'] = 'pythonw.exe'

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.decode("utf-8").rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.decode("utf-8").rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        interpreter.resolve()
        return interpreter

    @staticmethod
    def from_registry_key(keyname):
        """
        Creates a PymakeInterpreter from a single registry key.

        :param keyname:  The keyname under HKEY_CURRENT_USER referring to the environment.       
        :return:         A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        args = {}
        try:
            regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, keyname)
            for k in ['Architecture', 'Description', 'InterpreterPath', 'LibraryPath', 'PathEnvironmentVariable', 'Version', 'WindowsInterpreterPath', 'PathEnvironmentVariable']:
                args[k] = winreg.QueryValueEx(regkey, k)[0]        
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            pass

        if 'InterpreterPath' in args:
            args['Path'] = os.path.dirname(args['InterpreterPath'])
            args['Id'] = os.path.basename(keyname)[1:-1]
            return PymakeInterpreter(**args) 
        return None

    def _import(self, datadict):
        """
        Internal method to import instance variables data from a dictionary. 

        :param datadict: The dictionary containing variables values.
        """
        self.GUID                       = datadict.get('Id', uuid.uuid1())
        self.BaseInterpreter            = datadict.get('BaseInterpreter', self.GUID)
        self.Architecture               = datadict.get('Architecture', "")
        self.Version                    = datadict.get('Version', "")
        self.Path                       = datadict.get('Path', "")
        self.Description                = datadict.get('Description', "")
        self.InterpreterPath            = datadict.get('InterpreterPath', "")
        self.InterpreterAbsPath         = datadict.get('InterpreterAbsPath', self.InterpreterPath if os.path.isabs(self.InterpreterPath) else os.path.abspath(os.path.join(self.Path, self.InterpreterPath)))
        self.WindowsInterpreterPath     = datadict.get('WindowsInterpreterPath', "")
        self.WindowsInterpreterAbsPath  = datadict.get('WindowsInterpreterAbsPath', self.WindowsInterpreterPath if os.path.isabs(self.WindowsInterpreterPath) else os.path.abspath(os.path.join(self.Path, self.WindowsInterpreterPath)))
        self.LibraryPath                = datadict.get('LibraryPath', "")
        self.LibraryAbsPath             = datadict.get('LibraryAbsPath', self.LibraryPath if os.path.isabs(self.LibraryPath) else os.path.abspath(os.path.join(self.Path, self.LibraryPath)))
        self.PathEnvironmentVariable    = datadict.get('PathEnvironmentVariable', "PYTHONPATH")
        self.VSVersion                  = datadict.get('VSVersion', None)

    def resolve(self):
        """
        'Resolves' the environment with existing environments in the windows registry.
        """
        if not self.VSVersion:
            raise ValueError('Cannot resolve interpreter with invalid Visual Studio Version')

        regkey_name = self.regkey_name.format(VSVersion=self.VSVersion)
        try:
            vs_regkey_name = os.path.dirname(regkey_name)
            winreg.OpenKey(winreg.HKEY_CURRENT_USER, vs_regkey_name)
        except WindowsError as ex:
            raise ValueError('Cannot resolve the registry path HKCU\%s for Visual Studio %s\'s PTVS.  Is PTVS installed?' % (vs_regkey_name, str(self.VSVersion)))

        regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, regkey_name)
        try:
            reginfo = winreg.QueryInfoKey(regkey)
            for i in range(reginfo[0]):
                interpreter_regkey_name = '{0}\\{1}'.format(regkey_name, winreg.EnumKey(regkey, i))
                interpreter = PymakeInterpreter.from_registry_key(interpreter_regkey_name)
                if interpreter and interpreter.InterpreterAbsPath == self.InterpreterAbsPath:
                    self.GUID = uuid.UUID(interpreter.GUID)
                    self.BaseInterpreter = self.GUID
                    break
        except WindowsError as ex:
            pass

    def register(self):
        """
        'Registers' the environment into the windows registry.

        :..note: https://pytools.codeplex.com/workitem/2765
        """
        if not self.VSVersion:
            raise ValueError('Cannot register interpreter with invalid Visual Studio Version')

        regkey_name = self.regkey_name.format(VSVersion=self.VSVersion)
        try:
            vs_regkey_name = os.path.dirname(regkey_name)
            winreg.OpenKey(winreg.HKEY_CURRENT_USER, vs_regkey_name)
        except WindowsError as ex:
            raise ValueError('Cannot register interpreter with Visual Studio %s that is not installed.' % str(self.VSVersion))

        interpreter_regkey_name = '{0}\\{{{1}}}'.format(regkey_name, str(self.GUID).lower())
        try:
            regkey = winreg.CreateKey(winreg.HKEY_CURRENT_USER, interpreter_regkey_name)
            winreg.SetValueEx(regkey, 'Architecture', 0, winreg.REG_SZ, self.Architecture)
            winreg.SetValueEx(regkey, 'Description', 0, winreg.REG_SZ, self.Description)
            winreg.SetValueEx(regkey, 'InterpreterPath', 0, winreg.REG_SZ, self.InterpreterAbsPath)
            winreg.SetValueEx(regkey, 'LibraryPath', 0, winreg.REG_SZ, self.LibraryAbsPath)
            winreg.SetValueEx(regkey, 'Version', 0, winreg.REG_SZ, self.Version)
            winreg.SetValueEx(regkey, 'WindowsInterpreterPath', 0, winreg.REG_SZ, self.WindowsInterpreterAbsPath)
            winreg.SetValueEx(regkey, 'PathEnvironmentVariable', 0, winreg.REG_SZ, self.PathEnvironmentVariable)
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            return False
        return True

{'fraction_non_alphanumeric': 0.10426560026660002, 'fraction_numerical': 0.0035824377239023577, 'mean_word_length': 2.615512048192771, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2603484', 'n_tokens_mistral': 6797, 'n_tokens_neox': 6728, 'n_words': 1703}