2022-11-14 13:21:30 +09:00
|
|
|
#!/usr/bin/env python3
|
2022-10-16 23:30:04 +09:00
|
|
|
import os
|
|
|
|
import ast
|
|
|
|
|
|
|
|
SOURCE_FOLDER = 'yandex_music'
|
2022-10-16 23:40:08 +09:00
|
|
|
EXCLUDED_FUNCTIONS = {'de_dict', 'de_json', 'de_list', 'de_json_async', 'de_list_async'}
|
2022-10-16 23:30:04 +09:00
|
|
|
|
|
|
|
ALIAS_TEMPLATE = '''
|
|
|
|
#: Псевдоним для :attr:`{name}`
|
|
|
|
{camel_case_name} = {name}
|
|
|
|
'''
|
|
|
|
|
|
|
|
ALIAS_SECTION_MARKER = ' # camelCase псевдонимы'
|
|
|
|
|
|
|
|
|
|
|
|
def _validate_function_name(function_name: str) -> bool:
|
|
|
|
if function_name.startswith('_'):
|
|
|
|
return False
|
|
|
|
|
|
|
|
if function_name in EXCLUDED_FUNCTIONS:
|
|
|
|
return False
|
|
|
|
|
|
|
|
# camel case will be the same
|
|
|
|
if '_' not in function_name:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def convert_snake_case_to_camel_case(string: str) -> str:
|
|
|
|
camel_case = ''.join(word.title() for word in string.split('_'))
|
|
|
|
return camel_case[0].lower() + camel_case[1:]
|
|
|
|
|
|
|
|
|
|
|
|
def _generate_code(function_name: str, intent=0) -> str:
|
|
|
|
camel_case_name = convert_snake_case_to_camel_case(function_name)
|
|
|
|
code = ALIAS_TEMPLATE.format(name=function_name, camel_case_name=camel_case_name)
|
|
|
|
|
|
|
|
code_lines = [line for line in code.split('\n') if line]
|
|
|
|
code_lines = [f'{" " * intent}{line}' for line in code_lines]
|
|
|
|
code = '\n'.join(code_lines)
|
|
|
|
|
|
|
|
return code
|
|
|
|
|
|
|
|
|
|
|
|
def _process_file(file: str) -> None:
|
|
|
|
with open(file, 'r', encoding='UTF-8') as f:
|
|
|
|
count_of_class_def = 0
|
|
|
|
file_aliases_code_fragments = []
|
|
|
|
tree = ast.parse(f.read())
|
|
|
|
for node in ast.walk(tree):
|
|
|
|
if isinstance(node, ast.ClassDef):
|
|
|
|
count_of_class_def += 1
|
|
|
|
|
|
|
|
if isinstance(node, ast.FunctionDef) or isinstance(node, ast.AsyncFunctionDef):
|
|
|
|
if _validate_function_name(node.name):
|
|
|
|
alias_code = _generate_code(node.name, node.col_offset)
|
|
|
|
file_aliases_code_fragments.append(alias_code)
|
|
|
|
|
|
|
|
# there are no such cases in data models yet
|
|
|
|
# only in yandex_music/exceptions.py and yandex_music/utils/difference.py
|
|
|
|
if count_of_class_def != 1:
|
|
|
|
return
|
|
|
|
|
|
|
|
f.seek(0)
|
|
|
|
file_code_lines = f.read().splitlines()
|
|
|
|
|
|
|
|
marker_lineno = None
|
|
|
|
for lineno, code_line in enumerate(file_code_lines):
|
|
|
|
if code_line == ALIAS_SECTION_MARKER:
|
|
|
|
marker_lineno = lineno
|
|
|
|
break
|
|
|
|
|
|
|
|
# we can't process files without markers now
|
|
|
|
if marker_lineno is None:
|
|
|
|
return
|
|
|
|
|
|
|
|
# remove prev aliases
|
|
|
|
file_code_lines = file_code_lines[:marker_lineno + 1]
|
|
|
|
file_code_lines.append('')
|
|
|
|
file_code_lines.extend(file_aliases_code_fragments)
|
|
|
|
file_code_lines.append('')
|
|
|
|
|
|
|
|
new_file_code = '\n'.join(file_code_lines)
|
|
|
|
|
|
|
|
with open(file, 'w', encoding='UTF-8') as f:
|
|
|
|
f.write(new_file_code)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
for root, _, files in os.walk(SOURCE_FOLDER):
|
|
|
|
for file in files:
|
|
|
|
if file.endswith('.py') and file != '__init__.py':
|
|
|
|
filepath = os.path.join(root, file)
|
|
|
|
_process_file(filepath)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|