
    K$                         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mZ ddl	mZ
 ddlmZ dd	lmZ ddlZ ej                  d
      ZdZd Zd Zd Zd Z	 ddZd Zy)a  A library to load and validate test arguments from a YAML argument file.

  The optional, positional ARGSPEC argument on the command line is used to
  specify an ARG_FILE:ARG_GROUP_NAME pair, where ARG_FILE is the path to the
  YAML-format argument file, and ARG_GROUP_NAME is the name of the arg group
  to load and parse.

  The basic format of a YAML argument file is:

  arg-group-1:
    arg1: value1
    arg2: value2

  arg-group-2:
    arg3: value3
    ...

  A special 'include: [<group-list>]' syntax allows composition/merging of
  arg-groups (see example below). Included groups can include: other groups as
  well, with unlimited nesting within one YAML file.

  Precedence of arguments:
    Args appearing on the command line will override any arg specified within
    an argument file.
    Args which are merged into a group using the 'include:' keyword have lower
    precedence than an arg already defined in that group.

  Example of a YAML argument file for use with 'gcloud test run ...' commands:

  memegen-robo-args:
    type: robo
    app: path/to/memegen.apk
    robo-script: crawl_init.json
    include: [common-args, matrix-quick]
    timeout: 5m

  notepad-instr-args:
    type: instrumentation
    app: path/to/notepad.apk
    test: path/to/notepad-test.apk
    include: [common-args, matrix-large]

  common-args:
    results-bucket: gs://my-results-bucket
    timeout: 600

  matrix-quick:
    device-ids: [Nexus5, Nexus6]
    os-version-ids: 21
    locales: en
    orientation: landscape

  matrix-large:
    device-ids: [Nexus5, Nexus6, Nexus7, Nexus9, Nexus10]
    os-version-ids: [18, 19, 21]
    include: all-supported-locales

  all-supported-locales:
    locales: [de, en_US, en_GB, es, fr, it, ru, zh]
    )absolute_import)division)unicode_literalsN)arg_validate)
exceptions)log)yamlz^[a-zA-Z0-9._\-]+\Zincludec                     | i S t        |       \  }}t        |      }t        t        |j	                                      i }t        ||||       t        j                  dt        j                  |      z          |S )a.  Loads a group of test args from an optional user-supplied arg file.

  Args:
    argspec: string containing an ARG_FILE:ARG_GROUP_NAME pair, where ARG_FILE
      is the path to a file containing groups of test arguments in yaml format,
      and ARG_GROUP_NAME is a yaml object name of a group of arg:value pairs.
    all_test_args_set: a set of strings for every possible gcloud-test argument
      name regardless of test type. Used for validation.

  Returns:
    A {str:str} dict created from the file which maps arg names to arg values.

  Raises:
    BadFileException: the YAML parser encountered an I/O error or syntax error
      while reading the arg-file.
    InvalidTestArgError: an argument name was not a valid gcloud test arg.
    InvalidArgException: an argument has an invalid value or no value.
  zArgs loaded from file: )
_SplitArgFileAndGroup_ReadArgGroupsFromFile_ValidateArgGroupNameslistkeys_MergeArgGroupIntoArgsr   infosix	text_type)argspecall_test_args_setarg_file
group_nameall_arg_groupsargs_from_files         4lib/googlecloudsdk/api_lib/firebase/test/arg_file.pyGetArgsFromArgFiler   `   st    & _I.w7(J)(3.n11345.^*,(($s}}^'DDE	    c                     | j                  d      }|dk  s|dk(  r'| j                  d      rt        j                  dd      | d| | |dz   d fS )	zBParses an ARGSPEC and returns the arg filename and arg group name.:r      zgs://zarg-specz&Format must be ARG_FILE:ARG_GROUP_NAMEN   )rfind
startswithr   InvalidArgException)file_and_group_strindexs     r   r   r      sd    

"
"3
'%
QY5A:"4"?"?"H

(
(<> >	FU	#%7a%A	AAr   c           	          i }t        j                  |       D ]s  }|t        j                  d       t	        |t
              r|j                  |       =t        j                  dj                  | t        j                  |                   |S )a	  Collects all the arg groups defined in the yaml file into a dictionary.

  Each dictionary key is an arg-group name whose corresponding value is a nested
  dictionary containing arg-name: arg-value pairs defined in that group.

  Args:
    arg_file: str, the name of the YAML argument file to open and parse.

  Returns:
    A dict containing all arg-groups found in the arg_file.

  Raises:
    yaml.Error: If the YAML file could not be read or parsed.
    BadFileException: If the contents of the file are not valid.
  zIgnoring empty yaml document.zCFailed to parse YAML file [{}]: [{}] is not a valid argument group.)r	   load_all_pathr   warning
isinstancedictupdatecalliope_exceptionsBadFileExceptionformatr   r   )r   
all_groupsds      r   r   r      s}      *h'ay	kk12	At	006(CMM!$457 7 ( 
r   c                     | D ];  }t         j                  |      rt        j                  dj	                  |             y )NzBInvalid argument group name [{0}]. Names may only use a-zA-Z0-9._-)_ARG_GROUP_PATTERNmatchr-   r.   r/   )group_namesr   s     r   r   r      s:    j##J/00
N6*   r   c                    |t               }n.||v r*t        j                  t        dj	                  |            ||vr%t        j                  dj	                  |            ||   }|s%t        j                  dj	                  |             y|D ]  }t        j                  |      }|t        k(  r"||vrt        j                  |      || v r)t        j                  dj	                  || |                ht        j                  |||         | |<    |j                  |       t        |v r8t        j                  t        |t                 }|D ]  }	t!        | |	|||        yy)a  Merges args from an arg group into the given args_from_file dictionary.

  Args:
    args_from_file: dict of arg:value pairs already loaded from the arg-file.
    group_name: str, the name of the arg-group to merge into args_from_file.
    all_arg_groups: dict containing all arg-groups loaded from the arg-file.
    all_test_args_set: set of str, all possible test arg names.
    already_included_set: set of str, all group names which were already
      included. Used to detect 'include:' cycles.

  Raises:
    BadFileException: an undefined arg-group name was encountered.
    InvalidArgException: a valid argument name has an invalid value, or
      use of include: led to cyclic references.
    InvalidTestArgError: an undefined argument name was encountered.
  Nz,Detected cyclic reference to arg group [{g}])gz5Could not find argument group [{g}] in argument file.zArgument group [{0}] is empty.zBSkipping include: of arg [{0}] because it already had value [{1}].)setr   r$   _INCLUDEr/   r-   r.   r   r)   r   InternalArgNameFromInvalidTestArgErrorr   ValidateArgFromFileaddValidateStringListr   )
r   r   r   r   already_included_set	arg_grouparg_nameargincluded_groupsincluded_groups
             r   r   r      sx   & !5))

(
(6==
=KM M ~%

.
.?	*	  Z()	KK077
CD
h

*
*8
4C
h
##**844
n	hh
N6(N3/02 )<<
y"$nS   :&"55h6?6IKO)^^^.0DF * r   c                 ,   	 t        |       \  }}	 t        t	        |      j                               }|D cg c]  }|j                  |      s|dz   |z    c}S # t        j                  $ r g cY S w xY w# t        j                  $ r g cY S w xY wc c}w )aR  Tab-completion function for ARGSPECs in the format ARG_FILE:ARG_GROUP.

  If the ARG_FILE exists, parse it on-the-fly to get the list of every ARG_GROUP
  it contains. If the ARG_FILE does not exist or the ARGSPEC does not yet
  contain a colon, then fall back to standard shell filename completion by
  returning an empty list.

  Args:
    prefix: the partial ARGSPEC string typed by the user so far.
    parsed_args: the argparse.Namespace for all args parsed so far.
    **kwargs: keyword args, not used.

  Returns:
    The list of all ARG_FILE:ARG_GROUP strings which match the prefix.
  r   )	r   r   r$   r   r   r   r	   FileLoadErrorr#   )prefixparsed_argskwargsr   group_prefixgroupsr7   s          r   ArgSpecCompleterrL      s     26:Hl(2779:F )/	M1!,,|2L8c>A	MM 
	'	' I 
		 I	Ms-   A "A6 B
BA32A36BB)N)__doc__
__future__r   r   r   re$googlecloudsdk.api_lib.firebase.testr   r   googlecloudsdk.callioper-   googlecloudsdk.corer   r	   r   compiler3   r9   r   r   r   r   r   rL    r   r   <module>rU      sl    ;z '  ' 	 = ; E # $ 
  RZZ 67 BB: :F|Nr   