pyfcstm 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyfcstm/config/meta.py +1 -1
- pyfcstm/model/model.py +19 -8
- pyfcstm/utils/__init__.py +1 -0
- pyfcstm/utils/safe.py +41 -0
- {pyfcstm-0.1.0.dist-info → pyfcstm-0.1.2.dist-info}/METADATA +1 -1
- {pyfcstm-0.1.0.dist-info → pyfcstm-0.1.2.dist-info}/RECORD +10 -9
- {pyfcstm-0.1.0.dist-info → pyfcstm-0.1.2.dist-info}/LICENSE +0 -0
- {pyfcstm-0.1.0.dist-info → pyfcstm-0.1.2.dist-info}/WHEEL +0 -0
- {pyfcstm-0.1.0.dist-info → pyfcstm-0.1.2.dist-info}/entry_points.txt +0 -0
- {pyfcstm-0.1.0.dist-info → pyfcstm-0.1.2.dist-info}/top_level.txt +0 -0
pyfcstm/config/meta.py
CHANGED
@@ -7,7 +7,7 @@ Overview:
|
|
7
7
|
__TITLE__ = 'pyfcstm'
|
8
8
|
|
9
9
|
#: Version of this project.
|
10
|
-
__VERSION__ = '0.1.
|
10
|
+
__VERSION__ = '0.1.2'
|
11
11
|
|
12
12
|
#: Short description of the project, will be included in ``setup.py``.
|
13
13
|
__DESCRIPTION__ = ('A Python framework for parsing finite state machine DSL and '
|
pyfcstm/model/model.py
CHANGED
@@ -38,6 +38,8 @@ __all__ = [
|
|
38
38
|
'parse_dsl_node_to_state_machine',
|
39
39
|
]
|
40
40
|
|
41
|
+
from ..utils import sequence_safe
|
42
|
+
|
41
43
|
|
42
44
|
@dataclass
|
43
45
|
class Operation(AstExportable):
|
@@ -877,18 +879,27 @@ class State(AstExportable, PlantUMLExportable):
|
|
877
879
|
:return: PlantUML representation of the state
|
878
880
|
:rtype: str
|
879
881
|
"""
|
882
|
+
|
883
|
+
def _name_safe(sub_state: Optional[str] = None):
|
884
|
+
subpath = [*self.path]
|
885
|
+
if sub_state is not None:
|
886
|
+
subpath.append(sub_state)
|
887
|
+
return sequence_safe(subpath)
|
888
|
+
|
880
889
|
with io.StringIO() as sf:
|
881
890
|
if self.is_leaf_state:
|
882
|
-
print(f'state {self.name}', file=sf, end='')
|
891
|
+
print(f'state {json.dumps(self.name)} as {_name_safe()}', file=sf, end='')
|
883
892
|
else:
|
884
|
-
print(f'state {self.name} {{', file=sf)
|
893
|
+
print(f'state {json.dumps(self.name)} as {_name_safe()} {{', file=sf)
|
885
894
|
for state in self.substates.values():
|
886
895
|
print(indent(state.to_plantuml(), prefix=' '), file=sf)
|
887
896
|
for trans in self.transitions:
|
888
897
|
with io.StringIO() as tf:
|
889
|
-
print('[*]' if trans.from_state is dsl_nodes.INIT_STATE
|
898
|
+
print('[*]' if trans.from_state is dsl_nodes.INIT_STATE
|
899
|
+
else _name_safe(trans.from_state), file=tf, end='')
|
890
900
|
print(' --> ', file=tf, end='')
|
891
|
-
print('[*]' if trans.to_state is dsl_nodes.EXIT_STATE
|
901
|
+
print('[*]' if trans.to_state is dsl_nodes.EXIT_STATE
|
902
|
+
else _name_safe(trans.to_state), file=tf, end='')
|
892
903
|
|
893
904
|
if trans.event is not None:
|
894
905
|
print(f' : {".".join(list(trans.event.path[len(self.path):]))}', file=tf, end='')
|
@@ -920,7 +931,7 @@ class State(AstExportable, PlantUMLExportable):
|
|
920
931
|
for during_aspect_item in self.on_during_aspects:
|
921
932
|
print(during_aspect_item.to_ast_node(), file=tf)
|
922
933
|
text = json.dumps(tf.getvalue().rstrip()).strip("\"")
|
923
|
-
print(f'{
|
934
|
+
print(f'{_name_safe()} : {text}', file=sf, end='')
|
924
935
|
|
925
936
|
return sf.getvalue()
|
926
937
|
|
@@ -1021,8 +1032,8 @@ class StateMachine(AstExportable, PlantUMLExportable):
|
|
1021
1032
|
print('end note', file=sf)
|
1022
1033
|
print('', file=sf)
|
1023
1034
|
print(self.root_state.to_plantuml(), file=sf)
|
1024
|
-
print(f'[*] --> {self.root_state.
|
1025
|
-
print(f'{self.root_state.
|
1035
|
+
print(f'[*] --> {sequence_safe(self.root_state.path)}', file=sf)
|
1036
|
+
print(f'{sequence_safe(self.root_state.path)} --> [*]', file=sf)
|
1026
1037
|
print('@enduml', file=sf, end='')
|
1027
1038
|
return sf.getvalue()
|
1028
1039
|
|
@@ -1147,7 +1158,7 @@ def parse_dsl_node_to_state_machine(dnode: dsl_nodes.StateMachineDSLProgram) ->
|
|
1147
1158
|
|
1148
1159
|
transitions = current_state.transitions
|
1149
1160
|
for subnode in node.substates:
|
1150
|
-
_inner_force_transitions = [
|
1161
|
+
_inner_force_transitions = []
|
1151
1162
|
for from_state, to_state, my_event_id, trans_event, condition_expr, guard in force_transition_tuples_to_inherit:
|
1152
1163
|
if from_state is dsl_nodes.ALL or from_state == subnode.name:
|
1153
1164
|
transitions.append(Transition(
|
pyfcstm/utils/__init__.py
CHANGED
@@ -3,5 +3,6 @@ from .decode import auto_decode
|
|
3
3
|
from .doc import format_multiline_comment
|
4
4
|
from .jinja2 import add_builtins_to_env, add_settings_for_env
|
5
5
|
from .json import IJsonOp
|
6
|
+
from .safe import sequence_safe
|
6
7
|
from .text import normalize, to_identifier
|
7
8
|
from .validate import ValidationError, ModelValidationError, IValidatable
|
pyfcstm/utils/safe.py
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
"""
|
2
|
+
Utility module for creating safe sequence identifiers.
|
3
|
+
|
4
|
+
This module provides functionality to convert sequences of strings into safe,
|
5
|
+
underscore-separated identifiers. It's particularly useful for generating
|
6
|
+
consistent naming conventions from potentially inconsistent input strings.
|
7
|
+
|
8
|
+
The main use case is to take a collection of string segments that may use
|
9
|
+
different naming conventions (CamelCase, snake_case, kebab-case, etc.) and
|
10
|
+
normalize them into a consistent, safe identifier format using underscores
|
11
|
+
as separators.
|
12
|
+
"""
|
13
|
+
|
14
|
+
import re
|
15
|
+
from typing import Iterable
|
16
|
+
|
17
|
+
from hbutils.string import underscore
|
18
|
+
|
19
|
+
|
20
|
+
def sequence_safe(segments: Iterable[str]) -> str:
|
21
|
+
"""
|
22
|
+
Convert a sequence of strings into a safe underscore-separated identifier.
|
23
|
+
|
24
|
+
This function takes a sequence of strings, converts each to underscore format,
|
25
|
+
normalizes multiple consecutive underscores to single underscores, and joins
|
26
|
+
them with double underscores ('__'). This is useful for creating consistent
|
27
|
+
identifiers from potentially inconsistent input strings.
|
28
|
+
|
29
|
+
:param segments: A sequence of strings to be converted into a safe identifier.
|
30
|
+
:type segments: Iterable[str]
|
31
|
+
|
32
|
+
:return: A safe underscore-separated identifier string.
|
33
|
+
:rtype: str
|
34
|
+
|
35
|
+
Example::
|
36
|
+
>>> sequence_safe(['CamelCase', 'snake_case', 'kebab-case'])
|
37
|
+
'camel_case__snake_case__kebab_case'
|
38
|
+
>>> sequence_safe(['Hello World', 'Test___String'])
|
39
|
+
'hello_world__test_string'
|
40
|
+
"""
|
41
|
+
return '__'.join(map(lambda x: re.sub(r'_+', '_', underscore(x)), segments))
|
@@ -1,7 +1,7 @@
|
|
1
1
|
pyfcstm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
2
|
pyfcstm/__main__.py,sha256=rqAJpNJgf8R-OZnKecjYyCrK_hJcQhHaO0UL6Vb92-8,75
|
3
3
|
pyfcstm/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
pyfcstm/config/meta.py,sha256=
|
4
|
+
pyfcstm/config/meta.py,sha256=aaBszpb_wRXoEVbFncNHuD9R0bLJbUlWeCyBhWpTTUk,534
|
5
5
|
pyfcstm/dsl/__init__.py,sha256=3GMEILDRArhkjz0vQPHOk_eiby74H94TOa3o-Tpo4x0,349
|
6
6
|
pyfcstm/dsl/error.py,sha256=BEaroPj98Q8J12IT73rfPeb9y0TXjPG6llDo5GiqRIU,8878
|
7
7
|
pyfcstm/dsl/listener.py,sha256=9J8QETMu40HxT20ZOJ4c9QWY7X_Y6AbEgkzoD-xTAg4,19633
|
@@ -25,23 +25,24 @@ pyfcstm/entry/plantuml.py,sha256=uZUZ_kxhxinh8Jw6nf0e4c2C14kfqH5eeRS3bbCDRbc,266
|
|
25
25
|
pyfcstm/model/__init__.py,sha256=aJ76DOX21iXRJN2xwsH7CiEG7iPkpDJMXKvEh9Xb9Q4,93
|
26
26
|
pyfcstm/model/base.py,sha256=3H6Sf9uTfAZUNemSmR4L1aoSICG42EcrVncgQDZNAXY,1761
|
27
27
|
pyfcstm/model/expr.py,sha256=X3eyOYMeZ66LdD0ZpwDjDRQUQrkpXtpSWLY9TILFzSI,18908
|
28
|
-
pyfcstm/model/model.py,sha256=
|
28
|
+
pyfcstm/model/model.py,sha256=hIxzlFjViZo7C9nwP7NAtGD6USedmK1k69QJFZbYLTw,56476
|
29
29
|
pyfcstm/render/__init__.py,sha256=Bettq3kIoswqSZQSxjQciMrmRZqkn5noaKoQO9d8Jlw,153
|
30
30
|
pyfcstm/render/env.py,sha256=pjZnlvYLL8sA9lZupKtIHijrHOiAWBeBU_ytNYLxz1w,1106
|
31
31
|
pyfcstm/render/expr.py,sha256=sT7uazQuEFrAFHBSTV0FviubNIYP-CTjhNhd4dO96Fo,7551
|
32
32
|
pyfcstm/render/func.py,sha256=FZlQiKxKpOomH83FDqYYoeeclXlmm07zHYJk8MN5Cws,2663
|
33
33
|
pyfcstm/render/render.py,sha256=FmhHJvoIwWFGpm-KqDqybadj9pZbo7-bIiNxnyBF2Fc,11577
|
34
|
-
pyfcstm/utils/__init__.py,sha256=
|
34
|
+
pyfcstm/utils/__init__.py,sha256=FwtqP21-Uzj_2ocvdKTJ9ex-qJ_hcnyhWKj_vFYd6pg,346
|
35
35
|
pyfcstm/utils/binary.py,sha256=6AnX6Hx4JFRHl0Y1A6OJ1b_1-QtzaajEywp0h-a4kbs,1196
|
36
36
|
pyfcstm/utils/decode.py,sha256=V9WYt9_db_ddIB3PiSsGPPAO_aAeHinNRvA3W5jO6XM,3636
|
37
37
|
pyfcstm/utils/doc.py,sha256=CNGQoxTl33KEAnEXl_sr4I97zNARaAa2IwKKt5IC1MA,1905
|
38
38
|
pyfcstm/utils/jinja2.py,sha256=9lJFnsxfzTfc9Wj1twhk3e6aFgRzBW-mbhdOVudNcKw,4321
|
39
39
|
pyfcstm/utils/json.py,sha256=WPubB5ObTNT8eEyGV3DcgFE8BuYxJUO8xYPx5_kvvCQ,3732
|
40
|
+
pyfcstm/utils/safe.py,sha256=PT5WbzRlQqbaxYVqPB5f6mIhJXb3sa8JBwPcqXnuU9U,1565
|
40
41
|
pyfcstm/utils/text.py,sha256=wb4vIWB3mLne1R64x_MIS5qsIlGQ6cGCUVcbPlV21Hw,2895
|
41
42
|
pyfcstm/utils/validate.py,sha256=87k1B-gzYd-mZP2N5-nsC8OeLZsfNTOCjp_5LUgsaxw,3129
|
42
|
-
pyfcstm-0.1.
|
43
|
-
pyfcstm-0.1.
|
44
|
-
pyfcstm-0.1.
|
45
|
-
pyfcstm-0.1.
|
46
|
-
pyfcstm-0.1.
|
47
|
-
pyfcstm-0.1.
|
43
|
+
pyfcstm-0.1.2.dist-info/LICENSE,sha256=pWgb-bBdsU2Gd2kwAXxketnm5W_2u8_fIeWEgojfrxs,7651
|
44
|
+
pyfcstm-0.1.2.dist-info/METADATA,sha256=EFjxrNds-RricBfU83I1ykUuXDjO89fgzRfvkDHKc_w,13742
|
45
|
+
pyfcstm-0.1.2.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
46
|
+
pyfcstm-0.1.2.dist-info/entry_points.txt,sha256=Jh9a4hY-nMh5VTiuIBiZcM403biCHOwXk5hKNBr3Eok,53
|
47
|
+
pyfcstm-0.1.2.dist-info/top_level.txt,sha256=0VZTj6MqIhOSyoQLYUk1inV0P34VgetNZIKrzj-HNqo,8
|
48
|
+
pyfcstm-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|