diff --git a/python/educational-core/resources/META-INF/plugin.xml b/python/educational-core/resources/META-INF/plugin.xml
index 5f794738eaa2..b3cf04f03d0c 100644
--- a/python/educational-core/resources/META-INF/plugin.xml
+++ b/python/educational-core/resources/META-INF/plugin.xml
@@ -195,4 +195,10 @@
+
+
+
+ com.jetbrains.edu.learning.stepic.EduCourseUpdater
+
+
\ No newline at end of file
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java b/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java
index c41739bef591..0bc4152966a2 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/EduPluginConfigurator.java
@@ -9,6 +9,8 @@ import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
@@ -18,6 +20,7 @@ import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.Lesson;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks;
+import com.jetbrains.edu.learning.courseGeneration.StudyGenerator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -126,9 +129,12 @@ public interface EduPluginConfigurator {
@NotNull Project project,
@NotNull Course course,
@Nullable String moduleDir) {
+ StudyGenerator.createCourse(course, project.getBaseDir());
}
default List getBundledCoursePaths() {
return Collections.emptyList();
}
+
+ default ModuleType getModuleType() {return StdModuleTypes.JAVA;}
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java b/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java
index 19535068e1c1..73be3a89bcc2 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/intellij/EduIntelliJTemplateFactory.java
@@ -3,14 +3,11 @@ package com.jetbrains.edu.learning.intellij;
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplatesFactory;
import com.jetbrains.edu.learning.courseFormat.Course;
-import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
import com.jetbrains.edu.learning.intellij.stepik.EduRemoteCourseTemplate;
+import com.jetbrains.edu.learning.stepic.EduCourseUpdater;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,16 +19,6 @@ import java.util.List;
@SuppressWarnings("unused") //used in other educational plugins that are stored in separate repository
public class EduIntelliJTemplateFactory extends ProjectTemplatesFactory {
private static final String GROUP_NAME = "Education";
- private static List ourRemoteCourses;
-
- static {
- ProgressManager.getInstance().run(new Task.Backgroundable(null, "Updating Course") {
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- ourRemoteCourses = new StudyProjectGenerator().getCourses(true);
- }
- });
- }
@NotNull
@Override
@@ -43,10 +30,9 @@ public class EduIntelliJTemplateFactory extends ProjectTemplatesFactory {
@Override
public ProjectTemplate[] createTemplates(@Nullable String group, WizardContext context) {
final ArrayList templates = new ArrayList<>();
- if (ourRemoteCourses != null) {
- for (Course course : ourRemoteCourses) {
- templates.add(new EduRemoteCourseTemplate(course));
- }
+ final List courses = EduCourseUpdater.getInstance().getRemoteCourses();
+ for (Course course : courses) {
+ templates.add(new EduRemoteCourseTemplate(course));
}
Collections.addAll(templates, ApplicationManager.getApplication().getExtensions(EduIntelliJProjectTemplate.EP_NAME));
return templates.toArray(new ProjectTemplate[templates.size()]);
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/intellij/localCourses/EduCustomCourseProjectTemplate.java b/python/educational-core/src/com/jetbrains/edu/learning/intellij/localCourses/EduCustomCourseProjectTemplate.java
index c80e8f4bc686..378200a8ef58 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/intellij/localCourses/EduCustomCourseProjectTemplate.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/intellij/localCourses/EduCustomCourseProjectTemplate.java
@@ -19,7 +19,7 @@ class EduCustomCourseProjectTemplate implements EduIntelliJProjectTemplate {
@Nullable
@Override
public String getDescription() {
- return "Custom Course Addition";
+ return "Select and add local course from *.zip";
}
@Override
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java b/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java
index 9aa0282e7985..2241f3344b76 100644
--- a/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java
+++ b/python/educational-core/src/com/jetbrains/edu/learning/intellij/stepik/EduRemoteCourseModuleBuilder.java
@@ -1,17 +1,17 @@
package com.jetbrains.edu.learning.intellij.stepik;
-import com.intellij.ide.util.projectWizard.JavaModuleBuilder;
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
-import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory;
import com.intellij.ide.util.projectWizard.SettingsStep;
import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.util.InvalidDataException;
import com.jetbrains.edu.learning.EduPluginConfigurator;
import com.jetbrains.edu.learning.StudyTaskManager;
@@ -23,13 +23,17 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
-class EduRemoteCourseModuleBuilder extends JavaModuleBuilder {
+class EduRemoteCourseModuleBuilder extends ModuleBuilder {
private static final Logger LOG = Logger.getInstance(EduRemoteCourseModuleBuilder.class);
private final Course myCourse;
+ private final ModuleType myModuleType;
+ private final ModuleBuilder myModuleBuilder;
private EduProjectGenerator myGenerator = new EduProjectGenerator();
public EduRemoteCourseModuleBuilder(Course course) {
myCourse = course;
+ myModuleType = EduPluginConfigurator.INSTANCE.forLanguage(myCourse.getLanguageById()).getModuleType();
+ myModuleBuilder = myModuleType.createModuleBuilder();
}
@Nullable
@@ -61,7 +65,7 @@ class EduRemoteCourseModuleBuilder extends JavaModuleBuilder {
@Nullable
@Override
public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep) {
- return ProjectWizardStepFactory.getInstance().createJavaSettingsStep(settingsStep, this, Conditions.alwaysTrue());
+ return myModuleBuilder.modifySettingsStep(settingsStep);
}
@NotNull
@@ -87,4 +91,20 @@ class EduRemoteCourseModuleBuilder extends JavaModuleBuilder {
}
return baseModule;
}
+
+ @Override
+ public void setupRootModel(ModifiableRootModel modifiableRootModel) throws ConfigurationException {
+ myModuleBuilder.setupRootModel(modifiableRootModel);
+ }
+
+ @Override
+ public ModuleType getModuleType() {
+ return myModuleType;
+ }
+
+ @Override
+ public void setContentEntryPath(String moduleRootPath) {
+ myModuleBuilder.setContentEntryPath(moduleRootPath);
+ super.setContentEntryPath(moduleRootPath);
+ }
}
diff --git a/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduCourseUpdater.java b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduCourseUpdater.java
new file mode 100644
index 000000000000..0a7721488be4
--- /dev/null
+++ b/python/educational-core/src/com/jetbrains/edu/learning/stepic/EduCourseUpdater.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jetbrains.edu.learning.stepic;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.components.ApplicationComponent;
+import com.jetbrains.edu.learning.courseFormat.Course;
+import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EduCourseUpdater implements ApplicationComponent {
+
+ private List ourRemoteCourses = new ArrayList<>();
+
+ public List getRemoteCourses() {
+ return ourRemoteCourses;
+ }
+
+ public static EduCourseUpdater getInstance() {
+ return ApplicationManager.getApplication().getComponent(EduCourseUpdater.class);
+ }
+
+ public EduCourseUpdater() {
+ ApplicationManager.getApplication().executeOnPooledThread(
+ () -> ourRemoteCourses = new StudyProjectGenerator().getCourses(true));
+ }
+}
diff --git a/python/educational-python/Edu-Python/resources/META-INF/plugin.xml b/python/educational-python/Edu-Python/resources/META-INF/plugin.xml
index 1d4b1055bfba..70ba9c6a50eb 100644
--- a/python/educational-python/Edu-Python/resources/META-INF/plugin.xml
+++ b/python/educational-python/Edu-Python/resources/META-INF/plugin.xml
@@ -45,8 +45,7 @@
-
+
diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java
index 3bbdd68f95a7..1bf1ad6c2fc4 100644
--- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java
+++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyEduPluginConfigurator.java
@@ -7,7 +7,10 @@ import com.intellij.ide.fileTemplates.FileTemplateUtil;
import com.intellij.ide.util.DirectoryUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -21,6 +24,7 @@ import com.jetbrains.edu.learning.core.EduNames;
import com.jetbrains.edu.learning.courseFormat.Course;
import com.jetbrains.edu.learning.courseFormat.tasks.Task;
import com.jetbrains.edu.learning.courseFormat.tasks.TaskWithSubtasks;
+import com.jetbrains.python.PythonModuleTypeBase;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -144,4 +148,27 @@ public class PyEduPluginConfigurator implements EduPluginConfigurator {
return Collections.singletonList(new File(new File(jarPath, "courses"), COURSE_NAME).getPath());
}
+
+ public ModuleType getModuleType() {
+ return PythonModuleTypeBase.getInstance();
+ }
+
+ @Override
+ public void configureModule(@NotNull Module module) {
+ final Project project = module.getProject();
+ StartupManager.getInstance(project).runWhenProjectIsInitialized(() -> {
+ final VirtualFile baseDir = project.getBaseDir();
+ final String testHelper = EduNames.TEST_HELPER;
+ if (baseDir.findChild(testHelper) != null) return;
+ final FileTemplate template = FileTemplateManager.getInstance(project).getInternalTemplate("test_helper");
+ final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir);
+ if (projectDir == null) return;
+ try {
+ FileTemplateUtil.createFromTemplate(template, testHelper, null, projectDir);
+ }
+ catch (Exception exception) {
+ LOG.error("Can't copy test_helper.py " + exception.getMessage());
+ }
+ });
+ }
}
diff --git a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyInitialConfigurator.java b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyInitialConfigurator.java
index f94eb2f67989..fb87f4f59b8a 100644
--- a/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyInitialConfigurator.java
+++ b/python/educational-python/Edu-Python/src/com/jetbrains/edu/learning/PyStudyInitialConfigurator.java
@@ -3,6 +3,7 @@ package com.jetbrains.edu.learning;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.util.io.FileUtil;
@@ -12,7 +13,7 @@ import org.jetbrains.annotations.NonNls;
import java.io.File;
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor", "UtilityClassWithPublicConstructor"})
-public class PyStudyInitialConfigurator {
+public class PyStudyInitialConfigurator implements ApplicationComponent {
@NonNls private static final String CONFIGURED_V40 = "StudyPyCharm.InitialConfiguration40";
/**