How to use kw_only_args method in Robotframework

Best Python code snippet using robotframework

parser.py

Source:parser.py Github

copy

Full Screen

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')...

Full Screen

Full Screen

ParameterSpecs.py

Source:ParameterSpecs.py Github

copy

Full Screen

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 )...

Full Screen

Full Screen

robotlibcore.py

Source:robotlibcore.py Github

copy

Full Screen

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...

Full Screen

Full Screen

argumentparser.py

Source:argumentparser.py Github

copy

Full Screen

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)...

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Robotframework automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful