o
    
_d:                     @   s   d dl mZ d dlmZ d dlmZ d dlm  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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 dd	lmZ d
d ZG dd dejZdd ZG dd dZ dS )    )partial)glob)convert_pathN)Path)DictIterableIteratorListOptionalTuple   )unique_everseen)SetuptoolsDeprecationWarningc                 C   s   t | t | jtjB  d S N)oschmodstatst_modeS_IWRITE)target r   ;lib/python3.10/site-packages/setuptools/command/build_py.pymake_writable   s   r   c                       sF  e Zd ZU dZdZeed< dZee	 ed< dd Z
	d6 fd	d
	Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd7dee	 f fddZdee	e	f fddZdeee	e	f  fddZdeee	e	f  fd d!Zd"d# Zd$d% Zd&ee	 d'e	dee	 fd(d)Zd*d+ Zd,d- Z d.d/ Z!d0d1 Z"d2d3 Z#e$d4d5 Z%  Z&S )8build_pyaX  Enhanced 'build_py' command that includes data files with packages

    The data files are specified via a 'package_data' argument to 'setup()'.
    See 'setuptools.dist.Distribution' for more details.

    Also, this version of the 'build_py' command allows you to specify both
    'py_modules' and 'packages' in the same setup operation.
    Feditable_modeNexisting_egg_info_dirc                 C   s@   t j|  | jj| _| jjpi | _d| jv r| jd= g | _d S )N
data_files)origr   finalize_optionsdistributionpackage_dataexclude_package_data__dict___build_py__updated_filesselfr   r   r   r   $   s   


zbuild_py.finalize_options   c                    s:   |rt t| }t t| }t ||||||S r   )strr   resolvesuper	copy_file)r%   ZinfileoutfileZpreserve_modeZpreserve_timeslinklevel	__class__r   r   r*   ,   s   zbuild_py.copy_filec                 C   sT   | j s| jr	| jrdS | j r|   | jr|   |   | tjj	| dd dS )z?Build modules, packages, and copy data files to build directoryNr   )include_bytecode)
Z
py_modulespackagesr   Zbuild_modulesZbuild_packagesbuild_package_dataZbyte_compiler   r   get_outputsr$   r   r   r   run7   s   zbuild_py.runc                 C   s&   |dkr|   | _| jS tj| |S )zlazily compute data filesr   )_get_data_filesr   r   r   __getattr__)r%   attrr   r   r   r6   G   s   
zbuild_py.__getattr__c                 C   s.   t j| |||\}}|r| j| ||fS r   )r   r   build_moduler#   append)r%   modulemodule_filepackager+   Zcopiedr   r   r   r8   N   s   zbuild_py.build_modulec                 C   s   |    tt| j| jpdS )z?Generate list of '(package,src_dir,build_dir,filenames)' tuplesr   )analyze_manifestlistmap_get_pkg_data_filesr1   r$   r   r   r   r5   T   s   zbuild_py._get_data_filesc                 C   s$   | j di  tt| j| jpdS )z
        Generate list of ``(package,src_dir,build_dir,filenames)`` tuples,
        but without triggering any attempt to analyze or build the manifest.
        manifest_filesr   )r"   
setdefaultr>   r?   r@   r1   r$   r   r   r   get_data_files_without_manifestY   s   z(build_py.get_data_files_without_manifestc                    sJ   |  | tjj| jg|d  } fdd| | D }| ||fS )N.c                    s   g | ]	}t j| qS r   )r   pathrelpath).0filesrc_dirr   r   
<listcomp>k   s    z0build_py._get_pkg_data_files.<locals>.<listcomp>)get_package_dirr   rE   join	build_libsplitfind_data_files)r%   r<   	build_dir	filenamesr   rI   r   r@   c   s   


zbuild_py._get_pkg_data_filesc                 C   s`   |  | j||}tttdd|}tj|}tt	j
j|}t| j|g |}| |||S )z6Return filenames for package's data files in 'src_dir'T)	recursive)_get_platform_patternsr    r?   r   r   	itertoolschainfrom_iterablefilterr   rE   isfilerA   getexclude_data_files)r%   r<   rJ   patternsZglobs_expandedZglobs_matchesZ
glob_filesfilesr   r   r   rP   q   s   zbuild_py.find_data_filesreturnc                    s"   | j rt|   S t |S )1See :class:`setuptools.commands.build.SubCommand`)r   r>   get_output_mappingkeysr)   r3   )r%   r0   r.   r   r   r3      s   zbuild_py.get_outputsc                 C   s(   t |  |  }tt|dd dS )r_   c                 S   s   | d S )Nr   r   )xr   r   r   <lambda>   s    z-build_py.get_output_mapping.<locals>.<lambda>)key)rU   rV    _get_package_data_output_mapping_get_module_mappingdictsorted)r%   mappingr   r   r   r`      s
   zbuild_py.get_output_mappingc                 c   s>    |   D ]\}}}|d}| | j||}||fV  qdS )z5Iterate over all modules producing (dest, src) pairs.rD   N)Zfind_all_modulesrO   Zget_module_outfilerN   )r%   r<   r:   r;   filenamer   r   r   rf      s   
zbuild_py._get_module_mappingc                 c   sJ    | j D ]\}}}}|D ]}tj||}tj||}||fV  qqdS )z6Iterate over package data producing (dest, src) pairs.N)r   r   rE   rM   )r%   r<   rJ   rQ   rR   rj   r   srcfiler   r   r   re      s   z)build_py._get_package_data_output_mappingc                 C   s@   |   D ]\}}| tj| | ||\}}t| qdS )z$Copy data files into build directoryN)re   Zmkpathr   rE   dirnamer*   r   )r%   r   rk   Z_outfZ_copiedr   r   r   r2      s
   
zbuild_py.build_package_datac                 C   sp  i  | _ }| jjsd S i }| jpdD ]}||t| |< qt| dd r=t| jd	 r=| j}t|d}|j
dd }n| d | d}|j}|jj}t }| ||D ]^}	tjt|	\}
}d }|}|
r|
|kr|
|vr|
}tj|
\}
}tj||}|
r|
|kr|
|vsq|
|v r||kr||rqWn|||
 |}|r|| |||
 g |	 qWd S )Nr   r   zSOURCES.txtzutf-8)encodingegg_info)rA   r   Zinclude_package_datar1   assert_relativerL   getattrr   r   exists	read_text
splitlinesZrun_commandget_finalized_commandrn   Zfilelistr]   _IncludePackageDataAbuse_filter_build_filesr   rE   rO   rM   	is_moduleimportable_subpackagewarnrB   r9   )r%   ZmfZsrc_dirsr<   Zegg_info_dirZmanifestr]   Zei_cmdcheckrE   dfprevZoldfZdf
importabler   r   r   r=      sL   






zbuild_py.analyze_manifestr]   rn   c                 #   sn    |  d}|| j|j|jf}dd |D }|D ]}tj| tj|r1t fdd|D r4|V  qdS )a}  
        ``build_meta`` may try to create egg_info outside of the project directory,
        and this can be problematic for certain plugins (reported in issue #3500).

        Extensions might also include between their sources files created on the
        ``build_lib`` and ``build_temp`` directories.

        This function should filter this case of invalid files out.
        buildc                 S   s   g | ]
}|rt j|qS r   )r   rE   normpath)rG   pr   r   r   rK      s    z0build_py._filter_build_files.<locals>.<listcomp>c                 3   s    | ]}| vV  qd S r   r   )rG   r{   Z	norm_pathr   r   	<genexpr>   s    z/build_py._filter_build_files.<locals>.<genexpr>N)	rt   rN   Z
build_tempZ
build_baser   rE   r   isabsall)r%   r]   rn   r   Z
build_dirsZ	norm_dirsrH   r   r   r   rv      s   

"zbuild_py._filter_build_filesc                 C   s   d S r   r   r$   r   r   r   get_data_files   s   zbuild_py.get_data_filesc                 C   s   z| j | W S  ty   Y nw tj| ||}|| j |< |r#| jjs%|S | jjD ]}||ks6||d r8 nq)|S t	|d}|
 }W d   n1 sPw   Y  d|vrbtjd|f |S )z8Check namespace packages' __init__ for declare_namespacerD   rbNs   declare_namespacezNamespace package problem: %s is a namespace package, but its
__init__.py does not call declare_namespace()! Please fix it.
(See the setuptools manual under "Namespace Packages" for details.)
")packages_checkedKeyErrorr   r   check_packager   Znamespace_packages
startswithioopenread	distutilserrorsZDistutilsError)r%   r<   Zpackage_dirZinit_pypkgr|   contentsr   r   r   r      s0   

zbuild_py.check_packagec                 C   s"   i | _ tj|  d| _d | _d S )NF)r   r   r   initialize_optionsr   r   r$   r   r   r   r     s   
zbuild_py.initialize_optionsc                 C   s0   t j| |}| jjd urtj| jj|S |S r   )r   r   rL   r   Zsrc_rootr   rE   rM   )r%   r<   resr   r   r   rL   	  s   zbuild_py.get_package_dirc                    s\   t | | j||}fdd|D }tj|}t|  fddD }t t|S )z6Filter filenames for package's data files in 'src_dir'c                 3   s    | ]	}t  |V  qd S r   )fnmatchrX   rG   pattern)r]   r   r   r         z.build_py.exclude_data_files.<locals>.<genexpr>c                 3   s    | ]	}| vr|V  qd S r   r   )rG   fn)badr   r   r     r   )r>   rT   r!   rU   rV   rW   setr   )r%   r<   rJ   r]   r\   Zmatch_groupsmatchesZkeepersr   )r   r]   r   r[     s   zbuild_py.exclude_data_filesc                    s.   t | dg | |g } fdd|D S )z
        yield platform-specific path patterns (suitable for glob
        or fn_match) from a glob-based spec (such as
        self.package_data or self.exclude_package_data)
        matching package in src_dir.
         c                 3   s"    | ]}t j t|V  qd S r   )r   rE   rM   r   r   rI   r   r   r   +  s
    
z2build_py._get_platform_patterns.<locals>.<genexpr>)rU   rV   rZ   )specr<   rJ   Zraw_patternsr   rI   r   rT     s   


zbuild_py._get_platform_patterns)r&   r&   Nr&   )r&   )'__name__
__module____qualname____doc__r   bool__annotations__r   r
   r'   r   r*   r4   r6   r8   r5   rC   r@   rP   r	   r3   r   r`   r   r   rf   re   r2   r=   r   rv   r   r   r   rL   r[   staticmethodrT   __classcell__r   r   r.   r   r      s8   
 		
)r   c                 C   s6   t j| s| S ddlm} td |  }||)Nr   )DistutilsSetupErrorz
        Error: setup script specifies an absolute path:

            %s

        setup() arguments must *always* be /-separated paths relative to the
        setup.py directory, *never* absolute paths.
        )r   rE   r   distutils.errorsr   textwrapdedentlstrip)rE   r   msgr   r   r   ro   2  s   	ro   c                   @   s@   e Zd ZdZG dd deZdd Zdd Zdd	 Zd
d Z	dS )ru   z>Inform users that package or module is included as 'data file'c                   @   s   e Zd ZdZdZdS )z!_IncludePackageDataAbuse._WarningzU
        Package {importable!r} is absent from the `packages` configuration.
        a|  
        ############################
        # Package would be ignored #
        ############################
        Python recognizes {importable!r} as an importable package[^1],
        but it is absent from setuptools' `packages` configuration.

        This leads to an ambiguous overall configuration. If you want to distribute this
        package, please make sure that {importable!r} is explicitly added
        to the `packages` configuration field.

        Alternatively, you can also rely on setuptools' discovery methods
        (for example by using `find_namespace_packages(...)`/`find_namespace:`
        instead of `find_packages(...)`/`find:`).

        You can read more about "package discovery" on setuptools documentation page:

        - https://setuptools.pypa.io/en/latest/userguide/package_discovery.html

        If you don't want {importable!r} to be distributed and are
        already explicitly excluding {importable!r} via
        `find_namespace_packages(...)/find_namespace` or `find_packages(...)/find`,
        you can try to use `exclude_package_data`, or `include-package-data=False` in
        combination with a more fine grained `package-data` configuration.

        You can read more about "package data files" on setuptools documentation page:

        - https://setuptools.pypa.io/en/latest/userguide/datafiles.html


        [^1]: For Python, any directory (with suitable naming) can be imported,
              even if it does not contain any `.py` files.
              On the other hand, currently there is no concept of package data
              directory, all directories are treated like packages.
        N)r   r   r   Z_SUMMARYZ_DETAILSr   r   r   r   _WarningJ  s    r   c                 C   s   t  | _d S r   )r   _already_warnedr$   r   r   r   __init__u  s   z!_IncludePackageDataAbuse.__init__c                 C   s    | do|d td   S )Nz.py)endswithlenisidentifier)r%   rH   r   r   r   rw   x  s    z"_IncludePackageDataAbuse.is_modulec                 C   s6   t |j}tttj|j}|rd|g|S d S )NrD   )	r   parentr>   rU   	takewhiler'   r   partsrM   )r%   r   rH   r   r   r   r   r   rx   {  s
   
z._IncludePackageDataAbuse.importable_subpackagec                 C   s,   || j vr| jj|d | j | d S d S )N)r~   )r   r   emitadd)r%   r~   r   r   r   ry     s   
z_IncludePackageDataAbuse.warnN)
r   r   r   r   r   r   r   rw   rx   ry   r   r   r   r   ru   G  s    +ru   )!	functoolsr   r   Zdistutils.utilr   Zdistutils.command.build_pyZcommandr   r   r   r   r   r   r   r   rU   r   pathlibr   typingr   r   r   r	   r
   r   Zextern.more_itertoolsr   warningsr   r   ro   ru   r   r   r   r   <module>   s*       