void apply()

in src/main/groovy/com/jetbrains/python/envs/PythonEnvsPlugin.groovy [288:537]


    void apply(Project project) {
        PythonEnvsExtension envs = project.extensions.create("envs", PythonEnvsExtension.class)

        project.repositories {
            mavenCentral()
        }

        project.configurations {
            jython
        }

        project.afterEvaluate {
            project.configurations.jython.incoming.beforeResolve {
                project.dependencies {
                    jython group: 'org.python', name: 'jython-installer', version: '2.7.1'
                }
            }

            createInstallPythonBuildTask(project, new File(project.buildDir, "python-build"))

            Task python_task = project.tasks.create(name: 'build_pythons') {

                onlyIf { !envs.pythons.empty }

                envs.pythons.each { env ->
                    switch (env.type) {
                        case EnvType.PYTHON:
                            if (isUnix) {
                                dependsOn createPythonUnixTask(project, env)
                            } else if (isWindows) {
                                dependsOn createPythonWindowsTask(project, env)
                            } else {
                                project.logger.error("Something is wrong with os: $osName")
                            }
                            break
                        case EnvType.JYTHON:
                            dependsOn createJythonTask(project, env)
                            break
                        case EnvType.PYPY:
                            if (isUnix) {
                                dependsOn createPythonUnixTask(project, env)
                            } else {
                                project.logger.warn("PyPy installation isn't supported for $osName, please use envFromZip instead")
                            }
                            break
                        default:
                            project.logger.error("$env.type isn't supported yet")
                    }
                }
            }

            Task python_from_zip_task = project.tasks.create(name: 'build_pythons_from_zip') {

                onlyIf { !envs.pythonsFromZip.empty }

                envs.pythonsFromZip.each { env ->
                    dependsOn project.tasks.create(name: "Bootstrap_${env.type ? env.type : ''}_'$env.name'_from_archive") {
                        onlyIf {
                            !env.envDir.exists() || isPythonInvalid(project, env)
                        }

                        doFirst {
                            project.buildDir.mkdir()
                            env.envDir.mkdirs()
                            env.envDir.deleteDir()
                        }

                        doLast {
                            try {
                                String archiveName = env.url.toString().with { urlString ->
                                    urlString.substring(urlString.lastIndexOf('/') + 1, urlString.length())
                                }
                                if (!archiveName.endsWith("zip")) {
                                    throw new RuntimeException("Wrong archive extension, only zip is supported")
                                }

                                File zipArchive = new File(project.buildDir, archiveName)
                                project.logger.quiet("Downloading $archiveName archive from $env.url")
                                project.ant.get(dest: zipArchive) {
                                    url(url: env.url)
                                }

                                project.logger.quiet("Unzipping downloaded $archiveName archive")
                                project.ant.unzip(src: zipArchive, dest: env.envDir)

                                env.envDir.with { dir ->
                                    if (dir.listFiles().length == 1) {
                                        File intermediateDir = dir.listFiles().last()
                                        if (!intermediateDir.isDirectory()) {
                                            throw new RuntimeException("Archive is wrong, $env.url")
                                        }
                                        project.ant.move(todir: dir) {
                                            fileset(dir: intermediateDir)
                                        }
                                    } else {
                                        return dir
                                    }
                                }

                                if (env.type != null) {
                                    if (!getExecutable("pip", env).exists()) {
                                        project.logger.quiet("Downloading & installing pip and setuptools")
                                        project.exec {
                                            if (env.type == EnvType.IRONPYTHON) {
                                                executable getExecutable("ipy", env)
                                                args "-m", "ensurepip"
                                            } else {
                                                executable getExecutable("python", env)
                                                args getPipFile(project, env.version)
                                            }
                                        }
                                    }
                                    upgradePipAndSetuptools(project, env)
                                }

                                project.logger.quiet("Deleting $archiveName archive")
                                zipArchive.delete()
                            }
                            catch (Exception e) {
                                project.logger.error(e.message)
                                throw new GradleException(e.message)
                            }

                            pipInstall(project, env, env.packages)
                        }
                    }
                }
            }

            Task virtualenvs_task = project.tasks.create(name: 'build_virtual_envs') {
                shouldRunAfter python_task, python_from_zip_task

                onlyIf { !envs.virtualEnvs.empty }

                envs.virtualEnvs.each { env ->
                    if (env.sourceEnv.type == EnvType.IRONPYTHON) {
                        project.logger.warn("IronPython doesn't support virtualenvs")
                        return
                    }

                    dependsOn project.tasks.create("Create_virtualenv_'$env.name'") {
                        onlyIf {
                            (!env.envDir.exists() || isPythonInvalid(project, env)) && env.sourceEnv.type != null
                        }

                        doFirst {
                            env.envDir.mkdirs()
                            env.envDir.deleteDir()
                        }

                        doLast {
                            project.logger.quiet("Installing needed virtualenv package")

                            pipInstall(project, env.sourceEnv, ["virtualenv"])

                            project.logger.quiet("Creating virtualenv from $env.sourceEnv.name at $env.envDir")
                            project.exec {
                                executable getExecutable("virtualenv", env.sourceEnv)
                                args env.envDir, "--always-copy"
                                workingDir env.sourceEnv.envDir
                            }

                            pipInstall(project, env, env.packages)
                        }
                    }
                }
            }

            Task conda_task = project.tasks.create(name: "build_condas") {

                onlyIf { !envs.condas.empty }

                envs.condas.each { Conda env ->
                    dependsOn project.tasks.create(name: "Bootstrap_${env.type}_'$env.name'") {
                        onlyIf {
                            !env.envDir.exists() || isPythonInvalid(project, env)
                        }

                        doFirst {
                            project.buildDir.mkdir()
                            env.envDir.mkdirs()
                            env.envDir.deleteDir()
                        }

                        doLast {
                            URL urlToConda = getUrlToDownloadConda(env)
                            File installer = new File(project.buildDir, urlToConda.toString().split("/").last())

                            if (!installer.exists()) {
                                project.logger.quiet("Downloading $installer.name")
                                project.ant.get(dest: installer) {
                                    url(url: urlToConda)
                                }
                            }

                            project.logger.quiet("Bootstraping to $env.envDir")
                            project.exec {
                                if (isWindows) {
                                    commandLine installer, "/InstallationType=JustMe", "/AddToPath=0", "/RegisterPython=0", "/S", "/D=$env.envDir"
                                } else {
                                    commandLine "bash", installer, "-b", "-p", env.envDir
                                }
                            }

                            pipInstall(project, env, env.packages)
                            condaInstall(project, env, env.condaPackages)
                        }
                    }
                }
            }

            Task conda_envs_task = project.tasks.create(name: 'build_conda_envs') {
                shouldRunAfter conda_task

                onlyIf { !envs.condaEnvs.empty }

                envs.condaEnvs.each { env ->
                    dependsOn project.tasks.create("Create_conda_env_'$env.name'") {
                        onlyIf {
                            !env.envDir.exists() || isPythonInvalid(project, env)
                        }

                        doFirst {
                            env.envDir.mkdirs()
                            env.envDir.deleteDir()
                        }

                        doLast {
                            project.logger.quiet("Creating condaenv '$env.name' at $env.envDir directory")
                            project.exec {
                                executable getExecutable("conda", env.sourceEnv)
                                args "create", "-p", env.envDir, "-y", "python=$env.version"
                                args env.condaPackages
                            }

                            pipInstall(project, env, env.packages)
                        }
                    }
                }
            }

            project.tasks.create(name: 'build_envs') {
                dependsOn python_task,
                        python_from_zip_task,
                        virtualenvs_task,
                        conda_task,
                        conda_envs_task
            }
        }
    }