Merge remote-tracking branch 'origin/master'

This commit is contained in:
Ekaterina Tuzova
2012-09-03 14:41:05 -04:00
2 changed files with 66 additions and 38 deletions
+4 -6
View File
@@ -27,8 +27,6 @@ but seemingly no one uses them in C extensions yet anyway.
VERSION = "1.116" # Must be a number-dot-number string, updated with each change that affects generated skeletons
# Note: DON'T FORGET TO UPDATE!
VERSION_CONTROL_HEADER_FORMAT = '# from %s by generator %s'
import sys
import os
import string
@@ -1836,9 +1834,8 @@ class ModuleRedeclarator(object):
else:
mod_name = " does not know its name"
out(0, "# module ", p_name, mod_name) # line 2
out(0, VERSION_CONTROL_HEADER_FORMAT % (
self.mod_filename or getattr(self.module, "__file__", "(built-in)"), VERSION)
) # line 3
out(0, "# from %s" % self.mod_filename or getattr(self.module, "__file__", "(built-in)")) # line 3
out(0, "# by generator %s" % VERSION) # line 4
if p_name == BUILTIN_MOD_NAME and version[0] == 2 and version[1] >= 6:
out(0, "from __future__ import print_function")
self.outDocAttr(out, self.module, 0)
@@ -2485,7 +2482,8 @@ def processOne(name, mod_file_name, doing_builtins):
if outfile is not None and not outfile.closed:
outfile.write("# encoding: %s\n" % OUT_ENCODING)
outfile.write("# module %s\n" % name)
outfile.write(VERSION_CONTROL_HEADER_FORMAT % (mod_file_name, VERSION))
outfile.write("# from %s\n" % mod_file_name)
outfile.write("# by generator %s\n" % VERSION)
outfile.write("\n\n")
outfile.write("# Skeleton generation error:\n#\n# " + (msg % args) + "\n")
if debug_mode:
@@ -55,8 +55,12 @@ public class PySkeletonRefresher {
private final static Pattern BLACKLIST_LINE = Pattern.compile("^([^=]+) = (\\d+\\.\\d+) (\\d+)\\s*$");
// we use the equals sign after filename so that we can freely include space in the filename
private final static Pattern OUR_VERSION_LINE = Pattern.compile("# from (\\S+) by generator (\\S+)\\s*");
// Path (the first component) may contain spaces, this header spec is deprecated
private static final Pattern VERSION_LINE_V1 = Pattern.compile("# from (\\S+) by generator (\\S+)\\s*");
// Skeleton header spec v2
private static final Pattern FROM_LINE_V2 = Pattern.compile("# from (.*)$");
private static final Pattern BY_LINE_V2 = Pattern.compile("# by generator (.*)$");
private String myExtraSyspath;
private VirtualFile myPregeneratedSkeletons;
@@ -148,15 +152,6 @@ public class PySkeletonRefresher {
return mySkeletonsPath;
}
@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 cachedChecker,
@Nullable Ref<Boolean> migrationFlag) throws InvalidSdkException {
final List<String> errorList = new SmartList<String>();
@@ -190,7 +185,8 @@ public class PySkeletonRefresher {
final String builtinsFileName = PythonSdkType.getBuiltinsFileName(mySdk);
final File builtinsFile = new File(skeletonsPath, builtinsFileName);
final boolean oldOrNonExisting = getSkeletonVersion(builtinsFile) == null;
final SkeletonHeader oldHeader = readSkeletonHeader(builtinsFile);
final boolean oldOrNonExisting = oldHeader == null || oldHeader.getVersion() == 0;
if (migrationFlag != null && !migrationFlag.get() && oldOrNonExisting) {
migrationFlag.set(true);
@@ -246,8 +242,8 @@ public class PySkeletonRefresher {
}
}
final Integer builtinVersion = getSkeletonVersion(builtinsFile);
if (myPregeneratedSkeletons == null && (builtinVersion == null || builtinVersion < myVersionChecker.getBuiltinVersion())) {
final SkeletonHeader newHeader = readSkeletonHeader(builtinsFile);
if (myPregeneratedSkeletons == null && (newHeader == null || newHeader.getVersion() < myVersionChecker.getBuiltinVersion())) {
indicate(PyBundle.message("sdk.gen.updating.builtins.$0", readablePath));
mySkeletonsGenerator.generateBuiltinSkeletons(mySdk);
}
@@ -284,27 +280,64 @@ public class PySkeletonRefresher {
}
@Nullable
private static Matcher getParseHeader(File infile) {
private static SkeletonHeader readSkeletonHeader(@NotNull File file) {
try {
Reader input = new FileReader(infile);
LineNumberReader lines = new LineNumberReader(input);
final LineNumberReader reader = new LineNumberReader(new FileReader(file));
try {
String line = null;
for (int i = 0; i < 3; i += 1) { // read three lines, skip first two
line = lines.readLine();
if (line == null) return null;
// Read 3 lines, skip first 2: encoding, module name
for (int i = 0; i < 3; i++) {
line = reader.readLine();
if (line == null) {
return null;
}
}
// Try the old whitespace-unsafe header format v1 first
final Matcher v1Matcher = VERSION_LINE_V1.matcher(line);
if (v1Matcher.matches()) {
return new SkeletonHeader(v1Matcher.group(1), fromVersionString(v1Matcher.group(2)));
}
final Matcher fromMatcher = FROM_LINE_V2.matcher(line);
if (fromMatcher.matches()) {
final String binaryFile = fromMatcher.group(1);
line = reader.readLine();
if (line != null) {
final Matcher byMatcher = BY_LINE_V2.matcher(line);
if (byMatcher.matches()) {
final int version = fromVersionString(byMatcher.group(1));
return new SkeletonHeader(binaryFile, version);
}
}
}
return OUR_VERSION_LINE.matcher(line);
}
finally {
lines.close();
reader.close();
}
}
catch (IOException ignore) {
catch (IOException e) {
}
return null;
}
static class SkeletonHeader {
@NotNull private final String myFile;
private final int myVersion;
public SkeletonHeader(@NotNull String binaryFile, int version) {
myFile = binaryFile;
myVersion = version;
}
@NotNull
public String getBinaryFile() {
return myFile;
}
public int getVersion() {
return myVersion;
}
}
private Map<String, Pair<Integer, Long>> loadBlacklist() {
Map<String, Pair<Integer, Long>> ret = new HashMap<String, Pair<Integer, Long>>();
File blacklistFile = new File(mySkeletonsPath, BLACKLIST_FILE_NAME);
@@ -420,12 +453,11 @@ public class PySkeletonRefresher {
final String itemName = item.getName();
if (PyNames.INIT_DOT_PY.equals(itemName) && item.length() == 0) continue; // these are versionless
if (BLACKLIST_FILE_NAME.equals(itemName)) continue; // don't touch the blacklist
Matcher headerMatcher = getParseHeader(item);
boolean canLive = headerMatcher != null && headerMatcher.matches();
final SkeletonHeader header = readSkeletonHeader(item);
boolean canLive = header != null;
if (canLive) {
String sourceName = headerMatcher.group(1);
canLive =
sourceName != null && (SkeletonVersionChecker.BUILTIN_NAME.equals(sourceName) || mySkeletonsGenerator.exists(sourceName));
final String binaryFile = header.getBinaryFile();
canLive = SkeletonVersionChecker.BUILTIN_NAME.equals(binaryFile) || mySkeletonsGenerator.exists(binaryFile);
}
if (!canLive) {
mySkeletonsGenerator.deleteOrLog(item);
@@ -524,13 +556,11 @@ public class PySkeletonRefresher {
final String moduleName = binaryItem.getModule();
final File skeleton = getSkeleton(moduleName, getSkeletonsPath());
Matcher matcher = getParseHeader(skeleton);
final SkeletonHeader header = readSkeletonHeader(skeleton);
boolean mustRebuild = true; // guilty unless proven fresh enough
if (matcher != null && matcher.matches()) {
int fileVersion = fromVersionString(matcher.group(2));
if (header != null) {
int requiredVersion = myVersionChecker.getRequiredVersion(moduleName);
mustRebuild = fileVersion < requiredVersion;
mustRebuild = header.getVersion() < requiredVersion;
}
if (!mustRebuild) { // ...but what if the lib was updated?
mustRebuild = (skeleton.exists() && binaryItem.lastModified() > skeleton.lastModified());