Skip to content

Commit 8e5cb92

Browse files
committed
add support for reading and setting the module docstring
- relevant unittest
1 parent c31bc60 commit 8e5cb92

File tree

6 files changed

+48
-6
lines changed

6 files changed

+48
-6
lines changed

graalpython/com.oracle.graal.python.test/src/tests/package/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,7 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40+
"""PACKAGE DOC"""
41+
4042
from . import moduleY
4143
print("after importing moduleY")

graalpython/com.oracle.graal.python.test/src/tests/package/moduleA.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,6 @@
3737
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3838
# SOFTWARE.
3939

40+
"""MODULE A DOC"""
41+
4042
print("module A")

graalpython/com.oracle.graal.python.test/src/tests/test_imports.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ def test_relative_import():
5151
raise e
5252

5353

54+
def test_module_docstring():
55+
import package
56+
assert package.__doc__ == "PACKAGE DOC"
57+
from package import moduleA
58+
assert moduleA.__doc__ == "MODULE A DOC"
59+
60+
5461
def test_dotted_import():
5562
# this is to prevent ides from optimising out the unused import
5663
try:

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ModuleRootNode.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,27 +27,45 @@
2727

2828
import com.oracle.graal.python.PythonLanguage;
2929
import com.oracle.graal.python.nodes.expression.ExpressionNode;
30+
import com.oracle.graal.python.nodes.frame.WriteGlobalNode;
3031
import com.oracle.truffle.api.CompilerAsserts;
32+
import com.oracle.truffle.api.CompilerDirectives;
3133
import com.oracle.truffle.api.frame.FrameDescriptor;
3234
import com.oracle.truffle.api.frame.FrameSlot;
3335
import com.oracle.truffle.api.frame.VirtualFrame;
3436
import com.oracle.truffle.api.source.SourceSection;
3537

38+
import static com.oracle.graal.python.nodes.SpecialAttributeNames.__DOC__;
39+
3640
public class ModuleRootNode extends PClosureRootNode {
3741

3842
private final String name;
43+
private final String doc;
3944

4045
@Child private ExpressionNode body;
46+
@Child private WriteGlobalNode writeModuleDoc;
4147

42-
public ModuleRootNode(PythonLanguage language, String name, ExpressionNode file, FrameDescriptor descriptor, FrameSlot[] freeVarSlots) {
48+
public ModuleRootNode(PythonLanguage language, String name, String doc, ExpressionNode file, FrameDescriptor descriptor, FrameSlot[] freeVarSlots) {
4349
super(language, descriptor, freeVarSlots);
4450
this.name = "<module '" + name + "'>";
51+
this.doc = doc;
4552
this.body = file;
4653
}
4754

55+
private WriteGlobalNode getWriteModuleDoc() {
56+
if (writeModuleDoc == null) {
57+
CompilerDirectives.transferToInterpreterAndInvalidate();
58+
writeModuleDoc = insert(WriteGlobalNode.create(__DOC__));
59+
}
60+
return writeModuleDoc;
61+
}
62+
4863
@Override
4964
public Object execute(VirtualFrame frame) {
5065
addClosureCellsToLocals(frame);
66+
if (doc != null) {
67+
getWriteModuleDoc().doWrite(frame, doc);
68+
}
5169
return body.execute(frame);
5270
}
5371

@@ -66,6 +84,10 @@ public String getName() {
6684
return name;
6785
}
6886

87+
public String getDoc() {
88+
return doc;
89+
}
90+
6991
@Override
7092
public SourceSection getSourceSection() {
7193
return body.getSourceSection();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/NodeFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,9 @@ public <T> T duplicate(Node orig, Class<T> clazz) {
132132
return (T) NodeUtil.cloneNode(orig);
133133
}
134134

135-
public ModuleRootNode createModuleRoot(String name, ExpressionNode file, FrameDescriptor fd) {
135+
public ModuleRootNode createModuleRoot(String name, String doc, ExpressionNode file, FrameDescriptor fd) {
136136
file.markAsRoot();
137-
return new ModuleRootNode(language, name, file, fd, null);
137+
return new ModuleRootNode(language, name, doc, file, fd, null);
138138
}
139139

140140
public FunctionRootNode createFunctionRoot(SourceSection sourceSection, String functionName, boolean isGenerator, FrameDescriptor frameDescriptor, ExpressionNode body,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/PythonTreeTranslator.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ public final class PythonTreeTranslator extends Python3BaseVisitor<Object> {
113113
protected final AssignmentTranslator assigns;
114114
protected final Source source;
115115
protected final String name;
116+
protected String moduleDoc;
117+
protected boolean firstStatement = true;
116118

117119
protected final boolean isInlineMode;
118120

@@ -232,7 +234,7 @@ public Object visitFile_input(Python3Parser.File_inputContext ctx) {
232234
ExpressionNode file = asExpression(super.visitFile_input(ctx));
233235
deriveSourceSection(ctx, file);
234236
environment.popScope();
235-
return factory.createModuleRoot(name, file, ctx.scope.getFrameDescriptor());
237+
return factory.createModuleRoot(name, moduleDoc, file, ctx.scope.getFrameDescriptor());
236238
}
237239

238240
@Override
@@ -256,7 +258,7 @@ public Object visitSingle_input(Python3Parser.Single_inputContext ctx) {
256258
if (isInlineMode) {
257259
return body;
258260
} else {
259-
return factory.createModuleRoot("<expression>", body, ctx.scope.getFrameDescriptor());
261+
return factory.createModuleRoot("<expression>", moduleDoc, body, ctx.scope.getFrameDescriptor());
260262
}
261263
}
262264

@@ -1284,7 +1286,14 @@ private LoopNode createForInScope(StatementNode target, ExpressionNode iterator,
12841286
@Override
12851287
public Object visitExpr_stmt(Python3Parser.Expr_stmtContext ctx) {
12861288
if (ctx.normassign().isEmpty() && ctx.annassign() == null && ctx.augassign() == null) {
1287-
return super.visitExpr_stmt(ctx);
1289+
Object exprNode = super.visitExpr_stmt(ctx);
1290+
if (firstStatement) {
1291+
firstStatement = false;
1292+
if (exprNode instanceof StringLiteralNode) {
1293+
moduleDoc = ((StringLiteralNode) exprNode).getValue();
1294+
}
1295+
}
1296+
return exprNode;
12881297
} else {
12891298
return assigns.translate(ctx);
12901299
}

0 commit comments

Comments
 (0)