o
    qN)j                     @  s   d 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	d
l
mZ ddlmZ ddlmZ erdd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dZG dd deZeZdS )a  

.. dialect:: mysql+pymysql
    :name: PyMySQL
    :dbapi: pymysql
    :connectstring: mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]
    :url: https://pymysql.readthedocs.io/

Unicode
-------

Please see :ref:`mysql_unicode` for current recommendations on unicode
handling.

.. _pymysql_ssl:

SSL Connections
------------------

The PyMySQL DBAPI accepts the same SSL arguments as that of MySQLdb,
described at :ref:`mysqldb_ssl`.   See that section for additional examples.

If the server uses an automatically-generated certificate that is self-signed
or does not match the host name (as seen from the client), it may also be
necessary to indicate ``ssl_check_hostname=false`` in PyMySQL::

    connection_uri = (
        "mysql+pymysql://scott:tiger@192.168.0.134/test"
        "?ssl_ca=/home/gord/client-ssl/ca.pem"
        "&ssl_cert=/home/gord/client-ssl/client-cert.pem"
        "&ssl_key=/home/gord/client-ssl/client-key.pem"
        "&ssl_check_hostname=false"
    )

MySQL-Python Compatibility
--------------------------

The pymysql DBAPI is a pure Python port of the MySQL-python (MySQLdb) driver,
and targets 100% compatibility.   Most behavioral notes for MySQL-python apply
to the pymysql driver as well.

    )annotations)Any)Dict)Optional)Type)TYPE_CHECKING)Union   )MySQLDialect_mysqldb   )langhelpers)Literal)ConnectArgsType)DBAPIConnection)DBAPICursor)DBAPIModule)PoolProxiedConnection)URLconnection_cls	Type[Any]returnboolc                 C  sN   t | j}z|jd }W n
 ty   Y dS w |dko&|j p&|jd duS )ax  Given a Connection class like pymysql.Connection, aiomysql.Connection,
    asyncmy.Connection, inspect the ping() method and determine if it
    has a "reconnect" parameter that either defaults to True, or is positional.

    a return value of True here means that when we call ``connection.ping()``,
    we **must** pass `reconnect=False`.  a return value of False means that
    we should call ``connection.ping()`` with **no arguments**.

    This routine originates from issue #10492 for pymysql, however arg
    signature mismatches in aiomysql/asyncmy tracked by issue #13306
    necessitated a more open ended function.

    r	   F	reconnectr   )r   get_callable_argspecpingargs
IndexErrordefaults)r   inspreconnect_arg r    /var/www/html/finance.cargoinsureonline.com/_shared/backend-venv/lib/python3.10/site-packages/sqlalchemy/dialects/mysql/pymysql.py _connection_ping_reconnects_trueJ   s   r"   c                      s~   e Zd ZdZdZdZejd&ddZe	d'd	d
Z
ejd&ddZd(ddZ	d)d* fddZd+ fdd Zd,d$d%Z  ZS )-MySQLDialect_pymysqlpymysqlTNr   r   c              	   C  s2   zt dj}|j| _W dS  ttfy   Y dS w )Nzpymysql.cursorsTF)
__import__cursorsSSCursor	_sscursorImportErrorAttributeError)selfr&   r    r    r!   supports_server_side_cursorsi   s   
z1MySQLDialect_pymysql.supports_server_side_cursorsr   c                 C  s   t dS )Nr$   )r%   )clsr    r    r!   import_dbapir   s   z!MySQLDialect_pymysql.import_dbapic              	   C  s0   zt djj}W t|S  ttfy   Y dS w )a4  determine if pymysql has deprecated, changed the default of,
        or removed the 'reconnect' argument of connection.ping().

        See #10492 and
        https://github.com/PyMySQL/mysqlclient/discussions/651#discussioncomment-7308971
        for background.

        Revised as part of #13306

        zpymysql.connectionsT)r%   connections
Connectionr)   r*   r"   )r+   r0   r    r    r!   _send_false_to_pingv   s   z(MySQLDialect_pymysql._send_false_to_pingdbapi_connectionr   Literal[True]c                 C  s    | j r
|d dS |  dS )NFT)r1   r   )r+   r2   r    r    r!   do_ping   s
   
zMySQLDialect_pymysql.do_pingurlr   _translate_argsOptional[Dict[str, Any]]r   c                   s"   |d u r	t dd}t j||dS )Nuser)username)r6   )dictsupercreate_connect_args)r+   r5   r6   	__class__r    r!   r<      s
   
z(MySQLDialect_pymysql.create_connect_argseDBAPIModule.Error
connection7Optional[Union[PoolProxiedConnection, DBAPIConnection]]cursorOptional[DBAPICursor]c                   sB   t  |||r
dS t|| jjrt| }d|v pd|v S dS )NTzalready closedzconnection was killedF)r;   is_disconnect
isinstanceloaded_dbapiErrorstrlower)r+   r?   rA   rC   str_er=   r    r!   rE      s   z"MySQLDialect_pymysql.is_disconnect	exceptionBaseExceptionr   c                 C  s$   t |jd tr|jd }|jd S )Nr   )rF   r   	Exception)r+   rL   r    r    r!   _extract_error_code   s   

z(MySQLDialect_pymysql._extract_error_code)r   r   )r   r   )r2   r   r   r3   )N)r5   r   r6   r7   r   r   )r?   r@   rA   rB   rC   rD   r   r   )rL   rM   r   r   )__name__
__module____qualname__driversupports_statement_cachedescription_encodingr   memoized_propertyr,   classmethodr.   r1   r4   r<   rE   rO   __classcell__r    r    r=   r!   r#   c   s    
		r#   N)r   r   r   r   )__doc__
__future__r   typingr   r   r   r   r   r   mysqldbr
   utilr   util.typingr   engine.interfacesr   r   r   r   r   
engine.urlr   r"   r#   dialectr    r    r    r!   <module>   s*   +
P