o
    1\                  
   @   s  d Z ddlmZ ddlmZ ddlmZ ddlZddlmZ ddlZddl	Z	ddl
mZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlZdd ZG dd dejZG dd dejZG dd dejZG dd dejZdd Zd\ddZdZdd Z dd Z!G d d! d!eZ"G d"d# d#eZ#G d$d% d%ej$Z$G d&d' d'eZ%G d(d) d)eZ&G d*d+ d+eZ'G d,d- d-eZ(G d.d/ d/eZ)G d0d1 d1eZ*G d2d3 d3eZ+i d4ej,d5e$d6ej,d7ej,d8ej,d9ej-d:d;d< d=d>d< d?ej,d@ej,dAej,dBej,dCej,dDej,dEej-dFej,dGej,ej,ej,ej,ej,ej,ej,ej,ej,dHZ.dIdJ Z/e0h dKZ1dLdM Z2dNdO Z3d]dPdQZ4G dRdS dSe5Z6dTdU Z7dVdW Z8dXdY Z9dZd[ Z:dS )^a&  Exceptions that can be thrown by calliope tools.

The exceptions in this file, and those that extend them, can be thrown by
the Run() function in calliope tools without worrying about stack traces
littering the screen in CLI mode. In interpreter mode, they are not caught
from within calliope.
    )absolute_import)division)unicode_literalsNwraps)
exceptions)log)
properties)console_attr)console_attr_osc                 G   sN   t  \}}}|rtj}|d || |r| | S |r#| |j S | dS )aV  Creates a new error based on the current exception being handled.

  If no exception is being handled, a new error with the given args
  is created.  If there is a current exception, the original exception is
  first logged (to file only).  A new error is then created with the
  same args as the current one.

  Args:
    error: The new error to create.
    *args: The standard args taken by the constructor of Exception for the new
      exception that is created.  If None, the args from the exception currently
      being handled will be used.

  Returns:
    The generated error exception.
  zAHandling the source of a tool exception, original details follow.zAn unknown error has occurred)sysexc_infor   file_only_loggererror	exceptionargs)r   r   _current_exceptionfile_logger r   ?/tmp/google-cloud-sdk/lib/googlecloudsdk/calliope/exceptions.pyNewErrorFromCurrentException+   s   

r   c                   @   s   e Zd ZdZedd ZdS )ToolExceptionzToolException is for Run methods to throw for non-code-bug errors.

  Attributes:
    command_name: The dotted group and command name for the command that threw
      this exception. This value is set by calliope.
  c                  G   s   t tg| R  S N)r   r   )r   r   r   r   FromCurrentW      zToolException.FromCurrentN)__name__
__module____qualname____doc__staticmethodr   r   r   r   r   r   O   s    r   c                   @      e Zd ZdZdS )ExitCodeNoErrorzA special exception for exit codes without error messages.

  If this exception is raised, it's identical in behavior to returning from
  the command code, except the overall exit code will be different.
  Nr   r   r   r   r   r   r   r   r"   \       r"   c                           e Zd ZdZ fddZ  ZS )FailedSubCommandz:Exception capturing a subcommand which did sys.exit(code).c                    s&   t t| jdd|||d d S )Nz*Failed command: [{0}] with exit code [{1}] )	exit_code)superr&   __init__formatjoin)selfcmdcode	__class__r   r   r*   g   s   


zFailedSubCommand.__init__r   r   r   r   r*   __classcell__r   r   r0   r   r&   d       r&   c                       r%   )DryRunErrorz&Raised when a dry run request is made.c                    s   t    || _d S r   )r)   r*   request)r-   r6   r0   r   r   r*   s   s   

zDryRunError.__init__r2   r   r   r0   r   r5   p   r4   r5   c                    s    fdd}|S )a_  A decorator that re-raises as an error.

  If any of the error_types are raised in the decorated function, this decorator
  will re-raise as an error.

  Args:
    error: Exception, The new exception to raise.
    *error_types: [Exception], A list of exception types that this decorator
      will watch for.

  Returns:
    The decorated function.
  c                    s   t   fdd}|S )z#Wrapper function for the decorator.c                     s4   z| i |W S  y   t t  Y d S w r   )core_exceptionsreraiser   )r   kwargs)r   error_typesfuncr   r   TryFunc   s
   z2RaiseErrorInsteadOf.<locals>.Wrap.<locals>.TryFuncr   )r;   r<   r   r:   )r;   r   Wrap   s   z!RaiseErrorInsteadOf.<locals>.Wrapr   )r   r:   r>   r   r=   r   RaiseErrorInsteadOfx   s   r?    c                 C   s~   t ||d krtd | S t | |kr| S ||kr)|| || t | d  } t | |kr1| S | d|t |  | } | S )a  Truncate string to line width, right aligning at align.

  Examples (assuming a screen width of 10):

  >>> _TruncateToLineWidth('foo', 0)
  'foo'
  >>> # Align to the beginning. Should truncate the end.
  ... _TruncateToLineWidth('0123456789abcdef', 0)
  '0123456789'
  >>> _TruncateToLineWidth('0123456789abcdef', 0, fill='...')
  '0123456...'
  >>> # Align to the end. Should truncate the beginning.
  ... _TruncateToLineWidth('0123456789abcdef', 16)
  '6789abcdef'
  >>> _TruncateToLineWidth('0123456789abcdef', 16, fill='...')
  '...9abcdef'
  >>> # Align to the middle (note: the index is toward the end of the string,
  ... # because this function right-aligns to the given index).
  ... # Should truncate the begnining and end.
  ... _TruncateToLineWidth('0123456789abcdef', 12)
  '23456789ab'
  >>> _TruncateToLineWidth('0123456789abcdef', 12, fill='...')
  '...5678...'

  Args:
    string: string to truncate
    align: index to right-align to
    width: maximum length for the resulting string
    fill: if given, indicate truncation with this string. Must be shorter than
      terminal width / 2.

  Returns:
    str, the truncated string

  Raises:
    ValueError, if provided fill is too long for the terminal.
     z8Screen not wide enough to display correct error message.N)lenr   warning)stringalignwidthfillr   r   r   _TruncateToLineWidth   s   &
rH   z^ invalid characterc              
   C   s   t | tjr't| D ]\}}z|d W q
 ttfy$   | Y   S w dS t| D ]\}}z|d W q+ ttfyE   | Y   S w dS )zDReturns the index of the first non-ascii char in s, -1 if all ascii.ascii)
isinstancesix	text_type	enumerateencodeAttributeErrorUnicodeErrordecode)sicbr   r   r   _NonAsciiIndex   s   rW   c                 C   s   d}| D ]}t |}|dkr||7 } n|t|d 7 }qtdd| t }t|}ddd | D }t \}}d}	|ttt|	 k rNd||fS t|||||	d		 }
t|||}d|
|fS )
a)  Format a string that will mark the first non-ASCII character it contains.

  Example:

  >>> args = ['command.py', '--foo=\xce\x94']
  >>> _FormatNonAsciiMarkerString(args) == (
  ...     'command.py --foo=\u0394\n'
  ...     '                 ^ invalid character'
  ... )
  True

  Args:
    args: The arg list for the command executed

  Returns:
    unicode, a properly formatted string with two lines, the second of which
      indicates the non-ASCII character in the first.

  Raises:
    ValueError: if the given string is all ASCII characters
  r      z:The command line is composed entirely of ASCII characters.r'   c                 S   s   g | ]}t |qS r   )r
   SafeText).0argr   r   r   
<listcomp>      z/_FormatNonAsciiMarkerString.<locals>.<listcomp>z...
)rG   )
rW   rB   
ValueError_MARKERr,   r   GetTermSizerH   ljustrstrip)r   posr[   first_non_ascii_indexmarker_stringrE   args_stringrF   r   rG   formatted_args_stringformatted_marker_stringr   r   r   _FormatNonAsciiMarkerString   s0   rj   c                       r%   )InvalidCharacterInArgExceptionz>InvalidCharacterInArgException is for non-ASCII CLI arguments.c                    sf   || _ tj|d }|dr|d d }|g|dd   }tt| dt	
| j t| d S )Nr   z.pyrX   zcFailed to read command line argument [{0}] because it does not appear to be valid 7-bit ASCII.

{1})invalid_argospathbasenameendswithr)   rk   r*   r+   r
   rY   rj   )r-   r   rm   r.   r0   r   r   r*   1  s   


z'InvalidCharacterInArgException.__init__r2   r   r   r0   r   rk   .  r4   rk   c                       r%   )BadArgumentExceptionz:For arguments that are wrong for reason hard to summarize.c                    "   t t| d|| || _d S NzInvalid value for [{0}]: {1})r)   rr   r*   r+   argument_name)r-   ru   messager0   r   r   r*   E     


zBadArgumentException.__init__r2   r   r   r0   r   rr   B  r4   rr   c                   @   r!   )HttpExceptionzHttpException is raised whenever the Http response status code != 200.

  See api_lib.util.exceptions.HttpException for full documentation.
  Nr#   r   r   r   r   rx   M  r$   rx   c                       r%   )InvalidArgumentExceptionz4InvalidArgumentException is for malformed arguments.c                    rs   rt   )r)   ry   r*   r+   parameter_namer-   rz   rv   r0   r   r   r*   W  rw   z!InvalidArgumentException.__init__r2   r   r   r0   r   ry   T  r4   ry   c                       r%   )ConflictingArgumentsExceptionzDConflictingArgumentsException arguments that are mutually exclusive.c                    s$   t t| dd|  || _d S )Nz&arguments not allowed simultaneously: , )r)   r|   r*   r,   parameter_names)r-   r~   r0   r   r   r*   a  s   

z&ConflictingArgumentsException.__init__r2   r   r   r0   r   r|   ^  r4   r|   c                       r%   )UnknownArgumentExceptionzAUnknownArgumentException is for arguments with unexpected values.c                    rs   )NzUnknown value for [{0}]: {1})r)   r   r*   r+   rz   r{   r0   r   r   r*   k  rw   z!UnknownArgumentException.__init__r2   r   r   r0   r   r   h  r4   r   c                       r%   )RequiredArgumentExceptionzKAn exception for when a usually optional argument is required in this case.c                    rs   )Nz$Missing required argument [{0}]: {1})r)   r   r*   r+   rz   r{   r0   r   r   r*   u  rw   z"RequiredArgumentException.__init__r2   r   r   r0   r   r   r  r4   r   c                       r%   )OneOfArgumentsRequiredExceptionzDAn exception for when one of usually optional arguments is required.c                    s(   t t| dd|| || _d S )Nz'One of arguments [{0}] is required: {1}r}   )r)   r   r*   r+   r,   
parameters)r-   r   rv   r0   r   r   r*     s   


z(OneOfArgumentsRequiredException.__init__r2   r   r   r0   r   r   |  r4   r   c                       s"   e Zd ZdZd fdd	Z  ZS )MinimumArgumentExceptionz;An exception for when one of several arguments is required.Nc                    s@   |rd |}nd}tt| d ddd |D | d S )Nz: {}r@   z!One of [{0}] must be supplied{1}.r}   c                 S   s   g | ]}d  |qS )z{0})r+   )rZ   pr   r   r   r\     r]   z5MinimumArgumentException.__init__.<locals>.<listcomp>)r+   r)   r   r*   r,   )r-   r~   rv   r0   r   r   r*     s   
z!MinimumArgumentException.__init__r   r2   r   r   r0   r   r     s    r   c                   @   r!   )BadFileExceptionz;BadFileException is for problems reading or writing a file.Nr#   r   r   r   r   r     r$   r   z.apitools.base.py.exceptions.BadStatusCodeErrorz%apitools.base.py.exceptions.HttpErrorz(apitools.base.py.exceptions.RequestErrorz+apitools.base.py.exceptions.RetryAfterErrorz.apitools.base.py.exceptions.TransferRetryErrorz&google.auth.exceptions.GoogleAuthErrorz3googlecloudsdk.calliope.parser_errors.ArgumentErrorc                 C      d S r   r   xr   r   r   <lambda>      r   z$googlecloudsdk.core.util.files.Errorc                 C   r   r   r   r   r   r   r   r     r   zhttplib.ResponseNotReadyzhttplib.BadStatusLinezhttplib.IncompleteReadzhttp.client.ResponseNotReadyzhttp.client.BadStatusLinezhttp.client.IncompleteReadz+oauth2client.client.AccessTokenRefreshErrorzssl.SSLErrorzsocket.error)zsocket.timeoutzurllib3.exceptions.PoolErrorz urllib3.exceptions.ProtocolErrorzurllib3.exceptions.SSLErrorzurllib3.exceptions.TimeoutErrorzbuiltins.ConnectionAbortedErrorzbuiltins.ConnectionRefusedErrorzbuiltins.ConnectionResetErrorc                 C   s   | j d | j S )zFReturns the exception name used as index into _KNOWN_ERRORS from type..)r   r   )clsr   r   r   _GetExceptionName  r   r   >!   ECOMMEPROTOEBADMSGEISCONNENOBUFSEREMCHGEMSGSIZEENETDOWNENOTCONNENOTSOCKENOTUNIQ	EHOSTDOWN	EMULTIHOP	ENETRESET	EREMOTEIO	ESHUTDOWN	ETIMEDOUT
EADDRINUSE
ECONNRESET
EOPNOTSUPP
EPROTOTYPEENETUNREACHENOPROTOOPTEAFNOSUPPORTECONNABORTEDECONNREFUSEDEDESTADDRREQEHOSTUNREACHEPFNOSUPPORTETOOMANYREFSEADDRNOTAVAILEPROTONOSUPPORTESOCKTNOSUPPORTc                    s   t  fddtD S )z0Returns True if exc is a socket error exception.c                 3   s"    | ]}t t|d  jkV  qdS )rJ   N)getattrerrno)rZ   nameexcr   r   	<genexpr>  s    
z!_IsSocketError.<locals>.<genexpr>)any_SOCKET_ERRNO_NAMESr   r   r   r   _IsSocketError  s   r   c                    s   t | tr	| dfS t | tjr| dfS d}t| g}tg  |rX|d} | t|}|dkr:t	| r:tj
}nt|}|rBn fdd|jD }|dd |D  |s |s\d	S || }|rf|dfS | dfS )
a  Convert the given exception into an alternate type if it is known.

  Searches backwards through Exception type hierarchy until it finds a match.

  Args:
    exc: Exception, the exception to convert.

  Returns:
    (exception, bool), exception is None if this is not a known type, otherwise
    a new exception that should be logged. The boolean is True if the error
    should be printed, or False to just exit without printing.
  FTNr   zbuiltins.OSErrorc                    s"   g | ]}| vrt |tr|qS r   )
issubclass	Exception)rZ   bc	processedr   r   r\   (  s
    z%ConvertKnownError.<locals>.<listcomp>c                 S   s   g | ]}|t ur|qS r   )r   )rZ   baser   r   r   r\   -  s    )NT)rK   r"   r7   Errortypesetpopaddr   r   NetworkIssueError_KNOWN_ERRORSget	__bases__extend)r   	known_errclassesr   r   basesnew_excr   r   r   ConvertKnownError  s2   





r   c                 C   sp   t | \}}|r%t||| |r|  tjjj rt|  t	| dS t
jt| t d t|  dS )a  Handles an error that occurs during command execution.

  It calls ConvertKnownError to convert exceptions to known types before
  processing. If it is a known type, it is printed nicely as as error. If not,
  it is raised as a crash.

  Args:
    exc: Exception, The original exception that occurred.
    command_path: str, The name of the command that failed (for error
      reporting).
    known_error_handler: f(): A function to report the current exception as a
      known error.
  r   N)r   _LogKnownErrorr	   VALUEScoreprint_handled_tracebacksGetBoolr7   r8   _Exitr   debugr
   rY   r   r   )r   command_pathknown_error_handler	known_excprint_errorr   r   r   HandleError8  s   
r   c                   @   s    e Zd ZdZdd Zdd ZdS )HttpExceptionAdditionalHelpa  Additional help text generator when specific HttpException was raised.

  Attributes:
     known_exc: googlecloudsdk.api_lib.util.exceptions.HttpException, The
       exception to handle.
    error_msg_signature: string, The signature message to determine the nature
      of the error.
    additional_help: string, The additional help to print if error_msg_signature
      appears in the exception error message.
  c                 C   s   || _ || _|| _d S r   )r   error_msg_signatureadditional_help)r-   r   r   r   r   r   r   r*   a  s   
z$HttpExceptionAdditionalHelp.__init__c                 C   s&   | j | jjv rd|t| jS |S )z-Appends the additional help to the given msg.z{0}

{1})r   r   rv   r+   r
   rY   r   )r-   msgr   r   r   Extendf  s
   z"HttpExceptionAdditionalHelp.ExtendN)r   r   r   r   r*   r   r   r   r   r   r   U  s    r   c                 C   s    d}d tjjj}t| ||S )zAdditional help when missing the 'serviceusage.services.use' permission.

  Args:
    known_exc: googlecloudsdk.api_lib.util.exceptions.HttpException, The
      exception to handle.

  Returns:
    A HttpExceptionAdditionalHelp object.
  ziGrant the caller the Owner or Editor role, or a custom role with the serviceusage.services.use permissionzIf you want to invoke the command from a project different from the target resource project, use `--billing-project` or `{}` property.)r+   r	   r   billingquota_projectr   r   error_message_signaturehelp_messager   r   r   /_BuildMissingServiceUsePermissionAdditionalHelpp  s   r   c                 C   s   d}d}t | ||S )ab  Additional help when missing authentication scopes.

  When authenticated using user credentials and service account credentials
  locally, the requested scopes (googlecloudsdk.core.config.CLOUDSDK_SCOPES)
  should be enough to run gcloud commands. If users run gcloud from a GCE VM,
  the scopes of the default service account is customizable during vm creation.
  It is possible that the default service account does not have required scopes.

  Args:
    known_exc: googlecloudsdk.api_lib.util.exceptions.HttpException, The
      exception to handle.

  Returns:
    A HttpExceptionAdditionalHelp object.
  z.Request had insufficient authentication scopesa  If you are in a compute engine VM, it is likely that the specified scopes during VM creation are not enough to run this command.
See https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam for more information about access scopes.
See https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#changeserviceaccountandscopes for how to update access scopes of the VM.)r   r   r   r   r   %_BuildMissingAuthScopesAdditionalHelp  s   r   c                 C   sp   d t|t| }t| tjr$t| }t| }||}||}t	j
|t d |r6t	| dS dS )z.Logs the error message of the known exception.z	({0}) {1}r   N)r+   r
   rY   rK   api_exceptionsrx   r   r   r   r   r   r   r   r   )r   r   r   r   service_use_helpauth_scopes_helpr   r   r   r     s   

r   c                 C   s   t t| dd dS )zFThis method exists so we can mock this out during testing to not exit.r(   rX   N)r   exitr   r   r   r   r   r     s   r   )r@   r   );r   
__future__r   r   r   r   	functoolsr   rn   r   googlecloudsdk.api_lib.utilr   r   googlecloudsdk.corer7   r   r	   googlecloudsdk.core.consoler
   r   googlecloudsdk.core.credentialscreds_exceptionsrL   r   r   r   r"   r&   r5   r?   rH   r`   rW   rj   rk   rr   rx   ry   r|   r   r   r   r   r   r   TokenRefreshErrorr   r   	frozensetr   r   r   r   objectr   r   r   r   r   r   r   r   r   <module>   s   $
:I



	 +%
1