
    .cj|                        U d 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m	Z	m
Z
mZmZmZ ddlmZmZmZ  ej        e          Zdddd	Z ed
          Z ed          ZdefdZdefdZdadefdZdedee	eef         ef         fdZdedefdZ de	eef         defdZ! eh d          Z"i Z#e	eef         e$d<   dedefdZ%de	eef         defdZ&i Z'e	eee(e(f         e	eef         f         e$d<   d>dZ)de	eef         fdZ*d?dedz  dee         fdZ+dee         fd Z,i Z-e	eee(f         e
e         f         e$d!<   d>d"Z.de
e         fd#Z/de
e         fd$Z0d%edefd&Z1defd'Z2defd(Z3de	eef         de	ee
f         fd)Z4de	eef         de
e	eef                  fd*Z5de
e	eef                  fd+Z6d,Z7d-e	eef         d.efd/Z8d0e
e	eef                  de	eef         fd1Z9d2Z:de	eef         defd3Z;de	eef         defd4Z<de	eef         defd5Z=d6ed7efd8Z> ej?        d9          Z@d:edeee         ef         fd;ZAd<ee         defd=ZBdS )@a  Lightweight skill metadata utilities shared by prompt_builder and skills_tool.

This module intentionally avoids importing the tool registry, CLI config, or any
heavy dependency chain.  It is safe to import at module level without triggering
tool registration or provider resolution.
    N)Path)AnyDictListOptionalSetTuple)get_config_pathget_skills_dir	is_termuxdarwinlinuxwin32)macosr   windows)z.gitz.githubz.hubz.archivez.venvvenvnode_moduleszsite-packages__pycache__z.toxz.noxz.pytest_cachez.mypy_cachez.ruff_cache)
references	templatesassetsscriptsreturnc                     	 | j         }n3# t          $ r& ddlm}  |t	          |                     j         }Y nw xY wt          d |D                       pt          |           S )ax  True if *path* should be skipped by active skill scanners.

    Use this on every ``SKILL.md`` path produced by direct ``rglob`` scans to
    prune dependency, virtualenv, VCS, cache, and progressive-disclosure
    support-package paths. Centralising the check here keeps every
    skill-scanning site in sync with the shared exclusion set.

    Accepts a Path or string.
    r   )PurePathc              3   (   K   | ]}|t           v V  d S N)EXCLUDED_SKILL_DIRS).0parts     3/home/ice/.hermes/hermes-agent/agent/skill_utils.py	<genexpr>z)is_excluded_skill_path.<locals>.<genexpr>D   s(      ==tt**======    )partsAttributeErrorpathlibr   stranyis_skill_support_path)pathr$   r   s      r!   is_excluded_skill_pathr+   5   s    *
 * * *$$$$$$T##)* ==u===== AVB B s   
 -::c                 *   t          | t                    r| nt          t          |                     }|j        }t	          |dd                   D ]@\  }}|t
          vs|dk    rt          |d|          }|dz                                  r dS AdS )a  True if *path* is under a support dir of an actual skill root.

    ``references/``, ``templates/``, ``assets/``, and ``scripts/`` are
    progressive-disclosure support areas when they sit directly inside a skill
    directory containing ``SKILL.md``. They are not active discovery roots for
    standalone skills. A preserved package such as
    ``some-skill/references/old-skill-package/SKILL.md`` is documentation data
    unless the caller explicitly loads it via ``file_path``.

    Legitimate categories or skill names such as ``skills/scripts/foo`` remain
    discoverable because their ``scripts`` component is not directly under a
    directory that contains ``SKILL.md``.
    Nr   SKILL.mdTF)
isinstancer   r'   r$   	enumerateSKILL_SUPPORT_DIRSexists)r*   path_objr$   idxr    
skill_roots         r!   r)   r)   I   s     "$--Btt4D		??HNE uSbSz**  	T)))SAXX5#;'
#++-- 	44	5r#   contentc                     t           ,ddlt          dd          pj        dt          ffd}|a t          |           S )z7Parse YAML with lazy import and CSafeLoader preference.Nr   CSafeLoadervaluec                 2                         |           S )N)Loader)load)r9   loaderyamls    r!   _loadzyaml_load.<locals>._loadq   s    99U69222r#   )_yaml_load_fnr>   getattr
SafeLoaderr'   )r6   r?   r=   r>   s     @@r!   	yaml_loadrC   i   sl     }d33Ft	3 	3 	3 	3 	3 	3 	3 	3 !!!r#   c                    i }|                      d          r
| dd         } | }|                      d          s||fS t          j        d| dd                   }|s||fS | d|                                dz            }| |                                dz   d         }	 t          |          }t          |t                    r|}n# t          $ rt |	                                
                    d          D ]I}d|vr|
                    dd          \  }}|	                                ||	                                <   JY nw xY w||fS )	u  Parse YAML frontmatter from a markdown string.

    Uses yaml with CSafeLoader for full YAML support (nested metadata, lists)
    with a fallback to simple key:value splitting for robustness.

    A single leading UTF-8 BOM (U+FEFF) is stripped before parsing. Windows
    GUI editors (Notepad, PowerShell ``>``) prepend one when saving a SKILL.md
    as UTF-8, and ``read_text(encoding="utf-8")`` preserves it (only
    ``utf-8-sig`` strips it). Left in place, the BOM defeats the ``---`` fence
    check below and the whole frontmatter is silently discarded — name,
    description, ``platforms`` gating, env-var setup, and conditional
    activation all vanish. See CONTRIBUTING.md "File encoding".

    Returns:
        (frontmatter_dict, remaining_body)
    u   ﻿   Nz---z
\n---\s*\n   
:)
startswithresearchstartendrC   r/   dict	Exceptionstripsplit)	r6   frontmatterbody	end_matchyaml_contentparsedlinekeyr9   s	            r!   parse_frontmatterrY   {   s   " #%K (## !""+De$$ !D  	-55I !D  1y001445L9==??Q&(()D
5<((fd## 	! K 5 5 5 &&((..t44 	5 	5D$C++JC',{{}}K		$$		5 	55 s   &C A;EE	platformsc                 p   | sdS t          | t                    s| g} t          j        }t	                      }| D ]|}t          |                                                                          }t          	                    ||          }|
                    |          r dS |r	|dk    r dS |r|dv r dS }dS )z?Return True when *platforms* is compatible with the current OS.Tr   )termuxandroidF)r/   listsysplatformr   r'   lowerrP   PLATFORM_MAPgetrI   )rZ   currentrunning_in_termuxr`   
normalizedmappeds         r!   skill_matches_platform_listrh      s     ti&&  K	lG!  ]]((**0022
!!*j99f%% 	44
  	7!2!244 	+@!@!@445r#   rR   c                 F    t          |                     d                    S )av  Return True when the skill is compatible with the current OS.

    Skills declare platform requirements via a top-level ``platforms`` list
    in their YAML frontmatter::

        platforms: [macos]          # macOS only
        platforms: [macos, linux]   # macOS and Linux

    If the field is absent or empty the skill is compatible with **all**
    platforms (backward-compatible default).

    Termux note: on Termux/Android, ``sys.platform`` is ``"linux"`` on
    older Pythons but became ``"android"`` on Python 3.13+. Termux is a
    Linux userland riding on the Android kernel, so skills tagged
    ``linux`` are treated as compatible in Termux regardless of which
    ``sys.platform`` value Python reports. Individual Linux commands
    inside a skill may still misbehave (no systemd, BusyBox utils, no
    apt/dnf, etc.) but that is on the skill, not on platform gating.
    rZ   )rh   rc   )rR   s    r!   skill_matches_platformrj      s    ( '{{'C'CDDDr#   >   s6dockerkanban_ENV_DETECT_CACHEenvc                    | t           v rt           |          S d}| dk    r\t          j        d          st          j        d          rd}n	 ddlm} t           |                      }n# t          $ r d}Y nrw xY w| dk    r$	 dd	lm}  |            }nV# t          $ r d}Y nHw xY w| d
k    r>t          j	        
                    d          pt          j	        
                    d          }|t           | <   |S )zReturn True when the named runtime environment is currently active.

    Cached per process. Unknown env names return True (fail-open: never hide a
    skill because of a tag we don't understand).
    Trm   HERMES_KANBAN_TASKHERMES_KANBAN_BOARDr   )_profile_has_kanban_toolsetFrl   )is_containerrk   z/run/s6z/package/admin/s6-overlay)rn   osgetenvtools.kanban_toolsrs   boolrO   hermes_constantsrt   r*   isdir)ro   resultrs   rt   s       r!   _detect_environmentr|      sF     %%F
h 9)** 	bi8M.N.N 	FFJJJJJJ99;;<<   		555555!\^^FF 	 	 	FFF		
 y)) 
RW]]'.
 .
 $cMs$   A) )A87A8B B"!B"c                    |                      d          }|sdS t          |t                    s|g}|D ]V}t          |                                                                          }|s8|t          vr dS t          |          r dS WdS )uR  Return True when the skill is relevant to the current runtime environment.

    Skills may declare an ``environments`` list in their YAML frontmatter::

        environments: [kanban]        # only relevant when kanban is active
        environments: [s6]            # only relevant inside the s6 Docker image
        environments: [docker]        # only relevant inside any container

    If the field is absent or empty the skill is relevant in **all**
    environments (backward-compatible default).

    This is an OFFER-time filter: it controls whether a skill shows up in the
    skills index / autocomplete / slash-command list. It is intentionally NOT
    enforced by ``skill_view`` or ``--skills`` preloading — an explicit load is
    explicit consent, and load-bearing force-loads (e.g. a dispatcher pinning
    a task to a specialist skill via ``--skills``) must always succeed
    regardless of how the offer surfaces filter the skill.

    A skill matches when ANY of its declared environments is currently active
    (OR semantics, mirroring ``platforms``). Unknown env tags fail open.
    environmentsTF)rc   r/   r^   r'   ra   rP   _KNOWN_ENVIRONMENTSr|   )rR   r~   ro   rf   s       r!   skill_matches_environmentr     s    , ??>22L tlD)) &$~  XX^^%%++--
 	00044z** 	44	5r#   _RAW_CONFIG_CACHEc                  8    t                                            dS )u/   Test hook — drop the shared raw config cache.N)r   clear r#   r!   _raw_config_cache_clearr   I  s    r#   c                  B   t                      } |                                 si S 	 |                                 }t          |           |j        |j        f}n# t          $ r d}Y nw xY w|t                              |          }||S 	 t          | 
                    d                    }n5# t          $ r(}t                              d| |           i cY d}~S d}~ww xY wt          |t                    si S |#t                                           |t          |<   |S )a  Read config.yaml with a shared mtime+size keyed cache.

    This module intentionally avoids importing ``hermes_cli.config`` on the
    skill prompt/build path. A tiny local cache gives the same repeated-read
    win without pulling the heavier CLI config stack into startup.
    Nutf-8encodingz"Could not read skill config %s: %s)r
   r2   statr'   st_mtime_nsst_sizeOSErrorr   rc   rC   	read_textrO   loggerdebugr/   rN   r   )config_pathr   	cache_keycachedrV   es         r!   _load_raw_configr   N  sN    "##K 	!!%%t'7F		   			 "&&y11M;00'0BBCC   9;JJJ						 fd## 	!!!'-)$Ms/   0A A&%A&
#B. .
C 8CC C r`   c                    t                      }|st                      S |                    d          }t          |t                    st                      S ddlm} | pt          j        d          p
 |d          }t          |                    d                    }|r>|                    d          pi                     |          }||t          |          z  S |S )a
  Read disabled skill names from config.yaml.

    Args:
        platform: Explicit platform name (e.g. ``"telegram"``).  When
            *None*, resolves from ``HERMES_PLATFORM`` or
            ``HERMES_SESSION_PLATFORM`` env vars.  Returns the global
            disabled list, unioned with the platform-specific list when a
            platform is resolved (a globally-disabled skill stays disabled
            on every platform).

    Reads the config file directly (no CLI config imports) to stay
    lightweight.
    skillsr   )get_session_envHERMES_PLATFORMHERMES_SESSION_PLATFORMdisabledplatform_disabled)
r   setrc   r/   rN   gateway.session_contextr   ru   rv   _normalize_string_set)r`   rV   
skills_cfgr   resolved_platformglobal_disabledr   s          r!   get_disabled_skill_namesr   q  s     F uuH%%Jj$'' uu777777 	69&''	6?455 
 ,JNN:,F,FGGO N'^^,?@@FBKK
 
 ("%:;L%M%MMMr#   c                 j    | t                      S t          | t                    r| g} d | D             S )Nc                     h | ]D}t          |                                          #t          |                                          ES r   )r'   rP   )r   vs     r!   	<setcomp>z(_normalize_string_set.<locals>.<setcomp>  s9    ===qc!ffllnn=CFFLLNN===r#   )r   r/   r'   )valuess    r!   r   r     s=    ~uu&# ==F====r#   _EXTERNAL_DIRS_CACHEc                  T    t                                            t                       dS )u(   Test hook — drop the in-process cache.N)r   r   r   r   r#   r!   _external_dirs_cache_clearr     s&       r#   c                  P   t                      } |                                 sg S 	 |                                 }t          |           |j        f}n# t
          $ r d}Y nw xY w|+t                              |          }|t          |          S t                      }|sg S |                    d          }t          |t                    sg S |                    d          }|sg }|t          |          t          |<   |S t          |t                    r|g}t          |t                    sg S ddlm}  |            }	t                                                      }
t!                      }g }|D ]}t          |                                          }|s't$          j                            t$          j                            |                    }t-          |          }|                                s|	|z                                  }n|                                }||
k    r||v r|                                r+|                    |           |                    |           t6                              d|           |t          |          t          |<   |S )u3  Read ``skills.external_dirs`` from config.yaml and return validated paths.

    Each entry is expanded (``~`` and ``${VAR}``) and resolved to an absolute
    path.  Only directories that actually exist are returned.  Duplicates and
    paths that resolve to the local ``~/.hermes/skills/`` are silently skipped.

    Cached in-process, keyed on ``config.yaml`` mtime — the function is
    called once per skill during banner / tool-registry scans, and YAML
    parsing a non-trivial config dominates ``hermes`` cold-start time
    when the cache is absent.
    Nr   external_dirsr   )get_hermes_homez0External skills dir does not exist, skipping: %s)r
   r2   r   r'   r   r   r   rc   r^   r   r/   rN   ry   r   r   resolver   rP   ru   r*   
expanduser
expandvarsr   is_absoluteis_diraddappendr   r   )r   r   r   r   rV   r   raw_dirsr{   r   hermes_homelocal_skillsseenentryexpandedps                  r!   get_external_skills_dirsr     s    "##K 	!!&)+&6&68H%I		   			 %)))44<<F 	H%%Jj$'' 	~~o..H  .26ll +(C   :h%% 	000000!/##K!##++--LeeDF P PE

  "" 	7%%bg&8&8&?&?@@NN}} 	q))++AA		A9988:: 	PHHQKKKMM!LLKQOOOO*.v,,Y'Ms   *A A A c                  f    t                      g} |                     t                                 | S )u   Return all skill directories: local ``~/.hermes/skills/`` first, then external.

    The local dir is always first (and always included even if it doesn't exist
    yet — callers handle that).  External dirs follow in config order.
    )r   extendr   )dirss    r!   get_all_skills_dirsr     s0     DKK(**+++Kr#   
identifierc                    | pd                                 }|s|S t          |                                          }|                                s|                    d          S 	 ddlm} t          |j                  }n# t          $ r t                      }Y nw xY w|g}	 |
                    t                                 n# t          $ r Y nw xY w|D ]6}	 t          |                    |                    c S # t          $ r Y 3w xY w	 t          |                                                    |                                                    S # t          $ r  t                               d|           |cY S w xY w)a  Normalize a skill identifier to a ``skill_view()``-safe relative path.

    Slash commands and cron jobs may store absolute paths to skills that live
    under ``~/.hermes/skills/`` (including via symlinks) or configured
    ``skills.external_dirs``. ``skill_view()`` rejects absolute names for
    security, so callers must translate trusted absolute paths to their
    relative form first.
     /r   )skills_toolu~   Skill identifier %r is an absolute path outside trusted skills roots — passing through unchanged (skill_view will reject it))rP   r   r   r   lstriptoolsr   
SKILLS_DIRrO   r   r   r   r'   relative_to
ValueErrorr   r   r   )r   raw_identifieridentifier_path_skills_toolprimary_roottrusted_rootsroots          r!   normalize_skill_lookup_namer     s    !&B--//N >**5577O&&(( *$$S)))(555555L344 ( ( (%''( "NM5778888      	2248899999 	 	 	H	?**,,889M9M9O9OPPQQQ   N	
 	
 	

 sI   &B BB#!C 
CC!C>>
D
DAE 'E?>E?c                 0   t          | t                    r| nt          t          |                     }	 |                                                                S # t
          t          f$ r) |                                                                cY S w xY wr   )r/   r   r'   r   r   r   RuntimeErrorabsolute)r*   r3   s     r!   _resolve_for_skill_ownershipr   G  s    !$--Btt4D		??H0""$$,,...\" 0 0 0""$$--/////0s   %A 7BBc                     t          |           }t                      D ]9}t          |          }	 |                    |            dS # t          $ r Y 6w xY wdS )a  Return True when ``path`` lives under a configured external skills dir.

    ``skills.external_dirs`` are externally owned: Hermes can discover and view
    their skills, and foreground user-directed tool calls may still edit them,
    but autonomous lifecycle maintenance must treat them as read-only. This
    helper centralizes the ownership boundary so curator/reporting/tool paths do
    not each need to re-interpret the config.
    TF)r   r   r   r   )r*   	candidater   resolved_roots       r!   is_external_skill_pathr   O  sx     -T22I(**  4T::	!!-00044 	 	 	H	5s   A
AAc                 d   |                      d          }t          |t                    si }|                     d          pi }t          |t                    si }|                     dg           |                     dg           |                     dg           |                     dg           dS )z>Extract conditional activation fields from parsed frontmatter.metadatahermesfallback_for_toolsetsrequires_toolsetsfallback_for_toolsrequires_tools)r   r   r   r   )rc   r/   rN   )rR   r   r   s      r!   extract_skill_conditionsr   f  s    z**Hh%% \\(##)rFfd## !',CR!H!H#ZZ(;R@@$jj)=rBB **%5r::	  r#   c                    |                      d          }t          |t                    sg S |                     d          }t          |t                    sg S |                     d          }|sg S t          |t                    r|g}t          |t                    sg S g }t	                      }|D ]3}t          |t                    st          |                     dd                                                    }|r||v rUt          |                     dd                                                    }|s||d}	|                     d          }
|
|
|	d<   |                     d
          }t          |t
                    r,|                                r|                                |	d
<   n||	d
<   |                    |           |                    |	           5|S )a   Extract config variable declarations from parsed frontmatter.

    Skills declare config.yaml settings they need via::

        metadata:
          hermes:
            config:
              - key: wiki.path
                description: Path to the LLM Wiki knowledge base directory
                default: "~/wiki"
                prompt: Wiki directory path

    Returns a list of dicts with keys: ``key``, ``description``, ``default``,
    ``prompt``.  Invalid or incomplete entries are silently skipped.
    r   r   configrX   r   description)rX   r   defaultNprompt)	rc   r/   rN   r^   r   r'   rP   r   r   )rR   r   r   rawr{   r   itemrX   descr   r   prompt_texts               r!   extract_skill_config_varsr   z  s     z**Hh%% 	\\(##Ffd## 	
**X

C 	#t ec4   	#%FD  $%% 	$((5"%%&&,,.. 	cTkk488M2..//5577 	!
 !
 ((9%%&E)hhx((k3'' 	#K,=,=,?,? 	#)//11E(OO"E(OeMr#   c                  r   g } t                      }t                      }t                      D ]}|                                st	          |d          D ]}	 |                    d          }t          |          \  }}n# t          $ r Y 8w xY w|                    d          p|j	        j
        }t          |          |v rot          |          st          |          }	|	D ]N}
|
d         |vrBt          |          |
d<   |                     |
           |                    |
d                    O
| S )aY  Scan all enabled skills and collect their config variable declarations.

    Walks every skills directory, parses each SKILL.md frontmatter, and returns
    a deduplicated list of config var dicts.  Each dict also includes a
    ``skill`` key with the skill name for attribution.

    Disabled and platform-incompatible skills are excluded.
    r.   r   r   namerX   skill)r   r   r   r   iter_skill_index_filesr   rY   rO   rc   parentr   r'   rj   r   r   r   )all_vars	seen_keysr   
skills_dir
skill_filer   rR   _
skill_nameconfig_varsvars              r!   discover_all_skill_config_varsr     si    &(HUUI'))H)++ . .
  "" 	0ZHH 	. 	.J **G*<<!23!7!7QQ    %00JJ4E4JJ:(**)+66 3K@@K" . .u:Y..#&z??CLOOC(((MM#e*---	.	.( Os   (B
BBzskills.configr   
dotted_keyc                     |                     d          }| }|D ]&}t          |t                    r||v r	||         }$ dS |S )zPWalk a nested dict following a dotted key.  Returns None if any part is missing..N)rQ   r/   rN   )r   r   r$   rd   r    s        r!   _resolve_dotpathr     sZ    S!!EG  gt$$ 	dmGG44Nr#   r   c                    t                      }i }| D ]}|d         }t           d| }t          ||          }|)t          |t                    r*|                                s|                    dd          }t          |t                    rDd|v sd|v r<t          j        	                    t          j        
                    |                    }|||<   |S )aV  Resolve current values for skill config vars from config.yaml.

    Skill config is stored under ``skills.config.<key>`` in config.yaml.
    Returns a dict mapping **logical** keys (as declared by skills) to their
    current values (or the declared default if the key isn't set).
    Path values are expanded via ``os.path.expanduser``.
    rX   r   Nr   r   ~z${)r   SKILL_CONFIG_PREFIXr   r/   r'   rP   rc   ru   r*   r   r   )r   r   resolvedr   logical_keystorage_keyr9   s          r!   resolve_skill_config_valuesr    s     F!H & &%j,<<{<< 55=Zs33=EKKMM=GGIr**E eS!! 	Bse||tu}}G&&rw'9'9%'@'@AAE %Or#   <   c                     |                      dd          }|r4t          |                                                              d          ndS )z@Normalize a skill's description field for comparison/truncation.r   r   z'")rc   r'   rP   )rR   raw_descs     r!   _normalize_skill_descriptionr	    sE    }b11H19A3x==  &&u---rAr#   c                     t          |           }|sdS t          |          t          k    r|dt          dz
           dz   S |S )zCExtract a system-prompt-length description from parsed frontmatter.r   NrF   z...r	  lenSKILL_PROMPT_DESC_LIMITrR   r   s     r!   extract_skill_descriptionr    sO    '44D r
4yy***0,q001E99Kr#   c                 P    t          |           }t          |          t          k    S )zMTrue when the description will be truncated in the system prompt skill index.r  r  s     r!   )is_skill_description_truncated_for_promptr  !  s!    '44Dt99...r#   r   filenamec              #   J  K   t          |           }g }t          j        |d          D ]T\  }}}d|v fd|D             |dd<   ||v r3|                    t          j                            ||                     Ut          |          D ]}t          |          V  dS )a  Walk skills_dir yielding sorted paths matching *filename*.

    Excludes Hermes metadata, VCS, virtualenv/dependency, cache, and skill
    support directories. Support directories (references/templates/assets/
    scripts) can contain arbitrary markdown and even archived package
    ``SKILL.md`` files, but they are progressive-disclosure data loaded through
    ``skill_view(..., file_path=...)`` rather than active skill roots.
    T)followlinksr.   c                 <    g | ]}|t           vrr	|t          v |S r   )r   r1   )r   dhas_skill_mds     r!   
<listcomp>z*iter_skill_index_files.<locals>.<listcomp>7  sE     
 
 
+++! ,&'+=&=&=  '>&=&=r#   N)r'   ru   walkr   r*   joinsortedr   )	r   r  skills_dir_strmatchesr   r   filesr*   r  s	           @r!   r   r   *  s       __NGW^FFF 	9 	9dE!U*
 
 
 

 
 
QQQ uNN27<<h77888w  4jj r#   z^[a-zA-Z0-9_-]+$r   c                 X    d| vrd| fS t          |                     dd                    S )z~Split ``'namespace:skill-name'`` into ``(namespace, bare_name)``.

    Returns ``(None, name)`` when there is no ``':'``.
    rH   NrE   )tuplerQ   )r   s    r!   parse_qualified_namer!  H  s3    
 $TzC##$$$r#   r   c                 X    | sdS t          t                              |                     S )zDCheck whether *candidate* is a valid namespace (``[a-zA-Z0-9_-]+``).F)rx   _NAMESPACE_REmatch)r   s    r!   is_valid_namespacer%  R  s+     u##I..///r#   )r   Nr   )C__doc__loggingru   rJ   r_   r&   r   typingr   r   r   r   r   r	   ry   r
   r   r   	getLogger__name__r   rb   	frozensetr   r1   rx   r+   r)   r@   r'   rC   rY   rh   rj   r   rn   __annotations__r|   r   r   intr   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r   r  r  r	  r  r  r   compiler#  r!  r%  r   r#   r!   <module>r/     s      				 				 



       8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 G G G G G G G G G G		8	$	$
    i  . YOPP D    (4    : "s " " " "$.s .uT#s(^S-@'A . . . .h3 4    2ES#X E4 E E E EB  i : : :;; %' 4T	? ' ' '+S +T + + + +\$4S> $d $ $ $ $T AC 4c3m,d38n<= B B B   
 $sCx.        F# #sTz #SX # # # #L>SX > > > >  ;= d5c?DJ67 < < <   P$t* P P P PfT$Z    6C 6C 6 6 6 6r0$ 0 0 0 0D    .$sCx. T#t)_    (84S> 8d4S>>R 8 8 8 8v$T#s(^(< $ $ $ $T & 	T#s(^ 	 	 	 	 	d38n%	#s(^   @  Bd38n B B B B B4S> c    /4S> /d / / / /t s    6 
.//%s %uXc]C-?'@ % % % %0(3- 0D 0 0 0 0 0 0r#   