Skip to content

Commit aede03c

Browse files
Merge pull request RustPython#762 from palaviv/doc
Support class and function __doc__
2 parents 69c8173 + 4e99350 commit aede03c

File tree

3 files changed

+110
-4
lines changed

3 files changed

+110
-4
lines changed

tests/snippets/class.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ def kungfu(x):
3737
assert x == 3
3838

3939

40-
# TODO:
41-
# assert Bar.__doc__ == " W00t "
40+
assert Bar.__doc__ == " W00t "
4241

4342
bar = Bar(42)
4443

@@ -117,3 +116,31 @@ def f(self):
117116
assert type(a) is super
118117
assert a.conjugate() == 1
119118

119+
120+
class T1:
121+
"test1"
122+
123+
assert T1.__doc__ == "test1"
124+
125+
class T2:
126+
'''test2'''
127+
128+
assert T2.__doc__ == "test2"
129+
130+
class T3:
131+
"""
132+
test3
133+
"""
134+
135+
assert T3.__doc__ == "\n test3\n "
136+
137+
class T4:
138+
139+
"""test4"""
140+
141+
def t1(self):
142+
"""t1"""
143+
pass
144+
145+
assert T4.__doc__ == "test4"
146+
assert T4.t1.__doc__ == "t1"

tests/snippets/function.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,39 @@
11
def foo():
2+
"""test"""
23
return 42
34

45
assert foo() == 42
6+
assert foo.__doc__ == "test"
57

68
def my_func(a,):
79
return a+2
810

911
assert my_func(2) == 4
12+
13+
14+
def f1():
15+
16+
"""test1"""
17+
pass
18+
19+
assert f1.__doc__ == "test1"
20+
21+
def f2():
22+
'''test2'''
23+
pass
24+
25+
assert f2.__doc__ == "test2"
26+
27+
def f3():
28+
"""
29+
test3
30+
"""
31+
pass
32+
33+
assert f3.__doc__ == "\n test3\n "
34+
35+
def f4():
36+
"test4"
37+
pass
38+
39+
assert f4.__doc__ == "test4"

vm/src/compile.rs

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,10 @@ impl Compiler {
597597
self.in_loop = false;
598598
self.in_function_def = true;
599599
let mut flags = self.enter_function(name, args)?;
600-
self.compile_statements(body)?;
600+
601+
let (new_body, doc_str) = get_doc(body);
602+
603+
self.compile_statements(new_body)?;
601604

602605
// Emit None at end:
603606
self.emit(Instruction::LoadConst {
@@ -662,6 +665,20 @@ impl Compiler {
662665
self.emit(Instruction::StoreName {
663666
name: name.to_string(),
664667
});
668+
669+
if let Some(doc_string) = doc_str {
670+
self.emit(Instruction::LoadConst {
671+
value: bytecode::Constant::String {
672+
value: doc_string.to_string(),
673+
},
674+
});
675+
self.emit(Instruction::LoadName {
676+
name: name.to_string(),
677+
});
678+
self.emit(Instruction::StoreAttr {
679+
name: "__doc__".to_string(),
680+
});
681+
}
665682
self.in_loop = was_in_loop;
666683
self.in_function_def = was_in_function_def;
667684
Ok(())
@@ -689,13 +706,17 @@ impl Compiler {
689706
line_number,
690707
name.to_string(),
691708
));
692-
self.compile_statements(body)?;
709+
710+
let (new_body, doc_str) = get_doc(body);
711+
712+
self.compile_statements(new_body)?;
693713
self.emit(Instruction::LoadConst {
694714
value: bytecode::Constant::None,
695715
});
696716
self.emit(Instruction::ReturnValue);
697717

698718
let code = self.pop_code_object();
719+
699720
self.emit(Instruction::LoadConst {
700721
value: bytecode::Constant::Code {
701722
code: Box::new(code),
@@ -755,6 +776,19 @@ impl Compiler {
755776
self.emit(Instruction::StoreName {
756777
name: name.to_string(),
757778
});
779+
if let Some(doc_string) = doc_str {
780+
self.emit(Instruction::LoadConst {
781+
value: bytecode::Constant::String {
782+
value: doc_string.to_string(),
783+
},
784+
});
785+
self.emit(Instruction::LoadName {
786+
name: name.to_string(),
787+
});
788+
self.emit(Instruction::StoreAttr {
789+
name: "__doc__".to_string(),
790+
});
791+
}
758792
self.in_loop = was_in_loop;
759793
Ok(())
760794
}
@@ -1511,6 +1545,21 @@ impl Compiler {
15111545
}
15121546
}
15131547

1548+
fn get_doc(body: &[ast::LocatedStatement]) -> (&[ast::LocatedStatement], Option<String>) {
1549+
if let Some(val) = body.get(0) {
1550+
if let ast::Statement::Expression { ref expression } = val.node {
1551+
if let ast::Expression::String { ref value } = expression {
1552+
if let ast::StringGroup::Constant { ref value } = value {
1553+
if let Some((_, body_rest)) = body.split_first() {
1554+
return (body_rest, Some(value.to_string()));
1555+
}
1556+
}
1557+
}
1558+
}
1559+
}
1560+
(body, None)
1561+
}
1562+
15141563
#[cfg(test)]
15151564
mod tests {
15161565
use super::Compiler;

0 commit comments

Comments
 (0)