summaryrefslogtreecommitdiff
path: root/python/testSrc/com/jetbrains/python/sdkTools/PyTestSdkTools.java
blob: 0b5cdadbbc43409c9f7583a852f99f1ff5a01e85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.jetbrains.python.sdkTools;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.UsefulTestCase;
import com.jetbrains.python.sdk.InvalidSdkException;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher;
import com.jetbrains.python.sdk.skeletons.SkeletonVersionChecker;
import org.hamcrest.Matchers;
import org.jetbrains.annotations.NotNull;
import org.junit.Assert;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * Engine to create SDK for tests.
 * See {@link #createTempSdk(com.intellij.openapi.vfs.VirtualFile, SdkCreationType, com.intellij.openapi.module.Module)}
 *
 * @author Ilya.Kazakevich
 */
public final class PyTestSdkTools {

  private static final Sdk[] NO_SDK = new Sdk[0];

  private PyTestSdkTools() {

  }

  /**
   * Creates SDK by its path and associates it with module.
   *
   * @param sdkHome         path to sdk
   * @param sdkCreationType SDK creation strategy (see {@link SdkCreationType} doc)
   * @return sdk
   */
  @NotNull
  public static Sdk createTempSdk(@NotNull final VirtualFile sdkHome,
                                  @NotNull final SdkCreationType sdkCreationType,
                                  @NotNull final Module module
  )
    throws InvalidSdkException, IOException {
    final Ref<Sdk> ref = Ref.create();
    UsefulTestCase.edt(new Runnable() {

      @Override
      public void run() {
        final Sdk sdk = SdkConfigurationUtil.setupSdk(NO_SDK, sdkHome, PythonSdkType.getInstance(), true, null, null);
        Assert.assertNotNull("Failed to create SDK on " + sdkHome, sdk);
        ref.set(sdk);
      }
    });
    final Sdk sdk = ref.get();
    if (sdkCreationType != SdkCreationType.EMPTY_SDK) {
      generateTempSkeletonsOrPackages(sdk, sdkCreationType == SdkCreationType.SDK_PACKAGES_AND_SKELETONS, module);
    }
    UsefulTestCase.edt(new Runnable() {
      @Override
      public void run() {
        SdkConfigurationUtil.addSdk(sdk);
      }
    });
    return sdk;
  }


  /**
   * Adds installed eggs to SDK, generates skeletons (optionally) and associates it with modle.
   *
   * @param sdk          sdk to process
   * @param addSkeletons add skeletons or only packages
   * @param module       module to associate with
   * @throws InvalidSdkException bas sdk
   * @throws IOException         failed to read eggs
   */
  private static void generateTempSkeletonsOrPackages(@NotNull final Sdk sdk,
                                                      final boolean addSkeletons,
                                                      @NotNull final Module module)
    throws InvalidSdkException, IOException {
    final Project project = module.getProject();
    ModuleRootModificationUtil.setModuleSdk(module, sdk);

    UsefulTestCase.edt(new Runnable() {
      @Override
      public void run() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          @Override
          public void run() {
            ProjectRootManager.getInstance(project).setProjectSdk(sdk);
          }
        });
      }
    });


    final SdkModificator modificator = sdk.getSdkModificator();
    modificator.removeRoots(OrderRootType.CLASSES);

    for (final String path : PythonSdkType.getSysPathsFromScript(sdk.getHomePath())) {
      PythonSdkType.addSdkRoot(modificator, path);
    }
    if (!addSkeletons) {
      UsefulTestCase.edt(new Runnable() {
        @Override
        public void run() {
          modificator.commitChanges();
        }
      });
      return;
    }

    final File tempDir = FileUtil.createTempDirectory(PyTestSdkTools.class.getName(), null);
    final File skeletonsDir = new File(tempDir, PythonSdkType.SKELETON_DIR_NAME);
    FileUtil.createDirectory(skeletonsDir);
    final String skeletonsPath = skeletonsDir.toString();
    PythonSdkType.addSdkRoot(modificator, skeletonsPath);

    UsefulTestCase.edt(new Runnable() {
      @Override
      public void run() {
        modificator.commitChanges();
      }
    });

    final SkeletonVersionChecker checker = new SkeletonVersionChecker(0);
    final PySkeletonRefresher refresher = new PySkeletonRefresher(project, null, sdk, skeletonsPath, null, null);
    final List<String> errors = refresher.regenerateSkeletons(checker);
    Assert.assertThat("Errors found", errors, Matchers.empty());
  }
}