Best Python code snippet using robotframework
parser.py
Source:parser.py  
1from re import match2from warnings import catch_warnings, filterwarnings3from .rply.errors import LexingError, ParserGeneratorWarning4from .rply.parser import LRParser5from .rply.parsergenerator import ParserGenerator6from .ast import *7from .error import throw8from .lexer import (9    lex,10    BIN_OP, INPLACE_OP, UNARY_OP, CMP_OP,11    POST_INPLACE_UNARY_OP, PRE_INPLACE_UNARY_OP,12    TOKENS,13)14from .moduleinfo import ModuleInfo15from .obj import (16    RESERVED, CONSTRUCTOR_TYPES,17    none,18)19__all__ = ['Parser', 'get_parser', 'parse']20class Parser:21    def __init__(self, /) -> None:22        self.pg = ParserGenerator(23            TOKENS,24            precedence=[25                ('left', ['EQUAL', *INPLACE_OP]),26                ('left', ['NOT']),27                ('left', [28                    'LESS', 'LESSEQUAL',29                    'EQEQUAL', 'NOTEQUAL',30                    'GREATER', 'GREATEREQUAL', 'EQEQEQUAL', 'NOTEQEQEQUAL',31                    'IN', 'NOTIN',32                ]),33                ('left', ['VBAR']),34                ('left', ['CIRCUMFLEX']),35                ('left', ['AMPER']),36                ('left', ['PLUS', 'MINUS']),37                ('left', ['LEFTSHIFT', 'RIGHTSHIFT']),38                ('left', ['STAR', 'SLASH', 'DOUBLESLASH', 'PERCENT']),39                ('right', ['INVERT', 'UADD', 'USUB']),40                ('left', ['DOUBLESTAR']),41            ],42        )43    def add_syntaxes(self, info: ModuleInfo, /) -> None:44        @self.pg.production('program :')45        def empty_program(p):46            return Module()47        @self.pg.production('program : expr')48        def single_stmt_program(p):49            return Module([Expr(p[0])])50        @self.pg.production('program : expr SEMI program')51        def merge_expr_to_program(p):52            return Module([Expr(p[0]), *p[2].body])53        @self.pg.production('program : if_stmt program')54        @self.pg.production('program : if_else_stmt program')55        @self.pg.production('program : if_elif_stmt program')56        @self.pg.production('program : func_def program')57        @self.pg.production('program : for_stmt program')58        @self.pg.production('program : for_of_stmt program')59        @self.pg.production('program : while_stmt program')60        def merge_stmt_to_program(p):61            return Module([p[0], *p[1].body])62        @self.pg.production('program : break_stmt SEMI program')63        @self.pg.production('program : continue_stmt SEMI program')64        def merge_stmt_to_program(p):65            return Module([p[0], *p[2].body])66        @self.pg.production(67            'if_stmt : IF LPAR expr RPAR LBRACE program RBRACE'68        )69        def if_stmt(p):70            return If(p[2], p[5].body)71        @self.pg.production('if_else_stmt : if_stmt or_else_stmt')72        def if_else_stmt(p):73            return If(p[0].test, p[0].body, p[1])74        @self.pg.production('if_elif_stmt : if_stmt merged_elif_stmt')75        @self.pg.production('if_elif_stmt : if_stmt elif_ending_stmt')76        @self.pg.production('if_elif_stmt : if_stmt elif_else_stmt')77        def if_elif_stmt(p):78            return If(p[0].test, p[0].body, [p[1]])79        @self.pg.production(80            'merged_elif_stmt : elif_ending_stmt elif_ending_stmt'81        )82        @self.pg.production(83            'merged_elif_stmt : elif_ending_stmt elif_else_stmt'84        )85        @self.pg.production(86            'merged_elif_stmt : elif_ending_stmt merged_elif_stmt'87        )88        def merged_elif_stmt(p):89            return If(p[0].test, p[0].body, [p[1]])90        @self.pg.production(91            'elif_ending_stmt : ELIF LPAR expr RPAR LBRACE program RBRACE'92        )93        def elif_ending_stmt(p):94            return If(p[2].test, p[5].body)95        @self.pg.production(96            'elif_else_stmt : ELIF LPAR expr RPAR LBRACE program RBRACE'97            '                 or_else_stmt'98        )99        def elif_else_stmt(p):100            return If(p[2], p[5].body, p[7])101        @self.pg.production(102            'for_stmt : FOR LPAR opt_expr SEMI opt_expr SEMI opt_expr RPAR'103            '           LBRACE program RBRACE'104        )105        def for_stmt(p):106            return For(p[2], p[4], p[6], p[9].body)107        @self.pg.production(108            'for_stmt : FOR LPAR opt_expr SEMI opt_expr SEMI opt_expr RPAR'109            '           LBRACE program RBRACE or_else_stmt'110        )111        def for_stmt(p):112            return For(p[2], p[4], p[6], p[9].body, p[11])113        @self.pg.production(114            'for_of_stmt : FOR LPAR NAME OF expr RPAR LBRACE program RBRACE'115        )116        def for_of_stmt(p):117            return ForOf(Name(p[2], Store()), p[4], p[7].body)118        @self.pg.production(119            'for_of_stmt : FOR LPAR NAME OF expr RPAR LBRACE program RBRACE'120            '              or_else_stmt'121        )122        def for_of_stmt(p):123            return ForOf(Name(p[2], Store()), p[4], p[7].body, p[9])124        @self.pg.production(125            'while_stmt : WHILE LPAR expr RPAR LBRACE program RBRACE'126        )127        def while_stmt(p):128            return While(p[2], p[5].body)129        @self.pg.production(130            'while_stmt : WHILE LPAR expr RPAR LBRACE program RBRACE'131            '             or_else_stmt'132        )133        def while_else_stmt(p):134            return While(p[2], p[5].body, p[7])135        @self.pg.production('or_else_stmt : ELSE LBRACE program RBRACE')136        def or_else_stmt(p):137            return p[2].body138        @self.pg.production('break_stmt : BREAK')139        def break_stmt(p):140            return Break(p[0])141        @self.pg.production('continue_stmt : CONTINUE')142        def continue_stmt(p):143            result = Continue(p[0])144            return result145        @self.pg.production(146            'func_def : FUNC NAME LPAR args_def RPAR'147            '           LBRACE program RBRACE'148        )149        def func_def_stmt(p):150            return FunctionDef(p[1].value, p[3], p[6].body)151        @self.pg.production('args_def :')152        def empty_args_def_expr(p):153            return Arguments()154        @self.pg.production('args_def : pos_only_args')155        @self.pg.production('args_def : normal_args')156        @self.pg.production('args_def : kw_only_args')157        def single_type_args_def_expr(p):158            return p[0]159        @self.pg.production('args_def : pos_only_args COMMA normal_args')160        def poa_na_args_def_expr(p):161            return Arguments(162                posonlyargs=p[0].posonlyargs, args=p[2].args,163                defaults=p[0].defaults + p[2].defaults,164            )165        @self.pg.production(166            'args_def : pos_only_args COMMA kw_only_args opt_kwarg'167        )168        def poa_koa_args_def_expr(p):169            return Arguments(170                posonlyargs=p[0].posonlyargs, vararg=p[2].vararg,171                kwonlyargs=p[2].kwonlyargs, defaults=p[0].defaults,172                kw_defaults=p[2].kw_defaults, kwarg=p[3].kwarg,173            )174        @self.pg.production(175            'args_def : normal_args COMMA kw_only_args opt_kwarg'176        )177        def na_koa_args_def_expr(p):178            return Arguments(179                args=p[0].args, vararg=p[2].vararg, kwonlyargs=p[2].kwonlyargs,180                defaults=p[0].defaults, kw_defaults=p[2].kw_defaults,181                kwarg=p[3].kwarg,182            )183        @self.pg.production(184            'args_def : pos_only_args COMMA normal_args COMMA kw_only_args'185            '           opt_kwarg'186        )187        def poa_na_koa_args_def_expr(p):188            return Arguments(189                posonlyargs=p[0].posonlyargs, args=p[2].args,190                vararg=p[4].vararg, kwonlyargs=p[4].kwonlyargs,191                defaults=p[0].defaults + p[2].defaults,192                kw_defaults=p[4].kw_defaults, kwarg=p[5].kwarg,193            )194        @self.pg.production('kw_only_args : STAR')195        def empty_kw_only_args_expr(p):196            return Arguments()197        @self.pg.production('kw_only_args : STAR COMMA args')198        @self.pg.production('kw_only_args : STAR COMMA kwargs')199        def kw_only_args_expr(p):200            return Arguments(kwonlyargs=p[2][0], kw_defaults=p[2][1])201        @self.pg.production('kw_only_args : STAR COMMA args COMMA kwargs')202        def kw_only_args_kwargs_expr(p):203            return Arguments(204                kwonlyargs=p[2][0] + p[4][0],205                kw_defaults=p[2][1] + p[4][1],206            )207        @self.pg.production('kw_only_args : STAR NAME COMMA args')208        @self.pg.production('kw_only_args : STAR NAME COMMA kwargs')209        def kw_only_args_with_vararg_expr(p):210            return Arguments(211                vararg=Arg(p[1].value, p[1]),212                kwonlyargs=p[3][0], kw_defaults=p[3][1]213            )214        @self.pg.production('kw_only_args : STAR NAME COMMA args COMMA kwargs')215        def kw_only_args_with_vararg_kwargs_expr(p):216            return Arguments(217                vararg=Arg(p[1].value, p[1]),218                kwonlyargs=p[3][0] + p[5][0], kw_defaults=p[3][1] + p[5][1],219            )220        @self.pg.production('opt_kwarg :')221        def empty_optional_keyword_arg_expr(p):222            return Arguments(kwarg=None)223        @self.pg.production('opt_kwarg : DOUBLESTAR NAME')224        def optional_keyword_arg_expr(p):225            return Arguments(kwarg=Arg(p[1].value, p[1]))226        @self.pg.production('normal_args :')227        def empty_normal_args_expr(p):228            return Arguments()229        @self.pg.production('normal_args : args')230        @self.pg.production('normal_args : kwargs')231        def normal_args_expr(p):232            return Arguments(args=p[0][0], defaults=p[0][1])233        @self.pg.production('normal_args : args COMMA kwargs')234        def normal_args_kwargs_expr(p):235            return Arguments(236                args=p[0][0] + p[2][0], defaults=p[0][1] + p[2][1]237            )238        @self.pg.production('pos_only_args : SLASH')239        def empty_pos_only_args_expr(p):240            return Arguments()241        @self.pg.production('pos_only_args : args COMMA SLASH')242        @self.pg.production('pos_only_args : kwargs COMMA SLASH')243        def pos_only_args_expr(p):244            return Arguments(posonlyargs=p[0][0], defaults=p[0][1])245        @self.pg.production('pos_only_args : args COMMA kwargs COMMA SLASH')246        def pos_only_args_kwargs_expr(p):247            return Arguments(248                posonlyargs=p[0][0] + p[2][0], defaults=p[0][1] + p[2][1]249            )250        @self.pg.production('args : NAME COMMA args')251        def args_expr(p):252            return [[Arg(p[0].value, p[0]), *p[2][0]], [None, *p[2][1]]]253        @self.pg.production('args : NAME')254        def single_arg_expr(p):255            return [[Arg(p[0].value, p[0])], [None]]256        @self.pg.production('kwargs : assignment COMMA kwargs')257        def keyword_args_expr(p):258            return [[Arg(p[0].target.id, p[0].target.token), *p[4][0]],259                    [p[0].value, *p[4][1]]]260        @self.pg.production('kwargs : assignment')261        def single_keyword_arg_expr(p):262            return [[Arg(p[0].target.id, p[0].target.token)],263                    [p[0].value]]264        @self.pg.production('expr : assignment')265        def assignment_as_expr(p):266            return p[0]267        @self.pg.production('assignment : NAME EQUAL expr')268        def assignment(p):269            if p[0].value in RESERVED:270                throw(info, p[0], 'SyntaxError',271                      f'cannot assign to {p[0].value}')272            name = Name(p[0], Store())273            return Assign(name, p[2])274        @self.pg.production('expr : LPAR expr RPAR')275        def expr_with_parentheses(p):276            return p[1]277        @self.pg.production('expr : NUMBER LPAR expr RPAR')278        def parentheses_number_multiplication(p):279            return BinOp(Number(p[0]), Mult, p[2])280        @self.pg.production('expr : expr LPAR RPAR')281        @self.pg.production('expr : expr LPAR tuple_expr RPAR')282        @self.pg.production('expr : expr LPAR tuple_expr COMMA RPAR')283        def function_call_expr(p):284            args = () if len(p) == 3 else p[2].values285            if isinstance(p[0], Name):286                if p[0].token.value in BUILTIN_FUNCTIONS:287                    return BUILTIN_FUNCTIONS[p[0].token.value](args)288                elif p[0].token.value in CONSTRUCTOR_TYPES:289                    return Construct(CONSTRUCTOR_TYPES[p[0].token.value], args)290            else:291                return Call(p[0], args, {})292        @self.pg.production('expr : expr LSQB expr RSQB')293        def get_item_expr(p):294            return GetItem(p[0], p[2])295        @self.pg.production('expr : expr LSQB opt_expr COLON opt_expr RSQB')296        @self.pg.production('expr : expr '297                            'LSQB opt_expr COLON opt_expr COLON opt_expr RSQB')298        def get_item_expr(p):299            return GetItem(300                p[0], Slice(p[2], p[4], none if len(p) == 6 else p[6])301            )302        @self.pg.production('opt_expr : ')303        @self.pg.production('opt_expr : expr')304        def optional_expr(p):305            return p[0] if p else Constant(none)306        @self.pg.production('expr : expr PLUS expr')307        @self.pg.production('expr : expr MINUS expr')308        @self.pg.production('expr : expr STAR expr')309        @self.pg.production('expr : expr SLASH expr')310        @self.pg.production('expr : expr DOUBLESLASH expr')311        @self.pg.production('expr : expr PERCENT expr')312        @self.pg.production('expr : expr DOUBLESTAR expr')313        @self.pg.production('expr : expr LEFTSHIFT expr')314        @self.pg.production('expr : expr RIGHTSHIFT expr')315        @self.pg.production('expr : expr AMPER expr')316        @self.pg.production('expr : expr CIRCUMFLEX expr')317        @self.pg.production('expr : expr VBAR expr')318        def binop_expr(p):319            return BinOp(p[0], BIN_OP[p[1].gettokentype()](), p[2])320        @self.pg.production('expr : NAME PLUSEQUAL expr')321        @self.pg.production('expr : NAME MINUSEQUAL expr')322        @self.pg.production('expr : NAME STAREQUAL expr')323        @self.pg.production('expr : NAME SLASHEQUAL expr')324        @self.pg.production('expr : NAME DOUBLESLASHEQUAL expr')325        @self.pg.production('expr : NAME PERCENTEQUAL expr')326        @self.pg.production('expr : NAME DOUBLESTAREQUAL expr')327        @self.pg.production('expr : NAME LEFTSHIFTEQUAL expr')328        @self.pg.production('expr : NAME RIGHTSHIFTEQUAL expr')329        @self.pg.production('expr : NAME AMPEREQUAL expr')330        @self.pg.production('expr : NAME CIRCUMFLEXEQUAL expr')331        @self.pg.production('expr : NAME VBAREQUAL expr')332        def inplace_assign_expr(p):333            if p[0].value in RESERVED:334                throw(info, p[0], 'SyntaxError',335                      f"'{p[0].value}' is an illegal expression "336                      f"for augmented assignment")337            return AugAssign(338                Name(p[0], Store()),339                INPLACE_OP[p[1].gettokentype()](),340                p[2],341            )342        @self.pg.production('expr : NAME PLUSPLUS')343        @self.pg.production('expr : NAME MINUSMINUS')344        def inplace_unary_expr(p):345            if p[0].value in RESERVED:346                throw(info, p[0], 'SyntaxError',347                      f"'{p[0].value}' is an illegal expression "348                      f"for inplace unary operation")349            return InplaceUnaryOp(350                Name(p[0], Load()),351                Name(p[0], Store()),352                POST_INPLACE_UNARY_OP[p[1].gettokentype()](),353            )354        @self.pg.production('expr : PLUSPLUS NAME')355        @self.pg.production('expr : MINUSMINUS NAME')356        def inplace_unary_expr(p):357            if p[1].value in RESERVED:358                throw(info, p[0], 'SyntaxError',359                      f"'{p[0].value}' is an illegal expression "360                      f"for inplace unary operation")361            return InplaceUnaryOp(362                Name(p[1], Load()),363                Name(p[1], Store()),364                PRE_INPLACE_UNARY_OP[p[0].gettokentype()](),365            )366        @self.pg.production('expr : NUMBER NAME')367        def variable_multiplication(p):368            return BinOp(369                Number(p[0]), Mult,370                Constant(p[1]) if p[1].value in RESERVED371                else Name(p[1], Load()),372            )373        @self.pg.production('expr : TILDE expr', precedence='INVERT')374        @self.pg.production('expr : NOT expr')375        @self.pg.production('expr : PLUS expr', precedence='UADD')376        @self.pg.production('expr : MINUS expr', precedence='USUB')377        def unaryop_expr(p):378            return UnaryOp(UNARY_OP[p[0].gettokentype()](), p[1])379        @self.pg.production('expr : cmp_expr')380        def cmp_expr_escape(p):381            return p[0]382        @self.pg.production('cmp_expr : expr LESS expr')383        @self.pg.production('cmp_expr : expr LESSEQUAL expr')384        @self.pg.production('cmp_expr : expr EQEQUAL expr')385        @self.pg.production('cmp_expr : expr NOTEQUAL expr')386        @self.pg.production('cmp_expr : expr GREATER expr')387        @self.pg.production('cmp_expr : expr GREATEREQUAL expr')388        @self.pg.production('cmp_expr : expr EQEQEQUAL expr')389        @self.pg.production('cmp_expr : expr NOTEQEQEQUAL expr')390        @self.pg.production('cmp_expr : expr IN expr')391        @self.pg.production('cmp_expr : cmp_expr LESS expr')392        @self.pg.production('cmp_expr : cmp_expr LESSEQUAL expr')393        @self.pg.production('cmp_expr : cmp_expr EQEQUAL expr')394        @self.pg.production('cmp_expr : cmp_expr NOTEQUAL expr')395        @self.pg.production('cmp_expr : cmp_expr GREATER expr')396        @self.pg.production('cmp_expr : cmp_expr GREATEREQUAL expr')397        @self.pg.production('cmp_expr : cmp_expr EQEQEQUAL expr')398        @self.pg.production('cmp_expr : cmp_expr NOTEQEQEQUAL expr')399        @self.pg.production('cmp_expr : cmp_expr IN expr')400        def cmp_expr(p):401            left = p[0]402            cmp_op = CMP_OP[p[1].gettokentype()]()403            if isinstance(left, Compare):404                return Compare(405                    left, left.ops + [cmp_op], left.comparators + [p[2]]406                )407            else:408                return Compare(left, [cmp_op], [p[2]])409        @self.pg.production('cmp_expr : expr NOT IN expr',410                            precedence='NOTIN')411        @self.pg.production('cmp_expr : cmp_expr NOT IN expr',412                            precedence='NOTIN')413        def multi_cmp_expr(p):414            left = p[0]415            cmp_op = CMP_OP[tuple(op.gettokentype() for op in p[1:-1])]416            if isinstance(p[0], Compare):417                return Compare(418                    left, left.ops + [cmp_op], left.comparators + [p[-1]]419                )420            else:421                return Compare(left, [cmp_op], [p[-1]])422        @self.pg.production('expr : NAME')423        def constant(p):424            if p[0].value in RESERVED:425                return Constant(p[0])426            return Name(p[0], Load())427        @self.pg.production('expr : NUMBER')428        def number(p):429            return Number(p[0])430        @self.pg.production('expr : STRING')431        def string(p):432            return String(p[0])433        @self.pg.production('expr : LPAR RPAR')434        def empty_tuple(p):435            return Tuple(())436        @self.pg.production('expr : LPAR tuple_expr RPAR')437        @self.pg.production('expr : LPAR tuple_expr COMMA RPAR')438        def filled_tuple(p):439            return p[1]440        @self.pg.production('expr : LSQB RSQB')441        def empty_list(p):442            return List([])443        @self.pg.production('expr : LSQB tuple_expr RSQB')444        @self.pg.production('expr : LSQB tuple_expr COMMA RSQB')445        def filled_list(p):446            return List([*p[1].values])447        @self.pg.production('tuple_expr : expr')448        def single_tuple_expr(p):449            return Tuple((p[0],))450        @self.pg.production('tuple_expr : tuple_expr COMMA expr')451        def multiple_tuple_expr(p):452            return Tuple(p[0].values + (p[2], ))453        @self.pg.error454        def error_handle(token):455            throw(info, token, 'SyntaxError', 'invalid syntax')456    def get_parser(self, info: ModuleInfo, /) -> LRParser:457        self.add_syntaxes(info)458        return self.pg.build()459def get_parser(info: ModuleInfo, /, *, log: str = 'default') -> LRParser:460    if log == 'full':461        return Parser().get_parser(info)462    elif log == 'default':463        with catch_warnings(record=True) as warnings:464            parser = Parser().get_parser(info)465            warning_unused = True466            unused_tokens = []467            for warning in warnings:468                if warning.category is not ParserGeneratorWarning:469                    continue470                if warning_unused and (result := match(471                    r"^Token '(.+)' is unused$", f'{warning.message}'472                )):473                    unused_tokens.append(result.group(1))474                else:475                    if warning_unused:476                        warning_unused = False477                        if len(unused_tokens) == 1:478                            print(f"\x1b[91mParserGeneratorWarning: "479                                  f"Token '{unused_tokens}' is unused\x1b[0m")480                        elif len(unused_tokens) > 1:481                            token_string = ', '.join(482                                f"'{token}'" for token in unused_tokens483                            )484                            print(f"\x1b[91mParserGeneratorWarning: "485                                  f"Token {token_string} are unused\x1b[0m")486                    print(f'\x1b[91mParserGeneratorWarning: '487                          f'{warning.message}\x1b[0m')488        return parser489    elif log == 'none':490        with catch_warnings():491            filterwarnings('ignore')492            return Parser().get_parser(info)493    else:494        raise ValueError(f"param log must be 'full', 'default', or 'none', "495                         f"not {log!r}")496def informed(node: Ast, info: ModuleInfo) -> Ast:497    if node is None:498        raise ValueError('cannot inform a node of None')499    node.info = info500    for field in node._fields:501        value = getattr(node, field)502        if isinstance(value, Ast):503            setattr(node, field, informed(value, info))504        elif isinstance(value, list):505            setattr(node, field, [informed(item, info) for item in value])506        elif isinstance(value, tuple):507            setattr(node, field, tuple(informed(item, info) for item in value))508    return node509def parse(source: str, *, path: str = '<unknown>',510          log: str = 'default') -> Module:511    tokens = lex(source)512    info = ModuleInfo(source, path)513    parser = get_parser(info, log=log)514    try:515        module = parser.parse(tokens)516    except LexingError as err:517        index = err.source_pos.idx518        lineno = source[:index].count('\n')519        line = source.split('\n')[lineno]520        if '\n' in source[:index]:521            padding = (index - source[:index].rfind('\n')) * ' '522        else:523            padding = index * ' '524        exit(f'  File "{path}", line {lineno + 1}\n'525             f'    {line}\n'526             f'   {padding}^\n'527             f'SyntaxError: invalid syntax')...ParameterSpecs.py
Source:ParameterSpecs.py  
1#     Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com2#3#     Part of "Nuitka", an optimizing Python compiler that is compatible and4#     integrates with CPython, but also works on its own.5#6#     Licensed under the Apache License, Version 2.0 (the "License");7#     you may not use this file except in compliance with the License.8#     You may obtain a copy of the License at9#10#        http://www.apache.org/licenses/LICENSE-2.011#12#     Unless required by applicable law or agreed to in writing, software13#     distributed under the License is distributed on an "AS IS" BASIS,14#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.15#     See the License for the specific language governing permissions and16#     limitations under the License.17#18""" This module maintains the parameter specification classes.19These are used for function, lambdas, generators. They are also a factory20for the respective variable objects. One of the difficulty of Python and21its parameter parsing is that they are allowed to be nested like this:22(a,b), c23Much like in assignments, which are very similar to parameters, except24that parameters may also be assigned from a dictionary, they are no less25flexible.26"""27from nuitka import Variables28from nuitka.PythonVersions import python_version29from nuitka.utils.InstanceCounters import (30    counted_del,31    counted_init,32    isCountingInstances,33)34class TooManyArguments(Exception):35    def __init__(self, real_exception):36        Exception.__init__(self)37        self.real_exception = real_exception38    def getRealException(self):39        return self.real_exception40class ParameterSpec(object):41    # These got many attributes, in part duplicating name and instance of42    # variables, pylint: disable=too-many-instance-attributes43    __slots__ = (44        "name",45        "owner",46        "normal_args",47        "normal_variables",48        "list_star_arg",49        "is_list_star_arg_single",50        "dict_star_arg",51        "list_star_variable",52        "dict_star_variable",53        "default_count",54        "kw_only_args",55        "kw_only_variables",56        "pos_only_args",57        "pos_only_variables",58    )59    @counted_init60    def __init__(61        self,62        ps_name,63        ps_normal_args,64        ps_pos_only_args,65        ps_kw_only_args,66        ps_list_star_arg,67        ps_dict_star_arg,68        ps_default_count,69        ps_is_list_star_arg_single=False,70    ):71        if type(ps_normal_args) is str:72            if ps_normal_args == "":73                ps_normal_args = ()74            else:75                ps_normal_args = ps_normal_args.split(",")76        if type(ps_kw_only_args) is str:77            if ps_kw_only_args == "":78                ps_kw_only_args = ()79            else:80                ps_kw_only_args = ps_kw_only_args.split(",")81        assert None not in ps_normal_args82        self.owner = None83        self.name = ps_name84        self.normal_args = tuple(ps_normal_args)85        self.normal_variables = None86        assert (87            ps_list_star_arg is None or type(ps_list_star_arg) is str88        ), ps_list_star_arg89        assert (90            ps_dict_star_arg is None or type(ps_dict_star_arg) is str91        ), ps_dict_star_arg92        assert type(ps_is_list_star_arg_single) is bool, ps_is_list_star_arg_single93        self.list_star_arg = ps_list_star_arg if ps_list_star_arg else None94        self.is_list_star_arg_single = ps_is_list_star_arg_single95        self.dict_star_arg = ps_dict_star_arg if ps_dict_star_arg else None96        self.list_star_variable = None97        self.dict_star_variable = None98        self.default_count = ps_default_count99        self.kw_only_args = tuple(ps_kw_only_args)100        self.kw_only_variables = None101        self.pos_only_args = tuple(ps_pos_only_args)102        self.pos_only_variables = None103    if isCountingInstances():104        __del__ = counted_del()105    def makeClone(self):106        return ParameterSpec(107            ps_name=self.name,108            ps_normal_args=self.normal_args,109            ps_pos_only_args=self.pos_only_args,110            ps_kw_only_args=self.kw_only_args,111            ps_list_star_arg=self.list_star_arg,112            ps_dict_star_arg=self.dict_star_arg,113            ps_default_count=self.default_count,114        )115    def getDetails(self):116        return {117            "ps_name": self.name,118            "ps_normal_args": ",".join(self.normal_args),119            "ps_pos_only_args": self.pos_only_args,120            "ps_kw_only_args": ",".join(self.kw_only_args),121            "ps_list_star_arg": self.list_star_arg122            if self.list_star_arg is not None123            else "",124            "ps_dict_star_arg": self.dict_star_arg125            if self.dict_star_arg is not None126            else "",127            "ps_default_count": self.default_count,128        }129    def checkParametersValid(self):130        arg_names = self.getParameterNames()131        # Check for duplicate arguments, could happen.132        for arg_name in arg_names:133            if arg_names.count(arg_name) != 1:134                return "duplicate argument '%s' in function definition" % arg_name135        return None136    def __repr__(self):137        parts = [str(normal_arg) for normal_arg in self.pos_only_args]138        if parts:139            parts.append("/")140        parts += [str(normal_arg) for normal_arg in self.normal_args]141        if self.list_star_arg is not None:142            parts.append("*%s" % self.list_star_arg)143        if self.dict_star_variable is not None:144            parts.append("**%s" % self.dict_star_variable)145        if parts:146            return "<ParameterSpec '%s'>" % ",".join(parts)147        else:148            return "<NoParameters>"149    def setOwner(self, owner):150        if self.owner is not None:151            return152        self.owner = owner153        self.normal_variables = []154        for normal_arg in self.normal_args:155            if type(normal_arg) is str:156                normal_variable = Variables.ParameterVariable(157                    owner=self.owner, parameter_name=normal_arg158                )159            else:160                assert False, normal_arg161            self.normal_variables.append(normal_variable)162        if self.list_star_arg:163            self.list_star_variable = Variables.ParameterVariable(164                owner=owner, parameter_name=self.list_star_arg165            )166        else:167            self.list_star_variable = None168        if self.dict_star_arg:169            self.dict_star_variable = Variables.ParameterVariable(170                owner=owner, parameter_name=self.dict_star_arg171            )172        else:173            self.dict_star_variable = None174        self.kw_only_variables = [175            Variables.ParameterVariable(owner=self.owner, parameter_name=kw_only_arg)176            for kw_only_arg in self.kw_only_args177        ]178        self.pos_only_variables = [179            Variables.ParameterVariable(owner=self.owner, parameter_name=pos_only_arg)180            for pos_only_arg in self.pos_only_args181        ]182    def getDefaultCount(self):183        return self.default_count184    def hasDefaultParameters(self):185        return self.getDefaultCount() > 0186    def getTopLevelVariables(self):187        return self.pos_only_variables + self.normal_variables + self.kw_only_variables188    def getAllVariables(self):189        result = list(self.pos_only_variables)190        result += self.normal_variables191        result += self.kw_only_variables192        if self.list_star_variable is not None:193            result.append(self.list_star_variable)194        if self.dict_star_variable is not None:195            result.append(self.dict_star_variable)196        return result197    def getParameterNames(self):198        result = list(self.pos_only_args + self.normal_args)199        result += self.kw_only_args200        if self.list_star_arg is not None:201            result.append(self.list_star_arg)202        if self.dict_star_arg is not None:203            result.append(self.dict_star_arg)204        return result205    def getStarListArgumentName(self):206        return self.list_star_arg207    def isStarListSingleArg(self):208        return self.is_list_star_arg_single209    def getListStarArgVariable(self):210        return self.list_star_variable211    def getStarDictArgumentName(self):212        return self.dict_star_arg213    def getDictStarArgVariable(self):214        return self.dict_star_variable215    def getKwOnlyVariables(self):216        return self.kw_only_variables217    def allowsKeywords(self):218        # Abstract method, pylint: disable=no-self-use219        return True220    def getKeywordRefusalText(self):221        return "%s() takes no keyword arguments" % self.name222    def getArgumentNames(self):223        return self.pos_only_args + self.normal_args224    def getArgumentCount(self):225        return len(self.normal_args) + len(self.pos_only_args)226    def getKwOnlyParameterNames(self):227        return self.kw_only_args228    def getKwOnlyParameterCount(self):229        return len(self.kw_only_args)230    def getPosOnlyParameterCount(self):231        return len(self.pos_only_args)232def matchCall(233    func_name,234    args,235    kw_only_args,236    star_list_arg,237    star_list_single_arg,238    star_dict_arg,239    num_defaults,240    num_posonly,241    positional,242    pairs,243    improved=False,244):245    """Match a call arguments to a signature.246    Args:247        func_name - Name of the function being matched, used to construct exception texts.248        args - normal argument names249        kw_only_args -  keyword only argument names (Python3)250        star_list_arg - name of star list argument if any251        star_dict_arg - name of star dict argument if any252        num_defaults - amount of arguments that have default values253        num_posonly - amount of arguments that must be given by position254        positional - tuple of argument values given for simulated call255        pairs - tuple of pairs arg argument name and argument values256        improved - (bool) should we give better errors than CPython or not.257    Returns:258        Dictionary of argument name to value mappings259    Notes:260        Based loosely on "inspect.getcallargs" with corrections.261    """262    # This is of incredible code complexity, but there really is no other way to263    # express this with less statements, branches, or variables.264    # pylint: disable=too-many-branches,too-many-locals,too-many-statements265    assert type(positional) is tuple, positional266    assert type(pairs) in (tuple, list), pairs267    # Make a copy, we are going to modify it.268    pairs = list(pairs)269    result = {}270    assigned_tuple_params = []271    def assign(arg, value):272        if type(arg) is str:273            # Normal case:274            result[arg] = value275        else:276            # Tuple argument case:277            assigned_tuple_params.append(arg)278            value = iter(value.getIterationValues())279            for i, subarg in enumerate(arg):280                try:281                    subvalue = next(value)282                except StopIteration:283                    raise TooManyArguments(284                        ValueError(285                            "need more than %d %s to unpack"286                            % (i, "values" if i > 1 else "value")287                        )288                    )289                # Recurse into tuple argument values, could be more tuples.290                assign(subarg, subvalue)291            # Check that not too many values we provided.292            try:293                next(value)294            except StopIteration:295                pass296            else:297                raise TooManyArguments(ValueError("too many values to unpack"))298    def isAssigned(arg):299        if type(arg) is str:300            return arg in result301        return arg in assigned_tuple_params302    num_pos = len(positional)303    num_total = num_pos + len(pairs)304    num_args = len(args)305    for arg, value in zip(args, positional):306        assign(arg, value)307    # Python3 does this check earlier.308    if python_version >= 0x300 and not star_dict_arg:309        for pair in pairs:310            try:311                arg_index = (args + kw_only_args).index(pair[0])312            except ValueError:313                if improved or python_version >= 0x370:314                    message = "'%s' is an invalid keyword argument for %s()" % (315                        pair[0],316                        func_name,317                    )318                else:319                    message = (320                        "'%s' is an invalid keyword argument for this function"321                        % pair[0]322                    )323                raise TooManyArguments(TypeError(message))324            else:325                if arg_index < num_posonly:326                    message = "'%s' is an invalid keyword argument for %s()" % (327                        pair[0],328                        func_name,329                    )330                    raise TooManyArguments(TypeError(message))331    if star_list_arg:332        if num_pos > num_args:333            value = positional[-(num_pos - num_args) :]334            assign(star_list_arg, value)335            if star_list_single_arg:336                if len(value) > 1:337                    raise TooManyArguments(338                        TypeError(339                            "%s expected at most 1 arguments, got %d"340                            % (func_name, len(value))341                        )342                    )343        else:344            assign(star_list_arg, ())345    elif 0 < num_args < num_total:346        # Special case for no default values.347        if num_defaults == 0:348            # Special cases text for one argument.349            if num_args == 1:350                raise TooManyArguments(351                    TypeError(352                        "%s() takes exactly one argument (%d given)"353                        % (func_name, num_total)354                    )355                )356            raise TooManyArguments(357                TypeError(358                    "%s expected %d arguments, got %d"359                    % (func_name, num_args, num_total)360                )361            )362        raise TooManyArguments(363            TypeError(364                "%s() takes at most %d %s (%d given)"365                % (366                    func_name,367                    num_args,368                    "argument" if num_args == 1 else "arguments",369                    num_total,370                )371            )372        )373    elif num_args == 0 and num_total:374        if star_dict_arg:375            if num_pos:376                # Could use num_pos, but Python also uses num_total.377                raise TooManyArguments(378                    TypeError(379                        "%s() takes exactly 0 arguments (%d given)"380                        % (func_name, num_total)381                    )382                )383        else:384            raise TooManyArguments(385                TypeError("%s() takes no arguments (%d given)" % (func_name, num_total))386            )387    named_argument_names = [pair[0] for pair in pairs]388    for arg in args + kw_only_args:389        if type(arg) is str and arg in named_argument_names:390            if isAssigned(arg):391                raise TooManyArguments(392                    TypeError(393                        "%s() got multiple values for keyword argument '%s'"394                        % (func_name, arg)395                    )396                )397            new_pairs = []398            for pair in pairs:399                if arg == pair[0]:400                    assign(arg, pair[1])401                else:402                    new_pairs.append(pair)403            assert len(new_pairs) == len(pairs) - 1404            pairs = new_pairs405    # Fill in any missing values with the None to indicate "default".406    if num_defaults > 0:407        for arg in (kw_only_args + args)[-num_defaults:]:408            if not isAssigned(arg):409                assign(arg, None)410    if star_dict_arg:411        assign(star_dict_arg, pairs)412    elif pairs:413        unexpected = next(iter(dict(pairs)))414        if improved:415            message = "%s() got an unexpected keyword argument '%s'" % (416                func_name,417                unexpected,418            )419        else:420            message = (421                "'%s' is an invalid keyword argument for this function" % unexpected422            )423        raise TooManyArguments(TypeError(message))424    unassigned = num_args - len([arg for arg in args if isAssigned(arg)])425    if unassigned:426        num_required = num_args - num_defaults427        # Special case required arguments.428        if num_required > 0 or improved:429            if num_defaults == 0 and num_args != 1:430                raise TooManyArguments(431                    TypeError(432                        "%s expected %d arguments, got %d"433                        % (func_name, num_args, num_total)434                    )435                )436            if num_required == 1:437                arg_desc = "1 argument" if python_version < 0x350 else "one argument"438            else:439                arg_desc = "%d arguments" % num_required440            raise TooManyArguments(441                TypeError(442                    "%s() takes %s %s (%d given)"443                    % (444                        func_name,445                        "at least" if num_defaults > 0 else "exactly",446                        arg_desc,447                        num_total,448                    )449                )450            )451        raise TooManyArguments(452            TypeError(453                "%s expected %s%s, got %d"454                % (455                    func_name,456                    ("at least " if python_version < 0x300 else "")457                    if num_defaults > 0458                    else "exactly ",459                    "%d arguments" % num_required,460                    num_total,461                )462            )463        )464    unassigned = len(kw_only_args) - len(465        [arg for arg in kw_only_args if isAssigned(arg)]466    )467    if unassigned:468        raise TooManyArguments(469            TypeError(470                "%s missing %d required keyword-only argument%s: %s"471                % (472                    func_name,473                    unassigned,474                    "s" if unassigned > 1 else "",475                    " and ".join(476                        "'%s'"477                        % [arg.getName() for arg in kw_only_args if not isAssigned(arg)]478                    ),479                )480            )481        )...robotlibcore.py
Source:robotlibcore.py  
1# Copyright 2017- Robot Framework Foundation2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7# http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14"""Generic test library core for Robot Framework.15Main usage is easing creating larger test libraries. For more information and16examples see the project pages at17https://github.com/robotframework/PythonLibCore18"""19import inspect20import os21import sys22from robot.utils import PY_VERSION23try:24    import typing25except ImportError:26    typing = None27from robot.api.deco import keyword  # noqa F40128from robot import __version__ as robot_version29PY2 = sys.version_info < (3,)30RF31 = robot_version < '3.2'31__version__ = '2.1.0'32class HybridCore(object):33    def __init__(self, library_components):34        self.keywords = {}35        self.keywords_spec = {}36        self.attributes = {}37        self.add_library_components(library_components)38        self.add_library_components([self])39    def add_library_components(self, library_components):40        self.keywords_spec['__init__'] = KeywordBuilder.build(self.__init__)41        for component in library_components:42            for name, func in self.__get_members(component):43                if callable(func) and hasattr(func, 'robot_name'):44                    kw = getattr(component, name)45                    kw_name = func.robot_name or name46                    self.keywords[kw_name] = kw47                    self.keywords_spec[kw_name] = KeywordBuilder.build(kw)48                    # Expose keywords as attributes both using original49                    # method names as well as possible custom names.50                    self.attributes[name] = self.attributes[kw_name] = kw51    def __get_members(self, component):52        if inspect.ismodule(component):53            return inspect.getmembers(component)54        if inspect.isclass(component):55            raise TypeError('Libraries must be modules or instances, got '56                            'class {!r} instead.'.format(component.__name__))57        if type(component) != component.__class__:58            raise TypeError('Libraries must be modules or new-style class '59                            'instances, got old-style class {!r} instead.'60                            .format(component.__class__.__name__))61        return self.__get_members_from_instance(component)62    def __get_members_from_instance(self, instance):63        # Avoid calling properties by getting members from class, not instance.64        cls = type(instance)65        for name in dir(instance):66            owner = cls if hasattr(cls, name) else instance67            yield name, getattr(owner, name)68    def __getattr__(self, name):69        if name in self.attributes:70            return self.attributes[name]71        raise AttributeError('{!r} object has no attribute {!r}'72                             .format(type(self).__name__, name))73    def __dir__(self):74        if PY2:75            my_attrs = dir(type(self)) + list(self.__dict__)76        else:77            my_attrs = super().__dir__()78        return sorted(set(my_attrs) | set(self.attributes))79    def get_keyword_names(self):80        return sorted(self.keywords)81class DynamicCore(HybridCore):82    def run_keyword(self, name, args, kwargs=None):83        return self.keywords[name](*args, **(kwargs or {}))84    def get_keyword_arguments(self, name):85        spec = self.keywords_spec.get(name)86        return spec.argument_specification87    def get_keyword_tags(self, name):88        return self.keywords[name].robot_tags89    def get_keyword_documentation(self, name):90        if name == '__intro__':91            return inspect.getdoc(self) or ''92        spec = self.keywords_spec.get(name)93        return spec.documentation94    def get_keyword_types(self, name):95        spec = self.keywords_spec.get(name)96        if spec is None:97            raise ValueError('Keyword "%s" not found.' % name)98        return spec.argument_types99    def __get_keyword(self, keyword_name):100        if keyword_name == '__init__':101            return self.__init__102        if keyword_name.startswith('__') and keyword_name.endswith('__'):103            return None104        method = self.keywords.get(keyword_name)105        if not method:106            raise ValueError('Keyword "%s" not found.' % keyword_name)107        return method108    def get_keyword_source(self, keyword_name):109        method = self.__get_keyword(keyword_name)110        path = self.__get_keyword_path(method)111        line_number = self.__get_keyword_line(method)112        if path and line_number:113            return '%s:%s' % (path, line_number)114        if path:115            return path116        if line_number:117            return ':%s' % line_number118        return None119    def __get_keyword_line(self, method):120        try:121            lines, line_number = inspect.getsourcelines(method)122        except (OSError, IOError, TypeError):123            return None124        for increment, line in enumerate(lines):125            if line.strip().startswith('def '):126                return line_number + increment127        return line_number128    def __get_keyword_path(self, method):129        try:130            return os.path.normpath(inspect.getfile(method))131        except TypeError:132            return None133class KeywordBuilder(object):134    @classmethod135    def build(cls, function):136        return KeywordSpecification(137            argument_specification=cls._get_arguments(function),138            documentation=inspect.getdoc(function) or '',139            argument_types=cls._get_types(function)140        )141    @classmethod142    def _get_arguments(cls, function):143        arg_spec = cls._get_arg_spec(function)144        argument_specification = cls._get_default_and_named_args(145            arg_spec, function146        )147        argument_specification.extend(cls._get_var_args(arg_spec))148        kw_only_args = cls._get_kw_only(arg_spec)149        if kw_only_args:150            argument_specification.extend(kw_only_args)151        argument_specification.extend(cls._get_kwargs(arg_spec))152        return argument_specification153    @classmethod154    def _get_arg_spec(cls, function):155        if PY2:156            return inspect.getargspec(function)157        return inspect.getfullargspec(function)158    @classmethod159    def _get_default_and_named_args(cls, arg_spec, function):160        args = cls._drop_self_from_args(function, arg_spec)161        args.reverse()162        defaults = list(arg_spec.defaults) if arg_spec.defaults else []163        formated_args = []164        for arg in args:165            if defaults:166                formated_args.append(167                    cls._format_defaults(arg, defaults.pop())168                )169            else:170                formated_args.append(arg)171        formated_args.reverse()172        return formated_args173    @classmethod174    def _drop_self_from_args(cls, function, arg_spec):175        return arg_spec.args[1:] if inspect.ismethod(function) else arg_spec.args176    @classmethod177    def _get_var_args(cls, arg_spec):178        if arg_spec.varargs:179            return ['*%s' % arg_spec.varargs]180        return []181    @classmethod182    def _get_kwargs(cls, arg_spec):183        if PY2:184            return ['**%s' % arg_spec.keywords] if arg_spec.keywords else []185        return ['**%s' % arg_spec.varkw] if arg_spec.varkw else []186    @classmethod187    def _get_kw_only(cls, arg_spec):188        kw_only_args = []189        if PY2:190            return kw_only_args191        for arg in arg_spec.kwonlyargs:192            if not arg_spec.kwonlydefaults or arg not in arg_spec.kwonlydefaults:193                kw_only_args.append(arg)194            else:195                value = arg_spec.kwonlydefaults.get(arg, '')196                kw_only_args.append(cls._format_defaults(arg, value))197        return kw_only_args198    @classmethod199    def _format_defaults(cls, arg, value):200        if RF31:201            return '%s=%s' % (arg, value)202        return arg, value203    @classmethod204    def _get_types(cls, function):205        if function is None:206            return function207        types = getattr(function, 'robot_types', ())208        if types is None or types:209            return types210        return cls._get_typing_hints(function)211    @classmethod212    def _get_typing_hints(cls, function):213        if PY2:214            return {}215        try:216            hints = typing.get_type_hints(function)217        except Exception:218            hints = function.__annotations__219        arg_spec = cls._get_arg_spec(function)220        all_args = cls._args_as_list(function, arg_spec)221        for arg_with_hint in list(hints):222            # remove return and self statements223            if arg_with_hint not in all_args:224                hints.pop(arg_with_hint)225        default = cls._get_defaults(arg_spec)226        return cls._remove_optional_none_type_hints(hints, default)227    @classmethod228    def _args_as_list(cls, function, arg_spec):229        function_args = []230        function_args.extend(cls._drop_self_from_args(function, arg_spec))231        if arg_spec.varargs:232            function_args.append(arg_spec.varargs)233        function_args.extend(arg_spec.kwonlyargs or [])234        if arg_spec.varkw:235            function_args.append(arg_spec.varkw)236        return function_args237    # Copied from: robot.running.arguments.argumentparser238    @classmethod239    def _remove_optional_none_type_hints(cls, type_hints, defaults):240        # If argument has None as a default, typing.get_type_hints adds241        # optional None to the information it returns. We don't want that.242        for arg, default in defaults:243            if default is None and arg in type_hints:244                type_ = type_hints[arg]245                if cls._is_union(type_):246                    types = type_.__args__247                    if len(types) == 2 and types[1] is type(None): # noqa248                        type_hints[arg] = types[0]249        return type_hints250    # Copied from: robot.running.arguments.argumentparser251    @classmethod252    def _is_union(cls, typing_type):253        if PY_VERSION >= (3, 7) and hasattr(typing_type, '__origin__'):254            typing_type = typing_type.__origin__255        return isinstance(typing_type, type(typing.Union))256    @classmethod257    def _get_defaults(cls, arg_spec):258        if not arg_spec.defaults:259            return {}260        names = arg_spec.args[-len(arg_spec.defaults):]261        return zip(names, arg_spec.defaults)262class KeywordSpecification(object):263    def __init__(self, argument_specification=None, documentation=None, argument_types=None):264        self.argument_specification = argument_specification265        self.documentation = documentation...argumentparser.py
Source:argumentparser.py  
1#  Copyright 2008-2015 Nokia Networks2#  Copyright 2016-     Robot Framework Foundation3#4#  Licensed under the Apache License, Version 2.0 (the "License");5#  you may not use this file except in compliance with the License.6#  You may obtain a copy of the License at7#8#      http://www.apache.org/licenses/LICENSE-2.09#10#  Unless required by applicable law or agreed to in writing, software11#  distributed under the License is distributed on an "AS IS" BASIS,12#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13#  See the License for the specific language governing permissions and14#  limitations under the License.15from robotide.lib.robot.errors import DataError16from robotide.lib.robot.utils import JYTHON, PY_VERSION, PY217from robotide.lib.robot.variables import is_dict_var, is_list_var, is_scalar_var18from .argumentspec import ArgumentSpec19if PY2:20    from inspect import getargspec, ismethod21    def getfullargspec(func):22        return getargspec(func) + ([], None, {})23else:24    from inspect import getfullargspec, ismethod25if PY_VERSION >= (3, 5):26    import typing27else:28    typing = None29if JYTHON:30    from java.lang import Class31    from java.util import List, Map32class _ArgumentParser(object):33    def __init__(self, type='Keyword'):34        self._type = type35    def parse(self, source, name=None):36        raise NotImplementedError37class PythonArgumentParser(_ArgumentParser):38    def parse(self, handler, name=None):39        args, varargs, kwargs, defaults, kwonly, kwonlydefaults, annotations \40                = getfullargspec(handler)41        if ismethod(handler) or handler.__name__ == '__init__':42            args = args[1:]  # drop 'self'43        spec = ArgumentSpec(44            name,45            self._type,46            positional=args,47            varargs=varargs,48            kwargs=kwargs,49            kwonlyargs=kwonly,50            defaults=self._get_defaults(args, defaults, kwonlydefaults)51        )52        spec.types = self._get_types(handler, annotations, spec)53        return spec54    def _get_defaults(self, args, default_values, kwonlydefaults):55        if default_values:56            defaults = dict(zip(args[-len(default_values):], default_values))57        else:58            defaults = {}59        if kwonlydefaults:60            defaults.update(kwonlydefaults)61        return defaults62    def _get_types(self, handler, annotations, spec):63        types = getattr(handler, 'robot_types', ())64        if types is None:65            return None66        if types:67            return types68        return self._get_type_hints(handler, annotations, spec)69    def _get_type_hints(self, handler, annotations, spec):70        if not typing:71            return annotations72        try:73            type_hints = typing.get_type_hints(handler)74        except Exception:  # Can raise pretty much anything75            return annotations76        self._remove_mismatching_type_hints(type_hints, spec.argument_names)77        self._remove_optional_none_type_hints(type_hints, spec.defaults)78        return type_hints79    def _remove_mismatching_type_hints(self, type_hints, argument_names):80        # typing.get_type_hints returns info from the original function even81        # if it is decorated. Argument names are got from the wrapping82        # decorator and thus there is a mismatch that needs to be resolved.83        mismatch = set(type_hints) - set(argument_names)84        for name in mismatch:85            type_hints.pop(name)86    def _remove_optional_none_type_hints(self, type_hints, defaults):87        # If argument has None as a default, typing.get_type_hints adds88        # optional None to the information it returns. We don't want that.89        for arg in defaults:90            if defaults[arg] is None and arg in type_hints:91                type_ = type_hints[arg]92                if self._is_union(type_):93                    types = type_.__args__94                    if len(types) == 2 and types[1] is type(None):95                        type_hints[arg] = types[0]96    def _is_union(self, type_):97        if PY_VERSION >= (3, 7) and hasattr(type_, '__origin__'):98            type_ = type_.__origin__99        return isinstance(type_, type(typing.Union))100class JavaArgumentParser(_ArgumentParser):101    def parse(self, signatures, name=None):102        if not signatures:103            return self._no_signatures_arg_spec(name)104        elif len(signatures) == 1:105            return self._single_signature_arg_spec(signatures[0], name)106        else:107            return self._multi_signature_arg_spec(signatures, name)108    def _no_signatures_arg_spec(self, name):109        # Happens when a class has no public constructors110        return self._format_arg_spec(name)111    def _single_signature_arg_spec(self, signature, name):112        varargs, kwargs = self._get_varargs_and_kwargs_support(signature.args)113        positional = len(signature.args) - int(varargs) - int(kwargs)114        return self._format_arg_spec(name, positional, varargs=varargs,115                                     kwargs=kwargs)116    def _get_varargs_and_kwargs_support(self, args):117        if not args:118            return False, False119        if self._is_varargs_type(args[-1]):120            return True, False121        if not self._is_kwargs_type(args[-1]):122            return False, False123        if len(args) > 1 and self._is_varargs_type(args[-2]):124            return True, True125        return False, True126    def _is_varargs_type(self, arg):127        return arg is List or isinstance(arg, Class) and arg.isArray()128    def _is_kwargs_type(self, arg):129        return arg is Map130    def _multi_signature_arg_spec(self, signatures, name):131        mina = maxa = len(signatures[0].args)132        for sig in signatures[1:]:133            argc = len(sig.args)134            mina = min(argc, mina)135            maxa = max(argc, maxa)136        return self._format_arg_spec(name, maxa, maxa-mina)137    def _format_arg_spec(self, name, positional=0, defaults=0, varargs=False,138                         kwargs=False):139        positional = ['arg%d' % (i+1) for i in range(positional)]140        if defaults:141            defaults = {name: '' for name in positional[-defaults:]}142        else:143            defaults = {}144        return ArgumentSpec(name, self._type,145                            positional=positional,146                            varargs='varargs' if varargs else None,147                            kwargs='kwargs' if kwargs else None,148                            defaults=defaults,149                            supports_named=False)150class _ArgumentSpecParser(_ArgumentParser):151    def parse(self, argspec, name=None):152        spec = ArgumentSpec(name, self._type)153        kw_only_args = False154        for arg in argspec:155            if spec.kwargs:156                self._raise_invalid_spec('Only last argument can be kwargs.')157            elif self._is_kwargs(arg):158                self._add_kwargs(spec, arg)159            elif self._is_kw_only_separator(arg):160                if spec.varargs or kw_only_args:161                    self._raise_invalid_spec('Cannot have multiple varargs.')162                kw_only_args = True163            elif self._is_varargs(arg):164                if spec.varargs or kw_only_args:165                    self._raise_invalid_spec('Cannot have multiple varargs.')166                self._add_varargs(spec, arg)167                kw_only_args = True168            elif '=' in arg:169                self._add_arg_with_default(spec, arg, kw_only_args)170            elif spec.defaults and not kw_only_args:171                self._raise_invalid_spec('Non-default argument after default '172                                         'arguments.')173            else:174                self._add_arg(spec, arg, kw_only_args)175        return spec176    def _raise_invalid_spec(self, error):177        raise DataError('Invalid argument specification: %s' % error)178    def _is_kwargs(self, arg):179        raise NotImplementedError180    def _add_kwargs(self, spec, kwargs):181        spec.kwargs = self._format_kwargs(kwargs)182    def _format_kwargs(self, kwargs):183        raise NotImplementedError184    def _is_kw_only_separator(self, arg):185        raise NotImplementedError186    def _is_varargs(self, arg):187        raise NotImplementedError188    def _add_varargs(self, spec, varargs):189        spec.varargs = self._format_varargs(varargs)190    def _format_varargs(self, varargs):191        raise NotImplementedError192    def _add_arg_with_default(self, spec, arg, kw_only_arg=False):193        arg, default = arg.split('=', 1)194        arg = self._add_arg(spec, arg, kw_only_arg)195        spec.defaults[arg] = default196    def _format_arg(self, arg):197        return arg198    def _add_arg(self, spec, arg, kw_only_arg=False):199        arg = self._format_arg(arg)200        target = spec.positional if not kw_only_arg else spec.kwonlyargs201        target.append(arg)202        return arg203class DynamicArgumentParser(_ArgumentSpecParser):204    def _is_kwargs(self, arg):205        return arg.startswith('**')206    def _format_kwargs(self, kwargs):207        return kwargs[2:]208    def _is_kw_only_separator(self, arg):209        return arg == '*'210    def _is_varargs(self, arg):211        return arg.startswith('*') and not self._is_kwargs(arg)212    def _format_varargs(self, varargs):213        return varargs[1:]214class UserKeywordArgumentParser(_ArgumentSpecParser):215    def _is_kwargs(self, arg):216        return is_dict_var(arg)217    def _format_kwargs(self, kwargs):218        return kwargs[2:-1]219    def _is_varargs(self, arg):220        return is_list_var(arg)221    def _format_varargs(self, varargs):222        return varargs[2:-1]223    def _is_kw_only_separator(self, arg):224        return arg == '@{}'225    def _format_arg(self, arg):226        if not is_scalar_var(arg):227            self._raise_invalid_spec("Invalid argument syntax '%s'." % arg)...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
