Skip to content

Commit aee8378

Browse files
committed
fix: made RobotCode work with Python 3.12
Because of some changes in `runtime_protocols', see python doc
1 parent 7f52283 commit aee8378

File tree

11 files changed

+78
-51
lines changed

11 files changed

+78
-51
lines changed

hatch.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ extra-dependencies = [
4848
"robotframework @ git+https://github.com/robotframework/robotframework.git",
4949
]
5050

51-
[envs.py312_rfmaster]
51+
[envs.py312_latest]
5252
python = "3.12"
5353
extra-dependencies = [
54-
"robotframework @ git+https://github.com/robotframework/robotframework.git",
54+
"robotframework==6.1.1",
5555
]
5656

5757
[envs.rfdevel]

packages/core/src/robotcode/core/dataclasses.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,6 @@ def _decode_case(cls, s: str) -> str: # pragma: no cover
105105
...
106106

107107

108-
@runtime_checkable
109-
class ConfigBase(HasCaseDecoder, HasCaseEncoder, Protocol):
110-
pass
111-
112-
113108
_T = TypeVar("_T")
114109

115110

packages/core/src/robotcode/core/utils/inspect.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import inspect
2-
from typing import Any, Callable, Coroutine, Iterator, List, Optional
2+
from typing import Any, Callable, Coroutine, Iterator, Optional
33

44

55
def iter_methods(
@@ -22,13 +22,6 @@ def iter_methods(
2222
yield m
2323

2424

25-
def get_methods(
26-
instance_or_type: Any,
27-
predicate: Optional[Callable[[Callable[..., Any]], bool]] = None,
28-
) -> List[Callable[..., Any]]:
29-
return list(iter_methods(instance_or_type, predicate))
30-
31-
3225
_lambda_type = type(lambda: 0)
3326
_lambda_name = (lambda: 0).__name__
3427

packages/jsonrpc2/src/robotcode/jsonrpc2/protocol.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ class RpcMethodEntry(NamedTuple):
154154

155155
@runtime_checkable
156156
class RpcMethod(Protocol):
157+
__slots__ = "__rpc_method__"
158+
157159
__rpc_method__: RpcMethodEntry
158160

159161

@@ -264,7 +266,12 @@ def get_methods(obj: Any) -> Dict[str, RpcMethodEntry]:
264266
)
265267
for method, rpc_method in map(
266268
lambda m1: (m1, cast(RpcMethod, m1)),
267-
filter(lambda m2: isinstance(m2, RpcMethod), iter_methods(obj)),
269+
iter_methods(
270+
obj,
271+
lambda m2: isinstance(m2, RpcMethod)
272+
or inspect.ismethod(m2)
273+
and isinstance(m2.__func__, RpcMethod),
274+
),
268275
)
269276
}
270277

@@ -761,7 +768,13 @@ async def handle_request(self, message: JsonRPCRequest) -> None:
761768

762769
params = self._convert_params(e.method, e.param_type, message.params)
763770

764-
if isinstance(e.method, HasThreaded) and e.method.__threaded__:
771+
if (
772+
isinstance(e.method, HasThreaded)
773+
and e.method.__threaded__
774+
or inspect.ismethod(e.method)
775+
and isinstance(e.method.__func__, HasThreaded)
776+
and e.method.__func__.__threaded__
777+
):
765778
task = run_coroutine_in_thread(
766779
ensure_coroutine(cast(Callable[..., Any], e.method)), *params[0], **params[1]
767780
)
@@ -826,7 +839,13 @@ async def handle_notification(self, message: JsonRPCNotification) -> None:
826839
try:
827840
params = self._convert_params(e.method, e.param_type, message.params)
828841

829-
if isinstance(e.method, HasThreaded) and e.method.__threaded__:
842+
if (
843+
isinstance(e.method, HasThreaded)
844+
and e.method.__threaded__
845+
or inspect.ismethod(e.method)
846+
and isinstance(e.method.__func__, HasThreaded)
847+
and e.method.__func__.__threaded__
848+
):
830849
task = run_coroutine_in_thread(
831850
ensure_coroutine(cast(Callable[..., Any], e.method)), *params[0], **params[1]
832851
)
Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
from typing import Any, Callable, List, Protocol, Set, TypeVar, Union, runtime_checkable
1+
from typing import Any, Callable, List, Protocol, TypeVar, Union, runtime_checkable
22

33
from .text_document import TextDocument
44

55
_F = TypeVar("_F", bound=Callable[..., Any])
66

7+
LANGUAGE_ID_ATTR = "__language_id__"
8+
79

810
def language_id(id: str, *ids: str) -> Callable[[_F], _F]:
911
def decorator(func: _F) -> _F:
10-
setattr(func, "__language_id__", {id, *ids})
12+
setattr(func, LANGUAGE_ID_ATTR, {id, *ids})
1113
return func
1214

1315
return decorator
1416

1517

16-
@runtime_checkable
17-
class HasLanguageId(Protocol):
18-
__language_id__: Set[str]
18+
TRIGGER_CHARACTERS_ATTR = "__trigger_characters__"
1919

2020

2121
def trigger_characters(characters: List[str]) -> Callable[[_F], _F]:
2222
def decorator(func: _F) -> _F:
23-
setattr(func, "__trigger_characters__", characters)
23+
setattr(func, TRIGGER_CHARACTERS_ATTR, characters)
2424
return func
2525

2626
return decorator
@@ -31,22 +31,28 @@ class HasTriggerCharacters(Protocol):
3131
__trigger_characters__: List[str]
3232

3333

34+
RETRIGGER_CHARACTERS_ATTR = "__retrigger_characters__"
35+
36+
3437
@runtime_checkable
3538
class HasRetriggerCharacters(Protocol):
3639
__retrigger_characters__: str
3740

3841

3942
def retrigger_characters(characters: List[str]) -> Callable[[_F], _F]:
4043
def decorator(func: _F) -> _F:
41-
setattr(func, "__retrigger_characters__", characters)
44+
setattr(func, RETRIGGER_CHARACTERS_ATTR, characters)
4245
return func
4346

4447
return decorator
4548

4649

50+
ALL_COMMIT_CHARACTERS_ATTR = "__all_commit_characters__"
51+
52+
4753
def all_commit_characters(characters: List[str]) -> Callable[[_F], _F]:
4854
def decorator(func: _F) -> _F:
49-
setattr(func, "__all_commit_characters__", characters)
55+
setattr(func, ALL_COMMIT_CHARACTERS_ATTR, characters)
5056
return func
5157

5258
return decorator
@@ -57,9 +63,12 @@ class HasAllCommitCharacters(Protocol):
5763
__all_commit_characters__: List[str]
5864

5965

66+
CODE_ACTION_KINDS_ATTR = "__code_action_kinds__"
67+
68+
6069
def code_action_kinds(characters: List[str]) -> Callable[[_F], _F]:
6170
def decorator(func: _F) -> _F:
62-
setattr(func, "__code_action_kinds__", characters)
71+
setattr(func, CODE_ACTION_KINDS_ATTR, characters)
6372
return func
6473

6574
return decorator
@@ -72,33 +81,35 @@ class HasCodeActionKinds(Protocol):
7281

7382
def language_id_filter(language_id_or_document: Union[str, TextDocument]) -> Callable[[Any], bool]:
7483
def filter(c: Any) -> bool:
75-
return not isinstance(c, HasLanguageId) or (
84+
return not hasattr(c, LANGUAGE_ID_ATTR) or (
7685
(
7786
language_id_or_document.language_id
7887
if isinstance(language_id_or_document, TextDocument)
7988
else language_id_or_document
8089
)
81-
in c.__language_id__
90+
in getattr(c, LANGUAGE_ID_ATTR)
8291
)
8392

8493
return filter
8594

8695

87-
@runtime_checkable
88-
class IsCommand(Protocol):
89-
__command_name__: str
96+
COMMAND_NAME_ATTR = "__command_name__"
9097

9198

9299
def command(name: str) -> Callable[[_F], _F]:
93100
def decorator(func: _F) -> _F:
94-
setattr(func, "__command_name__", name)
101+
setattr(func, COMMAND_NAME_ATTR, name)
95102
return func
96103

97104
return decorator
98105

99106

107+
def is_command(func: Callable[..., Any]) -> bool:
108+
return hasattr(func, COMMAND_NAME_ATTR)
109+
110+
100111
def get_command_name(func: Callable[..., Any]) -> str:
101-
if isinstance(func, IsCommand):
102-
return func.__command_name__ # type: ignore
112+
if hasattr(func, COMMAND_NAME_ATTR):
113+
return str(getattr(func, COMMAND_NAME_ATTR))
103114

104115
raise TypeError(f"{func} is not a command.")

packages/language_server/src/robotcode/language_server/common/parts/code_action.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
TextDocumentIdentifier,
1818
)
1919
from robotcode.jsonrpc2.protocol import rpc_method
20-
from robotcode.language_server.common.decorators import HasCodeActionKinds, language_id_filter
20+
from robotcode.language_server.common.decorators import CODE_ACTION_KINDS_ATTR, HasCodeActionKinds, language_id_filter
2121
from robotcode.language_server.common.has_extend_capabilities import HasExtendCapabilities
2222
from robotcode.language_server.common.parts.protocol_part import LanguageServerProtocolPart
2323
from robotcode.language_server.common.text_document import TextDocument
@@ -49,7 +49,7 @@ def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
4949
*[
5050
cast(HasCodeActionKinds, e).__code_action_kinds__
5151
for e in self.collect
52-
if isinstance(e, HasCodeActionKinds)
52+
if hasattr(e, CODE_ACTION_KINDS_ATTR)
5353
]
5454
)
5555
)

packages/language_server/src/robotcode/language_server/common/parts/commands.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
ServerCapabilities,
1818
)
1919
from robotcode.jsonrpc2.protocol import JsonRPCErrorException, rpc_method
20-
from robotcode.language_server.common.decorators import IsCommand, get_command_name
20+
from robotcode.language_server.common.decorators import get_command_name, is_command
2121
from robotcode.language_server.common.has_extend_capabilities import HasExtendCapabilities
2222
from robotcode.language_server.common.parts.protocol_part import LanguageServerProtocolPart
2323

@@ -60,7 +60,7 @@ def register_all(self, instance: object) -> None:
6060
getattr(instance, k) for k, v in type(instance).__dict__.items() if callable(v) and not k.startswith("_")
6161
]
6262
for method in all_methods:
63-
if isinstance(method, IsCommand):
63+
if is_command(method):
6464
self.register(cast(_FUNC_TYPE, method))
6565

6666
def get_command_name(self, callback: _FUNC_TYPE, name: Optional[str] = None) -> str:

packages/language_server/src/robotcode/language_server/common/parts/completion.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@
1919
TextEdit,
2020
)
2121
from robotcode.jsonrpc2.protocol import rpc_method
22-
from robotcode.language_server.common.decorators import HasAllCommitCharacters, HasTriggerCharacters, language_id_filter
22+
from robotcode.language_server.common.decorators import (
23+
ALL_COMMIT_CHARACTERS_ATTR,
24+
TRIGGER_CHARACTERS_ATTR,
25+
HasAllCommitCharacters,
26+
HasTriggerCharacters,
27+
language_id_filter,
28+
)
2329
from robotcode.language_server.common.has_extend_capabilities import HasExtendCapabilities
2430
from robotcode.language_server.common.parts.protocol_part import LanguageServerProtocolPart
2531
from robotcode.language_server.common.text_document import TextDocument
@@ -51,7 +57,7 @@ def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
5157
*[
5258
cast(HasTriggerCharacters, e).__trigger_characters__
5359
for e in self.collect
54-
if isinstance(e, HasTriggerCharacters)
60+
if hasattr(e, TRIGGER_CHARACTERS_ATTR)
5561
]
5662
)
5763
)
@@ -61,7 +67,7 @@ def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
6167
*[
6268
cast(HasAllCommitCharacters, e).__all_commit_characters__
6369
for e in self.collect
64-
if isinstance(e, HasAllCommitCharacters)
70+
if hasattr(e, ALL_COMMIT_CHARACTERS_ATTR)
6571
]
6672
)
6773
)

packages/language_server/src/robotcode/language_server/common/parts/inline_value.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
)
1919
from robotcode.jsonrpc2.protocol import rpc_method
2020
from robotcode.language_server.common.decorators import (
21-
HasLanguageId,
21+
LANGUAGE_ID_ATTR,
2222
language_id_filter,
2323
)
2424
from robotcode.language_server.common.has_extend_capabilities import (
@@ -52,8 +52,8 @@ def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
5252
if len(self.collect):
5353
document_filters: DocumentSelector = []
5454
for e in self.collect:
55-
if isinstance(e, HasLanguageId):
56-
for lang_id in e.__language_id__: # type: ignore
55+
if hasattr(e, LANGUAGE_ID_ATTR):
56+
for lang_id in getattr(e, LANGUAGE_ID_ATTR):
5757
document_filters.append(TextDocumentFilterType1(language=lang_id))
5858
capabilities.inline_value_provider = InlineValueRegistrationOptions(
5959
work_done_progress=True,

packages/language_server/src/robotcode/language_server/common/parts/signature_help.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
TextDocumentIdentifier,
1717
)
1818
from robotcode.jsonrpc2.protocol import rpc_method
19-
from robotcode.language_server.common.decorators import HasRetriggerCharacters, HasTriggerCharacters, language_id_filter
19+
from robotcode.language_server.common.decorators import (
20+
RETRIGGER_CHARACTERS_ATTR,
21+
TRIGGER_CHARACTERS_ATTR,
22+
HasRetriggerCharacters,
23+
HasTriggerCharacters,
24+
language_id_filter,
25+
)
2026
from robotcode.language_server.common.has_extend_capabilities import HasExtendCapabilities
2127
from robotcode.language_server.common.text_document import TextDocument
2228

@@ -45,7 +51,7 @@ def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
4551
*[
4652
cast(HasTriggerCharacters, e).__trigger_characters__
4753
for e in self.collect
48-
if isinstance(e, HasTriggerCharacters)
54+
if hasattr(e, TRIGGER_CHARACTERS_ATTR)
4955
]
5056
)
5157
)
@@ -55,7 +61,7 @@ def extend_capabilities(self, capabilities: ServerCapabilities) -> None:
5561
*[
5662
cast(HasRetriggerCharacters, e).__retrigger_characters__
5763
for e in self.collect
58-
if isinstance(e, HasRetriggerCharacters)
64+
if hasattr(e, RETRIGGER_CHARACTERS_ATTR)
5965
]
6066
)
6167
)

0 commit comments

Comments
 (0)