Compare commits
3 Commits
master
...
placement_
Author | SHA1 | Date | |
---|---|---|---|
f10221686c | |||
342de3e1d1 | |||
0dbd5f57e6 |
@ -1,35 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
cd src
|
|
||||||
|
|
||||||
#pyinstaller --specpath ../dist/cspec \
|
|
||||||
# --workpath ../dist/cbuild \
|
|
||||||
# --distpath ../dist/cdist \
|
|
||||||
# --add-data ../../src/py_to_uxf/appsettings.json:. \
|
|
||||||
# --hidden-import pynput.keyboard._xorg \
|
|
||||||
# --hidden-import pynput.mouse._xorg \
|
|
||||||
# --hidden-import pyfiglet.fonts \
|
|
||||||
# --collect-data pyfiglet \
|
|
||||||
# -n py_to_uxf \
|
|
||||||
# -y \
|
|
||||||
# py_to_uxf/main.py
|
|
||||||
|
|
||||||
build=../dist/cbuild/
|
|
||||||
python -m nuitka \
|
|
||||||
--follow-imports \
|
|
||||||
--include-package=pkg_resources \
|
|
||||||
--include-package=pynput.keyboard._xorg \
|
|
||||||
--include-package=pynput.mouse._xorg \
|
|
||||||
--include-package=Xlib \
|
|
||||||
--output-dir=$build \
|
|
||||||
py_to_uxf/main.py
|
|
||||||
|
|
||||||
|
|
||||||
file="py_to_uxf/appsettings.json"
|
|
||||||
if [ -f "$file" ]; then
|
|
||||||
if [ -d "$build/main.dist/" ]; then
|
|
||||||
build=$build/main.dist/
|
|
||||||
fi
|
|
||||||
cp $file $build
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd ../
|
|
@ -18,13 +18,10 @@ class Application(ApplicationABC):
|
|||||||
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
|
||||||
ApplicationABC.__init__(self, config, services)
|
ApplicationABC.__init__(self, config, services)
|
||||||
|
|
||||||
|
config.parse_console_arguments(self._services)
|
||||||
self._path = config.get_configuration('p')
|
self._path = config.get_configuration('p')
|
||||||
self._file = ''
|
self._file = config.get_configuration('o')
|
||||||
try:
|
|
||||||
self._file = config.get_configuration('-pAdditionalArguments')[1]
|
|
||||||
except Exception as e:
|
|
||||||
Console.error('Expected file')
|
|
||||||
sys.exit()
|
|
||||||
self._parser: PythonParserABC = services.get_service(PythonParserABC)
|
self._parser: PythonParserABC = services.get_service(PythonParserABC)
|
||||||
self._umlet_creator: UmletCreatorABC = services.get_service(UmletCreatorABC)
|
self._umlet_creator: UmletCreatorABC = services.get_service(UmletCreatorABC)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"Parser": {
|
"Parser": {
|
||||||
"IgnoreClassNames": [
|
"IgnoreClassNames": [
|
||||||
"ABC",
|
"ABC",
|
||||||
|
"ABCMeta",
|
||||||
"Enum"
|
"Enum"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -16,13 +16,14 @@
|
|||||||
"LicenseName": "",
|
"LicenseName": "",
|
||||||
"LicenseDescription": "",
|
"LicenseDescription": "",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"sh_cpl-core>=2021.11.0.post3",
|
"cpl-core==2022.10.0.post7",
|
||||||
"sh_cpl-query==2021.11.0.post3"
|
"cpl-query==2022.10.0.post2"
|
||||||
],
|
],
|
||||||
"PythonVersion": ">=3.9.2",
|
"DevDependencies": [
|
||||||
"PythonPath": {
|
"cpl-cli==2022.10.1"
|
||||||
"linux": ""
|
],
|
||||||
},
|
"PythonVersion": ">=3.10.4",
|
||||||
|
"PythonPath": {},
|
||||||
"Classifiers": []
|
"Classifiers": []
|
||||||
},
|
},
|
||||||
"BuildSettings": {
|
"BuildSettings": {
|
||||||
|
@ -2,7 +2,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from cpl_core.application import StartupABC
|
from cpl_core.application import StartupABC
|
||||||
from cpl_core.configuration import ConfigurationABC, ConsoleArgument
|
from cpl_core.configuration import ConfigurationABC, ArgumentTypeEnum
|
||||||
from cpl_core.console import Console
|
from cpl_core.console import Console
|
||||||
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
|
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
|
||||||
from cpl_core.environment import ApplicationEnvironment
|
from cpl_core.environment import ApplicationEnvironment
|
||||||
@ -38,10 +38,9 @@ class Startup(StartupABC):
|
|||||||
Console.error(f'Expected config file appsettings.json')
|
Console.error(f'Expected config file appsettings.json')
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
configuration.add_console_argument(ConsoleArgument('-', 'p', [], ' ', False, [
|
configuration.create_console_argument(ArgumentTypeEnum.Variable, '-', 'p', [], ' ')
|
||||||
ConsoleArgument('-', 'o', [], ' ', is_value_token_optional=False)
|
configuration.create_console_argument(ArgumentTypeEnum.Variable, '-', 'o', [], ' ')
|
||||||
]))
|
|
||||||
configuration.add_console_arguments(error=False)
|
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
def configure_services(self, services: ServiceCollectionABC, environment: ApplicationEnvironment) -> ServiceProviderABC:
|
||||||
|
@ -6,7 +6,7 @@ class ClassImplementation:
|
|||||||
def __init__(self, base: PythonClass, subclass: PythonClass):
|
def __init__(self, base: PythonClass, subclass: PythonClass):
|
||||||
self._base = base
|
self._base = base
|
||||||
self._subclass = subclass
|
self._subclass = subclass
|
||||||
self.is_first = True
|
self._is_first = True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def base(self) -> PythonClass:
|
def base(self) -> PythonClass:
|
||||||
@ -16,8 +16,16 @@ class ClassImplementation:
|
|||||||
def subclass(self) -> PythonClass:
|
def subclass(self) -> PythonClass:
|
||||||
return self._subclass
|
return self._subclass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_first(self) -> bool:
|
||||||
|
return self._is_first
|
||||||
|
|
||||||
|
@is_first.setter
|
||||||
|
def is_first(self, value: bool):
|
||||||
|
self._is_first = value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'<{type(self).__name__} {self.is_first} {self._subclass.name} -> {self._base.name}>'
|
return f'<{type(self).__name__} {self._is_first} {self._subclass.name} -> {self._base.name}>'
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<{type(self).__name__} {self.is_first} {self._subclass.name} -> {self._base.name}>'
|
return f'<{type(self).__name__} {self._is_first} {self._subclass.name} -> {self._base.name}>'
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import math
|
from cpl_query.extension import List
|
||||||
import textwrap
|
|
||||||
|
|
||||||
from cpl_core.console import Console
|
|
||||||
|
|
||||||
from py_to_uxf_core.model.dimension import Dimension
|
from py_to_uxf_core.model.dimension import Dimension
|
||||||
from py_to_uxf_core.model.position import Position
|
from py_to_uxf_core.model.position import Position
|
||||||
@ -20,6 +17,9 @@ class UMLClass:
|
|||||||
self._position = pos
|
self._position = pos
|
||||||
self._dimension = dim
|
self._dimension = dim
|
||||||
|
|
||||||
|
self._base_classes = List(type(self))
|
||||||
|
self._sub_classes = List(type(self))
|
||||||
|
|
||||||
self._attributes = ''
|
self._attributes = ''
|
||||||
self._functions = ''
|
self._functions = ''
|
||||||
|
|
||||||
@ -43,6 +43,22 @@ class UMLClass:
|
|||||||
def dimension(self, value: int):
|
def dimension(self, value: int):
|
||||||
self._dimension = value
|
self._dimension = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_classes(self) -> List['UMLClass']:
|
||||||
|
return self._base_classes
|
||||||
|
|
||||||
|
@base_classes.setter
|
||||||
|
def base_classes(self, value: List['UMLClass']):
|
||||||
|
self._base_classes = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sub_classes(self) -> List['UMLClass']:
|
||||||
|
return self._sub_classes
|
||||||
|
|
||||||
|
@sub_classes.setter
|
||||||
|
def sub_classes(self, value: List['UMLClass']):
|
||||||
|
self._sub_classes = value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'<{type(self).__name__} {self._cls}: {self._position} {self._dimension}>'
|
return f'<{type(self).__name__} {self._cls}: {self._position} {self._dimension}>'
|
||||||
|
|
||||||
|
@ -16,9 +16,12 @@
|
|||||||
"LicenseName": "",
|
"LicenseName": "",
|
||||||
"LicenseDescription": "",
|
"LicenseDescription": "",
|
||||||
"Dependencies": [
|
"Dependencies": [
|
||||||
"sh_cpl-core>=2021.11.0.post3"
|
"cpl-core==2022.10.0.post2"
|
||||||
],
|
],
|
||||||
"PythonVersion": ">=3.9.2",
|
"DevDependencies": [
|
||||||
|
"cpl-cli==2022.10.1"
|
||||||
|
],
|
||||||
|
"PythonVersion": ">=3.10.4",
|
||||||
"PythonPath": {
|
"PythonPath": {
|
||||||
"linux": ""
|
"linux": ""
|
||||||
},
|
},
|
||||||
|
@ -16,11 +16,9 @@ class ImplementationScannerService(ImplementationScannerABC):
|
|||||||
ImplementationScannerABC.__init__(self)
|
ImplementationScannerABC.__init__(self)
|
||||||
self._parser_settings: ParserSettings = configuration.get_configuration(ParserSettings)
|
self._parser_settings: ParserSettings = configuration.get_configuration(ParserSettings)
|
||||||
|
|
||||||
def _get_implementation(self, base_name: str, sub_class: PythonClass, classes: List[PythonClass]) -> Optional[ClassImplementation]:
|
@staticmethod
|
||||||
|
def _get_implementation(base_name: str, sub_class: PythonClass, classes: List[PythonClass]) -> Optional[ClassImplementation]:
|
||||||
base: Optional[PythonClass] = classes.where(lambda c: c.name == base_name).first_or_default()
|
base: Optional[PythonClass] = classes.where(lambda c: c.name == base_name).first_or_default()
|
||||||
if base_name in self._parser_settings.ignore_class_names:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if base is None:
|
if base is None:
|
||||||
new_base = PythonClass(base_name)
|
new_base = PythonClass(base_name)
|
||||||
classes.append(new_base)
|
classes.append(new_base)
|
||||||
@ -44,13 +42,20 @@ class ImplementationScannerService(ImplementationScannerABC):
|
|||||||
implementations.append(implementation)
|
implementations.append(implementation)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for name in base_name.split(','):
|
split_base_name = base_name.split(',')
|
||||||
|
found_first_base = False
|
||||||
|
for i in range(len(split_base_name)):
|
||||||
|
name = split_base_name[i]
|
||||||
if '=' in name:
|
if '=' in name:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
implementation = self._get_implementation(name, sub, classes)
|
implementation = self._get_implementation(name, sub, classes)
|
||||||
if implementation is not None:
|
if implementation is not None:
|
||||||
implementation.is_first = False
|
if i > 0 and found_first_base:
|
||||||
|
implementation.is_first = False
|
||||||
|
|
||||||
|
if not found_first_base:
|
||||||
|
found_first_base = name not in self._parser_settings.ignore_class_names
|
||||||
implementations.append(implementation)
|
implementations.append(implementation)
|
||||||
return implementations
|
return implementations
|
||||||
return None
|
return None
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
from cpl_core.configuration import ConfigurationABC
|
from cpl_core.configuration import ConfigurationABC
|
||||||
from cpl_core.console import Console
|
from cpl_core.console import Console
|
||||||
from cpl_query.extension import List
|
from cpl_query.extension import List
|
||||||
|
|
||||||
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.configuration.parser_settings import ParserSettings
|
||||||
from py_to_uxf_core.configuration.uml_creator_settings import UMLCreatorSettings
|
from py_to_uxf_core.configuration.uml_creator_settings import UMLCreatorSettings
|
||||||
from py_to_uxf_core.model.class_implementation import ClassImplementation
|
from py_to_uxf_core.model.class_implementation import ClassImplementation
|
||||||
from py_to_uxf_core.model.dimension import Dimension
|
from py_to_uxf_core.model.dimension import Dimension
|
||||||
@ -10,6 +13,8 @@ from py_to_uxf_core.model.position import Position
|
|||||||
from py_to_uxf_core.model.python_class import PythonClass
|
from py_to_uxf_core.model.python_class import PythonClass
|
||||||
from py_to_uxf_core.model.uml_class import UMLClass
|
from py_to_uxf_core.model.uml_class import UMLClass
|
||||||
|
|
||||||
|
OrderedImplementation = dict[ClassImplementation, List]
|
||||||
|
|
||||||
|
|
||||||
class UmletCreatorService(UmletCreatorABC):
|
class UmletCreatorService(UmletCreatorABC):
|
||||||
|
|
||||||
@ -17,73 +22,57 @@ class UmletCreatorService(UmletCreatorABC):
|
|||||||
UmletCreatorABC.__init__(self)
|
UmletCreatorABC.__init__(self)
|
||||||
|
|
||||||
self._settings: UMLCreatorSettings = config.get_configuration(UMLCreatorSettings)
|
self._settings: UMLCreatorSettings = config.get_configuration(UMLCreatorSettings)
|
||||||
|
self._parser_settings: ParserSettings = config.get_configuration(ParserSettings)
|
||||||
self._moved_classes: list[UMLClass] = []
|
self._moved_classes: list[UMLClass] = []
|
||||||
self._padding = 30
|
self._padding = 30
|
||||||
|
|
||||||
def _sort_by_implementation(self, uml_classes: List[UMLClass], implementations: List[ClassImplementation]):
|
@staticmethod
|
||||||
base_sub_map: dict[UMLClass, list[UMLClass]] = {}
|
def _resolve_implementations(classes: List[UMLClass], implementations: List[ClassImplementation]) -> List[UMLClass]:
|
||||||
|
new_classes = List(UMLClass)
|
||||||
|
sub_classes = List(UMLClass)
|
||||||
for implementation in implementations:
|
for implementation in implementations:
|
||||||
sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
implementation: ClassImplementation = implementation
|
||||||
base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
base: UMLClass = classes.where(lambda c: c.cls == implementation.base).first()
|
||||||
|
sub: UMLClass = classes.where(lambda c: c.cls == implementation.subclass).first()
|
||||||
|
|
||||||
if base_class not in base_sub_map:
|
base.sub_classes.append(sub)
|
||||||
base_sub_map[base_class] = []
|
sub.base_classes.append(base)
|
||||||
|
if base not in new_classes:
|
||||||
|
new_classes.append(base)
|
||||||
|
sub_classes.append(sub)
|
||||||
|
|
||||||
if sub_class in base_sub_map[base_class]:
|
for cls in classes:
|
||||||
continue
|
if cls not in new_classes and cls not in sub_classes:
|
||||||
base_sub_map[base_class].append(sub_class)
|
new_classes.append(cls)
|
||||||
|
|
||||||
last_base = Position(self._padding, self._padding)
|
return new_classes
|
||||||
highest_y = self._padding
|
|
||||||
|
|
||||||
for base in base_sub_map:
|
def _move_classes(self, classes: List[UMLClass], moved_classes: List[UMLClass], next_pos: Position, highest_y: int):
|
||||||
subclasses = base_sub_map[base]
|
for cls in classes:
|
||||||
|
if cls.cls.name in self._parser_settings.ignore_class_names:
|
||||||
base.position.x = last_base.x
|
|
||||||
base.position.y = last_base.y
|
|
||||||
|
|
||||||
last_sub = Position(base.position.x, base.position.y + base.dimension.height)
|
|
||||||
for sub_class in subclasses:
|
|
||||||
if sub_class not in self._moved_classes:
|
|
||||||
sub_class.position.x = base.position.x
|
|
||||||
sub_class.position.y = base.position.y
|
|
||||||
|
|
||||||
if sub_class.position.x <= last_sub.x:
|
|
||||||
sub_class.position.x = last_sub.x
|
|
||||||
if sub_class.position.y <= last_sub.y:
|
|
||||||
sub_class.position.y = last_sub.y + self._padding * 2
|
|
||||||
|
|
||||||
last_sub.x = sub_class.position.x + sub_class.dimension.width + self._padding
|
|
||||||
if sub_class.position.y + sub_class.dimension.height > highest_y:
|
|
||||||
highest_y = sub_class.position.y + sub_class.dimension.height
|
|
||||||
|
|
||||||
self._moved_classes.append(sub_class)
|
|
||||||
|
|
||||||
last_base.x = last_sub.x
|
|
||||||
if last_base.x <= self._settings.max_pixel_x:
|
|
||||||
last_base.x += self._padding * 2
|
|
||||||
else:
|
|
||||||
last_base.x = self._padding
|
|
||||||
last_base.y = highest_y + self._padding * 2
|
|
||||||
|
|
||||||
self._moved_classes.append(base)
|
|
||||||
|
|
||||||
for cls in uml_classes:
|
|
||||||
if cls in self._moved_classes:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
new_x = last_base.x
|
if cls not in moved_classes:
|
||||||
if new_x <= self._settings.max_pixel_x:
|
Console.write_line(f'MOVE {cls.cls.name} to {next_pos} - {cls.dimension}')
|
||||||
cls.position.x = new_x
|
|
||||||
last_base.x = new_x + cls.dimension.width + self._padding
|
|
||||||
cls.position.y = last_base.y
|
|
||||||
else:
|
|
||||||
cls.position.x = self._padding
|
|
||||||
cls.position.y = highest_y + self._padding * 2
|
|
||||||
last_base = cls.position
|
|
||||||
|
|
||||||
if cls.position.y + cls.dimension.height > highest_y:
|
if next_pos.x > self._settings.max_pixel_x:
|
||||||
highest_y = cls.position.y + cls.dimension.height
|
next_pos.x = self._padding
|
||||||
|
next_pos.y = highest_y + self._padding * 2
|
||||||
|
|
||||||
|
cls.position.x = next_pos.x
|
||||||
|
cls.position.y = next_pos.y
|
||||||
|
|
||||||
|
next_pos.x = cls.position.x + cls.dimension.width + self._padding
|
||||||
|
|
||||||
|
if cls.position.y + cls.dimension.height > highest_y:
|
||||||
|
highest_y = cls.position.y + cls.dimension.height
|
||||||
|
|
||||||
|
moved_classes.append(cls)
|
||||||
|
|
||||||
|
if cls.sub_classes.count() > 0:
|
||||||
|
next_pos.x = cls.position.x
|
||||||
|
next_pos.y = cls.position.y + cls.dimension.height + self._padding
|
||||||
|
self._move_classes(cls.sub_classes, moved_classes, next_pos, highest_y)
|
||||||
|
|
||||||
def generate_xml(self, classes: List[PythonClass], implementations: List[ClassImplementation]) -> str:
|
def generate_xml(self, classes: List[PythonClass], implementations: List[ClassImplementation]) -> str:
|
||||||
uml_classes = List(UMLClass)
|
uml_classes = List(UMLClass)
|
||||||
@ -96,16 +85,33 @@ class UmletCreatorService(UmletCreatorABC):
|
|||||||
uml_cls.create_xml_body()
|
uml_cls.create_xml_body()
|
||||||
uml_classes.append(uml_cls)
|
uml_classes.append(uml_cls)
|
||||||
|
|
||||||
self._sort_by_implementation(uml_classes, implementations)
|
sorted_classes = self._resolve_implementations(uml_classes, implementations)
|
||||||
for implementation in implementations:
|
moved_classes = List(UMLClass)
|
||||||
sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
self._move_classes(sorted_classes, moved_classes, Position(self._padding, self._padding), 0)
|
||||||
base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
|
||||||
xml_relations += sub_class.implementation_as_xml(base_class)
|
|
||||||
|
|
||||||
for uml_cls in uml_classes:
|
for uml_cls in moved_classes:
|
||||||
# save class xml
|
# save class xml
|
||||||
|
if uml_cls.cls.name in self._parser_settings.ignore_class_names:
|
||||||
|
continue
|
||||||
|
|
||||||
xml_classes += uml_cls.as_xml()
|
xml_classes += uml_cls.as_xml()
|
||||||
|
|
||||||
|
# self._sort_by_implementation(uml_classes, implementations)
|
||||||
|
# oi = self._sort_implementations_by_base_order(implementations)
|
||||||
|
# for uml_cls in self._move_by_implementation(oi, uml_classes):
|
||||||
|
# save class xml
|
||||||
|
# if uml_cls.cls.name in self._parser_settings.ignore_class_names:
|
||||||
|
# continue
|
||||||
|
#
|
||||||
|
# xml_classes += uml_cls.as_xml()
|
||||||
|
|
||||||
|
# for implementation in implementations:
|
||||||
|
# sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
||||||
|
# base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
||||||
|
# if base_class.cls.name in self._parser_settings.ignore_class_names:
|
||||||
|
# continue
|
||||||
|
# xml_relations += sub_class.implementation_as_xml(base_class)
|
||||||
|
|
||||||
return f"""\
|
return f"""\
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<diagram program="umlet" version="14.1.1">
|
<diagram program="umlet" version="14.1.1">
|
||||||
|
Loading…
Reference in New Issue
Block a user