boris-behav-obs 9.3.5__tar.gz → 9.4.1__tar.gz

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.
Files changed (121) hide show
  1. {boris_behav_obs-9.3.5/boris_behav_obs.egg-info → boris_behav_obs-9.4.1}/PKG-INFO +1 -1
  2. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/about.py +5 -4
  3. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/config_file.py +1 -1
  4. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/converters.py +1 -3
  5. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/core.py +126 -116
  6. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/dialog.py +4 -25
  7. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/observation.py +8 -4
  8. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/observation_operations.py +2 -0
  9. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/player_dock_widget.py +0 -24
  10. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/utilities.py +170 -75
  11. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/version.py +2 -2
  12. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/write_event.py +11 -2
  13. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1/boris_behav_obs.egg-info}/PKG-INFO +1 -1
  14. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/pyproject.toml +2 -2
  15. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/LICENSE.TXT +0 -0
  16. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/MANIFEST.in +0 -0
  17. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/README.TXT +0 -0
  18. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/README.md +0 -0
  19. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/__init__.py +0 -0
  20. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/__main__.py +0 -0
  21. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/add_modifier.py +0 -0
  22. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/add_modifier_ui.py +0 -0
  23. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/advanced_event_filtering.py +0 -0
  24. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/analysis_plugins/__init__.py +0 -0
  25. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/analysis_plugins/_latency.py +0 -0
  26. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/analysis_plugins/number_of_occurences.py +0 -0
  27. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/analysis_plugins/number_of_occurences_by_independent_variable.py +0 -0
  28. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/analysis_plugins/time_budget.py +0 -0
  29. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/behav_coding_map_creator.py +0 -0
  30. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/behavior_binary_table.py +0 -0
  31. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/behaviors_coding_map.py +0 -0
  32. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/boris_cli.py +0 -0
  33. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/cmd_arguments.py +0 -0
  34. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/coding_pad.py +0 -0
  35. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/config.py +0 -0
  36. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/connections.py +0 -0
  37. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/converters_ui.py +0 -0
  38. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/cooccurence.py +0 -0
  39. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/core_qrc.py +0 -0
  40. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/core_ui.py +0 -0
  41. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/db_functions.py +0 -0
  42. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/dev.py +0 -0
  43. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/duration_widget.py +0 -0
  44. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/edit_event.py +0 -0
  45. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/edit_event_ui.py +0 -0
  46. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/event_operations.py +0 -0
  47. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/events_cursor.py +0 -0
  48. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/events_snapshots.py +0 -0
  49. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/exclusion_matrix.py +0 -0
  50. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/export_events.py +0 -0
  51. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/export_observation.py +0 -0
  52. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/external_processes.py +0 -0
  53. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/geometric_measurement.py +0 -0
  54. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/gui_utilities.py +0 -0
  55. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/image_overlay.py +0 -0
  56. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/import_observations.py +0 -0
  57. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/irr.py +0 -0
  58. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/latency.py +0 -0
  59. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/measurement_widget.py +0 -0
  60. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/media_file.py +0 -0
  61. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/menu_options.py +0 -0
  62. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/modifier_coding_map_creator.py +0 -0
  63. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/modifiers_coding_map.py +0 -0
  64. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/mpv-1.0.3.py +0 -0
  65. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/mpv.py +0 -0
  66. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/mpv2.py +0 -0
  67. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/observation_ui.py +0 -0
  68. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/observations_list.py +0 -0
  69. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/otx_parser.py +0 -0
  70. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/param_panel.py +0 -0
  71. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/param_panel_ui.py +0 -0
  72. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/plot_data_module.py +0 -0
  73. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/plot_events.py +0 -0
  74. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/plot_events_rt.py +0 -0
  75. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/plot_spectrogram_rt.py +0 -0
  76. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/plot_waveform_rt.py +0 -0
  77. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/plugins.py +0 -0
  78. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/portion/__init__.py +0 -0
  79. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/portion/const.py +0 -0
  80. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/portion/dict.py +0 -0
  81. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/portion/func.py +0 -0
  82. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/portion/interval.py +0 -0
  83. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/portion/io.py +0 -0
  84. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/preferences.py +0 -0
  85. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/preferences_ui.py +0 -0
  86. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/project.py +0 -0
  87. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/project_functions.py +0 -0
  88. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/project_import_export.py +0 -0
  89. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/project_ui.py +0 -0
  90. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/qrc_boris.py +0 -0
  91. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/qrc_boris5.py +0 -0
  92. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/select_modifiers.py +0 -0
  93. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/select_observations.py +0 -0
  94. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/select_subj_behav.py +0 -0
  95. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/state_events.py +0 -0
  96. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/subjects_pad.py +0 -0
  97. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/synthetic_time_budget.py +0 -0
  98. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/time_budget_functions.py +0 -0
  99. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/time_budget_widget.py +0 -0
  100. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/transitions.py +0 -0
  101. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/video_equalizer.py +0 -0
  102. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/video_equalizer_ui.py +0 -0
  103. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/video_operations.py +0 -0
  104. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/view_df.py +0 -0
  105. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris/view_df_ui.py +0 -0
  106. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris_behav_obs.egg-info/SOURCES.txt +0 -0
  107. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris_behav_obs.egg-info/dependency_links.txt +0 -0
  108. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris_behav_obs.egg-info/entry_points.txt +0 -0
  109. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris_behav_obs.egg-info/requires.txt +0 -0
  110. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/boris_behav_obs.egg-info/top_level.txt +0 -0
  111. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/setup.cfg +0 -0
  112. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_db_functions.py +0 -0
  113. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_export_observation.py +0 -0
  114. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_irr.py +0 -0
  115. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_observation_gui.py +0 -0
  116. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_otx_parser.py +0 -0
  117. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_preferences_gui.py +0 -0
  118. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_project_functions.py +0 -0
  119. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_time_budget.py +0 -0
  120. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_utilities.py +0 -0
  121. {boris_behav_obs-9.3.5 → boris_behav_obs-9.4.1}/tests/test_utilities2.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boris-behav-obs
3
- Version: 9.3.5
3
+ Version: 9.4.1
4
4
  Summary: BORIS - Behavioral Observation Research Interactive Software
5
5
  Author-email: Olivier Friard <olivier.friard@unito.it>
6
6
  License-Expression: GPL-3.0-only
@@ -31,7 +31,6 @@ from . import config as cfg
31
31
  from . import utilities as util
32
32
 
33
33
 
34
- from PySide6.QtCore import qVersion
35
34
  from PySide6.QtGui import QPixmap
36
35
  from PySide6.QtWidgets import QMessageBox
37
36
 
@@ -41,8 +40,6 @@ def actionAbout_activated(self):
41
40
  About dialog
42
41
  """
43
42
 
44
- import PySide6
45
-
46
43
  programs_versions: list = ["MPV media player"]
47
44
 
48
45
  mpv_lib_version, mpv_lib_file_path, mpv_api_version = util.mpv_lib_version()
@@ -108,6 +105,7 @@ def actionAbout_activated(self):
108
105
  '<a href="https://besjournals.onlinelibrary.wiley.com/doi/full/10.1111/2041-210X.12584">DOI:10.1111/2041-210X.12584</a>'
109
106
  )
110
107
  )
108
+ """
111
109
  n = "\n"
112
110
  current_system = platform.uname()
113
111
  details = (
@@ -123,8 +121,11 @@ def actionAbout_activated(self):
123
121
  f"Memory (RAM) Total: {memory.get('total_memory', 'Not available'):.2f} Mb "
124
122
  f"Free: {memory.get('free_memory', 'Not available'):.2f} Mb\n\n"
125
123
  )
124
+ """
125
+
126
+ details = util.get_systeminfo()
126
127
 
127
- details += n.join(programs_versions)
128
+ details += "\n".join(programs_versions)
128
129
  """
129
130
  memory_in_use = f"{utilities.rss_memory_used(self.pid)} Mb" if utilities.rss_memory_used(self.pid) != -1 else "Not available"
130
131
  percent_memory_in_use = (f"({utilities.rss_memory_percent_used(self.pid):.1f} % of total memory)"
@@ -72,7 +72,7 @@ def read(self):
72
72
  if not isinstance(self.saved_state, QByteArray):
73
73
  self.saved_state = None
74
74
 
75
- logging.debug(f"saved state: {self.saved_state}")
75
+ # logging.debug(f"saved state: {self.saved_state}")
76
76
 
77
77
  self.timeFormat = cfg.HHMMSS
78
78
  try:
@@ -22,8 +22,6 @@ This file is part of BORIS.
22
22
 
23
23
  import sys
24
24
  import json
25
- import urllib.error
26
- import urllib.parse
27
25
  import urllib.request
28
26
 
29
27
 
@@ -314,7 +312,7 @@ def load_converters_from_file_repo(self, mode: str):
314
312
  QMessageBox.critical(
315
313
  self,
316
314
  "BORIS",
317
- (f"The code of {converter_name} converter produces an error: " f"<br><b>{sys.exc_info()[1]}</b>"),
315
+ (f"The code of {converter_name} converter produces an error: <br><b>{sys.exc_info()[1]}</b>"),
318
316
  )
319
317
 
320
318
  self.tw_converters.setRowCount(self.tw_converters.rowCount() + 1)
@@ -19,34 +19,31 @@ This file is part of BORIS.
19
19
  along with this program; if not see <http://www.gnu.org/licenses/>.
20
20
 
21
21
  """
22
+ # ruff: noqa: E402
22
23
 
23
24
  import os
24
25
  import sys
26
+ from pathlib import Path
25
27
 
26
- os.environ["PATH"] = os.path.dirname(__file__) + os.sep + "misc" + os.pathsep + os.environ["PATH"]
28
+ # os.environ["PATH"] = os.path.dirname(__file__) + os.sep + "misc" + os.pathsep + os.environ["PATH"]
27
29
 
30
+ os.environ["PATH"] = str(Path(__file__).parent / "misc") + os.pathsep + os.environ["PATH"]
28
31
  sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), ".")))
29
32
 
30
-
31
33
  import datetime
32
-
33
34
  import json
34
35
  import logging
35
- import pathlib as pl
36
36
  import platform
37
37
  import re
38
38
  import PIL.Image
39
39
  import PIL.ImageEnhance
40
+ from PIL.ImageQt import Image
40
41
  import subprocess
41
-
42
42
  import locale
43
43
  import tempfile
44
44
  import time
45
- import urllib.error
46
- import urllib.parse
47
45
  import urllib.request
48
46
  from typing import Union, Tuple
49
-
50
47
  from decimal import Decimal as dec
51
48
  from decimal import ROUND_DOWN
52
49
  import gzip
@@ -57,7 +54,6 @@ import shutil
57
54
 
58
55
  matplotlib.use("QtAgg")
59
56
 
60
- import PySide6
61
57
  from PySide6.QtCore import (
62
58
  Qt,
63
59
  QPoint,
@@ -66,7 +62,6 @@ from PySide6.QtCore import (
66
62
  QDateTime,
67
63
  QUrl,
68
64
  QAbstractTableModel,
69
- qVersion,
70
65
  QElapsedTimer,
71
66
  QSettings,
72
67
  )
@@ -88,7 +83,28 @@ from PySide6.QtWidgets import (
88
83
  QStyledItemDelegate,
89
84
  QTableWidgetItem,
90
85
  )
91
- from PIL.ImageQt import Image
86
+
87
+
88
+ from . import cmd_arguments
89
+
90
+ # parse command line arguments
91
+ (options, args) = cmd_arguments.parse_arguments()
92
+
93
+ # set logging parameters
94
+ if options.debug:
95
+ logging.basicConfig(
96
+ format="%(asctime)s,%(msecs)d %(module)s l.%(lineno)d %(levelname)s %(message)s",
97
+ datefmt="%H:%M:%S",
98
+ level=logging.DEBUG,
99
+ )
100
+ else:
101
+ logging.basicConfig(
102
+ format="%(asctime)s,%(msecs)d %(message)s",
103
+ datefmt="%H:%M:%S",
104
+ level=logging.INFO,
105
+ )
106
+
107
+ from . import utilities as util
92
108
 
93
109
  from . import dialog
94
110
  from . import gui_utilities
@@ -105,21 +121,15 @@ from . import plot_waveform_rt
105
121
  from . import plot_events_rt
106
122
  from . import plugins
107
123
  from . import project_functions
108
-
109
124
  from . import select_observations
110
125
  from . import subjects_pad
111
126
  from . import version
112
127
  from . import event_operations
113
- from . import cmd_arguments
114
-
115
128
  from . import core_qrc
116
129
  from .core_ui import Ui_MainWindow
117
130
  from . import config as cfg
118
131
  from . import video_operations
119
-
120
132
  from . import project
121
- from . import utilities as util
122
-
123
133
  from . import menu_options as menu_options
124
134
  from . import connections as connections
125
135
  from . import config_file
@@ -128,7 +138,7 @@ from . import observation_operations
128
138
  from . import write_event
129
139
 
130
140
 
131
- # matplotlib.pyplot.switch_backend("Qt5Agg")
141
+ logging.debug("test")
132
142
 
133
143
  __version__ = version.__version__
134
144
  __version_date__ = version.__version_date__
@@ -143,44 +153,13 @@ if util.versiontuple(platform.python_version()) < util.versiontuple(MIN_PYTHON_V
143
153
  if sys.platform == "darwin": # for MacOS
144
154
  os.environ["LC_ALL"] = "en_US.UTF-8"
145
155
 
146
- # parse command line arguments
147
- (options, args) = cmd_arguments.parse_arguments()
148
-
149
- # set logging parameters
150
- if options.debug:
151
- logging.basicConfig(
152
- format="%(asctime)s,%(msecs)d %(module)s l.%(lineno)d %(levelname)s %(message)s",
153
- datefmt="%H:%M:%S",
154
- level=logging.DEBUG,
155
- )
156
- else:
157
- logging.basicConfig(
158
- format="%(asctime)s,%(msecs)d %(message)s",
159
- datefmt="%H:%M:%S",
160
- level=logging.INFO,
161
- )
162
156
 
163
157
  if options.version:
164
158
  print(f"version {__version__} release date: {__version_date__}")
165
159
  sys.exit(0)
166
160
 
167
-
168
161
  logging.debug("BORIS started")
169
- logging.info(f"BORIS version {__version__} release date: {__version_date__}")
170
- logging.info(f"Operating system: {platform.uname().system} {platform.uname().release} {platform.uname().version}")
171
- logging.info(f"CPU: {platform.uname().machine} {platform.uname().processor}")
172
- logging.info(f"Python {platform.python_version()} ({'64-bit' if sys.maxsize > 2**32 else '32-bit'})")
173
- logging.info(f"Qt {qVersion()} - PySide {PySide6.__version__}")
174
-
175
-
176
- (r, memory) = util.mem_info()
177
- if not r:
178
- logging.info(
179
- (
180
- f"Memory (RAM) Total: {memory.get('total_memory', 'Not available'):.2f} Mb "
181
- f"Free: {memory.get('free_memory', 'Not available'):.2f} Mb"
182
- )
183
- )
162
+ logging.info(util.get_systeminfo())
184
163
 
185
164
 
186
165
  def excepthook(exception_type, exception_value, traceback_object):
@@ -1044,8 +1023,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1044
1023
  tmp_dir = self.ffmpeg_cache_dir if self.ffmpeg_cache_dir and os.path.isdir(self.ffmpeg_cache_dir) else tempfile.gettempdir()
1045
1024
 
1046
1025
  wav_file_path = (
1047
- pl.Path(tmp_dir)
1048
- / pl.Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"] + ".wav").name
1026
+ Path(tmp_dir) / Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"] + ".wav").name
1049
1027
  )
1050
1028
 
1051
1029
  self.spectro = plot_spectrogram_rt.Plot_spectrogram_RT()
@@ -1134,8 +1112,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1134
1112
  tmp_dir = self.ffmpeg_cache_dir if self.ffmpeg_cache_dir and os.path.isdir(self.ffmpeg_cache_dir) else tempfile.gettempdir()
1135
1113
 
1136
1114
  wav_file_path = (
1137
- pl.Path(tmp_dir)
1138
- / pl.Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"] + ".wav").name
1115
+ Path(tmp_dir) / Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"] + ".wav").name
1139
1116
  )
1140
1117
 
1141
1118
  self.waveform = plot_waveform_rt.Plot_waveform_RT()
@@ -1245,8 +1222,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1245
1222
 
1246
1223
  try:
1247
1224
  wav_file_path = str(
1248
- pl.Path(tmp_dir)
1249
- / pl.Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"] + ".wav").name
1225
+ Path(tmp_dir) / Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"] + ".wav").name
1250
1226
  )
1251
1227
  except Exception:
1252
1228
  return
@@ -1362,7 +1338,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1362
1338
  try:
1363
1339
  last_version = urllib.request.urlopen(version_URL).read().strip().decode("utf-8")
1364
1340
  except Exception:
1365
- QMessageBox.warning(self, cfg.programName, "Can not check for updates...")
1341
+ QMessageBox.warning(self, cfg.programName, "Can not check for updates. Check your connection.")
1366
1342
  return
1367
1343
 
1368
1344
  # record check timestamp
@@ -1394,7 +1370,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1394
1370
  return
1395
1371
 
1396
1372
  # check if a .git is present
1397
- if (pl.Path(__file__).parent.parent / pl.Path(".git")).is_dir():
1373
+ if (Path(__file__).parent.parent / Path(".git")).is_dir():
1398
1374
  QMessageBox.critical(self, cfg.programName, "A .git directory is present, BORIS cannot be automatically updated.")
1399
1375
  return
1400
1376
 
@@ -1424,7 +1400,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1424
1400
 
1425
1401
  # copy from temp dir to current BORIS dir
1426
1402
  try:
1427
- shutil.copytree(f"{temp_dir.name}/BORIS-{last_version}", pl.Path(__file__).parent.parent, dirs_exist_ok=True)
1403
+ shutil.copytree(f"{temp_dir.name}/BORIS-{last_version}", Path(__file__).parent.parent, dirs_exist_ok=True)
1428
1404
  except Exception:
1429
1405
  QMessageBox.critical(self, cfg.programName, "A problem occurred during the copy the new version of BORIS.")
1430
1406
  return
@@ -1547,15 +1523,15 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1547
1523
  if self.image_idx == 0:
1548
1524
  return
1549
1525
 
1550
- current_dir = pl.Path(self.images_list[self.image_idx]).parent
1526
+ current_dir = Path(self.images_list[self.image_idx]).parent
1551
1527
  for image_path in self.images_list[self.image_idx - 1 :: -1]:
1552
- if pl.Path(image_path).parent != current_dir:
1528
+ if Path(image_path).parent != current_dir:
1553
1529
  self.image_idx = self.images_list.index(image_path)
1554
1530
 
1555
1531
  # seek to first image of directory
1556
- current_dir2 = pl.Path(self.images_list[self.image_idx]).parent
1532
+ current_dir2 = Path(self.images_list[self.image_idx]).parent
1557
1533
  for image_path2 in self.images_list[self.image_idx - 1 :: -1]:
1558
- if pl.Path(image_path2).parent != current_dir2:
1534
+ if Path(image_path2).parent != current_dir2:
1559
1535
  self.image_idx = self.images_list.index(image_path2) + 1
1560
1536
  break
1561
1537
  if self.images_list.index(image_path2) == 0:
@@ -1592,9 +1568,9 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1592
1568
  if self.playerType == cfg.IMAGES:
1593
1569
  if len(self.pj[cfg.OBSERVATIONS][self.observationId].get(cfg.DIRECTORIES_LIST, [])) <= 1:
1594
1570
  return
1595
- current_dir = pl.Path(self.images_list[self.image_idx]).parent
1571
+ current_dir = Path(self.images_list[self.image_idx]).parent
1596
1572
  for image_path in self.images_list[self.image_idx + 1 :]:
1597
- if pl.Path(image_path).parent != current_dir:
1573
+ if Path(image_path).parent != current_dir:
1598
1574
  self.image_idx = self.images_list.index(image_path)
1599
1575
  self.extract_frame(self.dw_player[0])
1600
1576
  break
@@ -1727,8 +1703,8 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1727
1703
  msg += f"<br>Time from 1st image: <b>{seconds_from_1st_formated}</b>"
1728
1704
 
1729
1705
  # image path
1730
- msg += f"<br><br>Directory: <b>{pl.Path(self.images_list[self.image_idx]).parent}</b>"
1731
- msg += f"<br>File name: <b>{pl.Path(self.images_list[self.image_idx]).name}</b>"
1706
+ msg += f"<br><br>Directory: <b>{Path(self.images_list[self.image_idx]).parent}</b>"
1707
+ msg += f"<br>File name: <b>{Path(self.images_list[self.image_idx]).name}</b>"
1732
1708
  msg += f"<br><small>Image resolution: <b>{pixmap.size().width()}x{pixmap.size().height()}</b></small>"
1733
1709
 
1734
1710
  self.lb_current_media_time.setText(msg)
@@ -1840,16 +1816,16 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1840
1816
  if self.pj[cfg.OBSERVATIONS][self.observationId][cfg.TYPE] == cfg.IMAGES:
1841
1817
  pixmap = QPixmap(self.images_list[self.image_idx])
1842
1818
  # draw measurements
1843
- RADIUS = 6
1819
+ # RADIUS = 6
1844
1820
  painter = QPainter()
1845
1821
  painter.begin(pixmap)
1846
1822
  for element in self.measurement_w.draw_mem.get(self.image_idx, []):
1847
1823
  painter = draw_element(painter, element)
1848
1824
  painter.end()
1849
1825
 
1850
- image_file_path = str(pl.Path(output_dir) / f"{pl.Path(self.images_list[self.image_idx]).stem}.jpg")
1826
+ image_file_path = str(Path(output_dir) / f"{Path(self.images_list[self.image_idx]).stem}.jpg")
1851
1827
  # check if file already exists
1852
- if pl.Path(image_file_path).is_file():
1828
+ if Path(image_file_path).is_file():
1853
1829
  if (
1854
1830
  dialog.MessageDialog(cfg.programName, f"The file {image_file_path} already exists.", (cfg.CANCEL, cfg.OVERWRITE))
1855
1831
  == cfg.CANCEL
@@ -1862,11 +1838,11 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1862
1838
  for n_player, dw in enumerate(self.dw_player):
1863
1839
  pixmap = util.pil2pixmap(dw.player.screenshot_raw())
1864
1840
 
1865
- p = pl.Path(dw.player.playlist[dw.player.playlist_pos]["filename"])
1866
- image_file_path = str(pl.Path(output_dir) / f"{p.stem}_{n_player}_{dw.player.estimated_frame_number:06}.jpg")
1841
+ p = Path(dw.player.playlist[dw.player.playlist_pos]["filename"])
1842
+ image_file_path = str(Path(output_dir) / f"{p.stem}_{n_player}_{dw.player.estimated_frame_number:06}.jpg")
1867
1843
 
1868
1844
  # draw measurements
1869
- RADIUS = 6
1845
+ # RADIUS = 6
1870
1846
  painter = QPainter()
1871
1847
  painter.begin(pixmap)
1872
1848
 
@@ -1877,7 +1853,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1877
1853
 
1878
1854
  painter.end()
1879
1855
  # check if file already exists
1880
- if pl.Path(image_file_path).is_file():
1856
+ if Path(image_file_path).is_file():
1881
1857
  if (
1882
1858
  dialog.MessageDialog(
1883
1859
  cfg.programName, f"The file {image_file_path} already exists.", (cfg.CANCEL, cfg.OVERWRITE)
@@ -1894,16 +1870,16 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1894
1870
  pixmap = QPixmap(self.images_list[frame_idx])
1895
1871
 
1896
1872
  # draw measurements
1897
- RADIUS = 6
1873
+ # RADIUS = 6
1898
1874
  painter = QPainter()
1899
1875
  painter.begin(pixmap)
1900
1876
  for element in self.measurement_w.draw_mem.get(frame_idx, []):
1901
1877
  painter = draw_element(painter, element)
1902
1878
  painter.end()
1903
1879
 
1904
- image_file_path = str(pl.Path(output_dir) / f"{pl.Path(self.images_list[frame_idx]).stem}.jpg")
1880
+ image_file_path = str(Path(output_dir) / f"{Path(self.images_list[frame_idx]).stem}.jpg")
1905
1881
  # check if file already exists
1906
- if pl.Path(image_file_path).is_file():
1882
+ if Path(image_file_path).is_file():
1907
1883
  if (
1908
1884
  dialog.MessageDialog(
1909
1885
  cfg.programName, f"The file {image_file_path} already exists.", (cfg.CANCEL, cfg.OVERWRITE)
@@ -1926,10 +1902,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1926
1902
 
1927
1903
  for frame_idx in d:
1928
1904
  for n_player in d[frame_idx]:
1929
- media_path = pl.Path(
1905
+ media_path = Path(
1930
1906
  self.dw_player[n_player - 1].player.playlist[self.dw_player[n_player - 1].player.playlist_pos]["filename"]
1931
1907
  )
1932
- file_name = pl.Path(f"{media_path.stem}_{element['player']}_{frame_idx:06}")
1908
+ file_name = Path(f"{media_path.stem}_{element['player']}_{frame_idx:06}")
1933
1909
 
1934
1910
  ffmpeg_command = [
1935
1911
  self.ffmpeg_bin,
@@ -1940,14 +1916,14 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1940
1916
  rf"select=gte(n\, {frame_idx})",
1941
1917
  "-frames:v",
1942
1918
  "1",
1943
- str(pl.Path(output_dir) / file_name.with_suffix(".jpg")),
1919
+ str(Path(output_dir) / file_name.with_suffix(".jpg")),
1944
1920
  ]
1945
1921
 
1946
1922
  p = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # do not use shell=True!
1947
1923
  out, error = p.communicate()
1948
1924
 
1949
- pixmap = QPixmap(str(pl.Path(output_dir) / file_name.with_suffix(".jpg")))
1950
- RADIUS = 6
1925
+ pixmap = QPixmap(str(Path(output_dir) / file_name.with_suffix(".jpg")))
1926
+ # RADIUS = 6
1951
1927
  painter = QPainter()
1952
1928
  painter.begin(pixmap)
1953
1929
 
@@ -1956,10 +1932,10 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1956
1932
 
1957
1933
  painter.end()
1958
1934
  # check if file already exists
1959
- if (pl.Path(output_dir) / file_name.with_suffix(".jpg")).is_file():
1935
+ if (Path(output_dir) / file_name.with_suffix(".jpg")).is_file():
1960
1936
  answer = dialog.MessageDialog(
1961
1937
  cfg.programName,
1962
- f"The file {pl.Path(output_dir) / file_name.with_suffix('.jpg')} already exists.",
1938
+ f"The file {Path(output_dir) / file_name.with_suffix('.jpg')} already exists.",
1963
1939
  (cfg.CANCEL, cfg.OVERWRITE, "Abort"),
1964
1940
  )
1965
1941
  if answer == cfg.CANCEL:
@@ -1967,7 +1943,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
1967
1943
  if answer == "Abort":
1968
1944
  return
1969
1945
 
1970
- pixmap.save(str(pl.Path(output_dir) / file_name.with_suffix(".jpg")), "JPG")
1946
+ pixmap.save(str(Path(output_dir) / file_name.with_suffix(".jpg")), "JPG")
1971
1947
 
1972
1948
  def resize_dw(self, dw_id):
1973
1949
  """
@@ -2441,7 +2417,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2441
2417
  """
2442
2418
  self.menuRecent_projects.clear()
2443
2419
  for project_file_path in self.recent_projects:
2444
- if pl.Path(project_file_path).is_file():
2420
+ if Path(project_file_path).is_file():
2445
2421
  action = QAction(self, visible=False, triggered=self.open_project_activated)
2446
2422
  action.setText(project_file_path)
2447
2423
  action.setVisible(True)
@@ -2772,7 +2748,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
2772
2748
  self.projectChanged = project_changed
2773
2749
  self.load_behaviors_in_twEthogram([self.pj[cfg.ETHOGRAM][x][cfg.BEHAVIOR_CODE] for x in self.pj[cfg.ETHOGRAM]])
2774
2750
  self.load_subjects_in_twSubjects([self.pj[cfg.SUBJECTS][x][cfg.SUBJECT_NAME] for x in self.pj[cfg.SUBJECTS]])
2775
- self.projectFileName = str(pl.Path(project_path).absolute())
2751
+ self.projectFileName = str(Path(project_path).absolute())
2776
2752
  self.project = True
2777
2753
  if str(self.projectFileName) not in self.recent_projects:
2778
2754
  self.recent_projects = [str(self.projectFileName)] + self.recent_projects
@@ -3356,7 +3332,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3356
3332
  project_new_file_name = os.path.splitext(os.path.splitext(project_new_file_name)[0])[0]
3357
3333
  project_new_file_name += ".boris"
3358
3334
  # check if file name with extension already exists
3359
- if pl.Path(project_new_file_name).is_file():
3335
+ if Path(project_new_file_name).is_file():
3360
3336
  if (
3361
3337
  dialog.MessageDialog(
3362
3338
  cfg.programName,
@@ -3372,7 +3348,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3372
3348
  project_new_file_name = os.path.splitext(project_new_file_name)[0]
3373
3349
  project_new_file_name += ".boris.gz"
3374
3350
  # check if file name with extension already exists
3375
- if pl.Path(project_new_file_name).is_file():
3351
+ if Path(project_new_file_name).is_file():
3376
3352
  if (
3377
3353
  dialog.MessageDialog(
3378
3354
  cfg.programName,
@@ -3452,7 +3428,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3452
3428
  self.projectFileName = os.path.splitext(os.path.splitext(self.projectFileName)[0])[0]
3453
3429
  self.projectFileName += ".boris"
3454
3430
  # check if file name with extension already exists
3455
- if pl.Path(self.projectFileName).is_file():
3431
+ if Path(self.projectFileName).is_file():
3456
3432
  if (
3457
3433
  dialog.MessageDialog(
3458
3434
  cfg.programName,
@@ -3471,7 +3447,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
3471
3447
 
3472
3448
  self.projectFileName += ".boris.gz"
3473
3449
  # check if file name with extension already exists
3474
- if pl.Path(self.projectFileName).is_file():
3450
+ if Path(self.projectFileName).is_file():
3475
3451
  if (
3476
3452
  dialog.MessageDialog(
3477
3453
  cfg.programName,
@@ -4065,14 +4041,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4065
4041
  """
4066
4042
  enable or disable video if any and audio if any
4067
4043
  """
4068
- # if video
4069
- # print(f"{n_player=} {enable=}")
4070
- # print(f"{self.dw_player[n_player].player.video_format=}")
4071
- # print(f"{self.dw_player[n_player].player.audio_bitrate=}")
4072
-
4073
- # self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.HAS_VIDEO][]
4074
- # if self.dw_player[n_player].player.playlist_pos is not None:
4075
- # print(self.dw_player[n_player].player.playlist[self.dw_player[n_player].player.playlist_pos]["filename"])
4076
4044
 
4077
4045
  if self.dw_player[n_player].player.video_format:
4078
4046
  self.dw_player[n_player].stack.setCurrentIndex(1 if not enable else 0)
@@ -4266,7 +4234,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
4266
4234
 
4267
4235
  # current media name
4268
4236
  if self.dw_player[0].player.playlist_pos is not None:
4269
- current_media_name = pl.Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"]).name
4237
+ current_media_name = Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"]).name
4270
4238
  current_playlist_index = self.dw_player[0].player.playlist_pos
4271
4239
  else:
4272
4240
  current_media_name = ""
@@ -5165,7 +5133,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
5165
5133
  ),
5166
5134
  )
5167
5135
  return
5168
- media_file_name = self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"]
5136
+ media_file_name = Path(self.dw_player[0].player.playlist[self.dw_player[0].player.playlist_pos]["filename"]).as_posix()
5169
5137
 
5170
5138
  time_ -= self.pj[cfg.OBSERVATIONS][self.observationId][cfg.MEDIA_INFO][cfg.MEDIA_CREATION_TIME][media_file_name]
5171
5139
 
@@ -5709,21 +5677,54 @@ def main():
5709
5677
 
5710
5678
  locale.setlocale(locale.LC_NUMERIC, "C")
5711
5679
 
5712
- # splashscreen
5713
- # no splashscreen for Mac because it can mask the first use dialog box
5714
-
5715
- if (not options.nosplashscreen) and (sys.platform != "darwin"):
5716
- start = time.time()
5717
- splash = QSplashScreen(QPixmap(":/splash"))
5718
- splash.show()
5719
- splash.raise_()
5720
- app.processEvents()
5721
- while time.time() - start < 1:
5722
- time.sleep(0.001)
5723
-
5724
5680
  # check FFmpeg
5725
5681
  ret, msg = util.check_ffmpeg_path()
5726
5682
  if not ret:
5683
+ if sys.platform.startswith("win"):
5684
+ QMessageBox.warning(
5685
+ None,
5686
+ cfg.programName,
5687
+ "FFmpeg is not available.<br>It will be downloaded",
5688
+ QMessageBox.Ok | QMessageBox.Default,
5689
+ QMessageBox.NoButton,
5690
+ )
5691
+
5692
+ # download ffmpeg and ffprobe from https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/
5693
+ url = "https://github.com/boris-behav-obs/boris-behav-obs.github.io/releases/download/files/"
5694
+
5695
+ # search where to download ffmpeg
5696
+ ffmpeg_dir = Path(__file__).parent / "misc"
5697
+
5698
+ logging.debug(f"{ffmpeg_dir=}")
5699
+
5700
+ if not ffmpeg_dir.is_dir():
5701
+ logging.info(f"Creating {ffmpeg_dir} directory")
5702
+ ffmpeg_dir.mkdir(parents=True, exist_ok=True)
5703
+
5704
+ for file_ in ("ffmpeg.exe", "ffprobe.exe"):
5705
+ local_filename = ffmpeg_dir / file_
5706
+ logging.info(f"Downloading {file_}...")
5707
+ try:
5708
+ urllib.request.urlretrieve(url + file_, local_filename)
5709
+ except Exception:
5710
+ logging.critical("The FFmpeg program can not be downloaded! Check your connection.")
5711
+ QMessageBox.warning(
5712
+ None,
5713
+ cfg.programName,
5714
+ "The FFmpeg program can not be downloaded!\nCheck your connection.",
5715
+ QMessageBox.Ok | QMessageBox.Default,
5716
+ QMessageBox.NoButton,
5717
+ )
5718
+ sys.exit(3)
5719
+
5720
+ logging.info(f"File downloaded as {local_filename}")
5721
+
5722
+ # re-test for ffmpeg
5723
+ ret, msg = util.check_ffmpeg_path()
5724
+
5725
+ if ret:
5726
+ ffmpeg_bin = msg
5727
+ else:
5727
5728
  QMessageBox.critical(
5728
5729
  None,
5729
5730
  cfg.programName,
@@ -5732,8 +5733,17 @@ def main():
5732
5733
  QMessageBox.NoButton,
5733
5734
  )
5734
5735
  sys.exit(3)
5735
- else:
5736
- ffmpeg_bin = msg
5736
+
5737
+ # splashscreen
5738
+ # no splashscreen for Mac because it can mask the first use dialog box
5739
+ if (not options.nosplashscreen) and (sys.platform != "darwin"):
5740
+ start = time.time()
5741
+ splash = QSplashScreen(QPixmap(":/splash"))
5742
+ splash.show()
5743
+ splash.raise_()
5744
+ app.processEvents()
5745
+ while time.time() - start < 1:
5746
+ time.sleep(0.001)
5737
5747
 
5738
5748
  app.setApplicationName(cfg.programName)
5739
5749
 
@@ -5771,7 +5781,7 @@ def main():
5771
5781
  # check project integrity
5772
5782
  # read config
5773
5783
  config_param: dict = {}
5774
- ini_file_path = pl.Path.home() / pl.Path(".boris")
5784
+ ini_file_path = Path.home() / Path(".boris")
5775
5785
  if ini_file_path.is_file():
5776
5786
  settings = QSettings(str(ini_file_path), QSettings.IniFormat)
5777
5787
  try:
@@ -26,7 +26,6 @@ import logging
26
26
  import math
27
27
  import pathlib as pl
28
28
  import platform
29
- import subprocess
30
29
  import sys
31
30
  import traceback
32
31
  from typing import Union
@@ -98,29 +97,11 @@ def global_error_message(exception_type, exception_value, traceback_object):
98
97
  Global error management
99
98
  save error using loggin.critical and stdout
100
99
  """
101
- import PySide6
102
-
103
- error_text: str = (
104
- f"BORIS version: {version.__version__}\n"
105
- f"OS: {platform.uname().system} {platform.uname().release} {platform.uname().version}\n"
106
- f"CPU: {platform.uname().machine} {platform.uname().processor}\n"
107
- f"Python {platform.python_version()} ({'64-bit' if sys.maxsize > 2**32 else '32-bit'})\n"
108
- f"Qt {qVersion()} - PySide {PySide6.__version__}\n"
109
- f"MPV library version: {util.mpv_lib_version()[0]}\n"
110
- f"MPV API version: {util.mpv_lib_version()[2]}\n"
111
- f"MPV library file path: {util.mpv_lib_version()[1]}\n\n"
112
- f"Error succeded at {dt.datetime.now():%Y-%m-%d %H:%M}\n\n"
113
- )
114
- error_text += "".join(traceback.format_exception(exception_type, exception_value, traceback_object))
115
100
 
116
- # system info
117
- systeminfo = ""
118
- if sys.platform.startswith("win"):
119
- systeminfo = subprocess.getoutput("systeminfo")
120
- if sys.platform.startswith("linux"):
121
- systeminfo = subprocess.getoutput("cat /etc/*rel*; uname -a")
122
-
123
- error_text += f"\n\nSystem info\n===========\n\n{systeminfo}"
101
+ error_text = "\n\nSystem info\n===========\n\n"
102
+ error_text += util.get_systeminfo()
103
+ error_text += f"Error succeded at {dt.datetime.now():%Y-%m-%d %H:%M}\n\n"
104
+ error_text += "".join(traceback.format_exception(exception_type, exception_value, traceback_object))
124
105
 
125
106
  # write to stdout
126
107
  logging.critical(error_text)
@@ -129,8 +110,6 @@ def global_error_message(exception_type, exception_value, traceback_object):
129
110
  try:
130
111
  with open(pl.Path.home() / "boris_error.log", "w") as f_error:
131
112
  f_error.write(error_text)
132
- f_error.write("\nSystem info:\n")
133
- f_error.write(systeminfo + "\n")
134
113
  except Exception:
135
114
  logging.critical(f"Impossible to write to {pl.Path.home() / 'boris_error.log'}")
136
115