pyqt-code-editor 0.0.28__tar.gz → 0.0.30__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.
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/PKG-INFO +2 -1
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyproject.toml +2 -1
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/__init__.py +1 -1
- pyqt_code_editor-0.0.30/pyqt_code_editor/environment_manager.py +37 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/check.py +5 -5
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/complete.py +4 -2
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/languages/generic.py +2 -2
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/languages/python.py +4 -3
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/process.py +109 -28
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/codestral.py +6 -1
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/jedi.py +12 -5
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/ruff.py +9 -2
- pyqt_code_editor-0.0.28/pyqt_code_editor/environment_manager.py +0 -37
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/COPYING +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/_settings.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/app.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/code_editors.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/languages/generic.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/languages/markdown.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/languages/python.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/languages/text.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/editor_panel.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/find_in_files.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/jupyter_console.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/project_explorer.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/settings_panel.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/sigmund.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/workspace_explorer.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/auto_indent.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/auto_pair.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/base.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/comment.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/execute.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/file_link.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/line_number.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/python_auto_indent.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/search_replace.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/shortcuts.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/smart_backspace_delete.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/symbols.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/theme.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/widgets/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/zoom.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/sigmund-analyst.png +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/signal_router.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/syntax_highlighters/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/syntax_highlighters/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/syntax_highlighters/languages/generic.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/syntax_highlighters/languages/python.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/syntax_highlighters/syntax_highlighter.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/themes.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/languages/python/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/languages/python/_auto_indent.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/languages/python/_extract_cells.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/languages/python/_mask_str_in_code.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/watchdog.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/calltip_widget.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/completion_popup.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/dock.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/quick_open_dialog.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/quick_open_file_dialog.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/quick_symbol_dialog.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/search_replace_frame.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/tab_splitter.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/tabbed_editor.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/manager.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/__init__.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/sigmund.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/symbol.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/settings.py +0 -0
- {pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/readme.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyqt_code_editor
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.30
|
|
4
4
|
Summary: Fully featured code-editor widgets for PyQt
|
|
5
5
|
Keywords: code editor,pyqt,ide
|
|
6
6
|
Author-email: Sebastiaan Mathôt <s.mathot@cogsci.nl>
|
|
@@ -10,6 +10,7 @@ License-File: COPYING
|
|
|
10
10
|
Requires-Dist: chardet
|
|
11
11
|
Requires-Dist: detect-indent
|
|
12
12
|
Requires-Dist: jedi
|
|
13
|
+
Requires-Dist: httpx<0.29.0
|
|
13
14
|
Requires-Dist: mistralai
|
|
14
15
|
Requires-Dist: pathspec
|
|
15
16
|
Requires-Dist: psutil
|
|
@@ -15,6 +15,7 @@ dependencies = [
|
|
|
15
15
|
"chardet",
|
|
16
16
|
"detect-indent",
|
|
17
17
|
"jedi",
|
|
18
|
+
"httpx<0.29.0",
|
|
18
19
|
"mistralai",
|
|
19
20
|
"pathspec",
|
|
20
21
|
"psutil",
|
|
@@ -36,4 +37,4 @@ Source = "https://github.com/open-cogsci/sigmund-analyst"
|
|
|
36
37
|
|
|
37
38
|
[project.scripts]
|
|
38
39
|
sigmund-analyst = "pyqt_code_editor.app:launch_app"
|
|
39
|
-
pyqt-code-editor = "pyqt_code_editor.app:launch_app"
|
|
40
|
+
pyqt-code-editor = "pyqt_code_editor.app:launch_app"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from qtpy.QtCore import Signal, QObject
|
|
3
|
+
import logging
|
|
4
|
+
logger = logging.getLogger(__name__)
|
|
5
|
+
|
|
6
|
+
class EnvironmentManager(QObject):
|
|
7
|
+
"""Singleton class to share the current environment and language between all
|
|
8
|
+
components of the app.
|
|
9
|
+
"""
|
|
10
|
+
environment_changed = Signal(str, str, str, str)
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
super().__init__()
|
|
14
|
+
self.name = None
|
|
15
|
+
self.path = None
|
|
16
|
+
self.language = None
|
|
17
|
+
self.prefix = None
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def current_environment(self):
|
|
21
|
+
return self.name, self.path, self.language
|
|
22
|
+
|
|
23
|
+
def set_environment(self, name, path, language, prefix=None):
|
|
24
|
+
if path != self.path:
|
|
25
|
+
# The path may not exist if the environment is simply python or
|
|
26
|
+
# python3, in which case we do not need to specify it at all.
|
|
27
|
+
if not os.path.exists(path):
|
|
28
|
+
path = None
|
|
29
|
+
self.name = name
|
|
30
|
+
self.path = path
|
|
31
|
+
self.language = language
|
|
32
|
+
self.prefix = prefix
|
|
33
|
+
self.environment_changed.emit(name, path, language, prefix)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Singleton instance
|
|
37
|
+
environment_manager = EnvironmentManager()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
from qtpy.QtWidgets import QWidget, QPlainTextEdit
|
|
2
|
-
from qtpy.QtCore import Qt, QRect, QPoint, QSize, QTimer
|
|
3
|
-
from qtpy.QtGui import QPainter, QColor, QBrush
|
|
4
1
|
import logging
|
|
2
|
+
from qtpy.QtCore import QTimer
|
|
3
|
+
from qtpy.QtGui import QColor
|
|
4
|
+
from ..environment_manager import environment_manager
|
|
5
5
|
logger = logging.getLogger(__name__)
|
|
6
6
|
|
|
7
7
|
|
|
@@ -50,8 +50,8 @@ class Check:
|
|
|
50
50
|
self.send_worker_request(
|
|
51
51
|
action='check',
|
|
52
52
|
code=code,
|
|
53
|
-
language=getattr(self, "code_editor_language", "python")
|
|
54
|
-
|
|
53
|
+
language=getattr(self, "code_editor_language", "python"),
|
|
54
|
+
prefix=environment_manager.prefix)
|
|
55
55
|
|
|
56
56
|
def handle_worker_result(self, action: str, result):
|
|
57
57
|
"""
|
|
@@ -276,7 +276,8 @@ class Complete:
|
|
|
276
276
|
multiline=multiline,
|
|
277
277
|
path=self.code_editor_file_path,
|
|
278
278
|
language=self.code_editor_language,
|
|
279
|
-
env_path=environment_manager.path
|
|
279
|
+
env_path=environment_manager.path,
|
|
280
|
+
prefix=environment_manager.prefix)
|
|
280
281
|
|
|
281
282
|
def _cm_request_calltip(self):
|
|
282
283
|
"""Send a calltip request."""
|
|
@@ -288,7 +289,8 @@ class Complete:
|
|
|
288
289
|
cursor_pos=cursor_pos,
|
|
289
290
|
path=self.code_editor_file_path,
|
|
290
291
|
language=self.code_editor_language,
|
|
291
|
-
env_path=environment_manager.path
|
|
292
|
+
env_path=environment_manager.path,
|
|
293
|
+
prefix=environment_manager.prefix)
|
|
292
294
|
|
|
293
295
|
def _cm_hide_calltip(self):
|
|
294
296
|
"""Hide the calltip widget."""
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/languages/generic.py
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from ..providers import symbol, codestral
|
|
2
2
|
|
|
3
|
-
def complete(code, cursor_pos, path, multiline, full, env_path):
|
|
3
|
+
def complete(code, cursor_pos, path, multiline, full, env_path, prefix):
|
|
4
4
|
if full or multiline:
|
|
5
5
|
completions = codestral.codestral_complete(
|
|
6
|
-
code, cursor_pos, multiline=multiline)
|
|
6
|
+
code, cursor_pos, multiline=multiline, prefix=prefix)
|
|
7
7
|
else:
|
|
8
8
|
completions = []
|
|
9
9
|
if not multiline:
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/languages/python.py
RENAMED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
from ..providers import jedi, codestral, ruff
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def complete(code, cursor_pos, path, multiline, full, env_path):
|
|
4
|
+
def complete(code, cursor_pos, path, multiline, full, env_path, prefix):
|
|
5
5
|
if full or multiline:
|
|
6
6
|
codestral_completions = codestral.codestral_complete(
|
|
7
|
-
code, cursor_pos, multiline=multiline)
|
|
7
|
+
code, cursor_pos, multiline=multiline, prefix=prefix)
|
|
8
8
|
else:
|
|
9
9
|
codestral_completions = []
|
|
10
10
|
if not multiline:
|
|
11
11
|
jedi_completions = jedi.jedi_complete(code, cursor_pos, path=path,
|
|
12
|
-
env_path=env_path
|
|
12
|
+
env_path=env_path,
|
|
13
|
+
prefix=prefix)
|
|
13
14
|
else:
|
|
14
15
|
jedi_completions = []
|
|
15
16
|
# If there is at least one jedi completion, it is always insert at first.
|
|
@@ -8,13 +8,98 @@ worker_functions_cache = {}
|
|
|
8
8
|
|
|
9
9
|
def main_worker_process_function(request_queue, result_queue):
|
|
10
10
|
"""
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
Main worker process for handling editor backend requests.
|
|
12
|
+
|
|
13
|
+
Runs in a separate process, continuously processing requests from a queue
|
|
14
|
+
and sending results back through another queue. Supports code completion,
|
|
15
|
+
calltips, symbol extraction, code checking, and settings management.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
request_queue : multiprocessing.Queue
|
|
20
|
+
Queue containing request dictionaries to process
|
|
21
|
+
result_queue : multiprocessing.Queue
|
|
22
|
+
Queue where results are sent back to the main process
|
|
23
|
+
|
|
24
|
+
Request Format
|
|
25
|
+
--------------
|
|
26
|
+
Each request must be a dictionary with the following structure:
|
|
27
|
+
|
|
28
|
+
Required fields:
|
|
29
|
+
action : str
|
|
30
|
+
The action to perform. One of: 'complete', 'calltip', 'symbols',
|
|
31
|
+
'check', 'set_settings', 'quit'
|
|
32
|
+
|
|
33
|
+
Optional fields (depending on action):
|
|
34
|
+
language : str, default 'text'
|
|
35
|
+
Programming language for syntax-aware processing
|
|
36
|
+
code : str, default ''
|
|
37
|
+
Source code content to analyze
|
|
38
|
+
cursor_pos : int, default 0
|
|
39
|
+
Character position of cursor in the code
|
|
40
|
+
path : str, optional
|
|
41
|
+
File path for context-aware processing
|
|
42
|
+
multiline : bool, default False
|
|
43
|
+
Whether to enable multiline completion mode
|
|
44
|
+
full : bool, default False
|
|
45
|
+
Whether to return full completion details
|
|
46
|
+
env_path : str, optional
|
|
47
|
+
Path to Python environment for context
|
|
48
|
+
prefix : str, optional
|
|
49
|
+
Prefix string for filtering results
|
|
50
|
+
settings : dict, optional
|
|
51
|
+
Settings to update (only for 'set_settings' action)
|
|
52
|
+
|
|
53
|
+
Response Format
|
|
54
|
+
---------------
|
|
55
|
+
Results are dictionaries placed on result_queue with action-specific content:
|
|
56
|
+
|
|
57
|
+
For 'complete' action:
|
|
58
|
+
{
|
|
59
|
+
'action': 'complete',
|
|
60
|
+
'completions': list or None,
|
|
61
|
+
'cursor_pos': int,
|
|
62
|
+
'multiline': bool,
|
|
63
|
+
'full': bool
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
For 'calltip' action:
|
|
67
|
+
{
|
|
68
|
+
'action': 'calltip',
|
|
69
|
+
'signatures': list or None,
|
|
70
|
+
'cursor_pos': int
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
For 'symbols' action:
|
|
74
|
+
{
|
|
75
|
+
'action': 'symbols',
|
|
76
|
+
'symbols': list
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
For 'check' action:
|
|
80
|
+
{
|
|
81
|
+
'action': 'check',
|
|
82
|
+
'messages': dict
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
Behavior
|
|
86
|
+
--------
|
|
87
|
+
- Runs indefinitely until receiving a 'quit' action
|
|
88
|
+
- Dynamically loads language-specific worker modules on first use
|
|
89
|
+
- Caches imported worker modules for efficiency
|
|
90
|
+
- Falls back to generic worker functions if language-specific module unavailable
|
|
91
|
+
- Skips invalid requests (None, non-dict, or missing 'action' field)
|
|
92
|
+
- Logs all major operations and errors
|
|
93
|
+
- For 'set_settings' action, updates the settings module attributes directly
|
|
94
|
+
- Worker modules must provide functions: complete, calltip, symbols, check
|
|
95
|
+
(functions can be None if not supported for that language)
|
|
96
|
+
|
|
97
|
+
Notes
|
|
98
|
+
-----
|
|
99
|
+
This function is designed to run in a separate process to avoid blocking
|
|
100
|
+
the main editor thread during potentially slow operations like code analysis.
|
|
101
|
+
Language-specific worker modules are expected to be in the 'languages'
|
|
102
|
+
subpackage.
|
|
18
103
|
"""
|
|
19
104
|
logger.info("Started completion worker.")
|
|
20
105
|
while True:
|
|
@@ -25,13 +110,21 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
25
110
|
if request is None:
|
|
26
111
|
logger.info("Received None request (possibly legacy or invalid). Skipping.")
|
|
27
112
|
continue
|
|
28
|
-
|
|
29
113
|
# Expect a dict with at least an 'action' field
|
|
30
114
|
if not isinstance(request, dict):
|
|
31
115
|
logger.info(f"Invalid request type: {type(request)}. Skipping.")
|
|
32
|
-
continue
|
|
33
|
-
|
|
116
|
+
continue
|
|
117
|
+
# Most of the parameters apply to multiple actions, so we extract them
|
|
118
|
+
# here.
|
|
34
119
|
action = request.get('action', None)
|
|
120
|
+
language = request.get('language', 'text')
|
|
121
|
+
code = request.get('code', '')
|
|
122
|
+
cursor_pos = request.get('cursor_pos', 0)
|
|
123
|
+
path = request.get('path', None)
|
|
124
|
+
multiline = request.get('multiline', False)
|
|
125
|
+
full = request.get('full', False)
|
|
126
|
+
env_path = request.get('env_path', None)
|
|
127
|
+
prefix = request.get('prefix', None)
|
|
35
128
|
if action is None:
|
|
36
129
|
logger.info("Request is missing 'action' field. Skipping.")
|
|
37
130
|
continue
|
|
@@ -46,8 +139,7 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
46
139
|
break
|
|
47
140
|
|
|
48
141
|
# Load the worker functions depending on the language. We store the
|
|
49
|
-
# imported module in a cache for efficiency
|
|
50
|
-
language = request.get('language', 'text')
|
|
142
|
+
# imported module in a cache for efficiency
|
|
51
143
|
if language not in worker_functions_cache:
|
|
52
144
|
try:
|
|
53
145
|
worker_functions = importlib.import_module(
|
|
@@ -66,16 +158,10 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
66
158
|
if worker_functions.complete is None:
|
|
67
159
|
completions = None
|
|
68
160
|
else:
|
|
69
|
-
code = request.get('code', '')
|
|
70
|
-
cursor_pos = request.get('cursor_pos', 0)
|
|
71
|
-
path = request.get('path', None)
|
|
72
|
-
multiline = request.get('multiline', False)
|
|
73
|
-
full = request.get('full', False)
|
|
74
|
-
env_path = request.get('env_path', None)
|
|
75
161
|
logger.info(f"Performing code completion: language='{language}', multiline={multiline}, path={path}, env_path={env_path}")
|
|
76
162
|
completions = worker_functions.complete(
|
|
77
163
|
code, cursor_pos, path=path, multiline=multiline, full=full,
|
|
78
|
-
env_path=env_path)
|
|
164
|
+
env_path=env_path, prefix=prefix)
|
|
79
165
|
if not completions:
|
|
80
166
|
logger.info("No completions")
|
|
81
167
|
else:
|
|
@@ -89,16 +175,13 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
89
175
|
})
|
|
90
176
|
|
|
91
177
|
elif action == 'calltip':
|
|
92
|
-
cursor_pos = request.get('cursor_pos', 0)
|
|
93
178
|
if worker_functions.calltip is None:
|
|
94
179
|
signatures = None
|
|
95
180
|
else:
|
|
96
|
-
code = request.get('code', '')
|
|
97
|
-
path = request.get('path', None)
|
|
98
|
-
env_path = request.get('env_path', None)
|
|
99
181
|
logger.info(f"Performing calltip: language='{language}', path={path}, env_path={env_path}")
|
|
100
182
|
signatures = worker_functions.calltip(
|
|
101
|
-
code, cursor_pos, path=path, env_path=env_path
|
|
183
|
+
code, cursor_pos, path=path, env_path=env_path,
|
|
184
|
+
prefix=prefix)
|
|
102
185
|
if signatures is None:
|
|
103
186
|
logger.info("No calltip signatures. Sending result back.")
|
|
104
187
|
else:
|
|
@@ -113,7 +196,6 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
113
196
|
if worker_functions.symbols is None:
|
|
114
197
|
symbols_results = []
|
|
115
198
|
else:
|
|
116
|
-
code = request.get('code', '')
|
|
117
199
|
symbols_results = worker_functions.symbols(code)
|
|
118
200
|
result_queue.put({
|
|
119
201
|
'action': 'symbols',
|
|
@@ -124,11 +206,10 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
124
206
|
if worker_functions.check is None:
|
|
125
207
|
check_results = {}
|
|
126
208
|
else:
|
|
127
|
-
|
|
128
|
-
check_results = worker_functions.check(code)
|
|
209
|
+
check_results = worker_functions.check(code, prefix=prefix)
|
|
129
210
|
result_queue.put({
|
|
130
211
|
'action': 'check',
|
|
131
212
|
'messages': check_results
|
|
132
213
|
})
|
|
133
214
|
|
|
134
|
-
logger.info("Completion worker has shut down.")
|
|
215
|
+
logger.info("Completion worker has shut down.")
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/codestral.py
RENAMED
|
@@ -6,7 +6,8 @@ client = None
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def codestral_complete(code: str, cursor_pos: int,
|
|
9
|
-
multiline: bool = False
|
|
9
|
+
multiline: bool = False,
|
|
10
|
+
prefix: str | None = None) -> list[str]:
|
|
10
11
|
global client
|
|
11
12
|
|
|
12
13
|
if not settings.codestral_api_key:
|
|
@@ -22,6 +23,10 @@ def codestral_complete(code: str, cursor_pos: int,
|
|
|
22
23
|
start = max(0, cursor_pos - settings.codestral_max_context)
|
|
23
24
|
end = cursor_pos + settings.codestral_max_context
|
|
24
25
|
prompt = code[start: cursor_pos]
|
|
26
|
+
if prefix:
|
|
27
|
+
if not prefix.endswith('\n'):
|
|
28
|
+
prefix += '\n'
|
|
29
|
+
prompt = prefix + prompt
|
|
25
30
|
suffix = code[cursor_pos: end]
|
|
26
31
|
|
|
27
32
|
request = dict(
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/jedi.py
RENAMED
|
@@ -21,11 +21,16 @@ def _signature_to_html(signature) -> str:
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def _prepare_jedi_script(code: str, cursor_position: int, path: str | None,
|
|
24
|
-
env_path: str | None):
|
|
24
|
+
env_path: str | None, prefix: str | None = None):
|
|
25
25
|
"""
|
|
26
26
|
Prepare a Jedi Script object and calculate line_no/column_no from the
|
|
27
27
|
given code and cursor_position. Returns (script, line_no, column_no).
|
|
28
28
|
"""
|
|
29
|
+
if prefix:
|
|
30
|
+
if not prefix.endswith('\n'):
|
|
31
|
+
prefix += '\n'
|
|
32
|
+
code = prefix + code
|
|
33
|
+
cursor_position += len(prefix)
|
|
29
34
|
# Convert the flat cursor_position into line & column (1-based indexing for Jedi)
|
|
30
35
|
line_no = code[:cursor_position].count('\n') + 1
|
|
31
36
|
last_newline_idx = code.rfind('\n', 0, cursor_position)
|
|
@@ -43,7 +48,8 @@ def _prepare_jedi_script(code: str, cursor_position: int, path: str | None,
|
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
def jedi_complete(code: str, cursor_position: int, path: str | None,
|
|
46
|
-
env_path: str | None = None
|
|
51
|
+
env_path: str | None = None,
|
|
52
|
+
prefix: str | None = None) -> list[str]:
|
|
47
53
|
"""
|
|
48
54
|
Perform Python-specific completion using Jedi. Returns a list of possible completions
|
|
49
55
|
for the text at the given cursor position, or None if no completion is found.
|
|
@@ -61,7 +67,7 @@ def jedi_complete(code: str, cursor_position: int, path: str | None,
|
|
|
61
67
|
return []
|
|
62
68
|
# Go Jedi!
|
|
63
69
|
script, line_no, column_no = _prepare_jedi_script(code, cursor_position,
|
|
64
|
-
path, env_path)
|
|
70
|
+
path, env_path, prefix)
|
|
65
71
|
completions = script.complete(line=line_no, column=column_no)
|
|
66
72
|
if not completions:
|
|
67
73
|
return []
|
|
@@ -75,7 +81,8 @@ def jedi_complete(code: str, cursor_position: int, path: str | None,
|
|
|
75
81
|
def jedi_signatures(code: str, cursor_position: int, path: str | None,
|
|
76
82
|
multiline: bool = False, max_width: int = 40,
|
|
77
83
|
max_lines: int = 10,
|
|
78
|
-
env_path: str | None = None
|
|
84
|
+
env_path: str | None = None,
|
|
85
|
+
prefix: str | None = None) -> list[str]:
|
|
79
86
|
"""
|
|
80
87
|
Retrieve function signatures (calltips) from Jedi given the current cursor position.
|
|
81
88
|
Returns a list of strings describing each signature, or None if none.
|
|
@@ -90,7 +97,7 @@ def jedi_signatures(code: str, cursor_position: int, path: str | None,
|
|
|
90
97
|
|
|
91
98
|
logger.info("Starting Jedi calltip request (multiline=%r).", multiline)
|
|
92
99
|
script, line_no, column_no = _prepare_jedi_script(code, cursor_position,
|
|
93
|
-
path, env_path)
|
|
100
|
+
path, env_path, prefix)
|
|
94
101
|
|
|
95
102
|
signatures = script.get_signatures(line=line_no, column=column_no)
|
|
96
103
|
if not signatures:
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/ruff.py
RENAMED
|
@@ -6,13 +6,20 @@ import logging
|
|
|
6
6
|
logger = logging.getLogger(__name__)
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def ruff_check(code: str) -> list[dict]:
|
|
9
|
+
def ruff_check(code: str, prefix: str | None = None) -> list[dict]:
|
|
10
10
|
"""
|
|
11
11
|
Lints Python source code using Ruff.
|
|
12
12
|
|
|
13
13
|
Args:
|
|
14
14
|
code (str): The Python source code to lint.
|
|
15
15
|
"""
|
|
16
|
+
if prefix:
|
|
17
|
+
if not prefix.endswith('\n'):
|
|
18
|
+
prefix += '\n'
|
|
19
|
+
code = prefix + code
|
|
20
|
+
prefix_line_offset = prefix.count('\n')
|
|
21
|
+
else:
|
|
22
|
+
prefix_line_offset = 0
|
|
16
23
|
with tempfile.NamedTemporaryFile(delete=False, suffix=".py", mode="w") as tmp_file:
|
|
17
24
|
tmp_file.write(code)
|
|
18
25
|
tmp_file_path = tmp_file.name
|
|
@@ -35,7 +42,7 @@ def ruff_check(code: str) -> list[dict]:
|
|
|
35
42
|
return {}
|
|
36
43
|
formatted_result = {}
|
|
37
44
|
for message in result:
|
|
38
|
-
row = message['location']['row']
|
|
45
|
+
row = message['location']['row'] - prefix_line_offset
|
|
39
46
|
if row not in formatted_result:
|
|
40
47
|
formatted_result[row] = []
|
|
41
48
|
formatted_result[row].append({
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from qtpy.QtCore import Signal, QObject
|
|
3
|
-
import logging
|
|
4
|
-
logger = logging.getLogger(__name__)
|
|
5
|
-
|
|
6
|
-
class EnvironmentManager(QObject):
|
|
7
|
-
"""Singleton class to share the current environment and language between all
|
|
8
|
-
components of the app.
|
|
9
|
-
"""
|
|
10
|
-
environment_changed = Signal(str, str, str)
|
|
11
|
-
|
|
12
|
-
def __init__(self):
|
|
13
|
-
super().__init__()
|
|
14
|
-
self.name = None
|
|
15
|
-
self.path = None
|
|
16
|
-
self.language = None
|
|
17
|
-
|
|
18
|
-
@property
|
|
19
|
-
def current_environment(self):
|
|
20
|
-
return self.name, self.path, self.language
|
|
21
|
-
|
|
22
|
-
def set_environment(self, name, path, language):
|
|
23
|
-
path = os.path.abspath(path)
|
|
24
|
-
if path == self.path:
|
|
25
|
-
return
|
|
26
|
-
if not os.path.exists(path):
|
|
27
|
-
logger.warning(f'no such environment: {path}')
|
|
28
|
-
return
|
|
29
|
-
logger.info(f'environment changed: {path}')
|
|
30
|
-
self.name = name
|
|
31
|
-
self.path = path
|
|
32
|
-
self.language = language
|
|
33
|
-
self.environment_changed.emit(name, path, language)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# Singleton instance
|
|
37
|
-
environment_manager = EnvironmentManager()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/__init__.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/code_editors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/code_editors/languages/text.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/editor_panel.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/find_in_files.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/jupyter_console.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/project_explorer.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/components/settings_panel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/python_auto_indent.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/search_replace.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/mixins/widgets/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/syntax_highlighters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/utils/languages/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/calltip_widget.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/completion_popup.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/quick_open_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/quick_symbol_dialog.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/search_replace_frame.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/tab_splitter.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/widgets/tabbed_editor.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/languages/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/__init__.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/sigmund.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.28 → pyqt_code_editor-0.0.30}/pyqt_code_editor/worker/providers/symbol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|