Best Python code snippet using playwright-python
documentation_provider.py
Source:documentation_provider.py  
...69                        if arg["name"] == "options":70                            for option in arg["type"]["properties"]:71                                if not works_for_python(option):72                                    continue73                                option = self_or_override(option)74                                option_name = to_snake_case(name_or_alias(option))75                                option["name"] = option_name76                                option["required"] = False77                                args[option_name] = option78                        else:79                            arg = self_or_override(arg)80                            arg_name = to_snake_case(name_or_alias(arg))81                            arg["name"] = arg_name82                            args[arg_name] = arg83                    member["args"] = args84            clazz["members"] = members85    def _add_link(self, kind: str, clazz: str, member: str, alias: str) -> None:86        match = re.match(r"(JS|CDP|[A-Z])([^.]+)", clazz)87        if not match:88            raise Exception("Invalid class " + clazz)89        var_name = to_snake_case(f"{match.group(1).lower()}{match.group(2)}")90        new_name = to_snake_case(alias)91        if kind == "event":92            self.links[93                f"[`event: {clazz}.{member}`]"94            ] = f"`{var_name}.on('{new_name}')`"95        elif kind == "property":96            self.links[f"[`property: {clazz}.{member}`]"] = f"`{var_name}.{new_name}`"97        else:98            self.links[f"[`method: {clazz}.{member}`]"] = f"`{var_name}.{new_name}()`"99    def print_entry(100        self,101        class_name: str,102        method_name: str,103        signature: Dict[str, Any] = None,104        is_property: bool = False,105    ) -> None:106        if class_name in ["BindingCall"] or method_name in [107            "pid",108            "_add_event_handler",109            "remove_listener",110        ]:111            return112        original_method_name = method_name113        self.printed_entries.append(f"{class_name}.{method_name}")114        clazz = self.classes[class_name]115        method = clazz["members"].get(method_name)116        if not method and "extends" in clazz:117            superclass = self.classes.get(clazz["extends"])118            if superclass:119                method = superclass["members"].get(method_name)120        fqname = f"{class_name}.{method_name}"121        if not method:122            self.errors.add(f"Method not documented: {fqname}")123            return124        doc_is_property = (125            not method.get("async") and not len(method["args"]) and "type" in method126        )127        if method["name"].startswith("is_") or method["name"].startswith("as_"):128            doc_is_property = False129        if doc_is_property != is_property:130            self.errors.add(f"Method vs property mismatch: {fqname}")131            return132        indent = " " * 8133        print(f'{indent}"""{class_name}.{to_snake_case(original_method_name)}')134        if method.get("comment"):135            print(f"{indent}{self.beautify_method_comment(method['comment'], indent)}")136        signature_no_return = {**signature} if signature else None137        if signature_no_return and "return" in signature_no_return:138            del signature_no_return["return"]139        # Collect a list of all names, flatten options.140        args = method["args"]141        if signature and signature_no_return:142            print("")143            print("        Parameters")144            print("        ----------")145            for [name, value] in signature.items():146                name = to_snake_case(name)147                if name == "return":148                    continue149                original_name = name150                doc_value = args.get(name)151                if name in args:152                    del args[name]153                if not doc_value:154                    self.errors.add(f"Parameter not documented: {fqname}({name}=)")155                else:156                    code_type = self.serialize_python_type(value)157                    print(f"{indent}{to_snake_case(original_name)} : {code_type}")158                    if doc_value.get("comment"):159                        print(160                            f"{indent}    {self.indent_paragraph(self.render_links(doc_value['comment']), f'{indent}    ')}"161                        )162                    self.compare_types(code_type, doc_value, f"{fqname}({name}=)", "in")163        if (164            signature165            and "return" in signature166            and str(signature["return"]) != "<class 'NoneType'>"167        ):168            value = signature["return"]169            doc_value = method170            self.compare_types(value, doc_value, f"{fqname}(return=)", "out")171            print("")172            print("        Returns")173            print("        -------")174            print(f"        {self.serialize_python_type(value)}")175        print(f'{indent}"""')176        for name in args:177            if args[name].get("deprecated"):178                continue179            self.errors.add(180                f"Parameter not implemented: {class_name}.{method_name}({name}=)"181            )182    def indent_paragraph(self, p: str, indent: str) -> str:183        lines = p.split("\n")184        result = [lines[0]]185        for line in lines[1:]:186            result.append(indent + line)187        return "\n".join(result)188    def beautify_method_comment(self, comment: str, indent: str) -> str:189        comment = comment.replace("\\", "\\\\")190        comment = comment.replace('"', '\\"')191        lines = comment.split("\n")192        result = []193        skip_example = False194        last_was_blank = True195        for line in lines:196            if not line.strip():197                last_was_blank = True198                continue199            match = re.match(r"\s*```(.+)", line)200            if match:201                lang = match[1]202                if lang in ["html", "yml", "sh", "py", "python"]:203                    skip_example = False204                elif lang == "python " + ("async" if self.is_async else "sync"):205                    skip_example = False206                    line = "```py"207                else:208                    skip_example = True209            if not skip_example:210                if last_was_blank:211                    last_was_blank = False212                    result.append("")213                result.append(self.render_links(line))214            if skip_example and line.strip() == "```":215                skip_example = False216        return self.indent_paragraph("\n".join(result), indent)217    def render_links(self, comment: str) -> str:218        for [old, new] in self.links.items():219            comment = comment.replace(old, new)220        return comment221    def make_optional(self, text: str) -> str:222        if text.startswith("Union["):223            if text.endswith("NoneType]"):224                return text225            return text[:-1] + ", NoneType]"226        return f"Union[{text}, NoneType]"227    def compare_types(228        self, value: Any, doc_value: Any, fqname: str, direction: str229    ) -> None:230        if "(arg=)" in fqname or "(pageFunction=)" in fqname:231            return232        code_type = self.serialize_python_type(value)233        doc_type = self.serialize_doc_type(doc_value["type"], direction)234        if not doc_value["required"]:235            doc_type = self.make_optional(doc_type)236        if doc_type != code_type:237            self.errors.add(238                f"Parameter type mismatch in {fqname}: documented as {doc_type}, code has {code_type}"239            )240    def serialize_python_type(self, value: Any) -> str:241        str_value = str(value)242        if isinstance(value, list):243            return f"[{', '.join(list(map(lambda a: self.serialize_python_type(a), value)))}]"244        if str_value == "<class 'playwright._impl._types.Error'>":245            return "Error"246        match = re.match(r"^<class '((?:pathlib\.)?\w+)'>$", str_value)247        if match:248            return match.group(1)249        match = re.match(250            r"playwright._impl._event_context_manager.EventContextManagerImpl\[playwright._impl.[^.]+.(.*)\]",251            str_value,252        )253        if match:254            return "EventContextManager[" + match.group(1) + "]"255        match = re.match(r"^<class 'playwright\._impl\.[\w_]+\.([^']+)'>$", str_value)256        if (257            match258            and "_api_structures" not in str_value259            and "_api_types" not in str_value260        ):261            if match.group(1) == "EventContextManagerImpl":262                return "EventContextManager"263            return match.group(1)264        match = re.match(r"^typing\.(\w+)$", str_value)265        if match:266            return match.group(1)267        origin = get_origin(value)268        args = get_args(value)269        hints = None270        try:271            hints = get_type_hints(value)272        except Exception:273            pass274        if hints:275            signature: List[str] = []276            for [name, value] in hints.items():277                signature.append(f"{name}: {self.serialize_python_type(value)}")278            return f"{{{', '.join(signature)}}}"279        if origin == Union:280            args = get_args(value)281            if len(args) == 2 and str(args[1]) == "<class 'NoneType'>":282                return self.make_optional(self.serialize_python_type(args[0]))283            ll = list(map(lambda a: self.serialize_python_type(a), args))284            ll.sort(key=lambda item: "}" if item == "NoneType" else item)285            return f"Union[{', '.join(ll)}]"286        if str(origin) == "<class 'dict'>":287            args = get_args(value)288            return f"Dict[{', '.join(list(map(lambda a: self.serialize_python_type(a), args)))}]"289        if str(origin) == "<class 'list'>":290            args = get_args(value)291            return f"List[{', '.join(list(map(lambda a: self.serialize_python_type(a), args)))}]"292        if str(origin) == "<class 'collections.abc.Callable'>":293            args = get_args(value)294            return f"Callable[{', '.join(list(map(lambda a: self.serialize_python_type(a), args)))}]"295        if str(origin) == "typing.Literal":296            args = get_args(value)297            if len(args) == 1:298                return '"' + self.serialize_python_type(args[0]) + '"'299            body = ", ".join(300                list(map(lambda a: '"' + self.serialize_python_type(a) + '"', args))301            )302            return f"Union[{body}]"303        return str_value304    def serialize_doc_type(self, type: Any, direction: str) -> str:305        result = self.inner_serialize_doc_type(type, direction)306        return result307    def inner_serialize_doc_type(self, type: Any, direction: str) -> str:308        if type["name"] == "Promise":309            type = type["templates"][0]310        if "union" in type:311            ll = [self.serialize_doc_type(t, direction) for t in type["union"]]312            ll.sort(key=lambda item: "}" if item == "NoneType" else item)313            for i in range(len(ll)):314                if ll[i].startswith("Union["):315                    ll[i] = ll[i][6:-1]316            return f"Union[{', '.join(ll)}]"317        type_name = type["name"]318        if type_name == "path":319            if direction == "in":320                return "Union[pathlib.Path, str]"321            else:322                return "pathlib.Path"323        if type_name == "function" and "args" not in type:324            return "Callable"325        if type_name == "function":326            return_type = "Any"327            if type.get("returnType"):328                return_type = self.serialize_doc_type(type["returnType"], direction)329            return f"Callable[[{', '.join(self.serialize_doc_type(t, direction) for t in type['args'])}], {return_type}]"330        if "templates" in type:331            base = type_name332            if type_name == "Array":333                base = "List"334            if type_name == "Object" or type_name == "Map":335                base = "Dict"336            return f"{base}[{', '.join(self.serialize_doc_type(t, direction) for t in type['templates'])}]"337        if type_name == "Object" and "properties" in type:338            items = []339            for p in type["properties"]:340                items.append(341                    (p["name"])342                    + ": "343                    + (344                        self.serialize_doc_type(p["type"], direction)345                        if p["required"]346                        else self.make_optional(347                            self.serialize_doc_type(p["type"], direction)348                        )349                    )350                )351            return f"{{{', '.join(items)}}}"352        if type_name == "boolean":353            return "bool"354        if type_name == "string":355            return "str"356        if type_name == "any" or type_name == "Serializable":357            return "Any"358        if type_name == "Object":359            return "Dict"360        if type_name == "Function":361            return "Callable"362        if type_name == "Buffer":363            return "bytes"364        if type_name == "URL":365            return "str"366        if type_name == "RegExp":367            return "Pattern"368        if type_name == "null":369            return "NoneType"370        if type_name == "EvaluationArgument":371            return "Dict"372        return type["name"]373    def print_remainder(self) -> None:374        for [class_name, clazz] in self.classes.items():375            for [member_name, member] in clazz["members"].items():376                if member.get("deprecated"):377                    continue378                entry = f"{class_name}.{member_name}"379                if entry not in self.printed_entries:380                    self.errors.add(f"Method not implemented: {entry}")381        with open("scripts/expected_api_mismatch.txt") as f:382            for line in f.readlines():383                sline = line.strip()384                if not len(sline) or sline.startswith("#"):385                    continue386                if sline in self.errors:387                    self.errors.remove(sline)388                else:389                    print("No longer there: " + sline, file=stderr)390        if len(self.errors) > 0:391            for error in self.errors:392                print(error, file=stderr)393            exit(1)394def works_for_python(item: Any) -> bool:395    return not item["langs"].get("only") or "python" in item["langs"]["only"]396def name_or_alias(item: Any) -> str:397    alias = (398        item["langs"].get("aliases").get("python")399        if item["langs"].get("aliases")400        else None401    )402    return alias or item["name"]403def self_or_override(item: Any) -> Any:404    override = (405        item["langs"].get("overrides").get("python")406        if item["langs"].get("overrides")407        else None408    )409    return override or item410def apply_type_or_override(member: Any) -> Any:411    if member["langs"].get("types") and member["langs"]["types"].get("python"):...LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!
