
    K$                         S r SSKJr  SSKJr  SSKJr  SSKrSSKJr  SSKJr  SSK	Jr
  SSKJr  SS	KJr  SSKr\R                  " S
5      rSrS rS rS rS r SS jrS rg)aq  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                     U c  0 $ [        U 5      u  p#[        U5      n[        [        UR	                  5       5      5        0 n[        XSUU5        [        R                  " S[        R                  " U5      -   5        U$ )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   `   sp    & _I.w7()(3.n11345.^*,(($s}}^'DDE	    c                     U R                  S5      nUS:  d  US:X  a-  U R                  S5      (       a  [        R                  " SS5      eU SU XS-   S 4$ )	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      se    

"
"3
'%
QY5A:"4"?"?"H"H

(
(<> >	FU	#%7a%A	AAr   c           	      :   0 n[         R                  " U 5       H~  nUc  [        R                  " S5        M  [	        U[
        5      (       a  UR                  U5        MF  [        R                  " SR                  U [        R                  " U5      5      5      e   U$ )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                     U  HB  n[         R                  U5      (       a  M  [        R                  " SR	                  U5      5      e   g )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                    Uc  [        5       nO-X;   a(  [        R                  " [        SR	                  US95      eX;  a#  [
        R                  " SR	                  US95      eX!   nU(       d&  [        R                  " SR	                  U5      5        gU H  n[        R                  " U5      nU[        :X  a  M%  Xs;  a  [        R                  " U5      eXp;   a*  [        R                  " SR	                  X`U   5      5        Mo  [        R                  " XuU   5      X'   M     UR                  U5        [        U;   a9  [        R                  " [        U[           5      nU H  n	[!        X	UX45        M     gg)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      sa   & !5)

(
(6==
=KM M %

.
.?	*	  ()	KK077
CD
h

*
*8
4C
h
#**844
	hh
N6(3/02 )<<
"$n   :&"55h6?6IKO)^^.F * r   c                 >    [        U 5      u  p4 [        [	        U5      R                  5       5      nU Vs/ s H"  ofR                  U5      (       d  M  US-   U-   PM$     sn$ ! [        R                   a    / s $ f = f! [        R                   a    / s $ f = fs  snf )a<  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:H(2779:F )/	M1,,|2L8c>A	MM 
	'	' I 
		 I	Ms-   A" "A> BB"A;:A;>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      sj    ;z '  ' 	 = ; E # $ 
 ZZ 67 BB: :F|Nr   