o
    Ph                     @   s  d Z ddlZddlZddlZddlZddlZddlZdZdddde	dej
e	 dejd	ejd
ejee	dejdejf f dejdejej fddZd!dej
e	 d
ejdeje	 fddZde	de	dejdejf fddZdZeddZeddZeddZeddZejeedd  dS )"uB  
🏃 runs: a better subprocess 🏃
---------------------------------------------------------------------

`runs` has improved versions of `call()`, `check_call()`, `check_output()`,
and `run()` from Python's `subprocess` module that handle multiple commands and
blocks of text, fix some defects, and add some features.


    import runs

    runs('''
        ls
        df -k  # or perhaps -h?
        echo 'Done and done'
    ''')

---

`subprocess` is essential but:

* You can only run one command at a time

* Commands to subprocess must be either a sequence of strings or a string,
  depending on whether `shell=True` or not

* Results are returned by default as bytes and not strings

---

The `runs` functions let you run a block of text as a sequence of subprocess
calls.

`runs` provides call-compatible replacements for the functions
`subprocess.call()`, `subprocess.check_call()`, `subprocess.check_output()`,
and `subprocess.run()`

Each replacement function takes a block of text, which is split into individual
command lines, or a list of commands, and returns a list of values, one for
each command.  A block of text can contain line continuations, and comments,
which are ignored.

The replacement functions also add optional logging, error handling,
and lazy evaluation, and use UTF-8 encoding by default.

The module `runs` is callable - `runs()` is a synonym for `runs.run()`.

EXAMPLES:


    # `runs()` or `runs.run()` writes to stdout and stderr just as if you'd run
    # the commands from the terminal

    import runs

    runs('echo "hello, world!"')  # prints hello, world!

    # runs.check_output() returns a list, one string result for each command

    results = check_output('''
        echo  line   one  # Here's line one.
        echo   'line "  two  "'  # and two!
    ''')
    assert results == ['line one', 'line "  two  "']

    # Line continuations work too, either single or double
    runs('''
        ls -cail

        # One command that takes many lines.
        g++ -DDEBUG  -O0 -g -std=c++17 -pthread -I ./include -lm -lstdc++ \
          -Wall -Wextra -Wno-strict-aliasing -Wpedantic \\
          -MMD -MP -MF -c src/tests.cpp -o build/./src/tests.cpp.o

        echo DONE
     ''')

NOTES:

Exactly like `subprocess`, `runs` differs from the shell in a few ways, so
you can't just paste your shell scripts in:

* Redirection doesn't work.


    result = runs.check_output('echo foo > bar.txt')
    assert result == ['foo > bar.txt\n']

* Pipes don't work.


    result = runs.check_output('echo foo | wc')
    assert result == ['foo | wc \n']

*  Environment variables are not expanded in command lines


    result = runs.check_output('echo $FOO', env={'FOO': 'bah!'})
    assert result == ['$FOO\n']

Environment variables are exported to the subprocess, absolutely,
but no environment variable expension happens on command lines.
    N)call
check_callcheck_outputrunsplit_commandsF)on_exceptionechonamecommandsargsr   r   .kwargsreturnc             	   o   s    |du rd}|dkrt }|rt|stt |}|du r!dd }t|s.tjt |tjd}tt| }|d}t	||D ]6}t
j|dd}	|rRd	d
d |	D }	z||	g|R i |}
W n tyo   |si || Y q=w |
V  q=d S )NT$ c                  W   s   d S N )xr   r   H/var/www/html/env_mimamsha/lib/python3.10/site-packages/runs/__init__.py<lambda>   s    z_run.<locals>.<lambda>)fileshellcomments c                 s   s    | ]}t |V  qd S r   )shlexquote).0cr   r   r   	<genexpr>   s    z_run.<locals>.<genexpr>)printcallable	functoolspartialsysstderrgetattr
subprocessgetr   r   splitjoin	Exception)r	   r
   r   r   r   r   functionr   linecmdresultr   r   r   _runt   s4   

r/   linesc                 #   s    g  dt jt f fdd}t| tr|  } | D ]>}|o!|| |drMdtj|d d dd}|	d	|	d	krCt
d
 |d d  q | | E d H  q| E d H  d S )Nr   c                  3   s*    d   }    | r| V  d S d S )Nr   )r)   stripclear)partswaitingr   r   emit   s   
zsplit_commands.<locals>.emit\r   Tr   #z+Comments cannot contain a line continuation)tIteratorstr
isinstance
splitlinesendswithr)   r   r(   count
ValueErrorappend)r0   r   r6   r,   no_commentsr   r4   r   r      s    



r   summaryc                    s|   ddd dddddt jt dt jdtdtdt jd	td
tdtdt jdt jt jt tf f fdd} |_tj	 |d|_
|S )NFutf8)iterateencodingr   r   mergealways_listr
   r   rF   rG   r   r   rH   rI   r   r   c                   sf   |j |||d |r|j tjd t | g|R i |}	|r!|	S t|	}
|s-t|
dkr/|
S |
d S )N)r   rG   r   )r$      r   )updater&   STDOUTr/   listlen)r
   rF   rG   r   r   rH   rI   r   r   itr.   r	   r   r   wrapped   s   z_wrap.<locals>.wrapped)r+   rD   )r:   Sequencer<   AnyboolUnionIterable__name___ARGSformat__doc__)r	   rD   rQ   r   rP   r   _wrap   s<   	
r[   a  
{summary}
See the help for `subprocess.{function}()` for more information.

Arguments:
  commands:
    A string, which gets split into lines on line endings, or a list of
    strings.

  args:
    Positional arguments to `subprocess.{function}()` (but prefer keyword
    arguments!)

  on_exception:
    If `on_exception` is `False`, the default, exceptions from
    `subprocess.{function}()` are raised as usual.

    If `on_exception` is True, they are ignored.

    If `on_exception` is a callable, the line that caused the exception is
    passed to it.

    If `on_exception` is a string, the line causing the exception
    is printed, prefixed with that string.

  echo:
    If `echo` is `False`, the default, then commands are silently executed.
    If `echo` is `True`, commands are printed prefixed with `$`
    If `echo` is a string, commands are printed prefixed with that string
    If `echo` is callable, then each command is passed to it.

  merge:
    If True, stderr is set to be subprocess.STDOUT

  always_list:
    If True, the result is always a list.
    If False, the result is a list, unless the input is of length 1, when
    the first element is returned.

  iterate:
    If `iterate` is `False`, the default, then a list of results is
    returned.

    Otherwise an iterator of results which is returned, allowing for lazy
    evaluation.

  encoding:
    Like the argument to `subprocess.{function}()`, except the default  is
    `'utf8'`

  kwargs:
    Named arguments passed on to `subprocess.{function}()`
r   znCall `subprocess.call()` on each command.
Return a list of integer returncodes, one for each command executed.r   zCall `subprocess.check_call()` on each command.
If any command has a non-zero returncode, raise `subprocess.CallProcessError`.
r   zCall `subprocess.check_output()` on each command.
If a command has a non-zero exit code, raise a `subprocess.CallProcessError`.
Otherwise, return the results as a list of strings, one for each command.r   zbCall `subprocess.run()` on each command.
Return a list of `subprocess.CompletedProcess` instances.T)mutabler   )rZ   r!   r   r&   r#   typingr:   xmod__all__r<   rR   rS   rU   rT   Callabler;   r/   r   r[   rX   r   r   r   r   rW   r   r   r   r   <module>   sZ    h

&+"6