8000 Add pyproject.toml with mypy section and type annotations such that `… · robotframework/robotframework@d1e6ce7 · GitHub
[go: up one dir, main page]

Skip to content

Commit d1e6ce7

Browse files
committed
Add pyproject.toml with mypy section and type annotations such that mypy src/robot/api runs successfully
1 parent 99ed036 commit d1e6ce7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+274
-175
lines changed

atest/testdata/keywords/type_conversion/FutureAnnotations.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from __future__ import annotations
21
from collections.abc import Mapping
32
from numbers import Integral
43
from typing import List

pyproject.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[tool.mypy]
2+
python_version = 3.6
3+
allow_redefinition = true
4+
show_error_codes = true
5+
strict_equality = true
6+
warn_redundant_casts = true
7+
warn_unused_ignores = true
8+
disallow_any_generics = true

src/robot/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# Allows running as a script. __name__ check needed with multiprocessing:
2121
# https://github.com/robotframework/robotframework/issues/1137
2222
if 'robot' not in sys.modules and __name__ == '__main__':
23-
import pythonpathsetter
23+
import pythonpathsetter # type: ignore[import]
2424

2525
from robot import run_cli
2626

src/robot/api/deco.py

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
1617
import inspect
1718

19+
from typing import TYPE_CHECKING, overload, cast, Any, Callable, TypeVar, Union, List, Tuple, Dict
20+
from typing_extensions import Literal
21+
22+
Fn = TypeVar("Fn", bound=Callable[..., Any])
23+
Cls = TypeVar("Cls", bound=type)
1824

19-
def not_keyword(func):
25+
def not_keyword(func: Fn) -> Fn:
2026
"""Decorator to disable exposing functions or methods as keywords.
2127
2228
Examples::
@@ -34,15 +40,20 @@ def exposed_as_keyword():
3440
3541
New in Robot Framework 3.2.
3642
"""
37-
func.robot_not_keyword = True
43+
func.robot_not_keyword = True # type: ignore[attr-defined]
3844
return func
3945

4046

41-
not_keyword.robot_not_keyword = True
47+
not_keyword.robot_not_keyword = True # type: ignore[attr-defined]
4248

49+
@overload
50+
def keyword(name: Fn) -> Fn: ...
51+
52+
@overload
53+
def keyword(name: str = None, tags: List[str] = ..., types: Union[Dict[str, type], List[type], None] = ...) -> Callable[[Fn], Fn]: ...
4354

4455
@not_keyword
45-
def keyword(name=None, tags=(), types=()):
56+
def keyword(name: Union[Fn, str, None] = None, tags: Union[List[str], Tuple[None, ...]] = (), types: Union[Dict[str, type], List[type], Tuple[None, ...], None] =()) -> Union[Callable[[Fn], Fn], Fn]:
4657
"""Decorator to set custom name, tags and argument types to keywords.
4758
4859
This decorator creates ``robot_name``, ``robot_tags`` and ``robot_types``
@@ -85,20 +96,26 @@ def no_conversion(length, case_insensitive=False):
8596
# ...
8697
"""
8798
if inspect.isroutine(name):
88-
return keyword()(name)
99+
return keyword()(name) # type: ignore[type-var, return-value]
89100

90-
def decorator(func):
91-
func.robot_name = name
92-
func.robot_tags = tags
93-
func.robot_types = types
101+
def decorator(func: Fn) -> Fn:
102+
func.robot_name = name# type:ignore[attr-defined]
103+
func.robot_tags = tags# type:ignore[attr-defined]
104+
func.robot_types = types# type:ignore[attr-defined]
94105
return func
95106

96107
return decorator
97108

109+
@overload
110+
def library(scope: Cls) -> Cls: ...
111+
112+
@overload
113+
def library(scope: Literal["GLOBAL", "SUITE", "TEST", None] = None, version: str =None, doc_format: str =None, listener: str=None,
114+
auto_keywords: bool=False) -> Callable[[Cls], Cls]: ...
98115

99116
@not_keyword
100-
def library(scope=None, version=None, doc_format=None, listener=None,
101-
auto_keywords=False):
117+
def library(scope: Union[Literal["GLOBAL", "SUITE", "TEST", None], Cls] = None, version: str =None, doc_format: str =None, listener: str=None,
118+
auto_keywords: bool=False) -> Union[Cls, Callable[[Cls], Cls]]:
102119
"""Class decorator to control keyword discovery and other library settings.
103120
104121
By default disables automatic keyword detection by setting class attribute
@@ -134,18 +151,18 @@ class LibraryConfiguration:
134151
The ``@library`` decorator is new in Robot Framework 3.2.
135152
"""
136153
if inspect.isclass(scope):
137-
return library()(scope)
154+
return library()(cast(type, scope))
138155

139-
def decorator(cls):
156+
def decorator(cls: Cls) -> Cls:
140157
if scope is not None:
141-
cls.ROBOT_LIBRARY_SCOPE = scope
158+
cls.ROBOT_LIBRARY_SCOPE = scope # type:ignore[attr-defined]
142159
if version is not None:
143-
cls.ROBOT_LIBRARY_VERSION = version
160+
cls.ROBOT_LIBRARY_VERSION = version# type:ignore[attr-defined]
144161
if doc_format is not None:
145-
cls.ROBOT_LIBRARY_DOC_FORMAT = doc_format
162+
cls.ROBOT_LIBRARY_DOC_FORMAT = doc_format# type:ignore[attr-defined]
146163
if listener is not None:
147-
cls.ROBOT_LIBRARY_LISTENER = listener
148-
cls.ROBOT_AUTO_KEYWORDS = auto_keywords
164+
cls.ROBOT_LIBRARY_LISTENER = listener# type:ignore[attr-defined]
165+
cls.ROBOT_AUTO_KEYWORDS = auto_keywords# type:ignore[attr-defined]
149166
return cls
150167

151168
return decorator

src/robot/api/exceptions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class Failure(AssertionError):
3131
"""
3232
ROBOT_SUPPRESS_NAME = True
3333

34-
def __init__(self, message, html=False):
34+
def __init__(self, message: str, html: bool=False) -> None:
3535
"""
3636
:param message: Exception message.
3737
:param html: When ``True``, message is considered to be HTML and not escaped.
@@ -57,7 +57,7 @@ class Error(RuntimeError):
5757
"""
5858
ROBOT_SUPPRESS_NAME = True
5959

60-
def __init__(self, message, html=False):
60+
def __init__(self, message: str, html: bool=False) -> None:
6161
"""
6262
:param message: Exception message.
6363
:param html: When ``True``, message is considered to be HTML and not escaped.
@@ -76,7 +76,7 @@ class SkipExecution(Exception):
7676
ROBOT_SKIP_EXECUTION = True
7777
ROBOT_SUPPRESS_NAME = True
7878

79-
def __init__(self, message, html=False):
79+
def __init__(self, message: str, html: bool=False) -> None:
8080
"""
8181
:param message: Exception message.
8282
:param html: When ``True``, message is considered to be HTML and not escaped.

src/robot/api/logger.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ def my_keyword(arg):
7070
from robot.output import librarylogger
7171
from robot.running.context import EXECUTION_CONTEXTS
7272

73+
from typing_extensions import Literal
7374

74-
def write(msg, level='INFO', html=False):
75+
76+
def write(msg: str, level: Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR"] = 'INFO', html: bool = False) -> None:
7577
"""Writes the message to the log file using the given level.
7678
7779
Valid log levels are ``TRACE``, ``DEBUG``, ``INFO`` (default), ``WARN``, and
@@ -86,26 +88,28 @@ def write(msg, level='INFO', html=False):
8688
librarylogger.write(msg, level, html)
8789
else:
8890
logger = logging.getLogger("RobotFramework")
89-
level = {'TRACE': logging.DEBUG // 2,
91+
level = {'TRACE': logging.DEBUG // 2, # type: ignore[assignment]
9092
'DEBUG': logging.DEBUG,
9193
'INFO': logging.INFO,
9294
'HTML': logging.INFO,
9395
'WARN': logging.WARN,
9496
'ERROR': logging.ERROR}[level]
95-
logger.log(level, msg)
97+
logger.log(level, msg) # type: ignore[arg-type]
98+
99+
96100

97101

98-
def trace(msg, html=False):
102+
def trace(msg: str, html: bool=False) -> None:
99103
"""Writes the message to the log file using the ``TRACE`` level."""
100104
write(msg, 'TRACE', html)
101105

102106

103-
def debug(msg, html=False):
107+
def debug(msg: str, html: bool=False) -> None:
104108
"""Writes the message to the log file using the ``DEBUG`` level."""
105109
write(msg, 'DEBUG', html)
106110

107111

108-
def info(msg, html=False, also_console=False):
112+
def info(msg: str, html: bool=False, also_console: bool=False) -> None:
109113
"""Writes the message to the log file using the ``INFO`` level.
110114
111115
If ``also_console`` argument is set to ``True``, the message is
@@ -116,18 +120,18 @@ def info(msg, html=False, also_console=False):
116120
console(msg)
117121

118122

119-
def warn(msg, html=False):
123+
def warn(msg: str, html: bool=False) -> None:
120124
"""Writes the message to the log file using the ``WARN`` level."""
121125
write(msg, 'WARN', html)
122126

123127

124-
def error(msg, html=False):
128+
def error(msg: str, html: bool=False) -> None:
125129
"""Writes the message to the log file using the ``ERROR`` level.
126130
"""
127131
write(msg, 'ERROR', html)
128132

129133

130-
def console(msg, newline=True, stream='stdout'):
134+
def console(msg: str, newline: bool=True, stream: str='stdout') -> None:
131135
"""Writes the message to the console.
132136
133137
If the ``newline`` argument is ``True``, a newline character is

src/robot/conf/settings.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import random
1818
import sys
1919
import time
20+
from typing import Dict, List, Tuple, Union
21+
from typing_extensions import Literal
2022

2123
from robot.errors import DataError, FrameworkError
2224
from robot.output import LOGGER, loggerhelper
@@ -30,7 +32,8 @@
3032

3133

3234
class _BaseSettings:
33-
_cli_opts = {'RPA' : ('rpa', None),
35+
_cli_opts: Dict[str, Tuple[str, object]] = {
36+
'RPA' : ('rpa', None),
3437
'Name' : ('name', None),
3538
'Doc' : ('doc', None),
3639
'Metadata' : ('metadata', []),

src/robot/htmldata/htmlfilewriter.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import os.path
1717
import re
18+
from typing import Optional
1819

1920
from robot.utils import HtmlWriter
2021
from robot.version import get_full_version
@@ -46,7 +47,7 @@ def _get_writers(self, base_dir):
4647

4748

4849
class _Writer:
49-
_handles_line = None
50+
_handles_line: Optional[str] = None
5051

5152
def handles(self, line):
5253
return line.startswith(self._handles_line)

src/robot/htmldata/jsonwriter.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15+
from typing import Optional, Union, Tuple
16+
1517

1618
class JsonWriter:
1719

@@ -55,7 +57,7 @@ def dump(self, data, mapping=None):
5557

5658

5759
class _Dumper:
58-
_handled_types = None
60+
_handled_types: Union[type, Tuple[type, ...], None] = None
5961

6062
def __init__(self, jsondumper):
6163
self._dump = jsondumper.dump

src/robot/htmldata/testdata/create_libdoc_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616

1717
with open(OUTPUT, 'w') as output:
1818
libdoc = LibraryDocumentation(INPUT)
19-
LibdocModelWriter(output, libdoc).write_data()
19+
LibdocModelWriter(output, libdoc).write_data() # type: ignore[attr-defined]
2020

2121
print(OUTPUT)

src/robot/libdoc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
# Allows running as a script. __name__ check needed with multiprocessing:
3838
# https://github.com/robotframework/robotframework/issues/1137
3939
if 'robot' not in sys.modules and __name__ == '__main__':
40-
import pythonpathsetter
40+
import pythonpathsetter # type: ignore[import]
4141

4242
from robot.utils import Application, seq2str
4343
from robot.errors import DataError

src/robot/libdocpkg/htmlutils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
import re
1717
try:
18-
from urllib import quote
18+
from urllib import quote # type: ignore[attr-defined]
1919
except ImportError:
2020
from urllib.parse import quote
2121

src/robot/libdocpkg/model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def _get_shortdoc(self):
164164
doc = HtmlToText().get_shortdoc_from_html(doc)
165165
return ' '.join(getshortdoc(doc).splitlines())
166166

167-
@shortdoc.setter
167+
@shortdoc.setter # type: ignore[no-redef,attr-defined]
168168
def shortdoc(self, shortdoc):
169169
self._shortdoc = shortdoc
170170

src/robot/libraries/Telnet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import time
2323

2424
try:
25-
import pyte
25+
import pyte # type: ignore[import]
2626
except ImportError:
2727
pyte = None
2828

src/robot/libraries/XML.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import os
1919

2020
try:
21-
from lxml import etree as lxml_etree
21+
from lxml import etree as lxml_etree # type: ignore[import]
2222
except ImportError:
2323
lxml_etree = None
2424

src/robot/libraries/dialogs_py.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
import sys
1716
from threading import current_thread
1817
import time
1918

2019
try:
21-
from Tkinter import (Button, Entry, Frame, Label, Listbox, TclError,
20+
from Tkinter import (Button, Entry, Frame, Label, Listbox, TclError, # type: ignore[import]
2221
Toplevel, Tk, BOTH, END, LEFT, W)
2322
except ImportError:
2423
from tkinter import (Button, Entry, Frame, Label, Listbox, TclError,
@@ -27,7 +26,7 @@
2726

2827
class _TkDialog(Toplevel):
2928
_left_button = 'OK'
30-
_right_button = 'Cancel'
29+
_right_button: str | None = 'Cancel'
3130

3231
def __init__(self, message, value=None, **extra):
3332
self._prevent_execution_with_timeouts()

src/robot/model/body.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
import re
16+
from typing import List, Optional
1717

1818
from .itemlist import ItemList
1919
from .modelobject import ModelObject
@@ -31,7 +31,7 @@ class BodyItem(ModelObject):
3131
ELSE = 'ELSE'
3232
RETURN = 'RETURN'
3333
MESSAGE = 'MESSAGE'
34-
type = None
34+
type: Optional[str] = None
3535
__slots__ = ['parent']
3636

3737
@property
@@ -60,7 +60,7 @@ class Body(ItemList):
6060
6161
Body contains the keywords and other structures such as for loops.
6262
"""
63-
__slots__ = []
63+
__slots__: List[str] = []
6464
# Set using 'Body.register' when these classes are created.
6565
keyword_class = None
6666
for_class = None
@@ -144,7 +144,7 @@ class IfBranches(Body):
144144
keyword_class = None
145145
for_class = None
146146
if_class = None
147-
__slots__ = []
147+
__slots__: List[str] = []
148148

149149
def create_branch(self, *args, **kwargs):
150150
return self.append(self.if_branch_class(*args, **kwargs))

0 commit comments

Comments
 (0)
0