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

Skip to content

Commit d758f54

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

Some content is hidden

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

61 files changed

+285
-177
lines changed

pyproject.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[tool.mypy]
2+
python_version = 3.6
3+
allow_redefinition = true
4+
show_error_codes = true
5+
6+
[[too.mypy.overrides]]
7+
modulename = "robot.api"
8+
strict_equality = true
9+
warn_redundant_casts = true
10+
warn_unused_ignores = true
11+
disallow_any_generics = true
12+
disallow_untyped_defs = true
13+
14+
[[too.mypy.overrides]]
15+
modulename = "robot.*"

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: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@
1515

1616
import inspect
1717

18+
from typing import overload, cast, Callable, TypeVar, Union, List, Tuple, Dict, Any, TYPE_CHECKING
1819

19-
def not_keyword(func):
20+
if TYPE_CHECKING:
21+
from typing_extensions import Literal
22+
23+
Fn = TypeVar("Fn", bound=Callable[..., Any])
24+
Cls = TypeVar("Cls", bound=type)
25+
26+
27+
def not_keyword(func: Fn) -> Fn:
2028
"""Decorator to disable exposing functions or methods as keywords.
2129
2230
Examples::
@@ -34,15 +42,23 @@ def exposed_as_keyword():
3442
3543
New in Robot Framework 3.2.
3644
"""
37-
func.robot_not_keyword = True
45+
func.robot_not_keyword = True # type: ignore[attr-defined]
3846
return func
3947

4048

41-
not_keyword.robot_not_keyword = True
49+
not_keyword.robot_not_keyword = True # type: ignore[attr-defined]
50+
51+
52+
@overload
53+
def keyword(name: Fn) -> Fn: ...
54+
55+
56+
@overload
57+
def keyword(name: str = None, tags: List[str] = ..., types: Union[Dict[str, type], List[type], None] = ...) -> Callable[[Fn], Fn]: ...
4258

4359

4460
@not_keyword
45-
def keyword(name=None, tags=(), types=()):
61+
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]:
4662
"""Decorator to set custom name, tags and argument types to keywords.
4763
4864
This decorator creates ``robot_name``, ``robot_tags`` and ``robot_types``
@@ -85,20 +101,29 @@ def no_conversion(length, case_insensitive=False):
85101
# ...
86102
"""
87103
if inspect.isroutine(name):
88-
return keyword()(name)
104+
return keyword()(name) # type: ignore[type-var, return-value]
89105

90-
def decorator(func):
91-
func.robot_name = name
92-
func.robot_tags = tags
93-
func.robot_types = types
106+
def decorator(func: Fn) -> Fn:
107+
func.robot_name = name# type:ignore[attr-defined]
108+
func.robot_tags = tags# type:ignore[attr-defined]
109+
func.robot_types = types# type:ignore[attr-defined]
94110
return func
95111

96112
return decorator
97113

98114

115+
@overload
116+
def library(scope: Cls) -> Cls: ...
117+
118+
119+
@overload
120+
def library(scope: 'Literal["GLOBAL", "SUITE", "TEST", None]' = None, version: str =None, doc_format: str =None, listener: str=None,
121+
auto_keywords: bool=False) -> Callable[[Cls], Cls]: ...
122+
123+
99124
@not_keyword
100-
def library(scope=None, version=None, doc_format=None, listener=None,
101-
auto_keywords=False):
125+
def library(scope: 'Union[Literal["GLOBAL", "SUITE", "TEST", None], Cls]' = None, version: str =None, doc_format: str =None, listener: str=None,
126+
auto_keywords: bool=False) -> Union[Cls, Callable[[Cls], Cls]]:
102127
"""Class decorator to control keyword discovery and other library settings.
103128
104129
By default disables automatic keyword detection by setting class attribute
@@ -134,18 +159,18 @@ class LibraryConfiguration:
134159
The ``@library`` decorator is new in Robot Framework 3.2.
135160
"""
136161
if inspect.isclass(scope):
137-
return library()(scope)
162+
return library()(cast(type, scope))
138163

139-
def decorator(cls):
164+
def decorator(cls: Cls) -> Cls:
140165
if scope is not None:
141-
cls.ROBOT_LIBRARY_SCOPE = scope
166+
cls.ROBOT_LIBRARY_SCOPE = scope # type:ignore[attr-defined]
142167
if version is not None:
143-
cls.ROBOT_LIBRARY_VERSION = version
168+
cls.ROBOT_LIBRARY_VERSION = version# type:ignore[attr-defined]
144169
if doc_format is not None:
145-
cls.ROBOT_LIBRARY_DOC_FORMAT = doc_format
170+
cls.ROBOT_LIBRARY_DOC_FORMAT = doc_format# type:ignore[attr-defined]
146171
if listener is not None:
147-
cls.ROBOT_LIBRARY_LISTENER = listener
148-
cls.ROBOT_AUTO_KEYWORDS = auto_keywords
172+
cls.ROBOT_LIBRARY_LISTENER = listener# type:ignore[attr-defined]
173+
cls.ROBOT_AUTO_KEYWORDS = auto_keywords# type:ignore[attr-defined]
149174
return cls
150175

151176
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: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,16 @@ def my_keyword(arg):
6666
"""
6767

6868
import logging
69-
69+
from typing import TYPE_CHECKING
7070
from robot.output import librarylogger
7171
from robot.running.context import EXECUTION_CONTEXTS
7272

7373

74-
def write(msg, level='INFO', html=False):
74+
if TYPE_CHECKING:
75+
from typing_extensions import Literal
76+
77+
78+
def write(msg: str, level: 'Literal["TRACE", "DEBUG", "INFO", "WARN", "ERROR"]' = 'INFO', html: bool = False) -> None:
7579
"""Writes the message to the log file using the given level.
7680
7781
Valid log levels are ``TRACE``, ``DEBUG``, ``INFO`` (default), ``WARN``, and
@@ -86,26 +90,28 @@ def write(msg, level='INFO', html=False):
8690
librarylogger.write(msg, level, html)
8791
else:
8892
logger = logging.getLogger("RobotFramework")
89-
level = {'TRACE': logging.DEBUG // 2,
93+
level = {'TRACE': logging.DEBUG // 2, # type: ignore[assignment]
9094
'DEBUG': logging.DEBUG,
9195
'INFO': logging.INFO,
9296
'HTML': logging.INFO,
9397
'WARN': logging.WARN,
9498
'ERROR': logging.ERROR}[level]
95-
logger.log(level, msg)
99+
logger.log(level, msg) # type: ignore[arg-type]
100+
101+
96102

97103

98-
def trace(msg, html=False):
104+
def trace(msg: str, html: bool=False) -> None:
99105
"""Writes the message to the log file using the ``TRACE`` level."""
100106
write(msg, 'TRACE', html)
101107

102108

103-
def debug(msg, html=False):
109+
def debug(msg: str, html: bool=False) -> None:
104110
"""Writes the message to the log file using the ``DEBUG`` level."""
105111
write(msg, 'DEBUG', html)
106112

107113

108-
def info(msg, html=False, also_console=False):
114+
def info(msg: str, html: bool=False, also_console: bool=False) -> None:
109115
"""Writes the message to the log file using the ``INFO`` level.
110116
111117
If ``also_console`` argument is set to ``True``, the message is
@@ -116,18 +122,18 @@ def info(msg, html=False, also_console=False):
116122
console(msg)
117123

118124

119-
def warn(msg, html=False):
125+
def warn(msg: str, html: bool=False) -> None:
120126
"""Writes the message to the log file using the ``WARN`` level."""
121127
write(msg, 'WARN', html)
122128

123129

124-
def error(msg, html=False):
130+
def error(msg: str, html: bool=False) -> None:
125131
"""Writes the message to the log file using the ``ERROR`` level.
126132
"""
127133
write(msg, 'ERROR', html)
128134

129135

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

src/robot/conf/settings.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import random
1818
import sys
1919
import time
20+
from typing import Dict, Tuple
2021

2122
from robot.errors import DataError, FrameworkError
2223
from robot.output import LOGGER, loggerhelper
@@ -30,7 +31,8 @@
3031

3132

3233
class _BaseSettings:
33-
_cli_opts = {'RPA' : ('rpa', None),
34+
_cli_opts: Dict[str, Tuple[str, object]] = {
35+
'RPA' : ('rpa', None),
3436
'Name' : ('name', None),
3537
'Doc' : ('doc', None),
3638
'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()

0 commit comments

Comments
 (0)
0