Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Andras Kovi committed Jul 19, 2017
0 parents commit a9b75cf
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

.idea/
out
29 changes: 29 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

BSD 3-Clause License

Copyright (c) 2017, Nokia All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 changes: 13 additions & 0 deletions PyVenvManage.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PLUGIN_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/resources/META-INF/plugin.xml" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#PyVenvManage


##Introduction

**PyVenvManage** is a plugin for managing the Python interpreter of Pycharm Projects.

It is a general issue that Python projects may have several interpreters in different
virtual environments for the various versions of the language. Managing these venvs
is easily done with `tox`, but configuring the project in Pycharm is painful.

With PyVenvManage the selection and setup of the venv is a few clicks without dialog boxes.

##Features

- Popup menu item to set the project interpreter
- Icon provider to indicate virtual environments in the project view

##Install from the Official PyCharm repository

Coming soon.

##Usage

![usage video](anim.gif?raw=true)
Binary file added anim.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!--
~ Copyright (C) 2017 Nokia
-->

<idea-plugin>
<id>com.github.nokia.pyvenv</id>
<name>PyVenv Manage</name>
<version>1.0</version>
<vendor url="https://github.com/nokia">Nokia</vendor>

<description><![CDATA[
<h1>PyVenvManage</h1>
<h2>Introduction</h2>
<em>PyVenvManage<em> is a plugin for managing the Python interpreter of Pycharm Projects.
<br/>
It is a general issue that Python projects may have several interpreters in different
virtual environments for the various versions of the language. Managing these venvs
is easily done with `tox`, but configuring the project in Pycharm is painful.
<br/>
With PyVenvManage the selection and setup of the venv is significantly simpler without dialog boxes.
<br/>
<h2>Features</h2>
<ul>
<li>Popup menu item to set the project interpreter</li>
<li>Icon for virtual environments in the project view</li>
</ul>]]></description>

<idea-version since-build="145.0"/>

<depends>com.intellij.modules.python</depends>

<extensions defaultExtensionNs="com.intellij">
<iconProvider implementation="com.github.nokia.VenvIconProvider" />
</extensions>

<actions>
<action
id="VenvConfigPlugin.com.github.nokia.ConfigurePythonVenv"
class="com.github.nokia.ConfigurePythonVenv"
text="Set project venv"
description="Configures this directory to be the venv for the project"
icon="PyVenvManageIcons.CONFIGRE_VENV">
<add-to-group group-id="ProjectViewPopupMenu" anchor="last"/>
</action>
</actions>

</idea-plugin>
95 changes: 95 additions & 0 deletions src/com/github/nokia/ConfigurePythonVenv.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2017 Nokia
*/

package com.github.nokia;

import com.intellij.notification.Notification;
import com.intellij.notification.NotificationGroup;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.vfs.VirtualFile;
import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
import com.jetbrains.python.sdk.PythonSdkType;

import java.text.MessageFormat;
import java.util.Collection;

/**
* Configures the selected directory as the virtual environment for the containing project.
*/
public class ConfigurePythonVenv extends AnAction {

@Override
public void actionPerformed(AnActionEvent e) {
Project project = e.getData(CommonDataKeys.PROJECT);

if (project == null) {
return;
}

VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);

if (file == null || !file.isDirectory()) {
return;
}

final String pythonExecutable = PythonSdkType.getPythonExecutable(file.getPath());

if (pythonExecutable != null) {
final PyConfigurableInterpreterList interpreterList = PyConfigurableInterpreterList.getInstance(project);
Collection<Sdk> sdks = interpreterList.getModel().getProjectSdks().values();
Sdk s = findExistingSdkForExecutable(pythonExecutable, sdks);

if (s == null) {
s = SdkConfigurationUtil.createAndAddSDK(pythonExecutable, PythonSdkType.getInstance());
}

SdkConfigurationUtil.setDirectoryProjectSdk(project, s);
showNotification(project, s);
}
}

private Sdk findExistingSdkForExecutable(String pythonExecutablePath, Collection<Sdk> sdks) {
for (Sdk sdk : sdks) {
if (pythonExecutablePath.equals(sdk.getHomePath())) {
return sdk;
}
}
return null;
}

private void showNotification(Project project, Sdk s) {
NotificationGroup notificationGroup = NotificationGroup.balloonGroup("SDK changed notification");
String message = MessageFormat.format("Updated SDK for project {0} to: {1}", project, s);
Notification notification = notificationGroup.createNotification(message, MessageType.INFO);
notification.notify(project);
}

@Override
public void update(AnActionEvent e) {
VirtualFile file = e.getData(CommonDataKeys.VIRTUAL_FILE);

if (file == null) {
return;
}

if (file.isDirectory()) {

if (PythonSdkType.getPythonExecutable(file.getPath()) != null) {
e.getPresentation().setEnabledAndVisible(true);
return;
}

}

e.getPresentation().setEnabledAndVisible(false);
}


}
32 changes: 32 additions & 0 deletions src/com/github/nokia/VenvIconProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2017 Nokia
*/

package com.github.nokia;

import com.intellij.ide.IconProvider;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.sdk.PythonSdkType;
import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.Icon;

/**
* Sets the icon of Virtual Environment directories in the project view.
*/
public class VenvIconProvider extends IconProvider {
@Nullable
@Override
public Icon getIcon(@NotNull PsiElement element, int flags) {
if (element instanceof PsiDirectory) {
final String venvRootPath = ((PsiDirectory) element).getVirtualFile().getPath();
if (PythonSdkType.getPythonExecutable(venvRootPath) != null) {
return PythonIcons.Python.Virtualenv;
};
}
return null;
}
}
11 changes: 11 additions & 0 deletions src/icons/PyVenvManageIcons.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright (C) 2017 Nokia
*/

package icons;

import javax.swing.*;

public interface PyVenvManageIcons {
Icon CONFIGRE_VENV = PythonIcons.Python.Python;
}

0 comments on commit a9b75cf

Please sign in to comment.