U
    Lk7gE                  
   @   s~  d dl Z d dlmZmZmZ d dlmZ zd dlmZ W n  e	k
rX   d dl
mZ Y nX zd dlmZ W n e	k
r   dZY nX d dlZd dlmZ ddd	d
dddddg	ZdZdZdZdZi Zi Zi ZejZG dd	 d	eZdd Zddddedddddf
ddZddddedddddf
ddZefddZdd Z edfddZ!dd Z"d d! Z#edfd"dZ$defd#d
Z%e!Z&e$Z'dS )$    N)MongoClientReadPreference
uri_parser)_UUID_REPRESENTATIONS)_check_name)
DriverInfo)PYMONGO_VERSIONDEFAULT_CONNECTION_NAMEDEFAULT_DATABASE_NAMEConnectionFailureconnect
disconnectdisconnect_allget_connectionget_dbregister_connectiondefaulttest	localhostii  c                   @   s   e Zd ZdZdS )r   zError raised when the database connection can't be established or
    when a connection with a requested alias can't be retrieved.
    N)__name__
__module____qualname____doc__ r   r   :/tmp/pip-unpacked-wheel-n1etwkgt/mongoengine/connection.pyr   -   s   c                 C   s,   t | tstdt n| dkr(t|  dS )zqCheck if a database name is valid.
    This functionality is copied from pymongo Database class constructor.
    zname must be an instance of %sz	$externalN)
isinstancestr	TypeErrorr   namer   r   r   _check_db_name5   s    
r    c
              
   K   sb  |p
| p
t |pt|pt||||||	d	}t|d  |d }t|trL|g}g }|D ]}|dsn|
drvtdd|krt	
|}|| |d}|r||d< d	D ]}||r|| ||< q|d
 }d|kr|d |d< d|kr|d |d< d|kr|d |d< d|krtjtjtjtjtjf}|d }t|trN| }|D ].}|j |ksr|j|krR|j} qqRd|kr||d d|d< n
| |d< d|kr|d |d< d|krdd t D }||d  |d< qT|| qT||d< |
dd |
dd dd |
 D }d|krTd|krTtdt d|
d < ||
 |S )!a  Get the connection settings as a dict

    :param db: the name of the database to use, for compatibility with connect
    :param name: the name of the specific database to use
    :param host: the host name of the: program: `mongod` instance to connect to
    :param port: the port that the: program: `mongod` instance is running on
    :param read_preference: The read preference for the collection
    :param username: username to authenticate with
    :param password: password to authenticate with
    :param authentication_source: database to authenticate against
    :param authentication_mechanism: database authentication mechanisms.
        By default, use SCRAM-SHA-1 with MongoDB 3.0 and later,
        MONGODB-CR (MongoDB Challenge Response protocol) for older servers.
    :param mongo_client_class: using alternative connection client other than
        pymongo.MongoClient, e.g. mongomock, montydb, that provides pymongo alike
        interface but not necessarily for connecting to a real mongo instance.
    :param kwargs: ad-hoc parameters to be passed into the pymongo driver,
        for example maxpoolsize, tz_aware, etc. See the documentation
        for pymongo's `MongoClient` for a full list.
    )	r   hostportread_preferenceusernamepasswordauthentication_sourceauthentication_mechanismauthmechanismpropertiesr   r!   zmongomock://Zis_mockzUse of mongomock:// URI or 'is_mock' were removed in favor of 'mongo_client_class=mongomock.MongoClient'. Check the CHANGELOG for more infoz://database)r#   r$   r%   optionsZ
replicasetZ
replicaSetZ
authsourcer&   Zauthmechanismr'   ZreadpreferenceZreadpreferencetags)Ztag_setsr#   r(   Zuuidrepresentationc                 S   s   i | ]\}}||qS r   r   .0kvr   r   r   
<dictcomp>   s     z,_get_connection_settings.<locals>.<dictcomp>ZslavesNZis_slavec                 S   s   h | ]}|  qS r   )lower)r,   keyr   r   r   	<setcomp>   s    z+_get_connection_settings.<locals>.<setcomp>a?  No uuidRepresentation is specified! Falling back to 'pythonLegacy' which is the default for pymongo 3.x. For compatibility with other MongoDB drivers this should be specified as 'standard' or '{java,csharp}Legacy' to work with older drivers in those languages. This will be changed to 'unspecified' in a future release.ZpythonLegacyZuuidRepresentation)r
   DEFAULT_HOSTDEFAULT_PORTr    r   r   
startswithget	Exceptionr   	parse_uriappendr   ZNEARESTPRIMARYZPRIMARY_PREFERREDZ	SECONDARYZSECONDARY_PREFERREDr0   r   mode	__class__r   itemspopkeyswarningswarnDeprecationWarningupdate)dbr   r!   r"   r#   r$   r%   r&   r'   r(   kwargsconn_settingsZ	conn_hostZresolved_hostsentityZuri_dictr)   paramZuri_optionsZread_preferencesZread_pf_modeZ
preferenceZReadPrefClassZREV_UUID_REPRESENTATIONSr?   r   r   r   _get_connection_settings?   s    "















	
rI   c                 K   s0   t f |||||||||	|
d
|}|t| < dS )a#  Register the connection settings.

    :param alias: the name that will be used to refer to this connection throughout MongoEngine
    :param db: the name of the database to use, for compatibility with connect
    :param name: the name of the specific database to use
    :param host: the host name of the: program: `mongod` instance to connect to
    :param port: the port that the: program: `mongod` instance is running on
    :param read_preference: The read preference for the collection
    :param username: username to authenticate with
    :param password: password to authenticate with
    :param authentication_source: database to authenticate against
    :param authentication_mechanism: database authentication mechanisms.
        By default, use SCRAM-SHA-1 with MongoDB 3.0 and later,
        MONGODB-CR (MongoDB Challenge Response protocol) for older servers.
    :param mongo_client_class: using alternative connection client other than
        pymongo.MongoClient, e.g. mongomock, montydb, that provides pymongo alike
        interface but not necessarily for connecting to a real mongo instance.
    :param kwargs: ad-hoc parameters to be passed into the pymongo driver,
        for example maxpoolsize, tz_aware, etc. See the documentation
        for pymongo's `MongoClient` for a full list.
    )
rD   r   r!   r"   r#   r$   r%   r&   r'   r(   N)rI   _connection_settings)aliasrD   r   r!   r"   r#   r$   r%   r&   r'   r(   rE   rF   r   r   r   r      s    #c                    s   ddl m} ddlm} t| d  rJt fddt D rJ   | t	krz|| t
D ]}t||r\|  q\t	| = | tkrt| = dS )z(Close the connection with a given alias.r   )Document)_get_documents_by_dbNc                 3   s   | ]} |k	V  qd S Nr   )r,   c
connectionr   r   	<genexpr>  s     zdisconnect.<locals>.<genexpr>)mongoenginerL   Zmongoengine.base.commonrM   _connectionsr>   allvaluesclose_dbsr	   
issubclassZ_disconnectrJ   )rK   rL   rM   Zdoc_clsr   rP   r   r     s    

c                  C   s   t t D ]} t|  qdS )zClose all registered database.N)listrT   r?   r   )rK   r   r   r   r   (  s    Fc           	      C   s   |rt |  | tkrt|  S | tkrB| tkr2d}nd|  }t|dd }t|   }||}tdk	rz|dtdtj	 d|kr|
d}nt}t|}|r|}ntf | |d	|}|t| < t|  S )
z'Return a connection with a given alias.z)You have not defined a default connectionz/Connection with alias "%s" has not been definedc                    sF   t dk rddddddh i ndh dd	d
 fdd|  D S )N   r   r$   r%   r&   r'   r(   Z
authSourceZauthMechanism)r&   r'   c                    s.   i | ]&\}}| kr|d k	r |||qS rN   )r6   r+   Zirrelevant_fields_setZrename_fieldsr   r   r/   T  s
    
 z;get_connection.<locals>._clean_settings.<locals>.<dictcomp>)r   r=   Zsettings_dictr   r]   r   _clean_settingsC  s     z'get_connection.<locals>._clean_settingsNZdriverZMongoEnginemongo_client_class)rK   r`   )r   rT   rJ   r	   r   copyr   
setdefaultrS   __version__r>   r   _find_existing_connection_create_connection)	rK   	reconnectmsgr_   Zraw_conn_settingsrF   r`   Zexisting_connectionrQ   r   r   r   r   .  s>     
 c              
   K   sH   z|f |W S  t k
rB } ztd|  d| W 5 d}~X Y nX dS )zk
    Create the new connection for this alias. Raise
    ConnectionFailure if it can't be established.
    zCannot connect to database z :
N)r7   r   )rK   r`   connection_settingser   r   r   re   w  s    re   c                 C   sZ   dd t  D }dd }|| }|D ].\}} || }||kr&t|r&t|   S q&dS )a,  
    Check if an existing connection could be reused

    Iterate over all of the connection settings and if an existing connection
    with the same parameters is suitable, return it

    :param connection_settings: the settings of the new connection
    :return: An existing connection or None
    c                 s   s   | ]\}}||  fV  qd S rN   )ra   )r,   db_aliassettingsr   r   r   rR     s   z,_find_existing_connection.<locals>.<genexpr>c                 S   s   dd |   D S )Nc                 S   s   i | ]\}}|d kr||qS r   r   r+   r   r   r   r/     s       zF_find_existing_connection.<locals>._clean_settings.<locals>.<dictcomp>)r=   r^   r   r   r   r_     s    z2_find_existing_connection.<locals>._clean_settingsN)rJ   r=   rT   r6   )rh   Zconnection_settings_bisr_   Zcleaned_conn_settingsrj   Zdb_conn_settingsr   r   r   rd     s    
rd   c                 C   s   |rt |  | tkrt| }t|  }||d  }tdk r|d r|d sT|d dkr|d d krd|d	 i}|d d k	r|d |d
< |j|d |d f| |t| < t|  S )Nr   r[   r$   r%   r'   zMONGODB-X509r(   sourcer&   Z	mechanism)r   rX   r   rJ   r   Zauthenticate)rK   rf   connrF   rD   Zauth_kwargsr   r   r   r     s6    

	 c                 K   sN   |t kr8t| }t| f|}||krFd|}t|nt|| f| t|S )al  Connect to the database specified by the 'db' argument.

    Connection settings may be provided here as well if the database is not
    running on the default port on localhost. If authentication is needed,
    provide username and password arguments as well.

    Multiple databases are supported by using aliases. Provide a separate
    `alias` to connect to a different instance of: program: `mongod`.

    In order to replace a connection identified by a given alias, you'll
    need to call ``disconnect`` first

    See the docstring for `register_connection` for more details about all
    supported kwargs.
    zUA different connection with alias `{}` was already registered. Use disconnect() first)rT   rJ   rI   formatr   r   r   )rD   rK   rE   Zprev_conn_settingZnew_conn_settingserr_msgr   r   r   r     s    
)(r@   Zpymongor   r   r   Zpymongo.commonr   Zpymongo.database_sharedr   ImportErrorZpymongo.databaseZpymongo.driver_infor   rS   Zmongoengine.pymongo_supportr   __all__r	   r
   r3   r4   rJ   rT   rX   r:   ZREAD_PREFERENCEr7   r   r    rI   r   r   r   r   re   rd   r   r   Z_get_connectionZ_get_dbr   r   r   r   <module>   s   

 
3I!