
    8                        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mZ  e	h d      Z
 G d d	ej                        Z G d
 dej                        Z G d dej                        Z G d dej                        Zd Zd Zy)a  This module provides argparse integration with absl.flags.

argparse_flags.ArgumentParser is a drop-in replacement for
argparse.ArgumentParser. It takes care of collecting and defining absl flags
in argparse.

Here is a simple example:

    # Assume the following absl.flags is defined in another module:
    #
    #     from absl import flags
    #     flags.DEFINE_string('echo', None, 'The echo message.')
    #
    parser = argparse_flags.ArgumentParser(
        description='A demo of absl.flags and argparse integration.')
    parser.add_argument('--header', help='Header message to print.')

    # The parser will also accept the absl flag `--echo`.
    # The `header` value is available as `args.header` just like a regular
    # argparse flag. The absl flag `--echo` continues to be available via
    # `absl.flags.FLAGS` if you want to access it.
    args = parser.parse_args()

    # Example usages:
    # ./program --echo='A message.' --header='A header'
    # ./program --header 'A header' --echo 'A message.'


Here is another example demonstrates subparsers:

    parser = argparse_flags.ArgumentParser(description='A subcommands demo.')
    parser.add_argument('--header', help='The header message to print.')

    subparsers = parser.add_subparsers(help='The command to execute.')

    roll_dice_parser = subparsers.add_parser(
        'roll_dice', help='Roll a dice.',
        # By default, absl flags can also be specified after the sub-command.
        # To only allow them before sub-command, pass
        # `inherited_absl_flags=None`.
        inherited_absl_flags=None)
    roll_dice_parser.add_argument('--num_faces', type=int, default=6)
    roll_dice_parser.set_defaults(command=roll_dice)

    shuffle_parser = subparsers.add_parser('shuffle', help='Shuffle inputs.')
    shuffle_parser.add_argument(
        'inputs', metavar='I', nargs='+', help='Inputs to shuffle.')
    shuffle_parser.set_defaults(command=shuffle)

    args = parser.parse_args(argv[1:])
    args.command(args)

    # Example usages:
    # ./program --echo='A message.' roll_dice --num_faces=6
    # ./program shuffle --echo='A message.' 1 2 3 4


There are several differences between absl.flags and argparse_flags:

1. Flags defined with absl.flags are parsed differently when using the
   argparse parser. Notably:

   1) absl.flags allows both single-dash and double-dash for any flag, and
      doesn't distinguish them; argparse_flags only allows double-dash for
      flag's regular name, and single-dash for flag's `short_name`.
   2) Boolean flags in absl.flags can be specified with `--bool`, `--nobool`,
      as well as `--bool=true/false` (though not recommended);
      in argparse_flags, it only allows `--bool`, `--nobool`.

2. Help related flag differences:
   1) absl.flags does not define help flags, absl.app does that; argparse_flags
      defines help flags unless passed with `add_help=False`.
   2) absl.app supports `--helpxml`; argparse_flags does not.
   3) argparse_flags supports `-h`; absl.app does not.
    )absolute_import)division)print_functionN)flags>   helphelpxmlundefokflagfilehelpfull	helpshortc                   :     e Zd ZdZ fdZd fd	Zd Zd Z xZS )ArgumentParserz:Custom ArgumentParser class to support special absl flags.c                 P   |j                  dd      }|dk7  rt        dj                  |            |j                  dt        j
                        | _        t        t        | &  di | | j                  rX| j                  ddt        j                  t        j                         | j                  dt        t        j                  d	       | j                  rL| j                  d
t        j                  t        j                         | j                  | j                         yy)a  Initializes ArgumentParser.

    Args:
      **kwargs: same as argparse.ArgumentParser, except:
          1. It also accepts `inherited_absl_flags`: the absl flags to inherit.
             The default is the global absl.flags.FLAGS instance. Pass None to
             ignore absl flags.
          2. The `prefix_chars` argument must be the default value '-'.

    Raises:
      ValueError: Raised when prefix_chars is not '-'.
    prefix_chars-zTargparse_flags.ArgumentParser only supports "-" as the prefix character, found "{}".inherited_absl_flagsz--helpshortr   )actiondefaultr   z
--helpfullzshow full help message and exitz	--undefok)r   r   N )get
ValueErrorformatpopr   FLAGS_inherited_absl_flagssuperr   __init__add_helpadd_argumentargparseSUPPRESS_HelpFullAction_define_absl_flags)selfkwargsr   	__class__s      4platform/bq/third_party/absl/flags/argparse_flags.pyr   zArgumentParser.__init__r   s    ::nc2Ls##)6,#79 9
 "(,BEKK!PD 
.$(262}} 
##(*;*;  = 
##*K  M !!

x00x7H7H  J
d889 "    c                 F   |t         j                  dd  }| j                  r| j                  j                  |d      }t	               }t        |d|      }t        t        | #  ||      \  }}||ur||_	        | j                  r]t        |d      rt        |j                  |      }|`	| j                  j                          	 | j                  j                          ||fS ||fS # t        j                  $ r'}| j!                  t#        |             Y d }~||fS d }~ww xY w)N   T)	force_gnur	   )sysargvr   read_flags_from_filesobjectgetattrr   r   parse_known_argsr	   hasattr_strip_undefok_argsmark_as_parsedvalidate_all_flagsr   IllegalFlagValueErrorerrorstr)r$   args	namespaceundefok_missingr	   er&   s         r'   r1   zArgumentParser.parse_known_args   s'   |XXab\d!! ''==
$ >  d hOiO<GNDBiOIt o%!i!! 
I	&"9#4#4d; 
  //1""557 d?9d? (( 

3q6d?s   C& &D 9DD c                     t        |j                  t        j                  d               }|D ]6  }|t        v r||   }||j
                  k(  s!||v}| j                  ||       8 y)zDefines flags from absl_flags.r   N)setget_key_flags_for_moduler,   r-   _BUILT_IN_FLAGSname_define_absl_flag)r$   
absl_flags	key_flagsrA   flag_instancesuppresss         r'   r#   z!ArgumentParser._define_absl_flags   sj    J77DEI		  &m 
##	# !	1}h7 r(   c                    |j                   }|j                  }d|z   g}|r|j                  dd|z          |rt        j                  }n|j
                  j                  dd      }|j                  rF|j                  d|z           | j                  |t        ||j                   j                         |d y | j                  |t        ||j                   j                         |d y)	z&Defines a flag from the flag_instance.--r   r   %z%%z--no)r   r   metavarrE   N)rA   
short_nameinsertr    r!   r   replacebooleanappendr   _BooleanFlagActionupper_FlagAction)r$   rE   rF   	flag_namerK   argument_nameshelptexts          r'   rB   z ArgumentParser._define_absl_flag   s    ""I))JY&'NAsZ/0""h ##++C6hFY./d"48$$**,%'
 d+H$$**,%'r(   )NN)	__name__
__module____qualname____doc__r   r1   r#   rB   __classcell__r&   s   @r'   r   r   o   s    B':R'R8 'r(   r   c                   B     e Zd ZdZej
                  f fd	ZddZ xZS )rR   z*Action class for Abseil non-boolean flags.c                 `    ~|| _         t        t        |   |t        j
                  ||       y)a  Initializes _FlagAction.

    Args:
      option_strings: See argparse.Action.
      dest: Ignored. The flag is always defined with dest=argparse.SUPPRESS.
      help: See argparse.Action.
      metavar: See argparse.Action.
      flag_instance: absl.flags.Flag, the absl flag instance.
      default: Ignored. The flag always uses dest=argparse.SUPPRESS so it
          doesn't affect the parsing result.
    )option_stringsdestr   rJ   N)_flag_instancer   rR   r   r    r!   )r$   r^   r_   r   rJ   rE   r   r&   s          r'   r   z_FlagAction.__init__   s6    & 	'D	+t%%	 & r(   c                 \    | j                   j                  |       d| j                   _        y)CSee https://docs.python.org/3/library/argparse.html#action-classes.FN)r`   parseusing_default_value)r$   parserr:   valuesoption_strings        r'   __call__z_FlagAction.__call__  s$    f%.3D+r(   N	rV   rW   rX   rY   r    r!   r   rh   rZ   r[   s   @r'   rR   rR      s    2 64r(   rR   c                   B     e Zd ZdZej
                  f fd	ZddZ xZS )rP   z&Action class for Abseil boolean flags.c                 (   ~~|| _         | j                   j                  g}| j                   j                  r%|j                  | j                   j                         t	        |      | _        t        t        | #  |t        j                  d||       y)a  Initializes _BooleanFlagAction.

    Args:
      option_strings: See argparse.Action.
      dest: Ignored. The flag is always defined with dest=argparse.SUPPRESS.
      help: See argparse.Action.
      metavar: See argparse.Action.
      flag_instance: absl.flags.Flag, the absl flag instance.
      default: Ignored. The flag always uses dest=argparse.SUPPRESS so it
          doesn't affect the parsing result.
    r   )r^   r_   nargsr   rJ   N)r`   rA   rK   rO   	frozenset_flag_namesr   rP   r   r    r!   )	r$   r^   r_   r   rJ   rE   r   
flag_namesr&   s	           r'   r   z_BooleanFlagAction.__init__  s    & 	g'D%%**+J%%++667 ,D	
d,% - r(   c                    t        |t              r|rt        d      |j                  d      r|dd }n|dd }|| j                  v r| j
                  j                  d       nK|j                  d      r|dd | j                  vrt        d|z         | j
                  j                  d	       d
| j
                  _        y)rb   zvalues must be an empty list.rH      Nr*   truenozinvalid option_string: falseF)
isinstancelistr   
startswithro   r`   rc   rd   )r$   re   r:   rf   rg   options         r'   rh   z_BooleanFlagAction.__call__5  s    fd#v677%QR fQR f!!!
't$qr
$:J:J(J2]BCC
(.3D+r(   ri   rj   r[   s   @r'   rP   rP     s    . @4r(   rP   c                   *     e Zd ZdZ fdZddZ xZS )r"   z!Action class for --helpfull flag.c                 r    ~~t         t        |   |t        j                  t        j                  d|       y)zInitializes _HelpFullAction.

    Args:
      option_strings: See argparse.Action.
      dest: Ignored. The flag is always defined with dest=argparse.SUPPRESS.
      default: Ignored.
      help: See argparse.Action.
    r   )r^   r_   r   rm   r   N)r   r"   r   r    r!   )r$   r^   r_   r   r   r&   s        r'   r   z_HelpFullAction.__init__I  s9     	g	/4)%!! * r(   c                    |j                          |j                  }|r^t        |j                               }t        j
                  d   }||v r|j                  |       t        |j                  |dd             |j                          y)rb   r    T)prefixinclude_special_flagsN)

print_helpr   sortedflags_by_module_dictr,   r-   removeprint_get_help_for_modulesexit)r$   re   r:   rf   rg   rC   modulesmain_modules           r'   rh   z_HelpFullAction.__call__Z  s|     --Jz6689gHHQKk		{#J,,
"D - : ;
KKMr(   ri   )rV   rW   rX   rY   r   rh   rZ   r[   s   @r'   r"   r"   F  s    )"r(   r"   c                     | rRt        d | j                  d      D              }|t        d |D              z  }|D cg c]  }t        ||      r| }}|S c c}w )z=Returns a new list of args after removing flags in --undefok.c              3   <   K   | ]  }|j                           y wri   )strip.0rA   s     r'   	<genexpr>z&_strip_undefok_args.<locals>.<genexpr>q  s     D1C

1Cs   ,c              3   &   K   | ]	  }d |z     yw)rt   Nr   r   s     r'   r   z&_strip_undefok_args.<locals>.<genexpr>r  s     ?s   )r>   split_is_undefok)r	   r9   undefok_namesargs       r'   r3   r3   n  s[    Ds1CDDMS????MG4C{3'FC4DG	+ Hs   AAc                     | j                  d      sy| j                  d      r| dd }n| dd }d|v r|j                  dd      \  }}n|}||v ryy)	zGReturns whether we can ignore arg based on a set of undefok flag names.r   FrH   rr   Nr*   =T)rx   r   )r   r   arg_without_dashrA   _s        r'   r   r   x  sg    		^^D12w12w$$S!,GD!D	]	r(   )rY   
__future__r   r   r   r    r,   abslr   rn   r@   r   ActionrR   rP   r"   r3   r   r   r(   r'   <module>r      s   JX '  %  
    |'X,, |'~!4(// !4H14 14h%hoo %Pr(   