jhg#dZddlZddlZddlmZmZmZmZmZm Z m Z ddl m Z m Z erddlmZGddejZdS) acMachinery for running and validating transcripts. If the user wants to run a transcript (see docs/transcript.rst), we need a mechanism to run each command in the transcript as a unit test, comparing the expected output to the actual output. This file contains the class necessary to make that work. This class is used in cmd2.py::run_transcript_tests() N) TYPE_CHECKINGIteratorListOptionalTextIOTuplecast)ansiutils)CmdceZdZUdZdZeded<ddZddZddZ dd Z d e d e e ddfd Z d e de fdZede d e dededee eeff dZdS) Cmd2TestCasezA unittest class used for transcript testing. Subclass this, setting CmdApp, to make a unittest.TestCase class that will execute the commands in a transcript file and expect the results shown. See example.py Nr cmdappreturnc |jru||jj|_t t t jt t |jj|j_dSdSN)r_fetchTranscriptsstdout _orig_stdoutr rr StdSimselfs _/home/jenkins/workspace/simtester-sanitize/venv/lib/python3.11/site-packages/cmd2/transcript.pysetUpzCmd2TestCase.setUp0sm ; ^  " " $ $ $!% 2D !%fel4 HZ;[;[.\.\!]!]DK     ^ ^c:|jr|j|j_dSdSr)rrrrs rtearDownzCmd2TestCase.tearDown8s) ; 3!%!2DK    3 3rc|jrDt|j}|D]\}}|||dSdSr)rsorted transcriptsitems_test_transcript)ritsfname transcripts rrunTestzCmd2TestCase.runTest=si ; 9)//1122C%( 9 9!z%%eZ8888 9 9 9 9rci|_tttt |jdg}|D]N}t |}t||j|<| OdS)N testfiles) r!r rstrgetattrropeniter readlinesclose)rr)r%tfiles rrzCmd2TestCase._fetchTranscriptsCs}cGDKb$I$IJJ   EKKE&*5??+<+<&=&=D U # KKMMMM  rr%r&c ||jdSd}d}tjt|}|dz }|s||jjsY tjt|}n#t $rd}Yn(wxYw|dz }||jjY|t|jjdg} t|}n#t $rd}YnwxYw|dz }||jjr| |t|jjd t|}n0#t $r#}d|d|d}t ||d}~wwxYw|dz }||jjd |} |j | } |jj } d} tj||jjrPd |d |d | d | d } ||  | || | Mg}tj||jjsn| | t|}n#t $rd}Yn:wxYw|dz }tj||jjn| r||| d |}||}d |d |d | d|d| d } |t%j|| t$jt$jz| |dSdS)NrFr Tz=Transcript broke off while reading command beginning at line z with zJCommand indicated application should quit, but more commands in transcriptz File z, line z Command was: z Expected: (nothing) Got:  z Expected: z Got: )rr strip_stylenext startswithvisible_prompt StopIterationlencontinuation_promptappendjoinonecmd_plus_hooksrread assertTruestrip assertFalse_transform_transcript_expectedrematch MULTILINEDOTALL)rr%r&line_numfinishedline command_partsexcmsgcommandstopresultstop_msgmessageexpected_partsexpecteds rr#zCmd2TestCase._test_transcriptKs/ ;  FZ 0 011A 6 [oodk&@AA +D,<,<==DD$#HEA  oodk&@AA "#dk&@"A"A"C"CDEM J''      MH//$+"ABB $$T#dk.M*N*N*P*P%QRRR6 ++DD$666}Zb}}kxyzk{}}C',,#56A //$+"ABB ggm,,G;0099D[',,..FcH%%001KLL |E||(||G||rx|||V\\^^ 4g>>>  x000N&t,,77 8RSS %%d+++ ++DD$#HEA &t,,77 8RSS  4(333ww~..H::8DDHzzzhzzzz^fzzpvzzzG OOBHXvr|bi7OPPRY Z Z Zm6 [6 [6 [6 [6 [sN!A99 BBC"" C10C1 E F 'FF  K K)(K)scd}d} ||||d\}}}|dkr |tj||dz }n}|tj|||z }|dz}||||d\}}}|dkr||||z }|dz}n#|tj||dz dz }n|S)aParse the string with slashed regexes into a valid regex. Given a string like: Match a 10 digit phone number: /\d{3}-\d{3}-\d{4}/ Turn it into a valid regular expression which matches the literal text of the string and the regular expression. We have to remove the slashes because they differentiate between plain text and a regular expression. Unless the slashes are escaped, in which case they are interpreted as plain text, or there is only one slash, which is treated as plain text also. Check the tests in tests/test_transcript.py to see all the edge cases. r2rTFNr ) _escaped_findrCescape)rrTregexstartfirst_slash_possecond_slash_poss rrBz+Cmd2TestCase._transform_transcript_expecteds " .2.@.@5RW.X.X +UOU"$$1UVV9---1U?%:#;<<<'!+373E3EeQPUW[3\3\0(%#a''Qu%5566E-q0EERYq~666E1 2 rrYrZin_regexcB |d|}|dkrn}|dkrnv||dz |dkrc|r||||dz z }|||z }n?|tj|||dz z }|tj||z }|dz}nn|||fS)aFind the next slash in {s} after {start} that is not preceded by a backslash. If we find an escaped slash, add everything up to and including it to regex, updating {start}. {start} therefore serves two purposes, tells us where to start looking for the next thing, and also tells us where in {s} we have already added things to {regex} {in_regex} specifies whether we are currently searching in a regex, we behave differently if we are or if we aren't. T/rVrr \)findrCrX)rYrTrZr]poss rrWzCmd2TestCase._escaped_finds &&e$$CbyyS1Ws]#t++ 3537?!3331US1W_+=!>!>>1S6!2!22 !GEEA Bc5  r)rN)__name__ __module__ __qualname____doc__rr__annotations__rrr'rr*rr#rB staticmethodintboolrrWrrrr$s2#FHUO"""^^^^3333 9999 >[c>[x}>[>[>[>[>[@------^,!S,!S,!,!,!sTWY\}I],!,!,!\,!,!,!rr)rfrCunittesttypingrrrrrrr r2r r cmd2r TestCaserrkrrrps   C!C!C!C!C!8$C!C!C!C!C!r