U
    d3=                     @   sz   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	 d dl
mZ d dlmZ d dlmZ d	ZG d
d dZdS )    N)StringIO)apps)settings)serializers)router)atomic)import_stringZtest_c                   @   s   e 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dZd0ddZd1ddZdd Zd2dd Zd3d"d#Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd!S )4BaseDatabaseCreationzs
    Encapsulate backend-specific differences pertaining to creation and
    destruction of the test database.
    c                 C   s
   || _ d S N)
connection)selfr    r   D/tmp/pip-unpacked-wheel-7vj2equ7/django/db/backends/base/creation.py__init__   s    zBaseDatabaseCreation.__init__c                 C   s
   | j  S r
   )r   _nodb_cursorr   r   r   r   r      s    z!BaseDatabaseCreation._nodb_cursorc                 C   s   t j|tj  d S r
   )sysstderrwriteoslinesep)r   msgr   r   r   log   s    zBaseDatabaseCreation.log   FTc           	      C   s0  ddl m} |  }|dkrBd}|r(d}| d|| ||f  | ||| | j  |tj	| jj
 d< || jjd< zR| jjd d	 d
krtj}dd t D t_|dt|d dd
| jj
dd W 5 | jjd d	 d
kr|t_X |r|  | j_|d| jj
d | j  tjddkr,|   |S )z
        Create a test database, prompting the user for confirmation if the
        database already exists. Return the name of the test database created.
        r   )call_commandr   ZCreatingzUsing existing %s test database for alias %s...NAMETESTZMIGRATEFc                 S   s   i | ]}|j d qS r
   )label).0Zappr   r   r   
<dictcomp>H   s     z7BaseDatabaseCreation.create_test_db.<locals>.<dictcomp>ZmigrateT)	verbosityinteractivedatabaseZ
run_syncdbZcreatecachetable)r#   ZRUNNING_DJANGOS_TEST_SUITEtrue)Zdjango.core.managementr   _get_test_db_namer   _get_database_display_str_create_test_dbr   closer   	DATABASESaliassettings_dictZMIGRATION_MODULESr   get_app_configsmaxserialize_db_to_stringZ_test_serialized_contentsZensure_connectionr   environget mark_expected_failures_and_skips)	r   r!   autoclobber	serializekeepdbr   test_database_nameactionZold_migration_modulesr   r   r   create_test_db    sN    



z#BaseDatabaseCreation.create_test_dbc                 C   s   |d | j jd< dS )z
        Set this database up to be used in testing as a mirror of a primary
        database whose settings are given.
        r   N)r   r+   )r   Zprimary_settings_dictr   r   r   set_as_test_mirrorj   s    z'BaseDatabaseCreation.set_as_test_mirrorc                    s.    fdd}t  }tjd| d|d | S )z
        Serialize all data in the database into a JSON string.
        Designed only for test runner usage; will not handle large
        amounts of data.
        c                  3   s   ddl m}  |  j}t D ]|}|jd k	r|j|jkr|jt	j
kr| D ]L}|j jrLt jj|rL|j jj|jjj}| E d H  qLqd S )Nr   )MigrationLoader)Zdjango.db.migrations.loaderr9   r   r   r,   Zmodels_moduler   Zmigrated_appsnamer   ZTEST_NON_SERIALIZED_APPSZ
get_models_metaZcan_migrater   Zallow_migrate_modelr*   Z_base_managerusingZorder_bypkiterator)r9   loaderZ
app_configmodelZquerysetr   r   r   get_objectsx   s*    


z@BaseDatabaseCreation.serialize_db_to_string.<locals>.get_objectsjsonN)indentstream)r   r   r3   getvalue)r   rA   outr   r   r   r.   q   s    z+BaseDatabaseCreation.serialize_db_to_stringc              
   C   s   t |}t }t| jjd^ | j : tjd|| jjdD ]}|  |	|j
jjj q>W 5 Q R X | jj|d W 5 Q R X dS )zw
        Reload the database with data from a string generated by
        the serialize_db_to_string() method.
        )r<   rB   )table_namesN)r   setr   r   r*   Zconstraint_checks_disabledr   Zdeserializesaveaddobject	__class__r;   Zdb_tableZcheck_constraints)r   datarG   objr   r   r   deserialize_db_from_string   s      
z/BaseDatabaseCreation.deserialize_db_from_stringc                 C   s    d| j j|dkrd| ndf S )zR
        Return display string for a database for use in various actions.
        z'%s'%s   z ('%s') )r   r*   )r   r!   Zdatabase_namer   r   r   r&      s    z.BaseDatabaseCreation._get_database_display_strc                 C   s0   | j jd d r | j jd d S t| j jd  S )z
        Internal implementation - return the name of the test DB that will be
        created. Only useful when called from create_test_db() and
        _create_test_db() and when no external munging is done with the 'NAME'
        settings.
        r   r   )r   r+   TEST_DATABASE_PREFIXr   r   r   r   r%      s    z&BaseDatabaseCreation._get_test_db_namec                 C   s   | d|  d S )Nz%CREATE DATABASE %(dbname)s %(suffix)s)execute)r   cursor
parametersr4   r   r   r   _execute_create_test_db   s    z,BaseDatabaseCreation._execute_create_test_dbc           	      C   sP  |   }| jj||  d}|  }z| ||| W n  tk
r@ } z|rp| W Y W  5 Q R  S | d|  |st	d| }|s|dkrz@|dkr| d| 
||f  |d|  | ||| W n< tk
r } z| d|  td	 W 5 d
}~X Y nX n| d td W 5 d
}~X Y nX W 5 Q R X |S )zF
        Internal implementation - create the test db tables.
        )Zdbnamesuffixz+Got an error creating the test database: %szXType 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: yesr   z,Destroying old test database for alias %s...zDROP DATABASE %(dbname)sz-Got an error recreating the test database: %srP   NzTests cancelled.)r%   r   ops
quote_namesql_table_creation_suffixr   rV   	Exceptionr   inputr&   rS   r   exit)	r   r!   r2   r4   r5   Ztest_db_paramsrT   eZconfirmr   r   r   r'      sJ     
&z$BaseDatabaseCreation._create_test_dbc                 C   sL   | j jd }|dkr:d}|r d}| d|| ||f  | ||| dS )z(
        Clone a test database.
        r   r   zCloning test databasezUsing existing clonez%s for alias %s...N)r   r+   r   r&   _clone_test_db)r   rW   r!   r2   r4   Zsource_database_namer6   r   r   r   clone_test_db   s    

z"BaseDatabaseCreation.clone_test_dbc                 C   s    | j j}|dd|d |iS )zX
        Return a modified connection settings dict for the n-th clone of a DB.
        r   z{}_{})r   r+   format)r   rW   Zorig_settings_dictr   r   r   get_test_db_clone_settings  s
     z/BaseDatabaseCreation.get_test_db_clone_settingsc                 C   s   t ddS )zI
        Internal implementation - duplicate the test db tables.
        znThe database backend doesn't support cloning databases. Disable the option to run tests in parallel processes.N)NotImplementedError)r   rW   r!   r4   r   r   r   r`     s    z#BaseDatabaseCreation._clone_test_dbNc                 C   s   | j   |dkr | j jd }n| |d }|dkr\d}|rBd}| d|| ||f  |sl| || |dk	r|tj| j j	 d< || j jd< dS )zv
        Destroy a test database, prompting the user for confirmation if the
        database already exists.
        Nr   r   Z
DestroyingZ
Preservingr   )
r   r(   r+   rc   r   r&   _destroy_test_dbr   r)   r*   )r   Zold_database_namer!   r4   rW   r5   r6   r   r   r   destroy_test_db  s(    


z$BaseDatabaseCreation.destroy_test_dbc              	   C   s0   |   }|d| jj|  W 5 Q R X dS )zF
        Internal implementation - remove the test db tables.
        zDROP DATABASE %sN)r   rS   r   rY   rZ   )r   r5   r!   rT   r   r   r   re   :  s    
z%BaseDatabaseCreation._destroy_test_dbc                 C   s   ddl m}m} | jjjD ]N}|d\}}}|dd }|tj	krt
|}t||}	t||||	 q| jjj D ]`\}
}|D ]R}|d\}}}|dd }|tj	krt
|}t||}	t||||
|	 qqxdS )z
        Mark tests in Django's test suite which are expected failures on this
        database and test which should be skipped on this database.
        r   )expectedFailureskip.N)Zunittestrg   rh   r   featuresZdjango_test_expected_failures
rpartitionsplitr   ZINSTALLED_APPSr   getattrsetattrZdjango_test_skipsitems)r   rg   rh   Z	test_nameZtest_case_name_Ztest_method_nameZtest_appZ	test_caseZtest_methodreasontestsr   r   r   r1   G  s     



z5BaseDatabaseCreation.mark_expected_failures_and_skipsc                 C   s   dS )zQ
        SQL to append to the end of the test table creation statements.
        rQ   r   r   r   r   r   r[   a  s    z.BaseDatabaseCreation.sql_table_creation_suffixc                 C   s$   | j j}|d |d |d |  fS )z
        Return a tuple with elements of self.connection.settings_dict (a
        DATABASES setting value) that uniquely identify a database
        accordingly to the RDBMS particularities.
        ZHOSTZPORTZENGINE)r   r+   r%   )r   r+   r   r   r   test_db_signatureg  s    z&BaseDatabaseCreation.test_db_signaturec                 C   s*   |  t|}| jj| | j  d S r
   )rc   strr   r+   updater(   )r   Z
_worker_idr+   r   r   r   setup_worker_connectionu  s    z,BaseDatabaseCreation.setup_worker_connection)r   FTF)F)F)r   FF)F)Nr   FN)__name__
__module____qualname____doc__r   r   r   r7   r8   r.   rO   r&   r%   rV   r'   ra   rc   r`   rf   re   r1   r[   rs   rv   r   r   r   r   r	      s:          
J	

/


       
#r	   )r   r   ior   Zdjango.appsr   Zdjango.confr   Zdjango.corer   Z	django.dbr   Zdjango.db.transactionr   Zdjango.utils.module_loadingr   rR   r	   r   r   r   r   <module>   s   