
    epj}                       U d 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mZ dZ e            Zded	<    e            Zded
<   i Zded<   i Zded<    e            Zded<    ej                    Zd?dZ eh d          Zded<   d@dZdAdZdBdZdCd ZdCd!Z dDd#Z!dEd$Z"dFd%Z#dGdHd*Z$dEd+Z%dId.Z&dAd/Z'ddd0dJd4Z(dKd6Z)dEd7Z*dKd8Z+dLd<Z,dMd=Z-dNd>Z.dS )OzFHelpers for loading Hermes .env files consistently across entrypoints.    )annotationsN)Path)load_dotenv)atomic_replacefast_safe_load)_API_KEY_TOKEN_SECRET_KEYset[str]_WARNED_KEYS_WARNED_UTF32_PATHSdict[str, str]_SECRET_SOURCESzdict[str, dict[str, str]]_SECRET_SOURCE_VALUES_BY_HOME_APPLIED_HOMESreturnc                 |    ddl m}  ddlm} t	          |                                          t	          |           z  S )aE  Return the combined set of known Hermes env-var keys.

    Includes both ``OPTIONAL_ENV_VARS`` (setup-flow vars with metadata) and
    ``_EXTRA_ENV_KEYS`` (provider/platform keys managed outside the setup
    wizard).  Lazy-imported to avoid circular-dependency during early-bootstrap
    ``load_hermes_dotenv()`` calls.
    r   )_EXTRA_ENV_KEYS)OPTIONAL_ENV_VARS)hermes_cli.configr   hermes_cli.config_defaultsr   setkeys)r   r   s     ;/home/thesage/.hermes/hermes-agent/hermes_cli/env_loader.py_known_hermes_env_keysr   7   sP     211111<<<<<< %%''((3+?+???    >   COPILOT_CLI_PATHCOPILOT_ACP_BASE_URLHERMES_ACP_AUTH_METHODHERMES_ACP_AUTO_APPROVEHERMES_COPILOT_ACP_ARGSHERMES_COPILOT_ACP_COMMANDzfrozenset[str]_PROFILE_MANAGED_ENV_KEYSpathr   c                $   t                      }	 |                     dd          }n=# t          $ r0 	 |                     dd          }n# t          $ r |cY cY S w xY wY nw xY w|                                D ]}|                                }|r|                    d          sd|vr2|                    d          r
|dd	         }|                    dd
          d                                         }|r|                    |           |S )aY  Return KEY names assigned in a dotenv file (including empty ``KEY=``).

    Uses a fast line scanner rather than full dotenv parsing so it works
    during early bootstrap without importing python-dotenv.  Ignores comment
    and blank lines.  Non-ASCII encoding errors fall back to ``latin-1``,
    matching ``_load_dotenv_with_fallback``.
    utf-8replaceencodingerrorslatin-1#=zexport    N   r   )r   	read_text	Exception
splitlinesstrip
startswithsplitadd)r%   r   textlinekeys        r   _env_keys_defined_in_dotenvr;   V   s?    UUD~~wy~AA   	>>9Y>GGDD 	 	 	KKKKK	 D
 !!  zz|| 	ts++ 	s$??9%% 	8Djja  #))++ 	HHSMMMKs2   ( 
A"A
A"AA"AA"!A"Nonec                    |                                  sdS t          |           }t          D ]!}||vr|t          j        v rt          j        |= "dS )u+  Remove inherited profile-managed Hermes keys absent from ``.env``.

    After the profile's ``.env`` has been loaded with ``override=True``,
    scan the file for which profile-managed keys it explicitly defines and
    delete any such key that exists in ``os.environ`` but is *not* present
    in the file.

    Scope is deliberately NARROW: only ``_PROFILE_MANAGED_ENV_KEYS`` —
    behavioral routing keys (ACP auth method, copilot-ACP endpoints) that a
    parent Hermes process injects and that silently change *which provider
    path* a profile uses. Provider API keys (OPENAI_API_KEY, …) are
    intentionally excluded: users legitimately export those in their shell
    (``export OPENAI_API_KEY=…`` is a documented flow — see
    ``tests/hermes_cli/test_dump_env_visibility.py``), and a startup scrub
    cannot distinguish a shell export from parent-process leakage. Clearing
    the full known-key set would delete user-exported credentials on every
    ``hermes`` invocation.

    Cross-profile *credential* isolation is handled at read time by
    ``agent.secret_scope.get_secret`` (scope authoritative under
    multiplexing), not by mutating ``os.environ`` here.

    Does **not** run when the ``.env`` file does not exist (bare-profile
    case, which follows ``#66930`` / ``#67027`` semantics).
    N)existsr;   r$   osenviron)r%   definedr:   s      r   %_clear_known_keys_missing_from_dotenvrB   r   s`    4 ;;== )$//G(    g#"3"3
3   r   env_varstr
str | Nonec                6    t                               |           S )a  Return the label of the secret source that supplied ``env_var``, if any.

    Returns ``"bitwarden"`` for keys pulled from Bitwarden Secrets Manager
    during the current process's ``load_hermes_dotenv()`` call.  Returns
    ``None`` for keys that came from ``.env``, the shell environment, or
    aren't tracked.  The returned label is metadata only: credential-pool
    persistence may store it to explain the origin of a borrowed secret, but
    must never treat it as authorization to persist the raw value.
    )r   get)rC   s    r   get_secret_sourcerH      s     w'''r   hermes_homestr | os.PathLikec                    t          t          |                                                     }t          t                              |i                     S )z>Return the external-secret value snapshot for ``hermes_home``.)rD   r   resolvedictr   rG   )rI   home_keys     r   get_secret_source_valuesrO      sD     4$$,,..//H-11(B??@@@r   c                |    t           5  t          t          |                     cddd           S # 1 swxY w Y   dS )at  Resolve one profile's configured sources without mutating ``os.environ``.

    Multiplex gateways can route a first turn to a secondary profile that has
    never run the process-global dotenv startup path.  Resolve that profile's
    sources against a private mapping seeded from its own ``.env`` and record
    the usual per-home snapshot for ``build_profile_secret_scope()``.

    Fail-open and once-per-home semantics intentionally mirror
    ``_apply_external_secret_sources``.  The returned mapping contains only
    values actually contributed by external sources, never the profile's
    plaintext ``.env`` entries.
    N)_SECRET_SOURCE_CACHE_LOCK_hydrate_profile_secret_sourcesr   )rI   s    r   hydrate_profile_secret_sourcesrS      s     
# B B.tK/@/@AAB B B B B B B B B B B B B B B B B Bs   155homec                   t          |                                           }|t          v rt          |           S 	 t	          |           }n# t
          $ r i cY S w xY w|si S 	 ddlmm} ddl	m
} fdt          j                                        D             }|                     || dz                       | dz  }|                                r9 ||                                          D ]\  }}|                    ||           t          |           |d<    ||| |          }	n# t
          $ r i cY S w xY w|	j        si S t                              |           i }
|	j                                        D ]1\  }}|                    |          }||j        t,          |<   ||
|<   2|
r
|
t.          |<   t1          |
          S )	zALocked implementation for :func:`hydrate_profile_secret_sources`.r   )_is_global_envload_env_file	apply_allc                2    i | ]\  }} |          ||S  r[   ).0namevaluerV   s      r   
<dictcomp>z3_hydrate_profile_secret_sources.<locals>.<dictcomp>   s?     
 
 
e~d##
%
 
 
r   .env.op.envHERMES_HOME)r@   )rD   rL   r   rO   _load_secrets_configr2   agent.secret_scoperV   rW   agent.secret_sources.registryrY   r?   r@   itemsupdater>   
setdefaultsourcesr7   
provenancerG   sourcer   r   rM   )rT   rN   cfgrW   rY   	local_envop_env_name_valuereportvaluesr]   appliedr^   rV   s                 @r   rR   rR      sD   4<<>>""H>!!'---"4((   			 	DDDDDDDD;;;;;;
 
 
 
!z//11
 
 
	
 	tf}55666 	!==?? 	4!.v!6!6!<!<!>!> 4 4v$$UF3333#&t99	- 3i888   			 > 	x   F*0022  gd##= 't 928%h/<<s$   A AA#CD/ /D>=D>c                     t                                            t                                           t                                           dS )u  Forget which HERMES_HOME paths have already had external secrets applied.

    The first call to ``_apply_external_secret_sources(home_path)`` in a
    process pulls from Bitwarden (or other configured backend), records the
    applied keys in ``_SECRET_SOURCES``, and remembers ``home_path`` so
    subsequent calls in the same process are no-ops.  Call this to force the
    next call to re-pull — useful for tests, and for long-running processes
    that want to refresh after a config change.
    N)r   clearr   r   r[   r   r   reset_secret_source_cacherv      s@     !'')))))r   c                    t          |           }|sdS |dk    rdS 	 ddlm}  ||          }||j        rd|j         dS n# t          $ r Y nw xY wd| dS )	u:  Return a human-readable suffix like ``" (from Bitwarden)"`` or ``""``.

    Use this when printing a detected credential so the user can see where
    it came from.  Empty string when the credential came from ``.env`` or
    the shell — those are the implicit / "default" cases users already
    understand.
     	bitwardenz (from Bitwarden)r   
get_sourceNz (from ))rH   re   r{   labelr2   )rC   rk   r{   
registereds       r   format_secret_source_suffixr      s     w''F r""<<<<<<Z''
!j&6!0Z-0000   Vs   $A 
AA   r^   limitintc                   g }| D ]s}t          |          dk    r^dt          |          d}|                                r	|d|dz  }||vr|                    |           t          |          |k    r ntd                    |          S )zEReturn a compact 'U+XXXX ('c'), ...' summary of non-ASCII codepoints.   zU+04X (r|   z, )ordisprintableappendlenjoin)r^   r   seenchr}   s        r   _format_offending_charsr     s    D  r77S==&R&&&E~~ &b%D  E"""4yyE!!99T??r   c                    t          t          j                                                  D ]&\  } t	          fdt
          D                       s'	 |                     d           ># t          $ r Y nw xY w|                     dd                              d          }|t          j        <   t          v rt          
                               t          |           t          |          z
  }t          |           pd}t          d d| d|d	k    rd
nd d| d	t          j                   t          dt          j                   (dS )a!  Strip non-ASCII characters from credential env vars in os.environ.

    Called after dotenv loads so the rest of the codebase never sees
    non-ASCII API keys.  Only touches env vars whose names end with
    known credential suffixes (``_API_KEY``, ``_TOKEN``, etc.).

    Emits a one-line warning to stderr when characters are stripped.
    Silent stripping would mask copy-paste corruption (Unicode lookalike
    glyphs from PDFs / rich-text editors, ZWSP from web pages) as opaque
    provider-side "invalid API key" errors (see #6843).
    c              3  B   K   | ]}                     |          V  d S )N)endswith)r\   suffixr:   s     r   	<genexpr>z/_sanitize_loaded_credentials.<locals>.<genexpr>7  s/      KKF3<<''KKKKKKr   asciiignore)r+   znon-printablez  Warning: z contained z non-ASCII characterr0   srx   r   u8   ) — stripped so the key can be sent as an HTTP header.filea@    This usually means the key was copy-pasted from a PDF, rich-text editor, or web page that substituted lookalike
  Unicode glyphs for ASCII letters. If authentication fails (e.g. "API key not valid"), re-copy the key from the
  provider's dashboard and run `hermes setup` (or edit the .env file in a plain-text editor).N)listr?   r@   rf   any_CREDENTIAL_SUFFIXESencodeUnicodeEncodeErrordecoder   r7   r   r   printsysstderr)r^   cleanedstrippeddetailr:   s       @r   _sanitize_loaded_credentialsr   *  s    2:++--.. 
 

UKKKK6JKKKKK 		LL!!!! 	 	 	D	,,wx,88??HH!
3,u::G,(//B?2# 2 2( 2 2!mmss2 2/52 2 2 		
 	
 	
 	
 	1 	
 	
 	
 	
 	
+
 
s   A++
A87A8overrideboolc                   	 t          | |d           n"# t          $ r t          | |d           Y nw xY wt                       d S )Nr'   )dotenv_pathr   r*   r,   )r   UnicodeDecodeErrorr   )r%   r   s     r   _load_dotenv_with_fallbackr   V  sn    Mx'JJJJJ M M Mx)LLLLLLM !"""""s    44c                   |                                  sdS 	 ddlm} n# t          $ r Y dS w xY w	 |                                 }n# t
          $ r Y dS w xY wd}|                    t          j                  s|                    t          j	                  rxt          |                                           }|t          vrLt                              |           ddl}|                    t                                         d|            dS |                    t          j                  s|                    t          j                  rk	 t)          j        t)          j        |          dd          5 }|                                }ddd           n# 1 swxY w Y   n# t0          $ r Y dS w xY wd}np	 t3          | d	d
          5 }|                                }ddd           n# 1 swxY w Y   n# t
          $ r Y dS w xY w|r|d                             d          rdS 	 d |D             } ||          }	|	|k    s|rddl}
|
                    t          | j                  dd          \  }}	 t;          j        |dd          5 }|                    |	           |                                  t;          j!        |"                                           ddd           n# 1 swxY w Y   tG          ||            dS # tH          $ r( 	 t;          j%        |           n# tL          $ r Y nw xY w w xY wdS # t
          $ r Y dS w xY w)u  Pre-sanitize a .env file before python-dotenv reads it.

    Strips embedded null bytes which crash ``os.environ[k] = v``
    with ``ValueError: embedded null byte`` — typically introduced by
    copy-pasting API keys from terminals or rich-text editors.

    Encoding: sniffs a leading BOM *before* any text decode. UTF-16
    (Notepad "Unicode") is decoded correctly and rewritten as clean
    UTF-8. UTF-32 is refused (left untouched) so we never fall through
    to the errors=replace corruption path. Order of BOM checks matters:
    UTF-32-LE's BOM starts with UTF-16-LE's FF FE.

    ``hermes_cli.config._sanitize_env_lines`` normalizes line endings while
    treating content after the first ``=`` as opaque for boundary discovery.
    Nr   )_sanitize_env_linesFz^Skipping .env sanitize for %s: UTF-32 BOM detected; leaving file untouched to avoid corruptionzutf-16)r*   newlineTz	utf-8-sigr(   r)   u   �c                :    g | ]}|                     d d          S ) rx   )r(   )r\   r9   s     r   
<listcomp>z0_sanitize_env_file_if_needed.<locals>.<listcomp>  s&    BBBDLL,,BBBr   z.tmpz.env_)dirr   prefixwr'   r*   )'r>   r   r   ImportError
read_bytesr2   r5   codecsBOM_UTF32_LEBOM_UTF32_BErD   rL   r   r7   logging	getLogger__name__warningBOM_UTF16_LEBOM_UTF16_BEioTextIOWrapperBytesIO	readlinesr   opentempfilemkstempparentr?   fdopen
writelinesflushfsyncfilenor   BaseExceptionunlinkOSError)r%   r   rawforce_utf8_rewritepath_keyr   foriginalr   	sanitizedr   fdtmps                r   _sanitize_env_file_if_neededr   c  s     ;;== 9999999   oo    
~~f)** cnnV=P.Q.Q  t||~~&&...##H---NNNh''//=  
 	
~~f)** cnnV=P.Q.Q 	!
3(D   );;==) ) ) ) ) ) ) ) ) ) ) ) ) ) ) " 	 	 	FF	 "	d[CCC )q;;==) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 	 	 	FF	  	..x88 	F
 CBBBB''11	  $6 OOO&&$$VG '  GBYr3999 )QLL+++GGIIIHQXXZZ((() ) ) ) ) ) ) ) ) ) ) ) ) ) ) sD)))))    IcNNNN   D ! "    s    
--A 
AA)F$ 7FF$ FF$ F F$ $
F21F29G8 G, G8 ,G00G8 3G04G8 8
HH)AM :L
 AK-!L
 -K11L
 4K15L
 

L<L*)L<*
L74L<6L77L<<M 
MM)rI   project_envstr | os.PathLike | Noner   
list[Path]c                0   g }t          | p(t          j        dt          j                    dz                      }|dz  }|rt          |          nd}|                                rt          |           |r#|                                rt          |           |                                r5t          |d           |                    |           t          |           |dz  }|                                r0t          j	        
                    d          st          |d	           |r;|                                r't          ||            |                    |           t          |           t                       t          |           |S )
a[  Load Hermes environment files with user config taking precedence.

    Behavior:
    - `~/.hermes/.env` overrides stale shell-exported values when present.
    - project `.env` acts as a dev fallback and only fills missing values when
      the user env exists.
    - if no user env exists, the project `.env` also overrides stale shell vars.
    rb   .hermesr`   NTr   ra   OP_SERVICE_ACCOUNT_TOKENF)r   r?   getenvrT   r>   r   r   r   rB   r@   rG   _apply_external_secret_sources_apply_managed_env_reapply_terminal_config_bridge)rI   r   loaded	home_pathuser_envproject_env_pathrn   s          r   load_hermes_dotenvr     s    F[UBImTY[[9=T$U$UVVI6!H,7AtK(((T  /$X... 7,3355 7$%5666 8"8d;;;;h 	.h777 "F}} ;rz~~.HII ;"6E:::: (,3355 ("#3&jIIII&'''"9--- $I...Mr   r   c                    	 t          |                                           t                                                      k    rdS ddlm}  |d           dS # t
          $ r Y dS w xY w)u  Re-assert config.yaml's explicit ``terminal.*`` keys over reloaded .env.

    Delegates to ``hermes_cli.config.apply_terminal_config_to_env`` — the
    single shared bridge (same one terminal_tool's fallback and the TUI/
    dashboard launchers use) — so key coverage, explicit-keys-only override
    semantics, cwd placeholder handling, and the managed-scope overlay can't
    drift from the other bridge sites. Only keys the user actually wrote in
    config.yaml's ``terminal`` section override env values; a config.yaml
    without a terminal section leaves .env/shell selections untouched.

    Scoped to the process HERMES_HOME: the shared bridge reads the
    process-global config, so re-applying it for a *different* profile's
    ``load_hermes_dotenv(hermes_home=...)`` call would bridge the wrong
    profile's config. Fail-open — a config problem must never break dotenv
    loading (the historical env-driven behavior still applies).
    Nr   )apply_terminal_config_to_env)env)r   rL   _process_hermes_homer   r   r2   )r   r   s     r   r   r     s    "	??""$$(<(>(>(F(F(H(HHHFBBBBBB$$......   s   AA A 
A)(A)c                     	 ddl m}  |                                 }n# t          $ r Y dS w xY w|dS |dz  }|                                sdS t          |           t          |d           dS )u  Apply the managed-scope .env last, with override, so it beats user/shell.

    Managed scope is machine-global (independent of HERMES_HOME / profile). v1
    enforcement is "applied last with override=True" — at the end of startup load
    ``os.environ`` holds the managed value for every managed key, beating both the
    user ``.env`` and any pre-existing shell export. This deliberately inverts the
    usual env-over-config precedence for the pinned keys (see
    ``docs/design/managed-scope.md`` §4.1).

    This does NOT prevent the agent from later mutating ``os.environ`` in-process
    or ``export``-ing in a subprocess shell; that hard boundary is a documented
    v2 item (design §8.1). v1 relies on filesystem permissions only.

    Fail-open: a missing managed dir or .env is the common case and a no-op; any
    error here is swallowed so managed scope can never block startup.
    r   )managed_scopeNr`   Tr   )
hermes_clir   get_managed_dirr2   r>   r   r   )r   managed_dirmanaged_envs      r   r   r   /  s    ",,,,,,#3355   &K  ---{T::::::s    
++c                   t          t          |                                                     }|t          v rdS 	 t	          |           }n# t
          $ r Y dS w xY w|sdS 	 ddlm} n# t          $ r Y dS w xY w	  |||           }n# t
          $ r Y dS w xY w|j	        sdS t          
                    |           |j        rkt                       i }|j                                        D ]7\  }}|j        t           |<   |t"          j        v rt"          j        |         ||<   8|t&          |<   |j	        D ]}|j        rUt+          d|j         dt/          |j                   dt/          |j                  dk    rdnd	 t0          j        
           |j        j        rxt+          d|j         d|j        j         t0          j        
           t9          |j        |j        j        |          }	|	r&t+          d|j         d|	 t0          j        
           |j        j        D ](}
t+          d|j         d|
 t0          j        
           )|j         D ] }t+          d| t0          j        
           !dS )u  Pull secrets from every enabled external source into env.

    Runs AFTER dotenv loads so .env values are visible (sources use them
    to locate bootstrap tokens) but BEFORE the rest of Hermes reads
    ``os.environ`` for credentials.  Any failure here is logged and
    swallowed — external secret sources must never block startup.

    The heavy lifting (source ordering, mapped-beats-bulk precedence,
    first-claim-wins conflict handling, override semantics, provenance)
    lives in ``agent.secret_sources.registry.apply_all``; this wrapper
    owns the once-per-HERMES_HOME guard, the post-apply ASCII
    sanitization sweep, the ``_SECRET_SOURCES`` provenance map that
    UI surfaces read, and the startup status lines.

    Idempotent within a process: subsequent calls for the same
    ``home_path`` are no-ops.  ``load_hermes_dotenv()`` runs at import
    time from several hot modules (cli.py, hermes_cli/main.py,
    run_agent.py, trajectory_compressor.py, ...), so without this guard
    the status lines would print 3-5x per CLI startup.  Use
    ``reset_secret_source_cache()`` if you need to force a re-pull
    (tests, long-running processes after a config change).
    Nr   rX   z  z
: applied z secretr0   r   rx   r   z: u   : → z  Secret sources: )!rD   r   rL   r   rc   r2   re   rY   r   ri   r7   applied_anyr   rj   rf   rk   r   r?   r@   r   rs   r   r}   r   r   r   resulterror_remediation_hintr]   
error_kindwarnings	conflicts)r   rN   rl   rY   rq   rr   r]   rs   srchintwarnconflicts               r   r   r   O  s)   . 4	??**,,--H>!!"9--    		
  
 	;;;;;;;   3	**    >  	 x    9 	%&&&
 "$#.4466 	0 	0MD'$+NOD!rz!!!z$/t28%h/~ = =; 	@SY @ @#ck*:*: @ @ #CK 0 0A 5 52@ @Z   
 : 	E6sy66CJ$466SZHHHH$SXsz/DcJJD E23922D22DDDDJ' 	= 	=D*sy**D**<<<<<	=$ @ @-8--CJ?????@ @s5   A 
AA!A( (
A65A6:B 
BBsource_namesecrets_cfgrM   c                   	 ddl m}  ||           }|dS |                    |           }t          |t                    r|ni }t          |                    ||          pd                                          S # t          $ r Y dS w xY w)u   Ask the failed source for its one-line fix-it hint.

    Defensive wrapper: remediation() is a pure mapping and shouldn't
    raise, but a plugin source could — and startup must never break on
    a status line.
    r   rz   Nrx   )	re   r{   rG   
isinstancerM   rD   remediationr4   r2   )r   r   r  r{   rk   src_cfgs         r   r   r     s    
<<<<<<K((>2//+..'66>''B6%%j'::@bAAGGIII   rrs   A< A$A< <
B
	B
c                   | dz  }|                                 si S | t                      k    r:	 ddlm}  |            pi }|                    d          pi S # t
          $ r Y nw xY w	 ddl}n# t          $ r i cY S w xY w	 t          |dd          5 }t          |          pi }ddd           n# 1 swxY w Y   n# t
          $ r i cY S w xY w|                    d          pi S )	zRead just the ``secrets:`` section out of config.yaml.

    Imported lazily and isolated from the main config loader so a
    malformed config can't take down dotenv loading entirely.
    zconfig.yamlr   )read_raw_configsecretsNrr'   r   )
r>   r   r   r  rG   r2   yamlr   r   r   )r   config_pathr  datar
  r   s         r   rc   rc     s    m+K 	 (****	999999"?$$*D88I&&,", 	 	 	D	   			+sW555 	+!!$$*D	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+   			88I$"$sY   (A 
A%$A%)A. .A=<A=B= B1%B= 1B55B= 8B59B= =CCc                 p    	 ddl m}   |             S # t          $ r t          j                    dz  cY S w xY w)z4The HERMES_HOME the shared config cache is keyed to.r   get_hermes_homer   )hermes_constantsr  r2   r   rT   r  s    r   r   r     sY    '444444    ' ' 'y{{Y&&&&'s     55)r   r   )r%   r   r   r   )r%   r   r   r<   )rC   rD   r   rE   )rI   rJ   r   r   )rT   r   r   r   )r   r<   )rC   rD   r   rD   )r   )r^   rD   r   r   r   rD   )r%   r   r   r   r   r<   )rI   r   r   r   r   r   )r   r   r   r<   )r   rD   r  rM   r   rD   )r   r   r   rM   )r   r   )/__doc__
__future__r   r   r   r?   r   	threadingpathlibr   dotenvr   utilsr   r   r   r   r   __annotations__r   r   r   r   RLockrQ   r   	frozensetr$   r;   rB   rH   rO   rS   rR   rv   r   r   r   r   r   r   r   r   r   r   rc   r   r[   r   r   <module>r     s&   L L L " " " " " "  				 				 



                 0 0 0 0 0 0 0 0 A 
      !$  % % % % #% $ $ $ $ <>  = = = = 355        +IO-- @ @ @ @* -6I 7 7 7 - -        8       D
( 
( 
( 
(A A A AB B B B&2 2 2 2j* * * *   6    )
 )
 )
 )
X
# 
# 
# 
#h h h hZ -1,0C C C C C CL   6; ; ; ;@_@ _@ _@ _@D   (!% !% !% !%H' ' ' ' ' 'r   