B
    ؐ<[&                 @   s   d Z dZddlZddlZddlmZ ddlmZmZ yddl	m
Z
mZ W n$ ek
rl   ddl	m
Z
mZ Y nX eeZG dd deZdS )	a	  
This plugin adds a test id (like #1) to each test name output. After
you've run once to generate test ids, you can re-run individual
tests by activating the plugin and passing the ids (with or
without the # prefix) instead of test names.

For example, if your normal test run looks like::

  % nosetests -v
  tests.test_a ... ok
  tests.test_b ... ok
  tests.test_c ... ok

When adding ``--with-id`` you'll see::

  % nosetests -v --with-id
  #1 tests.test_a ... ok
  #2 tests.test_b ... ok
  #3 tests.test_c ... ok

Then you can re-run individual tests by supplying just an id number::

  % nosetests -v --with-id 2
  #2 tests.test_b ... ok

You can also pass multiple id numbers::

  % nosetests -v --with-id 2 3
  #2 tests.test_b ... ok
  #3 tests.test_c ... ok
  
Since most shells consider '#' a special character, you can leave it out when
specifying a test id.

Note that when run without the -v switch, no special output is displayed, but
the ids file is still written.

Looping over failed tests
-------------------------

This plugin also adds a mode that will direct the test runner to record
failed tests. Subsequent test runs will then run only the tests that failed
last time. Activate this mode with the ``--failed`` switch::

 % nosetests -v --failed
 #1 test.test_a ... ok
 #2 test.test_b ... ERROR
 #3 test.test_c ... FAILED
 #4 test.test_d ... ok
 
On the second run, only tests #2 and #3 will run::

 % nosetests -v --failed
 #2 test.test_b ... ERROR
 #3 test.test_c ... FAILED

As you correct errors and tests pass, they'll drop out of subsequent runs.

First::

 % nosetests -v --failed
 #2 test.test_b ... ok
 #3 test.test_c ... FAILED

Second::

 % nosetests -v --failed
 #3 test.test_c ... FAILED

When all tests pass, the full set will run on the next invocation.

First::

 % nosetests -v --failed
 #3 test.test_c ... ok

Second::
 
 % nosetests -v --failed
 #1 test.test_a ... ok
 #2 test.test_b ... ok
 #3 test.test_c ... ok
 #4 test.test_d ... ok

.. note ::

  If you expect to use ``--failed`` regularly, it's a good idea to always run
  using the ``--with-id`` option. This will ensure that an id file is always
  created, allowing you to add ``--failed`` to the command line as soon as
  you have failing tests. Otherwise, your first run using ``--failed`` will
  (perhaps surprisingly) run *all* tests, because there won't be an id file
  containing the record of failed tests from your previous run.
  
F    N)Plugin)srcset)dumploadc               @   sr   e Zd ZdZdZdZdZdZdd Zdd	 Z	d
d Z
dddZdd Zdd Zdd Zdd Zdd Zdd ZdS )TestIdz
    Activate to add a test id (like #1) to each test name output. Activate
    with --failed to rerun failing tests only.
    idNTFc             C   s<   t | || |jddddddd |jdd	d
ddd dS )z&Register commandline options.
        z	--id-fileZstore
testIdFilez.noseidsZFILEzfStore test ids found in test runs in this file. Default is the file .noseids in the working directory.)actiondestdefaultmetavarhelpz--failed
store_truefailedFz/Run the tests that failed in the last test run.)r
   r   r   r   N)r   optionsZ
add_option)selfparserenv r   2lib/python3.7/site-packages/nose/plugins/testid.pyr   x   s    
zTestId.optionsc             C   s   t | || |jr*d| _d| _td tj	|j
| _tj| js\tj|j| j| _d| _i | _i | _g | _g | _i | _|jdk| _dS )zConfigure plugin.
        TzLooping on failed tests      N)r   	configurer   ZenabledloopOnFailedlogdebugospath
expanduserr	   idfileisabsjoinZ
workingDirr   idstestssource_names_seen	verbosity_write_hashes)r   r   Zconfr   r   r   r      s    
zTestId.configurec             C   s   |  rg | _| jr<tttt| j t| j }n| j	}t
| jd}t|| j| jd| |  td|| j| j dS )z&Save new ids file, if needed.
        wb)r#   r   r%   z#Saved test ids: %s, failed %s to %sN)ZwasSuccessfulr   
collectingdictlistzipr$   valueskeysr#   openr    r   r%   closer   r   )r   resultr#   fhr   r   r   finalize   s    (zTestId.finalizec          
      s  t d|| yt| jd}t|}d|krL|d | _|d | _|d | _n|| _g | _|| _| jrt| jd | _	t
ttt| j t| j | _nd| _	t d| j| j| j| j| j |  W nZ tk
r } zt d| jt| W d	d	}~X Y n$ tk
r&   t d
| j Y nX | jrJ| jrJd| _| j}g | _g }g }g }x8|D ]0}	| |	}
|
|	kr||
 n
||	 q\W |rt|}t| j t d |  fdd|D }|r| j| |s|}nd| _t d||| d	|| p
|fS )zTranslate ids in the list of requested names into their
        test addresses, if they are found in my dict of tests.
        z
ltfn %s %srbr#   r   r%   r   z8Loaded test ids %s tests %s failed %s sources %s from %szError loading %s : %sNzIO error reading %sFzold: %s new: %sc                s   g | ]}| kr|qS r   r   ).0s)old_setr   r   
<listcomp>   s    z-TestId.loadTestsFromNames.<locals>.<listcomp>z&translated: %s new sources %s names %s)r   r   r0   r    r   r#   r   r%   maxr   r+   r,   r-   r.   r/   r$   r1   
ValueErrorstrIOErrorr   r*   trappendr   extend)r   namesmoduler3   dataeZ
translatedZ
new_sourceZ
really_newnameZtransZnew_setr   )r8   r   loadTestsFromNames   sb    

*$




zTestId.loadTestsFromNamesc             C   sD   t d| |\}}}|d k	r(t|}n|}|d k	r@d||f S |S )NzMake name %sz%s:%s)r   r   r   )r   ZaddrfilenamerB   Zcallheadr   r   r   makeName   s    

zTestId.makeNamec             C   s
   || _ dS )zBGet handle on output stream so the plugin can print id #s
        N)stream)r   rJ   r   r   r   setOutputStream  s    zTestId.setOutputStreamc             C   s   |  }td||| jk || jkr^|| jkr<| d n| d| j|   d| j|< dS | j| j|< | d| j  |  jd7  _dS )zMaybe output an id # before the test name.

        Example output::

          #1 test.test ... ok
          #2 test.test_two ... ok

        zstart test %s (%s)z   z#%s r   N)addressr   r   r$   r&   writer   )r   testZadrr   r   r   	startTest  s    	


zTestId.startTestc             C   sP   |j dkrLyt| j|  }W n tk
r4   Y nX || jkrL| j| d S )NF)Zpassedr<   r$   rL   KeyErrorr   r?   )r   rN   keyr   r   r   	afterTest  s    

zTestId.afterTestc             C   s`   t d| yt|dd}W n tk
r4   |S X t d| || jkr\| | j| S |S )Nztr '%s'# z
Got key %s)r   r   intreplacer;   r#   rI   )r   rE   rQ   r   r   r   r>   (  s    
z	TestId.trc             C   s   | j r| j| d S )N)r(   rJ   rM   )r   outputr   r   r   rM   5  s    zTestId.write)N)__name__
__module____qualname____doc__rE   r    r*   r   r   r   r4   rF   rI   rK   rO   rR   r>   rM   r   r   r   r   r   n   s   
Hr   )r[   Z__test__Zloggingr   Znose.pluginsr   Z	nose.utilr   r   pickler   r   ImportErrorZ	getLoggerrX   r   r   r   r   r   r   <module>^   s   
