From 7038e3e9aa4b62058a06b2089dcf193847aabbca Mon Sep 17 00:00:00 2001 From: "liana.bakradze" Date: Sat, 16 Jul 2016 11:18:55 +0300 Subject: [PATCH 1/6] EDU-338 Add supported python versions info to the course.json --- .../jetbrains/edu/coursecreator/CCUtils.java | 2 +- .../coursecreator/ui/CCNewProjectPanel.form | 20 +++++++-- .../coursecreator/ui/CCNewProjectPanel.java | 22 ++++++++++ .../edu/learning/courseFormat/Course.java | 21 ++++++++- .../coursecreator/PyCCProjectGenerator.java | 44 ++++++++++++++----- .../learning/PyStudyPluginConfigurator.java | 2 +- 6 files changed, 95 insertions(+), 16 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java index 2d68478b6845..331366280c17 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java @@ -44,7 +44,7 @@ public class CCUtils { @Nullable public static CCLanguageManager getStudyLanguageManager(@NotNull final Course course) { - Language language = Language.findLanguageByID(course.getLanguage()); + Language language = Language.findLanguageByID(course.getLanguageID()); return language == null ? null : CCLanguageManager.INSTANCE.forLanguage(language); } diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form index d4c33c0524d1..9af0ba14c209 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form @@ -1,6 +1,6 @@
- + @@ -26,7 +26,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -60,6 +60,20 @@ + + + + + + + + + + + + + + diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java index b3b141d6cb8c..7b4830c9cb43 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java @@ -1,10 +1,12 @@ package com.jetbrains.edu.coursecreator.ui; import com.intellij.facet.ui.FacetValidatorsManager; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.JBColor; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentEvent; @@ -14,10 +16,14 @@ public class CCNewProjectPanel { private JTextArea myDescription; private JTextField myName; private JTextField myAuthorField; + private JLabel myLanguageLevelLabel; + private ComboBox myLanguageLevelCombobox; private FacetValidatorsManager myValidationManager; public CCNewProjectPanel() { + myLanguageLevelLabel.setVisible(false); + myLanguageLevelCombobox.setVisible(false); final String userName = System.getProperty("user.name"); if (userName != null) { myAuthorField.setText(userName); @@ -81,4 +87,20 @@ public class CCNewProjectPanel { public JTextField getNameField() { return myName; } + + public JLabel getLanguageLevelLabel() { + return myLanguageLevelLabel; + } + + public ComboBox getLanguageLevelCombobox() { + return myLanguageLevelCombobox; + } + + @Nullable + public String getLanguageVersion() { + if (!myLanguageLevelCombobox.isVisible() || myLanguageLevelCombobox.getItemCount() == 0) { + return null; + } + return (String)myLanguageLevelCombobox.getSelectedItem(); + } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java index fa4f47594757..98e3eeca0f1b 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java @@ -10,6 +10,7 @@ import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.stepic.StepicUser; import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -122,9 +123,14 @@ public class Course { } public Language getLanguageById() { - return Language.findLanguageByID(myLanguage); + return Language.findLanguageByID(getLanguageID()); } + /** + * This method should be used by serialized only + * Use {@link #getLanguageID()} and {@link #getLanguageVersion()} methods instead + */ + @Deprecated public String getLanguage() { return myLanguage; } @@ -133,6 +139,19 @@ public class Course { myLanguage = language; } + public String getLanguageID() { + return myLanguage.split(" ")[0]; + } + + @Nullable + public String getLanguageVersion() { + String[] split = myLanguage.split(" "); + if (split.length <= 1) { + return null; + } + return split[1]; + } + public void setAuthors(List authors) { this.authors = authors; } diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index b0b612df6f2e..b37ea4c4f0f0 100644 --- a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -12,6 +12,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; @@ -27,6 +28,7 @@ import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.statistics.EduUsagesCollector; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.newProject.PythonProjectGenerator; +import com.jetbrains.python.psi.LanguageLevel; import icons.CourseCreatorPythonIcons; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -38,6 +40,9 @@ import java.io.File; public class PyCCProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator { private static final Logger LOG = Logger.getInstance(PyCCProjectGenerator.class); + public static final String ALL_VERSIONS = "All versions"; + public static final String PYTHON_3 = "3x"; + public static final String PYTHON_2 = "2x"; private CCNewProjectPanel mySettingsPanel; @Nls @@ -56,14 +61,11 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire @Override public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, @Nullable Object settings, @NotNull Module module) { - generateProject(project, baseDir, mySettingsPanel.getName(), - mySettingsPanel.getAuthors(), mySettingsPanel.getDescription()); + generateProject(project, baseDir, mySettingsPanel); } - public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, - @NotNull final String name, @NotNull final String[] authors, - @NotNull final String description) { - final Course course = getCourse(project, name, authors, description); + public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir, CCNewProjectPanel settingsPanel) { + final Course course = getCourse(project, settingsPanel); EduUsagesCollector.projectTypeCreated(CCUtils.COURSE_MODE); final PsiDirectory projectDir = PsiManager.getInstance(project).findDirectory(baseDir); @@ -94,12 +96,19 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire } @NotNull - private static Course getCourse(@NotNull Project project, @NotNull String name, @NotNull String[] authors, @NotNull String description) { + private static Course getCourse(@NotNull Project project, @NotNull CCNewProjectPanel settingsPanel) { final Course course = new Course(); + String name = settingsPanel.getName(); course.setName(name); - course.setAuthors(authors); - course.setDescription(description); - course.setLanguage(PythonLanguage.getInstance().getID()); + course.setAuthors(settingsPanel.getAuthors()); + course.setDescription(settingsPanel.getDescription()); + + String language = PythonLanguage.getInstance().getID(); + String version = settingsPanel.getLanguageVersion(); + if (version != null && !ALL_VERSIONS.equals(version)) { + language += " " + version; + } + course.setLanguage(language); course.setCourseMode(CCUtils.COURSE_MODE); File coursesDir = new File(PathManager.getConfigPath(), "courses"); @@ -125,6 +134,7 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire @Override public JPanel extendBasePanel() throws ProcessCanceledException { mySettingsPanel = new CCNewProjectPanel(); + setupLanguageLevels(mySettingsPanel); mySettingsPanel.registerValidators(new FacetValidatorsManager() { public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) { throw new UnsupportedOperationException(); @@ -136,4 +146,18 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire }); return mySettingsPanel.getMainPanel(); } + + private static void setupLanguageLevels(CCNewProjectPanel panel) { + JLabel languageLevelLabel = panel.getLanguageLevelLabel(); + languageLevelLabel.setText("Python Version:"); + languageLevelLabel.setVisible(true); + ComboBox languageLevelCombobox = panel.getLanguageLevelCombobox(); + languageLevelCombobox.addItem(ALL_VERSIONS); + languageLevelCombobox.addItem(PYTHON_3); + languageLevelCombobox.addItem(PYTHON_2); + for (LanguageLevel level : LanguageLevel.values()) { + languageLevelCombobox.addItem(level.toString()); + } + languageLevelCombobox.setVisible(true); + } } diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java index 5a163337ecfa..76890be13420 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyPluginConfigurator.java @@ -34,6 +34,6 @@ public class PyStudyPluginConfigurator extends StudyBasePluginConfigurator { StudyTaskManager taskManager = StudyTaskManager.getInstance(project); if (taskManager == null) return false; Course course = taskManager.getCourse(); - return course != null && "Python".equals(course.getLanguage()) && "PyCharm".equals(course.getCourseType()); + return course != null && "Python".equals(course.getLanguageID()) && "PyCharm".equals(course.getCourseType()); } } From f342787bb7bcc0a3ac6f89a1a8f21f7775cb0391 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 20 Jul 2016 17:33:27 +0300 Subject: [PATCH 2/6] larger course description panel --- .../src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java index fce2da4a59db..f9b3b14a1849 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java @@ -104,7 +104,7 @@ public class StudyNewProjectPanel extends JPanel implements PanelWithAnchor { myDescriptionPane.setEditable(true); myDescriptionPane.setEnabled(true); myAuthorLabel.setEnabled(true); - myDescriptionPane.setPreferredSize(new Dimension(150, 100)); + myDescriptionPane.setPreferredSize(new Dimension(150, 150)); myDescriptionPane.setFont(coursesCombo.getFont()); myInfoPanel.add(myAuthorLabel); myInfoPanel.add(myDescriptionPane); From 2206f6585e2477139d53d67dc72e1cee571284d8 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 20 Jul 2016 20:57:32 +0300 Subject: [PATCH 3/6] prefer python 3 sdk to create projects --- .../PythonGenerateProjectCallback.java | 31 +++++++++++++------ .../jetbrains/python/sdk/PythonSdkType.java | 2 +- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java b/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java index 220ea0d959f0..ee6e620a2851 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java @@ -44,6 +44,7 @@ import com.jetbrains.python.newProject.PythonProjectGenerator; import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.packaging.PyPackageManagerUI; import com.jetbrains.python.packaging.PyRequirement; +import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.sdk.*; import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import org.jetbrains.annotations.NotNull; @@ -101,9 +102,10 @@ public class PythonGenerateProjectCallback implements NullableConsumer requirements = manager.getRequirements(module); - if (requirements != null && sdk != null) { + if (requirements != null) { final PyPackageManagerUI ui = new PyPackageManagerUI(project, sdk, null); ui.install(requirements, Collections.emptyList()); } @@ -139,14 +141,8 @@ public class PythonGenerateProjectCallback implements NullableConsumer flavors = PythonSdkFlavor.getApplicableFlavors(false); - String baseSdk = null; - for (PythonSdkFlavor flavor : flavors) { - final Collection baseSdks = flavor.suggestHomePaths(); - if (!baseSdks.isEmpty()) { - baseSdk = baseSdks.iterator().next(); - } - } + final String baseSdk = getBaseSdk(); + if (baseSdk != null) { final PyPackageManager packageManager = PyPackageManager.getInstance(new PyDetectedSdk(baseSdk)); try { @@ -171,6 +167,23 @@ public class PythonGenerateProjectCallback implements NullableConsumer baseSdks = flavor.suggestHomePaths(); + for (String sdk : baseSdks) { + final String versionString = flavor.getVersionString(sdk); + final String prefix = flavor.getName() + " "; + if (versionString != null && versionString.startsWith(prefix)) { + final LanguageLevel level = LanguageLevel.fromPythonVersion(versionString.substring(prefix.length())); + if (level.isAtLeast(LanguageLevel.PYTHON30)) { + python3Sdk = sdk; + } + } + } + return python3Sdk != null ? python3Sdk : baseSdks.iterator().next(); + } + @Nullable private static Project generateProject(@NotNull final ProjectSettingsStepBase settings) { final DirectoryProjectGenerator generator = settings.getProjectGenerator(); diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index f4e78a80c7c8..ea124318a5ae 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -424,7 +424,7 @@ public final class PythonSdkType extends SdkType { return suggestSdkNameFromVersion(sdkHome, name); } - public static String suggestSdkNameFromVersion(String sdkHome, String version) { + private static String suggestSdkNameFromVersion(String sdkHome, String version) { sdkHome = FileUtil.toSystemDependentName(sdkHome); final String shortHomeName = FileUtil.getLocationRelativeToUserHome(sdkHome); if (version != null) { From 709c8906ce64147047b3eaa52380e4bcb2cd6381 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 25 Jul 2016 17:26:51 +0300 Subject: [PATCH 4/6] moved virtualenv creation to the project generator --- .../coursecreator/ui/CCNewProjectPanel.form | 8 +-- .../coursecreator/PyCCProjectGenerator.java | 2 +- .../PyStudyDirectoryProjectGenerator.java | 55 ++++++++++++++++++ .../PythonGenerateProjectCallback.java | 57 ++----------------- .../newProject/PythonProjectGenerator.java | 3 + 5 files changed, 67 insertions(+), 58 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form index 9af0ba14c209..7d27d1116c6d 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form @@ -1,6 +1,6 @@
- + @@ -20,7 +20,7 @@ - + @@ -46,13 +46,13 @@ - + - + diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index b37ea4c4f0f0..dfe93ef62c2e 100644 --- a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -149,7 +149,7 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire private static void setupLanguageLevels(CCNewProjectPanel panel) { JLabel languageLevelLabel = panel.getLanguageLevelLabel(); - languageLevelLabel.setText("Python Version:"); + languageLevelLabel.setText("Python:"); languageLevelLabel.setVisible(true); ComboBox languageLevelCombobox = panel.getLanguageLevelCombobox(); languageLevelCombobox.addItem(ALL_VERSIONS); diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java index 1e63ad532000..2b562590f0d8 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -1,5 +1,6 @@ package com.jetbrains.edu.learning; +import com.intellij.execution.ExecutionException; import com.intellij.facet.ui.FacetEditorValidator; import com.intellij.facet.ui.FacetValidatorsManager; import com.intellij.facet.ui.ValidationResult; @@ -9,11 +10,13 @@ import com.intellij.ide.fileTemplates.FileTemplateUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; +import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.psi.PsiDirectory; @@ -24,7 +27,13 @@ import com.jetbrains.edu.learning.stepic.CourseInfo; import com.jetbrains.edu.learning.stepic.EduStepicConnector; import com.jetbrains.edu.learning.ui.StudyNewProjectPanel; import com.jetbrains.python.configuration.PyConfigurableInterpreterList; +import com.jetbrains.python.newProject.PyNewProjectSettings; import com.jetbrains.python.newProject.PythonProjectGenerator; +import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.sdk.AbstractCreateVirtualEnvDialog; +import com.jetbrains.python.sdk.PyDetectedSdk; +import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import icons.InteractiveLearningPythonIcons; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -34,6 +43,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.util.Collection; import java.util.List; @@ -176,4 +186,49 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp return true; }; } + + public void createAndAddVirtualEnv(Project project, PyNewProjectSettings settings) { + final ProjectSdksModel model = PyConfigurableInterpreterList.getInstance(project).getModel(); + final String baseSdk = getBaseSdk(); + + if (baseSdk != null) { + final PyPackageManager packageManager = PyPackageManager.getInstance(new PyDetectedSdk(baseSdk)); + try { + final String path = packageManager.createVirtualEnv(project.getBasePath() + "/.idea/VirtualEnvironment", false); + AbstractCreateVirtualEnvDialog.setupVirtualEnvSdk(path, true, new AbstractCreateVirtualEnvDialog.VirtualEnvCallback() { + @Override + public void virtualEnvCreated(Sdk createdSdk, boolean associateWithProject) { + settings.setSdk(createdSdk); + model.addSdk(createdSdk); + try { + model.apply(); + } + catch (ConfigurationException exception) { + LOG.error("Error adding created virtual env " + exception.getMessage()); + } + } + }); + } + catch (ExecutionException e) { + LOG.warn("Failed to create virtual env " + e.getMessage()); + } + } + } + + private static String getBaseSdk() { + final PythonSdkFlavor flavor = PythonSdkFlavor.getApplicableFlavors(false).get(0); + String python3Sdk = null; + final Collection baseSdks = flavor.suggestHomePaths(); + for (String sdk : baseSdks) { + final String versionString = flavor.getVersionString(sdk); + final String prefix = flavor.getName() + " "; + if (versionString != null && versionString.startsWith(prefix)) { + final LanguageLevel level = LanguageLevel.fromPythonVersion(versionString.substring(prefix.length())); + if (level.isAtLeast(LanguageLevel.PYTHON30)) { + python3Sdk = sdk; + } + } + } + return python3Sdk != null ? python3Sdk : baseSdks.iterator().next(); + } } diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java b/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java index ee6e620a2851..245ec1905768 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/PythonGenerateProjectCallback.java @@ -15,7 +15,6 @@ */ package com.jetbrains.python.newProject.actions; -import com.intellij.execution.ExecutionException; import com.intellij.ide.util.projectWizard.AbstractNewProjectStep; import com.intellij.ide.util.projectWizard.ProjectSettingsStepBase; import com.intellij.ide.util.projectWizard.WebProjectTemplate; @@ -44,13 +43,10 @@ import com.jetbrains.python.newProject.PythonProjectGenerator; import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.packaging.PyPackageManagerUI; import com.jetbrains.python.packaging.PyRequirement; -import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.sdk.*; -import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; import java.util.Collections; import java.util.List; @@ -79,10 +75,11 @@ public class PythonGenerateProjectCallback implements NullableConsumer baseSdks = flavor.suggestHomePaths(); - for (String sdk : baseSdks) { - final String versionString = flavor.getVersionString(sdk); - final String prefix = flavor.getName() + " "; - if (versionString != null && versionString.startsWith(prefix)) { - final LanguageLevel level = LanguageLevel.fromPythonVersion(versionString.substring(prefix.length())); - if (level.isAtLeast(LanguageLevel.PYTHON30)) { - python3Sdk = sdk; - } - } - } - return python3Sdk != null ? python3Sdk : baseSdks.iterator().next(); - } - @Nullable private static Project generateProject(@NotNull final ProjectSettingsStepBase settings) { final DirectoryProjectGenerator generator = settings.getProjectGenerator(); diff --git a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java index ba2723ad8c32..275fd33234bc 100644 --- a/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java +++ b/python/openapi/src/com/jetbrains/python/newProject/PythonProjectGenerator.java @@ -17,6 +17,7 @@ package com.jetbrains.python.newProject; import com.intellij.facet.ui.ValidationResult; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.util.BooleanFunction; import com.intellij.util.containers.ContainerUtil; @@ -83,4 +84,6 @@ public abstract class PythonProjectGenerator { public MouseListener getErrorLabelMouseListener() { return myErrorLabelMouseListener; } + + public void createAndAddVirtualEnv(Project project, PyNewProjectSettings settings) {} } From 8f42fbff7d0b2bca6ea2f06fe226c5270094bd16 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 25 Jul 2016 17:52:49 +0300 Subject: [PATCH 5/6] use course language level to create virtualenv --- .../StudyProjectGenerator.java | 28 +++++++++---------- .../PyStudyDirectoryProjectGenerator.java | 22 +++++++++++---- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java index 1f36a3c6265f..3229be1fecb6 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java @@ -11,7 +11,6 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -105,7 +104,7 @@ public class StudyProjectGenerator { } @Nullable - protected Course getCourse(@NotNull final Project project) { + public Course getCourse(@NotNull final Project project) { final File courseFile = new File(new File(OUR_COURSES_DIR, mySelectedCourseInfo.getName()), EduNames.COURSE_META_FILE); if (courseFile.exists()) { @@ -119,20 +118,17 @@ public class StudyProjectGenerator { return readCourseFromCache(adaptiveCourseFile, true); } } - return ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable() { - @Override - public Course compute() throws RuntimeException { - ProgressManager.getInstance().getProgressIndicator().setIndeterminate(true); - return execCancelable(() -> { + return ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { + ProgressManager.getInstance().getProgressIndicator().setIndeterminate(true); + return execCancelable(() -> { - final Course course = EduStepicConnector.getCourse(project, mySelectedCourseInfo); - if (course != null) { - flushCourse(project, course); - course.initCourse(false); - } - return course; - }); - } + final Course course = EduStepicConnector.getCourse(project, mySelectedCourseInfo); + if (course != null) { + flushCourse(project, course); + course.initCourse(false); + } + return course; + }); }, "Creating Course", true, project); } @@ -161,7 +157,9 @@ public class StudyProjectGenerator { public static void openFirstTask(@NotNull final Course course, @NotNull final Project project) { LocalFileSystem.getInstance().refresh(false); final Lesson firstLesson = StudyUtils.getFirst(course.getLessons()); + if (firstLesson == null) return; final Task firstTask = StudyUtils.getFirst(firstLesson.getTaskList()); + if (firstTask == null) return; final VirtualFile taskDir = firstTask.getTaskDir(project); if (taskDir == null) return; final Map taskFiles = firstTask.getTaskFiles(); diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java index 2b562590f0d8..2e7288b30701 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -22,6 +22,7 @@ import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; import com.intellij.util.BooleanFunction; +import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; import com.jetbrains.edu.learning.stepic.CourseInfo; import com.jetbrains.edu.learning.stepic.EduStepicConnector; @@ -189,7 +190,7 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp public void createAndAddVirtualEnv(Project project, PyNewProjectSettings settings) { final ProjectSdksModel model = PyConfigurableInterpreterList.getInstance(project).getModel(); - final String baseSdk = getBaseSdk(); + final String baseSdk = getBaseSdk(project); if (baseSdk != null) { final PyPackageManager packageManager = PyPackageManager.getInstance(new PyDetectedSdk(baseSdk)); @@ -215,20 +216,29 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp } } - private static String getBaseSdk() { + private String getBaseSdk(@NotNull final Project project) { + final Course course = myGenerator.getCourse(project); + LanguageLevel baseLevel = LanguageLevel.PYTHON30; + if (course != null) { + final String version = course.getLanguageVersion(); + if (version != null) { + baseLevel = LanguageLevel.fromPythonVersion(version); + } + } final PythonSdkFlavor flavor = PythonSdkFlavor.getApplicableFlavors(false).get(0); - String python3Sdk = null; + String baseSdk = null; final Collection baseSdks = flavor.suggestHomePaths(); for (String sdk : baseSdks) { final String versionString = flavor.getVersionString(sdk); final String prefix = flavor.getName() + " "; if (versionString != null && versionString.startsWith(prefix)) { final LanguageLevel level = LanguageLevel.fromPythonVersion(versionString.substring(prefix.length())); - if (level.isAtLeast(LanguageLevel.PYTHON30)) { - python3Sdk = sdk; + if (level.isAtLeast(baseLevel)) { + baseSdk = sdk; + break; } } } - return python3Sdk != null ? python3Sdk : baseSdks.iterator().next(); + return baseSdk != null ? baseSdk : baseSdks.iterator().next(); } } From ef8d7bd9389b04662d562641be4a9d2399e1091d Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 25 Jul 2016 18:33:27 +0300 Subject: [PATCH 6/6] show course language level only in change course info dialog --- .../resources/META-INF/plugin.xml | 2 +- .../actions/CCChangeCourseInfo.java | 7 ++- .../coursecreator/ui/CCNewProjectPanel.form | 4 +- .../coursecreator/PyCCChangeCourseInfo.java | 47 +++++++++++++++++++ .../coursecreator/PyCCProjectGenerator.java | 23 --------- .../PyStudyDirectoryProjectGenerator.java | 4 +- .../edu/learning/PyStudyLanguageManager.java | 2 + 7 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCChangeCourseInfo.java diff --git a/python/educational-core/course-creator/resources/META-INF/plugin.xml b/python/educational-core/course-creator/resources/META-INF/plugin.xml index 94c1704c0429..313a484685ad 100644 --- a/python/educational-core/course-creator/resources/META-INF/plugin.xml +++ b/python/educational-core/course-creator/resources/META-INF/plugin.xml @@ -54,7 +54,7 @@ - + diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java index 9b0839dacaa6..4552161cdb91 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java @@ -19,7 +19,6 @@ import javax.swing.*; import java.awt.*; public class CCChangeCourseInfo extends DumbAwareAction { - private static final String ACTION_TEXT = "Change Course Information"; public CCChangeCourseInfo() { @@ -61,15 +60,21 @@ public class CCChangeCourseInfo extends DumbAwareAction { CCNewProjectPanel panel = new CCNewProjectPanel(course.getName(), Course.getAuthorsString(course.getAuthors()), course.getDescription()); + setupLanguageLevels(course, panel); DialogBuilder builder = createChangeInfoDialog(project, panel); if (builder.showAndGet()) { course.setAuthors(panel.getAuthors()); course.setName(panel.getName()); course.setDescription(panel.getDescription()); + setVersion(course, panel); ProjectView.getInstance(project).refresh(); } } + protected void setVersion(Course course, CCNewProjectPanel panel) {} + + protected void setupLanguageLevels(Course course, CCNewProjectPanel panel) {} + private static DialogBuilder createChangeInfoDialog(Project project, @NotNull CCNewProjectPanel panel) { DialogBuilder builder = new DialogBuilder(project); diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form index 7d27d1116c6d..a38d52649a60 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.form @@ -15,7 +15,7 @@ - + @@ -53,7 +53,7 @@ - + diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCChangeCourseInfo.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCChangeCourseInfo.java new file mode 100644 index 000000000000..5845edc0ffc2 --- /dev/null +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCChangeCourseInfo.java @@ -0,0 +1,47 @@ +package com.jetbrains.edu.coursecreator; + +import com.intellij.openapi.ui.ComboBox; +import com.jetbrains.edu.coursecreator.actions.CCChangeCourseInfo; +import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel; +import com.jetbrains.edu.learning.courseFormat.Course; +import com.jetbrains.python.PythonLanguage; + +import javax.swing.*; + +import static com.jetbrains.edu.learning.PyStudyLanguageManager.PYTHON_2; +import static com.jetbrains.edu.learning.PyStudyLanguageManager.PYTHON_3; + +public class PyCCChangeCourseInfo extends CCChangeCourseInfo { + public static final String ALL_VERSIONS = "All versions"; + + public PyCCChangeCourseInfo() { + super(); + } + + protected void setVersion(Course course, CCNewProjectPanel panel) { + String version = panel.getLanguageVersion(); + String language = PythonLanguage.getInstance().getID(); + if (version != null && !ALL_VERSIONS.equals(version)) { + language += " " + version; + } + course.setLanguage(language); + } + + protected void setupLanguageLevels(Course course, CCNewProjectPanel panel) { + JLabel languageLevelLabel = panel.getLanguageLevelLabel(); + languageLevelLabel.setText("Python:"); + languageLevelLabel.setVisible(true); + ComboBox languageLevelCombobox = panel.getLanguageLevelCombobox(); + languageLevelCombobox.addItem(ALL_VERSIONS); + languageLevelCombobox.addItem(PYTHON_3); + languageLevelCombobox.addItem(PYTHON_2); + languageLevelCombobox.setVisible(true); + final String version = course.getLanguageVersion(); + if (version != null) { + languageLevelCombobox.setSelectedItem(version); + } + else { + languageLevelCombobox.setSelectedItem(ALL_VERSIONS); + } + } +} diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index dfe93ef62c2e..29b7c31b6493 100644 --- a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -12,7 +12,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.platform.DirectoryProjectGenerator; @@ -28,7 +27,6 @@ import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.statistics.EduUsagesCollector; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.newProject.PythonProjectGenerator; -import com.jetbrains.python.psi.LanguageLevel; import icons.CourseCreatorPythonIcons; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -40,9 +38,6 @@ import java.io.File; public class PyCCProjectGenerator extends PythonProjectGenerator implements DirectoryProjectGenerator { private static final Logger LOG = Logger.getInstance(PyCCProjectGenerator.class); - public static final String ALL_VERSIONS = "All versions"; - public static final String PYTHON_3 = "3x"; - public static final String PYTHON_2 = "2x"; private CCNewProjectPanel mySettingsPanel; @Nls @@ -104,10 +99,6 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire course.setDescription(settingsPanel.getDescription()); String language = PythonLanguage.getInstance().getID(); - String version = settingsPanel.getLanguageVersion(); - if (version != null && !ALL_VERSIONS.equals(version)) { - language += " " + version; - } course.setLanguage(language); course.setCourseMode(CCUtils.COURSE_MODE); @@ -134,7 +125,6 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire @Override public JPanel extendBasePanel() throws ProcessCanceledException { mySettingsPanel = new CCNewProjectPanel(); - setupLanguageLevels(mySettingsPanel); mySettingsPanel.registerValidators(new FacetValidatorsManager() { public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) { throw new UnsupportedOperationException(); @@ -147,17 +137,4 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire return mySettingsPanel.getMainPanel(); } - private static void setupLanguageLevels(CCNewProjectPanel panel) { - JLabel languageLevelLabel = panel.getLanguageLevelLabel(); - languageLevelLabel.setText("Python:"); - languageLevelLabel.setVisible(true); - ComboBox languageLevelCombobox = panel.getLanguageLevelCombobox(); - languageLevelCombobox.addItem(ALL_VERSIONS); - languageLevelCombobox.addItem(PYTHON_3); - languageLevelCombobox.addItem(PYTHON_2); - for (LanguageLevel level : LanguageLevel.values()) { - languageLevelCombobox.addItem(level.toString()); - } - languageLevelCombobox.setVisible(true); - } } diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java index 2e7288b30701..2da13df60a45 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -221,8 +221,8 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp LanguageLevel baseLevel = LanguageLevel.PYTHON30; if (course != null) { final String version = course.getLanguageVersion(); - if (version != null) { - baseLevel = LanguageLevel.fromPythonVersion(version); + if (PyStudyLanguageManager.PYTHON_2.equals(version)) { + baseLevel = LanguageLevel.PYTHON27; } } final PythonSdkFlavor flavor = PythonSdkFlavor.getApplicableFlavors(false).get(0); diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyLanguageManager.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyLanguageManager.java index 5cb6c220d3fc..5eb4b81436e2 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyLanguageManager.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyLanguageManager.java @@ -4,6 +4,8 @@ import com.jetbrains.edu.learning.core.EduNames; import org.jetbrains.annotations.NotNull; public class PyStudyLanguageManager implements StudyLanguageManager { + public static final String PYTHON_3 = "3.x"; + public static final String PYTHON_2 = "2.x"; @NotNull @Override