def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
python类get_docstring()的实例源码
def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
def coerce_file(fn):
"""Coerce file content to something useful for setuptools.setup(), turn :
.py into mock object by extracting __special__ attributes values
.md into rst text. Remove images with "[nopypi" alt text and emojis
:url: https://github.com/Kraymer/setupgoon
"""
import ast
import os
import re
import subprocess
import tempfile
import time # noqa
text = open(os.path.join(os.path.dirname(__file__), fn)).read()
if fn.endswith('.py'): # extract version, docstring etc out of python file
mock = type('mock', (object,), {})()
for attr in ('version', 'author', 'author_email', 'license', 'url'):
regex = r'^__%s__\s*=\s*[\'"]([^\'"]*)[\'"]$' % attr
m = re.search(regex, text, re.MULTILINE)
setattr(mock, attr, m.group(1) if m else None)
mock.docstring = ast.get_docstring(ast.parse(text))
if mock.version.endswith('dev'):
mock.version += str(int(time.time()))
return mock
if 'upload' in sys.argv and fn.endswith('md'): # convert markdown to rest
text = '\n'.join([l for l in text.split('\n') if '[nopypi' not in l])
text = re.sub(r':\S+:', '', text) # no emojis
with tempfile.NamedTemporaryFile(mode='w+') as tmp:
tmp.write(text)
tmp.flush()
text, stderr = subprocess.Popen(['pandoc', '-t', 'rst', tmp.name],
stdout=subprocess.PIPE).communicate()
return text.decode('utf-8')
def _add_file_docs(self, tree):
"""Extracts the file docstring of the .bzl file."""
docstring = ast.get_docstring(tree)
if docstring == None:
return
lines = docstring.split("\n")
i = 0
for line in lines:
if line != '':
i = i + 1
else:
break
self.title = " ".join(lines[:i])
self.description = "\n".join(lines[i + 1:])
def _add_macro_doc(self, stmt):
# The defaults array contains default values for the last arguments.
# The first shift arguments are mandatory.
shift = len(stmt.args.args) - len(stmt.args.defaults)
rule = self.__language.rule.add()
rule.name = stmt.name
rule.type = build_pb2.RuleDefinition.MACRO
doc = ast.get_docstring(stmt)
if doc:
extracted_docs = common.parse_docstring(doc)
rule.documentation = extracted_docs.doc
if extracted_docs.example_doc:
rule.example_documentation = extracted_docs.example_doc
else:
extracted_docs = common.ExtractedDocs(
doc="", attr_docs={}, example_doc="", output_docs={})
for i in range(len(stmt.args.args)):
attr = rule.attribute.add()
attr_name = stmt.args.args[i].id
attr.name = attr_name
if attr_name in extracted_docs.attr_docs:
attr.documentation = extracted_docs.attr_docs[attr_name]
if i < shift: # The first arguments are mandatory
attr.mandatory = True
attr.type = build_pb2.Attribute.UNKNOWN
else:
node = stmt.args.defaults[i - shift]
attr.mandatory = False
attr.type = get_type(node)
if attr.type == build_pb2.Attribute.BOOLEAN:
attr.default = node.id
for template, doc in extracted_docs.output_docs.iteritems():
output = rule.output.add()
output.template = template
output.documentation = doc
def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
def visit_Module(self, node):
if sys.version_info >= (3, 7):
docstring = ast.get_docstring(node, clean=False)
for t in self.check_str(docstring):
yield t
for t in self.generic_visit(node):
yield t
def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
def _get_docstring(self, node):
return ast.get_docstring(node)
def cmp(self, node, pattern):
docstring = ast.get_docstring(node)
if docstring is None:
return False
LOG.debug("Comparing %r and %r", docstring, pattern.pattern)
return pattern(docstring)
def get_doc(self, module):
for node in module.body:
if isinstance(node, ast.ClassDef):
yield ast.get_docstring(node)
for sub_node in node.body:
if isinstance(sub_node, ast.FunctionDef):
yield ast.get_docstring(sub_node)
def test_get_docstring(self):
node = ast.parse('def foo():\n """line one\n line two"""')
self.assertEqual(ast.get_docstring(node.body[0]),
'line one\nline two')
def rst_sections_in_module(tree, module_name, exports):
docstring = ast.get_docstring(tree)
if docstring:
yield docstring
for toplevel in tree.body:
try:
if toplevel.name not in exports:
continue
except AttributeError:
continue
print(
'Documenting {}.{}'.format(module_name, toplevel.name),
file=sys.stderr)
class_doc = ast.get_docstring(toplevel)
if class_doc:
yield toplevel.name + '\n' + '-' * len(toplevel.name)
yield class_doc
if type(toplevel) == ast.ClassDef:
for fun in toplevel.body:
if type(fun) != ast.FunctionDef:
continue
fun_doc = ast.get_docstring(fun)
if fun_doc:
fun_sig = signature(module_name, toplevel.name, fun)
yield fun.name + '\n' + '+' * len(fun.name)
yield 'Signature:\n ' + fun_sig
yield fun_doc
else:
if not fun.name.startswith('_'):
print('Missing docstring for ' + fun.name, file=sys.stderr)
def get_docstring(self, node):
return self.parser.parse(ast.get_docstring(node))
def visit_FunctionDef(self, node):
return {
'type': 'function',
'docstring': self.get_docstring(node),
'decorators': [],
'name': node.name,
'args': self.visit(node.args)
}
def func_check(node, kw=False):
'''
Function specific check
Action - check return type
Action - check pstep/psubstep buddy with report_step/report_substep_status
check docstring
check print statement - should use print_utils
scan for class - class check
scan for function - recursive function check
'''
status = True
have_return = False
substep_count = 0
# investigate everything in a function
for child in ast.walk(node):
if child != node and isinstance(child, ast.FunctionDef):
# check for private method in action file
if kw and child.name.startswith("_"):
print node.name, child.name, "should move to utils"
status = False
tmp_status = func_check(child, kw)
status &= tmp_status
elif child != node and isinstance(child, ast.ClassDef):
tmp_status = class_check(child, kw)
status &= tmp_status
elif 'war_print_class.py' not in sys.argv[1] and isinstance(child, ast.Print):
# check for print statement
status = False
print "Please use print_Utils instead of print in {}: {}".format(
sys.argv[1], child.lineno)
elif isinstance(child, ast.Return):
# check for return statement
have_return = True
elif isinstance(child, ast.Attribute) and child.attr == 'pSubStep':
# check for Substep and report substep pair
substep_count += 1
elif isinstance(child, ast.Attribute) and child.attr == 'report_substep_status':
substep_count -= 1
if ast.get_docstring(node) is None:
print node.name, "doesn't contain any docstring"
status = False
if kw and not have_return and node.name != "__init__":
print node.name, "doesn't contain a return statement"
status = False
if kw and substep_count:
print node.name, "have non-pair pSubStepreport_substep_status"
status = False
return status
def extract_info(self, module):
"""
.. py:attribute:: extract_info()
This function loop over parser object and extracts the informations
(contains name, documentation, line number etc.) for function, class
and attribute objects.
:rtype: dict
.. note::
"""
def extracter(root_nod):
for node in root_nod.body:
if isinstance(node, ast.ClassDef):
yield {
"name": node.name,
"lineno": node.lineno - 1,
"docstring": ast.get_docstring(node),
"type": 'class'}
for sub_node in node.body:
args_ = []
if isinstance(sub_node, ast.FunctionDef):
for arg in sub_node.args.args:
try:
args_.append(arg.id)
except AttributeError:
args_.extend([item.id for item in arg.elts if item.id != 'self'])
yield {
"name": sub_node.name,
"lineno": sub_node.lineno - 1,
"docstring": ast.get_docstring(sub_node),
"type": 'attribute',
"args": args_,
"header": ''}
for n in extracter(sub_node):
yield n
elif isinstance(node, ast.FunctionDef):
args_ = []
for arg in node.args.args:
try:
args_.append(arg.id)
except AttributeError:
args_.extend([item.id for item in arg])
yield {
"name": node.name,
"lineno": node.lineno - 1,
"docstring": ast.get_docstring(node),
"type": 'function',
"args": args_}
for n in extracter(node):
yield n
return extracter(module)