Skip to content

Commit 5e76771

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feat/final_major_one_version
# Conflicts: # requirements.txt # setup.py # source/rafcon/core/start.py # source/rafcon/gui/start.py # source/rafcon/utils/profiling.py
2 parents ff86299 + e3e9f72 commit 5e76771

File tree

104 files changed

+748
-781
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+748
-781
lines changed

CHANGELOG.rst

+10
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ Changelog
44
Information about :ref:`RAFCON` changes in each release will be published here. More
55
details can be found in the `GIT commit log <https://github.com/DLR-RM/RAFCON/commits/develop>`__.
66

7+
Future Release
8+
"""""""
9+
- Features:
10+
- Add skip & skip all buttons in the dialog of the broken libraries during loading a broken session
11+
- Set the default directory of the dialog during saving a state machine in accordance with the chosen library in the library tree
12+
- Create the data flows & data ports automatically in the nested states
13+
- Create the data port automatically when the other state does not have one during connecting the data flows
14+
- Support waypoints for data flows
15+
- Custom background color for states
16+
717

818
1.0.0
919
"""""""

README.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ via:
9696

9797
.. code-block:: bash
9898
99-
pip install --user "pycairo<2.0.0,>=1.10.0"
99+
pip install --user "pycairo==1.19.1"
100100
101101
If you are using Python 3.4, you will need a ``pip`` version <= 8. Run the following command, to downgrade ``pip``:
102102

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[build-system]
22
requires = [
3-
"setuptools >= 40.9.0"
3+
"setuptools==48.0.0"
44
]
55
build-backend = "setuptools.build_meta"

share/rafcon/examples/libraries/turtle_libraries/clear_field/clear_field_CLEAR_FIELD/meta_data.json

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
{
22
"gui": {
33
"editor_gaphas": {
4+
"background_color": {
5+
"__jsonqualname__": "__builtin__.tuple",
6+
"items": [
7+
0.0,
8+
0.0,
9+
0.0
10+
]
11+
},
12+
"custom_background_color": false,
413
"income": {
514
"rel_pos": {
6-
"__jsonqualname__": "__builtin__.tuple",
15+
"__jsonqualname__": "__builtin__.tuple",
716
"items": [
8-
0,
17+
0,
918
12.5
1019
]
1120
}
12-
},
21+
},
1322
"name": {
1423
"rel_pos": {
1524
"__jsonqualname__": "__builtin__.tuple",
@@ -42,6 +51,19 @@
4251
}
4352
}
4453
},
54+
"income": {
55+
"gui": {
56+
"editor_gaphas": {
57+
"rel_pos": {
58+
"__jsonqualname__": "__builtin__.tuple",
59+
"items": [
60+
0,
61+
12.5
62+
]
63+
}
64+
}
65+
}
66+
},
4567
"outcome-1": {
4668
"gui": {
4769
"editor_gaphas": {

source/rafcon/core/config.py

-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class ObservableConfig(DefaultConfig, Observable):
3636

3737
keys_requiring_state_machine_refresh = set()
3838
keys_requiring_restart = set()
39-
keys_not_to_fill_up = set()
4039

4140
def __init__(self, default_config_string, logger_object=None):
4241
DefaultConfig.__init__(self, default_config_string, logger_object, rel_config_path='rafcon')
@@ -90,7 +89,6 @@ class Config(ObservableConfig):
9089
"""
9190

9291
keys_requiring_restart = ()
93-
keys_not_to_fill_up = {"LIBRARY_PATHS"}
9492

9593
def __init__(self, logger_object=None):
9694
"""Default constructor

source/rafcon/core/custom_exceptions.py

+13
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,19 @@ def __init__(self, message):
2828
super(LibraryNotFoundException, self).__init__(message)
2929

3030

31+
class LibraryNotFoundSkipException(Exception):
32+
33+
def __init__(self, message):
34+
""" A custom exception for the case when a library is not found and user decided to skip loading the broken state machine
35+
36+
:param message: the error message for the exception
37+
:return:
38+
"""
39+
40+
# Call the base class constructor with the parameters it needs
41+
super(LibraryNotFoundSkipException, self).__init__(message)
42+
43+
3144
class RecoveryModeException(ValueError):
3245

3346
def __init__(self, message, do_delete_item):

source/rafcon/core/decorators.py

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def wraps_safely(obj, attr_names=functools.WRAPPER_ASSIGNMENTS):
2323
# Solves problem with missing attributes: http://stackoverflow.com/a/28752007
2424
return functools.wraps(obj, assigned=list(filter(functools.partial(hasattr, obj), attr_names)))
2525

26+
2627
global_lock_counter = 0
2728

2829

source/rafcon/core/execution/execution_engine.py

-2
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,6 @@ def _wait_for_finishing(self):
221221
self.__set_execution_mode_to_finished()
222222
self.state_machine_manager.active_state_machine_id = None
223223
plugins.run_on_state_machine_execution_finished()
224-
# self.__set_execution_mode_to_stopped()
225224
self.state_machine_running = False
226225

227226
def backward_step(self):
@@ -466,7 +465,6 @@ def handle_execution_mode(self, container_state, next_child_state_to_execute=Non
466465
"""
467466
with self.state_counter_lock:
468467
self.state_counter += 1
469-
# logger.verbose("Increase state_counter!" + str(self.state_counter))
470468

471469
woke_up_from_pause_or_step_mode = False
472470

source/rafcon/core/global_variable_manager.py

-13
Original file line numberDiff line numberDiff line change
@@ -315,18 +315,6 @@ def get_all_keys_starting_with(self, start_key):
315315
# Properties for all class fields that must be observed by gtkmvc3
316316
#########################################################################
317317

318-
@property
319-
def global_variable_dictionary(self):
320-
"""Property for the _global_variable_dictionary field"""
321-
dict_copy = {}
322-
for key, value in self.__global_variable_dictionary.items():
323-
if key in self.__variable_references and self.__variable_references[key]:
324-
dict_copy[key] = value
325-
else:
326-
dict_copy[key] = copy.deepcopy(value)
327-
328-
return dict_copy
329-
330318
def get_all_keys(self):
331319
"""Returns all variable names in the GVM
332320
@@ -355,7 +343,6 @@ def check_value_and_type(value, data_type):
355343
:return:
356344
"""
357345
if value is not None and data_type is not type(None):
358-
# if not isinstance(value, data_type):
359346
if not type_inherits_of_type(data_type, type(value)):
360347
raise TypeError(
361348
"Value: '{0}' is not of data type: '{1}', value type: {2}".format(value, data_type, type(value)))

source/rafcon/core/id_generator.py

-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import uuid
2323

2424
STATE_ID_LENGTH = 6
25-
RUN_ID_LENGTH = 10
2625
experiment_id = ''+str(uuid.uuid1())
2726

2827
state_name_counter = 0
@@ -34,7 +33,6 @@
3433
history_item_id_counter = 0
3534
semantic_data_id_counter = 0
3635

37-
used_run_ids = []
3836
used_global_variable_ids = []
3937

4038

source/rafcon/core/interface.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def save_folder_cmd_line(query, default_name=None, default_path=None):
9191
return user_input
9292

9393

94-
def show_notice(notice):
94+
def show_notice(notice, custom_buttons=None):
9595
"""Shows a notice on the console that has to be acknowledged
9696
9797
:param str notice: Notice to show to the user

source/rafcon/core/library_manager.py

+34-11
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@
2727

2828
from rafcon.core import interface
2929
from rafcon.core.storage import storage
30-
from rafcon.core.custom_exceptions import LibraryNotFoundException
30+
from rafcon.core.custom_exceptions import LibraryNotFoundException, LibraryNotFoundSkipException
3131
import rafcon.core.config as config
3232

3333
from rafcon.utils import log
3434
logger = log.get_logger(__name__)
3535

36+
SKIP = 10
37+
SKIP_ALL = 11
38+
3639

3740
@Singleton
3841
class LibraryManager(Observable):
@@ -60,11 +63,9 @@ def __init__(self):
6063
# a list to hold all library states that were skipped by the user during the replacement procedure
6164
self._skipped_states = []
6265
self._skipped_library_roots = []
63-
64-
# loaded libraries
6566
self._loaded_libraries = {}
66-
self._libraries_instances = {}
67-
67+
self._open_group_of_state_machines = False
68+
self._skip_all_broken_libraries = False
6869
self._show_dialog = True
6970

7071
@property
@@ -75,6 +76,22 @@ def show_dialog(self):
7576
def show_dialog(self, value):
7677
self._show_dialog = value
7778

79+
@property
80+
def open_group_of_state_machines(self):
81+
return self._open_group_of_state_machines
82+
83+
@open_group_of_state_machines.setter
84+
def open_group_of_state_machines(self, value):
85+
self._open_group_of_state_machines = value
86+
87+
@property
88+
def skip_all_broken_libraries(self):
89+
return self._skip_all_broken_libraries
90+
91+
@skip_all_broken_libraries.setter
92+
def skip_all_broken_libraries(self, value):
93+
self._skip_all_broken_libraries = value
94+
7895
def prepare_destruction(self):
7996
self.clean_loaded_libraries()
8097

@@ -178,7 +195,7 @@ def _load_nested_libraries(self, library_path, target_dict):
178195
:param target_dict: the target dictionary to store all loaded libraries to
179196
"""
180197
for library_name in os.listdir(library_path):
181-
library_folder_path, library_name = self.check_clean_path_of_library(library_path, library_name)
198+
_, library_name = self.check_clean_path_of_library(library_path, library_name)
182199
full_library_path = os.path.join(library_path, library_name)
183200
if os.path.isdir(full_library_path) and library_name[0] != '.':
184201
if os.path.exists(os.path.join(full_library_path, storage.STATEMACHINE_FILE)) \
@@ -271,7 +288,6 @@ def get_os_path_to_library(self, library_path, library_name, allow_user_interact
271288

272289
library_os_path = self._get_library_os_path_from_library_dict_tree(library_path, library_name)
273290
while library_os_path is None: # until the library is found or the user aborts
274-
275291
regularly_found = False
276292
new_library_os_path = None
277293
if allow_user_interaction and self.show_dialog:
@@ -281,9 +297,16 @@ def get_os_path_to_library(self, library_path, library_name, allow_user_interact
281297
"If your library_path is correct and the library was moved, please " \
282298
"select the new root/library_os_path folder of the library which should be situated within a "\
283299
"loaded library_root_path. If not, please abort.".format(library_name, library_path)
284-
interface.show_notice_func(notice)
285-
new_library_os_path = interface.open_folder_func("Select root folder for library name '{0}'"
286-
"".format(original_path_and_name))
300+
custom_buttons = (('Skip', SKIP), ('Skip All', SKIP_ALL)) if self.open_group_of_state_machines else None
301+
response = SKIP if self.skip_all_broken_libraries else interface.show_notice_func(notice, custom_buttons)
302+
if response == SKIP:
303+
raise LibraryNotFoundSkipException("Library '{0}' not found in sub-folder {1}".format(library_name, library_path))
304+
elif response == SKIP_ALL:
305+
self.skip_all_broken_libraries = True
306+
raise LibraryNotFoundSkipException("Library '{0}' not found in sub-folder {1}".format(library_name, library_path))
307+
else:
308+
new_library_os_path = interface.open_folder_func("Select root folder for library name '{0}'"
309+
"".format(original_path_and_name))
287310
if new_library_os_path is None:
288311
# User clicked cancel => cancel library search
289312
# If the library root path is existent (e.g. "generic") and only the specific library state is not (
@@ -390,7 +413,7 @@ def get_library_state_copy_instance(self, lib_os_path):
390413
if lib_os_path in self._loaded_libraries:
391414
# this list can also be taken to open library state machines TODO -> implement it -> because faster
392415
state_machine = self._loaded_libraries[lib_os_path]
393-
# as long as the a library state root state is never edited so the state first has to be copied here
416+
# as long as the library state root state is never edited so the state first has to be copied here
394417
state_copy = copy.deepcopy(state_machine.root_state)
395418
return state_machine.version, state_copy
396419
else:

source/rafcon/core/state_elements/scope.py

-9
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ def generate_time_stamp():
3737
return int(round(time.time() * 1000000))
3838

3939

40-
def get_human_readable_time(timestamp):
41-
"""
42-
Converts a timestamp to a human readable format.
43-
:param timestamp: the timestamp to be converted
44-
:return: the converted timestamp
45-
"""
46-
return datetime.datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
47-
48-
4940
class ScopedVariable(DataPort):
5041
"""A class for representing a scoped variable in a container state
5142

source/rafcon/core/state_elements/state_element.py

-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,6 @@ def __deepcopy__(self, memo=None, _nil=[]):
6161
raise NotImplementedError("__deepcopy__ method of class StateElement has to be implemented")
6262

6363
def _safe_init(self, parent):
64-
# uncomment this line when using LOAD_SM_WITH_CHECKS to check if unsafe_init triggers safe_init
65-
# raise Exception("Must not be executed during unsafe init")
6664
self.parent = parent
6765

6866
def _unsafe_init(self, parent):

source/rafcon/core/state_machine.py

-5
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ class StateMachine(Observable, JSONObject, Hashable):
5454
state_machine_id = None
5555
version = None
5656

57-
old_marked_dirty = True
58-
5957
_root_state = None
6058
_marked_dirty = True
6159
_file_system_path = None
@@ -189,8 +187,6 @@ def root_state(self):
189187
@root_state.setter
190188
@Observable.observed
191189
def root_state(self, root_state):
192-
# if not isinstance(root_state, State):
193-
# raise AttributeError("root_state has to be of type State")
194190
if root_state is not None:
195191
from rafcon.core.states.state import State
196192
if not isinstance(root_state, State):
@@ -241,7 +237,6 @@ def marked_dirty(self):
241237
def marked_dirty(self, marked_dirty):
242238
if not isinstance(marked_dirty, bool):
243239
raise AttributeError("marked_dirty has to be of type bool")
244-
self.old_marked_dirty = self._marked_dirty
245240
self._marked_dirty = marked_dirty
246241

247242
def get_state_by_path(self, path, as_check=False):

source/rafcon/core/state_machine_manager.py

-5
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ def has_dirty_state_machine(self):
7979
return True
8080
return False
8181

82-
def reset_dirty_flags(self):
83-
"""Set all marked_dirty flags of the state machine to false."""
84-
for sm_id, sm in self.state_machines.items():
85-
sm.marked_dirty = False
86-
8782
def is_state_machine_open(self, file_system_path):
8883
for loaded_sm in self._state_machines.values():
8984
if loaded_sm.file_system_path == file_system_path:

source/rafcon/core/states/concurrency_state.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,20 @@ def start_child_states(self, concurrency_history_item, do_not_start_state=None):
9999
state.concurrency_queue_id = index
100100

101101
state.generate_run_id()
102-
target_excution_history = None
102+
target_execution_history = None
103103
if not self.backward_execution:
104104
# In the case that execution logging is disabled there is no concurrency_history_item
105105
if concurrency_history_item:
106106
# care for the history items; this item is only for execution visualization
107107
concurrency_history_item.execution_histories[index].push_call_history_item(
108108
state, CallType.EXECUTE, self, state.input_data)
109-
target_excution_history = concurrency_history_item.execution_histories[index]
109+
target_execution_history = concurrency_history_item.execution_histories[index]
110110
else: # backward execution
111111
last_history_item = concurrency_history_item.execution_histories[index].pop_last_item()
112112
assert isinstance(last_history_item, ReturnItem)
113-
target_excution_history = concurrency_history_item.execution_histories[index]
113+
target_execution_history = concurrency_history_item.execution_histories[index]
114114

115-
state.start(target_excution_history, self.backward_execution, False)
115+
state.start(target_execution_history, self.backward_execution, False)
116116

117117
return concurrency_queue
118118

0 commit comments

Comments
 (0)