Пример #1
0
        private static List <PythonInstall> FindEnvironments(bool force_registry, Request request)
        {
            List <PythonInstall> result = new List <PythonInstall>();
            string requested_location   = request.GetOptionValue("PythonLocation");

            if (!force_registry && !string.IsNullOrEmpty(requested_location))
            {
                PythonInstall install = FromPath(requested_location, request);
                if (install != null)
                {
                    result.Add(install);
                }
            }
            else
            {
                HashSet <string> seen_paths = new HashSet <string>();
                if (Environment.Is64BitOperatingSystem)
                {
                    FindEnvironments(result, true, false, seen_paths, request);
                }
                FindEnvironments(result, false, false, seen_paths, request);
                FindEnvironments(result, false, true, seen_paths, request);
            }
            return(result);
        }
Пример #2
0
 private static void FindEnvironments(List <PythonInstall> result, bool win64, bool user, HashSet <string> seen_paths, Request request)
 {
     using (RegistryKey basekey = RegistryKey.OpenBaseKey(
                user ? RegistryHive.CurrentUser : RegistryHive.LocalMachine,
                win64 ? RegistryView.Registry64 : RegistryView.Registry32))
     {
         RegistryKey pythoncore = basekey.OpenSubKey(@"Software\Python\PythonCore");
         if (pythoncore != null)
         {
             foreach (string version in pythoncore.GetSubKeyNames())
             {
                 RegistryKey installpathkey = pythoncore.OpenSubKey(string.Format(@"{0}\InstallPath", version));
                 if (installpathkey != null)
                 {
                     string path = installpathkey.GetValue(null).ToString();
                     if (!seen_paths.Add(path))
                     {
                         continue;
                     }
                     PythonInstall install = FromPath(path, request);
                     if (install != null)
                     {
                         install.from_registry = true;
                         install.reg_user      = user;
                         result.Add(install);
                         request.Debug("Python::FindInstalledEnvironments found {0} in {1}", install.version, install.install_path);
                     }
                     installpathkey.Dispose();
                 }
             }
             pythoncore.Dispose();
         }
     }
 }
Пример #3
0
 public static PythonInstall FromPath(string installpath, Request request)
 {
     try
     {
         PythonInstall result = new PythonInstall();
         if (Directory.Exists(installpath))
         {
             result.install_path = installpath;
             result.exe_path     = Path.Combine(installpath, "python.exe");
         }
         else
         {
             result.install_path = Path.GetDirectoryName(installpath);
             result.exe_path     = installpath;
         }
         result.ReadInterpreterInfo(request);
         string requested_version_str = request.GetOptionValue("PythonVersion");
         if (!string.IsNullOrEmpty(requested_version_str))
         {
             VersionIdentifier requested_version = new VersionIdentifier(requested_version_str);
             if (!requested_version.IsPrefix(result.version))
             {
                 return(null);
             }
         }
         return(result);
     }
     catch (Exception e)
     {
         request.Debug("Python at {0} isn't usable: {1}", installpath, e);
     }
     return(null);
 }
Пример #4
0
        public bool CheckDependencies(PythonInstall install, out DistRequirement failed_dependency, Request request)
        {
            failed_dependency = new DistRequirement();
            if (requires_dist.Count == 0)
            {
                return(true);
            }
            List <PythonPackage> installed_packages = new List <PythonPackage>(install.FindInstalledPackages(null, null, request));

            foreach (var dep in requires_dist)
            {
                if (dep.marker != null && !dep.marker.Eval(install))
                {
                    continue;
                }
                bool satisfied_dependency = false;
                foreach (var package in installed_packages)
                {
                    if (package.SatisfiesDependency(install, dep, request))
                    {
                        satisfied_dependency = true;
                        break;
                    }
                }
                if (!satisfied_dependency)
                {
                    failed_dependency = dep;
                    return(false);
                }
            }
            return(true);
        }
Пример #5
0
        private static PythonInstall FromReleaseRes(JObject res, Request request)
        {
            string        release_name = res["name"].ToString();
            PythonInstall result       = new PythonInstall();

            result.version = new VersionIdentifier(release_name.Substring(7));
            var parts = res["resource_uri"].ToString().TrimEnd('/').Split('/');

            result.web_resource = parts[parts.Length - 1];
            result.source       = "Python.org";
            return(result);
        }
Пример #6
0
 public static PythonPackage FromFastReference(string fastreference, Request request)
 {
     if (fastreference.StartsWith("distinfo:"))
     {
         string[]      parts   = fastreference.Substring(9).Split(new char[] { '|' }, 2);
         PythonInstall install = PythonInstall.FromPath(parts[0], request);
         return(FromDistInfo(parts[1], install, request));
     }
     else if (fastreference.StartsWith("egginfo:"))
     {
         string[]      parts   = fastreference.Substring(8).Split(new char[] { '|' }, 2);
         PythonInstall install = PythonInstall.FromPath(parts[0], request);
         return(FromEggInfo(parts[1], install, request));
     }
     else if (fastreference.StartsWith("pypi:"))
     {
         string[] parts     = fastreference.Substring(5).Split(new char[] { '#' }, 3);
         string   source    = parts[0];
         string   sourceurl = parts[1];
         parts = parts[2].Split(new char[] { '/' });
         string name    = parts[0];
         string version = parts[1];
         return(PyPI.GetPackage(new Tuple <string, string>(source, sourceurl), name, version, request));
     }
     else if (fastreference.StartsWith("archive:"))
     {
         string[] parts        = fastreference.Substring(8).Split(new char[] { '/' }, 3);
         string   name         = parts[0];
         string   version      = parts[1];
         string   archive_path = parts[2];
         foreach (var package in PackagesFromFile(archive_path, request))
         {
             if (package.name == name && package.version.Compare(version) == 0)
             {
                 return(package);
             }
         }
     }
     else if (fastreference.StartsWith("pythonweb:"))
     {
         return(PythonWebsite.PackageFromWebResource(fastreference.Substring(10), request));
     }
     else if (fastreference.StartsWith("installedpython:"))
     {
         return(PythonInstall.FromPath(fastreference.Substring(16), request));
     }
     return(null);
 }
Пример #7
0
        private bool CanInstall(PythonInstall install, PackageDownload download, out bool install_specific, Request request)
        {
            install_specific = false;
            if (download.packagetype == "bdist_wheel")
            {
                string tag = download.basename;
                if (tag.EndsWith(".whl"))
                {
                    tag = tag.Substring(0, tag.Length - 4);
                }
                int platform_dash = tag.LastIndexOf('-');
                if (platform_dash <= 0)
                {
                    return(false);
                }
                int abi_dash = tag.LastIndexOf('-', platform_dash - 1);
                if (abi_dash <= 0)
                {
                    return(false);
                }
                int python_dash = tag.LastIndexOf('-', abi_dash - 1);
                if (python_dash <= 0)
                {
                    return(false);
                }
                tag = tag.Substring(python_dash + 1);

                install_specific = true;

                if (install.CompatibleWithTag(tag))
                {
                    return(true);
                }

                return(false);
            }
            else if (download.packagetype == "sdist")
            {
                install_specific = false;
                return(true);
            }
            return(true);
        }
Пример #8
0
        private bool Install(PythonInstall install, PackageDownload download, Request request)
        {
            if (download.packagetype != "bdist_wheel")
            {
                if (!install.InstallPip(request))
                {
                    return(false);
                }
            }

            string tempdir, filename;

            if (!DoDownload(download, out tempdir, out filename, request))
            {
                return(false);
            }

            try
            {
                if (download.packagetype == "bdist_wheel")
                {
                    foreach (var package in PackagesFromFile(filename, request))
                    {
                        if (package.MatchesName(name) && package.version.raw_version_string == version.raw_version_string)
                        {
                            return(package.Install(install, request));
                        }
                    }
                    request.Error(ErrorCategory.MetadataError, name, "Downloaded package file doesn't contain the expected package.");
                    return(false);
                }
                else
                {
                    return(install.InstallViaPip(filename, request));
                }
            }
            finally
            {
                File.Delete(filename);
                Directory.Delete(tempdir);
            }
        }
Пример #9
0
 public bool SatisfiesDependency(PythonInstall install, DistRequirement dep, Request request)
 {
     if (dep.marker != null && !dep.marker.Eval(install))
     {
         // FIXME: handle this, somehow?
         return(true);
     }
     if (!MatchesName(dep.name))
     {
         return(false);
     }
     if (dep.has_version_specifier)
     {
         if (!dep.version_specifier.MatchesVersion(version))
         {
             return(false);
         }
     }
     return(true);
 }
Пример #10
0
        public static PythonPackage FromEggInfo(string path, PythonInstall install, Request request)
        {
            var result = new PythonPackage(null);

            result.status       = Constants.PackageStatus.Installed;
            result.egginfo_path = path;
            result.install      = install;
            try
            {
                result.ReadMetadata(Path.Combine(path, "PKG-INFO"));
            }
            catch (Exception e)
            {
                request.Debug(string.Format("Unexpected Exception thrown in 'Python::FromEggInfo' -- {1}\\{2}\r\n{3}"), e.GetType().Name, e.Message, e.StackTrace);
            }
            if (result.name != null)
            {
                return(result);
            }
            return(null);
        }
Пример #11
0
        private static bool InstallDependencies(PythonInstall install, Dictionary <string, PythonPackage> deps, Request request)
        {
            while (deps.Count != 0)
            {
                var enumerator = deps.GetEnumerator();
                enumerator.MoveNext();
                PythonPackage package = enumerator.Current.Value;

                bool unsatisfied_deps = true;
                while (unsatisfied_deps)
                {
                    unsatisfied_deps = false;
                    foreach (var dep in package.requires_dist)
                    {
                        if (dep.marker != null && !dep.marker.Eval(install))
                        {
                            continue;
                        }
                        if (deps.ContainsKey(NormalizeName(dep.name)))
                        {
                            // FIXME: Infinite loop if dep graph has cycles
                            package          = deps[NormalizeName(dep.name)];
                            unsatisfied_deps = true;
                            break;
                        }
                    }
                }

                if (!package.Install(install, request))
                {
                    return(false);
                }

                deps.Remove(NormalizeName(package.name));
            }

            return(true);
        }
Пример #12
0
        public bool CanInstall(PythonInstall install, bool install_64bit, Request request)
        {
            if (is_wheel)
            {
                if (this.tags == null)
                {
                    return(true);
                }
                foreach (var tag in this.tags)
                {
                    if (install.CompatibleWithTag(tag, install_64bit))
                    {
                        return(true);
                    }
                }
                return(false);
            }
            else if (source != null)
            {
                bool any_install_specific_download = false;

                foreach (var download in downloads)
                {
                    bool install_specific;
                    if (CanInstall(install, download, install_64bit, out install_specific, request))
                    {
                        return(true);
                    }
                    if (install_specific)
                    {
                        any_install_specific_download = true;
                    }
                }
                return(!any_install_specific_download);
            }
            return(true);
        }
Пример #13
0
        public void GetInstalledPackages(string name, string requiredVersion, string minimumVersion, string maximumVersion, Request request)
        {
            request.Debug("Calling '{0}::GetInstalledPackages({1},{2},{3},{4})'", ProviderName, name, requiredVersion, minimumVersion, maximumVersion);
            VersionIdentifier required = string.IsNullOrEmpty(requiredVersion) ? null : new VersionIdentifier(requiredVersion);
            VersionIdentifier minimum  = string.IsNullOrEmpty(minimumVersion) ? null : new VersionIdentifier(minimumVersion);
            VersionIdentifier maximum  = string.IsNullOrEmpty(maximumVersion) ? null : new VersionIdentifier(maximumVersion);

            foreach (var install in PythonInstall.FindEnvironments(request))
            {
                if (string.IsNullOrEmpty(name) || name == "Python")
                {
                    install.YieldSelf(request);
                }
                foreach (var package in install.FindInstalledPackages(name, requiredVersion, request))
                {
                    if ((required == null || required.Compare(package.version) == 0) &&
                        (minimum == null || minimum.Compare(package.version) <= 0) &&
                        (maximum == null || maximum.Compare(package.version) >= 0))
                    {
                        package.YieldSelf(request);
                    }
                }
            }
        }
Пример #14
0
        public void InstallPackage(string fastPackageReference, Request request)
        {
            request.Debug("Calling '{0}::InstallPackage' '{1}'", ProviderName, fastPackageReference);
            var package = PythonPackage.FromFastReference(fastPackageReference, request);

            if (package is PythonInstall)
            {
                ((PythonInstall)package).Install(request);
                return;
            }
            bool retried = false;

retry:
            List <PythonInstall> usableinstalls   = new List <PythonInstall>();
            List <PythonInstall> unusableinstalls = new List <PythonInstall>();

            foreach (var candidateinstall in PythonInstall.FindEnvironments(request))
            {
                if (package.CanInstall(candidateinstall, request))
                {
                    usableinstalls.Add(candidateinstall);
                }
                else
                {
                    unusableinstalls.Add(candidateinstall);
                }
            }
            if (usableinstalls.Count == 1)
            {
                package.Install(usableinstalls[0], request);
            }
            else if (usableinstalls.Count == 0)
            {
                // Need to install a Python
                if (retried)
                {
                    request.Error(ErrorCategory.NotImplemented, package.name, "Failed to install a Python interpreter");
                    return;
                }

                List <PythonPackage> candidate_pythons = new List <PythonPackage>(
                    PythonWebsite.Search("Python", null, null, null, true, request));
                candidate_pythons.Sort(new PackageVersionComparer());

                bool installed = false;

                for (int i = candidate_pythons.Count - 1; i >= 0; i--)
                {
                    if (Environment.Is64BitOperatingSystem &&
                        ((PythonInstall)candidate_pythons[i]).CanInstall(true, request) &&
                        package.CanInstall((PythonInstall)candidate_pythons[i], true, request))
                    {
                        ((PythonInstall)candidate_pythons[i]).Install(true, request);
                        installed = true;
                        break;
                    }
                    else if (((PythonInstall)candidate_pythons[i]).CanInstall(false, request) &&
                             package.CanInstall((PythonInstall)candidate_pythons[i], true, request))
                    {
                        ((PythonInstall)candidate_pythons[i]).Install(false, request);
                        installed = true;
                        break;
                    }
                }

                if (installed)
                {
                    retried = true;
                    goto retry;
                }
                else
                {
                    request.Error(ErrorCategory.NotImplemented, package.name, "Couldn't find a Python interpreter to install for this");
                    return;
                }
            }
            else if (usableinstalls.Count > 1)
            {
                if (request.GetOptionValue("Force") == "True")
                {
                    PythonInstall greatest = usableinstalls[0];
                    foreach (var candidate in usableinstalls)
                    {
                        if (candidate.version.Compare(greatest.version) > 0)
                        {
                            greatest = candidate;
                        }
                    }
                    package.Install(greatest, request);
                }
                else
                {
                    request.Warning("Multiple installed Python interpreters could satisfy this request:");
                    foreach (var install in usableinstalls)
                    {
                        request.Warning("  Python version '{0}' at '{1}'", install.version, install.exe_path);
                    }
                    request.Warning("Please select a Python to install to, using e.g. -PythonVersion 3.2 or -PythonLocation c:\\python32\\python.exe");
                    request.Error(ErrorCategory.NotSpecified, package.name, "Not enough information to select a Python interpreter for the install");
                }
            }
        }
Пример #15
0
        public bool Install(PythonInstall install, Request request)
        {
            DistRequirement failed_dependency;

            request.Debug("Installing {0} {1}", name, version.ToString());
            if (incomplete_metadata)
            {
                return(PyPI.GetPackage(new Tuple <string, string>(source, sourceurl), name, version.raw_version_string, request).Install(install, request));
            }
            if (!CheckDependencies(install, out failed_dependency, request))
            {
                var deps = SimpleResolveDependencies(install, out failed_dependency, request);
                if (deps == null)
                {
                    request.Error(ErrorCategory.NotInstalled, name, string.Format("Dependency '{0}' not found, unable to resolve automatically.", failed_dependency.raw_string));
                    return(false);
                }

                if (!InstallDependencies(install, deps, request))
                {
                    return(false);
                }
            }
            if (is_wheel)
            {
                if (install.InstallWheel(archive_path, request) != 0)
                {
                    request.Error(ErrorCategory.NotSpecified, name, "wheel install failed");
                    return(false);
                }
                foreach (var package in install.FindInstalledPackages(name, null, request))
                {
                    if (package.version.raw_version_string != version.raw_version_string)
                    {
                        package.Uninstall(request);
                    }
                }
                return(true);
            }
            else if (source != null)
            {
                PackageDownload?fallback_download = null;
                foreach (var download in downloads)
                {
                    bool install_specific;
                    if (CanInstall(install, download, out install_specific, request))
                    {
                        if (install_specific)
                        {
                            return(Install(install, download, request));
                        }
                        else if (fallback_download == null)
                        {
                            fallback_download = download;
                        }
                    }
                }
                if (fallback_download != null)
                {
                    return(Install(install, fallback_download.Value, request));
                }
                request.Error(ErrorCategory.NotImplemented, name, "installing not implemented for this package type");
                return(false);
            }
            else
            {
                request.Error(ErrorCategory.NotImplemented, name, "installing not implemented for this package type");
                return(false);
            }
        }
Пример #16
0
 internal bool Eval(PythonInstall install)
 {
     return(ValueIsTrue(RealEval(install)));
 }
Пример #17
0
        private object RealEval(PythonInstall install)
        {
            object result = null;
            int    i;

            switch (type)
            {
            case MarkerType.And:
                result = submarkers[0].RealEval(install);
                i      = 1;
                while (i < submarkers.Length && ValueIsTrue(result))
                {
                    result = submarkers[i++].RealEval(install);
                }
                break;

            case MarkerType.Or:
                result = submarkers[0].RealEval(install);
                i      = 1;
                while (i < submarkers.Length && !ValueIsTrue(result))
                {
                    result = submarkers[i++].RealEval(install);
                }
                break;

            case MarkerType.StringLiteral:
                result = str_value;
                break;

            case MarkerType.StringVariable:
                result = install.get_string_marker_variable(marker_variable);
                break;

            case MarkerType.VersionVariable:
                result = install.get_version_marker_variable(marker_variable);
                break;

            case MarkerType.ExtraVariable:
                result = "";     // FIXME: add support for specifying extras?
                break;

            case MarkerType.ComparisonList:
                object a, b;
                a = submarkers[0].RealEval(install);
                if (a is bool)
                {
                    throw new Exception("can't do comparisons with booleans");
                }
                bool res = true, version_comparison;
                i = 0;
                while (res && i < comparisons.Length)
                {
                    b = submarkers[i + 1].RealEval(install);
                    if (b is bool)
                    {
                        throw new Exception("can't do comparisons with booleans");
                    }
                    var cmp = comparisons[i];
                    if (cmp == ComparisonType.In || cmp == ComparisonType.NotIn)
                    {
                        version_comparison = false;
                    }
                    else if (cmp == ComparisonType.Equal || cmp == ComparisonType.NotEqual)
                    {
                        version_comparison = (a is VersionIdentifier || b is VersionIdentifier);
                    }
                    else
                    {
                        version_comparison = true;
                    }
                    if (version_comparison)
                    {
                        VersionIdentifier va, vb;
                        va = (a as VersionIdentifier) ?? new VersionIdentifier((string)a);
                        vb = (b as VersionIdentifier) ?? new VersionIdentifier((string)b);
                        switch (cmp)
                        {
                        case ComparisonType.Equal:
                            res = va.Compare(vb) == 0;
                            break;

                        case ComparisonType.NotEqual:
                            res = va.Compare(vb) != 0;
                            break;

                        case ComparisonType.LT:
                            res = va.Compare(vb) < 0;
                            break;

                        case ComparisonType.GT:
                            res = va.Compare(vb) > 0;
                            break;

                        case ComparisonType.LTE:
                            res = va.Compare(vb) <= 0;
                            break;

                        case ComparisonType.GTE:
                            res = va.Compare(vb) >= 0;
                            break;
                        }
                    }
                    else
                    {
                        string sa, sb;
                        sa = (a as string) ?? ((VersionIdentifier)a).raw_version_string;
                        sb = (b as string) ?? ((VersionIdentifier)b).raw_version_string;
                        switch (cmp)
                        {
                        case ComparisonType.Equal:
                            res = sa == sb;
                            break;

                        case ComparisonType.NotEqual:
                            res = sa != sb;
                            break;

                        case ComparisonType.In:
                            res = sb.Contains(sa);
                            break;

                        case ComparisonType.NotIn:
                            res = !sb.Contains(sa);
                            break;
                        }
                    }
                    a = b;
                    i++;
                }
                result = res;
                break;
            }

            return(result);
        }
Пример #18
0
        private Dictionary <string, PythonPackage> SimpleResolveDependencies(PythonInstall install, out DistRequirement failed_dependency, Request request)
        {
            Dictionary <string, PythonPackage> result     = new Dictionary <string, PythonPackage>();
            Queue <DistRequirement>            to_resolve = new Queue <DistRequirement>();
            var  installed_packages = new Dictionary <string, PythonPackage>();
            bool need_recheck       = true; // True if we're [up|down]grading a package, and therefore may need to recheck deps

            foreach (var package in install.FindInstalledPackages(null, null, request))
            {
                installed_packages[package.name] = package;
            }

            while (need_recheck)
            {
                need_recheck = false;

                to_resolve.Clear();
                foreach (var dep in requires_dist)
                {
                    request.Debug("Adding dependency {0}", dep.raw_string);
                    to_resolve.Enqueue(dep);
                }

                result.Clear();

                while (to_resolve.Count != 0)
                {
                    var           dep = to_resolve.Dequeue();
                    PythonPackage package;

                    request.Debug("Examining dependency {0}", dep.raw_string);

                    if (dep.marker != null && !dep.marker.Eval(install))
                    {
                        request.Debug("Does not apply to current Python environment");
                        continue;
                    }

                    if (result.TryGetValue(NormalizeName(dep.name), out package))
                    {
                        if (!package.SatisfiesDependency(install, dep, request))
                        {
                            failed_dependency = dep;
                            return(null);
                        }
                        request.Debug("Satisfied by package to install {0} {1}", package.name, package.version.ToString());
                    }
                    else
                    {
                        if (installed_packages.TryGetValue(NormalizeName(dep.name), out package))
                        {
                            if (package.SatisfiesDependency(install, dep, request))
                            {
                                request.Debug("Satisfied by installed package {0} {1}", package.name, package.version.ToString());
                                continue;
                            }
                            else
                            {
                                request.Debug("Not satisfied by installed package {0} {1}", package.name, package.version.ToString());
                                need_recheck = true;
                            }
                        }

                        // find newest version of package that satisfies dependency

                        package = null;
                        foreach (var candidate_package in PyPI.ExactSearch(dep.name, request))
                        {
                            request.Debug("Examining {0} {1}", candidate_package.name, candidate_package.version.ToString());
                            if (candidate_package.SatisfiesDependency(install, dep, request))
                            {
                                package = candidate_package;
                                break;
                            }
                        }

                        if (package == null)
                        {
                            request.Debug("Cannot satisfy dependency");
                            failed_dependency = dep;
                            return(null);
                        }

                        request.Debug("Selecting {0} {1}", package.name, package.version.ToString());

                        // need to do another request to find dependencies
                        if (package.incomplete_metadata)
                        {
                            package = PyPI.GetPackage(new Tuple <string, string>(package.source, package.sourceurl),
                                                      package.name, package.version.raw_version_string, request);
                        }

                        // add its dependencies to queue
                        foreach (var dep2 in package.requires_dist)
                        {
                            request.Debug("Adding dependency {0}", dep2.raw_string);
                            to_resolve.Enqueue(dep2);
                        }

                        result[NormalizeName(package.name)] = package;
                    }
                }
            }

            failed_dependency = default(DistRequirement);
            return(result);
        }