o 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[)FcCsF|s|dvr td|||_||_||_dSd|_|_|_dS)N)rz(]z()z[]zbound flags not valid: ) ValueErrorr r r)selflowerupperboundsemptyr1/usr/lib/python3/dist-packages/psycopg2/_range.py__init__/s zRange.__init__cCs2|jdur |jjdSd|jj|j|j|jS)Nz (empty=True)z{}({!r}, {!r}, {!r}))r __class____name__formatr r rrrr__repr__:s   zRange.__repr__cCs>|jdurdS|jdt|jdt|j|jdg}d|S)Nrrz, )rstrr r join)ritemsrrr__str__As  z Range.__str__cC|jS)z:The lower bound of the range. `!None` if empty or unbound.)r rrrrrNz Range.lowercCr$)z:The upper bound of the range. `!None` if empty or unbound.)r rrrrrSr%z Range.uppercCs |jduS)z`!True` if the range is empty.NrrrrrisemptyXs z Range.isemptycC|jdurdS|jduS)z0`!True` if the range doesn't have a lower bound.NFrr rrrr lower_inf]  zRange.lower_infcCr()z1`!True` if the range doesn't have an upper bound.NFrr rrrr upper_infdr+zRange.upper_infcC&|jdus |jdur dS|jddkS)z4`!True` if the lower bound is included in the range.NFr[r)rrrr lower_inckzRange.lower_inccCr.)z4`!True` if the upper bound is included in the range.NFr]r,rrrr upper_incrr1zRange.upper_inccCs|jdurdS|jdur"|jddkr||jkrdSn||jkr"dS|jdur>|jddkr7||jkr5dSdS||jkr>dSdS)NFrr/rr2T)rr r )rxrrr __contains__ys"       zRange.__contains__cCs |jduSNr&rrrr__bool__ zRange.__bool__cCst||Sr6)typer7rrrr __nonzero__szRange.__nonzero__cCs2t|tsdS|j|jko|j|jko|j|jkS)NF) isinstancer r r rrotherrrr__eq__s    z Range.__eq__cCs || Sr6)r>r<rrr__ne__s z Range.__ne__cCst|j|j|jfSr6)hashr r rrrrr__hash__szRange.__hash__cCs`t|tstSdD]$}t||}t||}||krq |dur!dS|dur(dS||kSdS)Nr TF)r;r NotImplementedgetattr)rr=attr self_value other_valuerrr__lt__s    z Range.__lt__cC||krdS||SNT)rGr<rrr__le__ z Range.__le__cCst|tr ||StSr6)r;r rGrBr<rrr__gt__s  z Range.__gt__cCrHrI)rLr<rrr__ge__rKz Range.__ge__csfddjDS)Ncs"i|] }t|r|t|qSr)hasattrrC).0slotrrr s z&Range.__getstate__..) __slots__rrrr __getstate__s zRange.__getstate__cCs"|D] \}}t|||qdSr6)r"setattr)rstaterPvaluerrr __setstate__szRange.__setstate__)NNrF)r __module__ __qualname____doc__rRrrr#propertyrrr'r*r-r0r3r5r7r:r>r?rArGrJrLrMrSrWrrrrr #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_cursgloballycasterrrrregister_rangesrdc@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()`. NcC ||_dSr6)adapted)rrgrrrrr8zRangeAdapter.__init__cCs|jtur|SdSr6)_protor)rprotorrr __conform__s zRangeAdapter.__conform__cCrfr6)_conn)rconnrrrpreparer8zRangeAdapter.preparecCs|jdur td|j}|jrd|jdS|jdur1t|j}t|dr,||j | }nd}|j durMt|j }t|drH||j | }nd}|jdd|d|d|j dd S) NzMRangeAdapter must be subclassed overriding its name or the getquoted() methods 'empty'::utf8rmsNULL(s, s, 's')) nameNotImplementedErrorrgr'encoderrrNrmrk getquotedrr)rrarrrrrrss4            zRangeAdapter.getquoted) rrXrYrZrprrjrmrsrrrrres rec@sZeZdZdZdddZddZeddZe d ej Z e d Z dd d Z dd dZdS)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. NcCsb||_||||jjp|jjj}t|f||j|_|dur,t |f|d|j|_ dSd|_ dS)NARRAY) subtype_oid_create_rangesadapterrprrrparse typecasterrarray_typecaster)rr_r`oidrw array_oidrprrrr(s  zRangeCaster.__init__cCsd|_t|trt|tfi|_||j_nzt|tr"|tur"||_Wn ty,Ynw|jdur6tdd|_zt|trGt|t fi|_t|t rS|t urS||_Wn ty]Ynw|jdurgtddS)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) ryr;r r9rerp issubclass TypeErrorranger )rr_r`rrrrx6s>        zRangeCaster._create_rangescCsddlm}ddlm}||\}}|jjdkr td|jj|j}d|vr0|dd\} } n|} d} z | d | | fWntyM|j sL| w| } ||kr]|j s]| | sgtd |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 foundr}rwr~)psycopg2.extensionsrpsycopg2.extrasrinfoserver_versionrstatussplitexecute autocommitrollbackfetchoner\)rrpr`rarrrlcurs conn_statusschematnamerecr9subtypearrayrrrr]YsD       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|durdS|dkr|jddS|j|}|dur"td|d|d}|dur;|d}|dur;|jd|}|d }|durT|d }|durT|jd|}|durf||j|}||j|}|d |d }||||S) NrT)rzfailed to parse range: ''z\1r) r _re_rangematchrgroup _re_undoublesubcastrw)rscurmrrrrrrrzs,      zRangeCaster.parsecCs4t|j||jdurt|j|t|j|jdSr6)r r{r|rrry)rscoperrrr^s   zRangeCaster._registerr6)rrXrYrZrrx classmethodr]recompileVERBOSErrrzr^rrrrr\!s # 7   r\c@eZdZdZdS) 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. NrrXrYrZrrrrrsrc@r) DateRangez#Represents :sql:`daterange` values.Nrrrrrrrc@r) DateTimeRangez!Represents :sql:`tsrange` values.Nrrrrrrrrc@r)DateTimeTZRangez#Represents :sql:`tstzrange` values.Nrrrrrrrrc@seZdZdZddZdS)NumberRangeAdapterz1Adapt a range if the subtype doesn't need quotes.cCs||j}|jrdS|jst|jd}nd}|js&t|jd}nd}d|j d|d||j dd dS)Ns'empty'asciirrr,r) rgr'r*rrrsdecoder-rrrr)rrtrrrrrrss,zNumberRangeAdapter.getquotedN)rrXrYrZrsrrrrrs ri@iAriViWiBiiC daterangeiHi:iItsrangeiDiZiE tstzrangeiFiiG)F)rZrpsycopg2._psycopgrrrrrrrrr r rdrer\rrrrrint4range_casterr^int8range_casternumrange_casterdaterange_castertsrange_castertstzrange_casterrrrrsR 00(