Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8d1a47c

Browse files
committed
Update utils module
1 parent f40bc75 commit 8d1a47c

6 files changed

Lines changed: 469 additions & 257 deletions

File tree

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ repos:
2020
- id: sort-simple-yaml
2121
files: .pre-commit-config.yaml
2222
- repo: https://github.com/astral-sh/ruff-pre-commit
23-
rev: v0.13.3
23+
rev: v0.14.0
2424
hooks:
2525
- id: ruff-format
2626
- id: ruff-check
@@ -38,7 +38,7 @@ repos:
3838
additional_dependencies:
3939
- tomli
4040
- repo: https://github.com/adhtruong/mirrors-typos
41-
rev: v1.37.2
41+
rev: v1.38.0
4242
hooks:
4343
- id: typos
4444
- repo: https://github.com/woodruffw/zizmor-pre-commit

pyproject.toml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ classifiers = [
3333
]
3434
keywords = ["mypy", "dmypy", "idle", "extension", "development", "daemon"]
3535
dependencies = [
36-
"mypy[dmypy]>=1.17.0",
36+
"mypy[dmypy]>=1.18.2",
3737
'orjson>=3.10.18',
3838
"trio>=0.30.0",
3939
]
@@ -98,6 +98,9 @@ disable_all_dunder_policy = true
9898

9999
[tool.typos]
100100
files.extend-exclude = ["*.pyi"]
101+
default.extend-ignore-re = [
102+
"(?Rm)^.*(#|//)\\s*spellchecker:disable-line$",
103+
]
101104

102105
[tool.black]
103106
line-length = 79
@@ -158,15 +161,6 @@ extend-ignore = [
158161
"D103", # undocumented-public-function
159162
"D107", # undocumented-public-init
160163
]
161-
"stubs/*" = [
162-
"A001", # builtin-variable-shadowing
163-
"A002", # builtin-argument-shadowing
164-
"N802", # invalid-function-name (lowercase)
165-
"N803", # invalid-argument-name (lowercase)
166-
"N815", # mixed-case-variable-in-class-scope
167-
"N816", # mixed-case-variable-in-global-scope
168-
"N818", # error-suffix-on-exception-name
169-
]
170164

171165
[tool.pytest.ini_options]
172166
addopts = "--cov-report=xml --cov-report=term-missing --cov=idlemypyextension"

src/idlemypyextension/extension.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@
4747
DAEMON_TIMEOUT_MIN: Final = 5
4848
ACTION_TIMEOUT_MIN: Final = 5
4949
UNKNOWN_FILE: Final = "<unknown file>"
50-
COULD_NOT_START_ERROR = client.Response(
50+
COULD_NOT_START_ERROR: Final = client.Response(
5151
{"out": "", "err": "Error: Could not start mypy daemon"},
5252
)
53+
MYPY_ERROR_TYPE: Final = re.compile(r" \[([a-z\-]+)\]\s*$")
5354

5455

5556
def debug(message: object) -> None:
@@ -66,9 +67,6 @@ def debug(message: object) -> None:
6667
print(f"\n[{__name__}] DEBUG: {as_str}")
6768

6869

69-
MYPY_ERROR_TYPE: Final = re.compile(r" \[([a-z\-]+)\]\s*$")
70-
71-
7270
def parse_comments(
7371
mypy_output: str,
7472
default_file: str = "<unknown file>",

src/idlemypyextension/utils.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,21 @@ def wrapper(*args: PS.args, **kwargs: PS.kwargs) -> T:
401401
return wrapper
402402

403403

404+
def log_exceptions_catch(function: Callable[PS, T]) -> Callable[PS, T | None]:
405+
"""Log and catch any exceptions raised."""
406+
407+
@wraps(function)
408+
def wrapper(*args: PS.args, **kwargs: PS.kwargs) -> T | None:
409+
"""Catch Exceptions, log them to log file. Return None on error."""
410+
try:
411+
return function(*args, **kwargs)
412+
except Exception as exc:
413+
extension_log_exception(exc)
414+
return None
415+
416+
return wrapper
417+
418+
404419
class Comment(NamedTuple):
405420
"""Represents one comment."""
406421

@@ -466,7 +481,7 @@ def parse(cls, file_position: str) -> Self:
466481
if sys.platform == "win32":
467482
windows_drive_letter, file_position = file_position.split(":", 1)
468483
windows_drive_letter += ":"
469-
position = file_position.split(":", 5)
484+
position = file_position.rsplit(":", 5)
470485

471486
filename = position[0]
472487
if len(position) > 1:
@@ -492,6 +507,25 @@ def parse(cls, file_position: str) -> Self:
492507
col_end=col_end,
493508
)
494509

510+
def serialize(self) -> str:
511+
"""Return file position as string."""
512+
if self.is_range():
513+
return f"{self.path}:{self.line}:{self.col}:{self.line_end}:{self.col_end}"
514+
if self.col != 0:
515+
return f"{self.path}:{self.line}:{self.col}"
516+
return f"{self.path}:{self.line}"
517+
518+
@classmethod
519+
def from_editor_current(cls, editwin: PyShellEditorWindow) -> Self | None:
520+
"""Return file position from editwin current position."""
521+
current_filename = editwin.io.filename
522+
if current_filename is None:
523+
return None
524+
current_filename = str(Path(current_filename).absolute())
525+
selected = get_selected_text_indexes(editwin.text)
526+
select_string = (":".join(selected)).replace(".", ":")
527+
return cls.parse(f"{current_filename}:{select_string}")
528+
495529

496530
class BaseExtension:
497531
"""Base extension class."""

tests/test_utils.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
from __future__ import annotations
22

3+
import sys
4+
from typing import Final
5+
36
import pytest
47

58
from idlemypyextension import utils
69

10+
IS_WINDOWS: Final = sys.platform == "win32"
11+
712

813
def test_get_required_config() -> None:
914
assert (
@@ -81,3 +86,140 @@ def test_get_whole_line(index: str, offset: int, expect: str) -> None:
8186
)
8287
def test_get_line_indent(text: str, expect: int) -> None:
8388
assert utils.get_line_indent(text, " ") == expect
89+
90+
91+
@pytest.mark.skipif(
92+
IS_WINDOWS,
93+
reason="Skipping Unix-specific tests on Windows",
94+
)
95+
def test_fileposition_parse_unix() -> None:
96+
assert utils.FilePosition.parse(
97+
"src/idleopenline/utils.py:59",
98+
) == utils.FilePosition("src/idleopenline/utils.py", 59, 0, 59, 0)
99+
assert utils.FilePosition.parse(
100+
"src/idleopenline/utils.py:59:43",
101+
) == utils.FilePosition(
102+
"src/idleopenline/utils.py",
103+
59,
104+
43,
105+
59,
106+
43,
107+
)
108+
assert utils.FilePosition.parse(
109+
"src/idleopenline/utils.py:59:43:60",
110+
) == utils.FilePosition(
111+
"src/idleopenline/utils.py",
112+
59,
113+
43,
114+
59,
115+
43,
116+
)
117+
assert utils.FilePosition.parse(
118+
"src/idleopenline/utils.py:59:43:60:48",
119+
) == utils.FilePosition(
120+
"src/idleopenline/utils.py",
121+
59,
122+
43,
123+
60,
124+
48,
125+
)
126+
assert utils.FilePosition.parse(
127+
"src/idleopenline/utils.py:59:43:60:48:103",
128+
) == utils.FilePosition(
129+
"src/idleopenline/utils.py",
130+
59,
131+
43,
132+
60,
133+
48,
134+
)
135+
136+
137+
@pytest.mark.skipif(
138+
not IS_WINDOWS,
139+
reason="Skipping Windows-specific tests on non-Windows platforms",
140+
)
141+
def test_fileposition_parse_windows() -> None:
142+
assert utils.FilePosition.parse(
143+
"C:\\path\\to\\file.py:59",
144+
) == utils.FilePosition("C:\\path\\to\\file.py", 59, 0, 59, 0)
145+
assert utils.FilePosition.parse(
146+
"C:\\path\\to\\file.py:59:43",
147+
) == utils.FilePosition(
148+
"C:\\path\\to\\file.py",
149+
59,
150+
43,
151+
59,
152+
43,
153+
)
154+
assert utils.FilePosition.parse(
155+
"C:\\path\\to\\file.py:59:43:60",
156+
) == utils.FilePosition(
157+
"C:\\path\\to\\file.py",
158+
59,
159+
43,
160+
59,
161+
43,
162+
)
163+
assert utils.FilePosition.parse(
164+
"C:\\path\\to\\file.py:59:43:60:48",
165+
) == utils.FilePosition(
166+
"C:\\path\\to\\file.py",
167+
59,
168+
43,
169+
60,
170+
48,
171+
)
172+
assert utils.FilePosition.parse(
173+
"C:\\path\\to\\file.py:59:43:60:48:103",
174+
) == utils.FilePosition(
175+
"C:\\path\\to\\file.py",
176+
59,
177+
43,
178+
60,
179+
48,
180+
)
181+
182+
183+
def test_fileposition_is_range() -> None:
184+
assert not utils.FilePosition(
185+
"src/idleopenline/utils.py",
186+
59,
187+
0,
188+
59,
189+
0,
190+
).is_range()
191+
assert not utils.FilePosition(
192+
"src/idleopenline/utils.py",
193+
59,
194+
43,
195+
59,
196+
43,
197+
).is_range()
198+
assert utils.FilePosition(
199+
"src/idleopenline/utils.py",
200+
59,
201+
43,
202+
60,
203+
48,
204+
).is_range()
205+
assert utils.FilePosition(
206+
"src/idleopenline/utils.py",
207+
59,
208+
43,
209+
59,
210+
48,
211+
).is_range()
212+
assert utils.FilePosition(
213+
"src/idleopenline/utils.py",
214+
59,
215+
43,
216+
60,
217+
43,
218+
).is_range()
219+
assert utils.FilePosition(
220+
"src/idleopenline/utils.py",
221+
59,
222+
43,
223+
60,
224+
48,
225+
).is_range()

0 commit comments

Comments
 (0)