B
    dW                 @   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ZddlZddl	Z	ddl
mZ ddlmZ ddlmZ ddlmZmZ ddlmZ ddlmZmZ d	d
dgZG dd dZG dd
 d
ZG dd	 d	eZdS )zHImplements the Astropy TestRunner which is a thin wrapper around pytest.    N)OrderedDict)	find_spec)wraps)set_temp_configset_temp_cache)find_current_module)AstropyWarningAstropyDeprecationWarning
TestRunnerTestRunnerBasekeywordc               @   s"   e Zd ZdZdddZdd ZdS )	r   a9  
    A decorator to mark a method as keyword argument for the ``TestRunner``.

    Parameters
    ----------
    default_value : `object`
        The default value for the keyword argument. (Default: `None`)

    priority : `int`
        keyword argument methods are executed in order of descending priority.
    Nr   c             C   s   || _ || _d S )N)default_valuepriority)selfr   r    r   a/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/astropy/tests/runner.py__init__$   s    zkeyword.__init__c                s(    fdd}| j |_| j|_ j|_|S )Nc                 s
    | |S )Nr   )argskwargs)fr   r   r   )   s    z!keyword.__call__.<locals>.keyword)r   _default_valuer   	_priority__doc__)r   r   r   r   )r   r   __call__(   s
    zkeyword.__call__)Nr   )__name__
__module____qualname__r   r   r   r   r   r   r   r      s   
c                   sd   e Zd ZdZdd Z fddZdd ZdZd	d
ddgZdZ	e
dd Zdd Ze
dd Z  ZS )r   a  
    The base class for the TestRunner.

    A test runner can be constructed by creating a subclass of this class and
    defining 'keyword' methods. These are methods that have the
    :class:`~astropy.tests.runner.keyword` decorator, these methods are used to
    construct allowed keyword arguments to the
    ``run_tests`` method as a way to allow
    customization of individual keyword arguments (and associated logic)
    without having to re-implement the whole
    ``run_tests`` method.

    Examples
    --------

    A simple keyword method::

        class MyRunner(TestRunnerBase):

            @keyword('default_value'):
            def spam(self, spam, kwargs):
                """
                spam : `str`
                    The parameter description for the run_tests docstring.
                """
                # Return value must be a list with a CLI parameter for pytest.
                return ['--spam={}'.format(spam)]
    c             C   s   t j|| _d S )N)ospathabspath	base_path)r   r    r   r   r   r   S   s    zTestRunnerBase.__init__c       	   	      s   t j| t jd}tdd |}t|dd dd}t | _d}xl|D ]d\}}y|d dd tkr^wBW n tk
rt   Y nX |j	| j|< |j
rB|d	7 }||j
 7 }|d
7 }qBW | jj|d| j_
t | S )N)	predicatec             S   s   | d j dkS )N   r   )r   )funcr   r   r   <lambda>h       z(TestRunnerBase.__new__.<locals>.<lambda>c             S   s
   | d j S )Nr"   )r   )xr   r   r   r$   j   r%   T)keyreverse Fz        z

)keywords)inspect
getmembers
isfunctionfiltersortedr   r*   NotImplemented	Exceptionr   r   stripRUN_TESTS_DOCSTRINGformat	run_testssuper__new__)	clsr   r   Z	functionsr*   Zsorted_keywordsZdoc_keywordsnamer#   )	__class__r   r   r7   V   s$    zTestRunnerBase.__new__c             K   s~   t | j}|| g }x^| D ]R}t| |}||| |}|tkrVtd| t|t	snt| d||7 }q$W |S )Nz/run_tests() got an unexpected keyword argument z" keyword method must return a list)
copydeepcopyr*   updatekeysgetattrr0   	TypeError
isinstancelist)r   r   r*   r   r   r#   resultr   r   r   _generate_args   s    


zTestRunnerBase._generate_argsz
        Run the tests for the package.

        This method builds arguments for and then calls ``pytest.main``.

        Parameters
        ----------
{keywords}

        pytestZpytest_remotedataZpytest_doctestplusZpytest_astropy_headeru   Test dependencies are missing: {module}. You should install the 'pytest-astropy' package (you may need to update the package if you have a previous version installed, e.g., 'pip install pytest-astropy --upgrade' or the equivalent with conda).c             C   s@   x:| j D ]0}t|}|d ks&|jd krt| jj|dqW d S )N)module)_required_dependenciesr   loaderRuntimeError_missing_dependancy_errorr4   )r8   rF   specr   r   r   _has_test_dependencies   s
    z%TestRunnerBase._has_test_dependenciesc          
   K   s(  | ddr8x*ttjddD ]}tjd| q"W |   dd l}t	| j
 }t	| }||st||}td|d  | jf |}|dd d k	r| d}n"| j
dd d k	r| j
d }ng }td}	td	}
t|	d
d( t|
d
d |j||dS Q R X W d Q R X d S )NZadd_local_eggs_to_pathFz.eggsz*.eggr   z/run_tests() got an unexpected keyword argument pluginsastropy_configastropy_cacheT)delete)r   rM   )popglobr   r   joinsysinsertrL   rE   setr*   r>   issubsetrB   
differencer@   rD   gettempfilemkdtempr   r   main)r   r   eggrE   Zallowed_kwargsZpassed_kwargsZwrong_kwargsr   rM   rN   rO   r   r   r   r5      s*    
	

zTestRunnerBase.run_testsc                sP   | | t  jd fdd}td}|dk	r8|j|_t|drF|`d|_|S )a  
        Constructs a `TestRunner` to run in the given path, and returns a
        ``test()`` function which takes the same arguments as
        ``TestRunner.run_tests``.

        The returned ``test()`` function will be defined in the module this
        was called from.  This is used to implement the ``astropy.test()``
        function (or the equivalent for affiliated packages).
        )r   c                 s    j f | S )N)r5   )r   )runnerr   r   test  s    z0TestRunnerBase.make_test_runner_in.<locals>.test   N__wrapped__F)r   r5   r   r   r   hasattrra   Z__test__)r8   r   r_   rF   r   )r^   r   make_test_runner_in   s    
z"TestRunnerBase.make_test_runner_in)r   r   r   r   r   r7   rD   r3   rG   rJ   classmethodrL   r5   rc   __classcell__r   r   )r:   r   r   5   s   3!6c                   s  e Zd ZdZd+ddZedddd Zed	dd
d Ze dd Ze dd Z	eg ddd Z
e dd Ze dd Zedddd Ze dd Ze dd Ze dd Zed d!d" Ze d#d$ Ze d%d& Ze d'd( Z fd)d*Z  ZS ),r
   z)
    A test runner for astropy tests
    Nc       	      C   s   | d}g }xz|D ]r}tj||dtjj}tj|s|||d}|dk	r`t|jf ||dk	rt	
|jf | q|| qW |S )aG  
        Generates the path for multiple packages.

        Parameters
        ----------
        packages : str
            Comma separated string of packages.
        base_path : str
            Base path to the source code or documentation.
        error : str
            Error message to be raised as ``ValueError``. Individual package
            name and path can be accessed by ``{name}`` and ``{path}``
            respectively. No error is raised if `None`. (Default: `None`)
        warning : str
            Warning message to be issued. Individual package
            name and path can be accessed by ``{name}`` and ``{path}``
            respectively. No warning is issues if `None`. (Default: `None`)

        Returns
        -------
        paths : list of str
            List of stings of existing package paths.
        ,.)r9   r   N)splitr   r   rS   replacesepisdir
ValueErrorr4   warningswarnappend)	r   packagesr    errorwarningpathspackager   infor   r   r   packages_path  s    


zTestRunner.packages_pathi  )r   c             C   s   |rt dt g S )NzThe coverage option is ignored on run_tests, since it can not be made to work in that context.  Use 'python setup.py test --coverage' instead.)rm   rn   r   )r   coverager   r   r   r   rw   F  s
    zTestRunner.coverager"   c             C   s>   |dkr| j g| _nd}| j|| j |d| _|d s:| jS g S )a   
        package : str, optional
            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.
        Nz6package to test is not found: {name} (at path {path}).)rq   	test_path)r    package_pathrv   )r   rt   r   error_messager   r   r   rt   S  s    

zTestRunner.packagec       	      C   s   g }|  |d | |rtj|\}}|dkr|d dkrDtdtj|d }tjtj|tj|}tj||f}tj	|r||kr|
d |}tj|sd|ksd|kstd	||g S g S )
z
        test_path : str, optional
            Specify location to test by path. May be a single file or
            directory. Must be specified absolutely or relative to the
            calling directory.
        rt   )z.rstr)   	docs_pathNz6Can not test .rst files without a docs_path specified.z--doctest-rstz.pyz.rstz=Test path must be a directory or a path to a .py or .rst file)rt   r   r   splitextrl   r   rS   pardircommonprefixexistsro   rk   )	r   rx   r   Zall_argsbaseextZabs_docs_pathZabs_test_pathcommonr   r   r   rx   h  s&    

zTestRunner.test_pathc             C   s    |rt j|tjd dS g S )z
        args : str, optional
            Additional arguments to be passed to ``pytest.main`` in the ``args``
            keyword argument.
        win)posix)shlexrh   rT   platform
startswith)r   r   r   r   r   r   r     s    zTestRunner.args)r   c             C   s   g S )z
        plugins : list, optional
            Plugins to be passed to ``pytest.main`` in the ``plugins`` keyword
            argument.
        r   )r   rM   r   r   r   r   rM     s    	zTestRunner.pluginsc             C   s   |r
dgS g S )z
        verbose : bool, optional
            Convenience option to turn on verbose output from pytest. Passing
            True is the same as specifying ``-v`` in ``args``.
        z-vr   )r   verboser   r   r   r   r     s    zTestRunner.verbosec             C   s(   |dk	r$|dkrd| gS t dg S )z
        pastebin : ('failed', 'all', None), optional
            Convenience option for turning on pytest pastebin output. Set to
            'failed' to upload info for failed tests, or 'all' to upload info
            for all tests.
        N)failedallz--pastebin=z$pastebin should be 'failed' or 'all')rl   )r   pastebinr   r   r   r   r     s
    zTestRunner.pastebinnonec             C   sF   |dkrd}n,|dkrd}n|dkr:t d|t d}d| gS )a  
        remote_data : {'none', 'astropy', 'any'}, optional
            Controls whether to run tests marked with @pytest.mark.remote_data. This can be
            set to run no tests with remote data (``none``), only ones that use
            data from http://data.astropy.org (``astropy``), or all tests that
            use remote data (``any``). The default is ``none``.
        TanyFr   )r   Zastropyr   zThe remote_data option should be one of none/astropy/any (found {}). For backward-compatibility, assuming 'any', but you should change the option to be one of the supported ones to avoid issues in future.z--remote-data=)rm   rn   r4   r	   )r   remote_datar   r   r   r   r     s    
zTestRunner.remote_datac             C   s<   |r8yddl }W n tk
r,   tdY nX dddgS g S )z
        pep8 : bool, optional
            Turn on PEP8 checking via the pytest-pep8 plugin and disable normal
            tests. Same as specifying ``--pep8 -k pep8`` in ``args``.
        r   NzOPEP8 checking requires pytest-pep8 plugin: https://pypi.org/project/pytest-pep8z--pep8z-kpep8)pytest_pep8ImportError)r   r   r   r   r   r   r   r     s    
zTestRunner.pep8c             C   s   |r
dgS g S )z
        pdb : bool, optional
            Turn on PDB post-mortem analysis for failing tests. Same as
            specifying ``--pdb`` in ``args``.
        z--pdbr   )r   pdbr   r   r   r   r     s    zTestRunner.pdbc             C   sL   |rH|d dkrt dyddl}W n tk
r@   t dY nX dgS g S )z
        open_files : bool, optional
            Fail when any tests leave files open.  Off by default, because
            this adds extra run time to the test suite.  Requires the
            ``psutil`` package.
        parallelr   zIopen file detection may not be used in conjunction with parallel testing.NzCopen file detection requested, but psutil package is not installed.z--open-fileszChecking for unclosed files)SystemErrorpsutilr   print)r   
open_filesr   r   r   r   r   r     s     zTestRunner.open_filesr   c             C   sF   |dkrByddl m} W n tk
r4   tdY nX dt|gS g S )a  
        parallel : int or 'auto', optional
            When provided, run the tests in parallel on the specified
            number of CPUs.  If parallel is ``'auto'``, it will use the all
            the cores on the machine.  Requires the ``pytest-xdist`` plugin.
        r   )pluginz;running tests in parallel requires the pytest-xdist packagez-n)Zxdistr   r   r   str)r   r   r   r   r   r   r   r     s    zTestRunner.parallelc             C   sf   g }|dk	rb|d sb|d dk	r:d}| j |d ||d}n|d sH|g}t|rb|d sb|d |S )za
        docs_path : str, optional
            The path to the documentation .rst files.
        N	skip_docsrt   zKCan not test .rst docs for {name}, since docs path ({path}) does not exist.)rr   rx   z--doctest-rst)rv   lenro   )r   r{   r   rs   Zwarning_messager   r   r   r{   *  s    

zTestRunner.docs_pathc             C   s   g S )zu
        skip_docs : `bool`, optional
            When `True`, skips running the doctests in the .rst files.
        r   )r   r   r   r   r   r   r   @  s    zTestRunner.skip_docsc             C   s   |rd| gS g S )z
        repeat : `int`, optional
            If set, specifies how many times each test should be run. This is
            useful for diagnosing sporadic failures.
        z	--repeat=r   )r   repeatr   r   r   r   r   I  s    zTestRunner.repeatc                s   ddl m} t jf |S )Nr   )Table)Zastropy.tabler   r6   r5   )r   r   r   )r:   r   r   r5   V  s    zTestRunner.run_tests)NN)r   r   r   r   rv   r   rw   rt   rx   r   rM   r   r   r   r   r   r   r   r{   r   r   r5   re   r   r   )r:   r   r
     s$   
*+	)r   r+   r   rR   r;   r   rT   rZ   rm   	importlibcollectionsr   importlib.utilr   	functoolsr   Zastropy.config.pathsr   r   Zastropy.utilsr   Zastropy.utils.exceptionsr   r	   __all__r   r   r
   r   r   r   r   <module>   s(   
 c