Added python function scan
This commit is contained in:
parent
2be818fcc1
commit
416940fd10
@ -7,10 +7,12 @@ from cpl_core.environment import ApplicationEnvironment
|
|||||||
|
|
||||||
from py_to_uxf_core.abc.class_scanner_abc import ClassScannerABC
|
from py_to_uxf_core.abc.class_scanner_abc import ClassScannerABC
|
||||||
from py_to_uxf_core.abc.file_scanner_abc import FileScannerABC
|
from py_to_uxf_core.abc.file_scanner_abc import FileScannerABC
|
||||||
|
from py_to_uxf_core.abc.function_scanner_abc import FunctionScannerABC
|
||||||
from py_to_uxf_core.abc.python_parser_abc import PythonParserABC
|
from py_to_uxf_core.abc.python_parser_abc import PythonParserABC
|
||||||
from py_to_uxf_core.abc.umlet_creator_abc import UmletCreatorABC
|
from py_to_uxf_core.abc.umlet_creator_abc import UmletCreatorABC
|
||||||
from py_to_uxf_core.service.class_scanner_service import ClassScannerService
|
from py_to_uxf_core.service.class_scanner_service import ClassScannerService
|
||||||
from py_to_uxf_core.service.file_scanner_service import FileScannerService
|
from py_to_uxf_core.service.file_scanner_service import FileScannerService
|
||||||
|
from py_to_uxf_core.service.function_scanner_service import FunctionScannerService
|
||||||
from py_to_uxf_core.service.python_parser_service import PythonParserService
|
from py_to_uxf_core.service.python_parser_service import PythonParserService
|
||||||
from py_to_uxf_core.service.umlet_creator_service import UmletCreatorService
|
from py_to_uxf_core.service.umlet_creator_service import UmletCreatorService
|
||||||
|
|
||||||
@ -29,6 +31,7 @@ class Startup(StartupABC):
|
|||||||
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
||||||
services.add_transient(FileScannerABC, FileScannerService)
|
services.add_transient(FileScannerABC, FileScannerService)
|
||||||
services.add_transient(ClassScannerABC, ClassScannerService)
|
services.add_transient(ClassScannerABC, ClassScannerService)
|
||||||
|
services.add_transient(FunctionScannerABC, FunctionScannerService)
|
||||||
|
|
||||||
services.add_singleton(PythonParserABC, PythonParserService)
|
services.add_singleton(PythonParserABC, PythonParserService)
|
||||||
services.add_singleton(UmletCreatorABC, UmletCreatorService)
|
services.add_singleton(UmletCreatorABC, UmletCreatorService)
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from cpl_query.extension import List
|
|
||||||
|
|
||||||
from py_to_uxf_core.model.python_class import PythonClass
|
from py_to_uxf_core.model.python_class import PythonClass
|
||||||
|
|
||||||
|
|
||||||
|
13
src/py_to_uxf_core/abc/function_scanner_abc.py
Normal file
13
src/py_to_uxf_core/abc/function_scanner_abc.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from py_to_uxf_core.model.python_function import PythonFunction
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionScannerABC(ABC):
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def __init__(self): pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def scan_line_for_function(self, line: str) -> Optional[PythonFunction]: pass
|
@ -0,0 +1,9 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionAccessModifierEnum(Enum):
|
||||||
|
|
||||||
|
public = '+'
|
||||||
|
private = '-'
|
||||||
|
protected = '#'
|
||||||
|
|
@ -1,8 +1,21 @@
|
|||||||
|
from cpl_query.extension import List
|
||||||
|
|
||||||
|
from py_to_uxf_core.model.python_function import PythonFunction
|
||||||
|
|
||||||
|
|
||||||
class PythonClass:
|
class PythonClass:
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._functions = List(PythonFunction)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def functions(self) -> List[PythonFunction]:
|
||||||
|
return self._functions
|
||||||
|
|
||||||
|
def add_function(self, func: PythonFunction):
|
||||||
|
self._functions.append(func)
|
||||||
|
29
src/py_to_uxf_core/model/python_function.py
Normal file
29
src/py_to_uxf_core/model/python_function.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
from cpl_query.extension import List
|
||||||
|
|
||||||
|
from py_to_uxf_core.model.function_access_modifier_enum import FunctionAccessModifierEnum
|
||||||
|
from py_to_uxf_core.model.python_function_argument import PythonFunctionArgument
|
||||||
|
|
||||||
|
|
||||||
|
class PythonFunction:
|
||||||
|
|
||||||
|
def __init__(self, access_modifier: FunctionAccessModifierEnum, name: str, args: List[PythonFunctionArgument], return_type: str):
|
||||||
|
self._access_modifier = access_modifier
|
||||||
|
self._name = name
|
||||||
|
self._args = args
|
||||||
|
self._return_type = return_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def access_modifier(self):
|
||||||
|
return self._access_modifier
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def args(self) -> List[PythonFunctionArgument]:
|
||||||
|
return self._args
|
||||||
|
|
||||||
|
@property
|
||||||
|
def return_type(self) -> str:
|
||||||
|
return self._return_type
|
19
src/py_to_uxf_core/model/python_function_argument.py
Normal file
19
src/py_to_uxf_core/model/python_function_argument.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
class PythonFunctionArgument:
|
||||||
|
|
||||||
|
def __init__(self, name: str, type: str):
|
||||||
|
self._name = name
|
||||||
|
self._type = type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self) -> str:
|
||||||
|
return self._type
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self._name}: {self._type}'
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'{self._name}: {self._type}'
|
@ -12,8 +12,8 @@ class ClassScannerService(ClassScannerABC):
|
|||||||
ClassScannerABC.__init__(self)
|
ClassScannerABC.__init__(self)
|
||||||
|
|
||||||
def scan_line_for_classes(self, line: str) -> Optional[PythonClass]:
|
def scan_line_for_classes(self, line: str) -> Optional[PythonClass]:
|
||||||
if 'class' in line:
|
if line.startswith('class'):
|
||||||
name = line.split(' ')[1]
|
name = line.split('class ')[1]
|
||||||
if '(' in name:
|
if '(' in name:
|
||||||
name = name.split('(')[0]
|
name = name.split('(')[0]
|
||||||
else:
|
else:
|
||||||
|
66
src/py_to_uxf_core/service/function_scanner_service.py
Normal file
66
src/py_to_uxf_core/service/function_scanner_service.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
import value as value
|
||||||
|
from cpl_query.extension import List
|
||||||
|
|
||||||
|
from py_to_uxf_core.abc.function_scanner_abc import FunctionScannerABC
|
||||||
|
from py_to_uxf_core.model.function_access_modifier_enum import FunctionAccessModifierEnum
|
||||||
|
from py_to_uxf_core.model.python_function import PythonFunction
|
||||||
|
from py_to_uxf_core.model.python_function_argument import PythonFunctionArgument
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionScannerService(FunctionScannerABC):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
FunctionScannerABC.__init__(self)
|
||||||
|
|
||||||
|
def scan_line_for_function(self, line: str) -> Optional[PythonFunction]:
|
||||||
|
# def xy():
|
||||||
|
# def xy() -> int:
|
||||||
|
# def xy(x: int, y: int) -> int:
|
||||||
|
# async def xy(x: int, y: int) -> int:
|
||||||
|
# async def _xy(x: int, y: int) -> int:
|
||||||
|
# async def __xy(x: int, y: int) -> int:
|
||||||
|
if line.startswith('def') or line.startswith('async def'):
|
||||||
|
# name
|
||||||
|
name = line.split('def ')[1]
|
||||||
|
name = name.split('(')[0]
|
||||||
|
access_modifier = FunctionAccessModifierEnum.public
|
||||||
|
args = List()
|
||||||
|
return_type = 'None'
|
||||||
|
|
||||||
|
# access_modifier
|
||||||
|
if name == '__init__' or name == '__repr__' or name == '__str__':
|
||||||
|
access_modifier = FunctionAccessModifierEnum.public
|
||||||
|
elif name.startswith('_'):
|
||||||
|
access_modifier = FunctionAccessModifierEnum.protected
|
||||||
|
elif name.startswith('__'):
|
||||||
|
access_modifier = FunctionAccessModifierEnum.private
|
||||||
|
|
||||||
|
# args
|
||||||
|
args_str = line.split('(')[1]
|
||||||
|
args_str = args_str.split(')')[0]
|
||||||
|
# multiple arguments
|
||||||
|
if ',' in args_str:
|
||||||
|
for argument in args_str.split(','):
|
||||||
|
# with type
|
||||||
|
type_str = 'any'
|
||||||
|
arg_name = argument
|
||||||
|
if ':' in argument:
|
||||||
|
type_str = argument.split(': ')[1]
|
||||||
|
arg_name = argument.split(': ')[0]
|
||||||
|
# without type
|
||||||
|
if arg_name.startswith(' '):
|
||||||
|
arg_name = arg_name.split(' ')[1]
|
||||||
|
args.append(PythonFunctionArgument(arg_name, type_str))
|
||||||
|
# single argument
|
||||||
|
elif args_str != '':
|
||||||
|
pass
|
||||||
|
|
||||||
|
# return_type
|
||||||
|
if '->' in line:
|
||||||
|
return_type_str = line.split('-> ')[1]
|
||||||
|
return_type = return_type_str.split(':')[0]
|
||||||
|
|
||||||
|
return PythonFunction(access_modifier, name, args, return_type)
|
||||||
|
return None
|
@ -4,27 +4,66 @@ from cpl_core.console import Console
|
|||||||
|
|
||||||
from py_to_uxf_core.abc.class_scanner_abc import ClassScannerABC
|
from py_to_uxf_core.abc.class_scanner_abc import ClassScannerABC
|
||||||
from py_to_uxf_core.abc.file_scanner_abc import FileScannerABC
|
from py_to_uxf_core.abc.file_scanner_abc import FileScannerABC
|
||||||
|
from py_to_uxf_core.abc.function_scanner_abc import FunctionScannerABC
|
||||||
from py_to_uxf_core.abc.python_parser_abc import PythonParserABC
|
from py_to_uxf_core.abc.python_parser_abc import PythonParserABC
|
||||||
from py_to_uxf_core.model.python_class import PythonClass
|
from py_to_uxf_core.model.python_class import PythonClass
|
||||||
|
|
||||||
|
|
||||||
class PythonParserService(PythonParserABC):
|
class PythonParserService(PythonParserABC):
|
||||||
|
|
||||||
def __init__(self, file_scanner: FileScannerABC, class_scanner: ClassScannerABC):
|
def __init__(
|
||||||
|
self,
|
||||||
|
file_scanner: FileScannerABC,
|
||||||
|
class_scanner: ClassScannerABC,
|
||||||
|
function_scanner: FunctionScannerABC
|
||||||
|
):
|
||||||
PythonParserABC.__init__(self)
|
PythonParserABC.__init__(self)
|
||||||
|
|
||||||
self._file_scanner = file_scanner
|
self._file_scanner = file_scanner
|
||||||
self._class_scanner = class_scanner
|
self._class_scanner = class_scanner
|
||||||
|
self._function_scanner = function_scanner
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
files = self._file_scanner.scan_files()
|
files = self._file_scanner.scan_files()
|
||||||
for file in files:
|
for file in files:
|
||||||
Console.write_line('f:', file)
|
Console.write_line('\nfi:', file)
|
||||||
|
is_comment = False
|
||||||
with open(file, 'r') as file_content:
|
with open(file, 'r') as file_content:
|
||||||
cls: Optional[PythonClass] = None
|
cls: Optional[PythonClass] = None
|
||||||
for line in file_content.readlines():
|
for line in file_content.readlines():
|
||||||
if cls is None:
|
line = line.replace(' ', '')
|
||||||
cls = self._class_scanner.scan_line_for_classes(line)
|
line = line.replace('\t', '')
|
||||||
|
# replace line break at the end of line
|
||||||
|
if line.endswith('\n'):
|
||||||
|
line = line.replace('\n', '')
|
||||||
|
|
||||||
|
if line == '\n' or line == '':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
Console.write_line('c:', cls.name)
|
# one line comments
|
||||||
|
if line != '"""' and line.startswith('"""') and line.endswith('"""') or line.startswith('#'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# start multi line comment
|
||||||
|
if line.startswith('"""') and not is_comment:
|
||||||
|
is_comment = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
# end multi line comment
|
||||||
|
if line.startswith('"""') or line.endswith('"""') and is_comment:
|
||||||
|
is_comment = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
if is_comment:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if cls is None:
|
||||||
|
cls = self._class_scanner.scan_line_for_classes(line)
|
||||||
|
if cls is not None:
|
||||||
|
Console.write_line('cl:', cls.name)
|
||||||
|
continue
|
||||||
|
|
||||||
|
func = self._function_scanner.scan_line_for_function(line)
|
||||||
|
if func is not None:
|
||||||
|
cls.add_function(func)
|
||||||
|
Console.write_line('fu:', func.access_modifier.value, func.name, func.args, func.return_type)
|
||||||
|
Loading…
Reference in New Issue
Block a user