o nnh+@sdZddlmZddlmZddlZddlZddlZ ddl m Z m Z m Z mZmZmZmZmZddlmZmZmZddlmZddlmZdd lmZdd lmZdd lm Z m!Z!dd l"m#Z#ej$d dGdddZ%GdddZ&edddZ'ej$d dGdddZ(edddZ)dS)z?Context information for the current invocation of ansible-test.) annotationsN)ApplicationErrorimport_plugins is_subdirANSIBLE_LIB_ROOTANSIBLE_TEST_ROOTANSIBLE_SOURCE_ROOTdisplaycache)find_path_providerget_path_provider_classesProviderNotFoundForPath)SourceProvider)UnversionedSource)InstalledSource)UnsupportedSource) ContentLayoutLayoutProvider)UnsupportedLayoutT)frozenc@s"eZdZUdZded<ded<dS) PayloadConfigzEConfiguration required to build a source tree payload for delegation.zlist[tuple[str, str]]fileszdict[str, int] permissionsN__name__ __module__ __qualname____doc____annotations__r r F/usr/local/lib/python3.10/dist-packages/ansible_test/_internal/data.pyr4s  rc@sfeZdZdZd"ddZd#ddZed$ddZddZe d%ddZ d&ddZ d"ddZ d'dd Z d!S)( DataContextzXData context providing details about the current execution environment for ansible-test.returnNonecCstjd}t}tt}tt}||_||_d|_ g|_ |r+| |||d\}}nt r=t |t r=| ||t d\}}n | |||d\}}||_||_dS)NANSIBLE_TEST_CONTENT_ROOTFT)osenvirongetgetcwdr rr_DataContext__layout_providers_DataContext__source_providers_DataContext__ansible_sourcepayload_callbacks#_DataContext__create_content_layoutr rcontentsource_provider)self content_path current_pathlayout_providerssource_providersr/r0r r r!__init__?s  zDataContext.__init__list[ContentLayout]c s|j}|j}|s gStj|jdtjdddtfddt D}g}|D]X}tj|tfddt D}|D]>}tj|}|tj|j|j kr]|} n | |j |j |dd } t| } | srqFtjd | jj| fdd|| qFq-|S) z Return a list of collection layouts, one for each collection in the same collection root as the current collection layout. An empty list is returned if the current content layout is not a collection layout. ansible_collectionszScanning collection root: %sr) verbosityc3*|]}tjtj|r|VqdSNr&pathisdirjoin.0name) root_pathr r! c(z8DataContext.create_collection_layouts..c3r:r;r<r@)namespace_pathr r!rDhrEFrz#Including collection: %s (%d files))r/ collectionr&r=r?rootr infosortedlistdir directoryr.r*r+len all_files full_nameappend) r1layoutrGnamespace_names collectionsnamespace_namecollection_namescollection_namecollection_pathcollection_layout file_countr )rFrCr!create_collection_layoutsVs.  z%DataContext.create_collection_layoutsr4list[t.Type[LayoutProvider]]r5list[t.Type[SourceProvider]]rHstrwalkbool&t.Tuple[ContentLayout, SourceProvider]cCsz tt|||}Wn tyt|}Ynwzt|tr#t|j}ntt||j|}Wnty:t|j}Ynw| |j| |j}||fS)z@Create a content layout using the given providers and root path.) r rrr isinstancerrHrrcreate get_paths)r4r5rHr^layout_providerr0rQr r r!__create_content_layout|s     z#DataContext.__create_content_layoutcsts0g}tt|fddjDtt|fddjDt|Sjj rBtfddj DSz t t j tdWn tyYttYnwtfddjDS)MReturn a tuple of Ansible source files with both absolute and relative paths.c3s0|]}tjj|tjdd|fVqdS)libansibleNr&r=r?rHrAr=r0r r!rDs(z6DataContext.__create_ansible_source..c3s2|]}tjj|tjddd|fVqdS)testrg ansible_testNrirjrkr r!rDs*c3s&|]}tjjj||fVqdSr;)r&r=r?r/rHrjr1r r!rDs$Fc3s$|] }tjj||fVqdSr;rirjrkr r!rDs")r rrextendrcrHrtupler/ is_ansiblerNr rr+rr)r1sourcesr )r1r0r!__create_ansible_sources&    z#DataContext.__create_ansible_sourcetuple[tuple[str, str], ...]cCs|js||_|jS)rf)r,#_DataContext__create_ansible_sourcernr r r!ansible_sources zDataContext.ansible_sourcecallback!c.Callable[[PayloadConfig], None]cCs|j|dS)z$Register the given payload callback.N)r-rP)r1rwr r r!register_payload_callbacksz%DataContext.register_payload_callbackcCs|jjr t|dS)z-Report an error if the layout is unsupported.N)r/ unsupportedrexplain_working_directoryrnr r r! check_layouts zDataContext.check_layoutcCsddg}tr|dtd|dt}|d|d|d|d|d|dtjtj|d krO|d tj|d n tj|d kra|d |d nd |tjjvro|d t |j j t r}| |j j d |}|S)z?Return a message explaining the working directory requirements.zJThe current working directory must be within the source tree being tested.zTesting Ansible: /zRTesting an Ansible collection: {...}/ansible_collections/{namespace}/{collection}/zNExample #1: community.general -> ~/code/ansible_collections/community/general/zTExample #2: ansible.util -> ~/.ansible/collections/ansible_collections/ansible/util/zCurrent working directory: r8zExpected parent directory: z/{namespace}/{collection}/z4No "ansible_collections" parent directory was found. )r rPr&r)r=basenamedirnamesplitseprar/rzlistror?)r1blockscwdmessager r r!r{s,       z%DataContext.explain_working_directoryN)r#r$)r#r7) r4r[r5r\rHr]r^r_r#r`)r#rt)rwrxr#r$)r#r])rrrrr6rZ staticmethodr.rupropertyrvryr|r{r r r r!r"<s  &    r"r#cCs$d}|D]}td|qt}|S)zInitialize provider plugins.)rQsourcez provider/%s)rr")provider_types provider_typecontextr r r! data_contexts rc@s*eZdZUdZded<ded<ded<dS) PluginInfoz$Information about an Ansible plugin.r] plugin_typerBz list[str]pathsNrr r r r!rs  r dict[str, dict[str, PluginInfo]]c si}tjjD]n\}ttj|}t|tj j }i}|D]F}tj |}|tj j |d}|dkr@dkr?q#ntj |d}tjj rVdkrV|d}||d|}||g|q#fdd |D|<q |S) z Analyze content. The primary purpose of this analysis is to facilitate mapping of integration tests to the plugin(s) they are intended to test. z __init__.py module_utilsrmodules_.cs i|] \}}|t||dqS))rrBr)r)rA plugin_namerrr r! s z#content_plugins..)rr/ plugin_pathsitemsrJ walk_filesrMrr&r=rrsplitextrqlstriprPr? setdefault) pluginsplugin_directoryrplugin_directory_offset plugin_files plugin_pathplugin_filename plugin_partsrr rr!content_pluginss,      r)r#r")r#r)*r __future__rcollections.abcabcc dataclassesr&typingtutilrrrrrr r r providerr r rprovider.sourcerprovider.source.unversionedrprovider.source.installedrprovider.source.unsupportedrprovider.layoutrrprovider.layout.unsupportedr dataclassrr"rrrr r r r!s0  (      *