PrEditor 1.0.0__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.

Potentially problematic release.


This version of PrEditor might be problematic. Click here for more details.

Files changed (158) hide show
  1. preditor/__init__.py +322 -0
  2. preditor/__main__.py +13 -0
  3. preditor/about_module.py +161 -0
  4. preditor/cli.py +192 -0
  5. preditor/config.py +302 -0
  6. preditor/contexts.py +119 -0
  7. preditor/cores/__init__.py +0 -0
  8. preditor/cores/core.py +20 -0
  9. preditor/dccs/maya/PrEditor_maya.mod +2 -0
  10. preditor/dccs/maya/plug-ins/PrEditor_maya.py +110 -0
  11. preditor/debug.py +144 -0
  12. preditor/delayable_engine/__init__.py +302 -0
  13. preditor/delayable_engine/delayables.py +85 -0
  14. preditor/enum.py +728 -0
  15. preditor/excepthooks.py +131 -0
  16. preditor/gui/__init__.py +93 -0
  17. preditor/gui/app.py +160 -0
  18. preditor/gui/codehighlighter.py +209 -0
  19. preditor/gui/completer.py +226 -0
  20. preditor/gui/console.py +867 -0
  21. preditor/gui/dialog.py +178 -0
  22. preditor/gui/drag_tab_bar.py +190 -0
  23. preditor/gui/editor_chooser.py +57 -0
  24. preditor/gui/errordialog.py +68 -0
  25. preditor/gui/find_files.py +125 -0
  26. preditor/gui/fuzzy_search/__init__.py +0 -0
  27. preditor/gui/fuzzy_search/fuzzy_search.py +93 -0
  28. preditor/gui/group_tab_widget/__init__.py +325 -0
  29. preditor/gui/group_tab_widget/grouped_tab_menu.py +35 -0
  30. preditor/gui/group_tab_widget/grouped_tab_models.py +108 -0
  31. preditor/gui/group_tab_widget/grouped_tab_widget.py +78 -0
  32. preditor/gui/group_tab_widget/one_tab_widget.py +54 -0
  33. preditor/gui/level_buttons.py +343 -0
  34. preditor/gui/logger_window_handler.py +48 -0
  35. preditor/gui/logger_window_plugin.py +32 -0
  36. preditor/gui/loggerwindow.py +1385 -0
  37. preditor/gui/newtabwidget.py +69 -0
  38. preditor/gui/set_text_editor_path_dialog.py +59 -0
  39. preditor/gui/status_label.py +99 -0
  40. preditor/gui/suggest_path_quotes_dialog.py +50 -0
  41. preditor/gui/ui/editor_chooser.ui +93 -0
  42. preditor/gui/ui/errordialog.ui +74 -0
  43. preditor/gui/ui/find_files.ui +140 -0
  44. preditor/gui/ui/loggerwindow.ui +1105 -0
  45. preditor/gui/ui/set_text_editor_path_dialog.ui +189 -0
  46. preditor/gui/ui/suggest_path_quotes_dialog.ui +225 -0
  47. preditor/gui/window.py +161 -0
  48. preditor/gui/workbox_mixin.py +389 -0
  49. preditor/gui/workbox_text_edit.py +137 -0
  50. preditor/gui/workboxwidget.py +298 -0
  51. preditor/logging_config.py +52 -0
  52. preditor/osystem.py +401 -0
  53. preditor/plugins.py +118 -0
  54. preditor/prefs.py +74 -0
  55. preditor/resource/environment_variables.html +26 -0
  56. preditor/resource/error_mail.html +85 -0
  57. preditor/resource/error_mail_inline.html +41 -0
  58. preditor/resource/img/README.md +17 -0
  59. preditor/resource/img/arrow_forward.png +0 -0
  60. preditor/resource/img/check-bold.png +0 -0
  61. preditor/resource/img/chevron-down.png +0 -0
  62. preditor/resource/img/chevron-up.png +0 -0
  63. preditor/resource/img/close-thick.png +0 -0
  64. preditor/resource/img/comment-edit.png +0 -0
  65. preditor/resource/img/content-copy.png +0 -0
  66. preditor/resource/img/content-cut.png +0 -0
  67. preditor/resource/img/content-duplicate.png +0 -0
  68. preditor/resource/img/content-paste.png +0 -0
  69. preditor/resource/img/content-save.png +0 -0
  70. preditor/resource/img/debug_disabled.png +0 -0
  71. preditor/resource/img/eye-check.png +0 -0
  72. preditor/resource/img/file-plus.png +0 -0
  73. preditor/resource/img/file-remove.png +0 -0
  74. preditor/resource/img/format-align-left.png +0 -0
  75. preditor/resource/img/format-letter-case-lower.png +0 -0
  76. preditor/resource/img/format-letter-case-upper.png +0 -0
  77. preditor/resource/img/format-letter-case.svg +1 -0
  78. preditor/resource/img/information.png +0 -0
  79. preditor/resource/img/logging_critical.png +0 -0
  80. preditor/resource/img/logging_custom.png +0 -0
  81. preditor/resource/img/logging_debug.png +0 -0
  82. preditor/resource/img/logging_error.png +0 -0
  83. preditor/resource/img/logging_info.png +0 -0
  84. preditor/resource/img/logging_not_set.png +0 -0
  85. preditor/resource/img/logging_warning.png +0 -0
  86. preditor/resource/img/marker.png +0 -0
  87. preditor/resource/img/play.png +0 -0
  88. preditor/resource/img/playlist-play.png +0 -0
  89. preditor/resource/img/plus-minus-variant.png +0 -0
  90. preditor/resource/img/preditor.ico +0 -0
  91. preditor/resource/img/preditor.png +0 -0
  92. preditor/resource/img/preditor.psd +0 -0
  93. preditor/resource/img/preditor.svg +44 -0
  94. preditor/resource/img/regex.svg +1 -0
  95. preditor/resource/img/restart.svg +1 -0
  96. preditor/resource/img/skip-forward-outline.png +0 -0
  97. preditor/resource/img/skip-next-outline.png +0 -0
  98. preditor/resource/img/skip-next.png +0 -0
  99. preditor/resource/img/skip-previous.png +0 -0
  100. preditor/resource/img/subdirectory-arrow-right.png +0 -0
  101. preditor/resource/img/text-search-variant.png +0 -0
  102. preditor/resource/img/warning-big.png +0 -0
  103. preditor/resource/lang/python.json +30 -0
  104. preditor/resource/settings.ini +25 -0
  105. preditor/resource/stylesheet/Bright.css +65 -0
  106. preditor/resource/stylesheet/Dark.css +199 -0
  107. preditor/scintilla/__init__.py +22 -0
  108. preditor/scintilla/delayables/__init__.py +11 -0
  109. preditor/scintilla/delayables/smart_highlight.py +94 -0
  110. preditor/scintilla/delayables/spell_check.py +173 -0
  111. preditor/scintilla/documenteditor.py +2038 -0
  112. preditor/scintilla/finddialog.py +68 -0
  113. preditor/scintilla/lang/__init__.py +80 -0
  114. preditor/scintilla/lang/config/bash.ini +15 -0
  115. preditor/scintilla/lang/config/batch.ini +14 -0
  116. preditor/scintilla/lang/config/cpp.ini +19 -0
  117. preditor/scintilla/lang/config/css.ini +19 -0
  118. preditor/scintilla/lang/config/eyeonscript.ini +17 -0
  119. preditor/scintilla/lang/config/html.ini +21 -0
  120. preditor/scintilla/lang/config/javascript.ini +24 -0
  121. preditor/scintilla/lang/config/lua.ini +16 -0
  122. preditor/scintilla/lang/config/maxscript.ini +20 -0
  123. preditor/scintilla/lang/config/mel.ini +18 -0
  124. preditor/scintilla/lang/config/mu.ini +22 -0
  125. preditor/scintilla/lang/config/nsi.ini +19 -0
  126. preditor/scintilla/lang/config/perl.ini +19 -0
  127. preditor/scintilla/lang/config/puppet.ini +19 -0
  128. preditor/scintilla/lang/config/python.ini +28 -0
  129. preditor/scintilla/lang/config/ruby.ini +19 -0
  130. preditor/scintilla/lang/config/sql.ini +7 -0
  131. preditor/scintilla/lang/config/xml.ini +21 -0
  132. preditor/scintilla/lang/config/yaml.ini +18 -0
  133. preditor/scintilla/lang/language.py +240 -0
  134. preditor/scintilla/lexers/__init__.py +0 -0
  135. preditor/scintilla/lexers/cpplexer.py +21 -0
  136. preditor/scintilla/lexers/javascriptlexer.py +25 -0
  137. preditor/scintilla/lexers/maxscriptlexer.py +234 -0
  138. preditor/scintilla/lexers/mellexer.py +368 -0
  139. preditor/scintilla/lexers/mulexer.py +32 -0
  140. preditor/scintilla/lexers/pythonlexer.py +41 -0
  141. preditor/scintilla/ui/finddialog.ui +160 -0
  142. preditor/settings.py +71 -0
  143. preditor/stream/__init__.py +80 -0
  144. preditor/stream/director.py +73 -0
  145. preditor/stream/manager.py +74 -0
  146. preditor/streamhandler_helper.py +46 -0
  147. preditor/utils/__init__.py +0 -0
  148. preditor/utils/cute.py +30 -0
  149. preditor/utils/stylesheets.py +54 -0
  150. preditor/utils/text_search.py +342 -0
  151. preditor/version.py +21 -0
  152. preditor/weakref.py +363 -0
  153. preditor-1.0.0.dist-info/METADATA +224 -0
  154. preditor-1.0.0.dist-info/RECORD +158 -0
  155. preditor-1.0.0.dist-info/WHEEL +5 -0
  156. preditor-1.0.0.dist-info/entry_points.txt +18 -0
  157. preditor-1.0.0.dist-info/licenses/LICENSE +165 -0
  158. preditor-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,343 @@
1
+ from __future__ import absolute_import
2
+
3
+ import logging
4
+ import types
5
+ from functools import partial
6
+
7
+ from Qt.QtGui import QIcon
8
+ from Qt.QtWidgets import QAction, QMenu, QToolButton
9
+
10
+ from .. import plugins, resourcePath
11
+ from ..enum import Enum, EnumGroup
12
+
13
+
14
+ class Level(Enum):
15
+
16
+ """
17
+ Custom `Enum` representing an information level.
18
+
19
+ Attributes:
20
+ cached_icon(None): Used to cache the created icon from `get_icon` for
21
+ future use.
22
+ icon_name(str): Name of source icon file to use when creating icon via
23
+ `get_icon`.
24
+ """
25
+
26
+ cached_icon = None
27
+ icon_name = "dot"
28
+
29
+ @property
30
+ def name(self):
31
+ """
32
+ Override of `name` property allowing for the return of a "friendly
33
+ name" to be used in place of the inferred name from the `Enum` instance
34
+ name.
35
+
36
+ Returns:
37
+ str: Name of `Enum` instance.
38
+ """
39
+ return getattr(self, "friendly_name", super(Level, self).name)
40
+
41
+ @property
42
+ def icon(self):
43
+ """
44
+ Icon representing the level. On first access, the icon is created via
45
+ the `get_icon`-method and cached for later use.
46
+
47
+ Returns:
48
+ QIcon:
49
+ """
50
+ if not self.cached_icon:
51
+ self.cached_icon = self.get_icon(self.icon_name, self.level)
52
+ return self.cached_icon
53
+
54
+ def get_icon(self, name, level):
55
+ """
56
+ Retrieves the icon of `name` and level.
57
+
58
+ Args:
59
+ name (str): Icon to retrieve QIcon for.
60
+ level (str): Level name to apply.
61
+
62
+ Returns:
63
+ QIcon: Correct instantiated QIcon.
64
+ """
65
+ return QIcon(
66
+ resourcePath('img/{name}_{level}.png'.format(name=name, level=level))
67
+ )
68
+
69
+
70
+ class LoggerLevel(Level):
71
+ """A Logger level `Enum` using the 'format_align_left' icon."""
72
+
73
+ icon_name = "logging"
74
+
75
+ def is_current(self, logger):
76
+ """Returns if the current logging level matches this label."""
77
+ return logging.getLevelName(logger.level) == self.label
78
+
79
+
80
+ class LoggerLevels(EnumGroup):
81
+ """
82
+ Logger levels with their implementation level name and number & custom
83
+ icon level.
84
+ """
85
+
86
+ Disabled = LoggerLevel(
87
+ friendly_name="Not Set / Inherited", label="NOTSET", number=0, level="not_set"
88
+ )
89
+ Critical = LoggerLevel(label="CRITICAL", number=50, level="critical")
90
+ Error = LoggerLevel(label="ERROR", number=40, level="error")
91
+ Warning = LoggerLevel(label="WARNING", number=30, level="warning")
92
+ Info = LoggerLevel(label="INFO", number=20, level="info")
93
+ Debug = LoggerLevel(label="DEBUG", number=10, level="debug")
94
+
95
+ @classmethod
96
+ def fromLabel(cls, label, default=None, logger=None):
97
+ try:
98
+ return super(LoggerLevels, cls).fromLabel(label, default=default)
99
+ except ValueError:
100
+ # This is not be a standard level, generate a custom level to use
101
+ if logger is None:
102
+ logger = logging.getLogger()
103
+ effective_level = logger.getEffectiveLevel()
104
+ effective_level_name = logging.getLevelName(effective_level)
105
+
106
+ enum = LoggerLevel(
107
+ label=effective_level_name,
108
+ number=effective_level,
109
+ level=effective_level_name,
110
+ )
111
+ # Force the custom icon as this enum's name won't match
112
+ enum.cached_icon = enum.get_icon(enum.icon_name, "custom")
113
+ # Add it to the enum
114
+ LoggerLevels.append(enum)
115
+ return enum
116
+
117
+
118
+ class LoggingLevelButton(QToolButton):
119
+
120
+ """
121
+ A drop down button to set logger levels for all loggers known to Python's
122
+ native logging implementation.
123
+
124
+ The logger menus present in the tool bar button have level-changing actions
125
+ as well a sub-menus for any descendant loggers.
126
+ """
127
+
128
+ def __init__(self, parent=None):
129
+ """
130
+ Creates the root logger menu this button displays when clicked.
131
+ Additionally, any pre-existing loggers and their menus are added.
132
+
133
+ Args:
134
+ parent (QWidget, optional): The parent widget for this button.
135
+ """
136
+ super(LoggingLevelButton, self).__init__(parent=parent)
137
+ self.setPopupMode(QToolButton.InstantPopup)
138
+
139
+ # create root logger menu
140
+ root = logging.getLogger("")
141
+ root_menu = LoggingLevelMenu(name="root", logger=root, parent=self)
142
+ self.setMenu(root_menu)
143
+
144
+ # TODO: Hook refresh up to a root logger signal
145
+ # Monkey patch root.setLogger to emit signal we connect to
146
+ root = self.patched_root_logger().level_changed.connect(self.refresh)
147
+
148
+ @staticmethod
149
+ def patched_root_logger():
150
+ """Returns `logging.getLogger("")`. This will have the level_changed
151
+ signal added if it wasn't already.
152
+
153
+ The level_changed signal is emitted any time something changes the
154
+ root logger level. PrEditor uses this to update the logging level button
155
+ icon any time the root logger's level is changed. The rest of the loggers
156
+ don't need this as the menu is built on demand with the correct icons indicated.
157
+ """
158
+ root = logging.getLogger("")
159
+ if hasattr(root, "level_changed"):
160
+ # Already patched, nothing to do
161
+ return root
162
+
163
+ # Need to patch the root logger
164
+ from signalslot import Signal
165
+
166
+ root.level_changed = Signal(args=["level"], name="level_changed")
167
+
168
+ # Store the current setLevel, so we can call it in our method
169
+ root._setLevel = root.setLevel
170
+
171
+ def setLevel(self, level):
172
+ """
173
+ Sets the threshold for this logger to `level`. Also emits the
174
+ instance's `level_changed`-signal with the level number as its payload.
175
+
176
+ Args:
177
+ level (int): Numeric level value.
178
+ """
179
+ # Call the original setLevel method
180
+ self._setLevel(level)
181
+ # Emit our signal
182
+ self.level_changed.emit(level=level)
183
+
184
+ root.setLevel = types.MethodType(setLevel, root)
185
+
186
+ return root
187
+
188
+ def refresh(self, **kwargs):
189
+ effective_level = logging.getLogger("").getEffectiveLevel()
190
+ effective_level_name = logging.getLevelName(effective_level)
191
+ level_enum = LoggerLevels.fromLabel(effective_level_name)
192
+
193
+ self.setIcon(level_enum.icon)
194
+ self.setToolTip("Logger 'root' current level: {}".format(level_enum.name))
195
+
196
+
197
+ class LazyMenu(QMenu):
198
+ """A menu class that only calls self.refresh when it is about to be shown."""
199
+
200
+ def __init__(self, *args, **kwargs):
201
+ super(LazyMenu, self).__init__(*args, **kwargs)
202
+ self.aboutToShow.connect(self.refresh)
203
+
204
+
205
+ class HandlerMenu(LazyMenu):
206
+ def __init__(self, logger, parent=None):
207
+ super(HandlerMenu, self).__init__(title="Handlers", parent=parent)
208
+ self.logger = logger
209
+
210
+ def install_handler(self, name):
211
+ plugins.add_logging_handler(self.logger, name)
212
+
213
+ def refresh(self):
214
+ self.clear()
215
+ # Add the Install sub menu showing all logging_handler plugins
216
+ handler_install = self.addMenu('Install')
217
+ for name, cls in plugins.logging_handlers():
218
+ act = handler_install.addAction(name)
219
+ act.triggered.connect(partial(self.install_handler, name))
220
+ for h in self.logger.handlers:
221
+ if type(h) is cls:
222
+ act.setEnabled(False)
223
+ act.setToolTip('Already installed for this logger.')
224
+ break
225
+
226
+ # Add a visual indication of all of the existing handlers
227
+ # TODO: Add ability to modify the formatters and auto-creation on startup
228
+ self.addSeparator()
229
+ for handler in self.logger.handlers:
230
+ act = self.addAction(repr(handler))
231
+ act.setEnabled(False)
232
+
233
+
234
+ class LoggingLevelMenu(LazyMenu):
235
+
236
+ """
237
+ Custom menu for Python Loggers.
238
+
239
+ Provides an interface for changing logger levels via menu actions. Also
240
+ displays the presently set level by highlighting the relevant menu action
241
+ and via the menu's icon (which displays the logger's effective level,
242
+ potentially inherited from its ancestor).
243
+ """
244
+
245
+ def __init__(self, name, logger, parent=None):
246
+ """
247
+ Creates the default level menu actions for updating the logger's level.
248
+
249
+ Args:
250
+ name (str): Name of Logger this menu will represent.
251
+ logger (logging.Logger): Logger this menu will represent and control
252
+ via actions that modify the logger's set level.
253
+ parent (QToolButton/QMenu): `QMenu` or `QToolButton` this menu will
254
+ be parented to.
255
+
256
+ Note: If the logger is merely a placeholder it will be initialized so
257
+ it can be added to the menu hierarchy. This ensures all ancestors
258
+ exist for appropriate parenting when descendants are added.
259
+ """
260
+ super(LoggingLevelMenu, self).__init__(title=name.split(".")[-1], parent=parent)
261
+
262
+ if isinstance(logger, logging.PlaceHolder):
263
+ logger = logging.getLogger(name)
264
+
265
+ self.logger = logger
266
+ self.name = name
267
+ self.update_ui()
268
+
269
+ def children(self):
270
+ """The direct sub-loggers of this logging object."""
271
+ parent = self.name
272
+ if parent == "root":
273
+ parent = ""
274
+ for name, logger in sorted(
275
+ logging.root.manager.loggerDict.items(), key=lambda x: x[0].lower()
276
+ ):
277
+ if name.startswith(parent):
278
+ remaining = name.lstrip(parent).lstrip(".")
279
+ if remaining and "." not in remaining:
280
+ yield name, logger
281
+
282
+ def level(self):
283
+ """Returns the current effective LoggerLevel for self.logger."""
284
+ effective_level = self.logger.getEffectiveLevel()
285
+ effective_level_name = logging.getLevelName(effective_level)
286
+ return LoggerLevels.fromLabel(effective_level_name, logger=self.logger)
287
+
288
+ def refresh(self):
289
+ self.clear()
290
+
291
+ self.addMenu(HandlerMenu(self.logger, self))
292
+ self.addSeparator()
293
+
294
+ for logger_level in LoggerLevels:
295
+ is_current = logger_level.is_current(self.logger)
296
+
297
+ action = QAction(logger_level.icon, logger_level.name, self)
298
+ action.setCheckable(True)
299
+ action.setChecked(is_current)
300
+
301
+ # tooltip example: "Set 'preditor.debug' to level Warning")
302
+ action.setToolTip(
303
+ "Set '{}' to level {}".format(self.name, logger_level.name)
304
+ )
305
+
306
+ # when clicked/activated set associated loggers level
307
+ action.triggered.connect(partial(self.setLevel, logger_level.number))
308
+ self.addAction(action)
309
+
310
+ self.addSeparator()
311
+
312
+ for name, child in self.children():
313
+ self.addMenu(LoggingLevelMenu(name, child, self))
314
+
315
+ def setLevel(self, level):
316
+ """
317
+ Sets the logger this menu object represents to the level supplied.
318
+
319
+ Args:
320
+ level (str): Logging level to set logger to.
321
+ """
322
+ self.logger.setLevel(level)
323
+ self.update_ui()
324
+
325
+ def update_ui(self):
326
+ """Set the menu icon to this LoggerLevel's icon.
327
+
328
+ If the updated logger is the root logger, the logging level toolbar
329
+ button's icon is updated instead.
330
+
331
+ Args:
332
+ level (LoggerLevel): Logging level to change icon to represent.
333
+ """
334
+
335
+ level_enum = self.level()
336
+ act = self.menuAction()
337
+ act.setIcon(level_enum.icon)
338
+ act.setToolTip(
339
+ "Logger '{}' current level: {}".format(self.logger.name, level_enum.name)
340
+ )
341
+
342
+ if self.name == "root":
343
+ self.parent().refresh()
@@ -0,0 +1,48 @@
1
+ from __future__ import absolute_import
2
+
3
+ import logging
4
+
5
+ from .. import instance
6
+
7
+
8
+ class LoggerWindowHandler(logging.Handler):
9
+ """A logging handler that writes directly to the PrEditor instance.
10
+
11
+ Args:
12
+ error (bool, optional): Write the output as if it were written
13
+ to sys.stderr and not sys.stdout. Ie in red text.
14
+ formatter (str or logging.Formatter, optional): If specified,
15
+ this is passed to setFormatter.
16
+ """
17
+
18
+ default_format = (
19
+ '%(levelname)s %(module)s.%(funcName)s line:%(lineno)d - %(message)s'
20
+ )
21
+
22
+ def __init__(self, error=True, formatter=default_format):
23
+ super(LoggerWindowHandler, self).__init__()
24
+ self.error = error
25
+ if formatter is not None:
26
+ if not isinstance(formatter, logging.Formatter):
27
+ formatter = logging.Formatter(formatter)
28
+ self.setFormatter(formatter)
29
+
30
+ def emit(self, record):
31
+ _instance = instance(create=False)
32
+ if _instance is None:
33
+ # No gui has been created yet, so nothing to do
34
+ return
35
+ try:
36
+ # If the python logger was closed and garbage collected,
37
+ # there is nothing to do, simply exit the call
38
+ console = _instance.console()
39
+ if not console:
40
+ return
41
+
42
+ msg = self.format(record)
43
+ msg = u'{}\n'.format(msg)
44
+ console.write(msg, self.error)
45
+ except (KeyboardInterrupt, SystemExit):
46
+ raise
47
+ except Exception:
48
+ self.handleError(record)
@@ -0,0 +1,32 @@
1
+ class LoggerWindowPlugin:
2
+ """Base class for LoggerWindow plugins.
3
+
4
+ These plugins are loaded using the `preditor.plug.loggerwindow` entry point.
5
+ This entry point is loaded when `LoggerWindow` is initialized. For each entry
6
+ point defined a single instance of the plugin is created per instance of
7
+ a LoggerWindow.
8
+
9
+ To save preferences override `record_prefs` and `restore_prefs` methods. These
10
+ are used to save and load preferences any time the PrEditor save/loads prefs.
11
+ """
12
+
13
+ def __init__(self, parent):
14
+ self.parent = parent
15
+
16
+ def record_prefs(self, name):
17
+ """Returns any prefs to save with the PrEditor's preferences.
18
+
19
+ Returns:
20
+ dict: A dictionary that will be saved using json or None.
21
+ """
22
+
23
+ def restore_prefs(self, name, prefs):
24
+ """Restore the preferences saved from a previous launch.
25
+
26
+ Args:
27
+ name(str): The name specified by the `preditor.plug.loggerwindow`
28
+ entry point.
29
+ prefs(dict or None): The prefs returned by a previous call to
30
+ `record_prefs()` from the last preference save. None is passed
31
+ if no prefs were recorded.
32
+ """