// Copyright 2015 Pants project contributors (see CONTRIBUTORS.md). // Licensed under the Apache License, Version 2.0 (see LICENSE). package com.twitter.intellij.pants.service.python; import com.intellij.openapi.externalSystem.model.DataNode; import com.intellij.openapi.externalSystem.model.ProjectKeys; import com.intellij.openapi.externalSystem.model.project.*; import com.intellij.openapi.module.ModuleTypeId; import com.intellij.openapi.util.io.FileUtil; import com.twitter.intellij.pants.service.PantsCompileOptionsExecutor; import com.twitter.intellij.pants.service.project.model.graph.BuildGraph; import com.twitter.intellij.pants.service.project.PantsResolverExtension; import com.twitter.intellij.pants.service.project.model.ProjectInfo; import com.twitter.intellij.pants.service.project.model.PythonSetup; import com.twitter.intellij.pants.service.project.model.TargetInfo; import com.twitter.intellij.pants.util.PantsConstants; import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.Map; import java.util.Optional; /** * Currently we configure requirements only for default interpreter. * * @see PythonInfoModifier for details. */ public class PythonRequirementsResolver implements PantsResolverExtension { @Override public void resolve( @NotNull ProjectInfo projectInfo, @NotNull PantsCompileOptionsExecutor executor, @NotNull DataNode<ProjectData> projectDataNode, @NotNull Map<String, DataNode<ModuleData>> modules, @NotNull Optional<BuildGraph> buildGraph ) { final PythonSetup pythonSetup = projectInfo.getPythonSetup(); if (pythonSetup == null) { LOG.warn("Current version of Pants doesn't provide information about Python setup. Please upgrade!"); return; } final DataNode<ModuleData> requirementsModuleDataNode = createRequirementsModule(projectDataNode, pythonSetup, executor); requirementsModuleDataNode.createChild( PythonSetupData.KEY, new PythonSetupData(requirementsModuleDataNode.getData(), pythonSetup.getDefaultInterpreterInfo()) ); for (Map.Entry<String, TargetInfo> targetInfoEntry : projectInfo.getSortedTargets()) { final String targetName = targetInfoEntry.getKey(); final TargetInfo targetInfo = targetInfoEntry.getValue(); final DataNode<ModuleData> moduleDataNode = modules.get(targetName); if (targetInfo.isPythonTarget() && moduleDataNode != null) { final ModuleDependencyData moduleDependencyData = new ModuleDependencyData( moduleDataNode.getData(), requirementsModuleDataNode.getData() ); moduleDependencyData.setExported(true); moduleDataNode.createChild(ProjectKeys.MODULE_DEPENDENCY, moduleDependencyData); moduleDataNode.createChild( PythonSetupData.KEY, new PythonSetupData(moduleDataNode.getData(), pythonSetup.getDefaultInterpreterInfo()) ); } } } @NotNull private DataNode<ModuleData> createRequirementsModule( @NotNull DataNode<ProjectData> projectDataNode, @NotNull PythonSetup pythonSetup, @NotNull PantsCompileOptionsExecutor executor ) { final String moduleName = "python_requirements"; final ModuleData moduleData = new ModuleData( moduleName, PantsConstants.SYSTEM_ID, ModuleTypeId.JAVA_MODULE, moduleName, projectDataNode.getData().getIdeProjectFileDirectoryPath() + "/" + moduleName, new File(executor.getBuildRoot(), moduleName).getAbsolutePath() ); final DataNode<ModuleData> moduleDataNode = projectDataNode.createChild(ProjectKeys.MODULE, moduleData); final File chroot = new File(pythonSetup.getDefaultInterpreterInfo().getChroot()); for (File dep : FileUtil.notNullize(new File(chroot, ".deps").listFiles())) { if (!dep.isDirectory()) { continue; } final ContentRootData contentRoot = new ContentRootData(PantsConstants.SYSTEM_ID, dep.getAbsolutePath()); contentRoot.storePath(ExternalSystemSourceType.SOURCE, dep.getAbsolutePath()); moduleDataNode.createChild(ProjectKeys.CONTENT_ROOT, contentRoot); } return moduleDataNode; } }