pygpt-net 2.6.3__py3-none-any.whl → 2.6.4__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.
Files changed (66) hide show
  1. pygpt_net/CHANGELOG.txt +5 -0
  2. pygpt_net/__init__.py +1 -1
  3. pygpt_net/config.py +55 -65
  4. pygpt_net/controller/chat/chat.py +38 -35
  5. pygpt_net/controller/chat/render.py +144 -217
  6. pygpt_net/controller/chat/stream.py +51 -25
  7. pygpt_net/controller/config/config.py +39 -42
  8. pygpt_net/controller/config/field/checkbox.py +16 -12
  9. pygpt_net/controller/config/field/checkbox_list.py +36 -31
  10. pygpt_net/controller/config/field/cmd.py +51 -57
  11. pygpt_net/controller/config/field/combo.py +33 -16
  12. pygpt_net/controller/config/field/dictionary.py +48 -55
  13. pygpt_net/controller/config/field/input.py +50 -32
  14. pygpt_net/controller/config/field/slider.py +40 -45
  15. pygpt_net/controller/config/field/textarea.py +20 -6
  16. pygpt_net/controller/config/placeholder.py +110 -231
  17. pygpt_net/controller/lang/mapping.py +57 -95
  18. pygpt_net/controller/lang/plugins.py +64 -55
  19. pygpt_net/controller/lang/settings.py +39 -38
  20. pygpt_net/controller/layout/layout.py +11 -2
  21. pygpt_net/controller/plugins/plugins.py +19 -1
  22. pygpt_net/controller/ui/mode.py +107 -125
  23. pygpt_net/core/bridge/bridge.py +5 -5
  24. pygpt_net/core/command/command.py +149 -219
  25. pygpt_net/core/ctx/ctx.py +94 -146
  26. pygpt_net/core/debug/debug.py +48 -58
  27. pygpt_net/core/models/models.py +74 -112
  28. pygpt_net/core/modes/modes.py +13 -21
  29. pygpt_net/core/plugins/plugins.py +154 -177
  30. pygpt_net/core/presets/presets.py +103 -176
  31. pygpt_net/core/render/web/body.py +2 -3
  32. pygpt_net/core/render/web/renderer.py +109 -180
  33. pygpt_net/core/text/utils.py +28 -44
  34. pygpt_net/core/tokens/tokens.py +104 -203
  35. pygpt_net/data/config/config.json +2 -2
  36. pygpt_net/data/config/models.json +2 -2
  37. pygpt_net/item/ctx.py +141 -139
  38. pygpt_net/plugin/agent/plugin.py +2 -1
  39. pygpt_net/plugin/audio_output/plugin.py +5 -2
  40. pygpt_net/plugin/base/plugin.py +77 -93
  41. pygpt_net/plugin/bitbucket/plugin.py +3 -2
  42. pygpt_net/plugin/cmd_code_interpreter/plugin.py +3 -2
  43. pygpt_net/plugin/cmd_custom/plugin.py +3 -2
  44. pygpt_net/plugin/cmd_files/plugin.py +3 -2
  45. pygpt_net/plugin/cmd_history/plugin.py +3 -2
  46. pygpt_net/plugin/cmd_mouse_control/plugin.py +5 -2
  47. pygpt_net/plugin/cmd_serial/plugin.py +3 -2
  48. pygpt_net/plugin/cmd_system/plugin.py +3 -6
  49. pygpt_net/plugin/cmd_web/plugin.py +3 -2
  50. pygpt_net/plugin/experts/plugin.py +2 -2
  51. pygpt_net/plugin/facebook/plugin.py +3 -4
  52. pygpt_net/plugin/github/plugin.py +4 -2
  53. pygpt_net/plugin/google/plugin.py +3 -3
  54. pygpt_net/plugin/idx_llama_index/plugin.py +3 -2
  55. pygpt_net/plugin/mailer/plugin.py +3 -5
  56. pygpt_net/plugin/openai_vision/plugin.py +3 -2
  57. pygpt_net/plugin/real_time/plugin.py +52 -60
  58. pygpt_net/plugin/slack/plugin.py +3 -4
  59. pygpt_net/plugin/telegram/plugin.py +3 -4
  60. pygpt_net/plugin/twitter/plugin.py +3 -4
  61. pygpt_net/ui/widget/textarea/web.py +18 -14
  62. {pygpt_net-2.6.3.dist-info → pygpt_net-2.6.4.dist-info}/METADATA +7 -2
  63. {pygpt_net-2.6.3.dist-info → pygpt_net-2.6.4.dist-info}/RECORD +66 -66
  64. {pygpt_net-2.6.3.dist-info → pygpt_net-2.6.4.dist-info}/LICENSE +0 -0
  65. {pygpt_net-2.6.3.dist-info → pygpt_net-2.6.4.dist-info}/WHEEL +0 -0
  66. {pygpt_net-2.6.3.dist-info → pygpt_net-2.6.4.dist-info}/entry_points.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  # GitHub: https://github.com/szczyglis-dev/py-gpt #
7
7
  # MIT License #
8
8
  # Created By : Marcin Szczygliński #
9
- # Updated Date: 2024.12.14 22:00:00 #
9
+ # Updated Date: 2025.08.15 23:00:00 #
10
10
  # ================================================== #
11
11
 
12
12
  import copy
@@ -36,18 +36,18 @@ class Plugins:
36
36
  'vision',
37
37
  'schedule'
38
38
  ]
39
- self.plugins = {}
40
- self.presets = {} # presets config
39
+ self.plugins: Dict[str, BasePlugin] = {}
40
+ self.presets: Dict[str, Any] = {} # presets config
41
41
  self.provider = JsonFileProvider(window)
42
42
 
43
- def is_registered(self, id: str) -> bool:
43
+ def is_registered(self, plugin_id: str) -> bool:
44
44
  """
45
45
  Check if plugin is registered
46
46
 
47
- :param id: plugin id
47
+ :param plugin_id: plugin id
48
48
  :return: True if registered
49
49
  """
50
- return id in self.plugins
50
+ return plugin_id in self.plugins
51
51
 
52
52
  def all(self) -> Dict[str, BasePlugin]:
53
53
  """
@@ -65,28 +65,28 @@ class Plugins:
65
65
  """
66
66
  return list(self.plugins.keys())
67
67
 
68
- def get(self, id: str) -> Optional[BasePlugin]:
68
+ def get(self, plugin_id: str) -> Optional[BasePlugin]:
69
69
  """
70
70
  Get plugin by id
71
71
 
72
- :param id: plugin id
72
+ :param plugin_id: plugin id
73
73
  :return: plugin instance
74
74
  """
75
- if self.is_registered(id):
76
- return self.plugins[id]
77
- return None
75
+ return self.plugins.get(plugin_id)
78
76
 
79
- def get_option(self, id: str, key: str) -> Any:
77
+ def get_option(self, plugin_id: str, key: str) -> Any:
80
78
  """
81
79
  Get plugin option
82
80
 
83
- :param id: plugin id
81
+ :param plugin_id: plugin id
84
82
  :param key: option key
85
83
  :return: option value
86
84
  """
87
- if self.is_registered(id):
88
- if key in self.plugins[id].options:
89
- return self.plugins[id].options[key]['value']
85
+ plugin = self.plugins.get(plugin_id)
86
+ if plugin and hasattr(plugin, 'options'):
87
+ opt = plugin.options.get(key)
88
+ if opt is not None:
89
+ return opt.get('value')
90
90
  return None
91
91
 
92
92
  def register(self, plugin: BasePlugin):
@@ -96,184 +96,183 @@ class Plugins:
96
96
  :param plugin: plugin instance
97
97
  """
98
98
  plugin.attach(self.window)
99
- id = plugin.id
100
- self.plugins[id] = plugin
99
+ plugin_id = plugin.id
100
+ self.plugins[plugin_id] = plugin
101
101
 
102
- # make copy of options
103
102
  if hasattr(plugin, 'options'):
104
- self.plugins[id].initial_options = copy.deepcopy(plugin.options)
103
+ self.plugins[plugin_id].initial_options = copy.deepcopy(plugin.options)
105
104
 
106
105
  try:
107
106
  removed = False
108
- plugins = self.window.core.config.get('plugins')
109
- if id in list(plugins.keys()):
110
- for key in list(plugins[id].keys()):
111
- if key in self.plugins[id].options:
112
- self.plugins[id].options[key]['value'] = plugins[id][key]
107
+ cfg = self.window.core.config
108
+ plugins_cfg = cfg.get('plugins')
109
+ if plugin_id in plugins_cfg:
110
+ p_cfg = plugins_cfg[plugin_id]
111
+ for key in list(p_cfg):
112
+ if hasattr(self.plugins[plugin_id], 'options') and key in self.plugins[plugin_id].options:
113
+ self.plugins[plugin_id].options[key]['value'] = p_cfg[key]
113
114
  else:
114
115
  removed = True
115
- del plugins[id][key]
116
+ del p_cfg[key]
116
117
 
117
- # remove invalid options
118
118
  if removed:
119
- self.window.core.config.save()
119
+ cfg.save()
120
120
 
121
- # register options (configure dict editors, etc.)
122
- self.register_options(id, self.plugins[id].options)
123
- # print("Loaded plugin: {}".format(plugin.name))
121
+ self.register_options(plugin_id, self.plugins[plugin_id].options if hasattr(self.plugins[plugin_id], 'options') else {})
124
122
  except Exception as e:
125
123
  self.window.core.debug.log(e)
126
- print('Error while loading plugin options: {}'.format(id))
124
+ print('Error while loading plugin options: {}'.format(plugin_id))
127
125
 
128
126
  def apply_all_options(self):
129
127
  """Apply all options to plugins"""
130
128
  removed = False
131
129
  user_config = self.window.core.config.get('plugins')
132
- for id in self.plugins:
133
- if hasattr(self.plugins[id], 'initial_options'):
134
- self.plugins[id].options = copy.deepcopy(self.plugins[id].initial_options) # copy
135
- if id in user_config:
136
- for key in user_config[id]:
137
- if key in self.plugins[id].options:
138
- self.plugins[id].options[key]['value'] = user_config[id][key]
130
+ for plugin_id, plugin in self.plugins.items():
131
+ if hasattr(plugin, 'initial_options'):
132
+ plugin.options = copy.deepcopy(plugin.initial_options)
133
+ if plugin_id in user_config:
134
+ ucfg = user_config[plugin_id]
135
+ for key in list(ucfg):
136
+ if hasattr(plugin, 'options') and key in plugin.options:
137
+ plugin.options[key]['value'] = ucfg[key]
139
138
  else:
140
139
  print("removed")
141
140
  removed = True
142
- del user_config[id][key]
141
+ del ucfg[key]
143
142
  if removed:
144
143
  self.window.core.config.save()
145
144
 
146
- def register_options(self, id: str, options: Dict[str, dict]):
145
+ def register_options(self, plugin_id: str, options: Dict[str, dict]):
147
146
  """
148
147
  Register plugin options
149
148
 
150
- :param id: plugin id
149
+ :param plugin_id: plugin id
151
150
  :param options: options dict
152
151
  """
153
- dict_types = ["dict", "cmd"]
154
- for key in options:
155
- option = options[key]
156
- if 'type' in option and option['type'] in dict_types:
157
- key_name = key
158
- if option['type'] == "cmd":
159
- key_name = key + ".params"
160
- parent = "plugin." + id
161
- option['label'] = key_name # option name
152
+ dict_types = ("dict", "cmd")
153
+ for key, option in options.items():
154
+ if option.get('type') in dict_types:
155
+ key_name = f"{key}.params" if option['type'] == "cmd" else key
156
+ parent = f"plugin.{plugin_id}"
157
+ option['label'] = key_name
162
158
  self.window.ui.dialogs.register_dictionary(key_name, parent, option)
163
159
 
164
- def unregister(self, id: str):
160
+ def unregister(self, plugin_id: str):
165
161
  """
166
162
  Unregister plugin
167
163
 
168
- :param id: plugin id
164
+ :param plugin_id: plugin id
169
165
  """
170
- if self.is_registered(id):
171
- self.plugins.pop(id)
166
+ self.plugins.pop(plugin_id, None)
172
167
 
173
- def enable(self, id: str):
168
+ def enable(self, plugin_id: str):
174
169
  """
175
170
  Enable plugin by ID
176
171
 
177
- :param id: plugin id
172
+ :param plugin_id: plugin id
178
173
  """
179
- if self.is_registered(id):
180
- self.plugins[id].enabled = True
181
- self.window.core.config.data['plugins_enabled'][id] = True
182
- self.window.core.config.save()
174
+ plugin = self.plugins.get(plugin_id)
175
+ if plugin:
176
+ plugin.enabled = True
177
+ cfg = self.window.core.config
178
+ cfg.data['plugins_enabled'][plugin_id] = True
179
+ cfg.save()
183
180
 
184
- def disable(self, id: str):
181
+ def disable(self, plugin_id: str):
185
182
  """
186
183
  Disable plugin by ID
187
184
 
188
- :param id: plugin id
185
+ :param plugin_id: plugin id
189
186
  """
190
- if self.is_registered(id):
191
- self.plugins[id].enabled = False
192
- self.window.core.config.data['plugins_enabled'][id] = False
193
- self.window.core.config.save()
187
+ plugin = self.plugins.get(plugin_id)
188
+ if plugin:
189
+ plugin.enabled = False
190
+ cfg = self.window.core.config
191
+ cfg.data['plugins_enabled'][plugin_id] = False
192
+ cfg.save()
194
193
 
195
- def destroy(self, id: str):
194
+ def destroy(self, plugin_id: str):
196
195
  """
197
196
  Destroy plugin workers (send stop signal)
198
197
 
199
- :param id: plugin id
198
+ :param plugin_id: plugin id
200
199
  """
201
- if self.is_registered(id):
202
- self.plugins[id].destroy()
200
+ plugin = self.plugins.get(plugin_id)
201
+ if plugin:
202
+ if hasattr(plugin, 'destroy'):
203
+ plugin.destroy()
203
204
 
204
- def has_options(self, id: str) -> bool:
205
+ def has_options(self, plugin_id: str) -> bool:
205
206
  """
206
207
  Check if plugin has options
207
208
 
208
- :param id: plugin id
209
+ :param plugin_id: plugin id
209
210
  :return: True if has options
210
211
  """
211
- if self.is_registered(id):
212
- return hasattr(self.plugins[id], 'options') and len(self.plugins[id].options) > 0
213
- return False
212
+ plugin = self.plugins.get(plugin_id)
213
+ return bool(plugin and hasattr(plugin, 'options') and len(plugin.options) > 0)
214
214
 
215
- def restore_options(self, id: str, all: bool = False):
215
+ def restore_options(self, plugin_id: str, all: bool = False):
216
216
  """
217
217
  Restore options to initial values
218
218
 
219
- :param id: plugin id
219
+ :param plugin_id: plugin id
220
220
  :param all: restore all options (including persisted)
221
221
  """
222
- options = []
223
- values = {}
224
- if not all:
225
- for key in self.plugins[id].options:
226
- if 'persist' in self.plugins[id].options[key] and self.plugins[id].options[key]['persist']:
227
- options.append(key)
222
+ plugin = self.plugins.get(plugin_id)
223
+ if not plugin:
224
+ return
228
225
 
229
- if not all:
230
- # store persisted values
231
- for key in options:
232
- values[key] = self.plugins[id].options[key]['value']
226
+ options_to_preserve: List[str] = []
227
+ values: Dict[str, Any] = {}
233
228
 
234
- # restore initial values
235
- if id in self.plugins:
236
- if hasattr(self.plugins[id], 'initial_options'):
237
- self.plugins[id].options = copy.deepcopy(self.plugins[id].initial_options) # copy
229
+ if not all and hasattr(plugin, 'options'):
230
+ for key, opt in plugin.options.items():
231
+ if 'persist' in opt and opt['persist']:
232
+ options_to_preserve.append(key)
233
+ for key in options_to_preserve:
234
+ values[key] = plugin.options[key]['value']
235
+
236
+ if hasattr(plugin, 'initial_options'):
237
+ plugin.options = copy.deepcopy(plugin.initial_options)
238
238
 
239
239
  if not all:
240
- # restore persisted values
241
- for key in options:
242
- self.plugins[id].options[key]['value'] = values[key]
240
+ for key in options_to_preserve:
241
+ plugin.options[key]['value'] = values[key]
243
242
 
244
- def get_name(self, id: str) -> str:
243
+ def get_name(self, plugin_id: str) -> str:
245
244
  """
246
245
  Get plugin name (translated)
247
246
 
248
- :param id: plugin id
247
+ :param plugin_id: plugin id
249
248
  :return: plugin name
250
249
  """
251
- plugin = self.get(id)
250
+ plugin = self.get(plugin_id)
252
251
  default = plugin.name
253
- trans_key = 'plugin.' + id
252
+ trans_key = f'plugin.{plugin_id}'
254
253
  name = trans(trans_key)
255
254
  if name == trans_key:
256
255
  name = default
257
256
  if plugin.use_locale:
258
- domain = 'plugin.{}'.format(id)
257
+ domain = f'plugin.{plugin_id}'
259
258
  name = trans('plugin.name', domain=domain)
260
259
  return name
261
260
 
262
- def get_desc(self, id: str) -> str:
261
+ def get_desc(self, plugin_id: str) -> str:
263
262
  """
264
263
  Get description (translated)
265
264
 
266
- :param id: plugin id
265
+ :param plugin_id: plugin id
267
266
  :return: plugin description
268
267
  """
269
- plugin = self.get(id)
268
+ plugin = self.get(plugin_id)
270
269
  default = plugin.description
271
- trans_key = 'plugin.' + id + '.description'
270
+ trans_key = f'plugin.{plugin_id}.description'
272
271
  tooltip = trans(trans_key)
273
272
  if tooltip == trans_key:
274
273
  tooltip = default
275
274
  if plugin.use_locale:
276
- domain = 'plugin.{}'.format(id)
275
+ domain = f'plugin.{plugin_id}'
277
276
  tooltip = trans('plugin.description', domain=domain)
278
277
  return tooltip
279
278
 
@@ -288,9 +287,9 @@ class Plugins:
288
287
  options['plugin.name'] = plugin.name
289
288
  options['plugin.description'] = plugin.description
290
289
 
291
- sorted_keys = sorted(plugin.options.keys())
292
- for key in sorted_keys:
293
- option = plugin.options[key]
290
+ plugin_options = getattr(plugin, 'options', {})
291
+ for key in sorted(plugin_options.keys()):
292
+ option = plugin_options[key]
294
293
  if 'label' in option:
295
294
  option_key = key + '.label'
296
295
  options[option_key] = option['label']
@@ -301,41 +300,39 @@ class Plugins:
301
300
  option_key = key + '.tooltip'
302
301
  options[option_key] = option['tooltip']
303
302
 
304
- # dump options to .ini file:
305
303
  ini = configparser.ConfigParser()
306
304
  ini['LOCALE'] = options
307
305
 
308
- # save with utf-8 encoding
309
306
  with io.open(path, mode="w", encoding="utf-8") as f:
310
307
  ini.write(f)
311
308
 
312
- def has_preset(self, id: str) -> bool:
309
+ def has_preset(self, preset_id: str) -> bool:
313
310
  """
314
311
  Check if preset exists
315
312
 
316
- :param id: preset id
313
+ :param preset_id: preset id
317
314
  :return: True if preset exists
318
315
  """
319
- return id in self.presets
316
+ return preset_id in self.presets
320
317
 
321
- def get_preset(self, id: str) -> Dict[str, Any]:
318
+ def get_preset(self, preset_id: str) -> Dict[str, Any]:
322
319
  """
323
320
  Get preset by id
324
321
 
325
- :param id: preset id
322
+ :param preset_id: preset id
326
323
  :return: preset dict
327
324
  """
328
- if self.has_preset(id):
329
- return self.presets[id]
325
+ if self.has_preset(preset_id):
326
+ return self.presets[preset_id]
330
327
 
331
- def set_preset(self, id: str, preset: Dict[str, Any]):
328
+ def set_preset(self, preset_id: str, preset: Dict[str, Any]):
332
329
  """
333
330
  Set config value
334
331
 
335
- :param id: id
332
+ :param preset_id: id
336
333
  :param preset: preset
337
334
  """
338
- self.presets[id] = preset
335
+ self.presets[preset_id] = preset
339
336
 
340
337
  def replace_presets(self, presets: Dict[str, Any]):
341
338
  """
@@ -357,11 +354,7 @@ class Plugins:
357
354
  """
358
355
  return self.presets
359
356
 
360
- def reset_options(
361
- self,
362
- plugin_id: str,
363
- keys: List[str]
364
- ):
357
+ def reset_options(self, plugin_id: str, keys: List[str]):
365
358
  """
366
359
  Reset plugin options
367
360
 
@@ -370,9 +363,9 @@ class Plugins:
370
363
  """
371
364
  updated = False
372
365
  user_config = self.window.core.config.get('plugins')
373
- if plugin_id in list(user_config.keys()):
366
+ if plugin_id in user_config:
374
367
  for key in keys:
375
- if key in list(user_config[plugin_id].keys()):
368
+ if key in user_config[plugin_id]:
376
369
  del user_config[plugin_id][key]
377
370
  self.remove_preset_values(plugin_id, key)
378
371
  updated = True
@@ -384,14 +377,13 @@ class Plugins:
384
377
  def reload_all(self):
385
378
  """Reload all plugins"""
386
379
  if self.presets is None or len(self.presets) == 0:
387
- self.reset_all() # if presets then it will be reloaded on presets load
380
+ self.reset_all()
388
381
 
389
382
  def reset_all(self):
390
383
  """Reset all options to initial values if presets"""
391
- # restore plugin options to initial values
392
- for id in list(self.plugins.keys()):
393
- self.restore_options(id, all=True) # all = with persisted values
394
- self.apply_all_options() # reload from config
384
+ for plugin_id in self.plugins:
385
+ self.restore_options(plugin_id, all=True)
386
+ self.apply_all_options()
395
387
 
396
388
  def clean_presets(self):
397
389
  """Remove invalid options from presets"""
@@ -400,23 +392,19 @@ class Plugins:
400
392
 
401
393
  removed = False
402
394
  if self.presets is not None:
403
- for id in self.presets:
404
- preset = self.presets[id]
405
- for config_preset in preset["config"]:
406
- for key in list(preset["config"][config_preset]):
407
- if config_preset in self.plugins:
395
+ for _preset_id, preset in self.presets.items():
396
+ preset_config = preset["config"]
397
+ for config_preset, cfg_values in preset_config.items():
398
+ if config_preset in self.plugins:
399
+ for key in list(cfg_values):
408
400
  if key not in self.plugins[config_preset].options:
409
401
  removed = True
410
- preset["config"][config_preset].pop(key)
402
+ cfg_values.pop(key)
411
403
  if removed:
412
404
  self.save_presets()
413
405
  print("[FIX] Removed invalid keys from plugin presets.")
414
406
 
415
- def remove_preset_values(
416
- self,
417
- plugin_id: str,
418
- key: str
419
- ):
407
+ def remove_preset_values(self, plugin_id: str, key: str):
420
408
  """
421
409
  Update preset value
422
410
 
@@ -429,22 +417,16 @@ class Plugins:
429
417
 
430
418
  if self.presets is None:
431
419
  return
432
- for id in self.presets:
433
- preset = self.presets[id]
434
- for config_preset in preset["config"]:
435
- if config_preset == plugin_id:
436
- if key in preset["config"][config_preset]:
437
- preset["config"][config_preset].pop(key)
438
- updated = True
420
+
421
+ for _preset_id, preset in self.presets.items():
422
+ preset_config = preset["config"]
423
+ if plugin_id in preset_config and key in preset_config[plugin_id]:
424
+ preset_config[plugin_id].pop(key)
425
+ updated = True
439
426
  if updated:
440
427
  self.save_presets()
441
428
 
442
- def update_preset_values(
443
- self,
444
- plugin_id: str,
445
- key: str,
446
- value: Any
447
- ):
429
+ def update_preset_values(self, plugin_id: str, key: str, value: Any):
448
430
  """
449
431
  Update preset value
450
432
 
@@ -458,41 +440,36 @@ class Plugins:
458
440
 
459
441
  if self.presets is None:
460
442
  return
461
- for id in self.presets:
462
- preset = self.presets[id]
463
- for config_preset in preset["config"]:
464
- if config_preset == plugin_id:
465
- if key in preset["config"][config_preset]:
466
- preset["config"][config_preset][key] = value
467
- updated = True
443
+
444
+ for _preset_id, preset in self.presets.items():
445
+ preset_config = preset["config"]
446
+ if plugin_id in preset_config and key in preset_config[plugin_id]:
447
+ preset_config[plugin_id][key] = value
448
+ updated = True
468
449
  if updated:
469
450
  self.save_presets()
470
451
 
471
-
472
452
  def save_presets(self):
473
453
  """Save presets"""
474
454
  self.provider.save(self.presets)
475
455
 
476
- def dump_locale_by_id(self, id: str, path: str):
456
+ def dump_locale_by_id(self, plugin_id: str, path: str):
477
457
  """
478
458
  Dump locale by id
479
459
 
480
- :param id: plugin id
460
+ :param plugin_id: plugin id
481
461
  :param path: path to locale file
482
462
  """
483
- if id in self.plugins:
484
- self.dump_locale(self.plugins[id], path)
463
+ plugin = self.plugins.get(plugin_id)
464
+ if plugin:
465
+ self.dump_locale(plugin, path)
485
466
 
486
467
  def dump_locales(self):
487
468
  """Dump all locales"""
488
469
  langs = ['en', 'pl']
489
- for id in self.plugins:
490
- domain = 'plugin.' + id
470
+ base_path = os.path.join(self.window.core.config.get_app_path(), 'data', 'locale')
471
+ for plugin_id, plugin in self.plugins.items():
472
+ domain = f'plugin.{plugin_id}'
491
473
  for lang in langs:
492
- path = os.path.join(
493
- self.window.core.config.get_app_path(),
494
- 'data',
495
- 'locale',
496
- domain + '.' + lang + '.ini'
497
- )
498
- self.dump_locale(self.plugins[id], str(path))
474
+ path = os.path.join(base_path, f'{domain}.{lang}.ini')
475
+ self.dump_locale(plugin, path)