{hmXdZddlZddlZddlmZddlmZmZddlm Z m Z m Z ddl m Z mZddlmZd ed eefd Zed GddZed GddZed GddeZGddZdS)z#Statement parsing classes for cmd2.N)Iterable) dataclassfield)AnyOptionalUnion) constantsutils)Cmd2ShlexError str_to_splitreturnc0tj|ddS)a/Split the string *str_to_split* using shell-like syntax. A wrapper around shlex.split() that uses cmd2's preferred arguments. This allows other classes to easily call split() the same way StatementParser does. :param str_to_split: the string being split :return: A list of tokens F)commentsposix)shlexsplit)r s \/home/jenkins/workspace/simtester-sanitize/venv/lib/python3.11/site-packages/cmd2/parsing.py shlex_splitrs ;|e5 A A AAT)frozenceZdZUdZeed<eed<eed<ej dZ ej dZ ej dZ dS) MacroArgzInformation used to replace or unescape arguments in a macro value when the macro is resolved. Normal argument syntax: {5} Escaped argument syntax: {{5}}. start_index number_str is_escapedz(? : :BJv&&MMMrrc`eZdZUdZeed<eed<eed<eeZ ee ed<dS)MacrozDefines a cmd2 macro.namevalueminimum_arg_countdefault_factoryarg_listN) rrrr r#r"r!rlistr2rr*rrr,r,Gs_ III JJJ %uT:::Hd8n:::::rr,ceZdZUdZdZeed<dZeed<dZeed<e e Z e eed<dZ eed<dZ eed <dZeed <dZeed <dZeed <dZeed <dZdedededdffd ZedefdZedefdZedefdZede efdZdeeeffdZedeeefddfdZxZS) Statementa;String subclass with additional attributes to store the results of parsing. The ``cmd`` module in the standard library passes commands around as a string. To retain backwards compatibility, ``cmd2`` does the same. However, we need a place to capture the additional output of the command parsing, so we add our own attributes to this subclass. Instances of this class should not be created by anything other than the [StatementParser.parse][cmd2.parsing.StatementParser.parse] method, nor should any of the attributes be modified once the object is created. The string portion of the class contains the arguments, but not the command, nor the output redirection clauses. Tips: 1. `argparse `_ is your friend for anything complex. ``cmd2`` has the decorator ([cmd2.decorators.with_argparser][]) which you can use to make your command method receive a namespace of parsed arguments, whether positional or denoted with switches. 2. For commands with simple positional arguments, use [args][cmd2.Statement.args] or [arg_list][cmd2.Statement.arg_list] 3. If you don't want to have to worry about quoted arguments, see [argv][cmd2.Statement.argv] for a trick which strips quotes off for you. argsrawcommandr0r2multiline_command terminatorsuffixpipe_tooutput output_tor. _pos_args_kw_argsrcHt||S)a,Create a new instance of Statement. We must override __new__ because we are subclassing `str` which is immutable and takes a different number of arguments as Statement. NOTE: @dataclass takes care of initializing other members in the __init__ it generates. )super__new__)clsr.r@rA __class__s rrDzStatement.__new__swwsE***rch|jr|jr|jd|j}n|jr|j}nd}|S)zCombine command and args with a space separating them. Quoted arguments remain quoted. Output redirection and piping are excluded, as are any command terminators.  r6)r9r7selfrtns rcommand_and_argszStatement.command_and_argssM < DI \//DI//CC \ ,CCC rcd}|jr ||jz }|jr |d|jzz }|jr |d|jzz }|jr!|d|jzz }|jr |d|jzz }|S)zIA string containing any ending terminator, suffix, and redirection chars.r6rHz | )r;r<r=r>r?rIs r post_commandzStatement.post_commands ? # 4? "C ; % 3$ $C < ( 54<' 'C ; , 3$ $C~ ,sT^++ rc |j|jzS)zpConcatenate [command_and_args][cmd2.Statement.command_and_args] and [post_command][cmd2.Statement.post_command].)rLrNrJs rexpanded_command_linezStatement.expanded_command_lines$t'888rc|jr?tj|jg}|d|jDng}|S)aA list of arguments a-la ``sys.argv``. The first element of the list is the command after shortcut and macro expansion. Subsequent elements of the list contain any additional arguments, with quotes removed, just like bash would. This is very useful if you are going to use ``argparse.parse_args()``. If you want to strip quotes from the input, you can use ``argv[1:]``. c3>K|]}tj|VdSN)r strip_quotes).0 cur_tokens r z!Statement.argv..s-TTu))44TTTTTTr)r9r rUextendr2rIs rargvzStatement.argvsS < %dl334C JJTTdmTTT T T T TC rc4|jS)zRConvert this Statement into a dictionary for use in persistent JSON history files.)__dict__copyrPs rto_dictzStatement.to_dicts}!!###r source_dictc |tj}n&#t$r}td|ddd}~wwxYw|}|tj=t|fi|S)zRestore a Statement from a dictionary. :param source_dict: source data dictionary (generated using to_dict()) :return: Statement object :raises KeyError: if source_dict is missing required elements z Statement dictionary is missing z fieldN)r5 _args_fieldKeyErrorr])r_r.exkwargss r from_dictzStatement.from_dicts T 56EE T T THbHHHIIt S T!!## 9( )))&)))s 838) rrrr r7r#r"r8r9rr3r2r:r;r<r=r>r?raobjectrrDpropertyrLrNrQrZdictr^ staticmethodre __classcell__)rFs@rr5r5Xs%<D#NNNCMMMGS %555Hd3i555 sJFCGSFCIsK +F + + + + + + + + + #   X cX&9s999X9d3iX$$c3h$$$$*tCH~*+***\*****rr5c eZdZdZ ddeeedeeedeeeefdeeeefddf dZd d d ed e de e effd Z dede efdZ dedefdZdedefdZdedeeefde de ee effdZdedefdZede ede eeffdZde ede efdZdS)StatementParserz>Parse user input as a string into discrete command components.N terminatorsmultiline_commandsaliases shortcutsrc||tjf|_nt||_|t|nd|_||ni|_| tj}tt|dd|_ g}| tj | tj | |jd|D}| ddgd |}d |d }tj||_dS) aInitialize an instance of StatementParser. The following will get converted to an immutable tuple before storing internally: terminators, multiline commands, and shortcuts. :param terminators: iterable containing strings which should terminate commands :param multiline_commands: iterable containing the names of commands that accept multiline input :param aliases: dictionary containing aliases :param shortcuts: dictionary containing shortcuts Nr*c,t|dS)Nr)len)xs rz*StatementParser.__init__..ss1Q4yyrT)keyreversec6g|]}tj|Sr*)r%escaperVrts r z,StatementParser.__init__..1s JJJqbillJJJrz\sz\Z|z \A\s*(\S*?)())r MULTILINE_TERMINATORrmtuplernroDEFAULT_SHORTCUTSsorteditemsrprYQUOTESREDIRECTION_CHARSjoinr%r&_command_pattern) rJrmrnrorpinvalid_command_charssecond_group_items second_groupexprs r__init__zStatementParser.__init__sP" )   ) >@D  $[11D PbPn59K3L3L3Ltv292Eww2  !3Ivioo&7&7=P=PZ^___``&!#$$Y%5666$$Y%@AAA$$T%5666JJ4IJJJ !!5%.111xx 233 .|... " 4 0 0rF) is_subcommandwordrcd}t|tsddt|dfS|sdS|tjrdS|sQ|jD]I\}}||r/d}|dd|jDz }d|fcSJd }g}|tj ||j |dd |Dz }|j |}|r|| d krd }d }||fS)aDetermine whether a word is a valid name for a command. Commands cannot include redirection characters, whitespace, or termination characters. They also cannot start with a shortcut. :param word: the word to check as a command :param is_subcommand: Flag whether this command name is a subcommand name :return: a tuple of a boolean and an error string If word is not a valid command, return ``False`` and an error string suitable for inclusion in an error message of your choice:: checkit = '>' valid, errmsg = statement_parser.is_valid_command(checkit) if not valid: errmsg = f"alias: {errmsg}" Fzmust be a string. Received z instead)Fzcannot be an empty string)Fz'cannot start with the comment characterzcannot start with a shortcut: z, c3 K|] \}}|V dSrTr*)rVshortcut_s rrXz3StatementParser.is_valid_command..^s&'U'U]h'U'U'U'U'U'Urz$cannot contain: whitespace, quotes, c6g|]}tj|Sr*)rquoterzs rr{z4StatementParser.is_valid_command..es >>>U[^^>>>rr Tr6) isinstancer#type startswithr COMMENT_CHARrprrYrrmrsearchgroup) rJrrvalidrrerrmsgerrcharsmatchs ris_valid_commandz StatementParser.is_valid_command;sx&$$$ ONT NNNN N 655 ??91 2 2 DCC )#~ ) ) !??8,,)=Fdii'U'Udn'U'U'UUUUF &=((( ) 8 3444()))$))>>X>>>???%,,T22  TU[[^^++EFf}rlinec"||}|tjrgS t |}n"#t $r}t|dd}~wwxYw||S)aLex a string into a list of tokens. Shortcuts and aliases are expanded and comments are removed. :param line: the command line being lexed :return: A list of tokens :raises Cmd2ShlexError: if a shlex error occurs (e.g. No closing quotation) N) _expandlstriprr rr ValueErrorr split_on_punctuation)rJrtokensrcs rtokenizezStatementParser.tokenizems||D!! ;;== # #I$: ; ; I / &&FF / / / $$$ . /((000s A A9$A44A9c 0d}|ddtjkr tj}d}d}g}||}t|dz}t |D]+\}} |jD]} | | r|}| }n+|rZ|tjkrt|dz}||d|\}}|d|}||dzd}n1||\} } | |jvr| }| }|dd}g}d} d}d} | tj }n#t$rt|}YnwxYw | tj }n#t$rt|}YnwxYw | tj }n#t$rt|}YnwxYw||krG||krA||dzd}tj|d|} |d|}n||kr||krtj }|}ntj }|}t||dzkrr?)r LINE_FEEDrrs enumeratermr_command_and_argsrnindexREDIRECTION_PIPErREDIRECTION_OUTPUTREDIRECTION_APPENDr expand_user_in_tokensrrU expand_userr5)rJrr;r9r7r2rterminator_posposrWtest_terminator testcommandtestargsr=r>r? pipe_index redir_index append_indexpipe_to_tokens output_index unquoted_pathr<r:s rparsezStatementParser.parses 9 + + +",Jt$$Vq'//  NC#'#3  ''88%(N!0JE    Y000!$Vq#44VO^O5LMMOWda./HNQ.001FF&*&<&>ADSTDXXD%,,W555%)*;%<%   Hix(( "8}} &/#t99 ,,\0Bc0I0I'3.'||H.A1EE  rrcd}d}|r|d}t|dkrd|dd}||fS)zOGiven a list of tokens, return a tuple of the command and the args as a string.r6rr rHN)rsr)rr9r7s rrz!StatementParser._command_and_argssQ  QiG v;;??88F122J''D}rcHg}||j|tjg}|D]}t |dks|dtjvr||?d}||}d} ||vr0||vr+||z }|dz }|t |kr ||}nn||v+n5|}||kr-||z }|dz }|t |kr ||}nn||k-||d}|t |krn|S)a|Further splits tokens from a command line using punctuation characters. Punctuation characters are treated as word breaks when they are in unquoted strings. Each run of punctuation characters is treated as a single token. :param tokens: the tokens as parsed by shlex :return: a new list of tokens, further split using punctuation r rr6)rYrmr rrsrappend) rJr punctuationpunctuated_tokenscur_initial_token cur_indexcur_char new_tokencur_puncs rrz$StatementParser.split_on_punctuations"$ 4+,,,96777!'* *  $%%**.?.BiFV.V.V!(():;;;I(3HI ;.."+55!X- !Q $s+<'='==='8'CHH! #+55 (H#h..!X- !Q $s+<'='==='8'CHH! #h.."((333 $5 6 666; :  r)NNNN)rrrr rrr#rhrr$rrr3rr5rrrrrrirrr*rrrlrls0HH046:,0.2 >1>1hsm,>1%Xc]3>1$sCx.) >1 DcN+ >1  >1>1>1>1@DI000S0D0USWY\S\M]0000d1S1T#Y1111.J #J )J J J J X9c39c99c9c9c9cv+++0C+@+SW+ y$s)# $++++@"C"C""""H $s) c3h   \ <!49<!c<!<!<!<!<!<!rrl)r r%rcollections.abcr dataclassesrrtypingrrrr6r r exceptionsr r#r3rrr,r5rlr*rrrs )) $$$$$$  Bc Bd3i B B B B $''''''''@ $ ; ; ; ; ; ; ; ;  $\*\*\*\*\*\*\*\*~a!a!a!a!a!a!a!a!a!a!r