o
    qoi.                     @   s0  d Z ddlZddlZddlmZmZ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mZ ejZejZejZejZejZejZedZedZh dZG dd dejZG dd dejZ dddej!ddde"dede"deej# deej$ dej%de&dej'e fddZ(dS )z5API to use command line flags with Fiddle Buildables.    N)AnyOptionalTypeVar)flags)epath)config)legacy_flags)utils)auto_config)serializationz2^(config|config_file|config_str|fiddler|set):(.+)$_F>   r   
config_strconfig_filec                   @   s4   e Zd ZdZdejfddZdejde	fddZ
d	S )
FiddleFlagSerializera  ABSL serializer for a Fiddle config flag.

  This class can be provided to `FiddleFlag` as a serializer
  to serialize a fiddle config to a single command line argument.

  Example usage:
  ```
  from absl import flags
  from fiddle import absl_flags as fdl_flags

  FLAGS = flags.FLAGS

  flags.DEFINE_flag(
    fdl_flags.FiddleFlag(
        name="config",
        default=None,
        parser=flags.ArgumentParser(),
        serializer=FiddleFlagSerializer(),
        help_string="My fiddle flag",
    ),
    flag_values=FLAGS,
  )

  serialized_flag = FLAGS['config'].serialize()
  ```

  Users will more commonly use `fdl_flags.DEFINE_fiddle_config`
  which provides this serializer by default.
  pyref_policyc                 C   
   || _ d S N)_pyref_policy)selfr    r   P/home/ubuntu/.local/lib/python3.10/site-packages/fiddle/_src/absl_flags/flags.py__init__K   s   
zFiddleFlagSerializer.__init__valuereturnc                 C   s"   t  }|j|| jd}d| S )Nr   zconfig_str:)r	   ZlibJSONSerializer	serializer   )r   r   
serializer
serializedr   r   r   r   N   s   
zFiddleFlagSerializer.serializeN)__name__
__module____qualname____doc__r   PyrefPolicyr   r   	Buildablestrr   r   r   r   r   r   ,   s    r   c                       s   e Zd ZdZdddddeej dedeej	 f fdd	Z
d
efddZdejd
efddZdd ZdddZded
eddfddZdef fddZedd Zejdd Z  ZS )
FiddleFlaga  ABSL flag class for a Fiddle config flag.

  This class is used to parse command line flags to construct a Fiddle `Config`
  object with certain transformations applied as specified in the command line
  flags.

  Most users should rely on the `DEFINE_fiddle_config()` API below. Using this
  class directly provides flexibility to users to parse Fiddle flags themselves
  programmatically. Also see the documentation for `DEFINE_fiddle_config()`
  below.

  Example usage where this flag is parsed from existing flag:
  ```
  from fiddle import absl_flags as fdl_flags

  _MY_CONFIG = fdl_flags.DEFINE_multi_string(
      "my_config",
      "Name of the fiddle config"
  )

  fiddle_flag = fdl_flags.FiddleFlag(
      name="config",
      default_module=my_module,
      default=None,
      parser=flags.ArgumentParser(),
      serializer=None,
      help_string="My fiddle flag",
  )
  fiddle_flag.parse(_MY_CONFIG.value)
  config = fiddle_flag.value
  ```
  NT)default_moduleallow_importsr   r'   r(   r   c                   s:   || _ || _|| _d | _d | _g | _t j|i | d S r   )r(   r'   r   first_command_initial_config_expression_remaining_directivessuperr   )r   r'   r(   r   argskwargs	__class__r   r   r   v   s   zFiddleFlag.__init__
expressionc                 C   s\   t j|}|j}t |t jj| j| jd}t	
|r%|j|ji |jS ||ji |jS NzCould not init a buildable from)r	   CallExpressionparse	func_nameresolve_function_referenceImportDottedNameDebugContextBASE_CONFIGr'   r(   r
   is_auto_configas_buildabler-   r.   )r   r1   	call_expr	base_namebase_fnr   r   r   _initial_config   s   
zFiddleFlag._initial_configcfgc                 C   sV   t j|}|j}t |t jj| j| jd}||g|j	R i |j
}|d ur)|S |S r2   )r	   r3   r4   r5   r6   r7   FIDDLERr'   r(   r-   r.   )r   r?   r1   r;   r<   fiddlernew_cfgr   r   r   _apply_fiddler   s   zFiddleFlag._apply_fiddlerc                 C   s,   |  |}| j| |  jt|7  _d S r   )_parser+   extendpresentlen)r   	arguments
new_parsedr   r   r   r4      s   
zFiddleFlag.parser   c                 C   s   | j | _d| _g | _d| _d S )NTr   )defaultr   using_default_valuer+   rF   )r   r   r   r   unparse   s   
zFiddleFlag.unparsecommandc              
   C   s   | j rtd| d| d| j d| j  d	|| _ |dkr%| || _d S |dkrNt| }tj	|
 | jd| _W d    d S 1 sGw   Y  d S |dkrat }|j|| jd| _d S d S )	Nz2Only one base configuration is permitted. Received:z after z was already provided.r   r   r   r   )r*   
ValueErrorr)   r>   r   r   Pathopenr   	load_jsonreadr   r	   r   deserialize)r   rM   r1   fr   r   r   r   _parse_config   s6   

"zFiddleFlag._parse_configc                    s   t tj| |S r   )r,   r   	MultiFlag
_serializer   r   r/   r   r   rX      s   zFiddleFlag._serializec                 C   s   | j rf| j d}t|}|std| j d| \}}| jd u r3|tvr0td| d|| _|dks?|dks?|dkrF| 	|| n|d	krRt
| j| n|d
kr_| | j|| _ntd| j s| jS )Nr   zAll flag values to zQ must begin with 'config:', 'config_file:', 'config_str:', 'set:', or 'fiddler:'.z|First flag command must specify the input config via either config or config_file or config_str commands. Received command: z	 instead.r   r   r   setrA   z&Internal error; should not be reached.)r+   pop_COMMAND_RE	fullmatchrO   namegroupsr)   _BASE_CONFIG_DIRECTIVESrV   r	   	set_value_valuerC   AssertionError)r   itemmatchrM   r1   r   r   r   r      s6   

"zFiddleFlag.valuec                 C   r   r   )rb   rY   r   r   r   r     s   
)r   N)r   r    r!   r"   r   types
ModuleTypeboolr   r#   r   r%   r>   r   r$   rC   r4   rL   rV   rX   propertyr   setter__classcell__r   r   r/   r   r&   T   s,    $

%r&   F)rJ   r'   r   flag_valuesrequiredr^   rJ   help_stringr'   r   rl   rm   r   c             
   C   s,   t jt| |||t  t|d|d||dS )a0  Declare and define a fiddle command line flag object.

  When used in a python binary, after the flags have been parsed from the
  command line, this command line flag object will have the `fdl.Config` object
  built.

  Example usage in a python binary:
  ```
  .... other imports ...
  from fiddle import absl_flags as fdl_flags

  _MY_FLAG = fdl_flags.DEFINE_fiddle_config(
      "my_config",
      help_string="My binary's fiddle config handle",
      default_module=sys.modules[__name__],
  )

  def base_config() -> fdl.Config:
    return some_import.fixture.as_buildable()

  def set_attributes(config, value: str):
    config.some_attr = value
    return config

  def main(argv) -> None:
    if len(argv) > 1:
      raise app.UsageError("Too many command-line arguments.")
    # _MY_FLAG.value contains the config object, built from `base_config()`
    # with any command line flags and overrides applied in the order passed in
    # the command line.
    some_import.do_something(_MY_FLAG.value.some_attr)

  if __name__ == "__main__":
    app.run(main)
  ```

  Invoking the above binary with:
  python3 -m path.to.my.binary --my_config=config:base_config \
  --my_config=fiddler:'set_attributes(value="float64")' \
  --my_config=set:some_other_attr.enable=True

  results in the `_MY_FLAG.value` set to the built config object with all the
  command line flags applied in the order they were passed in.

  To load a Fiddle config from a serialized file:
  python3 -m path.to.my.binary --my_config=config_file:path/to/file

  Args:
    name: name of the command line flag.
    default: default value of the flag.
    help_string: help string describing what the flag does.
    default_module: the python module where this flag is defined.
    pyref_policy: a policy for importing references to Python objects.
    flag_values: the ``FlagValues`` instance with which the flag will be
      registered. This should almost never need to be overridden.
    required: bool, is this a required flag. This must be used as a keyword
      argument.

  Returns:
    A handle to defined flag.
  r   )r^   r'   rJ   r   parserr   rn   )rl   rm   )r   DEFINE_flagr&   ArgumentParserr   )r^   rJ   rn   r'   r   rl   rm   r   r   r   DEFINE_fiddle_config  s   G	rr   ))r"   rerf   typingr   r   r   abslr   etilsr   fiddle._srcr   fiddle._src.absl_flagsr   r	   fiddle._src.experimentalr
   r   apply_fiddlers_toapply_overrides_tocreate_buildable_from_flagsflags_parserrewrite_fdl_argsfdl_flags_suppliedcompiler\   r   r`   ArgumentSerializerr   rW   r&   FLAGSr%   rg   r#   
FlagValuesrh   
FlagHolderrr   r   r   r   r   <module>   sZ   
( 6	