a
    1$e:                     @   s   d dl Z d dlmZ d dlZd dlZd dlZd dlmZ d dlm	Z
 edd Zd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ddZdS )     N)contextmanager)GeoDataFrame)_compatc                 c   s   ddl m}m} t| |rZ|  sR|   | V  W d   qX1 sF0    Y  q| V  nHt| |r|  }|V  W d   q1 s0    Y  ntd|  dS )a  
    Yield a connection within a transaction context.

    Engine.begin() returns a Connection with an implicit Transaction while
    Connection.begin() returns the Transaction. This helper will always return a
    Connection with an implicit (possibly nested) Transaction.

    Parameters
    ----------
    conn_or_engine : Connection or Engine
        A sqlalchemy Connection or Engine instance
    Returns
    -------
    Connection
    r   )Engine
ConnectionNzUnknown Connectable: )Zsqlalchemy.engine.baser   r   
isinstanceZin_transactionbegin
ValueError)Zconn_or_enginer   r   conn r   L/var/www/html/django/DPS/env/lib/python3.9/site-packages/geopandas/io/sql.py	_get_conn   s    

&

&r   geomc           	      C   s   || vrt d|| j |dkr:t d| d| |  }|jstjj	}dd }dd }t
|jd	 trz|}n|}|| | |< }|d
u rtjrt|jd	 }ntjj|jd	 j}|d	krd|}t| ||dS )a`  
    Transforms a pandas DataFrame into a GeoDataFrame.
    The column 'geom_col' must be a geometry column in WKB representation.
    To be used to convert df based on pd.read_sql to gdf.
    Parameters
    ----------
    df : DataFrame
        pandas DataFrame with geometry column in WKB representation.
    geom_col : string, default 'geom'
        column name to convert to shapely geometries
    crs : pyproj.CRS, optional
        CRS to use for the returned GeoDataFrame. The value can be anything accepted
        by :meth:`pyproj.CRS.from_user_input() <pyproj.crs.CRS.from_user_input>`,
        such as an authority string (eg "EPSG:4326") or a WKT string.
        If not set, tries to determine CRS from the SRID associated with the
        first geometry in the database, and assigns that to all geometries.
    Returns
    -------
    GeoDataFrame
    z"Query missing geometry column '{}'   zDuplicate geometry column 'zC' detected in SQL query output. Onlyone geometry column is allowed.c                 S   s   t jt| S )zLoad from Python 2 binary.shapelywkbloadsstrxr   r   r   load_geom_bufferS   s    z&_df_to_geodf.<locals>.load_geom_bufferc                 S   s   t jjt| ddS )z!Load from binary encoded as text.T)hexr   r   r   r   r   load_geom_textW   s    z$_df_to_geodf.<locals>.load_geom_textr   Nzepsg:{})crsgeometry)r	   formatcolumnsZto_listcountZdropnaemptyr   r   r   r   ZiatbytesapplycompatZSHAPELY_GE_20Zget_sridZgeosZlgeosZGEOSGetSRIDZ_geomr   )	dfgeom_colr   geomsZload_geom_bytesr   r   Z	load_geomsridr   r   r   _df_to_geodf.   s,    

r'   Tc	              	      s^   |du r.t j| ||||||d}	t|	 dS t j| ||||||d}
 fdd|
D S dS )a  
    Returns a GeoDataFrame corresponding to the result of the query
    string, which must contain a geometry column in WKB representation.

    It is also possible to use :meth:`~GeoDataFrame.read_file` to read from a database.
    Especially for file geodatabases like GeoPackage or SpatiaLite this can be easier.

    Parameters
    ----------
    sql : string
        SQL query to execute in selecting entries from database, or name
        of the table to read from the database.
    con : sqlalchemy.engine.Connection or sqlalchemy.engine.Engine
        Active connection to the database to query.
    geom_col : string, default 'geom'
        column name to convert to shapely geometries
    crs : dict or str, optional
        CRS to use for the returned GeoDataFrame; if not set, tries to
        determine CRS from the SRID associated with the first geometry in
        the database, and assigns that to all geometries.
    chunksize : int, default None
        If specified, return an iterator where chunksize is the number of rows to
        include in each chunk.

    See the documentation for pandas.read_sql for further explanation
    of the following parameters:
    index_col, coerce_float, parse_dates, params, chunksize

    Returns
    -------
    GeoDataFrame

    Examples
    --------
    PostGIS

    >>> from sqlalchemy import create_engine  # doctest: +SKIP
    >>> db_connection_url = "postgresql://myusername:mypassword@myhost:5432/mydatabase"
    >>> con = create_engine(db_connection_url)  # doctest: +SKIP
    >>> sql = "SELECT geom, highway FROM roads"
    >>> df = geopandas.read_postgis(sql, con)  # doctest: +SKIP

    SpatiaLite

    >>> sql = "SELECT ST_AsBinary(geom) AS geom, highway FROM roads"
    >>> df = geopandas.read_postgis(sql, con)  # doctest: +SKIP
    N)	index_colcoerce_floatparse_datesparams	chunksizer$   r   c                 3   s   | ]}t | d V  qdS )r-   N)r'   ).0r#   r   r$   r   r   	<genexpr>       z _read_postgis.<locals>.<genexpr>)pdZread_sqlr'   )sqlconr$   r   r(   r)   r*   r+   r,   r#   Zdf_generatorr   r/   r   _read_postgism   s*    ;		r5   c                  O   s&   dd l }|jdtdd t| i |S )Nr   zgeopandas.io.sql.read_postgis() is intended for internal use only, and will be deprecated. Use geopandas.read_postgis() instead.   
stacklevel)warningswarnFutureWarningr5   )argskwargsr9   r   r   r   read_postgis   s    r>   c                 C   s   t | jj }d}|D ]}|du r(qqd|v rd}qt|dkrp|rLd}qt|d du rbtdqt|d  }nd	}t| jjr|d
7 }||fS )a  
    Get basic geometry type of a GeoDataFrame. See more info from:
    https://geoalchemy-2.readthedocs.io/en/latest/types.html#geoalchemy2.types._GISType

    Following rules apply:
     - if geometries all share the same geometry-type,
       geometries are inserted with the given GeometryType with following types:
        - Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon,
          GeometryCollection.
        - LinearRing geometries will be converted into LineString -objects.
     - in all other cases, geometries will be inserted with type GEOMETRY:
        - a mix of Polygons and MultiPolygons in GeoSeries
        - a mix of Points and LineStrings in GeoSeries
        - geometry is of type GeometryCollection,
          such as GeometryCollection([Point, LineStrings])
     - if any of the geometries has Z-coordinate, all records will
       be written with 3D.
    FN
LinearRingTr   Z
LINESTRINGr   z No valid geometries in the data.ZGEOMETRYZ)	listr   	geom_typeuniquelenr	   upperanyZhas_z)gdfZ
geom_types	has_curvegtZtarget_geom_typer   r   r   _get_geometry_type   s"    
rJ   c                 C   s   d}d}| j durzPdD ]F}| j j|d}|dur6 q`| j jd|d}|durt|d } q`qW n" ty   tj|tdd	 Y n0 |du rd
}tj|tdd	 |S )zA
    Get EPSG code from CRS if available. If not, return -1.
    NzNCould not parse CRS from the GeoDataFrame. Inserting data without defined CRS.)d   F      )min_confidenceZESRI)Z	auth_namerN   r   r6   r7   )r   Zto_epsgZto_authorityint	Exceptionr9   r:   UserWarning)rG   r&   Zwarning_msg
confidenceZ	auth_sridr   r   r   _get_srid_from_crs   s*    

rT   c                    s@   ddl m  | jdk}| j||f  fdd| j||f< | S )Nr   
LineStringr?   c                    s    | S )Nr   )r   rU   r   r   <lambda>(  r1   z3_convert_linearring_to_linestring.<locals>.<lambda>)Zshapely.geometryrV   rB   locr!   )rG   	geom_namemaskr   rU   r   !_convert_linearring_to_linestring   s    

r[   c                    s   t jr*tjtj| | jjdddd}nZt jr`ddlm}m} ||| | jjdddd}n$ddl	m
   fdd| | D }tj| d	d
}|||< |S )zConvert geometries to ewkb.)r&   T)r   Zinclude_sridr   )set_sridto_wkb)dumpsc                    s   g | ]} |d dqS )T)r&   r   r   )r.   r   r^   r&   r   r   
<listcomp>B  r1   z$_convert_to_ewkb.<locals>.<listcomp>F)copy)r"   ZUSE_SHAPELY_20r   r]   r\   values_dataZ
USE_PYGEOSZpygeosshapely.wkbr^   r2   Z	DataFrame)rG   rY   r&   r%   r\   r]   r#   r   r_   r   _convert_to_ewkb-  s$    re   c                 C   s   dd l }dd l}| }||}|| |d ddd |D }|j}	|	 4}
d	| j
j| j
j|}|
j||d W d    n1 s0    Y  d S )Nr   z, c                 s   s   | ]}d  |V  qdS )z"{}"N)r   )r.   kr   r   r   r0   U  r1   z$_psql_insert_copy.<locals>.<genexpr>z'COPY "{}"."{}" ({}) FROM STDIN WITH CSV)r3   file)iocsvStringIOwriter	writerowsseekjoin
connectioncursorr   tableschemanameZcopy_expert)tblr
   keysZ	data_iterrh   ri   Zs_bufrk   r   Z
dbapi_conncurr3   r   r   r   _psql_insert_copyL  s    



rw   failFc	                 C   s  zddl m}	 ddlm}
 W n ty6   tdY n0 |  } | jj}t| }t	| \}}|durv|	||d||< n||	||di}|rt
| |} t| ||} |dur|}nd}|dkr:t|d}|j|||r||
d	j|||d
 d }||krdj||d}t|W d   n1 s00    Y  t|,}| j||||||||td	 W d   n1 sv0    Y  dS )a  
    Upload GeoDataFrame into PostGIS database.

    This method requires SQLAlchemy and GeoAlchemy2, and a PostgreSQL
    Python driver (e.g. psycopg2) to be installed.

    Parameters
    ----------
    name : str
        Name of the target table.
    con : sqlalchemy.engine.Connection or sqlalchemy.engine.Engine
        Active connection to the PostGIS database.
    if_exists : {'fail', 'replace', 'append'}, default 'fail'
        How to behave if the table already exists:

        - fail: Raise a ValueError.
        - replace: Drop the table before inserting new values.
        - append: Insert new values to the existing table.
    schema : string, optional
        Specify the schema. If None, use default schema: 'public'.
    index : bool, default True
        Write DataFrame index as a column.
        Uses *index_label* as the column name in the table.
    index_label : string or sequence, default None
        Column label for index column(s).
        If None is given (default) and index is True,
        then the index names are used.
    chunksize : int, optional
        Rows will be written in batches of this size at a time.
        By default, all rows will be written at once.
    dtype : dict of column name to SQL type, default None
        Specifying the datatype for columns.
        The keys should be the column names and the values
        should be the SQLAlchemy types.

    Examples
    --------

    >>> from sqlalchemy import create_engine  # doctest: +SKIP
    >>> engine = create_engine("postgresql://myusername:mypassword@myhost:5432/mydatabase";)  # doctest: +SKIP
    >>> gdf.to_postgis("my_table", engine)  # doctest: +SKIP
    r   )Geometry)textz,'to_postgis()' requires geoalchemy2 package.N)geometry_typer&   publicappendz6SELECT Find_SRID('{schema}', '{table}', '{geom_col}');)rr   rq   r$   zkThe CRS of the target table (EPSG:{epsg_t}) differs from the CRS of current GeoDataFrame (EPSG:{epsg_src}).)Zepsg_tZepsg_src)rr   	if_existsindexindex_labelr,   dtypemethod)Zgeoalchemy2ry   Z
sqlalchemyrz   ImportErrorra   r   rs   rT   rJ   r[   re   r   dialectZ	has_tableexecuter   Zfetchoner	   Zto_sqlrw   )rG   rs   r4   rr   r~   r   r   r,   r   ry   rz   rY   r&   r{   rH   Zschema_namero   Ztarget_sridmsgr   r   r   _write_postgis_  s`    6



(
r   )r   N)r   NNTNNN)Nrx   FNNN)r9   
contextlibr   Zpandasr2   r   rd   Z	geopandasr   r   r"   r   r'   r5   r>   rJ   rT   r[   re   rw   r   r   r   r   r   <module>   s<   

B       
V."      