
    +'&h(                     <   U d 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d
lmZ ddlmZ ddlmZ ddlmZ eej                 ed<   eej                 ed<   	 ddlmZ ddlmZ  G d de          Z eeej                  Zej        Zn"# e$ r  G d dej                  Z e Ze ZY nw xY w G d de          Z! G d de          Z" ee!          d             Z# G d de          Zg dZ$d!dZ% e%             dee&         fd Z'dS )"a	  This module defines the internals to map the spatial functions to the spatial columns.

This module defines the :class:`GenericFunction` class, which is the base for
the implementation of spatial functions in GeoAlchemy.  This module is also
where actual spatial functions are defined. Spatial functions supported by
GeoAlchemy are defined in this module. See :class:`GenericFunction` to know how
to create new spatial functions.

.. note::

    By convention the names of spatial functions are prefixed by ``ST_``.  This
    is to be consistent with PostGIS', which itself is based on the ``SQL-MM``
    standard.

Functions created by subclassing :class:`GenericFunction` can be called
in several ways:

* By using the ``func`` object, which is the SQLAlchemy standard way of calling
  a function. For example, without the ORM::

      select([func.ST_Area(lake_table.c.geom)])

  and with the ORM::

      Session.query(func.ST_Area(Lake.geom))

* By applying the function to a geometry column. For example, without the
  ORM::

      select([lake_table.c.geom.ST_Area()])

  and with the ORM::

      Session.query(Lake.geom.ST_Area())

* By applying the function to a :class:`geoalchemy2.elements.WKBElement`
  object (:class:`geoalchemy2.elements.WKBElement` is the type into
  which GeoAlchemy converts geometry values read from the database), or
  to a :class:`geoalchemy2.elements.WKTElement` object. For example,
  without the ORM::

      conn.scalar(lake['geom'].ST_Area())

  and with the ORM::

      session.scalar(lake.geom.ST_Area())

.. warning::

    A few functions (like `ST_Transform()`, `ST_Union()`, `ST_SnapToGrid()`, ...) can be used on
    several spatial types (:class:`geoalchemy2.types.Geometry`,
    :class:`geoalchemy2.types.Geography` and / or :class:`geoalchemy2.types.Raster` types). In
    GeoAlchemy2, these functions are only defined for the :class:`geoalchemy2.types.Geometry` type,
    as it can not be defined for several types at the same time. Therefore, using these functions on
    :class:`geoalchemy2.types.Geography` or :class:`geoalchemy2.types.Raster` requires minor
    tweaking to enforce the type by passing the `type_=Geography` or `type_=Raster` argument to the
    function::

        s = select([func.ST_Transform(
                            lake_table.c.raster,
                            2154,
                            type_=Raster)
                        .label('transformed_raster')])

Reference
---------

    N)List)Type)inspect)compiles)
annotation)	functions)ColumnElement)
FromClause)elements)
_FUNCTIONS)_get_docstring_GeoFunctionBase_GeoFunctionParent)_GenericMeta)with_metaclassc                   (     e Zd ZdZdZd fdZ xZS )_GeoGenericMetazExtend the registering mechanism of sqlalchemy.

        The spatial functions are registered in a specific registry for geoalchemy2.
        FreturnNc                     t           j                            |                                           t	          t
          |                               |||           d S N)r   function_registryaddlowersuperr   __init__)clsclsnamebasesclsdict	__class__s       P/var/www/html/reinick/venv/lib/python3.11/site-packages/geoalchemy2/functions.pyr   z_GeoGenericMeta.__init__e   sJ    &**7==??;;;/3''00%IIIII    r   N)__name__
__module____qualname____doc__	_registerr   __classcell__r    s   @r!   r   r   ]   sX        	 	
 		J 	J 	J 	J 	J 	J 	J 	J 	J 	Jr"   r   c                   8     e Zd Zd fdZedd            Z xZS )GeoGenericFunctionr   Nc                     t           j        | j        vr |                     | j        | j                   t                                                       d S r   )r   	Annotated__mro___register_geo_functionr$   __dict__r   __init_subclass__)r   r    s    r!   r2   z$GeoGenericFunction.__init_subclass__q   sI    #3;66**3<FFFGG%%'''''r"   c                     t          | dd          | _        | j        r3t          j                            |                                           d S d| _        d S )Nr(   T)getattrr(   r   r   r   r   )r   r   r   s      r!   r0   z)GeoGenericFunction._register_geo_functionv   sU     $Cd;;CM } %*..w}}????? !%r"   r#   )r$   r%   r&   r2   classmethodr0   r)   r*   s   @r!   r,   r,   p   s]        	( 	( 	( 	( 	( 	(
 
		% 		% 		% 
		% 		% 		% 		% 		%r"   r,   c                   X    e Zd ZU dZeed<   	 deddfdZedee	         fd            Z
dS )TableRowElementFinherit_cache
selectabler   Nc                     || _         d S r   r9   )selfr9   s     r!   r   zTableRowElement.__init__   s    $r"   c                     | j         gS r   r;   )r<   s    r!   _from_objectszTableRowElement._from_objects   s      r"   )r$   r%   r&   r8   bool__annotations__r   propertyr   r
   r>    r"   r!   r7   r7      sw         M4/%4 %D % % % % !tJ/ ! ! ! X! ! !r"   r7   c                   >    e Zd ZU dZd Zeed<   dZeed<   	 d	dZ	dZdS )
ST_AsGeoJSONzSpecial process for the ST_AsGeoJSON() function.

    This is to be able to work with its feature version introduced in PostGIS 3.
    nameTr8   r   Nc                 F   |                     dd           }t          |          }||g|z   }t          |          D ]\  }}t          |t          j                  r t          |t          j                  rM|j        r|j	        }|j
        g}n|j        }|j
        |j        g} t          t          j        |          | ||<   	 t          |          }	t!          |	d          rt#          |	j                  ||<   # t&          $ r Y w xY wt)          j        | g|R i | d S )Nexprr9   )poplist	enumerate
isinstancer   Functionr   _SpatialElementextendedgeom_from_extended_versiondata	geom_fromsridr4   funcr   hasattrr7   r9   	Exceptionr   r   )
r<   argskwargsrG   	args_listidxelement	func_name	func_argsinsps
             r!   r   zST_AsGeoJSON.__init__   sN   zz&$''JJ	*I%i00 	 	LC'9#566 GX%=>> # = ' BI!(II ' 1I!(w| <I!C!C!CY!O	#"7++Dt\22 J)8)I)I	#    H 	#D?9????????s   6C<<
D	D	a7  Return the geometry as a GeoJSON "geometry" object, or the row as a GeoJSON feature" object (PostGIS 3 only). (Cf GeoJSON specifications RFC 7946). 2D and 3D Geometries are both supported. GeoJSON only support SFS 1.1 geometry types (no curve support for example). See https://postgis.net/docs/ST_AsGeoJSON.htmlr#   )
r$   r%   r&   r'   rE   strr@   r8   r?   r   rB   r"   r!   rD   rD      sa          
 D#M4.@ @ @ @6	9 GGr"   rD   c                 <    |j         t          | j        j                  d         fi |}t	          | j        dd          }| j        j        }d|d|d}t          j        ||          }|r|                    d          S |	                    d          d         S )	Nr   schema z(.?z	.?\.)?(.?z.?)\.   .)
processrI   r9   columnsr4   rE   rematchgroupsplit)rZ   compilerkwcompiledr`   rE   patternms           r!   _compile_table_row_thingro      s      xW%7%? @ @ CJJrJJH
 W'266F"DD*0&&$$$7G
(##A wwqzz >>#q!!r"   c                       e Zd ZdZdZddZdS )GenericFunctionaJ  The base class for GeoAlchemy functions.

    This class inherits from ``sqlalchemy.sql.functions.GenericFunction``, so
    functions defined by subclassing this class can be given a fixed return
    type. For example, functions like :class:`ST_Buffer` and
    :class:`ST_Envelope` have their ``type`` attributes set to
    :class:`geoalchemy2.types.Geometry`.

    This class allows constructs like ``Lake.geom.ST_Buffer(2)``. In that
    case the ``Function`` instance is bound to an expression (``Lake.geom``
    here), and that expression is passed to the function when the function
    is actually called.

    If you need to use a function that GeoAlchemy does not provide you will
    certainly want to subclass this class. For example, if you need the
    ``ST_TransScale`` spatial function, which isn't (currently) natively
    supported by GeoAlchemy, you will write this::

        from geoalchemy2 import Geometry
        from geoalchemy2.functions import GenericFunction

        class ST_TransScale(GenericFunction):
            name = 'ST_TransScale'
            type = Geometry
    Fr   Nc                    |                     dd           }t          |          }||g|z   }t          |          D ]k\  }}t          |t          j                  rL|j        r|j        }|j        g}n|j	        }|j        |j
        g} t          t          j        |          | ||<   lt          j        | g|R i | d S )NrG   )rH   rI   rJ   rK   r   rM   rN   rO   rP   rQ   rR   r4   r   rS   r   r   )	r<   rV   rW   rG   rX   rY   elemr[   r\   s	            r!   r   zGenericFunction.__init__   s    zz&$''JJ	*I"9-- 	P 	PIC$ 899 P= 7 $ ?I!%II $I!%DI 6I!C!C!CY!O	##D?9????????r"   r#   )r$   r%   r&   r'   r(   r   rB   r"   r!   rq   rq      s?         8 I@ @ @ @ @ @r"   rq   )rq   rD   r7   r   c                      t           D ]b\  } }}| dt          | ||          d}|||d<   t          | t          f|          t	                      | <   t
                              |            cd S )NT)rE   r8   r'   type)r   r   ru   rq   globals__all__append)rE   type_doc
attributess       r!   _create_dynamic_functionsr|     s    &  eS!%dC77
 

 !&Jvto%7DD		$t r"   c                      t           S r   )rw   rB   r"   r!   __dir__r~      s    Nr"   r#   )(r'   rf   typingr   r   
sqlalchemyr   sqlalchemy.ext.compilerr   sqlalchemy.sqlr   r   sqlalchemy.sql.elementsr	   sqlalchemy.sql.selectabler
   geoalchemy2r   geoalchemy2._functionsr   geoalchemy2._functions_helpersr   rq   r@   sqlalchemy.sql.functionsr   sqlalchemy.utilr   r   r   r   ImportErrorr,   r7   rD   ro   rw   r|   r^   r~   rB   r"   r!   <module>r      s  C C CJ 
			                   , , , , , , % % % % % % $ $ $ $ $ $ 1 1 1 1 1 1 0 0 0 0 0 0             - - - - - - 9 9 9 9 9 9y01 1 1 123 3 3 3,, 655555......J J J J J, J J J &~oy7PQQ"2 , , ,% % % % %Y6 % % %$ *+-,2	! 	! 	! 	! 	!m 	! 	! 	!* * * * *# * * *Z 
/" " ",-@ -@ -@ -@ -@& -@ -@ -@`           c      s   +2B B=<B=