pyqt-code-editor 0.0.21__tar.gz → 0.0.22__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.21 → pyqt_code_editor-0.0.22}/PKG-INFO +1 -1
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/__init__.py +1 -1
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/_settings.py +1 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/app.py +1 -1
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/jupyter_console.py +18 -12
- pyqt_code_editor-0.0.22/pyqt_code_editor/environment_manager.py +29 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/complete.py +10 -2
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/file_link.py +51 -5
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/languages/python.py +3 -2
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/process.py +7 -4
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/jedi.py +14 -8
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/COPYING +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyproject.toml +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/code_editors.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/languages/generic.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/languages/markdown.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/languages/python.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/languages/text.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/editor_panel.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/find_in_files.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/project_explorer.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/settings_panel.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/sigmund.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/workspace_explorer.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/auto_indent.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/auto_pair.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/base.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/check.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/comment.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/execute.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/line_number.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/python_auto_indent.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/search_replace.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/shortcuts.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/smart_backspace_delete.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/symbols.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/theme.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/widgets/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/zoom.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/signal_router.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/syntax_highlighters/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/syntax_highlighters/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/syntax_highlighters/languages/generic.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/syntax_highlighters/languages/python.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/syntax_highlighters/syntax_highlighter.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/themes.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/utils/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/utils/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/utils/languages/python/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/utils/languages/python/_auto_indent.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/utils/languages/python/_extract_cells.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/utils/languages/python/_mask_str_in_code.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/watchdog.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/calltip_widget.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/completion_popup.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/dock.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/quick_open_dialog.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/quick_open_file_dialog.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/quick_symbol_dialog.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/search_replace_frame.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/tab_splitter.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/tabbed_editor.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/languages/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/languages/generic.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/manager.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/__init__.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/codestral.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/ruff.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/sigmund.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/symbol.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/settings.py +0 -0
- {pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/readme.md +0 -0
|
@@ -84,6 +84,7 @@ class Settings(QObject):
|
|
|
84
84
|
default_filename = SettingProperty('untitled.txt', "Files")
|
|
85
85
|
default_language = SettingProperty('python', "Files")
|
|
86
86
|
default_encoding = SettingProperty('utf-8', "Files")
|
|
87
|
+
max_file_size = SettingProperty(5 * 1024 ** 2, "Files") # 5 MB)
|
|
87
88
|
|
|
88
89
|
# Keyboard shortcuts
|
|
89
90
|
shortcut_move_line_up = SettingProperty('Alt+Up', "Shortcuts")
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/jupyter_console.py
RENAMED
|
@@ -5,12 +5,14 @@ from qtconsole.rich_jupyter_widget import RichJupyterWidget
|
|
|
5
5
|
from qtconsole.manager import QtKernelManager
|
|
6
6
|
from jupyter_client.kernelspec import KernelSpecManager
|
|
7
7
|
import qtawesome as qta
|
|
8
|
+
import sys
|
|
8
9
|
import os
|
|
9
10
|
import logging
|
|
10
11
|
import uuid
|
|
11
12
|
import json
|
|
12
13
|
from concurrent.futures import Future
|
|
13
14
|
from .. import settings
|
|
15
|
+
from ..environment_manager import environment_manager
|
|
14
16
|
from ..themes import THEMES, OUTER_CONTENT_MARGINS, HORIZONTAL_SPACING
|
|
15
17
|
from ..widgets import Dock
|
|
16
18
|
from .. import watchdog
|
|
@@ -359,8 +361,8 @@ print(json.dumps({result_var}))
|
|
|
359
361
|
class JupyterConsole(Dock):
|
|
360
362
|
"""Dockable widget containing tabbed Jupyter consoles"""
|
|
361
363
|
|
|
362
|
-
execution_complete = Signal(str, object)
|
|
363
|
-
workspace_updated = Signal(dict)
|
|
364
|
+
execution_complete = Signal(str, object)
|
|
365
|
+
workspace_updated = Signal(dict)
|
|
364
366
|
|
|
365
367
|
def __init__(self, parent=None, default_kernel='python3'):
|
|
366
368
|
super().__init__("Jupyter Console", parent)
|
|
@@ -370,7 +372,7 @@ class JupyterConsole(Dock):
|
|
|
370
372
|
# ---------------------------------------------------------------------
|
|
371
373
|
# Kernel cache
|
|
372
374
|
# ---------------------------------------------------------------------
|
|
373
|
-
self.available_kernels =
|
|
375
|
+
self.available_kernels = {} # will be filled by refresh_kernel_menu()
|
|
374
376
|
|
|
375
377
|
# ---------------------------------------------------------------------
|
|
376
378
|
# UI setup
|
|
@@ -429,6 +431,14 @@ class JupyterConsole(Dock):
|
|
|
429
431
|
console_tab = self.tab_widget.widget(index)
|
|
430
432
|
if console_tab:
|
|
431
433
|
console_tab.update_workspace()
|
|
434
|
+
spec = self.available_kernels.get(console_tab.kernel_name, None)
|
|
435
|
+
if spec:
|
|
436
|
+
python_executable = spec['spec']['argv'][0]
|
|
437
|
+
else:
|
|
438
|
+
python_executable = sys.executable
|
|
439
|
+
environment_manager.set_environment(console_tab.kernel_name,
|
|
440
|
+
python_executable,
|
|
441
|
+
'python')
|
|
432
442
|
|
|
433
443
|
# -------------------------------------------------------------------------
|
|
434
444
|
# Kernel handling
|
|
@@ -439,12 +449,9 @@ class JupyterConsole(Dock):
|
|
|
439
449
|
|
|
440
450
|
# Get available kernelspecs
|
|
441
451
|
kernel_spec_manager = HomeAwareKernelSpecManager()
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
self.available_kernels = list(specs.keys())
|
|
446
|
-
|
|
447
|
-
for spec_name, spec in specs.items():
|
|
452
|
+
self.available_kernels = kernel_spec_manager.get_all_specs()
|
|
453
|
+
self.fallback_kernel = list(self.available_kernels.keys())[0]
|
|
454
|
+
for spec_name, spec in self.available_kernels.items():
|
|
448
455
|
display_name = spec['spec']['display_name']
|
|
449
456
|
action = QAction(display_name, self)
|
|
450
457
|
action.setData(spec_name)
|
|
@@ -462,12 +469,11 @@ class JupyterConsole(Dock):
|
|
|
462
469
|
"""
|
|
463
470
|
if kernel_name not in self.available_kernels:
|
|
464
471
|
if self.available_kernels:
|
|
465
|
-
fallback = self.available_kernels[0]
|
|
466
472
|
logger.warning(
|
|
467
473
|
"Requested kernel '%s' not found. "
|
|
468
|
-
"Falling back to '%s'.", kernel_name,
|
|
474
|
+
"Falling back to '%s'.", kernel_name, self.fallback_kernel
|
|
469
475
|
)
|
|
470
|
-
kernel_name =
|
|
476
|
+
kernel_name = self.fallback_kernel
|
|
471
477
|
else:
|
|
472
478
|
logger.error("No available kernels found. Cannot create console tab.")
|
|
473
479
|
return None
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from qtpy.QtCore import Signal, QObject
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class EnvironmentManager(QObject):
|
|
5
|
+
"""Singleton class to share the current environment and language between all
|
|
6
|
+
components of the app.
|
|
7
|
+
"""
|
|
8
|
+
environment_changed = Signal(str, str, str)
|
|
9
|
+
|
|
10
|
+
def __init__(self):
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.name = None
|
|
13
|
+
self.path = None
|
|
14
|
+
self.language = None
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def current_environment(self):
|
|
18
|
+
return self.name, self.path, self.language
|
|
19
|
+
|
|
20
|
+
def set_environment(self, name, path, language):
|
|
21
|
+
if path != self.path:
|
|
22
|
+
self.name = name
|
|
23
|
+
self.path = path
|
|
24
|
+
self.language = language
|
|
25
|
+
self.environment_changed.emit(name, path, language)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Singleton instance
|
|
29
|
+
environment_manager = EnvironmentManager()
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
1
3
|
import logging
|
|
2
4
|
from qtpy.QtCore import QTimer, Qt
|
|
3
5
|
from qtpy.QtGui import QTextCursor
|
|
4
6
|
from qtpy.QtWidgets import QApplication
|
|
5
7
|
from ..widgets.completion_popup import CompletionPopup
|
|
6
8
|
from ..widgets.calltip_widget import CalltipWidget
|
|
9
|
+
from ..environment_manager import environment_manager
|
|
7
10
|
from .. import settings
|
|
8
11
|
logging.basicConfig(level=logging.INFO, force=True)
|
|
9
12
|
logger = logging.getLogger(__name__)
|
|
@@ -273,7 +276,8 @@ class Complete:
|
|
|
273
276
|
cursor_pos=cursor_pos, full=full,
|
|
274
277
|
multiline=multiline,
|
|
275
278
|
path=self.code_editor_file_path,
|
|
276
|
-
language=self.code_editor_language
|
|
279
|
+
language=self.code_editor_language,
|
|
280
|
+
env_path=environment_manager.path)
|
|
277
281
|
|
|
278
282
|
def _cm_request_calltip(self):
|
|
279
283
|
"""Send a calltip request."""
|
|
@@ -284,7 +288,8 @@ class Complete:
|
|
|
284
288
|
self.send_worker_request(action='calltip', code=code,
|
|
285
289
|
cursor_pos=cursor_pos,
|
|
286
290
|
path=self.code_editor_file_path,
|
|
287
|
-
language=self.code_editor_language
|
|
291
|
+
language=self.code_editor_language,
|
|
292
|
+
env_path=environment_manager.path)
|
|
288
293
|
|
|
289
294
|
def _cm_hide_calltip(self):
|
|
290
295
|
"""Hide the calltip widget."""
|
|
@@ -533,3 +538,6 @@ class Complete:
|
|
|
533
538
|
def update_theme(self):
|
|
534
539
|
super().update_theme()
|
|
535
540
|
self._cm_calltip_widget.apply_stylesheet()
|
|
541
|
+
|
|
542
|
+
def _current_environment(self):
|
|
543
|
+
return os.environ.get('SIGMUND_PYENV', sys.executable)
|
|
@@ -40,7 +40,12 @@ class FileLink:
|
|
|
40
40
|
if not path.is_file():
|
|
41
41
|
raise FileNotFoundError(f"No such file: {path}")
|
|
42
42
|
|
|
43
|
+
# Check file size
|
|
44
|
+
file_size = path.stat().st_size
|
|
45
|
+
is_large = file_size > settings.max_file_size
|
|
46
|
+
|
|
43
47
|
raw_data = path.read_bytes()
|
|
48
|
+
encoding_unknown = False
|
|
44
49
|
|
|
45
50
|
if encoding is None:
|
|
46
51
|
# First see if everything is within ASCII range
|
|
@@ -51,14 +56,55 @@ class FileLink:
|
|
|
51
56
|
except UnicodeDecodeError:
|
|
52
57
|
# Not pure ASCII; let chardet pick
|
|
53
58
|
detect_result = chardet.detect(raw_data)
|
|
54
|
-
# If detection fails or returns None,
|
|
55
|
-
|
|
59
|
+
# If detection fails or returns None, or confidence is low
|
|
60
|
+
if (detect_result is None or
|
|
61
|
+
detect_result.get("encoding") is None or
|
|
62
|
+
detect_result.get("confidence", 0) < 0.7):
|
|
63
|
+
used_encoding = "utf-8"
|
|
64
|
+
encoding_unknown = True
|
|
65
|
+
else:
|
|
66
|
+
used_encoding = detect_result["encoding"]
|
|
56
67
|
else:
|
|
57
68
|
used_encoding = encoding
|
|
69
|
+
|
|
70
|
+
# Show warning if file is large or encoding is uncertain
|
|
71
|
+
if is_large or encoding_unknown:
|
|
72
|
+
warnings = []
|
|
73
|
+
if is_large:
|
|
74
|
+
size_mb = file_size / (1024 * 1024)
|
|
75
|
+
warnings.append(f"This file is {size_mb:.1f} MB, which exceeds the recommended maximum of {settings.max_file_size / (1024 * 1024):.1f} MB.")
|
|
76
|
+
if encoding_unknown:
|
|
77
|
+
warnings.append("The file encoding could not be reliably detected. It may not display correctly.")
|
|
78
|
+
|
|
79
|
+
warning_message = "\n\n".join(warnings)
|
|
80
|
+
warning_message += "\n\nDo you want to continue opening this file?"
|
|
81
|
+
|
|
82
|
+
reply = QMessageBox.warning(
|
|
83
|
+
self,
|
|
84
|
+
"File Warning",
|
|
85
|
+
warning_message,
|
|
86
|
+
QMessageBox.Yes | QMessageBox.No,
|
|
87
|
+
QMessageBox.No
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if reply != QMessageBox.Yes:
|
|
91
|
+
logger.info(f"User declined to open file: {path}")
|
|
92
|
+
return
|
|
93
|
+
|
|
58
94
|
logger.info(f'opening file as {used_encoding}')
|
|
59
95
|
# Try reading with the chosen encoding
|
|
60
|
-
|
|
61
|
-
|
|
96
|
+
try:
|
|
97
|
+
with path.open("r", encoding=used_encoding) as f:
|
|
98
|
+
content = f.read()
|
|
99
|
+
except UnicodeDecodeError as e:
|
|
100
|
+
# If decoding fails, offer to try as binary or cancel
|
|
101
|
+
reply = QMessageBox.critical(
|
|
102
|
+
self,
|
|
103
|
+
"Encoding Error",
|
|
104
|
+
f"Failed to decode file with {used_encoding} encoding.\n{str(e)}\n\nThis may not be a text file.",
|
|
105
|
+
QMessageBox.Cancel
|
|
106
|
+
)
|
|
107
|
+
return
|
|
62
108
|
|
|
63
109
|
# Store the content in the editor
|
|
64
110
|
self.setPlainText(content)
|
|
@@ -181,4 +227,4 @@ class FileLink:
|
|
|
181
227
|
# Re-add the file to watcher so we keep listening for future changes
|
|
182
228
|
if self._file_watcher is not None:
|
|
183
229
|
self._file_watcher.addPath(changed_path)
|
|
184
|
-
self._watch_file_changes = True
|
|
230
|
+
self._watch_file_changes = True
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/languages/python.py
RENAMED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
from ..providers import jedi, codestral, ruff
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def complete(code, cursor_pos, path, multiline, full):
|
|
4
|
+
def complete(code, cursor_pos, path, multiline, full, env_path):
|
|
5
5
|
if full or multiline:
|
|
6
6
|
codestral_completions = codestral.codestral_complete(
|
|
7
7
|
code, cursor_pos, path=path, multiline=multiline)
|
|
8
8
|
else:
|
|
9
9
|
codestral_completions = []
|
|
10
10
|
if not multiline:
|
|
11
|
-
jedi_completions = jedi.jedi_complete(code, cursor_pos, path=path
|
|
11
|
+
jedi_completions = jedi.jedi_complete(code, cursor_pos, path=path,
|
|
12
|
+
env_path=env_path)
|
|
12
13
|
else:
|
|
13
14
|
jedi_completions = []
|
|
14
15
|
# If there is at least one jedi completion, it is always insert at first.
|
|
@@ -68,9 +68,11 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
68
68
|
path = request.get('path', None)
|
|
69
69
|
multiline = request.get('multiline', False)
|
|
70
70
|
full = request.get('full', False)
|
|
71
|
-
|
|
71
|
+
env_path = request.get('env_path', None)
|
|
72
|
+
logger.info(f"Performing code completion: language='{language}', multiline={multiline}, path={path}, env_path={env_path}")
|
|
72
73
|
completions = worker_functions.complete(
|
|
73
|
-
code, cursor_pos, path=path, multiline=multiline, full=full
|
|
74
|
+
code, cursor_pos, path=path, multiline=multiline, full=full,
|
|
75
|
+
env_path=env_path)
|
|
74
76
|
if not completions:
|
|
75
77
|
logger.info("No completions")
|
|
76
78
|
else:
|
|
@@ -90,9 +92,10 @@ def main_worker_process_function(request_queue, result_queue):
|
|
|
90
92
|
else:
|
|
91
93
|
code = request.get('code', '')
|
|
92
94
|
path = request.get('path', None)
|
|
93
|
-
|
|
95
|
+
env_path = request.get('env_path', None)
|
|
96
|
+
logger.info(f"Performing calltip: language='{language}', path={path}, env_path={env_path}")
|
|
94
97
|
signatures = worker_functions.calltip(
|
|
95
|
-
code, cursor_pos, path=path)
|
|
98
|
+
code, cursor_pos, path=path, env_path=env_path)
|
|
96
99
|
if signatures is None:
|
|
97
100
|
logger.info("No calltip signatures. Sending result back.")
|
|
98
101
|
else:
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/jedi.py
RENAMED
|
@@ -20,7 +20,8 @@ def _signature_to_html(signature) -> str:
|
|
|
20
20
|
return f"({sig_line}){return_hint}"
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
def _prepare_jedi_script(code: str, cursor_position: int, path: str | None
|
|
23
|
+
def _prepare_jedi_script(code: str, cursor_position: int, path: str | None,
|
|
24
|
+
env_path: str | None):
|
|
24
25
|
"""
|
|
25
26
|
Prepare a Jedi Script object and calculate line_no/column_no from the
|
|
26
27
|
given code and cursor_position. Returns (script, line_no, column_no).
|
|
@@ -32,15 +33,17 @@ def _prepare_jedi_script(code: str, cursor_position: int, path: str | None):
|
|
|
32
33
|
column_no = cursor_position
|
|
33
34
|
else:
|
|
34
35
|
column_no = cursor_position - (last_newline_idx + 1)
|
|
35
|
-
|
|
36
36
|
logger.info("Creating Jedi Script for path=%r at line=%d, column=%d",
|
|
37
37
|
path, line_no, column_no)
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
# We explicitly indicate that the environment is safe, because we know that
|
|
39
|
+
# they come from the app itself
|
|
40
|
+
env = jedi.create_environment(env_path, safe=False) if env_path else None
|
|
41
|
+
script = jedi.Script(code, path=path, environment=env)
|
|
40
42
|
return script, line_no, column_no
|
|
41
43
|
|
|
42
44
|
|
|
43
|
-
def jedi_complete(code: str, cursor_position: int, path: str | None
|
|
45
|
+
def jedi_complete(code: str, cursor_position: int, path: str | None,
|
|
46
|
+
env_path: str | None = None) -> list[str]:
|
|
44
47
|
"""
|
|
45
48
|
Perform Python-specific completion using Jedi. Returns a list of possible completions
|
|
46
49
|
for the text at the given cursor position, or None if no completion is found.
|
|
@@ -57,7 +60,8 @@ def jedi_complete(code: str, cursor_position: int, path: str | None) -> list[str
|
|
|
57
60
|
if code_up_to_cursor.rfind('#') > code_up_to_cursor.rfind('\n'):
|
|
58
61
|
return []
|
|
59
62
|
# Go Jedi!
|
|
60
|
-
script, line_no, column_no = _prepare_jedi_script(code, cursor_position,
|
|
63
|
+
script, line_no, column_no = _prepare_jedi_script(code, cursor_position,
|
|
64
|
+
path, env_path)
|
|
61
65
|
completions = script.complete(line=line_no, column=column_no)
|
|
62
66
|
if not completions:
|
|
63
67
|
return []
|
|
@@ -70,7 +74,8 @@ def jedi_complete(code: str, cursor_position: int, path: str | None) -> list[str
|
|
|
70
74
|
|
|
71
75
|
def jedi_signatures(code: str, cursor_position: int, path: str | None,
|
|
72
76
|
multiline: bool = False, max_width: int = 40,
|
|
73
|
-
max_lines: int = 10
|
|
77
|
+
max_lines: int = 10,
|
|
78
|
+
env_path: str | None = None):
|
|
74
79
|
"""
|
|
75
80
|
Retrieve function signatures (calltips) from Jedi given the current cursor position.
|
|
76
81
|
Returns a list of strings describing each signature, or None if none.
|
|
@@ -84,7 +89,8 @@ def jedi_signatures(code: str, cursor_position: int, path: str | None,
|
|
|
84
89
|
return None
|
|
85
90
|
|
|
86
91
|
logger.info("Starting Jedi calltip request (multiline=%r).", multiline)
|
|
87
|
-
script, line_no, column_no = _prepare_jedi_script(code, cursor_position,
|
|
92
|
+
script, line_no, column_no = _prepare_jedi_script(code, cursor_position,
|
|
93
|
+
path, env_path)
|
|
88
94
|
|
|
89
95
|
signatures = script.get_signatures(line=line_no, column=column_no)
|
|
90
96
|
if not signatures:
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/__init__.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/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.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/code_editors/languages/text.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/editor_panel.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/find_in_files.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/components/project_explorer.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/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.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/python_auto_indent.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/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.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/mixins/widgets/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/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.21 → pyqt_code_editor-0.0.22}/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.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/calltip_widget.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/completion_popup.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/quick_open_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/quick_symbol_dialog.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/search_replace_frame.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/tab_splitter.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/widgets/tabbed_editor.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/languages/__init__.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/languages/generic.py
RENAMED
|
File without changes
|
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/__init__.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/codestral.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/ruff.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/sigmund.py
RENAMED
|
File without changes
|
{pyqt_code_editor-0.0.21 → pyqt_code_editor-0.0.22}/pyqt_code_editor/worker/providers/symbol.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|