<s> """<STR_LIT>""" <EOL> import re <EOL> import string <EOL> import sys <EOL> from google . appengine . api import datastore <EOL> from google . appengine . api import datastore_errors <EOL> from google . appengine . api import datastore_types <EOL> from google . appengine . ext import db <EOL> from google . appengine . datastore import datastore_pb <EOL> class SearchableEntity ( datastore . Entity ) : <EOL> """<STR_LIT>""" <EOL> _FULL_TEXT_INDEX_PROPERTY = '<STR_LIT>' <EOL> _FULL_TEXT_MIN_LENGTH = <NUM_LIT:3> <EOL> _FULL_TEXT_STOP_WORDS = frozenset ( [ <EOL> '<STR_LIT:a>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:all>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:i>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:none>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT:state>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:to>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> _PUNCTUATION_REGEX = re . compile ( '<STR_LIT:[>' + re . escape ( string . punctuation ) + '<STR_LIT:]>' ) <EOL> def __init__ ( self , kind_or_entity , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( kind_or_entity , datastore . Entity ) : <EOL> self . _Entity__key = kind_or_entity . _Entity__key <EOL> self . update ( kind_or_entity ) <EOL> else : <EOL> super ( SearchableEntity , self ) . __init__ ( kind_or_entity , * args , ** kwargs ) <EOL> def _ToPb ( self ) : <EOL> """<STR_LIT>""" <EOL> if SearchableEntity . _FULL_TEXT_INDEX_PROPERTY in self : <EOL> del self [ SearchableEntity . _FULL_TEXT_INDEX_PROPERTY ] <EOL> index = set ( ) <EOL> for ( name , values ) in self . items ( ) : <EOL> if not isinstance ( values , list ) : <EOL> values = [ values ] <EOL> if ( isinstance ( values [ <NUM_LIT:0> ] , basestring ) and <EOL> not isinstance ( values [ <NUM_LIT:0> ] , datastore_types . Blob ) ) : <EOL> for value in values : <EOL> index . update ( SearchableEntity . _FullTextIndex ( value ) ) <EOL> index_list = list ( index ) <EOL> if index_list : <EOL> self [ SearchableEntity . _FULL_TEXT_INDEX_PROPERTY ] = index_list <EOL> return super ( SearchableEntity , self ) . _ToPb ( ) <EOL> @ classmethod <EOL> def _FullTextIndex ( cls , text ) : <EOL> """<STR_LIT>""" <EOL> if text : <EOL> datastore_types . ValidateString ( text , '<STR_LIT:text>' , max_len = sys . maxint ) <EOL> text = cls . _PUNCTUATION_REGEX . sub ( '<STR_LIT:U+0020>' , text ) <EOL> words = text . lower ( ) . split ( ) <EOL> words = set ( words ) <EOL> words -= cls . _FULL_TEXT_STOP_WORDS <EOL> for word in list ( words ) : <EOL> if len ( word ) < cls . _FULL_TEXT_MIN_LENGTH : <EOL> words . remove ( word ) <EOL> else : <EOL> words = set ( ) <EOL> return words <EOL> class SearchableQuery ( datastore . Query ) : <EOL> """<STR_LIT>""" <EOL> def Search ( self , search_query ) : <EOL> """<STR_LIT>""" <EOL> datastore_types . ValidateString ( search_query , '<STR_LIT>' ) <EOL> self . _search_query = search_query <EOL> return self <EOL> def _ToPb ( self , limit = None ) : <EOL> """<STR_LIT>""" <EOL> if SearchableEntity . _FULL_TEXT_INDEX_PROPERTY in self : <EOL> raise datastore_errors . BadFilterError ( <EOL> '<STR_LIT>' % SearchableEntity . _FULL_TEXT_INDEX_PROPERTY ) <EOL> pb = super ( SearchableQuery , self ) . _ToPb ( limit = limit ) <EOL> if hasattr ( self , '<STR_LIT>' ) : <EOL> keywords = SearchableEntity . _FullTextIndex ( self . _search_query ) <EOL> for keyword in keywords : <EOL> filter = pb . add_filter ( ) <EOL> filter . set_op ( datastore_pb . Query_Filter . EQUAL ) <EOL> prop = filter . add_property ( ) <EOL> prop . set_name ( SearchableEntity . _FULL_TEXT_INDEX_PROPERTY ) <EOL> prop . mutable_value ( ) . set_stringvalue ( keyword ) <EOL> return pb <EOL> class SearchableModel ( db . Model ) : <EOL> """<STR_LIT>""" <EOL> class Query ( db . Query ) : <EOL> """<STR_LIT>""" <EOL> _search_query = None <EOL> def search ( self , search_query ) : <EOL> """<STR_LIT>""" <EOL> self . _search_query = search_query <EOL> return self <EOL> def _get_query ( self ) : <EOL> """<STR_LIT>""" <EOL> query = db . Query . _get_query ( self , _query_class = SearchableQuery ) <EOL> if self . _search_query : <EOL> query . Search ( self . _search_query ) <EOL> return query <EOL> def _save_to_entity ( self ) : <EOL> """<STR_LIT>""" <EOL> return db . Model . _save_to_entity ( self , _entity_class = SearchableEntity ) <EOL> @ classmethod <EOL> def all ( cls ) : <EOL> """<STR_LIT>""" <EOL> return SearchableModel . Query ( cls ) </s>
