
    -                         d Z ddlmZ ddlmZ ddlmZ ddlZddlZddl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Zd
ZdZdZdZ ed      ez
  ZdZdZdZdZd Zd Zd Zd Zd Z  G d de!      Z"ddZ#y)zFUtilities for handling YAML schemas for gcloud export/import commands.    )absolute_import)division)unicode_literalsN)log)resource_projector)yaml_printer)filesz6A gcloud export/import command YAML validation schema.P   (      zdescription: z<YAML-WORKAROUND/>z	Optional.zOutput only.z	Required.c                    t         | t        z  z
  }t        j                  |t	        t
        |            }t        |      dk7  rdj                  |      S |d   }|t        |      t        z   z
  }|dk  r|dz   |dz  z   t        z   S |S )a;  Returns description: |- text wrapped so it won't exceed _WIDTH at depth.

  The YAML representer doesn't seem to take the length of the current tag
  into account when deciding whether to inline strings or use |-. In this case
  the tag is always "description: ". This function detects when YAML would fail
  and adds temporary marker lines to produce the desired output. The marker
  lines are removed prior to final output.

  Args:
    depth: The nested dict depth.
    text: The text string to wrap.

  Returns:
    Text wrapped so it won't exceed _WIDTH at depth.
     
r    )
_WIDTH_INDENTtextwrapwrapmax_MINWRAPlenjoin_DESCRIPTION_INDENT_YAML_WORKAROUND)depthtextwidthlineslinenudges         2lib/googlecloudsdk/command_lib/util/apis/export.py_WrapDescriptionr"   1   s      EGO
$%
--c(E2
3%Z1_99U	q$
3t922
3%
QY $;$'777	+    c                    t        j                  |       j                         }t        j                  d|      ryt        j                  d|      ryt        j                  d|      ry|dk(  ry|dk(  ry|dk(  ry	|d
k(  ry|S )z6Returns the JSON schema normalized type name for name.z.?int64integerz.?int32z^int\d*$floatnumberdoubleboolbooleanbytesstring)six	text_typelowerrematch)namess     r!   _NormalizeTypeNamer4   O   sy    	mmD!!XXj!XXj!XXk1'\(]&['\	
(r#   c                     | j                  di       j                  di       j                  di       j                  di       j                  dd      }|dk(  S )a?  Returns whether the field represents a google.protobuf.Struct message.

  google.protobuf.Struct is the following message:
    message Struct {
      // Unordered map of dynamically typed values.
      map<string, Value> fields = 1;
    }

  In apitools, this corresponds to a message with an additionalProperties
  field containing a list of AdditionalProperty messages each of which holds a
  key/value pair, where the value is a extra_types.JsonValue message.

  Args:
    field: A message spec field dict.
  Returns:
    True iff the field is a google.protobuf.Struct.
  fieldsadditionalPropertiesvaluetype 	JsonValue)get)fieldmaybe_map_value_types     r!   _IsProtobufStructFieldr?   c   sc    $ C
 "&&)c'C2"sb "	  
	,,r#   c                     g }t        j                  |       D ]7  \  }}|d   }|dk7  s|j                  t              s'|j	                  |       9 |S )zReturns the list of required field names in fields.

  Args:
    fields: A message spec fields dict.

  Returns:
    The list of required field names in fields.
  descriptionr7   )r-   	iteritems
startswith	_REQUIREDappend)r6   requiredr2   r8   rA   s        r!   _GetRequiredFieldsrG   ~   sU     (]]6*kdE&K %%+*@*@*Kood + 
/r#   c                 <    t        |      }|rt        |      | d<   yy)zAdds required fields to spec.rF   N)rG   sorted)specr6   rF   s      r!   _AddRequiredFieldsrK      s#    '(h'D r#   c                   6    e Zd ZdZd	dZd Zd Zd Zd Zd Z	y)
ExportSchemasGeneratorz>Recursively generates export JSON schemas for nested messages.Nc                 >    || _         || _        t               | _        y N)_api
_directoryset
_generated)selfapi	directorys      r!   __init__zExportSchemasGenerator.__init__   s    DIDOeDOr#   c                     |dz   S )z4Returns the schema file name given the message name.z.yaml )rT   message_names     r!   _GetSchemaFileNamez)ExportSchemasGenerator._GetSchemaFileName   s    '!!r#   c                     | j                  |      }| j                  r*t        j                  j	                  | j                  |      }|S )z9Returns the schema file path name given the message name.)r[   rQ   ospathr   )rT   rZ   	file_paths      r!   _GetSchemaFilePathz)ExportSchemasGenerator._GetSchemaFilePath   s7    ''5I'',,t	:ir#   c                    t        j                         }|j                  d       t        j                  dt        j                         |      j                  |       t        j                  dj                  t              d|j                               }| j                  |      }t        j                  dj                  |             t!        j"                  |      5 }|j                  |       ddd       y# 1 sw Y   yxY w)z;Writes the schema in spec to the _GetSchemaFilePath() file.z4$schema: "http://json-schema.org/draft-06/schema#"

yaml)r2   	projectoroutz
 *{}
r   zGenerating JSON schema [{}].N)ioStringIOwriter   YamlPrinterr   IdentityProjectorPrintr0   subformatr   getvaluer`   r   infor	   
FileWriter)rT   rZ   rJ   tmpcontentr_   ws          r!   _WriteSchemaz#ExportSchemasGenerator._WriteSchema   s    
++-CIIFG$668 tffZ&&'78$OG''5IHH+229=>			)	$ggg 
%	$	$s   !C<<Dc           	         |dz  }t        t        j                  |            D ]H  \  }}|d   j                         }|j	                  t
              r!|t        t
              d j                         }n5|j	                  t              r |t        t              d j                         }|j	                  t              rt        j                         }|||<   t        ||      |d<   |j                  d      r6d|d<   t        j                  |j                  di             }	|	|d<   |	}|dz  }t        |j                  d      t              }
|j                  dd      }|j                  d	i       }|
ru|d
k(  r6||= t        j                         }| j                  ||||       |s|||<   t!        |      rd|d<   | j#                  |      |d<   | j%                  ||       || j&                  v r| j#                  |      |d<   t)        |      }|dk(  rL|j                  d      }d|d<   t        t        j                  |      D cg c]  \  }}|	 c}}      |d<   D||d<   K yc c}}w )a  Adds message fields to the YAML spec.

    Args:
      depth: The nested dict depth.
      parent: The parent spec (nested ordered dict to add fields to) of spec.
      spec: The nested ordered dict to add fields to.
      fields: A message spec fields dict to add to spec.
    r   rA   Nrepeatedarrayr9   itemsr*   r6   r7   objectz$refenumchoicesr,   )rI   r-   rB   striprC   	_OPTIONALr   rD   _OUTPUT_ONLYcollectionsOrderedDictr"   r<   
isinstancestr
_AddFieldsr?   r[   GeneraterS   r4   )rT   r   parentrJ   r6   r2   r8   rA   drw   is_message_field	type_name	subfields
propertiesry   n_s                    r!   r   z!ExportSchemasGenerator._AddFields   s>    
QJEcmmF34e-(..0k					*!#i./288:!!),!#i./288:				-

!
!
#ad4j)%=a	:	&	''		'2(>?'


 $EIIf$5s;))FI.i))Hb)i	))4j"..0*
//%J	
:%F4L#E* !F) --i8!F)
--	9
-'--i8!F)(3)& 99Y'D AfIcmmD.AB.Ada.ABCAfI!AfIm 5h  Cs   I1c                    || j                   v ry| j                   j                  |       t        j                         }dj	                  | j
                  j                  | j
                  j                  |      |d<   t        |d<   d|d<   t        ||       d|d<   t        j                         }||d	<   dd
i}t        j                         }||d<   d|d<   d|d<   d|d<   t        j                         }||d	<   t        j                  |      |d<   t        j                  |      |d<   t        j                  |      |d<   t        j                  |      |d<   t        j                  |      |d<   t        j                         }||d<   d|d<   d|d<   ||d<   | j                  d|||       | j                  ||       y)aq  Recursively generates export/import YAML schemas for message_spec.

    The message and nested messages are generated in separate schema files in
    the destination directory. Pre-existing files are silently overwritten.

    Args:
      message_name: The API message name for message_spec.
      message_spec: An arg_utils.GetRecursiveMessageSpec() message spec.
    Nz{} {} {} export schematitlerA   rx   r9   Fr7   r   r,   COMMENTz-User specified info ignored by gcloud import.ztemplate-idregiondateversionUNKNOWNrv   z+Unknown API fields that cannot be imported.rw   r   )rS   addr~   r   rl   rP   r2   r   _SPEC_DESCRIPTIONrK   r   rs   )	rT   rZ   message_specrJ   r   type_stringcommentcomment_propertiesunknowns	            r!   r   zExportSchemasGenerator.Generate   s    t&OO% ""$D,33				))<9DM+DDLt\*#(D	 ((*J#D8$K %%'G#JyGFOLGM&+G"#$002.GL(3(?(?(L}%#.#:#:;#Gx (3(?(?(L}%!,!8!8!Ev$/$;$;K$Hy! %%'G#JyGFOJGM"GGOOAtZ6lD)r#   rO   )
__name__
__module____qualname____doc__rW   r[   r`   rs   r   r   rY   r#   r!   rM   rM      s%    F
"@"D6*r#   rM   c                 <    t        | |      j                  ||       y)a  Recursively generates export/import YAML schemas for message_spec in api.

  The message and nested messages are generated in separate schema files in the
  current directory. Pre-existing files are silently overwritten.

  Args:
    api: An API registry object.
    message_name: The API message name for message_spec.
    message_spec: An arg_utils.GetRecursiveMessageSpec() message spec.
    directory: The path name of the directory to place the generated schemas,
      None for the current directory.
  N)rM   r   )rU   rZ   r   rV   s       r!   GenerateExportSchemasr   8  s     i(11,Mr#   rO   )$r   
__future__r   r   r   r~   re   r]   r0   r   googlecloudsdk.corer   googlecloudsdk.core.resourcer   r   googlecloudsdk.core.utilr	   r-   r   r   r   r   r   r   r   r|   r}   rD   r"   r4   r?   rG   rK   rx   rM   r   rY   r#   r!   <module>r      s     M &  '  	 	 	  # ; 5 * 
 M 	
/*W4 ' 		<(-6.(Y*V Y*xNr#   