[WIP] Added implementation scanning
This commit is contained in:
parent
61b1838c40
commit
c53b3b7669
@ -4,9 +4,11 @@ from cpl_core.application import ApplicationABC
|
||||
from cpl_core.configuration import ConfigurationABC
|
||||
from cpl_core.console import Console
|
||||
from cpl_core.dependency_injection import ServiceProviderABC
|
||||
from cpl_query.extension import List
|
||||
|
||||
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.model.class_implementation import ClassImplementation
|
||||
from py_to_uxf_core.model.python_class import PythonClass
|
||||
|
||||
|
||||
@ -58,8 +60,11 @@ class Application(ApplicationABC):
|
||||
Console.write_line(f'Output path:', self._file)
|
||||
xml = ''
|
||||
try:
|
||||
classes: list[PythonClass] = self._parser.parse()
|
||||
Console.write_line(f'Found {len(classes)} classes')
|
||||
classes: List[PythonClass] = self._parser.parse_classes()
|
||||
Console.write_line(f'Found {classes.count()} classes')
|
||||
implementations: List[ClassImplementation] = self._parser.parse_implementations(classes)
|
||||
Console.write_line(f'Found {implementations.count()} implementations')
|
||||
Console.write_line(implementations)
|
||||
# self._console_output(classes)
|
||||
xml = self._umlet_creator.generate_xml(classes)
|
||||
except Exception as e:
|
||||
|
@ -9,12 +9,14 @@ from py_to_uxf_core.abc.attribute_scanner_abc import AttributeScannerABC
|
||||
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.function_scanner_abc import FunctionScannerABC
|
||||
from py_to_uxf_core.abc.implementation_scanner_abc import ImplementationScannerABC
|
||||
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.service.attribute_scanner_service import AttributeScannerService
|
||||
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.function_scanner_service import FunctionScannerService
|
||||
from py_to_uxf_core.service.implementation_scanner_service import ImplementationScannerService
|
||||
from py_to_uxf_core.service.python_parser_service import PythonParserService
|
||||
from py_to_uxf_core.service.umlet_creator_service import UmletCreatorService
|
||||
|
||||
@ -38,6 +40,7 @@ class Startup(StartupABC):
|
||||
services.add_transient(ClassScannerABC, ClassScannerService)
|
||||
services.add_transient(FunctionScannerABC, FunctionScannerService)
|
||||
services.add_transient(AttributeScannerABC, AttributeScannerService)
|
||||
services.add_transient(ImplementationScannerABC, ImplementationScannerService)
|
||||
|
||||
services.add_singleton(PythonParserABC, PythonParserService)
|
||||
services.add_singleton(UmletCreatorABC, UmletCreatorService)
|
||||
|
14
src/py_to_uxf_core/abc/implementation_scanner_abc.py
Normal file
14
src/py_to_uxf_core/abc/implementation_scanner_abc.py
Normal file
@ -0,0 +1,14 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from py_to_uxf_core.model.class_implementation import ClassImplementation
|
||||
from py_to_uxf_core.model.python_class import PythonClass
|
||||
|
||||
|
||||
class ImplementationScannerABC(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def scan_line_for_implementation(self, line: str, classes: list[PythonClass]) -> Optional[ClassImplementation]: pass
|
@ -2,6 +2,7 @@ from abc import ABC, abstractmethod
|
||||
|
||||
from cpl_query.extension import List
|
||||
|
||||
from py_to_uxf_core.model.class_implementation import ClassImplementation
|
||||
from py_to_uxf_core.model.python_class import PythonClass
|
||||
|
||||
|
||||
@ -11,4 +12,7 @@ class PythonParserABC(ABC):
|
||||
def __init__(self): pass
|
||||
|
||||
@abstractmethod
|
||||
def parse(self) -> List[PythonClass]: pass
|
||||
def parse_classes(self) -> List[PythonClass]: pass
|
||||
|
||||
@abstractmethod
|
||||
def parse_implementations(self, classes: List[PythonClass]) -> List[ClassImplementation]: pass
|
||||
|
22
src/py_to_uxf_core/model/class_implementation.py
Normal file
22
src/py_to_uxf_core/model/class_implementation.py
Normal file
@ -0,0 +1,22 @@
|
||||
from py_to_uxf_core.model.python_class import PythonClass
|
||||
|
||||
|
||||
class ClassImplementation:
|
||||
|
||||
def __init__(self, base: PythonClass, subclass: PythonClass):
|
||||
self._base = base
|
||||
self._subclass = subclass
|
||||
|
||||
@property
|
||||
def base(self) -> PythonClass:
|
||||
return self._base
|
||||
|
||||
@property
|
||||
def subclass(self) -> PythonClass:
|
||||
return self._subclass
|
||||
|
||||
def __str__(self):
|
||||
return f'{self._subclass.name} -> {self._base.name}'
|
||||
|
||||
def __repr__(self):
|
||||
return f'{self._subclass.name} -> {self._base.name}'
|
32
src/py_to_uxf_core/service/implementation_scanner_service.py
Normal file
32
src/py_to_uxf_core/service/implementation_scanner_service.py
Normal file
@ -0,0 +1,32 @@
|
||||
from typing import Optional
|
||||
|
||||
from cpl_core.console import Console
|
||||
from cpl_query.extension import List
|
||||
|
||||
from py_to_uxf_core.abc.implementation_scanner_abc import ImplementationScannerABC
|
||||
from py_to_uxf_core.model.class_implementation import ClassImplementation
|
||||
from py_to_uxf_core.model.python_class import PythonClass
|
||||
|
||||
|
||||
class ImplementationScannerService(ImplementationScannerABC):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def scan_line_for_implementation(self, line: str, classes: List[PythonClass]) -> Optional[ClassImplementation]:
|
||||
line = line.replace(' ', '')
|
||||
line = line.replace('\t', '')
|
||||
if line.startswith('class ') and '(' in line and ')' in line:
|
||||
sub_name = line.split('class ')[1].split('(')[0]
|
||||
sub: Optional[PythonClass] = classes.where(lambda c: c.name == sub_name).first_or_default()
|
||||
if sub is None:
|
||||
return None
|
||||
|
||||
base_name = line.split('(')[1].split(')')[0]
|
||||
base: Optional[PythonClass] = classes.where(lambda c: c.name == base_name).first_or_default()
|
||||
if base is None:
|
||||
return None
|
||||
|
||||
return ClassImplementation(base, sub)
|
||||
|
||||
return None
|
@ -8,7 +8,9 @@ from py_to_uxf_core.abc.attribute_scanner_abc import AttributeScannerABC
|
||||
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.function_scanner_abc import FunctionScannerABC
|
||||
from py_to_uxf_core.abc.implementation_scanner_abc import ImplementationScannerABC
|
||||
from py_to_uxf_core.abc.python_parser_abc import PythonParserABC
|
||||
from py_to_uxf_core.model.class_implementation import ClassImplementation
|
||||
from py_to_uxf_core.model.python_class import PythonClass
|
||||
|
||||
|
||||
@ -19,7 +21,8 @@ class PythonParserService(PythonParserABC):
|
||||
file_scanner: FileScannerABC,
|
||||
class_scanner: ClassScannerABC,
|
||||
function_scanner: FunctionScannerABC,
|
||||
attribute_scanner: AttributeScannerABC
|
||||
attribute_scanner: AttributeScannerABC,
|
||||
implementation_scanner: ImplementationScannerABC
|
||||
):
|
||||
PythonParserABC.__init__(self)
|
||||
|
||||
@ -27,8 +30,11 @@ class PythonParserService(PythonParserABC):
|
||||
self._class_scanner = class_scanner
|
||||
self._function_scanner = function_scanner
|
||||
self._attribute_scanner = attribute_scanner
|
||||
self._implementation_scanner = implementation_scanner
|
||||
|
||||
def parse(self) -> List[PythonClass]:
|
||||
self._files_with_classes: list[str] = []
|
||||
|
||||
def parse_classes(self) -> List[PythonClass]:
|
||||
files = self._file_scanner.scan_files()
|
||||
classes = List(PythonClass)
|
||||
for file in files:
|
||||
@ -74,6 +80,7 @@ class PythonParserService(PythonParserABC):
|
||||
cls = self._class_scanner.scan_line_for_classes(line)
|
||||
if cls is not None:
|
||||
classes.append(cls)
|
||||
self._files_with_classes.append(file)
|
||||
continue
|
||||
|
||||
func = self._function_scanner.scan_line_for_function(line)
|
||||
@ -90,6 +97,56 @@ class PythonParserService(PythonParserABC):
|
||||
cls.add_attribute(attribute)
|
||||
except Exception as e:
|
||||
Console.error(f'Parsing {file}@{i}', f'{e} -> {traceback.format_exc()}')
|
||||
file_content.close()
|
||||
exit()
|
||||
|
||||
file_content.close()
|
||||
return classes
|
||||
|
||||
def parse_implementations(self, classes: List[PythonClass]) -> List[ClassImplementation]:
|
||||
implementations = List()
|
||||
files = self._files_with_classes
|
||||
for file in files:
|
||||
is_comment = False
|
||||
with open(file, 'r') as file_content:
|
||||
implementation: Optional[ClassImplementation] = None
|
||||
lines = file_content.readlines()
|
||||
|
||||
for i in range(len(lines)):
|
||||
try:
|
||||
line = lines[i]
|
||||
line = line.replace(' ', '')
|
||||
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
|
||||
|
||||
# one line comments
|
||||
if line != '"""' and line.startswith('"""') and line.endswith('"""') or line.startswith('#'):
|
||||
continue
|
||||
|
||||
# start multi line comment
|
||||
if line.startswith('"""') or line.count('"""') == 1 and not is_comment:
|
||||
is_comment = True
|
||||
continue
|
||||
|
||||
# end multi line comment
|
||||
if line.startswith('"""') or line.endswith('"""') or line.count('"""') == 1 and is_comment:
|
||||
is_comment = False
|
||||
continue
|
||||
|
||||
if is_comment:
|
||||
continue
|
||||
|
||||
if implementation is None:
|
||||
implementation = self._implementation_scanner.scan_line_for_implementation(line, classes)
|
||||
if implementation is not None:
|
||||
implementations.append(implementation)
|
||||
except Exception as e:
|
||||
Console.error(f'Parsing {file}@{i}', f'{e} -> {traceback.format_exc()}')
|
||||
file_content.close()
|
||||
exit()
|
||||
file_content.close()
|
||||
return implementations
|
||||
|
Loading…
Reference in New Issue
Block a user