B
    îq\ã5  ã               @   sŒ   d 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
 ddlmZ e
dd„ ƒZG dd	„ d	eƒZG d
d„ deedZdS )zn
Implements the wrapper for the Astropy test runner in the form of the
``./setup.py test`` distutils command.
é    N)Úlog)Úcontextmanager)ÚCommandc           	   c   s<   t tjdƒ&} tj}| t_z
dV  W d|t_X W dQ R X dS )zš
    A context manager to temporarily disable stdout.

    Used later when installing a temporary copy of astropy to avoid a
    very verbose output.
    ÚwN)ÚopenÚosÚdevnullÚsysÚstdout)r   Z
old_stdout© r   ú4lib/python3.7/site-packages/astropy/tests/command.pyÚ_suppress_stdout   s    
r   c                   s    e Zd ZdZ‡ fdd„Z‡  ZS )ÚFixRemoteDataOptiona  
    This metaclass is used to catch cases where the user is running the tests
    with --remote-data. We've now changed the --remote-data option so that it
    takes arguments, but we still want --remote-data to work as before and to
    enable all remote tests. With this metaclass, we can modify sys.argv
    before distutils/setuptools try to parse the command-line options.
    c                sp   yt j d¡}W n tk
r$   Y nX dt j|< yt j d¡}W n tk
rT   Y nX dt j|< tƒ  |||¡S )Nz--remote-dataz--remote-data=anyz-Rz-R=any)r	   ÚargvÚindexÚ
ValueErrorÚsuperÚ__init__)ÚclsÚnameÚbasesZdctÚidx)Ú	__class__r   r   r   ,   s    

zFixRemoteDataOption.__init__)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Ú__classcell__r   r   )r   r   r   $   s   r   c               @   sv   e Zd ZdZdddddddd	d
dddddddddgZdZdd„ Zdd„ Zdd„ Zdd„ Z	dd„ Z
d%d d!„Zd"d#„ Zd$S )&ÚAstropyTestzRun the tests for this package)zpackage=ÚPz³The name of a specific package to test, e.g. 'io.fits' or 'utils'. Accepts comma separated string to specify multiple packages. If nothing is specified, all default tests are run.)z
test-path=ÚtaH  Specify a test location by path.  If a relative path to a  .py file, it is relative to the built package, so e.g., a  leading "astropy/" is necessary.  If a relative  path to a .rst file, it is relative to the directory *below* the --docs-path directory, so a leading "docs/" is usually necessary.  May also be an absolute path.)zverbose-resultsÚVz#Turn on verbose output from pytest.)zplugins=Úpz&Plugins to enable when running pytest.)z	pastebin=Úbz8Enable pytest pastebin output. Either 'all' or 'failed'.)zargs=Úaz,Additional arguments to be passed to pytest.)zremote-data=ÚRzZRun tests that download remote data. Should be one of none/astropy/any (defaults to none).)Úpep8Ú8zPEnable PEP8 checking and disable regular tests. Requires the pytest-pep8 plugin.)ÚpdbÚdz0Start the interactive Python debugger on errors.)ÚcoverageÚcz8Create a coverage report. Requires the coverage package.)z
open-filesÚozAFail if any tests leave files open.  Requires the psutil package.)z	parallel=Újz”Run the tests in parallel on the specified number of CPUs.  If "auto", all the cores on the machine will be used.  Requires the pytest-xdist plugin.)z
docs-path=NzŒThe path to the documentation .rst files.  If not provided, and the current directory contains a directory called "docs", that will be used.)z	skip-docsNz(Don't test the documentation .rst files.)zrepeat=NzPHow many times to repeat each test (can be used to check for sporadic failures).)z
temp-root=Nz°The root directory in which to create the temporary testing files. If unspecified the system default is used (e.g. /tmp) as explained in the documentation for tempfile.mkstemp.)zverbose-installNzOTurn on terminal output from the installation of astropy in a temporary folder.)ÚreadonlyNz7Make the temporary installation being tested read-only.Ú c             C   sp   d | _ d | _d| _d | _d | _d | _d| _d| _d| _d| _	d| _
d| _d | _d| _d | _d | _d| _d| _d S )NFZnoner   )ÚpackageZ	test_pathZverbose_resultsZpluginsZpastebinÚargsZremote_datar&   r(   r*   Z
open_filesÚparallelÚ	docs_pathZ	skip_docsÚrepeatÚ	temp_rootÚverbose_installr.   )Úselfr   r   r   Úinitialize_optionsz   s$    zAstropyTest.initialize_optionsc             C   s   d S )Nr   )r7   r   r   r   Úfinalize_optionsŽ   s    zAstropyTest.finalize_optionsc             C   sD   d}d}| j r*|  ¡ \}}||7 }||7 }d}d}|j|| ||dS )z9
        Build a Python script to run the tests.
        r/   z/import builtins; builtins._ASTROPY_TEST_ = Truea×  {cmd_pre}{0}; import {1.package_name}, sys; result = ({1.package_name}.test(package={1.package!r}, test_path={1.test_path!r}, args={1.args!r}, plugins={1.plugins!r}, verbose={1.verbose_results!r}, pastebin={1.pastebin!r}, remote_data={1.remote_data!r}, pep8={1.pep8!r}, pdb={1.pdb!r}, open_files={1.open_files!r}, parallel={1.parallel!r}, docs_path={1.docs_path!r}, skip_docs={1.skip_docs!r}, add_local_eggs_to_path=True, repeat={1.repeat!r})); {cmd_post}sys.exit(result))Úcmd_preÚcmd_post)r*   Ú_generate_coverage_commandsÚformat)r7   r:   r;   ZpreZpostZset_flagÚcmdr   r   r   Úgenerate_testing_command“   s    z$AstropyTest.generate_testing_commandc          	   C   sr  | j jr| j  | j j¡ | jdkr|| j  d¡ dd¡}|dk	rbtj |d ¡rbtj 	|d ¡| _ntj d¡r|tj 	d¡| _|  
¡  | j jrœ| j  | j j¡ tj d¡rÀt dtj | jd¡¡ | jrÜt d¡ | jdd	 zfy.|  ¡ }tjtjd
|g| jdd}| ¡ }W n2 tk
r>   ddl}| |j¡ | ¡ }Y nX W d| jrX| jdd	 t | j¡ X t |ƒ‚dS )z 
        Run the tests!
        NZ
build_docsZ
source_diré   Zdocsz.eggsz;changing permissions of temporary installation to read-onlyF)Úwritablez-c)ÚcwdZ	close_fdsr   T)!ÚdistributionZinstall_requiresZfetch_build_eggsr3   Zget_option_dictÚgetr   ÚpathÚexistsÚabspathÚ_build_temp_installZtests_requireÚshutilÚcopytreeÚjoinÚtesting_pathr.   r   ÚinfoÚ _change_permissions_testing_pathr?   Ú
subprocessÚPopenr	   Ú
executableÚwaitÚKeyboardInterruptÚsignalZsend_signalÚSIGINTZrmtreeÚtmp_dirÚ
SystemExit)r7   Zcfg_docs_dirr>   ZtestprocZretcoderT   r   r   r   Úrun·   s<    


zAstropyTest.runc          	   C   sÞ   t j| jd | jd}tj |¡| _t 	d 
| j¡¡ |  d¡ | j d¡}| j|_| jrf|  d¡ ntƒ  |  d¡ W dQ R X |  d¡}|j| _| jdk	rÌtj | jtj | j¡¡}t | j|¡ || _t d| j¡ dS )a  
        Install the package and to a temporary directory for the purposes of
        testing. This allows us to test the install command, include the
        entry points, and also avoids creating pyc and __pycache__ directories
        inside the build directory
        z-test-)ÚprefixÚdirz&installing to temporary directory: {0}ZinstallNz	setup.cfg)ÚtempfileZmkdtempÚpackage_namer5   r   rE   ÚrealpathrV   r   rM   r=   Zreinitialize_commandrC   Zget_command_objrY   r6   Zrun_commandr   Zget_finalized_commandZinstall_librL   r3   rK   ÚbasenamerI   rJ   Úcopy)r7   rV   Zinstall_cmdZnew_docs_pathr   r   r   rH   ÿ   s&    




zAstropyTest._build_temp_installFc             C   s†   |rt jt jB }nt j}xht | j¡D ]X\}}}x(|D ] }t tj ||¡|t j	B ¡ q6W x"|D ]}t tj ||¡|¡ q`W q&W d S )N)
ÚstatÚS_IRUSRÚS_IWUSRr   ÚwalkrL   ÚchmodrE   rK   ÚS_IXUSR)r7   rA   Zbasic_flagsÚrootÚdirsÚfilesÚdirnameÚfilenamer   r   r   rN   .  s    
 
z,AstropyTest._change_permissions_testing_pathc       	   	   C   s  | j dkrtdƒ‚yddl}W n tk
r:   tdƒ‚Y nX tj | j| j 	dd¡dd¡}t
|d	ƒ}| ¡ }W dQ R X | 	d
| j 	dd¡¡}tj | jd¡}t
|dƒ}| | d¡¡ W dQ R X d tj d¡tj |¡¡}d tj d¡tj | j¡¡}||fS )zf
        This method creates the post and pre commands if coverage is to be
        generated
        r   z*--coverage can not be used with --parallelNz;--coverage requires that the coverage package is installed.Ú.ú/ZtestsÚ
coveragercÚrz{packagename}Úwbzutf-8z\import coverage; cov = coverage.coverage(data_file=r"{0}", config_file=r"{1}"); cov.start();z	.coveragezicov.stop(); from astropy.tests.helper import _save_coverage; _save_coverage(cov, result, r"{0}", r"{1}");)r2   r   r*   ÚImportErrorr   rE   rK   rL   r\   Úreplacer   ÚreadrV   ÚwriteÚencoder=   rG   )	r7   r*   rm   ÚfdZcoveragerc_contentZtmp_coveragercZtmpr:   r;   r   r   r   r<   9  s.    
z'AstropyTest._generate_coverage_commandsN)F)r   r   r   ZdescriptionZuser_optionsr\   r8   r9   r?   rX   rH   rN   r<   r   r   r   r   r   ?   s6   $H/
r   )Ú	metaclass)r   r   r`   rI   rO   r	   r[   Z	distutilsr   Ú
contextlibr   Z
setuptoolsr   r   Útyper   r   r   r   r   r   Ú<module>   s   