m &Ec@sWdkZdkZdklZdklZdkZdkZdklZdk l Z dk Z dk lZlZlZdklZdklZdklZlZlZd klZlZeid Zyd klZWne j od ZnXd e!fdYZ"de ei#ei$fdYZ%dfdYZ&dZ'dS(N(sbisect(srandint(sMV(s Persistent(s intersectionsweightedIntersectionsIISet(sOIBTree(sIOBTree(sLazyMapsLazyCats LazyValues(sAbstractCatalogBrains NoBrainers Zope.ZCatalog(s safe_callablecCsBt|do$t|dpt|tiSn t|SdS(Nt __class__t__call__(thasattrtobt isinstancettypest ClassTypetcallable(R((t8/data/zmath/zope/lib/python/Products/ZCatalog/Catalog.pyt safe_callable's$t CatalogErrorcBstZRS(N(t__name__t __module__(((RR /stCatalogcBsFtZdZeZeedZdZdZdZ dZ e fdZ dZ dZed Zd Zd Zd Zd ZdZeeddZdZdZdZdZdZdZdZededdZdeddZdZdZ eeddZ!e!Z"RS(s An Object Catalog An Object Catalog maintains a table of object metadata, and a series of manageable indexes to quickly search for objects (references in the metadata) that satisfy a search query. This class is not Zope specific, and can be used in any python program to build catalogs of objects. Note that it does require the objects to be Persistent, and thus must be used with ZODB3. cCsMh|_f|_h|_|i|dj o ||_n|idS(N( tselftschematnamestindexestcleartbrainstNonet _v_brainst updateBrains(Rt vocabularyR((Rt__init__@s     cCs |iS(N(Rt_length(R((Rt__len__YscCsGt|dp3|id}|id=tii||_ndS(s- migration of old __len__ magic for Zope 2.8 RRN(RRt__dict__tntBTreestLengthR(RR((Rtmigrate__len__\s  cCsgt|_t|_t|_tii|_x*|i i D]}|i |i qFWdS(s clear catalog N(tIOBTreeRtdatatOIBTreetuidstpathsRRRRtkeystindextgetIndexR(RR&((RRcs   cCs|i|idS(N(Rt useBrainsR(R((RRnscCst||joP|\}}}|i|i|i |i }||_ ||_ ||_n>|i|i|i |i }||_ d|_ d|_|S(si Returns instances of self._v_brains, or whatever is passed into self.useBrains. iN(ttypeR&tttypetnormalized_scoretscoretkeyRt_v_result_classR!t__of__t aq_parenttrtdata_record_id_tdata_record_score_tdata_record_normalized_score_(RR&R*R+R,R-R1((Rt __getitem__qs"   "   cCsti|||idS(sz initialize your brains. This method is called when the catalog is first activated (from the persistent storage) N(t Persistentt __setstate__RtstateR(RR8((RR7scCsdt|fdY}|ii}t|ii|d|D]6}|i |}t |do|i|qPqPW||=||=||=t |dp|in|iidntidt|dS(sW Uncatalog and object from the Catalog. and 'uid' is a unique Catalog identifier Note, the uid must be the same as when the object was catalogued, otherwise it will not get removed from the catalog This method should not raise an exception if the uid cannot be found in the catalog. tunindex_objectRisRuncatalogObject unsuccessfully attempted to uncatalog an object with a uid of %s. N(RR!R#R$RR%RYRZRtridRCR'RhRRlRRRdRNRORP( RRZR$RCRRhRmR!R#((RtuncatalogObjectos&     cCs|i|iS(s* return unique values for FieldIndex name N(RR'RCt uniqueValues(RRC((RtuniqueValuesForscCs|ii|S(s7 return the rid if catalog contains an object with uid N(RR#RYRZ(RRZ((RthasuidscCsjg}xW|iD]L}t||t}|tj ot|o |}n|i |qWt |S(s% turns an object into a record tuple N( trecordRRRhR^R\RHtattrR RFRJ(RR\RsRrRh((RR[s  cCs-|i|d}|d|_|i|S(Nii(RR.RrR1R2R/(RRrR1((Rt instantiates cCsE|i|}h}x+|iiD]\}}||||      &  A cCs|djp|djp tdt} t} |i}|i }d}t}g}|i} t|do|i}nt|}|o)|djo|t||ddjod}yt|tfWntj ot|}nXx|iD]u\}}| ||}|oSt|d|}||j o |}n|t|7}| |||fq q W|i|o|i nt!t"||}n|djp|d|joxE|D]=}y||}Wn|j oqX| |||fqW|oJ|i|o|i n|dj o|| }nt"|}qw|Sn|og}d}d}x|D]}y||}Wn|j oqX||jo||joqnt'||} |i)| ||i)| |||f||jo|d=|d=n |d7}|d}qW|i |ot"|}qw|Sn|pg}d}d} x|D]}y||}Wn|j oqX||jo|| joqnt'||} |i)| ||i)| |||f||jo|d=|d=n |d7}|d} qW|ot"|}qw|Snt|i|t|}||_+|S(Nis Limit value must be 1 or greaterR%idiii(,RRtAssertionErrorRt_lazymapt intersectiont _intersectionRR5t_self__getitem__RtdocumentToKeyMapt index_key_mapt_NonetKeyErrort _keyerrorRuRFRRR%R=trlenRtlengthtIISetRURvtktintsetR^tsortRRt LazyValuestdidR-RtworsttbisectRQR`tbesttactual_result_count(RRRRRRRRuRRRFRQRRRRRR%RRR-RRRR((RR"s $    3            cCsld|}|i|d}|dj o|Snt||d}|dj o|Sn|id|dS(s.Helper function to find sort-on or sort-order.ssort-%sssort_%sN(RsRCtkwRYRtvalR^R(RRsRRRC((Rt_get_sort_attrs   cCs|id|}|dj o\|ii|}|djotd|n%t |dptd|n|SndSdS(s&Returns a search index object or None.tonsUnknown sort_on index (%s)tkeyForDocumentsOThe index chosen for sort_on (%s) is not capable of being used as a sort index.N( RRtargstsort_index_nameRRRYRR R(RRRR((Rt _getSortIndexs  c Ks|djo| ot|dd}nt||}|i|}|i d|}d}|dj oC|i d|} t | to| idjo d}qn|i|||||S( NtREQUESTRitorderRt descendingi(sreverseR(RRRR^RtCatalogSearchArgumentsMapRRRRt sort_limitRRRRPtlowerRt_merge( RRtusedRRRRRRR((Rt searchResultss #(#R R t__doc__t NoBrainerRRRRRRRR)R5R7R(RLRRRVRWR'RaRkRnRpRqR[RtRxRzRRRRRR(((RR 2s<       &    )6 $     h  RcBs5tZdZdZdZedZdZRS(s Multimap catalog arguments coming simultaneously from keywords and request. Values that are empty strings are treated as non-existent. This is to ignore empty values, thereby ignoring empty form fields to be consistent with hysterical behavior. cCs$|ph|_|ph|_dS(N(RRtkeywords(RRR((RRscCsgg}|ii||}||jp |djo|i|}n|djot|n|S(NR@(tmarkerRRRYR-tvRR(RR-RR((RR5s cCs0y||}Wntj o |SnX|SdS(N(RR-RRtdefault(RR-RR((RRYs  cCs.y ||Wntj o dSnXdSdS(Nii(RR-R(RR-((RRBs   (R R RRR5RRYRB(((RRs   cCs|pt|Snt|djo(g}xD|D]}|i|q5Wn&t|djo|d}ngS|i|o|int d|t|SdS(sSort/merge sub-results, generating a flat sequence. results is a list of result set sequences, all with or without sort keys iicCs|d|dS(Nii(RI(RI((Rt!sN( t has_sort_keysRtresultsR=tallR1textendRRR(RRRRR1((Rt mergeResults s ((RtloggingRtrandomR_t AcquisitiontExtensionClasstMissingRHt PersistenceR6t BTrees.LengthRtBTrees.IIBTreeRRRtBTrees.OIBTreeR"tBTrees.IOBTreeR tLazyRRRt CatalogBrainsR:Rt getLoggerRNt"DocumentTemplate.cDocumentTemplateR t ImportErrort ExceptionR tImplicittBaseR RR(RRNR RR_R RRRR R6R:RRRRRR RRRRHR"RR((Rt?s0           "'