Skip to content

Commit

Permalink
improved TypedDict conversion (#475)
Browse files Browse the repository at this point in the history
* improved TypedDict conversion
  • Loading branch information
Snooz82 authored Nov 3, 2020
1 parent a0bde4a commit 9320e5b
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 24 deletions.
7 changes: 2 additions & 5 deletions Browser/keywords/playwright_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ def new_browser(
Useful so that you can see what is going on. Defaults to no delay.
"""
params = locals_to_params(locals())
params = convert_typed_dict(Proxy, params, "proxy")
params = convert_typed_dict(self.new_context.__annotations__, params)
if timeout:
params["timeout"] = self.convert_timeout(timeout)
params["slowMo"] = self.convert_timeout(slowMo)
Expand Down Expand Up @@ -434,10 +434,7 @@ def new_context(
If there's no open Browser this keyword will open one. Does not create pages.
"""
params = locals_to_params(locals())
params = convert_typed_dict(GeoLocation, params, "geolocation")
params = convert_typed_dict(ViewportDimensions, params, "viewport")
params = convert_typed_dict(Proxy, params, "proxy")
params = convert_typed_dict(ViewportDimensions, params, "videoSize")
params = convert_typed_dict(self.new_context.__annotations__, params)
if not videosPath:
params.pop("videoSize", None)
options = json.dumps(params, default=str)
Expand Down
57 changes: 38 additions & 19 deletions Browser/utils/data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,49 @@
# limitations under the License.

from enum import Enum, auto
from typing import Dict
from typing import Dict, Union

from typing_extensions import TypedDict


def convert_typed_dict(data_type, params: Dict, key: str) -> Dict:
if key not in params:
return params
dictionary = {k.lower(): v for k, v in params[key].items()}
struct = data_type.__annotations__
typed_dict = data_type()
for req_key in data_type.__required_keys__:
if req_key.lower() not in dictionary:
raise RuntimeError(
f"`{dictionary}` cannot be converted to {data_type.__name__}."
f"\nThe required key '{req_key}' in not set in given value."
f"\nExpected types: {data_type.__annotations__}"
)
typed_dict[req_key] = struct[req_key](dictionary[req_key.lower()])
for opt_key in data_type.__optional_keys__:
if opt_key.lower() not in dictionary:
class TypedDictDummy(TypedDict):
pass


def convert_typed_dict(function_annotations: Dict, params: Dict) -> Dict:
for arg_name, arg_type in function_annotations.items():
if arg_name not in params or params[arg_name] is None:
continue
typed_dict[opt_key] = struct[opt_key](dictionary[opt_key.lower()])
params[key] = typed_dict
arg_value = params[arg_name]
if getattr(arg_type, "__origin__", None) is Union:
for union_type in arg_type.__args__:
if arg_value is None or not isinstance(
union_type, type(TypedDictDummy)
):
continue
arg_type = union_type
break
if isinstance(arg_type, type(TypedDictDummy)):
if not isinstance(arg_value, dict):
raise TypeError(
f"Argument '{arg_name}' expects a dictionary like object but did get '{type(arg_value)} instead.'"
)
lower_case_dict = {k.lower(): v for k, v in arg_value.items()}
struct = arg_type.__annotations__
typed_dict = arg_type()
for req_key in arg_type.__required_keys__: # type: ignore
if req_key.lower() not in lower_case_dict:
raise RuntimeError(
f"`{lower_case_dict}` cannot be converted to {arg_type.__name__}."
f"\nThe required key '{req_key}' in not set in given value."
f"\nExpected types: {arg_type.__annotations__}"
)
typed_dict[req_key] = struct[req_key](lower_case_dict[req_key.lower()]) # type: ignore
for opt_key in arg_type.__optional_keys__: # type: ignore
if opt_key.lower() not in lower_case_dict:
continue
typed_dict[opt_key] = struct[opt_key](lower_case_dict[opt_key.lower()]) # type: ignore
params[arg_name] = typed_dict
return params


Expand Down

0 comments on commit 9320e5b

Please sign in to comment.