Skip to content

Commit ba44933

Browse files
committed
Re-enabled APIVersion checking in imp.java. Used ASM to read and write APIVersion
as an annotation. Incremented APIVersion from 12 to 13.
1 parent f94d445 commit ba44933

5 files changed

Lines changed: 74 additions & 43 deletions

File tree

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
1-
// Copyright (c) Corporation for National Research Initiatives
2-
1+
/*
2+
* Copyright (c) 2008 Jython Developers
3+
* Licensed to PSF under a Contributor Agreement.
4+
*/
35
package org.python.compiler;
4-
import java.io.DataOutputStream;
5-
import java.io.IOException;
6-
7-
public class APIVersion {
8-
int attName;
9-
int version;
106

11-
public APIVersion(int version) throws IOException {
12-
//FJW attName = pool.UTF8("org.python.APIVersion");
13-
//FJW this.version = version;
14-
}
7+
import java.lang.annotation.Retention;
8+
import java.lang.annotation.RetentionPolicy;
159

16-
public void write(DataOutputStream stream) throws IOException {
17-
//FJW stream.writeShort(attName);
18-
//FJW stream.writeInt(4);
19-
//FJW stream.writeInt(version);
20-
}
10+
@Retention(RetentionPolicy.RUNTIME)
11+
public @interface APIVersion {
12+
int value();
2113
}

src/org/python/compiler/ClassFile.java

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.Collections;
1111
import java.util.List;
1212

13+
import org.python.objectweb.asm.AnnotationVisitor;
1314
import org.python.objectweb.asm.Attribute;
1415
import org.python.objectweb.asm.ClassWriter;
1516
import org.python.objectweb.asm.FieldVisitor;
@@ -26,7 +27,6 @@ public class ClassFile
2627
String[] interfaces;
2728
List<MethodVisitor> methodVisitors;
2829
List<FieldVisitor> fieldVisitors;
29-
List<Attribute> attributes;
3030

3131
public static String fixName(String n) {
3232
if (n.indexOf('.') == -1)
@@ -53,7 +53,6 @@ public ClassFile(String name, String superclass, int access) {
5353

5454
methodVisitors = Collections.synchronizedList(new ArrayList());
5555
fieldVisitors = Collections.synchronizedList(new ArrayList());
56-
attributes = Collections.synchronizedList(new ArrayList());
5756
}
5857

5958
public void setSource(String name) {
@@ -67,7 +66,6 @@ public void addInterface(String name) throws IOException {
6766
interfaces = new_interfaces;
6867
}
6968

70-
//FIXME: Should really return a MethodVisitor
7169
public Code addMethod(String name, String type, int access)
7270
throws IOException
7371
{
@@ -84,14 +82,6 @@ public void addField(String name, String type, int access)
8482
fieldVisitors.add(fv);
8583
}
8684

87-
public void endAttributes()
88-
throws IOException
89-
{
90-
for (Attribute attr : attributes) {
91-
cw.visitAttribute(attr);
92-
}
93-
}
94-
9585
public void endFields()
9686
throws IOException
9787
{
@@ -110,17 +100,16 @@ public void endMethods()
110100
}
111101
}
112102

113-
public void addAttribute(Attribute attr) throws IOException {
114-
//FIXME: Do nothing for now.
115-
//attributes.add(attr);
116-
}
117-
118103
public void write(OutputStream stream) throws IOException {
119104
cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, this.name, null, this.superclass, interfaces);
105+
AnnotationVisitor av = cw.visitAnnotation("Lorg/python/compiler/APIVersion;", true);
106+
//XXX: should imp.java really house this value or should imp.java point into org.python.compiler?
107+
av.visit("value", new Integer(org.python.core.imp.APIVersion));
108+
av.visitEnd();
109+
120110
if (sfilename != null) {
121111
cw.visitSource(sfilename, null);
122112
}
123-
endAttributes();
124113
endFields();
125114
endMethods();
126115

src/org/python/compiler/Module.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -574,8 +574,6 @@ public void write(OutputStream stream) throws IOException {
574574
if (sfilename != null) {
575575
classfile.setSource(sfilename);
576576
}
577-
//FIXME: switch to asm style.
578-
//classfile.addAttribute(new APIVersion(org.python.core.imp.APIVersion));
579577
classfile.write(stream);
580578
}
581579

src/org/python/core/APIReader.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2008 Jython Developers
3+
* Licensed to PSF under a Contributor Agreement.
4+
*/
5+
package org.python.core;
6+
7+
import org.python.objectweb.asm.AnnotationVisitor;
8+
import org.python.objectweb.asm.ClassReader;
9+
import org.python.objectweb.asm.commons.EmptyVisitor;
10+
11+
import java.io.InputStream;
12+
import java.io.IOException;
13+
14+
/**
15+
* This class reads a classfile from a byte array and pulls out the value of
16+
* the class annotation for APIVersion, which can then be retrieved by a call
17+
* to getVersion().
18+
*
19+
* Hopefully the use of ClassReader in this implementation is not too
20+
* expensive. I suspect it is not since EmptyVisitor is just a bag of empty
21+
* methods so shouldn't cost too much. If it turns out to cost too much, we
22+
* will want to implement a special purpose ClassReader that only reads out the
23+
* APIVersion annotation I think.
24+
*/
25+
public class APIReader extends EmptyVisitor {
26+
27+
private boolean nextVisitIsVersion = false;
28+
29+
private int version = -1;
30+
31+
public APIReader(byte[] data) throws IOException {
32+
ClassReader r = new ClassReader(data);
33+
r.accept(this, 0);
34+
}
35+
36+
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
37+
nextVisitIsVersion = desc.equals("Lorg/python/compiler/APIVersion;");
38+
return this;
39+
}
40+
41+
public void visit(String name, Object value) {
42+
if (nextVisitIsVersion) {
43+
version = (Integer)value;
44+
nextVisitIsVersion = false;
45+
}
46+
}
47+
48+
public int getVersion() {
49+
return version;
50+
}
51+
}

src/org/python/core/imp.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class imp {
2222

2323
private static final String UNKNOWN_SOURCEFILE = "<unknown>";
2424

25-
public static final int APIVersion = 12;
25+
public static final int APIVersion = 13;
2626

2727
/** A non-empty fromlist for __import__'ing sub-modules. */
2828
private static final PyObject nonEmptyFromlist = new PyTuple(Py.newString("__doc__"));
@@ -113,11 +113,13 @@ public static byte[] unmarshalCode(String name, InputStream fp,
113113
byte[] data = readBytes(fp);
114114
int n = data.length;
115115

116-
//Need to find another way to check the api version -- probably using
117-
//an Annotation instead of an Attribute makes sense.
118-
/*
119-
int api = (data[n - 4] << 24) + (data[n - 3] << 16)
120-
+ (data[n - 2] << 8) + data[n - 1];
116+
int api;
117+
try {
118+
APIReader ar = new APIReader(data);
119+
api = ar.getVersion();
120+
} catch (IOException i) {
121+
api = -1;
122+
}
121123
if (api != APIVersion) {
122124
if (testing) {
123125
return null;
@@ -126,7 +128,6 @@ public static byte[] unmarshalCode(String name, InputStream fp,
126128
+ APIVersion + ") in: " + name);
127129
}
128130
}
129-
*/
130131
return data;
131132
}
132133

0 commit comments

Comments
 (0)