o |nh"?@sdZddlZddlZddlmZddlmZmZddlmZddl m Z ddl m Z m Z mZmZmZmZdd lmZdd lmZ d%d ed ede de dee eeefeff ddZdeeeefde de de eeeffddZdeeeefde de defddZ  d&dedededede de deee ffddZ d'dededede de def dd Z d'dededede de de f d!d"ZGd#d$d$eZdS)(zCommon Shell Utilities.Ngetpass)PopenPIPE)Process)Thread)AnyTupleListUnionCallableOptional) MetaMixin)FrameworkErrorTcommandcaptureargskwargsreturncOsX|dd|d<|durt|g|Ri|\}}}|||fSt|g|Ri|}|S)aL Wrapper around ``exec_cmd`` and ``exec_cmd2`` depending on whether capturing output is desired. Defaults to setting the Popen ``shell`` keyword argument to ``True`` (string command rather than list of command and arguments). Arguments: command (str): The command (and arguments) to run. capture (bool): Whether or not to capture output. Other Parameters: args: Additional arguments are passed to ``Popen()``. kwargs: Additional keyword arguments are passed to ``Popen()``. Returns: tuple: When ``capture==True``, returns the ``(stdout, stderror, return_code)`` of the command. int: When ``capture==False``, returns only the ``exitcode`` of the command. Example: .. code-block:: python from cement.utils import shell # execute a command and capture output stdout, stderr, exitcode = shell.cmd('echo helloworld') # execute a command but do not capture output exit_code = shell.cmd('echo helloworld', capture=False) shellT)getexec_cmd exec_cmd2)rrrrstdoutstderrexitcoderJ/usr/local/bin/dhwp/env/lib/python3.10/site-packages/cement/utils/shell.pycmds % rcmd_argscOs^d|vr t|d<d|vrt|d<t|g|Ri|}|\}}||||jfS)a Execute a shell call using Subprocess. All additional ``*args`` and ``**kwargs`` are passed directly to ``subprocess.Popen``. See `Subprocess `_ for more information on the features of ``Popen()``. Args: cmd_args (list): List of command line arguments. Other Parameters: args: Additional arguments are passed to ``Popen()``. kwargs: Additional keyword arguments are passed to ``Popen()``. Returns: tuple: The ``(stdout, stderror, return_code)`` of the command. Example: .. code-block:: python from cement.utils import shell stdout, stderr, exitcode = shell.exec_cmd(['echo', 'helloworld']) rr)keysrr communicatewait returncode)r rrprocrrrrrr@s    rcOs$t|g|Ri|}||jS)a Similar to ``exec_cmd``, however does not capture stdout, stderr (therefore allowing it to print to console). All additional ``*args`` and ``**kwargs`` are passed directly to ``subprocess.Popen``. See `Subprocess `_ for more information on the features of ``Popen()``. Args: cmd_args (list): List of command line arguments Other Parameters: args: Additional arguments are passed to ``Popen()`` kwargs: Additional keyword arguments are passed to ``Popen()`` Returns: int: The integer return code of the command. Example: .. code-block:: python from cement.utils import shell exitcode = shell.exec_cmd2(['echo', 'helloworld']) )rr#r$)r rrr%rrrrhsrFtargetstartjointhreadcOs<|durt|||g|Ri|St|||g|Ri|S)a Wrapper around ``spawn_process`` and ``spawn_thread`` depending on desired execution model. Args: target (function): The target function to execute in the sub-process. Keyword Args: start (bool): Call ``start()`` on the process before returning the process object. join (bool): Call ``join()`` on the process before returning the process object. Only called if ``start == True``. thread (bool): Whether to spawn as thread instead of process. Other Parameters: args: Additional arguments are passed to ``Process()`` kwargs: Additional keyword arguments are passed to ``Process()``. Returns: object: The process object returned by Process(). Example: .. code-block:: python from cement.utils import shell def add(a, b): print(a + b) p = shell.spawn(add, args=(12, 27)) p.join() T) spawn_thread spawn_process)r&r'r(r)rrrrrspawns'r,cOF||d<t|i|}|r|s||S|r!|r!|||S)a^ A quick wrapper around ``multiprocessing.Process()``. By default the ``start()`` function will be called before the spawned process object is returned. See `MultiProcessing `_ for more information on the features of ``Process()``. Args: target (function): The target function to execute in the sub-process. Keyword Args: start (bool): Call ``start()`` on the process before returning the process object. join (bool): Call ``join()`` on the process before returning the process object. Only called if ``start == True``. Other Parameters: args: Additional arguments are passed to ``Process()`` kwargs: Additional keyword arguments are passed to ``Process()``. Returns: object: The process object returned by Process(). Example: .. code-block:: python from cement.utils import shell def add(a, b): print(a + b) p = shell.spawn_process(add, args=(12, 27)) p.join() r&)rr'r()r&r'r(rrr%rrrr+)r+cOr-)a> A quick wrapper around ``threading.Thread()``. By default the ``start()`` function will be called before the spawned thread object is returned See `Threading `_ for more information on the features of ``Thread()``. Args: target (function): The target function to execute in the thread. Keyword Args: start (bool): Call ``start()`` on the thread before returning the thread object. join (bool): Call ``join()`` on the thread before returning the thread object. Only called if ``start == True``. Other Parameters: args: Additional arguments are passed to ``Thread()``. kwargs: Additional keyword arguments are passed to ``Thread()``. Returns: object: The thread object returned by ``Thread()``. Example: .. code-block:: python from cement.utils import shell def add(a, b): print(a + b) t = shell.spawn_thread(add, args=(12, 27)) t.join() r&)rr'r()r&r'r(rrthrrrrr*r.r*c seZdZdZGdddZ ddeedededdffd d Zdedefd d Z dedefd dZ dedefddZ dddZ deefddZ dddZZS)Prompta A wrapper around ``input`` whose purpose is to limit the redundent tasks of gather usr input. Can be used in several ways depending on the use case (simple input, options, and numbered selection). Args: text (str): The text displayed at the input prompt. Example: Simple prompt to halt operations and wait for user to hit enter: .. code-block:: python p = shell.Prompt("Press Enter To Continue", default='ENTER') .. code-block:: text $ python myapp.py Press Enter To Continue $ Provide a numbered list for longer selections: .. code-block:: python p = Prompt("Where do you live?", options=[ 'San Antonio, TX', 'Austin, TX', 'Dallas, TX', 'Houston, TX', ], numbered = True, ) .. code-block:: text Where do you live? 1: San Antonio, TX 2: Austin, TX 3: Dallas, TX 4: Houston, TX Enter the number for your selection: Create a more complex prompt, and process the input from the user: .. code-block:: python class MyPrompt(Prompt): class Meta: text = "Do you agree to the terms?" options = ['Yes', 'no', 'maybe-so'] options_separator = '|' default = 'no' clear = True max_attempts = 99 def process_input(self): if self.input.lower() == 'yes': # do something crazy pass else: # don't do anything... maybe exit? print("User doesn't agree! I'm outa here") sys.exit(1) MyPrompt() .. code-block:: text $ python myapp.py [TERMINAL CLEAR] Do you agree to the terms? [Yes|no|maybe-so] no User doesn't agree! I'm outa here $ echo $? $ 1 c@seZdZUdZdZeed<dZeeed<dZ ee ed<dZ eed<d Z e ed <d Zeed <d Ze ed<d Ze ed<d Ze ed<dZeed<dZeed<d Ze ed<d Ze ed<dS)z Prompt.Metazk Optional meta-data (can also be passed as keyword arguments to the parent class). zTell me someting interesting:textNdefaultoptions,options_separatorFnumberedz$Enter the number for your selection:selection_textTautocase_insensitiveclear clear_command max_attemptsmax_attempts_exceptionsuppress)__name__ __module__ __qualname____doc__r1str__annotations__r2r r3dictr5r6boolr7r8r9r:r;r=intr>r?rrrrMetaxs           rINr1rkwrcsD|dur||d<tt|j|i|d|_|jjr |dSdS)Nr1)superr0__init__input_metar8prompt)selfr1rrJ __class__rrrLs zPrompt.__init__cCs t|}|SNrrPr1resrrr_get_suppressed_inputszPrompt._get_suppressed_inputcCst|}|SrS)builtinsrMrTrrr_get_unsuppressed_inputs zPrompt._get_unsuppressed_inputcCs(|jjdur ||}|S||}|S)NT)rNr?rVrXrTrrr _get_inputs   zPrompt._get_inputcCs|jjr t|jjd}|jjdurW|jjdurC||jjd}d}|jjD]}||d|d}|d7}q'|d}||jj}n|jj }|jjd| |jjd}n|jj}| |d |_ |j dkrv|jj durv|jj |_ dS|j dkrd|_ dSdS) NTz z:  z [] )rNr:ossystemr;r3r6r1r7r5r(rYrMr2)rPr1countoptionseprrr_prompts*       zPrompt._promptc Csd}|jdur||t|jjkr|jjdurtd|jS|d7}||jdur*q|jjdurw|jjrQz|jjt|jd|_Wn4t t fyPd|_Yqw|jj durldd|jjD}|j |vrkd|_qn |j|jjvrwd|_q|jdus| |jS)zK Prompt the user, and store their input as ``self.input``. rNTz2Maximum attempts exceeded getting valid user inputr[cSsg|]}|qSr)lower).0xrrr s z!Prompt.prompt..)rMrHrNr=r>rrdr3r6 IndexError ValueErrorr9re process_input)rPattempt lower_optionsrrrrOs@       z Prompt.promptcCsdS)z Does not do anything. Is intended to be used in a sub-class to handle user input after it is prompted. Nr)rPrrrrk szPrompt.process_inputrS)rN)r@rArBrCrIr rDrrLrVrXrYrdrOrk __classcell__rrrQrr0s&W5  )r0)T)TFF)TF) rCr_rWr subprocessrrmultiprocessingr threadingrtypingrr r r r r core.metarcore.excrrDrGrHrrrr,r+r*r0rrrrs       2  ( #  . 5 4