Skip to content

Commit c8ed260

Browse files
committed
fixed stub_gen.py
1 parent 5680551 commit c8ed260

11 files changed

+219
-167
lines changed

Browser/__init__.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import re
21
import os
3-
2+
import re
43
from concurrent.futures import ThreadPoolExecutor, Future
54
from typing import Set
65

@@ -19,6 +18,18 @@
1918
)
2019
from .playwright import Playwright
2120
from .utils import logger
21+
from .utils.data_types import (
22+
TypedDict,
23+
AssertionOperator,
24+
ElementState,
25+
ColorScheme,
26+
ViewportDimensions,
27+
SupportedBrowsers,
28+
SelectAttribute,
29+
KeyboardModifier,
30+
MouseButton,
31+
RequestMethod,
32+
)
2233
from .version import VERSION
2334

2435
__version__ = VERSION

Browser/assertion_engine.py

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,20 @@
1-
from enum import Enum
1+
import re
22
from typing import (
33
Any,
4+
cast,
5+
Callable,
46
Dict,
7+
List,
8+
Optional,
59
Tuple,
6-
Callable,
710
TypeVar,
8-
cast,
9-
Optional,
10-
List,
1111
)
12-
import re
1312

1413
from robot.libraries.BuiltIn import BuiltIn # type: ignore
1514

15+
from .utils.data_types import AssertionOperator
1616
from .utils.robot_booleans import is_truthy
1717

18-
AssertionOperator = Enum(
19-
"AssertionOperator",
20-
{
21-
"equal": "==",
22-
"==": "==",
23-
"shouldbe": "==",
24-
"inequal": "!=",
25-
"!=": "!=",
26-
"shouldnotbe": "!=",
27-
"lessthan": "<",
28-
"<": "<",
29-
"greaterthan": ">",
30-
">": ">",
31-
"<=": "<=",
32-
">=": ">=",
33-
"contains": "*=",
34-
"*=": "*=",
35-
"starts": "^=",
36-
"^=": "^=",
37-
"shouldstartwith": "^=",
38-
"ends": "$=",
39-
"$=": "$=",
40-
"matches": "$",
41-
"validate": "validate",
42-
"then": "then",
43-
"evaluate": "then",
44-
},
45-
)
46-
4718
NumericalOperators = [
4819
AssertionOperator["=="],
4920
AssertionOperator["!="],
@@ -83,7 +54,6 @@
8354
),
8455
}
8556

86-
8757
T = TypeVar("T")
8858

8959

Browser/gen_stub.py

Lines changed: 74 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,73 +2,93 @@
22
import inspect
33
from typing import Any
44

5-
br: Any = Browser.Browser()
6-
keywords = br.get_keyword_names()
7-
function_list = list()
8-
for keyword in keywords:
9-
keyword_name = keyword
10-
if " " in keyword:
5+
6+
def is_named_method(keyword_name: str) -> bool:
7+
keyword_attribute = br.attributes[keyword_name]
8+
return (
9+
keyword_attribute.robot_name is not None
10+
and keyword_attribute.robot_name == keyword_name
11+
)
12+
13+
14+
def get_method_name_for_keyword(keyword_name: str) -> str:
15+
if is_named_method(keyword_name):
1116
for key in br.attributes.keys():
12-
if keyword == br.attributes[key].robot_name and " " not in key:
13-
keyword_name = key
14-
break
15-
args = br.get_keyword_arguments(keyword)
16-
types = br.get_keyword_types(keyword)
17-
args_str = ""
18-
for arg in args:
19-
if isinstance(arg, tuple):
20-
arg_name = arg[0]
21-
if arg_name[0] == "*":
22-
tpe = types[arg_name[1:]]
23-
else:
24-
tpe = types[arg_name]
25-
if hasattr(tpe, "__name__"):
26-
arg_type = tpe.__name__
27-
else:
28-
arg_type = str(tpe.__repr__()).lstrip("typing.")
29-
if arg[1] is None:
30-
arg_type_str = f"Optional[{arg_type}]"
31-
else:
32-
arg_type_str = arg_type
33-
if arg_type == "str":
34-
arg_str = f"{arg_name}: {arg_type_str} = '{arg[1]}'"
35-
else:
36-
arg_str = f"{arg_name}: {arg_type_str} = {arg[1]}"
37-
else:
38-
if arg[0] == "*":
39-
arg_name = arg[1:]
40-
else:
41-
arg_name = arg
42-
if arg_name in types:
43-
tpe = types[arg_name]
44-
if hasattr(tpe, "__name__"):
45-
arg_type = tpe.__name__
46-
else:
47-
arg_type = str(tpe.__repr__()).lstrip("typing.")
48-
arg_str = f"{arg}: {arg_type}"
17+
if key != keyword_name and keyword_name == br.attributes[key].robot_name:
18+
return key
19+
return keyword_name
20+
21+
22+
def get_type_string_from_type(argument_type: type) -> str:
23+
if hasattr(argument_type, "__name__"):
24+
return argument_type.__name__
25+
else:
26+
return str(argument_type.__repr__()).lstrip("typing.")
27+
28+
29+
def get_type_sting_from_argument(argument_string: str, argument_types: dict) -> str:
30+
agrument_name = argument_string.lstrip("*")
31+
if agrument_name in argument_types:
32+
return get_type_string_from_type(argument_types[agrument_name])
33+
return ""
34+
35+
36+
def get_function_list_from_keywords(keywords):
37+
functions = list()
38+
for keyword in keywords:
39+
method_name = get_method_name_for_keyword(keyword)
40+
keyword_arguments = br.get_keyword_arguments(keyword)
41+
keyword_types = br.get_keyword_types(keyword)
42+
arguments_list = list()
43+
for argument in keyword_arguments:
44+
if isinstance(argument, tuple):
45+
arg_str = argument[0]
46+
default_value = argument[1]
47+
arg_type_str = get_type_sting_from_argument(arg_str, keyword_types)
48+
if arg_type_str:
49+
if default_value is None:
50+
arg_type_str = f"Optional[{arg_type_str}]"
51+
if arg_type_str == "str":
52+
default_value = f"'{default_value}'"
53+
arg_str = arg_str + f": {arg_type_str}"
54+
elif isinstance(default_value, str):
55+
default_value = f"'{default_value}'"
56+
arg_str = arg_str + f" = {default_value}"
4957
else:
50-
arg_str = f"{arg}"
58+
arg_str = argument
59+
arg_type_str = get_type_sting_from_argument(arg_str, keyword_types)
60+
if arg_type_str:
61+
arg_str = arg_str + f": {arg_type_str}"
62+
arguments_list.append(arg_str)
63+
arguments_string = (
64+
f", {', '.join(arguments_list)}" if len(arguments_list) > 0 else ""
65+
)
66+
functions.append(f" def {method_name}(self{arguments_string}): ...\n")
67+
functions.sort()
68+
return functions
5169

52-
args_str = f"{args_str}, {arg_str}"
53-
function_list.append(f" def {keyword_name}(self{args_str}): ...\n")
5470

55-
function_list.sort()
71+
br: Any = Browser.Browser()
72+
function_list = get_function_list_from_keywords(br.get_keyword_names())
73+
5674

5775
pyi_boilerplate = f"""from concurrent.futures import Future
58-
from typing import Union, Any, Dict, List, Optional
76+
from typing import (
77+
Any,
78+
Dict,
79+
List,
80+
Optional,
81+
Union,
82+
)
5983
60-
from .assertion_engine import AssertionOperator
61-
from .keywords.input import SelectAttribute, MouseButton, KeyboardModifier
62-
from .keywords.playwright_state import SupportedBrowsers, ViewportDimensions, ColorScheme
63-
from .keywords.waiter import ElementState
64-
from .keywords.evaluation import RequestMethod
84+
from .utils.data_types import *
6585
6686
6787
class Browser:
6888
6989
def __init__(self, {str(inspect.signature(br.__init__))[1:]}: ...\n
7090
"""
7191

72-
with open("Browser/__init__.pyi", "w") as stub_file:
92+
with open("__init__.pyi", "w") as stub_file:
7393
stub_file.write(pyi_boilerplate)
7494
stub_file.writelines(function_list)

Browser/keywords/evaluation.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,22 @@
1-
from enum import Enum, auto
21
import json
3-
from typing import Any, Optional
42

53
from robotlibcore import keyword # type: ignore
4+
from typing import Optional, Any
65

76
from ..base import LibraryComponent
87
from ..generated.playwright_pb2 import Request
98
from ..utils import logger
10-
11-
12-
class RequestMethod(Enum):
13-
HEAD = auto()
14-
GET = auto()
15-
POST = auto()
16-
PUT = auto()
17-
PATCH = auto()
18-
DELETE = auto()
9+
from ..utils.data_types import RequestMethod
1910

2011

2112
class Evaluation(LibraryComponent):
2213
@keyword(tags=["HTTP", "BrowserControl"])
2314
def http(
2415
self,
25-
url,
16+
url: str,
2617
method: RequestMethod = RequestMethod.GET,
2718
body: Optional[str] = None,
28-
headers: dict = {},
19+
headers: Optional[dict] = None,
2920
):
3021
"""Performs an HTTP request in the current browser context
3122
@@ -52,6 +43,8 @@ def http(
5243
| Should Be Equal | ${res.body.some_field} | some value |
5344
5445
"""
46+
if headers is None:
47+
headers = {}
5548
body = body if body else ""
5649
with self.playwright.grpc_channel() as stub:
5750
response = stub.HttpRequest(
@@ -65,14 +58,14 @@ def http(
6558
logger.debug(response.log)
6659
return self._format_response(json.loads(response.body))
6760

68-
def _get_headers(self, body, headers):
61+
def _get_headers(self, body: str, headers: dict):
6962
try:
7063
json.loads(body)
7164
return {"Content-Type": "application/json", **headers}
7265
except json.decoder.JSONDecodeError:
7366
return headers
7467

75-
def _format_response(self, response):
68+
def _format_response(self, response: dict):
7669
headers = json.loads(response["headers"])
7770
response["headers"] = headers
7871
if "content-type" in headers and "application/json" in headers["content-type"]:

Browser/keywords/getters.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
import json
2-
from typing import Any, Dict, Optional, Union, List
2+
from typing import (
3+
Any,
4+
Dict,
5+
List,
6+
Optional,
7+
Union,
8+
)
39

410
from robotlibcore import keyword # type: ignore
511

6-
from ..base import LibraryComponent
7-
from ..generated.playwright_pb2 import Request
812
from ..assertion_engine import (
913
bool_verify_assertion,
1014
verify_assertion,
1115
list_verify_assertion,
1216
dict_verify_assertion,
1317
int_dict_verify_assertion,
1418
int_str_verify_assertion,
15-
AssertionOperator,
1619
)
17-
from .input import SelectAttribute
18-
from Browser.utils import logger
20+
from ..base import LibraryComponent
21+
from ..generated.playwright_pb2 import Request
22+
from ..utils import logger
23+
from ..utils.data_types import AssertionOperator, SelectAttribute
1924

2025

2126
class Getters(LibraryComponent):

Browser/keywords/input.py

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,16 @@
11
import json
2-
from enum import Enum, auto
2+
from typing import (
3+
Dict,
4+
Optional,
5+
)
36

47
from robotlibcore import keyword # type: ignore
5-
from typing import Optional, Dict
68

79
from ..base import LibraryComponent
810
from ..generated.playwright_pb2 import Request
9-
from ..utils.time_conversion import timestr_to_millisecs
1011
from ..utils import logger
11-
12-
13-
class MouseButton(Enum):
14-
left = auto()
15-
middle = auto()
16-
right = auto()
17-
18-
19-
class KeyboardModifier(Enum):
20-
Alt = auto()
21-
Control = auto()
22-
Meta = auto()
23-
Shift = auto()
24-
25-
26-
class SelectAttribute(Enum):
27-
value = auto()
28-
label = auto()
29-
text = label
30-
index = auto()
12+
from ..utils.data_types import MouseButton, KeyboardModifier, SelectAttribute
13+
from ..utils.time_conversion import timestr_to_millisecs
3114

3215

3316
class Input(LibraryComponent):

0 commit comments

Comments
 (0)