gn\dZddlZddlZddlmZmZddlmZmZm Z m Z m Z m Z m Z ddlmZmZddlmZded e efd Zed Gd dZed GddZed GddeZGddZdS)z"Statement parsing classes for cmd2N) dataclassfield)AnyDictIterableListOptionalTupleUnion) constantsutils)Cmd2ShlexError str_to_splitreturnc0tj|ddS)z 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)rs \/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) MacroArgz Information 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 e e ed<dS)MacrozDefines a cmd2 macronamevalueminimum_arg_countdefault_factoryarg_listN) r r!r"r#r&r%r$rlistr5rrr-rrr/r/Js_ III JJJ %uT:::Hd8n:::::rr/ceZdZUdZdZeed<dZeed<dZeed<e e Z e eed<dZ eed<dZeed <dZeed <dZeed <dZeed <dZeed <dZdedededdffd ZedefdZedefdZedefdZede efdZdeeeffdZedeeefddfdZxZ S) 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. argsrawcommandr3r5multiline_command terminatorsuffixpipe_tooutput output_tor1pos_argskw_argsrcLt||}|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__)clsr1rCrDstmt __class__s rrGzStatement.__new__s!wwsE** 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.  r9)r<r:selfrtns 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)zHA string containing any ending terminator, suffix, and redirection charsr9rLz | )r>r?r@rArBrMs r post_commandzStatement.post_commands ? # 4? "C ; % 3$ $C < ( 54<' 'C ; , 3$ $C~ ,sT^++ rc |j|jzS)zoConcatenate [command_and_args][cmd2.Statement.command_and_args] and [post_command][cmd2.Statement.post_command])rPrRrNs rexpanded_command_linezStatement.expanded_command_lines$t'888rc|jrLtj|jg}|jD])}|tj|*ng}|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:]``. )r<r strip_quotesr5append)rNrO cur_tokens rargvzStatement.argvse < %dl334C!] : :  5-i889999 :C rc4|jS)zcUtility method to convert this Statement into a dictionary for use in persistent JSON history files)__dict__copyrTs rto_dictzStatement.to_dicts}!!###r source_dictc |tj}n%#t$r}td|dd}~wwxYw|}|tj=t|fi|S)a Utility method to restore 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)r8 _args_fieldKeyErrorr])r_r1exkwargss r from_dictzStatement.from_dicts J 56EE J J JHbHHHII I J!!## 9( )))&)))s 727)!r r!r"r#r:r&r%r;r<rr6r5rr=r>r?r@rArBraobjectrrGpropertyrPrRrUrZrr^ staticmethodre __classcell__)rJs@rr8r8[s%<D#NNNCMMMGS %555Hd3i555 sJFCGSFCIsK F s s {       #   X cX&9s999X9d3iX&$c3h$$$$*tCH~*+***\*****rr8c 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(escape.0rss r z,StatementParser.__init__..7s JJJqbillJJJrz\sz\Z|z \A\s*(\S*?)())r MULTILINE_TERMINATORrltuplermrnDEFAULT_SHORTCUTSsorteditemsroextendQUOTESREDIRECTION_CHARSjoinr(r)_command_pattern) rNrlrmrnroinvalid_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|ts"ddtt|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 dS)Nr-)rzshortcut_s r z3StatementParser.is_valid_command..ds&'U'U]h'U'U'U'U'U'Urz$cannot contain: whitespace, quotes, c6g|]}tj|Sr-)rquoterys rr{z4StatementParser.is_valid_command..ks >>>U[^^>>>rr Tr9) isinstancer&type startswithr COMMENT_CHARrorrrrlrsearchgroup) rNrrvalidrrerrmsgerrcharsmatchs ris_valid_commandz StatementParser.is_valid_commandAs&$$$ RQDJJQQQQ Q 655 ??91 2 2 DCC )#~ ) ) !??8,,)=Fdii'U'Udn'U'U'UUUUF &=((( ) 8 3444()))$))>>X>>>???%,,T22  u{{1~~%%f}rlinec$||}|tjrgS t |}n!#t $r}t|d}~wwxYw||}|S)a# Lex 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 ValueErrorrsplit_on_punctuation)rNrtokensrcs rtokenizezStatementParser.tokenizets||D!! ;;== # #I$: ; ; I % &&FF % % % $$ $ %**622 s A A8$A33A8c 6d}|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@rArB)r LINE_FEEDrrr enumeraterlr_command_and_argsrmindexREDIRECTION_PIPErREDIRECTION_OUTPUTREDIRECTION_APPENDrexpand_user_in_tokensrrW expand_userr8)rNrr>r<r:r5rterminator_posposrYtest_terminator testcommandtestargsr@rArB pipe_index redir_index append_indexpipe_to_tokens output_index unquoted_pathr?r= statements rparsezStatementParser.parses 9 + + +",Jt$$Vq'//  NC#'#3  ''88%(N!0JE    Y000!$Vq#44VO^O5LMMOWda./HNQ.001FF&*&<&>ADSTDXXD%,,W555%)*;%<%   Hix(( "8}} t99 ,,\0Bc0I0I$I||Hi;;  rrcd}d}|r|d}t|dkrd|dd}||fS)z`Given a list of tokens, return a tuple of the command and the args as a string. r9rr rLN)rrr)rr<r:s 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 rr9)rrlr rrrrrX) rNr 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)r r!r"r#r rr&rrr'r rrrr8rrr rrrhrrr-rrrkrks*HH046:,0.2 >1>1hsm,>1%Xc]3>1$sCx.) >1 DcN+ >1  >1>1>1>1@DI111S1D1USWY\S\M]1111fST#Y6P#P)PPPPd=3=9====~ / /+0C+@ /SW / y$s)# $ / / / /D"C"C""""H $s) c3h   \ <!49<!c<!<!<!<!<!<!rrk)r#r(r dataclassesrrtypingrrrrr r r r9r r exceptionsrr&rrr/r8rkr-rrrs!)(  BcBd3iBBBB $''''''''@ $ ; ; ; ; ; ; ; ;  $_*_*_*_*_*_*_*_*Dt!t!t!t!t!t!t!t!t!t!r