diff --git a/boris/project.py b/boris/project.py index 7ead436a..5c8190d6 100644 --- a/boris/project.py +++ b/boris/project.py @@ -578,7 +578,7 @@ def convert_behaviors_keys_to_lower_case(self): # convert modifier shortcuts if self.twBehaviors.item(row, cfg.behavioursFields[cfg.MODIFIERS]).text(): modifiers_dict = ( - eval(self.twBehaviors.item(row, cfg.behavioursFields[cfg.MODIFIERS]).text()) + json.loads(self.twBehaviors.item(row, cfg.behavioursFields[cfg.MODIFIERS]).text()) if self.twBehaviors.item(row, cfg.behavioursFields[cfg.MODIFIERS]).text() else {} ) @@ -593,7 +593,7 @@ def convert_behaviors_keys_to_lower_case(self): except Exception: logging.warning("error during conversion of modifier short cut to lower case") - self.twBehaviors.item(row, cfg.behavioursFields[cfg.MODIFIERS]).setText(str(modifiers_dict)) + self.twBehaviors.item(row, cfg.behavioursFields[cfg.MODIFIERS]).setText(json.dumps(modifiers_dict)) def convert_subjects_keys_to_lower_case(self): """ @@ -796,7 +796,7 @@ def twBehaviors_cellDoubleClicked(self, row: int, column: int) -> None: else: QMessageBox.information(self, cfg.programName, "Change the behavior type on first column to select a coding map") - # check if double click on category + # check if double click on behavior type if column == cfg.behavioursFields["type"]: self.behavior_type_doubleclicked(row) @@ -808,6 +808,7 @@ def twBehaviors_cellDoubleClicked(self, row: int, column: int) -> None: if column == cfg.behavioursFields[cfg.BEHAVIOR_CATEGORY]: self.category_doubleclicked(row) + # check if double click on modifiers if column == cfg.behavioursFields[cfg.MODIFIERS]: # check if behavior has coding map if ( @@ -1735,12 +1736,6 @@ def check_ethogram(self) -> dict: QMessageBox.critical(self, cfg.programName, "Error removing leading/trailing spaces in modifiers") else: - """ - if row["modifiers"]: - row["modifiers"] = eval(row["modifiers"]) - else: - row["modifiers"] = {} - """ row["modifiers"] = json.loads(row["modifiers"]) if row["modifiers"] else {} else: row[field] = "" diff --git a/boris/project_import_export.py b/boris/project_import_export.py index 03eed6a4..7a77ce10 100644 --- a/boris/project_import_export.py +++ b/boris/project_import_export.py @@ -133,7 +133,7 @@ def export_ethogram(self) -> None: # modifiers if self.twBehaviors.item(r, cfg.behavioursFields[cfg.MODIFIERS]).text(): # modifiers a string - modifiers_dict = eval(self.twBehaviors.item(r, cfg.behavioursFields[cfg.MODIFIERS]).text()) + modifiers_dict = json.loads(self.twBehaviors.item(r, cfg.behavioursFields[cfg.MODIFIERS]).text()) modifiers_list = [] for key in modifiers_dict: values = ",".join(modifiers_dict[key]["values"]) @@ -350,19 +350,22 @@ def import_ethogram_from_dict(self, project: dict): item.setBackground(QColor(230, 230, 230)) else: - if field == cfg.MODIFIERS and isinstance(project[cfg.ETHOGRAM][i][field], str): - modif_set_dict = {} - if project[cfg.ETHOGRAM][i][field]: - modif_set_list = project[cfg.ETHOGRAM][i][field].split("|") - for modif_set in modif_set_list: - modif_set_dict[str(len(modif_set_dict))] = { - "name": "", - "type": cfg.SINGLE_SELECTION, - "values": modif_set.split(","), - } - project[cfg.ETHOGRAM][i][field] = dict(modif_set_dict) - - item.setText(str(project[cfg.ETHOGRAM][i][field])) + if field == cfg.MODIFIERS: + if isinstance(project[cfg.ETHOGRAM][i][field], str): + modif_set_dict = {} + if project[cfg.ETHOGRAM][i][field]: + modif_set_list = project[cfg.ETHOGRAM][i][field].split("|") + for modif_set in modif_set_list: + modif_set_dict[str(len(modif_set_dict))] = { + "name": "", + "type": cfg.SINGLE_SELECTION, + "values": modif_set.split(","), + } + project[cfg.ETHOGRAM][i][field] = dict(modif_set_dict) + else: + item.setText(json.dumps(project[cfg.ETHOGRAM][i][field])) + else: + item.setText(project[cfg.ETHOGRAM][i][field]) if field not in cfg.ETHOGRAM_EDITABLE_FIELDS: item.setFlags(Qt.ItemIsEnabled) @@ -460,8 +463,11 @@ def load_dataframe_into_behaviors_tablewidget(self, df: pd.DataFrame) -> int: def import_behaviors_from_project(self): + """ + import ethogram from a BORIS project file + """ fn = QFileDialog().getOpenFileName( - self, "Import behaviors from project file", "", ("Project files (*.boris *.boris.gz);;" "All files (*)") + self, "Import behaviors from BORIS project file", "", ("Project files (*.boris *.boris.gz);;" "All files (*)") ) file_name = fn[0] if type(fn) is tuple else fn @@ -474,7 +480,7 @@ def import_behaviors_from_project(self): def import_behaviors_from_text_file(self): """ - Import behaviors from text file (CSV or TSV) + Import ethogram from text file (CSV or TSV) """ if self.twBehaviors.rowCount(): diff --git a/boris/version.py b/boris/version.py index 65f78073..f9392e86 100644 --- a/boris/version.py +++ b/boris/version.py @@ -20,5 +20,5 @@ """ -__version__ = "8.27.2" -__version_date__ = "2024-07-03" +__version__ = "8.27.3" +__version_date__ = "2024-08-19"