L iQUdZddlmZddlZddlZddlZddlmZm Z ddl m Z ddl m Z ddlmZmZddlZddlmZdd lmZdd lmZdd lmZeeZd ed <ddZe GddZe GddZ d dZ!d!dZ"d!dZ#d!dZ$ d"dZ% d#dZ&d$dZ'd%dZ( d&dZ) d'dZ* d(dZ+ d) d*dZ,y)+aDiscovery utilities for Component v2 manifests in installed packages. The scanner searches installed distributions for a ``pyproject.toml`` with ``[tool.streamlit.component]`` configuration and extracts the component manifests along with their package roots. The implementation prioritizes efficiency and safety by filtering likely candidates and avoiding excessive filesystem operations. ) annotationsN)ThreadPoolExecutor as_completed) dataclass)Path)AnyFinal)utils)ComponentPathUtils)StreamlitComponentRegistryError) get_loggerr _LOGGERc&|jddS)aNormalize a distribution name to an importable package name. This helper converts hyphens to underscores to derive a best-effort importable module/package name from a distribution name. Parameters ---------- dist_name : str The distribution/project name (e.g., "my-awesome-component"). Returns ------- str The normalized package name suitable for import lookups (e.g., "my_awesome_component"). -_)replace) dist_names n/mnt/ssd/data/python-lab/Trading/venv/lib/python3.12/site-packages/streamlit/components/v2/manifest_scanner.py_normalize_package_namer-s"   S# &&c0eZdZUdZded<ded<ded<y)ComponentManifestzParsed component manifest data.strnameversionzlist[ComponentConfig] componentsN)__name__ __module__ __qualname____doc____annotations__rrrrAs) I L%%rrcVeZdZUdZded<dZded<ed dZed dZd d Z y) ComponentConfigzStructured configuration for a single component entry. Parameters ---------- name Component name as declared in ``pyproject.toml``. asset_dir Optional relative directory containing component assets. rrNz str | None asset_dirc|jd}t|tr|s td|jd}|t|ts tdt ||S)aCreate a ComponentConfig from a raw dict. Parameters ---------- config Raw component dictionary parsed from TOML. Returns ------- ComponentConfig Parsed and validated component configuration. rz-Component entry missing required 'name' fieldr%z'asset_dir' must be a string)rr%)get isinstancer ValueErrorr$)config name_valueasset_dir_values r from_dictzComponentConfig.from_dictYsfZZ' *c**LM M **[1  &z/3/O;< <%  rc tj|S#t$r }tj d|Yd}~yd}~wwxYw)zCBest-effort parse without raising; returns None on malformed input.z&Skipping malformed component entry: %sN)r$r- Exceptionrdebug)r*es r parse_or_nonezComponentConfig.parse_or_nonevs: ",,V4 4  MMBA F s A;Ac v|jytj|j||jz j}|j r|j s)t d|jd|jd|dtj||jd|S)a@Resolve and security-check the component's asset root directory. Parameters ---------- package_root : Path The root directory of the installed component package. Returns ------- Path | None Absolute, resolved path to the asset directory, or ``None`` if ``asset_dir`` is not declared. Raises ------ StreamlitComponentRegistryError If the declared directory does not exist, is not a directory, or resolves outside of ``package_root``. NzDeclared asset_dir 'z' for component 'z;' does not exist or is not a directory under package root 'z'.r%)abs_pathrootkind) r%r validate_path_securityresolveexistsis_dirr rensure_within_root)self package_root asset_roots rresolve_asset_rootz"ComponentConfig.resolve_asset_roots( >> ! 11$..A"T^^3<<>   "**;*;*=1&t~~&66G {SLLX>Y[]  --%%' r)r*dict[str, Any]returnr$)r*r@rAzComponentConfig | None)r=rrA Path | None) rrrr r!r% staticmethodr-r2r?r"rrr$r$JsC I Iz   8)rr$c|jj}d|jvr|jdjnd}d|vryd|vry |jjdxsg}|D]}|sd|jvsy |jdS#t$r }t j d|Yd}~5d}~wwxYw) aCheck if a package is likely to contain streamlit components before expensive operations. This early filter reduces the number of packages that need file I/O operations from potentially hundreds down to just a few candidates. Parameters ---------- dist : importlib.metadata.Distribution The package distribution to check. Returns ------- bool True if the package might contain streamlit components, False otherwise. Summary streamlitTz Requires-DistzFFailed to parse package metadata for streamlit component detection: %sN)z streamlit- streamlit_zst-st_)rlowermetadataget_allr/rr0 startswith)distrsummary requires_dist requirementr1s r&_is_likely_streamlit_component_packagerRs( 99?? D2;t}}2LdmmI&,,.RTGdg   --o>D" ( K{k.?.?.AA  ??E FF   TVW   s*&B":B" B"B"" C +CC cvt|jttfdfD]}||}||cSy)aFind ``pyproject.toml`` for a package. Handles both regular and editable installs. The function uses increasingly permissive strategies to locate the file while validating that the file belongs to the given distribution. Parameters ---------- dist : importlib.metadata.Distribution The package distribution to find pyproject.toml for. Returns ------- Path | None Path to the ``pyproject.toml`` file if found, otherwise ``None``. ct|SN)_pyproject_via_import_spec)d package_names rz._find_package_pyproject_toml..s,Q =rN)rr_pyproject_via_read_text_pyproject_via_dist_files)rNfinderresultrXs @r_find_package_pyproject_tomlr^sJ"+4995L !!=   M rct|j} t|dr|jd}|r|jr|jD]}dt |vsdt |vs t t |j|}|j}||jfD]5}|dz }|jst||j|s1|ccSyy#t$rYwxYw#t$rYywxYw)zLocate pyproject.toml using the distribution's read_text + nearby files. This works for many types of installations including some editable ones. read_textpyproject.toml __init__.pyz.pyN) rrhasattrr`filesrr locate_fileparentr9_validate_pyproject_for_packager/)rNrXpyproject_contentfile file_path current_dir search_dirpyproject_paths rrZrZs +4995L 4 % $/? @  TZZ!JJ%D$D 1Uc$i5G%(,S1A1A$1G-H(II*3*:*:K/:KN1N$2$9$9$;(G(6(, (4)& ,:$9 :" 1%0  )%$% sUAC5-AC&C&C&C5!C&"C5$C5& C2/C51C22C55 DDcNt|j}t|dd}|sy|D]l}t|dddk(st|j ds. t t|j |}t||j|r|cSny#t$rY{wxYw)z?Locate pyproject.toml by scanning the distribution's file list.rdNrra) rrgetattrrendswithrrergr/)rNrXrdrirms rr[r[$s*4995L D'4 (E   4 &*: :c$i>P>P ?  !%c$*:*:4*@&A!B2"II  *)     s;B B$#B$cD tjj|}|ro|jrct |jj }||j fD]3}|dz }|j st||j|s1|cSy#t$rYywxYw)zLocate pyproject.toml by resolving the import spec and checking nearby. For editable installs, try the package directory and its parent only. raN) importlibutil find_specoriginrrfr9rgrr/)rNrXspec package_dirrlrms rrVrV;s ~~'' 5 DKKt{{+22K*K,>,>? * !+.>!>!((*/N"II 0 *) *  s$A2B5B BB BBc t|d5}tj|}dddd}dvrd|dvr|dd}|s d|vrd|dvrd|ddvr |ddd}|rEtj|}tj|}tj|}|||fvSy #1swYxYw#t $r"} t jd ||| Yd} ~ y d} ~ wwxYw) aValidate that a ``pyproject.toml`` file belongs to the specified package. Parameters ---------- pyproject_path : Path Path to the pyproject.toml file to validate. dist_name : str The distribution name (e.g., "streamlit-bokeh"). package_name : str The package name (e.g., "streamlit_bokeh"). Returns ------- bool True if the file belongs to this package, False otherwise. utf-8encodingNprojectrtool setuptoolsz package-nameFz0Error validating pyproject.toml at %s for %s: %s)opentomlloadpackaging_utilscanonicalize_namer/rr0) rmrrXfpyproject_data project_namecanonical_projectcanonical_distcanonical_packager1s rrgrgSs$&+ .7 3 *q!YYq\N *   &6^I5N+N))4V>yIN / A A, O %9J(KK KC * *F  >    s. B8B,BB8,B51B88 C#CC#c t|d5}tj|cdddS#1swYyxYw#t$r!}tj d||Yd}~yd}~wwxYw)zJLoad and parse a pyproject.toml, returning parsed data or None on failure.ryrzNz(Failed to parse pyproject.toml at %s: %s)rrrr/rr0)rmrr1s r_load_pyprojectrsW .7 3 q99Q<    @.RSTs) :. :7:: A$AA$c|jdijdijd}|sy|jd}t|tsy|Dcgc]}t|ts|}}|sy|Scc}w)zGExtract raw component dicts from pyproject data; return None if absent.r}rG componentNr)r'r(listdict)rstreamlit_componentraw_componentsitemr]s r_extract_componentsrs 62&**;;?? L (,,\:N nd +($:dD+A$F$  M $s A<1A<c>d} tjj|}|r+|jrt |jj }t|dd}|sV|rT|D]O}|t|vsdt|vs t t|j|}|j }n|s |j }|S#t $r!}tjd||Yd}~d}~wwxYw#t $r!}tjd||Yd}~d}~wwxYw)z2Resolve the package root directory with fallbacks.Nz9Failed to resolve package root via import spec for %s: %srdrbz8Failed to resolve package root via dist files for %s: %s) rrrsrtrurrfr/rr0rorre) rNrXrmr=rvr1rdri init_paths r_resolve_package_rootrs!%L  ~~'' 5 DKK ,33L D'4 (E E Ds4y(]c$i-G  $S)9)9$)?%@ AI#,#3#3L  %,, 3   G     !MMR$s0A C/C2 C/C**C/2 D;DDc|jdi}|jdxs |j}|jdxs|jxsd}||fS)z4Derive project name and version with safe fallbacks.r|rrz0.0.0)r'rr)rrN project_table derived_namederived_versions r_derive_project_metadatarsX#&&y"5M $$V,9 L#'' 2MdllMgO  ((rc  t|}|syt|}|yt|}|syt|j}t |||}t ||\}}|Dcgc]}tj|x} | } }| syt||| } | |fScc}w#t$r,} tjdt|dd| Yd} ~ yd} ~ wwxYw)aProcess a single package to extract component manifest. This function is designed to be called from a thread pool for parallel processing. Parameters ---------- dist : importlib.metadata.Distribution The package distribution to process. Returns ------- tuple[ComponentManifest, Path] | None The manifest and package root if found, otherwise ``None``. N)rrrz/Unexpected error processing distribution %s: %srz )r^rrrrrrr$r2rr/rr0ro) rNrmrrrXr=rrcompparsedparsed_componentsmanifestr1s r_process_single_packagers")5d;(8  !,^<.tyy9 ,T<P (@QU(V% o'4 )77==J 4 4 !$#(  ,''4 "  = D&+ .   s> B B B5B! BBBB C&"C  Ccg}ttjj}|s|S|Dcgc]}t |r|}}t j dt|t||s|S|%tdtjxsddz}t|t|d}t j dt||t|5}|Dcic]#}|jt||j%}}t|D]&}|j!}|s|j#|( dddt j d t||Scc}wcc}w#1swY4xYw) a%Scan installed packages for Streamlit component metadata. Uses parallel processing to improve performance in environments with many installed packages. Applies early filtering to only check packages likely to contain streamlit components. Parameters ---------- max_workers : int or None Maximum number of worker threads. If None, uses min(32, (os.cpu_count() or 1) + 4). Returns ------- list[tuple[ComponentManifest, Path]] List of tuples of manifests and their package root paths. zAFiltered %d packages down to %d candidates for component scanningN zNScanning %d candidate packages for component manifests using %d worker threads) max_workersz"Found %d component manifests total)rrrrK distributionsrRrr0lenminos cpu_countrsubmitrrrr]append) r manifestsall_distributionsrNcandidate_distributionsexecutorfuture_to_distfuturer]s rscan_component_manifestsrs(79IY//==?@  &  1$ 7   MMK  #$ #"r||~2a78 S012K MMX #$  4 )0  OO3T :DII E  #>2 )F]]_F  ( ) ) MM6IG [B  ) )s)E+E5#(E0 "E5.E50E55E>)rrrAr)rNimportlib.metadata.DistributionrAbool)rNrrArB)rNrrXrrArB)rmrrrrXrrAr)rmrrAzdict[str, Any] | None)rr@rAzlist[dict[str, Any]] | None)rNrrXrrmrrAr)rr@rNrrAztuple[str, str])rNrrAz%tuple[ComponentManifest, Path] | NonerU)rz int | NonerAz$list[tuple[ComponentManifest, Path]])-r __future__rimportlib.metadatarrimportlib.utilrconcurrent.futuresrr dataclassesrpathlibrtypingrr r packagingr r,streamlit.components.v2.component_path_utilsr streamlit.errorsr streamlit.loggerr rrr!rrr$rRr^rZr[rVrgrrrrrrr"rrrsj# ?! .K<'H%%'( && & ]] ]@/G )/G /Gd@$N. )9<0>>%(>8;> >B&" )"9<"NR" "J)")*I)): ):*:|#JJ)Jr