{h dZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlmZmZddlmZddlmZddlmZmZmZmZmZmZmZmZddlmZdd l m!Z!m"Z"erddl#Z#e j$e%Z&ne j$Z&ed Z'd e%d e(fd Z)d e%d e%fdZ*d e%d e%fdZ+d e%d e%fdZ,ded e(fdZ-GddZ.de%d e(fdZ/de0e'd e0e'fdZ1de%d e%fdZ2dee%d e0e%fdZ3de%d ee4e%ffdZ5de%d e0ee4e%ffdZ6dee%d e0e%fd Z7d!e0e%d"e0e%d dfd#Z8d!e0e%d$e0e%d dfd%Z9d&e%d e%fd'Z:d!e0e%d dfd(Z;d ee%fd)Zej=fd-e0e%d+e4d e0e%fd.Z?d/e%d e0e%fd0Z@Gd1d2ZAGd3d4ZBGd5d6ZCGd7d8ZDGd9d:ZEd;e0e%d e0e%fd<ZFGd=d>eZGd?dd@dAdBdCe%dDeGdEe%dFee4dGe4dHe(d e%fdIZHd?dd@dAdBdCe%dEe%dFee4dGe4dHe(d e%f dJZId?dd@dAdBdCe%dEe%dFee4dGe4dHe(d e%f dKZJd?dd@dAdBdCe%dEe%dFee4dGe4dHe(d e%f dLZKd@dMdNe%dOe4dGe4d e%fdPZLdCe%d eMe4e%ffdQZNdReedSefeedSeffdTe%d dfdUZOdVedSefd eePefdWZQGdXdYeZRGdZd[ZSd\e%d e%fd]ZTd^e%d_e%d eUfd`ZVdaZW dhdbe%dcee%ddeee%e%geUfd ee%fdeZXdfedSefd eYeMe%efeffdgZZdS)izShared utility functions.N)CallableIterable)SequenceMatcher)Enum) TYPE_CHECKINGAnyOptionalTextIOTypeVarUnioncastget_type_hints) constants)ChoicesProviderFunc CompleterFunc_Targreturnctt|dko%|d|dko|dtjvS)z~Check if a string is quoted. :param arg: the string being checked for quotes :return: True if a string is quoted rr)lenrQUOTESrs Z/home/jenkins/workspace/simtester-sanitize/venv/lib/python3.11/site-packages/cmd2/utils.py is_quotedr"s7 s88a< LCFc"g- L#a&IQuote a string if it contains spaces and isn't already quoted. )rr#rs rquote_string_if_neededr&2s+~~C   rc8t|r |dd}|S)zStrip outer quotes from a string. Applies to both single and double quotes. :param arg: string to strip outer quotes from :return: same string with potentially outer quotes stripped rr)rrs r strip_quotesr(:s$~~!B$i Jrvalc2t|tr]|tdkrdS|tdkrdStdt|tr|St |S)aConvert anything to a boolean based on its value. Strings like "True", "true", "False", and "false" return True, True, False, and False respectively. All other values are converted using bool() :param val: value being converted :return: boolean value expressed in the passed in value :raises ValueError: if the string does not contain a value corresponding to a boolean value TFz(must be True or False (case-insensitive)) isinstancestr capitalize ValueErrorbool)r)s rto_boolr0Gs#sE >>  s4yy ( (4 >>  s5zz ) )5CDDD#t 99rceZdZdZdddddddedeeeeegeffdede de ed e eee e gefd e e ed e e d e ed dfdZd efdZded dfdZdS)SettablezMUsed to configure an attribute to be settable via the set command in the CLI.N)settable_attrib_name onchange_cbchoiceschoices_provider completernameval_type descriptionsettable_objectr3r4r5r6r7rc|tur9dtdttfd} t}t t | }||_||_||_||_ ||n||_ ||_ ||_ ||_ | |_dS)aSettable Initializer. :param name: name of the instance attribute being made settable :param val_type: callable used to cast the string value from the command line into its proper type and even validate its value. Setting this to bool provides tab completion for true/false and validation using to_bool(). The val_type function should raise an exception if it fails. This exception will be caught and printed by Cmd.do_set(). :param description: string describing this setting :param settable_object: object to which the instance attribute belongs (e.g. self) :param settable_attrib_name: name which displays to the user in the output of the set command. Defaults to `name` if not specified. :param onchange_cb: optional function or method to call when the value of this settable is altered by the set command. (e.g. onchange_cb=self.debug_changed) Cmd.do_set() passes the following 3 arguments to onchange_cb: param_name: str - name of the changed parameter old_value: Any - the value before being changed new_value: Any - the value after being changed The following optional settings provide tab completion for a parameter's values. They correspond to the same settings in argparse-based tab completion. A maximum of one of these should be provided. :param choices: iterable of accepted values :param choices_provider: function that provides choices for this argument :param completer: tab completion function that provides choices for this argument _rc ddgS)z&Tab complete lowercase boolean values.truefalser!)r=s rget_bool_choicesz+Settable.__init__..get_bool_choicess ((rN)r/r,listr0r rr8r9r: settable_objr3r4r5r6r7) selfr8r9r:r;r3r4r5r6r7rAs r__init__zSettable.__init___sN t   )C )DI ) ) ) )H#$79IJJ    &+ > > > > # " " "r)__name__ __module__ __qualname____doc__r,r typerrobjectr rrrrrErIrTr!rrr2r2\s4WW/3>B+/:>-18#8#8#8#S 8SE3J#7788# 8#  8#'sm8#hR}c'9:;8#(3-(8###678#M*8# 8#8#8#8#tE3EEEE?s?t??????rr2 file_pathcddl}tjtj|}d} ||dd5}td|Ddkrd}dddn #1swxYwYn#t$rt$rYnwxYw|S) zReturn if a file contains only ASCII or UTF-8 encoded text and isn't empty. :param file_path: path to the file being checked :return: True if the file is a non-empty text file, otherwise False :raises OSError: if file can't be read rNFutf-8strictencodingerrorsc3K|]}dVdS)rNr!).0r=s r zis_text_file..s..1......rT) codecsospathabspath expanduserstripopensumOSErrorUnicodeDecodeError)r[re expanded_pathvalid_text_filefs r is_text_filerrsMMMGOOBG$6$6y7H7H$I$IJJMO  [[[ J J 'a..a...  1$$"& ' ' ' ' ' ' ' ' ' ' ' ' ' ' '        s6B&. B B&BB&!B"B&&B=<B= list_to_prunec~tj}|D]}d||<t|S)zRemove duplicates from a list while preserving order of the items. :param list_to_prune: the list being pruned of duplicates :return: The pruned list N) collections OrderedDictrBkeys)rs temp_dictitems rremove_duplicatesrzsD 3>2I2K2KI $    ! !!rastrcPtjd|S)zNormalize and casefold Unicode strings for saner comparisons. :param astr: input unicode string :return: a normalized and case-folded version of the input string NFC) unicodedata normalizecasefold)r{s r norm_foldrs#   - - 6 6 8 88r list_to_sortc.t|tS)a)Sorts a list of strings alphabetically. For example: ['a1', 'A11', 'A2', 'a22', 'a3'] To sort a list in place, don't call this method, which makes a copy. Instead, do this: my_list.sort(key=norm_fold) :param list_to_sort: the list being sorted :return: the sorted list key)sortedrrs ralphabetical_sortrs ,I . . ..r input_strc` t|S#t$rt|cYSwxYw)zTry to convert the passed-in string to an integer. If that fails, it converts it to lower case using norm_fold. :param input_str: string to convert :return: the string as an integer or a lower case version of the string. )intr.rrs rtry_int_or_force_to_lower_casersB $9~~ $$$#####$s --c@dtjd|DS)zConvert a string into a list of integers and strings to support natural sorting (see natural_sort). For example: natural_keys('abc123def') -> ['abc', '123', 'def'] :param input_str: string to convert :return: list of strings and integers c,g|]}t|Sr!)r)rcsubstrs r z natural_keys..s! _ _ _v *6 2 2 _ _ _rz(\d+))resplitrs r natural_keysrs& ` _(T]A^A^ _ _ __rc.t|tS)aQSorts a list of strings case insensitively as well as numerically. For example: ['a1', 'A2', 'a3', 'A11', 'a22'] To sort a list in place, don't call this method, which makes a copy. Instead, do this: my_list.sort(key=natural_keys) :param list_to_sort: the list being sorted :return: the list sorted naturally r)rrrs r natural_sortr s ,L 1 1 11rtokenstokens_to_quotec\t|D]\}}||vrt|||<dS)zQuote specific tokens in a list. :param tokens: token list being edited :param tokens_to_quote: the tokens, which if present in tokens, to quote N) enumerater#)rritokens rquote_specific_tokensrsF f%%,,5 O # #$U++F1I,,rtokens_to_unquotec`t|D]\}}t|}||vr|||<dS)zUnquote specific tokens in a list. :param tokens: token list being edited :param tokens_to_unquote: the tokens, which if present in tokens, to unquote N)rr()rrrrunquoted_tokens runquote_specific_tokensr#sL f%%''5%e,, . . .&F1I''rrc|rRt|r|d}t|}nd}tj|}|r||z|z}|S)zkWrap os.expanduser() to support expanding ~ in quoted strings. :param token: the string to expand r)rr(rfrgri)r quote_chars r expand_userr/sl  4 U   qJ ''EEJ""5))  4&3E Lrc`t|D]\}}t||||<dS)zaCall expand_user() on all tokens in a list of strings. :param tokens: tokens to expand. N)rr)rindexr=s rexpand_user_in_tokensrDs@ f%%33q#F5M22u 33rctjd}|s$tjdddkrgd}ngd}tjd}|gn-d|tjjD}tj ||D]\}}tj ||}tj |ratj |tjrBtjdddkr&tj|d }n|}nd}|S) zSet cmd2.Cmd.DEFAULT_EDITOR. If EDITOR env variable is set, that will be used. Otherwise the function will look for a known editor in directories specified by PATH env variable. :return: Default editor or None. EDITORNwin)zcode.cmdz notepad++.exez notepad.exe) vimviemacsnanopicojoecodesublatomgeditgeanykatePATHcPg|]#}tj|!|$Sr!rfrgislinkrcps rrzfind_editor..\s0,q,q,q1_a_f_m_mno_p_p,qQ,q,q,qrr)rfenvirongetsysplatformgetenvrrgpathsep itertoolsproductrMisfileaccessX_OKsplitext)editoreditorsenv_pathpathspossible_editorrg editor_paths r find_editorrMs3 Z^^H % %F  < u $ $BBBGGuuuG9V$$&,q,qrw8W8W,q,q,q%.%6w%F%F   !OT',,t_==Kw~~k** rybg/N/N <#u,,W--o>>qAFF,FF MrpatternrcDfdtj|DS)avReturn a list of file paths based on a glob pattern. Only files are returned, not directories, and optionally only files for which the user has a specified access to. :param pattern: file name or glob pattern :param access: file access type to verify (os.* where * is F_OK, R_OK, W_OK, or X_OK) :return: list of files matching the name or glob pattern c|g|]8}tj|!tj|6|9Sr!)rfrgrr)rcrqrs rrz+files_from_glob_pattern..vs> X X X!RW^^A->-> X29QPVCWCW XA X X Xr)glob)rrs `rfiles_from_glob_patternrms* Y X X Xty)) X X XXrpatternsc`g}|D](}t||}||)|S)aReturn a list of file paths based on a list of glob patterns. Only files are returned, not directories, and optionally only files for which the user has a specified access to. :param patterns: list of file names and/or glob patterns :param access: file access type to verify (os.* where * is F_OK, R_OK, W_OK, or X_OK) :return: list of files matching the names and/or glob patterns r)rextend)rrfilesrmatchess rfiles_from_glob_patternsrysD E)'&AAA W Lr starts_withcddg}|D] }||vrgcS tjd}|gn-d|tjjD}t }|D]w}tj||}t|dztj}|D]4} | tj | 5xt|S)zReturn names of executables in a user's path. :param starts_with: what the exes should start with. leave blank for all exes in path. :return: a list of matching exe names *?rNcPg|]#}tj|!|$Sr!rrs rrz$get_exes_in_path..s0(m(m(mq[][b[i[ijk[l[l(m(m(m(mrr) rfrrrgrsetrMrraddbasenamerB) r wildcardswildcardrrexes_setrg full_pathrmatchs rget_exes_in_pathrsc I { " "III #y  H"BB(m(mHNN27?4S4S(m(m(mEuuH22GLL{33 ))c/"'JJJ 2 2E LL))%00 1 1 1 1 2 >>rc eZdZdZdddddeedfdeded ed d f d Zd ed d fdZ d efdZ d e fdZ dde ed efdZd e fdZddZd efdZed efdZded efdZd S)StdSimzClass to simulate behavior of sys.stdout or sys.stderr. Stores contents in internal buffer and optionally echos to the inner stream it is simulating. Fr]replace)echor`ra inner_streamrr`rarNct||_||_||_||_d|_t ||_dS)afStdSim Initializer. :param inner_stream: the wrapped stream. Should be a TextIO or StdSim instance. :param echo: if True, then all input will be echoed to inner_stream :param encoding: codec for encoding/decoding strings (defaults to utf-8) :param errors: how to handle encoding/decoding errors (defaults to replace) FN)rrr`ra pause_storageByteBufbuffer)rDrrr`ras rrEzStdSim.__init__s:)    "dmm rsc*t|tstdt||js4|jxj||j|j z c_|j r|j |dSdS)zAdd str to internal bytes buffer and if echo is True, echo contents to inner stream. :param s: String to write to the stream z"write() argument must be str, not r_N) r+r, TypeErrorrYrrbyte_bufencoder`rarrwrite)rDrs rrz StdSim.writes !S!! LJaJJKK K! Y K AHHdmDKH$X$X X 9 '   # #A & & & & & ' 'rcX|jj|j|jS)z#Get the internal contents as a str.r_)rrdecoder`rarHs rgetvaluezStdSim.getvalues${#**DM$+*VVVrc4t|jjS)z#Get the internal contents as bytes.)bytesrrrHs rgetbyteszStdSim.getbytessT[)***rrsizec ||dkr)|}|nQ|jjd||j|j}|jj|d|j_|S)zRead from the internal contents as a str and then clear them out. :param size: Number of bytes to read from the stream Nrr_)rclearrrrr`ra)rDrresults rreadz StdSim.readsv <42::]]__F JJLLLL[)%4%077W[Wb7ccF#';#7#>DK  rcV|}||S)zARead from the internal contents as bytes and then clear them out.)rr)rDrs r readbyteszStdSim.readbytess!  rcB|jjdS)zClear the internal contents.N)rrrrHs rrz StdSim.clears ""$$$$$rcF|jr|jSdS)z[StdSim only considered an interactive stream if `echo` is True and `inner_stream` is a tty.F)rrisattyrHs rr z StdSim.isattys& 9 .$++-- -urcX t|jjS#t$rYdSwxYw)zHandle when the inner stream doesn't have a line_buffering attribute. Which is the case when running unit tests because pytest sets stdout to a pytest EncodedFile object. F)r/rline_bufferingAttributeErrorrHs rr zStdSim.line_bufferings=  )899 9   55 s  ))rycX||jvr |j|St|j|S)zhWhen an attribute lookup fails to find the attribute in the usual places, this special method is called.)__dict__rGr)rDrys r __getattr__zStdSim.__getattr__s/ 4= =& &t($///r)rrN)rUrVrWrXr r r/r,rErrrrr rrrrr propertyr rrr!rrrrs $$$FH,-$ $  $  $ $$$$, 's 't ' ' ' 'W#WWWW+%++++  #     5 %%%% X00000000rrc6eZdZdZdZdeddfdZdeddfdZdS) rzHUsed by StdSim to write binary data and stores the actual bytes written.)  std_sim_instancerNc:t|_||_dS)z Initialize the ByteBuf instance.N) bytearrayrr)rDrs rrEzByteBuf.__init__s!  0rbcttstdt|jjs|xjz c_|jjrp|jjj |jj rBtfdtjDr|jdSdSdSdS)zVAdd bytes to internal bytes buffer and if echo is True, echo contents to inner stream.z%a bytes-like object is required, not c3 K|]}|vV dSNr!)rcnewliners rrdz ByteBuf.write.. s';i;iWGqL;i;i;i;i;i;irN)r+rrrYrrrrrrrr anyrNEWLINESflush)rDrs `rrz ByteBuf.writes!U## OMDGGMMNN N$2  MMQ MM  % .  ! . 5 ; ;A > > > $3 .;i;i;i;iX_Xh;i;i;i8i8i .%++----- . . . . . .r) rUrVrWrXrrrErrr!rrrrseRRH11D1111 .u.......rrceZdZdZdedeeefdeeefddfdZddZ dd Z dd Z d e ddfd Z ed eeefdeeefddfdZdS) ProcReaderzUsed to capture stdout and stderr from a Popen process if any of those were set to subprocess.PIPE. If neither are pipes, then the process will run normally and no output will be captured. procstdoutstderrrNcT||_||_||_tjd|jddi|_tjd|jddi|_|jj|j |jj |j dSdS)zProcReader initializer. :param proc: the Popen process being read from :param stdout: the stream to write captured stdout :param stderr: the stream to write captured stderr. out_thread read_stdoutT)r8targetkwargs err_threadFN) _proc_stdout_stderr threadingThread_reader_thread_func _out_thread _err_threadr$startr%)rDr#r$r%s rrEzProcReader.__init__*s   $+dF^huw{g|}}}$+dF^huw|g}~~~ :  (   " " $ $ $ :  (   " " $ $ $ $ $ ) (rc"ddl}tjdr!|j|jdS tj|jj }tj ||j dS#t$rYdSwxYw)zASend a SIGINT to the process similar to if +C were pressed.rNr) signalrr startswithr, send_signalCTRL_BREAK_EVENTrfgetpgidpidkillpgSIGINTProcessLookupError)rDr6group_ids r send_sigintzProcReader.send_sigint?s < " "5 ) )  J " "6#: ; ; ; ; ; :djn55 (FM22222%    s8B B Bc8|jdS)zTerminate the process.N)r, terminaterHs rrBzProcReader.terminatePs rc~|jr|j|jr|j|j\}}|r||j||r||j|dSdS)zWait for the process to finish.N) r2is_aliverMr3r, communicate _write_bytesr-r.)rDouterrs rwaitzProcReader.waitTs   $ $ & & $   ! ! # # #   $ $ & & $   ! ! # # #:))++S  1   dlC 0 0 0  1   dlC 0 0 0 0 0 1 1rr(c~|r|jj}|j}n|jj}|j}|t d|ji|}|r8|t|| |||jgdSdS)zThread function that reads a stream from the process. :param read_stdout: if True, then this thread deals with stdout. Otherwise it deals with stderr. Nzread_stream is None) r,r$r-r%r.r.pollpeekrrrF)rDr( read_stream write_stream availables rr1zProcReader._reader_thread_funcds  (*+K2 *eE3J>O *TX * * *\ * * *rr"c>eZdZdZd dZdefdZd dZdeddfdZ dS) ContextFlaga{A context manager which is also used as a boolean flag value within the default sigint handler. Its main use is as a flag to prevent the SIGINT handler in cmd2 from raising a KeyboardInterrupt while a critical code section has set the flag to True. Because signal handling is always done on the main thread, this class is not thread-safe since there is no need. rNcd|_dS)zWhen this flag has a positive value, it is considered set. When it is 0, it is not set. It should never go below 0. rN_ContextFlag__countrHs rrEzContextFlag.__init__s  rc|jdkS)zIDefine the truth value of an object when it is used in a boolean context.rr[rHs r__bool__zContextFlag.__bool__s|arc&|xjdz c_dS)zTWhen a with block is entered, the __enter__ method of the context manager is called.rNr[rHs r __enter__zContextFlag.__enter__s  rargscZ|xjdzc_|jdkrtddS)zqWhen the execution flow exits a with statement block this is called, regardless of whether an exception occurred.rrzcount has gone below 0N)r\r.)rDras r__exit__zContextFlag.__exit__s6  *3&&.)3#:. 3  3  333333rrestyles_to_parsecRddlm}Gdd}|}t|D]T\}}|t|jjt|jjfvr|}||_n|j |s4|j |s|j |r/|j |j |j ||_ n|j |s4|j |s|j |r/|j|j |j||_n|t|jjt|jjt|jjfvr/|j|j |j||_n|t|jjt|jjfvr/|j|j |j||_n%|t|jjt|jjfvr.|j|j |j||_n|t|jjt|jjfvr.|j|j |j||_na|t|jj t|jj!fvr-|j"|j |j"||_"||j |<VtG|j $S)aFilter a style list down to only those which would still be in effect if all were processed in order. Utility function for align_text() / truncate_line(). This is mainly used to reduce how many style strings are stored in memory when building large multiline strings with ANSI styles. We only need to carry over styles from previous lines that are still in effect. :param styles_to_parse: list of styles to evaluate. :return: list of styles that are still in effect. ransiceZdZdZddZdS)-_remove_overridden_styles..StyleStatez,Keeps track of what text styles are enabled.rNci|_d|_d|_d|_d|_d|_d|_d|_d|_dSr) style_dict reset_allfgbg intensityitalicoverline strikethrough underlinerHs rrEz6_remove_overridden_styles..StyleState.__init__sH.0DO-1DN%)DG%)DG,0DN)-DK+/DM04D ,0DNNNrr)rUrVrWrXrEr!rr StyleStaterts.:: 1 1 1 1 1 1rr)%rrrrr, TextStyle RESET_ALL ALT_RESET_ALLrw STD_FG_RErEIGHT_BIT_FG_RE RGB_FG_RErxrvpop STD_BG_REEIGHT_BIT_BG_RE RGB_BG_REryINTENSITY_BOLD INTENSITY_DIMINTENSITY_NORMALrz ITALIC_ENABLEITALIC_DISABLEr{OVERLINE_ENABLEOVERLINE_DISABLEr|STRIKETHROUGH_ENABLESTRIKETHROUGH_DISABLEr}UNDERLINE_ENABLEUNDERLINE_DISABLEr~rBvalues)rorrr style_staterstyles r_remove_overridden_stylesrs11111111$*,,K!/22(.(. u S122C8T4U4UV V V$*,,K$)K ! ! ^ ! !% ( ( *D,@,F,Fu,M,M *QUQ_QeQefkQlQl *~)&**;>:::"KNN ^ ! !% ( ( *D,@,F,Fu,M,M *QUQ_QeQefkQlQl *~)&**;>:::"KNN  - . . , - - / 0 0   $0&**;+@AAA$)K ! ! s4>788#dn>[:\:\] ] ]!-&**;+=>>>!&K   s4>9::C@_<`<`a a a#/&**;+?@@@#(K s4>>??T^EiAjAjk k k(4&**;+DEEE(-K % % s4>:;;SAa=b=bc c c$0&**;+@AAA$)K !). u%%  &--// 0 00rceZdZdZdZdZdZdS) TextAlignmentzHorizontal text alignment.rrN)rUrVrWrXLEFTCENTERRIGHTr!rrrrs#$$ D F EEErrr%F fill_charwidth tab_widthtruncatetext alignmentrrrrcddl}ddl}ddlm}|%|jp t j}|dkrtd| dd|z}| dd}| |} t| dkrtd| |} | d krtd || \} } |r|nd g} |}g}t#| D]\}}|dkr|d |rt'||}| |}|d krtd t)t+|}||krdn||z }|t.jkrd}|}n|t.jkr |dz}||z }n|}d}|| z| z}|| z| z}|d|| |z zz }|d|| |z zz }| s| s|s|rL|r|jj| z|z| z}||jjz }|r|jj| z|z| z}||jjz }||d |z|z|z||t=|}|S)uAlign text for display within a given width. Supports characters with display widths greater than 1. ANSI style sequences do not count toward the display width. If text has line breaks, then each line is aligned independently. There are convenience wrappers around this function: align_left(), align_center(), and align_right() :param text: text to align (can contain multiple lines) :param alignment: how to align the text :param fill_char: character that fills the alignment gap. Defaults to space. (Cannot be a line breaking character) :param width: display width of the aligned text. Defaults to width of the terminal. :param tab_width: any tabs in the text will be replaced with this many spaces. if fill_char is a tab, then it will be converted to one space. :param truncate: if True, then each line will be shortened to fit within the display width. The truncated portions are replaced by a '…' character. Defaults to False. :return: aligned text :raises TypeError: if fill_char is more than one character (not including ANSI style sequences) :raises ValueError: if text or fill_char contains an unprintable character :raises ValueError: if width is less than 1 rNrrqzwidth must be at least 1 r%z1Fill character must be exactly one character longrz*Fill character is an unprintable characterr z/Text to align contains an unprintable characterr) ioshutilrrrget_terminal_sizecolumnsrDEFAULT_TERMINAL_WIDTHr.r strip_stylerrstyle_aware_wcswidthr splitlinesStringIOrr truncate_linerBget_styles_dictrrrrrrrMrrr)rrrrrrrrrrstripped_fill_charfill_char_widthfill_char_style_beginfill_char_style_endlinestext_bufprevious_stylesrline line_width line_stylestotal_fill_widthleft_fill_widthright_fill_width left_fill right_fills r align_textrs:IIIMMM }((**2Vi6V qyy3444 <<cIo . .D!!$,,I)))44 !##KLLL// ::O"FGGH2;AS1T1T..!% /DOO   B4E{{}}H "$O ''4E4E t 199 NN4  . u--D..t44   OPP Q?4007799:: !+e 3 3119K  * * *O/   -. . ..!3O//A  .O %7;MM &/9=OO  SOd.G.G .R.RRSS c-0I0I*0U0UUVV  ! 3$7 3? 3k 3 o N47LLyX[nn 1 1I q!^58MMPZZ]pp $.2 2J y277?#;#;;dBZOPPP {+++3ODD     rc@t|tj||||S)ukLeft align text for display within a given width. Supports characters with display widths greater than 1. ANSI style sequences do not count toward the display width. If text has line breaks, then each line is aligned independently. :param text: text to left align (can contain multiple lines) :param fill_char: character that fills the alignment gap. Defaults to space. (Cannot be a line breaking character) :param width: display width of the aligned text. Defaults to width of the terminal. :param tab_width: any tabs in the text will be replaced with this many spaces. if fill_char is a tab, then it will be converted to one space. :param truncate: if True, then text will be shortened to fit within the display width. The truncated portion is replaced by a '…' character. Defaults to False. :return: left-aligned text :raises TypeError: if fill_char is more than one character (not including ANSI style sequences) :raises ValueError: if text or fill_char contains an unprintable character :raises ValueError: if width is less than 1 r)rrrrrrrrs r align_leftrs$( dM.)5\epx y y yyrc@t|tj||||S)u_Center text for display within a given width. Supports characters with display widths greater than 1. ANSI style sequences do not count toward the display width. If text has line breaks, then each line is aligned independently. :param text: text to center (can contain multiple lines) :param fill_char: character that fills the alignment gap. Defaults to space. (Cannot be a line breaking character) :param width: display width of the aligned text. Defaults to width of the terminal. :param tab_width: any tabs in the text will be replaced with this many spaces. if fill_char is a tab, then it will be converted to one space. :param truncate: if True, then text will be shortened to fit within the display width. The truncated portion is replaced by a '…' character. Defaults to False. :return: centered text :raises TypeError: if fill_char is more than one character (not including ANSI style sequences) :raises ValueError: if text or fill_char contains an unprintable character :raises ValueError: if width is less than 1 r)rrrrs r align_centerrs$( dM0IU^grz { { {{rc@t|tj||||S)unRight align text for display within a given width. Supports characters with display widths greater than 1. ANSI style sequences do not count toward the display width. If text has line breaks, then each line is aligned independently. :param text: text to right align (can contain multiple lines) :param fill_char: character that fills the alignment gap. Defaults to space. (Cannot be a line breaking character) :param width: display width of the aligned text. Defaults to width of the terminal. :param tab_width: any tabs in the text will be replaced with this many spaces. if fill_char is a tab, then it will be converted to one space. :param truncate: if True, then text will be shortened to fit within the display width. The truncated portion is replaced by a '…' character. Defaults to False. :return: right-aligned text :raises TypeError: if fill_char is more than one character (not including ANSI style sequences) :raises ValueError: if text or fill_char contains an unprintable character :raises ValueError: if width is less than 1 r)rrrrs r align_rightrs$( dM/9E]fqy z z zzr)rr max_widthcddl}ddlm}|dd|z}||dkrt d|dkrt d |||kr|St |}d }d}d}|} |s||vrK| ||t||} | ||| z }Q||} || } | |z|kr#tj } || } d }|| z }| | |dz }|tt|} | d | | S) uTruncate a single line to fit within a given display width. Any portion of the string that is truncated is replaced by a '…' character. Supports characters with display widths greater than 1. ANSI style sequences do not count toward the display width. If there are ANSI style sequences in the string after where truncation occurs, this function will append them to the returned string. This is done to prevent issues caused in cases like: truncate_line(Fg.BLUE + hello + Fg.RESET, 3) In this case, "hello" would be truncated before Fg.RESET resets the color from blue. Appending the remaining style sequences makes sure the style is in the same state had the entire string been printed. align_text() relies on this behavior when preserving style over multiple lines. :param line: text to truncate :param max_width: the maximum display width the resulting string is allowed to have :param tab_width: any tabs in the text will be replaced with this many spaces :return: line that has a display width less than or equal to width :raises ValueError: if text contains an unprintable character like a newline :raises ValueError: if max_width is less than 1 rNrrqrr%rz&text contains an unprintable characterzmax_width must be at least 1FTr)rrrrrrr.rrrrrrHORIZONTAL_ELLIPSISrrBrrMr)rrrrrr styles_dictdoner total_width truncated_buf style_lenchar char_widthremaining_styless rrrs*III <<cIo . .D   &&",,BCCD1}}7888   &&)33 "$''K D EKKKMMM K      E 2 3 3 3K.//I OOE " " " Y E E{..t44   #y 0 00D22488JDz! D!!!  ).1k6H6H6J6J1K1KLL 011222  ! ! # ##rcddlm}d}tj} |j||}|nN|||<|t|z }l|S)a4Return an OrderedDict containing all ANSI style sequences found in a string. The structure of the dictionary is: key: index where sequences begins value: ANSI style sequence found at index in text Keys are in ascending order :param text: text to search for style sequences rrqr) rrrrurv ANSI_STYLE_REsearchgroupr4r)rrrr4stylesrs rrr0s E  $ & &F$"))$66 =  % u{{}} U[[]]### $ Mrfunc.categoryct|tr"|D]}t|tj|dSt j|r"t|jtj|dSt|tj|dS)a*Categorize a function. The help command output will group the passed function under the specified category heading :param func: function or list of functions to categorize :param category: category to put it in Example: ```py import cmd2 class MyApp(cmd2.Cmd): def do_echo(self, arglist): self.poutput(' '.join(arglist) cmd2.utils.categorize(do_echo, "Text Processing") ``` For an alternative approach to categorizing commands using a decorator, see [cmd2.decorators.with_category][] N)r+rrPrCMD_ATTR_HELP_CATEGORYinspectismethod__func__)rrrys r categorizerLs,$!!B F FD D):H E E E E F F  $  B y?JJJJJi6AAAAArmethct|tjrt|jSt j|s9t j|rit|drYt|j drDt j |j j D]}|j |j vr|cSt|d|}t j|rrtt j||jdddddd}t|t(r|St+t(t|dd S) a$Attempt to resolve the class that defined a method. Inspired by implementation published here: https://stackoverflow.com/a/25959545/1956611 :param meth: method to inspect :return: class type in which the supplied method was defined. None if it couldn't be resolved. __self__ __class__rz .rr. __objclass__N)r+ functoolspartialget_defining_classrrr isbuiltinhasattrrgetmrorrUrrG isfunction getmodulerWrrsplitrYr )rclss rrrksV$ )**-!$),,,/$/$+D*$=$=/BI$-YdBeBe/>$-"9::  C} ,, -tZ..$g'--t/@/F/F{TU/V/VWX/Y/`/`adfg/h/hij/kll c4  J gdND99 : ::rceZdZdZdZdZdZdS)CompletionModezIEnum for what type of tab completion to perform in cmd2.Cmd.read_input().rrrN)rUrVrWrXNONECOMMANDSCUSTOMr!rrrrs)SS D H FFFrrc6eZdZdZdddejdeddfdZdS) CustomCompletionSettingszQUsed by cmd2.Cmd.complete() to tab complete strings other than command arguments.F)preserve_quotesparserrrNc"||_||_dS)arCustomCompletionSettings initializer. :param parser: arg parser defining format of string being tab completed :param preserve_quotes: if True, then quoted tokens will keep their quotes when processed by ArgparseCompleter. This is helpful in cases when you're tab completing flag-like tokens (e.g. -o, --option) and you don't want them to be treated as argparse flags when quoted. Set this to True if you plan on passing the string to argparse with the tokens still quoted. N)rr)rDrrs rrEz!CustomCompletionSettings.__init__s .r)rUrVrWrXargparseArgumentParserr/rEr!rrrrsT[[SX / / /x6 /D /]a / / / / / /rrdoccd}d}|D]E}|}|dr|rn0|r|r|dz }||z }d}A|rnF|S)zpStrip annotations from a docstring leaving only the text description. :param doc: documentation string rF:rT)rrjr7)rcmd_desc found_firstdoc_line stripped_lines rstrip_doc_annotationsrs HKNN$$   ((   # #C ( (      !D   %HKK   E  Ors1s2cttd||td||S)zRatio from s1,s2 may be different to s2,s1. We keep the max. See https://docs.python.org/3/library/difflib.html#difflib.SequenceMatcher.ratio N)maxrratio)rr s rsimilarity_functionr sE tR,,2244odBPR6S6S6Y6Y6[6[ \ \\rgffffff?requested_commandoptionssimilarity_function_to_usecd}t}|}|pt}|D]*}|||}||kr|}|}+|S)aGiven a requested command and an iterable of possible options returns the most similar (if any is similar). :param requested_command: The command entered by the user :param options: The list of available commands to search for the most similar :param similarity_function_to_use: An optional callable to use to compare commands :return: The most similar command or None if no one is similar N)MIN_SIMIL_TO_CONSIDERlowerr )rrrproposed_command best_similrequested_command_to_compareeachsimils rsuggest_similarrst&J#4#:#:#<#< !;!R?R$$**4::<<9UVV   J#  rfunc_or_methodc t|}n"#t$r}td|d}~wwxYw|dd}t j|r|dd|t durd}||fS)abUse typing.get_type_hints() to extract type hints for parameters and return value. This exists because the inspect module doesn't have a safe way of doing this that works both with and without importing annotations from __future__ until Python 3.10. TODO: Once cmd2 only supports Python 3.10+, change to use inspect.get_annotations(eval_str=True) :param func_or_method: Function or method to return the type hints for :return tuple with first element being dictionary mapping param names to type hints and second element being return type hint, unspecified, returns None z;Argument passed to get_types should be a function or methodNrrD)rrr.rrrrY)r type_hintsexcret_anns r get_typesrsa#N33 aaaVWW]``annXt,,G''%vt$$$$t** w s 1,1r)[rXrrurSrrrrrfr subprocessrr/r~collections.abcrrdifflibrenumrtypingrrr r r r r rrrargparse_customrrcmd2Popenr,rVrr/rr#r&r(r0r2rrrBrzrrrrrrrrrrrF_OKrrrrrr"rYrerrrrrrrdictrrrYrrrrfloatr rrtuplerr!rrr,s&    ........######]]]]]]]]]]]]]]]]]]]]????????#KKK"3'KK"K WT]]M3M4MMMMcc c c    *T?T?T?T?T?T?T?T?nCD6 "T"X "$r( " " " "9C9C9999 /HSM /d3i / / / / $c $eCHo $ $ $ $`C`DsCx$9```` 2x} 2c 2 2 2 2,$s),d3i,D,,,, 'DI '$s) 'PT ' ' ' 'ss*3$s)33333Xc]@9; Y YS Y# YDI Y Y Y YAC  tCy # DQTI     #$s)<^0^0^0^0^0^0^0^0B........8c*c*c*c*c*c*c*c*L77777777<33333333:N1tCyN1T#YN1N1N1N1bD{{{ {{ { C= {  {{ {{{{~$'tVWjozzz z z/7}zPSzcgzzzzz0$'tVWjo||| | |/7}|PS|cg|||||0$'tVWjo{{{ { {/7}{PS{cg{{{{{.BCL$L$L$L$L$3L$sL$L$L$L$^#$sCx.8BU8CH-xc8J/KKLBX[B`dBBBB>;Xc3h/;HT#Y4G;;;;2T$////////"ss2]C]S]U]]]]y}%-c]PXYacfhkblnsbsYtPu c],hsCx0U4S>3;N5Or