
5dVA              	   @   s8  d  Z  d d l Z d d l m Z m Z d d l m Z m Z m Z m	 Z	 d d l m
 Z
 m Z m Z Gd d   d e  Z d d	 d
  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z Gd d   d e  Z e e e  e e e d d d d d d Z e j   e e e d d d d  d d! Z e j   e e e d d" d d# d d$ Z e j   e d% e d d& d d' d d( Z e j   e d) e d d* d d+ d d, Z e j   e d- e d d. d d/ d d0 Z e j   d S)1z1Implementation of the Range type and adaptation

    N)ProgrammingErrorInterfaceError)	ISQLQuoteadaptregister_adapterb)new_typenew_array_typeregister_typec               @   s*  e  Z d  Z d Z d, Z d d d d d d	  Z d
 d   Z e d d    Z e d d    Z	 e d d    Z
 e d d    Z e d d    Z e d d    Z e d d    Z d d   Z d d   Z d d   Z d  d!   Z d" d#   Z d$ d%   Z d& d'   Z d( d)   Z d* d+   Z d S)-Rangea  Python representation for a PostgreSQL |range|_ type.

    :param lower: lower bound for the range. `!None` means unbound
    :param upper: upper bound for the range. `!None` means unbound
    :param bounds: one of the literal strings ``()``, ``[)``, ``(]``, ``[]``,
        representing whether the lower or upper bounds are included
    :param empty: if `!True`, the range is empty

    _lower_upper_boundsNz[)Fc             C   s^   | sC | d k r% t  d |   n  | |  _ | |  _ | |  _ n d  |  _ |  _ |  _ d  S)N[)(]()[]zbound flags not valid: %r)r   r   r   r   )
ValueErrorr   r   r   )selflowerupperboundsempty r   3/tmp/pip-build-0jahl3lb/psycopg2/psycopg2/_range.py__init__-   s    		zRange.__init__c             C   sD   |  j  d  k r d |  j j Sd |  j j |  j |  j |  j  f Sd  S)Nz%s(empty=True)z%s(%r, %r, %r))r   	__class____name__r   r   )r   r   r   r   __repr__8   s    zRange.__repr__c             C   s   |  j  S)z:The lower bound of the range. `!None` if empty or unbound.)r   )r   r   r   r   r   ?   s    zRange.lowerc             C   s   |  j  S)z:The upper bound of the range. `!None` if empty or unbound.)r   )r   r   r   r   r   D   s    zRange.upperc             C   s   |  j  d k S)z`!True` if the range is empty.N)r   )r   r   r   r   isemptyI   s    zRange.isemptyc             C   s    |  j  d k r d S|  j d k S)z0`!True` if the range doesn't have a lower bound.NF)r   r   )r   r   r   r   	lower_infN   s     zRange.lower_infc             C   s    |  j  d k r d S|  j d k S)z1`!True` if the range doesn't have an upper bound.NF)r   r   )r   r   r   r   	upper_infT   s     zRange.upper_infc             C   s7   |  j  d k r d S|  j d k r& d S|  j  d d k S)z4`!True` if the lower bound is included in the range.NFr   [)r   r   )r   r   r   r   	lower_incZ   s
      zRange.lower_incc             C   s7   |  j  d k r d S|  j d k r& d S|  j  d d k S)z4`!True` if the upper bound is included in the range.NF   ])r   r   )r   r   r   r   	upper_inca   s
      zRange.upper_incc             C   s   |  j  d  k r d S|  j d  k	 ra |  j  d d k rK | |  j k  r^ d Sqa | |  j k ra d Sn  |  j d  k	 r |  j  d d k r | |  j k r d Sq | |  j k r d Sn  d S)NFr   r"   r$   r%   T)r   r   r   )r   xr   r   r   __contains__h   s         zRange.__contains__c             C   s   |  j  d  k	 S)N)r   )r   r   r   r   __bool__x   s    zRange.__bool__c             C   sG   t  | t  s d S|  j | j k oF |  j | j k oF |  j | j k S)NF)
isinstancer   r   r   r   )r   otherr   r   r   __eq__{   s
    zRange.__eq__c             C   s   |  j  |  S)N)r,   )r   r+   r   r   r   __ne__   s    zRange.__ne__c             C   s   t  |  j |  j |  j f  S)N)hashr   r   r   )r   r   r   r   __hash__   s    zRange.__hash__c             C   s   t  | t  s t Sxe d D]] } t |  |  } t | |  } | | k rM q | d  k r] d S| d  k rm d S| | k  Sq Wd S)Nr   r   r   TF)z_lowerz_upperz_bounds)r*   r   NotImplementedgetattr)r   r+   attrZ
self_valueZother_valuer   r   r   __lt__   s    zRange.__lt__c             C   s!   |  | k r d S|  j  |  Sd  S)NT)r3   )r   r+   r   r   r   __le__   s    zRange.__le__c             C   s$   t  | t  r | j |   St Sd  S)N)r*   r   r3   r0   )r   r+   r   r   r   __gt__   s    zRange.__gt__c             C   s!   |  | k r d S|  j  |  Sd  S)NT)r5   )r   r+   r   r   r   __ge__   s    zRange.__ge__)z_lowerz_upperz_bounds)r   
__module____qualname____doc__	__slots__r   r   propertyr   r   r   r    r!   r#   r&   r(   r)   r,   r-   r/   r3   r4   r5   r6   r   r   r   r   r   !   s(   	r   Fc             C   s3   t  j |  | |  } | j | r( | p+ d  | S)a  Create and register an adapter and the typecasters to convert between
    a PostgreSQL |range|_ type and a PostgreSQL `Range` subclass.

    :param pgrange: the name of the PostgreSQL |range| type. Can be
        schema-qualified
    :param pyrange: a `Range` strict subclass, or just a name to give to a new
        class
    :param conn_or_curs: a connection or cursor used to find the oid of the
        range and its subtype; the typecaster is registered in a scope limited
        to this object, unless *globally* is set to `!True`
    :param globally: if `!False` (default) register the typecaster only on
        *conn_or_curs*, otherwise register it globally
    :return: `RangeCaster` instance responsible for the conversion

    If a string is passed to *pyrange*, a new `Range` subclass is created
    with such name and will be available as the `~RangeCaster.range` attribute
    of the returned `RangeCaster` object.

    The function queries the database on *conn_or_curs* to inspect the
    *pgrange* type and raises `~psycopg2.ProgrammingError` if the type is not
    found.  If querying the database is not advisable, use directly the
    `RangeCaster` class and register the adapter and typecasters using the
    provided functions.

    N)RangeCaster_from_db	_register)pgrangepyrangeconn_or_cursZgloballyZcasterr   r   r   register_range   s    rB   c               @   sL   e  Z d  Z d Z d Z d d   Z d d   Z d d   Z d	 d
   Z d S)RangeAdapterz`ISQLQuote` adapter for `Range` subclasses.

    This is an abstract class: concrete classes must set a `name` class
    attribute or override `getquoted()`.
    Nc             C   s   | |  _  d  S)N)adapted)r   rD   r   r   r   r      s    zRangeAdapter.__init__c             C   s   |  j  t k r |  Sd  S)N)Z_protor   )r   protor   r   r   __conform__   s    zRangeAdapter.__conform__c             C   s   | |  _  d  S)N)_conn)r   connr   r   r   prepare   s    zRangeAdapter.preparec             C   s  |  j  d  k r t d   n  |  j } | j rA t d |  j   S| j d  k	 r t | j  } t | d  r | j |  j	  n  | j
   } n d } | j d  k	 r t | j  } t | d  r | j |  j	  n  | j
   } n d } t |  j  d  | d | t d | j  S)NzMRangeAdapter must be subclassed overriding its name or the getquoted() methodz	'empty'::rI   s   NULL(s   , z, '%s'))nameNotImplementedErrorrD   r   r   r   r   hasattrrI   rG   	getquotedr   r   )r   rar   r   r   r   r   rN      s&    		zRangeAdapter.getquoted)	r   r7   r8   r9   rK   r   rF   rI   rN   r   r   r   r   rC      s   rC   c               @   s   e  Z d  Z d Z d d d  Z d d   Z e d d    Z e j	 d	 e j
  Z e j	 d
  Z d d d  Z d d d  Z d S)r<   a	  Helper class to convert between `Range` and PostgreSQL range types.

    Objects of this class are usually created by `register_range()`. Manual
    creation could be useful if querying the database is not advisable: in
    this case the oids must be provided.
    Nc             C   s   | |  _  |  j | |  |  j j p1 |  j j j } t | f | |  j  |  _ | d  k	 r} t	 | f | d |  j  |  _
 n	 d  |  _
 d  S)NARRAY)subtype_oid_create_rangesadapterrK   r   r   r   parse
typecasterr	   array_typecaster)r   r?   r@   oidrR   	array_oidrK   r   r   r   r     s    	zRangeCaster.__init__c             C   s2  d |  _  t | t  r? t | t f i   |  _  | |  j  _ n@ y+ t | t  ri | t k	 ri | |  _  n  Wn t k
 r~ Yn X|  j  d k r t d   n  d |  _ yU t | t  r t | t	 f i   |  _ n  t | t	  r | t	 k	 r | |  _ n  Wn t k
 rYn X|  j d k r.t d   n  d S)z0Create Range and RangeAdapter classes if needed.Nz:pgrange must be a string or a RangeAdapter strict subclassz1pyrange must be a type or a Range strict subclass)
rT   r*   strtyperC   rK   
issubclass	TypeErrorranger   )r   r?   r@   r   r   r   rS     s.    		zRangeCaster._create_rangesc             C   sQ  d d l  m } d d l m } | |  \ } } | j d k  rW t d | j   n  | j } d | k r | j d d  \ }	 }
 n | }
 d }	 y | j d	 |
 |	 f  Wn+ t k
 r | j	 s | j
   n    Yn0 X| j   } | | k r
| j	 r
| j
   n  | s#t d
 |   n  | \ } } } t | | d | d | d | S)z|Return a `RangeCaster` instance for the type *pgrange*.

        Raise `ProgrammingError` if the type is not found.
        r   )STATUS_IN_TRANSACTION)_solve_conn_cursiX` z'range types not available in version %s.r$   publiczselect rngtypid, rngsubtype,
    (select typarray from pg_type where oid = rngtypid)
from pg_range r
join pg_type t on t.oid = rngtypid
join pg_namespace ns on ns.oid = typnamespace
where typname = %s and ns.nspname = %s;
zPostgreSQL type '%s' not foundrX   rR   rY   )psycopg2.extensionsr_   Zpsycopg2.extrasr`   Zserver_versionr   statussplitexecuteZ
autocommitrollbackZfetchoner<   )r   rK   r@   rA   r_   r`   rH   ZcursZconn_statusZschematnameZrecr[   subtypearrayr   r   r   r=   5  s8    		
zRangeCaster._from_dba]  
        ( \(|\[ )                   # lower bound flag
        (?:                         # lower bound:
          " ( (?: [^"] | "")* ) "   #   - a quoted string
          | ( [^",]+ )              #   - or an unquoted string
        )?                          #   - or empty (not catched)
        ,
        (?:                         # upper bound:
          " ( (?: [^"] | "")* ) "   #   - a quoted string
          | ( [^"\)\]]+ )           #   - or an unquoted string
        )?                          #   - or empty (not catched)
        ( \)|\] )                   # upper bound flag
        z	(["\\])\1c             C   sg  | d  k r d  S| d k r, |  j  d d  S|  j j |  } | d  k r] t d |   n  | j d  } | d  k r | j d  } | d  k	 r |  j j d |  } q n  | j d  } | d  k r | j d  } | d  k	 r |  j j d |  } q n  | d  k	 r8| j |  j |  } | j |  j |  } n  | j d	  | j d
  } |  j  | | |  S)Nr   Tzfailed to parse range: '%s'      z\1      r$      )	r^   	_re_rangematchr   group_re_undoublesubcastrR   )r   scurmr   r   r   r   r   r   rU   }  s,    zRangeCaster.parsec             C   sI   t  |  j |  |  j d  k	 r2 t  |  j |  n  t |  j |  j  d  S)N)r
   rV   rW   r   r^   rT   )r   Zscoper   r   r   r>     s    zRangeCaster._register)r   r7   r8   r9   r   rS   classmethodr=   recompileVERBOSErp   rs   rU   r>   r   r   r   r   r<      s   "8r<   c               @   s   e  Z d  Z d Z d S)NumericRangezA `Range` suitable to pass Python numeric types to a PostgreSQL range.

    PostgreSQL types :sql:`int4range`, :sql:`int8range`, :sql:`numrange` are
    casted into `!NumericRange` instances.
    N)r   r7   r8   r9   r   r   r   r   r}     s   r}   c               @   s   e  Z d  Z d Z d S)	DateRangez#Represents :sql:`daterange` values.N)r   r7   r8   r9   r   r   r   r   r~     s   r~   c               @   s   e  Z d  Z d Z d S)DateTimeRangez!Represents :sql:`tsrange` values.N)r   r7   r8   r9   r   r   r   r   r     s   r   c               @   s   e  Z d  Z d Z d S)DateTimeTZRangez#Represents :sql:`tstzrange` values.N)r   r7   r8   r9   r   r   r   r   r     s   r   c               @   s"   e  Z d  Z d Z d d   Z d S)NumberRangeAdapterz1Adapt a range if the subtype doesn't need quotes.c             C   s   |  j  } | j r d S| j s@ t | j  j   j d  } n d } | j sp t | j  j   j d  } n d } d | j	 d | | | j	 d f j
 d  S)Ns   'empty'ascii z'%s%s,%s%s'r   r$   )rD   r   r    r   r   rN   decoder!   r   r   encode)r   rO   r   r   r   r   r   rN     s    			!	!zNumberRangeAdapter.getquotedN)r   r7   r8   r9   rN   r   r   r   r   r     s   r   rX   i@  rR      rY   iA  iV     iW  iB  i  iC  Z	daterangeiH  i:  iI  ZtsrangeiD  iZ  iE  Z	tstzrangeiF  i  iG  )r9   rz   Zpsycopg2._psycopgr   r   rc   r   r   r   r   r   r	   r
   objectr   rB   rC   r<   r}   r~   r   r   r   Zint4range_casterr>   Zint8range_casterZnumrange_casterZdaterange_casterZtsrange_casterZtstzrange_casterr   r   r   r   <module>   s@   "0





