mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -2432,8 +2432,11 @@ if __name__ == "__main__":
|
||||
names.append(BUILTIN_MOD_NAME)
|
||||
if '__main__' in names:
|
||||
names.remove('__main__') # we don't want ourselves processed
|
||||
ok = True
|
||||
for name in names:
|
||||
processOne(name, None, True)
|
||||
ok = ok and processOne(name, None, True)
|
||||
if not ok:
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
if len(args) > 2:
|
||||
|
||||
@@ -13,6 +13,8 @@ settings_file = os.getenv('PYCHARM_DJANGO_SETTINGS_MODULE') or os.getenv('DJANGO
|
||||
if not settings_file:
|
||||
settings_file = 'settings'
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE')
|
||||
|
||||
from django.core import management
|
||||
from django.core.management.commands.test import Command
|
||||
from django.conf import settings
|
||||
|
||||
@@ -119,7 +119,7 @@ class InterpreterInterface(BaseInterpreterInterface):
|
||||
server = self.get_server()
|
||||
|
||||
if server is not None:
|
||||
server.NotifyAboutMagic(magic_commands, self.interpreter.ipython.automagic)
|
||||
server.NotifyAboutMagic(magic_commands, self.interpreter.is_automagic())
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -85,3 +85,13 @@ class PyDevFrontEnd(PrefilterFrontEnd):
|
||||
return True #needs more
|
||||
|
||||
return False #execute complete (no more)
|
||||
|
||||
def update(self, globals, locals):
|
||||
locals['_oh'] = self.shell.user_ns['_oh']
|
||||
locals['_ip'] = self.shell.user_ns['_ip']
|
||||
self.shell.user_global_ns = globals
|
||||
self.shell.user_ns = locals
|
||||
|
||||
def is_automagic(self):
|
||||
return True if self.ipython0.rc.automagic else False
|
||||
|
||||
|
||||
@@ -131,3 +131,6 @@ class PyDevFrontEnd:
|
||||
# print(rep)
|
||||
return False #execute complete (no more)
|
||||
|
||||
def is_automagic(self):
|
||||
return self.ipython.automagic
|
||||
|
||||
|
||||
@@ -253,7 +253,10 @@ def start_server(host, port, interpreter):
|
||||
server.register_function(handshake)
|
||||
|
||||
if IPYTHON:
|
||||
interpreter.interpreter.ipython.hooks.editor = ipython_editor(interpreter)
|
||||
try:
|
||||
interpreter.interpreter.ipython.hooks.editor = ipython_editor(interpreter)
|
||||
except :
|
||||
pass
|
||||
|
||||
server.serve_forever()
|
||||
|
||||
|
||||
@@ -310,7 +310,7 @@ class WriterThread(PyDBDaemonThread):
|
||||
def addCommand(self, cmd):
|
||||
""" cmd is NetCommand """
|
||||
self.cmdQueue.put(cmd)
|
||||
|
||||
|
||||
def OnRun(self):
|
||||
""" just loop and write responses """
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<id>Pythonid</id>
|
||||
<name>Python</name>
|
||||
<idea-version since-build="110.0" until-build="111.0"/>
|
||||
<idea-version since-build="112.0" until-build="113.0"/>
|
||||
<description>Smart editing for Python scripts</description>
|
||||
<version>2.8.0</version>
|
||||
<depends>com.intellij.modules.ultimate</depends>
|
||||
|
||||
Binary file not shown.
@@ -63,7 +63,7 @@ public class GenerateBinaryStubsFix implements LocalQuickFix {
|
||||
final PySkeletonRefresher refresher = new PySkeletonRefresher(mySdk, null, null);
|
||||
refresher.generateSkeleton(myQualifiedName, "", assemblyRefs);
|
||||
final VirtualFile skeletonDir;
|
||||
skeletonDir = LocalFileSystem.getInstance().findFileByPath(refresher.getSkeletonPath());
|
||||
skeletonDir = LocalFileSystem.getInstance().findFileByPath(refresher.getSkeletonsPath());
|
||||
if (skeletonDir != null) {
|
||||
skeletonDir.refresh(true, true);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ __builtin__.dir = \
|
||||
__builtin__.divmod = \
|
||||
:type x: int or long or float or complex \n\
|
||||
:type y: int or long or float or complex \n\
|
||||
:rtype: (int or long or float or complex, int or long or float or complex) \n\
|
||||
:rtype: (int or long or float, int or long or float) \n\
|
||||
|
||||
__builtin__.enumerate.__init__ = \
|
||||
:type iterable: collections.Iterable \n\
|
||||
@@ -89,7 +89,7 @@ __builtin__.ord = \
|
||||
__builtin__.pow = \
|
||||
:type x: int or long or float or complex \n\
|
||||
:type y: int or long or float or complex \n\
|
||||
:rtype: int or long or float or complex \n\
|
||||
:rtype: int or long or float \n\
|
||||
|
||||
__builtin__.range = \
|
||||
:type start: int or None \n\
|
||||
|
||||
@@ -44,12 +44,12 @@ public class PyStringFormatInspection extends PyInspection {
|
||||
public static class Visitor extends PyInspectionVisitor {
|
||||
private static class Inspection {
|
||||
private static final ImmutableMap<Character, String> FORMAT_CONVERSIONS = ImmutableMap.<Character, String>builder()
|
||||
.put('d', "int or long")
|
||||
.put('i', "int or long")
|
||||
.put('o', "int or long")
|
||||
.put('u', "int or long")
|
||||
.put('x', "int or long")
|
||||
.put('X', "int or long")
|
||||
.put('d', "int or long or float")
|
||||
.put('i', "int or long or float")
|
||||
.put('o', "int or long or float")
|
||||
.put('u', "int or long or float")
|
||||
.put('x', "int or long or float")
|
||||
.put('X', "int or long or float")
|
||||
.put('e', "float")
|
||||
.put('E', "float")
|
||||
.put('f', "float")
|
||||
|
||||
@@ -358,8 +358,8 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference
|
||||
// TODO: Cython-dependent code without CythonLanguageDialect.isInsideCythonFile() check
|
||||
if (element instanceof PyParameter || element instanceof PyTargetExpression || element instanceof CythonVariable) {
|
||||
// Check if the reference is in the same or inner scope of the element scope, not shadowed by an intermediate declaration
|
||||
PsiElement ourContainer = PsiTreeUtil.getParentOfType(getElement(), PsiNamedElement.class, PyLambdaExpression.class, PyComprehensionElement.class);
|
||||
PsiElement theirContainer = PsiTreeUtil.getParentOfType(element, PsiNamedElement.class, PyLambdaExpression.class, PyComprehensionElement.class);
|
||||
PsiElement ourContainer = PsiTreeUtil.getParentOfType(getElement(), ScopeOwner.class, PyComprehensionElement.class);
|
||||
PsiElement theirContainer = PsiTreeUtil.getParentOfType(element, ScopeOwner.class, PyComprehensionElement.class);
|
||||
if (ourContainer != null) {
|
||||
if (ourContainer == theirContainer) {
|
||||
return true;
|
||||
|
||||
@@ -61,6 +61,16 @@ public class PySkeletonRefresher {
|
||||
private Map<String,Pair<Integer,Long>> myBlacklist;
|
||||
private SkeletonVersionChecker myVersionChecker;
|
||||
|
||||
private static class ListBinariesResult {
|
||||
public final int generatorVersion;
|
||||
public final Map<String, File> modules;
|
||||
|
||||
ListBinariesResult(int generatorVersion, Map<String, File> modules) {
|
||||
this.generatorVersion = generatorVersion;
|
||||
this.modules = modules;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new object that refreshes skeletons of given SDK.
|
||||
* @param sdk a Python SDK
|
||||
@@ -72,7 +82,7 @@ public class PySkeletonRefresher {
|
||||
mySdk = sdk;
|
||||
mySkeletonsPath = skeletonsPath;
|
||||
}
|
||||
|
||||
|
||||
private void indicate(String msg) {
|
||||
if (myIndicator != null) {
|
||||
myIndicator.checkCanceled();
|
||||
@@ -93,23 +103,24 @@ public class PySkeletonRefresher {
|
||||
}
|
||||
}
|
||||
|
||||
private String getExtraSyspath() {
|
||||
if (myExtraSyspath == null) {
|
||||
VirtualFile[] class_dirs = mySdk.getRootProvider().getFiles(OrderRootType.CLASSES);
|
||||
StringBuilder arg_builder = new StringBuilder("\"");
|
||||
int i = 0;
|
||||
while (i < class_dirs.length) {
|
||||
if (i > 0) arg_builder.append(File.pathSeparator);
|
||||
if (class_dirs[i].isInLocalFileSystem()) {
|
||||
final String pathname = class_dirs[i].getPath();
|
||||
if (!mySkeletonsPath.equals(pathname)) arg_builder.append(pathname);
|
||||
}
|
||||
i += 1;
|
||||
private static String getExtraSysPath(Sdk sdk, String skeletonsPath) {
|
||||
final VirtualFile[] classDirs = sdk.getRootProvider().getFiles(OrderRootType.CLASSES);
|
||||
final StringBuilder builder = new StringBuilder("\"");
|
||||
int i = 0;
|
||||
while (i < classDirs.length) {
|
||||
if (i > 0) {
|
||||
builder.append(File.pathSeparator);
|
||||
}
|
||||
arg_builder.append("\"");
|
||||
myExtraSyspath = arg_builder.toString();
|
||||
if (classDirs[i].isInLocalFileSystem()) {
|
||||
final String pathname = classDirs[i].getPath();
|
||||
if (!skeletonsPath.equals(pathname)) {
|
||||
builder.append(pathname);
|
||||
}
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
return myExtraSyspath;
|
||||
builder.append("\"");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +128,7 @@ public class PySkeletonRefresher {
|
||||
* @return path name of skeleton dir for the SDK, guaranteed to be already created.
|
||||
*/
|
||||
@NotNull
|
||||
public String getSkeletonPath() {
|
||||
public String getSkeletonsPath() {
|
||||
if (mySkeletonsPath == null) {
|
||||
mySkeletonsPath = PythonSdkType.getSkeletonsPath(mySdk.getHomePath());
|
||||
final File skeletonsDir = new File(mySkeletonsPath);
|
||||
@@ -132,14 +143,22 @@ public class PySkeletonRefresher {
|
||||
return regenerateSkeletons(cached_checker, null);
|
||||
}
|
||||
|
||||
List<String> regenerateSkeletons(
|
||||
@Nullable SkeletonVersionChecker cached_checker,
|
||||
@Nullable Ref<Boolean> migration_flag
|
||||
) {
|
||||
List<String> error_list = new SmartList<String>();
|
||||
String home_path = mySdk.getHomePath();
|
||||
final File skel_dir = new File(mySkeletonsPath);
|
||||
if (!skel_dir.exists()) skel_dir.mkdirs();
|
||||
@Nullable
|
||||
private static Integer getSkeletonVersion(File file) {
|
||||
final Matcher headerMatcher = getParseHeader(file);
|
||||
if (headerMatcher != null && headerMatcher.matches()) {
|
||||
return fromVersionString(headerMatcher.group(2));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> regenerateSkeletons(@Nullable SkeletonVersionChecker cached_checker,
|
||||
@Nullable Ref<Boolean> migration_flag) {
|
||||
final List<String> error_list = new SmartList<String>();
|
||||
final String home_path = mySdk.getHomePath();
|
||||
final String skeletonsPath = getSkeletonsPath();
|
||||
final File skeletonsDir = new File(skeletonsPath);
|
||||
if (!skeletonsDir.exists()) skeletonsDir.mkdirs();
|
||||
final String readable_path = PythonSdkType.shortenDirName(home_path);
|
||||
|
||||
myBlacklist = loadBlacklist();
|
||||
@@ -147,11 +166,8 @@ public class PySkeletonRefresher {
|
||||
indicate(PyBundle.message("sdk.gen.querying.$0", readable_path));
|
||||
// get generator version and binary libs list in one go
|
||||
|
||||
final List<String> binaries_output = listBinaries();
|
||||
if (binaries_output.size() < 1) {
|
||||
throw new InvalidSdkException("Empty output from " + GENERATOR3 + " for " + home_path);
|
||||
}
|
||||
myGeneratorVersion = fromVersionString(binaries_output.get(0).trim());
|
||||
final ListBinariesResult binaries = listBinaries(mySdk, getExtraSysPath(mySdk, getSkeletonsPath()));
|
||||
myGeneratorVersion = binaries.generatorVersion;
|
||||
myPregeneratedSkeletons = findPregeneratedSkeletons();
|
||||
|
||||
indicate(PyBundle.message("sdk.gen.reading.versions.file"));
|
||||
@@ -159,12 +175,11 @@ public class PySkeletonRefresher {
|
||||
else myVersionChecker = new SkeletonVersionChecker(myGeneratorVersion);
|
||||
|
||||
// check builtins
|
||||
String builtinsFileName = PythonSdkType.getBuiltinsFileName(mySdk);
|
||||
File builtins_file = new File(skel_dir, builtinsFileName);
|
||||
final String builtinsFileName = PythonSdkType.getBuiltinsFileName(mySdk);
|
||||
final File builtinsFile = new File(skeletonsPath, builtinsFileName);
|
||||
|
||||
final boolean oldOrNonExisting = getSkeletonVersion(builtinsFile) == null;
|
||||
|
||||
Matcher header_matcher = getParseHeader(builtins_file);
|
||||
final boolean oldOrNonExisting = header_matcher == null || // no file
|
||||
!header_matcher.matches(); // no version line
|
||||
if (migration_flag != null && !migration_flag.get() && oldOrNonExisting) {
|
||||
migration_flag.set(true);
|
||||
Notifications.Bus.notify(
|
||||
@@ -177,28 +192,60 @@ public class PySkeletonRefresher {
|
||||
}
|
||||
|
||||
if (myPregeneratedSkeletons != null && oldOrNonExisting) {
|
||||
LOG.info("Unpacking pregenerated skeletons...");
|
||||
indicate("Unpacking pregenerated skeletons...");
|
||||
try {
|
||||
ZipUtil.extract(new File(JarFileSystem.getInstance().getVirtualFileForJar(myPregeneratedSkeletons).getPath()),
|
||||
new File(mySkeletonsPath), null);
|
||||
final VirtualFile jar = JarFileSystem.getInstance().getVirtualFileForJar(myPregeneratedSkeletons);
|
||||
if (jar != null) {
|
||||
ZipUtil.extract(new File(jar.getPath()),
|
||||
new File(getSkeletonsPath()), null);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info("Error unpacking pregenerated skeletons", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (myPregeneratedSkeletons == null && (oldOrNonExisting || fromVersionString(header_matcher.group(2)) < myVersionChecker.getBuiltinVersion())) {
|
||||
|
||||
if (oldOrNonExisting) {
|
||||
final Sdk base = PythonSdkType.getInstance().getVirtualEnvBaseSdk(mySdk);
|
||||
if (base != null) {
|
||||
indicate("Copying base SDK skeletons for virtualenv...");
|
||||
final String baseSkeletonsPath = PythonSdkType.getSkeletonsPath(base.getHomePath());
|
||||
final ListBinariesResult baseBinaries = listBinaries(base, getExtraSysPath(base, baseSkeletonsPath));
|
||||
for (Map.Entry<String, File> entry : binaries.modules.entrySet()) {
|
||||
final String module = entry.getKey();
|
||||
final File binary = entry.getValue();
|
||||
final File baseBinary = baseBinaries.modules.get(module);
|
||||
final File fromFile = getSkeleton(module, baseSkeletonsPath);
|
||||
if (baseBinaries.modules.containsKey(module) &&
|
||||
fromFile.exists() &&
|
||||
binary.length() == baseBinary.length()) { // Weak binary modules equality check
|
||||
final File toFile = fromFile.isDirectory() ?
|
||||
getPackageSkeleton(module, skeletonsPath) :
|
||||
getModuleSkeleton(module, skeletonsPath);
|
||||
try {
|
||||
FileUtil.copy(fromFile, toFile);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info("Error copying base virtualenv SDK skeleton for " + module, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final Integer builtinVersion = getSkeletonVersion(builtinsFile);
|
||||
if (myPregeneratedSkeletons == null && (builtinVersion == null || builtinVersion < myVersionChecker.getBuiltinVersion())) {
|
||||
indicate(PyBundle.message("sdk.gen.updating.builtins.$0", readable_path));
|
||||
generateBuiltinSkeletons();
|
||||
}
|
||||
|
||||
if (!oldOrNonExisting) {
|
||||
indicate(PyBundle.message("sdk.gen.cleaning.$0", readable_path));
|
||||
cleanUpSkeletons(skel_dir);
|
||||
cleanUpSkeletons(skeletonsDir);
|
||||
}
|
||||
|
||||
indicate(PyBundle.message("sdk.gen.updating.$0", readable_path));
|
||||
List<UpdateResult> skel_errors = updateOrCreateSkeletons(binaries_output);
|
||||
List<UpdateResult> skel_errors = updateOrCreateSkeletons(binaries.modules);
|
||||
|
||||
if (skel_errors.size() > 0) {
|
||||
indicateMinor(BLACKLIST_FILE_NAME);
|
||||
@@ -206,9 +253,9 @@ public class PySkeletonRefresher {
|
||||
if (error.isFresh()) error_list.add(error.getName());
|
||||
myBlacklist.put(error.getPath(), new Pair<Integer, Long>(myGeneratorVersion, error.getTimestamp()));
|
||||
}
|
||||
storeBlacklist(skel_dir, myBlacklist);
|
||||
storeBlacklist(skeletonsDir, myBlacklist);
|
||||
}
|
||||
else removeBlacklist(skel_dir);
|
||||
else removeBlacklist(skeletonsDir);
|
||||
|
||||
indicate(PyBundle.message("sdk.gen.reloading"));
|
||||
VirtualFile skeletonsVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(mySkeletonsPath);
|
||||
@@ -217,29 +264,53 @@ public class PySkeletonRefresher {
|
||||
return error_list;
|
||||
}
|
||||
|
||||
private List<String> listBinaries() {
|
||||
String homePath = mySdk.getHomePath();
|
||||
final String parent_dir = new File(homePath).getParent();
|
||||
long start_time = System.currentTimeMillis();
|
||||
final ProcessOutput run_result = SdkUtil.getProcessOutput(
|
||||
parent_dir,
|
||||
new String[]{homePath, PythonHelpersLocator.getHelperPath(GENERATOR3), "-v", "-L", "-s", getExtraSyspath()},
|
||||
PythonSdkType.getVirtualEnvAdditionalEnv(homePath),
|
||||
MINUTE * 4 // see PY-3898
|
||||
);
|
||||
LOG.info("Retrieving binary module list took " + (System.currentTimeMillis() - start_time) + " ms");
|
||||
if (run_result.getExitCode() != 0) {
|
||||
StringBuilder sb = new StringBuilder("failed to run ").append(GENERATOR3).append(" for ").append(homePath);
|
||||
if (run_result.isTimeout()) sb.append(": timed out.");
|
||||
@NotNull
|
||||
private static ListBinariesResult listBinaries(Sdk sdk, String extraSysPath) {
|
||||
final String homePath = sdk.getHomePath();
|
||||
final String parentDir = new File(homePath).getParent();
|
||||
final long startTime = System.currentTimeMillis();
|
||||
final String[] cmd = new String[] {homePath, PythonHelpersLocator.getHelperPath(GENERATOR3), "-v", "-L", "-s", extraSysPath};
|
||||
final ProcessOutput process = SdkUtil.getProcessOutput(parentDir,
|
||||
cmd,
|
||||
PythonSdkType.getVirtualEnvAdditionalEnv(homePath),
|
||||
MINUTE * 4); // see PY-3898
|
||||
LOG.info("Retrieving binary module list took " + (System.currentTimeMillis() - startTime) + " ms");
|
||||
if (process.getExitCode() != 0) {
|
||||
final StringBuilder sb = new StringBuilder("failed to run ").append(GENERATOR3).append(" for ").append(homePath);
|
||||
if (process.isTimeout()) {
|
||||
sb.append(": timed out.");
|
||||
}
|
||||
else {
|
||||
sb.append(", exit code ").append(run_result.getExitCode()).append(", stderr: \n-----\n");
|
||||
for (String err_line : run_result.getStderrLines()) sb.append(err_line).append("\n");
|
||||
sb.append(", exit code ")
|
||||
.append(process.getExitCode())
|
||||
.append(", stderr: \n-----\n");
|
||||
for (String line : process.getStderrLines()) {
|
||||
sb.append(line).append("\n");
|
||||
}
|
||||
sb.append("-----");
|
||||
}
|
||||
throw new InvalidSdkException(sb.toString());
|
||||
}
|
||||
// stdout contains version in the first line and then the list of binaries
|
||||
return run_result.getStdoutLines();
|
||||
final List<String> lines = process.getStdoutLines();
|
||||
if (lines.size() < 1) {
|
||||
throw new InvalidSdkException("Empty output from " + GENERATOR3 + " for " + homePath);
|
||||
}
|
||||
final Iterator<String> iter = lines.iterator();
|
||||
final int generatorVersion = fromVersionString(iter.next().trim());
|
||||
final Map<String, File> binaries = new HashMap<String, File>();
|
||||
while (iter.hasNext()) {
|
||||
final String line = iter.next();
|
||||
int cutpos = line.indexOf(' ');
|
||||
if (cutpos >= 0) {
|
||||
String moduleName = line.substring(0, cutpos);
|
||||
String path = line.substring(cutpos + 1);
|
||||
binaries.put(moduleName, new File(path));
|
||||
}
|
||||
else {
|
||||
LOG.error("Bad binaries line: '" + line + "', SDK " + homePath); // but don't die yet
|
||||
}
|
||||
}
|
||||
return new ListBinariesResult(generatorVersion, binaries);
|
||||
}
|
||||
|
||||
static final Pattern ourVersionLinePat = Pattern.compile("# from (\\S+) by generator (\\S+)\\s*");
|
||||
@@ -442,51 +513,56 @@ public class PySkeletonRefresher {
|
||||
* (Re-)generates skeletons for all binary python modules. Up-to-date skeletons are not regenerated.
|
||||
* Does one module at a time: slower, but avoids certain conflicts.
|
||||
*
|
||||
* @param binaries output of generator3 -L, list of prospective binary modules
|
||||
* @param modules output of generator3 -L
|
||||
* @return blacklist data; whatever was not generated successfully is put here.
|
||||
*/
|
||||
private List<UpdateResult> updateOrCreateSkeletons(List<String> binaries) {
|
||||
final List<UpdateResult> error_list = new SmartList<UpdateResult>();
|
||||
final Iterator<String> bin_iter = binaries.iterator();
|
||||
bin_iter.next(); // skip version number. if it weren't here, we'd already die up in regenerateSkeletons()
|
||||
final int count = Math.max(0, binaries.size() - 1);
|
||||
int i = 0;
|
||||
while (bin_iter.hasNext()) {
|
||||
private List<UpdateResult> updateOrCreateSkeletons(Map<String, File> modules) {
|
||||
final List<String> names = new ArrayList<String>(modules.keySet());
|
||||
Collections.sort(names);
|
||||
final List<UpdateResult> results = new ArrayList<UpdateResult>();
|
||||
final int count = names.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
checkCanceled();
|
||||
if (myIndicator != null) {
|
||||
myIndicator.setFraction((double)i / count);
|
||||
}
|
||||
final String line = bin_iter.next(); // line = "mod_name path"
|
||||
int cutpos = line.indexOf(' ');
|
||||
if (cutpos < 0) LOG.error("Bad binaries line: '" + line + "', SDK " + mySdk.getHomePath()); // but don't die yet
|
||||
else {
|
||||
String moduleName = line.substring(0, cutpos);
|
||||
String module_lib_name = line.substring(cutpos+1);
|
||||
if (updateOrCreateSkeleton(moduleName, module_lib_name, error_list)) continue;
|
||||
final String name = names.get(i);
|
||||
final File module = modules.get(name);
|
||||
if (module != null) {
|
||||
updateOrCreateSkeleton(name, module.getPath(), results);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return error_list;
|
||||
return results;
|
||||
}
|
||||
|
||||
private static File getSkeleton(String moduleName, String skeletonsPath) {
|
||||
final File module = getModuleSkeleton(moduleName, skeletonsPath);
|
||||
return module.exists() ? module : getPackageSkeleton(moduleName, skeletonsPath);
|
||||
}
|
||||
|
||||
private static File getModuleSkeleton(String module, String skeletonsPath) {
|
||||
final String modulePath = module.replace('.', '/');
|
||||
return new File(skeletonsPath, modulePath + ".py");
|
||||
}
|
||||
|
||||
private static File getPackageSkeleton(String pkg, String skeletonsPath) {
|
||||
final String packagePath = pkg.replace('.', '/');
|
||||
return new File(new File(skeletonsPath, packagePath), PyNames.INIT_DOT_PY);
|
||||
}
|
||||
|
||||
private boolean updateOrCreateSkeleton(String moduleName, String moduleLibName, List<UpdateResult> error_list) {
|
||||
final String modulePath = moduleName.replace('.', '/');
|
||||
String skeletonPath = getSkeletonPath(); // will create dirs as needed
|
||||
File skeleton_file = new File(skeletonPath, modulePath + ".py");
|
||||
if (!skeleton_file.exists()) {
|
||||
skeleton_file = new File(new File(skeletonPath, modulePath), PyNames.INIT_DOT_PY);
|
||||
}
|
||||
File lib_file = new File(moduleLibName);
|
||||
Matcher matcher = getParseHeader(skeleton_file);
|
||||
final File skeleton = getSkeleton(moduleName, getSkeletonsPath());
|
||||
final File binary = new File(moduleLibName);
|
||||
Matcher matcher = getParseHeader(skeleton);
|
||||
boolean must_rebuild = true; // guilty unless proven fresh enough
|
||||
if (matcher != null && matcher.matches()) {
|
||||
int file_version = SkeletonVersionChecker.fromVersionString(matcher.group(2));
|
||||
int required_version = myVersionChecker.getRequiredVersion(moduleName);
|
||||
must_rebuild = file_version < required_version;
|
||||
}
|
||||
final long lib_file_timestamp = lib_file.lastModified();
|
||||
final long lib_file_timestamp = binary.lastModified();
|
||||
if (!must_rebuild) { // ...but what if the lib was updated?
|
||||
must_rebuild = (lib_file.exists() && skeleton_file.exists() && lib_file_timestamp > skeleton_file.lastModified());
|
||||
must_rebuild = (binary.exists() && skeleton.exists() && lib_file_timestamp > skeleton.lastModified());
|
||||
// really we can omit both exists() calls but I keep these to make the logic clear
|
||||
}
|
||||
if (myBlacklist != null) {
|
||||
@@ -516,7 +592,7 @@ public class PySkeletonRefresher {
|
||||
private boolean copyPregeneratedSkeleton(String moduleName) {
|
||||
File targetDir;
|
||||
final String modulePath = moduleName.replace('.', '/');
|
||||
File skeletonsDir = new File(getSkeletonPath());
|
||||
File skeletonsDir = new File(getSkeletonsPath());
|
||||
VirtualFile pregenerated = myPregeneratedSkeletons.findFileByRelativePath(modulePath + ".py");
|
||||
if (pregenerated == null) {
|
||||
pregenerated = myPregeneratedSkeletons.findFileByRelativePath(modulePath + "/" + PyNames.INIT_DOT_PY);
|
||||
@@ -560,7 +636,11 @@ public class PySkeletonRefresher {
|
||||
return null;
|
||||
}
|
||||
LOG.info("Pregenerated skeletons root is " + root);
|
||||
String version = mySdk.getVersionString().toLowerCase().replace(" ", "-");
|
||||
final String versionString = mySdk.getVersionString();
|
||||
if (versionString == null) {
|
||||
return null;
|
||||
}
|
||||
String version = versionString.toLowerCase().replace(" ", "-");
|
||||
File f;
|
||||
if (SystemInfo.isMac) {
|
||||
String osVersion = SystemInfo.OS_VERSION;
|
||||
@@ -569,7 +649,7 @@ public class PySkeletonRefresher {
|
||||
int secondDot = osVersion.indexOf('.', dot+1);
|
||||
if (secondDot >= 0) {
|
||||
osVersion = osVersion.substring(0, secondDot);
|
||||
}
|
||||
}
|
||||
}
|
||||
f = new File(root, "skeletons-mac-" + myGeneratorVersion + "-" + osVersion + "-" + version + ".zip");
|
||||
}
|
||||
@@ -611,17 +691,18 @@ public class PySkeletonRefresher {
|
||||
* @param assemblyRefs refs that generator wants to know in .net environment, if applicable
|
||||
* @return true if generation completed successfully
|
||||
*/
|
||||
public boolean generateSkeleton(
|
||||
@NotNull String modname, @Nullable String modfilename, @Nullable List<String> assemblyRefs
|
||||
) {
|
||||
public boolean generateSkeleton(@NotNull String modname, @Nullable String modfilename, @Nullable List<String> assemblyRefs) {
|
||||
boolean ret = true;
|
||||
String binaryPath = mySdk.getHomePath();
|
||||
if (myExtraSyspath == null) {
|
||||
myExtraSyspath = getExtraSysPath(mySdk, mySkeletonsPath);
|
||||
}
|
||||
final String parent_dir = new File(binaryPath).getParent();
|
||||
List<String> commandLine = new ArrayList<String>();
|
||||
commandLine.add(binaryPath);
|
||||
commandLine.add(PythonHelpersLocator.getHelperPath(GENERATOR3));
|
||||
commandLine.add("-d");
|
||||
commandLine.add(getSkeletonPath());
|
||||
commandLine.add(getSkeletonsPath());
|
||||
if (assemblyRefs != null && !assemblyRefs.isEmpty()) {
|
||||
commandLine.add("-c");
|
||||
commandLine.add(StringUtil.join(assemblyRefs, ";"));
|
||||
@@ -630,7 +711,7 @@ public class PySkeletonRefresher {
|
||||
commandLine.add("-x");
|
||||
}
|
||||
commandLine.add("-s");
|
||||
commandLine.add(getExtraSyspath());
|
||||
commandLine.add(myExtraSyspath);
|
||||
commandLine.add(modname);
|
||||
if (modfilename != null) commandLine.add(modfilename);
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ public class PythonSdkType extends SdkType {
|
||||
@NotNull
|
||||
@NonNls
|
||||
public static String getBuiltinsFileName(Sdk sdk) {
|
||||
final String version = sdk.getVersionString();
|
||||
final String version = sdk.getVersionString();
|
||||
if (version != null && version.startsWith("Python 3")) {
|
||||
return PyBuiltinCache.BUILTIN_FILE_3K;
|
||||
}
|
||||
@@ -193,6 +193,28 @@ public class PythonSdkType extends SdkType {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean isVirtualEnv(Sdk sdk) {
|
||||
final String path = sdk.getHomePath();
|
||||
return path != null && getVirtualEnvRoot(path) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Sdk getVirtualEnvBaseSdk(Sdk sdk) {
|
||||
if (isVirtualEnv(sdk)) {
|
||||
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdk.getHomePath());
|
||||
final String version = getVersionString(sdk);
|
||||
if (flavor != null && version != null) {
|
||||
for (Sdk baseSdk : getAllSdks()) {
|
||||
final PythonSdkFlavor baseFlavor = PythonSdkFlavor.getFlavor(baseSdk.getHomePath());
|
||||
if (!isVirtualEnv(baseSdk) && flavor.equals(baseFlavor) && version.equals(getVersionString(baseSdk))) {
|
||||
return baseSdk;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param binaryPath must point to a Python interpreter
|
||||
* @return if the surroundings look like a virtualenv installation, its root is returned (normally the grandparent of binaryPath).
|
||||
@@ -425,24 +447,11 @@ public class PythonSdkType extends SdkType {
|
||||
final Task.Modal setupTask = new Task.Modal(project, "Setting up library files for " + sdk.getName(), false) {
|
||||
// TODO: make this a backgroundable task. see #setupSdkPaths(final Sdk sdk) and its modificator handling
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
try {
|
||||
sdkModificator.removeAllRoots();
|
||||
updateSdkRootsFromSysPath(sdkModificator, indicator);
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
new PySkeletonRefresher(sdk, getSkeletonsPath(sdk.getHomePath()), indicator).regenerateSkeletons(null);
|
||||
PythonSdkUpdater.getInstance().markAlreadyUpdated(sdk.getHomePath());
|
||||
}
|
||||
//sdkModificator.commitChanges() must happen outside, in dispatch thread.
|
||||
}
|
||||
catch (InvalidSdkException e) {
|
||||
success.set(false);
|
||||
LOG.warn(e);
|
||||
Notifications.Bus.notify(
|
||||
new Notification(
|
||||
SKELETONS_TOPIC, "Refresh failed", "Skeleton re-generation failed. Please see PyCharm log for traceback. Send it to developers.",
|
||||
NotificationType.WARNING
|
||||
)
|
||||
);
|
||||
sdkModificator.removeAllRoots();
|
||||
updateSdkRootsFromSysPath(sdkModificator, indicator);
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
refreshSkeletonsOfSDK(sdk, getSkeletonsPath(sdk.getHomePath()), null);
|
||||
PythonSdkUpdater.getInstance().markAlreadyUpdated(sdk.getHomePath());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -648,13 +657,15 @@ public class PythonSdkType extends SdkType {
|
||||
}
|
||||
|
||||
static void refreshSkeletonsOfSDK(Sdk sdk) {
|
||||
refreshSkeletonsOfSDK(sdk, findSkeletonsPath(sdk), new Ref<Boolean>(false));
|
||||
}
|
||||
|
||||
static void refreshSkeletonsOfSDK(Sdk sdk, String skeletonsPath, @Nullable Ref<Boolean> migrationFlag) {
|
||||
final Map<String, List<String>> errors = new TreeMap<String, List<String>>();
|
||||
final List<String> failed_sdks = new SmartList<String>();
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
List<String> sdk_errors;
|
||||
Ref<Boolean> migration_flag = new Ref<Boolean>(false);
|
||||
final String homePath = sdk.getHomePath();
|
||||
final String skeletonsPath = findSkeletonsPath(sdk);
|
||||
if (skeletonsPath == null) {
|
||||
LOG.info("Could not find skeletons path for SDK path " + homePath);
|
||||
}
|
||||
@@ -662,7 +673,7 @@ public class PythonSdkType extends SdkType {
|
||||
LOG.info("Refreshing skeletons for " + homePath);
|
||||
try {
|
||||
SkeletonVersionChecker checker = new SkeletonVersionChecker(0); // this default version won't be used
|
||||
sdk_errors = new PySkeletonRefresher(sdk, skeletonsPath, indicator).regenerateSkeletons(checker, migration_flag);
|
||||
sdk_errors = new PySkeletonRefresher(sdk, skeletonsPath, indicator).regenerateSkeletons(checker, migrationFlag);
|
||||
if (sdk_errors.size() > 0) {
|
||||
String sdk_name = sdk.getName();
|
||||
List<String> known_errors = errors.get(sdk_name);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from foo import #import
|
||||
@@ -0,0 +1 @@
|
||||
from foo <caret> #import
|
||||
@@ -0,0 +1,15 @@
|
||||
if True:
|
||||
<caret>foo = {}
|
||||
else:
|
||||
foo = object()
|
||||
|
||||
if "a" == "b":
|
||||
foo.x = 1
|
||||
foo.save()
|
||||
|
||||
if "c" == "d":
|
||||
foo.y = 1
|
||||
foo.save()
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
if True:
|
||||
bar = {}
|
||||
else:
|
||||
bar = object()
|
||||
|
||||
if "a" == "b":
|
||||
bar.x = 1
|
||||
bar.save()
|
||||
|
||||
if "c" == "d":
|
||||
bar.y = 1
|
||||
bar.save()
|
||||
|
||||
|
||||
|
||||
@@ -93,12 +93,12 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testKwParamsInCodeUsage() { //PY-1002
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testKwParamsInCodeGetUsage() { //PY-1002
|
||||
|
||||
public void testKwParamsInCodeGetUsage() { //PY-1002
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSuperInitKwParamsNotOnlySelfAndKwArgs() { //PY-1050
|
||||
public void testSuperInitKwParamsNotOnlySelfAndKwArgs() { //PY-1050
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testIsInstance() {
|
||||
doTest();
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIsInstanceAssert() {
|
||||
@@ -247,7 +247,7 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testNonlocal() { // PY-2289
|
||||
doTest3K();
|
||||
}
|
||||
|
||||
|
||||
public void testYield() {
|
||||
doTest();
|
||||
}
|
||||
@@ -265,15 +265,15 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testSuperMethod() { // PY-170
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testElse() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testElseNotIndented() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testElseInTryNotIndented() {
|
||||
doTest();
|
||||
}
|
||||
@@ -281,7 +281,7 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testElif() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testElifNotIndented() {
|
||||
doTest();
|
||||
}
|
||||
@@ -297,11 +297,11 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testFinallyInExcept() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testContinue() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testNoContinueInFinally() {
|
||||
final String testName = "completion/" + getTestName(true);
|
||||
myFixture.configureByFile(testName + ".py");
|
||||
@@ -332,7 +332,7 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testNoIdentifiersInImport() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testSuperClassAttributes() {
|
||||
doTest();
|
||||
}
|
||||
@@ -452,7 +452,7 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testMro() { // PY-3989
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testNamedTuple() { //
|
||||
final String testName = "completion/" + getTestName(true);
|
||||
myFixture.configureByFile(testName + ".py");
|
||||
@@ -461,15 +461,15 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
assertTrue(strings.contains("lat"));
|
||||
assertTrue(strings.contains("long"));
|
||||
}
|
||||
|
||||
|
||||
public void testPrivateMemberType() { // PY-4589
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
public void testCompleteBeforeSyntaxError() { // PY-3792
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
// PY-4279
|
||||
public void testFieldReassignment() {
|
||||
doTest();
|
||||
@@ -478,4 +478,9 @@ public class PythonCompletionTest extends PyTestCase {
|
||||
public void testSuperInit() { // PY-5066
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-5144
|
||||
public void testImportKeyword() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,10 @@ public class PyRenameTest extends PyTestCase {
|
||||
public void testRenameKeywordArgument() { // PY-3890
|
||||
doTest("baz");
|
||||
}
|
||||
|
||||
public void testRenameTarget() { // PY-5146
|
||||
doTest("bar");
|
||||
}
|
||||
|
||||
public void testClassNameConflict() { // PY-2390
|
||||
doRenameConflictTest("Foo", "A class named 'Foo' is already defined in classNameConflict.py");
|
||||
|
||||
Reference in New Issue
Block a user