U aD@srdZddlZddlmZmZddlmZmZmZddlm Z m Z m Z GdddZ d/d d Z Gd d d ZGd ddZGddde ZGddde ZGddde ZGddde ZGdddeZeeeeeeddddZeeeeddddZeeeed d!d"dZeed#ed$d%d&dZeed'ed(d)d*dZeed+ed,d-d.dZedS)0z1Implementation of the Range type and adaptation N)ProgrammingErrorInterfaceError) ISQLQuoteadaptregister_adapter)new_typenew_array_type register_typec@seZdZdZdZd2ddZdd Zd d Zed d Z eddZ eddZ eddZ eddZ eddZeddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Zd0d1ZdS)3RangeaPython 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_boundsN[)FcCsD|s.|dkrtd|||_||_||_nd|_|_|_dS)N)rz(]z()z[]zbound flags not valid: ) ValueErrorr r r)selflowerupperboundsemptyrPC:\Users\vtejo\AppData\Local\Temp\pip-unpacked-wheel-8c51wohf\psycopg2\_range.py__init__/szRange.__init__cCs6|jdkr|jjdSd|jj|j|j|jSdS)Nz (empty=True)z{}({!r}, {!r}, {!r}))r __class____name__formatr r rrrr__repr__:s  zRange.__repr__cCs>|jdkrdS|jdt|jdt|j|jdg}d|S)Nrrz, )rstrr r join)ritemsrrr__str__As z Range.__str__cCs|jS)z:The lower bound of the range. `!None` if empty or unbound.)r rrrrrNsz Range.lowercCs|jS)z:The upper bound of the range. `!None` if empty or unbound.)r rrrrrSsz Range.uppercCs |jdkS)z`!True` if the range is empty.NrrrrrisemptyXsz Range.isemptycCs|jdkrdS|jdkS)z0`!True` if the range doesn't have a lower bound.NFrr rrrr lower_inf]s zRange.lower_infcCs|jdkrdS|jdkS)z1`!True` if the range doesn't have an upper bound.NFrr rrrr upper_infds zRange.upper_infcCs&|jdks|jdkrdS|jddkS)z4`!True` if the lower bound is included in the range.NFr[r&rrrr lower_inckszRange.lower_inccCs&|jdks|jdkrdS|jddkS)z4`!True` if the upper bound is included in the range.NFr]r(rrrr upper_incrszRange.upper_inccCs~|jdkrdS|jdk rD|jddkr6||jkrDdSn||jkrDdS|jdk rz|jddkrl||jkrzdSn||jkrzdSdS)NFrr*rr,T)rr r )rxrrr __contains__ys       zRange.__contains__cCs |jdk SNr$rrrr__bool__szRange.__bool__cCst||Sr0)typer1rrrr __nonzero__szRange.__nonzero__cCs2t|tsdS|j|jko0|j|jko0|j|jkS)NF) isinstancer r r rrotherrrr__eq__s    z Range.__eq__cCs || Sr0)r7r5rrr__ne__sz Range.__ne__cCst|j|j|jfSr0)hashr r rrrrr__hash__szRange.__hash__cCsbt|tstSdD]J}t||}t||}||kr4q|dkrBdS|dkrPdS||kSqdS)Nr TF)r4r NotImplementedgetattr)rr6attrZ self_valueZ other_valuerrr__lt__s   z Range.__lt__cCs||kr dS||SdSNT)r>r5rrr__le__sz Range.__le__cCst|tr||StSdSr0)r4r r>r;r5rrr__gt__s  z Range.__gt__cCs||kr dS||SdSr?)rAr5rrr__ge__sz Range.__ge__csfddjDS)Ncs"i|]}t|r|t|qSr)hasattrr<).0slotrrr s z&Range.__getstate__..) __slots__rrrr __getstate__s zRange.__getstate__cCs"|D]\}}t|||qdSr0)r"setattr)rstaterEvaluerrr __setstate__szRange.__setstate__)NNrF)r __module__ __qualname____doc__rGrrr#propertyrrr%r'r)r+r-r/r1r3r7r8r:r>r@rArBrHrLrrrrr #s>          r FcCs&t|||}|| r|pd|S)aCreate 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)pgrangepyrange conn_or_cursZgloballyZcasterrrrregister_rangesrWc@s4eZdZdZdZddZddZddZd d ZdS) RangeAdapterz`ISQLQuote` adapter for `Range` subclasses. This is an abstract class: concrete classes must set a `name` class attribute or override `getquoted()`. NcCs ||_dSr0)adapted)rrYrrrrszRangeAdapter.__init__cCs|jtkr|SdSr0)Z_protor)rprotorrr __conform__s zRangeAdapter.__conform__cCs ||_dSr0)_conn)rconnrrrprepareszRangeAdapter.preparecCs|jdkrtd|j}|jr.d|jdS|jdk rbt|j}t|drX||j | }nd}|j dk rt|j }t|dr||j | }nd}|jdd|d|d|j dd S) NzMRangeAdapter must be subclassed overriding its name or the getquoted() methods 'empty'::utf8r^sNULL(s, s, 's')) nameNotImplementedErrorrYr%encoderrrCr^r\ getquotedrr)rrarrrrrrds4            zRangeAdapter.getquoted) rrMrNrOrarr[r^rdrrrrrXs rXc@sZeZdZdZdddZddZeddZe d ej Z e d Z dd d Z dd dZdS)rQa 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. NcCs`||_||||jjp"|jjj}t|f||j|_|dk rVt |f|d|j|_ nd|_ dS)NARRAY) subtype_oid_create_rangesadapterrarrrparse typecasterrarray_typecaster)rrTrUoidrh array_oidrarrrr(s zRangeCaster.__init__cCsd|_t|tr*t|tfi|_||j_n2zt|trD|tk rD||_Wntk rZYnX|jdkrntdd|_z6t|trt|t fi|_t|t r|t k r||_Wntk rYnX|jdkrtddS)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) rjr4r r2rXra issubclass TypeErrorranger )rrTrUrrrri6s6        zRangeCaster._create_rangescCsddlm}ddlm}||\}}|jjdkr@td|jj|j}d|kr`|dd\} } n|} d} z| d | | fWn$tk r|j s| Yn X| } ||kr|j s| | std |d | \} } }t ||| | |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.rpubliczselect 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; zPostgreSQL type 'z ' not foundrnrhro)psycopg2.extensionsrsZpsycopg2.extrasrtinfoZserver_versionrstatussplitexecuteZ autocommitrollbackZfetchonerQ)rrarUrVrsrtr]ZcursZ conn_statusZschemaZtnameZrecr2subtypearrayrrrrRYsF       zRangeCaster._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 (["\\])\1cCs|dkr dS|dkr |jddS|j|}|dkrDtd|d|d}|dkrv|d}|dk rv|jd|}|d }|dkr|d }|dk r|jd|}|dk r||j|}||j|}|d |d }||||S) NrT)rzfailed to parse range: ''z\1r) rr _re_rangematchrgroup _re_undoublesubcastrh)rscurmrrrrrrrks,      zRangeCaster.parsecCs4t|j||jdk r"t|j|t|j|jdSr0)r rlrmrrrrj)rZscoperrrrSs   zRangeCaster._register)N)N)N)rrMrNrOrri classmethodrRrecompileVERBOSErrrkrSrrrrrQ!s # 7   rQc@seZdZdZdS) 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. NrrMrNrOrrrrrsrc@seZdZdZdS) DateRangez#Represents :sql:`daterange` values.Nrrrrrrsrc@seZdZdZdS) DateTimeRangez!Represents :sql:`tsrange` values.Nrrrrrrsrc@seZdZdZdS)DateTimeTZRangez#Represents :sql:`tstzrange` values.Nrrrrrrsrc@seZdZdZddZdS)NumberRangeAdapterz1Adapt a range if the subtype doesn't need quotes.cCs||j}|jrdS|js,t|jd}nd}|jsLt|jd}nd}d|j d|d||j dd dS)Ns'empty'asciirrr,r) rYr%r'rrrddecoder)rrrc)rrerrrrrrdszNumberRangeAdapter.getquotedN)rrMrNrOrdrrrrrsri@iArwiViWiBiiCZ daterangeiHi:iIZtsrangeiDiZiEZ tstzrangeiFiiG)F)rOrZpsycopg2._psycopgrrrxrrrrrr r rWrXrQrrrrrZint4range_casterrSZint8range_casterZnumrange_casterZdaterange_casterZtsrange_casterZtstzrange_casterrrrrsh0 0(