ComGen/py_comment.py
2024-09-04 19:27:55 +02:00

279 lines
8.6 KiB
Python

import re
# Option default value
STYLE_DOCSTRING = 'reStructuredText'
def getOptions():
""" Get options from the options.txt file
Returns
-------
None
"""
global STYLE_DOCSTRING
try:
with open('options.ini', 'r') as file:
file_content = file.read()
style_docstring_match = re.search(r'(?<=style_docstring = )\w+', file_content)
except FileNotFoundError:
style_docstring_match = None
if style_docstring_match:
STYLE_DOCSTRING = style_docstring_match.group()
def getFunctions(filename: str) -> list:
""" Get the name, arguments and return type of all functions in a file
Parameters
----------
filename : str
Name of the file to get the functions from
Returns
-------
list
List of functions name, arguments and return type
"""
with open(filename, 'r') as file:
content = file.read()
pattern_function = re.compile(r'(?:async\s+)?def\s+(\w+)\s*\(([^)]*)\)\s*(?:->\s*([^:\n]+))?\s*:', re.MULTILINE)
functions = re.findall(pattern_function, content)
return functions
def parseArgument(arg: str) -> str:
""" Parse the argument name and type
Parameters
----------
arg : str
Argument to parse
Returns
-------
str
Argument name and type
"""
arg = arg.split('=')[0]
try:
arg_name, arg_type = arg.split(':')
arg_type = arg_type.strip()
except ValueError:
arg_name = arg
arg_type = ''
return arg_name, arg_type
def writeFunctionCommentLines_google(content: list, index: int, function: list, indent: str) -> list:
""" Write the function comment lines in Google style
Parameters
----------
content : list
Content of the file
index : int
Line index where the function is located
function : list
Function name, arguments and return type
indent : str
Indentation of the comment block
Returns
-------
list
Content of the file with the comment block added
"""
docstring_lines = [f'{indent}""" Description\n\n']
args = [arg.strip() for arg in function[1].split(',') if arg.strip()]
if args:
docstring_lines.append(f'{indent}Args:\n')
for arg in args:
arg_name, arg_type = parseArgument(arg)
docstring_lines.append(f'{indent} {arg_name} {"(" + arg_type + ")" if arg_type else ""}:\n')
docstring_lines.append(f'{indent}\n')
docstring_lines.append(f'{indent}Returns:\n')
docstring_lines.append(f'{indent} {function[2] + ":" if function[2] else ""}\n')
docstring_lines.append(f'{indent}"""\n')
content[index:index] = docstring_lines
return content
def writeFunctionCommentLines_reStructuredText(content: list, index: int, function: list, indent: str) -> list:
""" Write the function comment lines in reStructuredText style
Parameters
----------
content : list
Content of the file
index : int
Line index where the function is located
function : list
Function name, arguments and return type
indent : str
Indentation of the comment block
Returns
-------
list
Content of the file with the comment block added
"""
docstring_lines = [f'{indent}""" Description\n\n']
args = [arg.strip() for arg in function[1].split(',') if arg.strip()]
for arg in args:
arg_name, arg_type = parseArgument(arg)
if arg_name:
docstring_lines.append(f'{indent}:param {arg_name}:\n')
docstring_lines.append(f'{indent}:type {arg_name}: {arg_type}\n')
docstring_lines.append(f'{indent}:return:\n')
docstring_lines.append(f'{indent}:rtype: {function[2] if function[2] else ""}\n')
docstring_lines.append(f'{indent}"""\n')
content[index:index] = docstring_lines
return content
def writeFunctionCommentLines_numpy(content: list, index: int, function: list, indent: str) -> list:
""" Write the function comment lines in Numpy style
Parameters
----------
content : list
Content of the file
index : int
Line index where the function is located
function : list
Function name, arguments and return type
indent : str
Indentation of the comment block
Returns
-------
list
Content of the file with the comment block added
"""
docstring_lines = [f'{indent}""" Description\n\n']
args = [arg.strip() for arg in function[1].split(',') if arg.strip()]
if args:
docstring_lines.append(f'{indent}Parameters\n')
docstring_lines.append(f'{indent}----------\n')
for arg in args:
arg_name, arg_type = parseArgument(arg)
docstring_lines.append(f'{indent}{arg_name} : {arg_type}\n\n')
docstring_lines.append(f'\n')
docstring_lines.append(f'{indent}Returns\n')
docstring_lines.append(f'{indent}-------\n')
docstring_lines.append(f'{indent}{function[2] if function[2] else ""}\n\n')
docstring_lines.append(f'{indent}"""\n')
content[index:index] = docstring_lines
return content
def writeFunctionCommentLines_epytext(content: list, index: int, function: list, indent: str) -> list:
""" Write the function comment lines in Epytext style
Parameters
----------
content : list
Content of the file
index : int
Line index where the function is located
function : list
Function name, arguments and return type
indent : str
Indentation of the comment block
Returns
-------
list
Content of the file with the comment block added
"""
docstring_lines = [f'{indent}""" Description\n\n']
args = [arg.strip() for arg in function[1].split(',') if arg.strip()]
for arg in args:
arg_name, arg_type = parseArgument(arg)
if arg_name:
docstring_lines.append(f'{indent}@param {arg_name}: {arg_type}\n')
docstring_lines.append(f'{indent}@type {arg_name}: {arg_type}\n')
docstring_lines.append(f'{indent}@return:\n')
docstring_lines.append(f'{indent}@rtype: {function[2] if function[2] else ""}\n')
docstring_lines.append(f'{indent}"""\n')
content[index:index] = docstring_lines
return content
def writeFunctionCommentLines(content: list, index: int, function: list, indentation: int) -> list:
""" Write the function comment lines in the selected style
Parameters
----------
content : list
Content of the file
index : int
Line index where the function is located
function : list
Function name, arguments and return type
indentation : int
Indentation of the comment block
Returns
-------
list
Content of the file with the comment block added, or the same content if the function already has a comment block
"""
if content[index].strip().startswith('"""'):
return content
indent = ' ' * indentation if indentation != 0 else ' '
if STYLE_DOCSTRING == 'Google':
content = writeFunctionCommentLines_google(content, index, function, indent)
return content
if STYLE_DOCSTRING == 'reStructuredText':
content = writeFunctionCommentLines_reStructuredText(content, index, function, indent)
return content
if STYLE_DOCSTRING == 'Numpy':
content = writeFunctionCommentLines_numpy(content, index, function, indent)
return content
if STYLE_DOCSTRING == 'Epytext':
content = writeFunctionCommentLines_epytext(content, index, function, indent)
return content
def writeFunctionComment(filename: str, function: list):
""" Write the comment block for a function
Parameters
----------
filename : str
Name of the file to write the comment block
function : str
Function name, arguments and return type
Returns
-------
None
"""
with open(filename, 'r') as file:
content = file.readlines()
for i, line in enumerate(content):
if line.strip().startswith((f'def {function[0]}', f'async def {function[0]}')):
indentation = len(line) - len(line.lstrip())
content = writeFunctionCommentLines(content, i + 1, function, indentation)
break
with open(filename, 'w') as file:
file.writelines(content)
def generateAllComments(filename: str):
""" Write the comment block for all functions in a file
Parameters
----------
filename : str
Name of the file to write the comment blocks
Returns
-------
None
"""
getOptions()
functions = getFunctions(filename)
for function in functions:
writeFunctionComment(filename, function)