<s> import re <EOL> import sys <EOL> from datetime import datetime , timedelta <EOL> from whoosh . compat import string_type , iteritems <EOL> from whoosh . qparser import plugins , syntax <EOL> from whoosh . qparser . taggers import Tagger <EOL> from whoosh . support . relativedelta import relativedelta <EOL> from whoosh . support . times import ( adatetime , timespan , fill_in , is_void , <EOL> TimeError , relative_days ) <EOL> from whoosh . util import rcompile <EOL> class DateParseError ( Exception ) : <EOL> "<STR_LIT>" <EOL> def print_debug ( level , msg , * args ) : <EOL> if level > <NUM_LIT:0> : <EOL> print ( ( "<STR_LIT:U+0020>" * ( level - <NUM_LIT:1> ) ) + ( msg % args ) ) <EOL> class Props ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , ** args ) : <EOL> self . __dict__ = args <EOL> def __repr__ ( self ) : <EOL> return repr ( self . __dict__ ) <EOL> def get ( self , key , default = None ) : <EOL> return self . __dict__ . get ( key , default ) <EOL> class ParserBase ( object ) : <EOL> """<STR_LIT>""" <EOL> def to_parser ( self , e ) : <EOL> if isinstance ( e , string_type ) : <EOL> return Regex ( e ) <EOL> else : <EOL> return e <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> raise NotImplementedError <EOL> def date_from ( self , text , dt = None , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> if dt is None : <EOL> dt = datetime . now ( ) <EOL> d , pos = self . parse ( text , dt , pos , debug + <NUM_LIT:1> ) <EOL> return d <EOL> class MultiBase ( ParserBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , elements , name = None ) : <EOL> """<STR_LIT>""" <EOL> self . elements = [ self . to_parser ( e ) for e in elements ] <EOL> self . name = name <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . __class__ . __name__ , self . name or '<STR_LIT>' , <EOL> self . elements ) <EOL> class Sequence ( MultiBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , elements , sep = "<STR_LIT>" , name = None , <EOL> progressive = False ) : <EOL> """<STR_LIT>""" <EOL> super ( Sequence , self ) . __init__ ( elements , name ) <EOL> self . sep_pattern = sep <EOL> if sep : <EOL> self . sep_expr = rcompile ( sep , re . IGNORECASE ) <EOL> else : <EOL> self . sep_expr = None <EOL> self . progressive = progressive <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> d = adatetime ( ) <EOL> first = True <EOL> foundall = False <EOL> failed = False <EOL> print_debug ( debug , "<STR_LIT>" , self . name , <EOL> self . sep_pattern , text [ pos : ] ) <EOL> for e in self . elements : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , text [ pos : ] ) <EOL> if self . sep_expr and not first : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> m = self . sep_expr . match ( text , pos ) <EOL> if m : <EOL> pos = m . end ( ) <EOL> else : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> break <EOL> print_debug ( debug , "<STR_LIT>" , self . name , e , pos ) <EOL> try : <EOL> at , newpos = e . parse ( text , dt , pos = pos , debug = debug + <NUM_LIT:1> ) <EOL> except TimeError : <EOL> failed = True <EOL> break <EOL> print_debug ( debug , "<STR_LIT>" , self . name , at ) <EOL> if not at : <EOL> break <EOL> pos = newpos <EOL> print_debug ( debug , "<STR_LIT>" , self . name , at , d ) <EOL> try : <EOL> d = fill_in ( d , at ) <EOL> except TimeError : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> failed = True <EOL> break <EOL> print_debug ( debug , "<STR_LIT>" , self . name , d ) <EOL> first = False <EOL> else : <EOL> foundall = True <EOL> if not failed and ( foundall or ( not first and self . progressive ) ) : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , d ) <EOL> return ( d , pos ) <EOL> else : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> return ( None , None ) <EOL> class Combo ( Sequence ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , elements , fn = None , sep = "<STR_LIT>" , min = <NUM_LIT:2> , max = <NUM_LIT:2> , <EOL> name = None ) : <EOL> """<STR_LIT>""" <EOL> super ( Combo , self ) . __init__ ( elements , sep = sep , name = name ) <EOL> self . fn = fn <EOL> self . min = min <EOL> self . max = max <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> dates = [ ] <EOL> first = True <EOL> print_debug ( debug , "<STR_LIT>" , self . name , <EOL> self . sep_pattern , text [ pos : ] ) <EOL> for e in self . elements : <EOL> if self . sep_expr and not first : <EOL> print_debug ( debug , "<STR_LIT>" , <EOL> self . name , text [ pos : ] ) <EOL> m = self . sep_expr . match ( text , pos ) <EOL> if m : <EOL> pos = m . end ( ) <EOL> else : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> return ( None , None ) <EOL> print_debug ( debug , "<STR_LIT>" , self . name , e ) <EOL> try : <EOL> at , pos = e . parse ( text , dt , pos , debug + <NUM_LIT:1> ) <EOL> except TimeError : <EOL> at , pos = None , None <EOL> print_debug ( debug , "<STR_LIT>" , self . name , at ) <EOL> if at is None : <EOL> return ( None , None ) <EOL> first = False <EOL> if is_void ( at ) : <EOL> continue <EOL> if len ( dates ) == self . max : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , self . max ) <EOL> return ( None , None ) <EOL> dates . append ( at ) <EOL> print_debug ( debug , "<STR_LIT>" , self . name , dates ) <EOL> if len ( dates ) < self . min : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , self . min ) <EOL> return ( None , None ) <EOL> return ( self . dates_to_timespan ( dates ) , pos ) <EOL> def dates_to_timespan ( self , dates ) : <EOL> if self . fn : <EOL> return self . fn ( dates ) <EOL> elif len ( dates ) == <NUM_LIT:2> : <EOL> return timespan ( dates [ <NUM_LIT:0> ] , dates [ <NUM_LIT:1> ] ) <EOL> else : <EOL> raise DateParseError ( "<STR_LIT>" % ( dates , ) ) <EOL> class Choice ( MultiBase ) : <EOL> """<STR_LIT>""" <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , text [ pos : ] ) <EOL> for e in self . elements : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , e ) <EOL> try : <EOL> d , newpos = e . parse ( text , dt , pos , debug + <NUM_LIT:1> ) <EOL> except TimeError : <EOL> d , newpos = None , None <EOL> if d : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> return ( d , newpos ) <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> return ( None , None ) <EOL> class Bag ( MultiBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , elements , sep = "<STR_LIT>" , onceper = True , <EOL> requireall = False , allof = None , anyof = None , name = None ) : <EOL> """<STR_LIT>""" <EOL> super ( Bag , self ) . __init__ ( elements , name ) <EOL> self . sep_expr = rcompile ( sep , re . IGNORECASE ) <EOL> self . onceper = onceper <EOL> self . requireall = requireall <EOL> self . allof = allof <EOL> self . anyof = anyof <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> first = True <EOL> d = adatetime ( ) <EOL> seen = [ False ] * len ( self . elements ) <EOL> while True : <EOL> newpos = pos <EOL> print_debug ( debug , "<STR_LIT>" , self . name , text [ pos : ] ) <EOL> if not first : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> m = self . sep_expr . match ( text , pos ) <EOL> if m : <EOL> newpos = m . end ( ) <EOL> else : <EOL> print_debug ( debug , "<STR_LIT>" , self . name ) <EOL> break <EOL> for i , e in enumerate ( self . elements ) : <EOL> print_debug ( debug , "<STR_LIT>" , self . name , e ) <EOL> try : <EOL> at , xpos = e . parse ( text , dt , newpos , debug + <NUM_LIT:1> ) <EOL> except TimeError : <EOL> at , xpos = None , None <EOL> print_debug ( debug , "<STR_LIT>" , self . name , at ) <EOL> if at : <EOL> if self . onceper and seen [ i ] : <EOL> return ( None , None ) <EOL> d = fill_in ( d , at ) <EOL> newpos = xpos <EOL> seen [ i ] = True <EOL> break <EOL> else : <EOL> break <EOL> pos = newpos <EOL> if self . onceper and all ( seen ) : <EOL> break <EOL> first = False <EOL> if ( not any ( seen ) <EOL> or ( self . allof and not all ( seen [ pos ] for pos in self . allof ) ) <EOL> or ( self . anyof and not any ( seen [ pos ] for pos in self . anyof ) ) <EOL> or ( self . requireall and not all ( seen ) ) ) : <EOL> return ( None , None ) <EOL> print_debug ( debug , "<STR_LIT>" , self . name , d ) <EOL> return ( d , pos ) <EOL> class Optional ( ParserBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , element ) : <EOL> self . element = self . to_parser ( element ) <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . __class__ . __name__ , self . element ) <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> try : <EOL> d , pos = self . element . parse ( text , dt , pos , debug + <NUM_LIT:1> ) <EOL> except TimeError : <EOL> d , pos = None , None <EOL> if d : <EOL> return ( d , pos ) <EOL> else : <EOL> return ( adatetime ( ) , pos ) <EOL> class ToEnd ( ParserBase ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , element ) : <EOL> self . element = element <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . __class__ . __name__ , self . element ) <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> try : <EOL> d , pos = self . element . parse ( text , dt , pos , debug + <NUM_LIT:1> ) <EOL> except TimeError : <EOL> d , pos = None , None <EOL> if d and pos == len ( text ) : <EOL> return ( d , pos ) <EOL> else : <EOL> return ( None , None ) <EOL> class Regex ( ParserBase ) : <EOL> """<STR_LIT>""" <EOL> fn = None <EOL> modify = None <EOL> def __init__ ( self , pattern , fn = None , modify = None ) : <EOL> self . pattern = pattern <EOL> self . expr = rcompile ( pattern , re . IGNORECASE ) <EOL> self . fn = fn <EOL> self . modify = modify <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . pattern , ) <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> m = self . expr . match ( text , pos ) <EOL> if not m : <EOL> return ( None , None ) <EOL> props = self . extract ( m ) <EOL> self . modify_props ( props ) <EOL> try : <EOL> d = self . props_to_date ( props , dt ) <EOL> except TimeError : <EOL> d = None <EOL> if d : <EOL> return ( d , m . end ( ) ) <EOL> else : <EOL> return ( None , None ) <EOL> def extract ( self , match ) : <EOL> d = match . groupdict ( ) <EOL> for key , value in iteritems ( d ) : <EOL> try : <EOL> value = int ( value ) <EOL> d [ key ] = value <EOL> except ( ValueError , TypeError ) : <EOL> pass <EOL> return Props ( ** d ) <EOL> def modify_props ( self , props ) : <EOL> if self . modify : <EOL> self . modify ( props ) <EOL> def props_to_date ( self , props , dt ) : <EOL> if self . fn : <EOL> return self . fn ( props , dt ) <EOL> else : <EOL> args = { } <EOL> for key in adatetime . units : <EOL> args [ key ] = props . get ( key ) <EOL> return adatetime ( ** args ) <EOL> class Month ( Regex ) : <EOL> def __init__ ( self , * patterns ) : <EOL> self . patterns = patterns <EOL> self . exprs = [ rcompile ( pat , re . IGNORECASE ) for pat in self . patterns ] <EOL> self . pattern = ( "<STR_LIT>" <EOL> + "<STR_LIT:|>" . join ( "<STR_LIT>" % pat for pat in self . patterns ) <EOL> + "<STR_LIT:)>" ) <EOL> self . expr = rcompile ( self . pattern , re . IGNORECASE ) <EOL> def modify_props ( self , p ) : <EOL> text = p . month <EOL> for i , expr in enumerate ( self . exprs ) : <EOL> m = expr . match ( text ) <EOL> if m : <EOL> p . month = i + <NUM_LIT:1> <EOL> break <EOL> class PlusMinus ( Regex ) : <EOL> def __init__ ( self , years , months , weeks , days , hours , minutes , seconds ) : <EOL> rel_years = "<STR_LIT>" % years <EOL> rel_months = "<STR_LIT>" % months <EOL> rel_weeks = "<STR_LIT>" % weeks <EOL> rel_days = "<STR_LIT>" % days <EOL> rel_hours = "<STR_LIT>" % hours <EOL> rel_mins = "<STR_LIT>" % minutes <EOL> rel_secs = "<STR_LIT>" % seconds <EOL> self . pattern = ( "<STR_LIT>" <EOL> % ( rel_years , rel_months , rel_weeks , rel_days , <EOL> rel_hours , rel_mins , rel_secs ) ) <EOL> self . expr = rcompile ( self . pattern , re . IGNORECASE ) <EOL> def props_to_date ( self , p , dt ) : <EOL> if p . dir == "<STR_LIT:->" : <EOL> dir = - <NUM_LIT:1> <EOL> else : <EOL> dir = <NUM_LIT:1> <EOL> delta = relativedelta ( years = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir , <EOL> months = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir , <EOL> weeks = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir , <EOL> days = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir , <EOL> hours = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir , <EOL> minutes = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir , <EOL> seconds = ( p . get ( "<STR_LIT>" ) or <NUM_LIT:0> ) * dir ) <EOL> return dt + delta <EOL> class Daynames ( Regex ) : <EOL> def __init__ ( self , next , last , daynames ) : <EOL> self . next_pattern = next <EOL> self . last_pattern = last <EOL> self . _dayname_exprs = tuple ( rcompile ( pat , re . IGNORECASE ) <EOL> for pat in daynames ) <EOL> dn_pattern = "<STR_LIT:|>" . join ( daynames ) <EOL> self . pattern = ( "<STR_LIT>" <EOL> % ( next , last , dn_pattern ) ) <EOL> self . expr = rcompile ( self . pattern , re . IGNORECASE ) <EOL> def props_to_date ( self , p , dt ) : <EOL> if re . match ( p . dir , self . last_pattern ) : <EOL> dir = - <NUM_LIT:1> <EOL> else : <EOL> dir = <NUM_LIT:1> <EOL> for daynum , expr in enumerate ( self . _dayname_exprs ) : <EOL> m = expr . match ( p . day ) <EOL> if m : <EOL> break <EOL> current_daynum = dt . weekday ( ) <EOL> days_delta = relative_days ( current_daynum , daynum , dir ) <EOL> d = dt . date ( ) + timedelta ( days = days_delta ) <EOL> return adatetime ( year = d . year , month = d . month , day = d . day ) <EOL> class Time12 ( Regex ) : <EOL> def __init__ ( self ) : <EOL> self . pattern = ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> self . expr = rcompile ( self . pattern , re . IGNORECASE ) <EOL> def props_to_date ( self , p , dt ) : <EOL> isam = p . ampm . lower ( ) . startswith ( "<STR_LIT:a>" ) <EOL> if p . hour == <NUM_LIT:12> : <EOL> if isam : <EOL> hr = <NUM_LIT:0> <EOL> else : <EOL> hr = <NUM_LIT:12> <EOL> else : <EOL> hr = p . hour <EOL> if not isam : <EOL> hr += <NUM_LIT:12> <EOL> return adatetime ( hour = hr , minute = p . mins , second = p . secs , microsecond = p . usecs ) <EOL> class DateParser ( object ) : <EOL> """<STR_LIT>""" <EOL> day = Regex ( "<STR_LIT>" , <EOL> lambda p , dt : adatetime ( day = p . day ) ) <EOL> year = Regex ( "<STR_LIT>" , <EOL> lambda p , dt : adatetime ( year = p . year ) ) <EOL> time24 = Regex ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> lambda p , dt : adatetime ( hour = p . hour , minute = p . mins , <EOL> second = p . secs , microsecond = p . usecs ) ) <EOL> time12 = Time12 ( ) <EOL> def __init__ ( self ) : <EOL> simple_year = "<STR_LIT>" <EOL> simple_month = "<STR_LIT>" <EOL> simple_day = "<STR_LIT>" <EOL> simple_hour = "<STR_LIT>" <EOL> simple_minute = "<STR_LIT>" <EOL> simple_second = "<STR_LIT>" <EOL> simple_usec = "<STR_LIT>" <EOL> tup = ( simple_year , simple_month , simple_day , simple_hour , <EOL> simple_minute , simple_second , simple_usec ) <EOL> simple_seq = Sequence ( tup , sep = "<STR_LIT>" , name = "<STR_LIT>" , <EOL> progressive = True ) <EOL> self . simple = Sequence ( ( simple_seq , "<STR_LIT>" ) , sep = '<STR_LIT>' ) <EOL> self . setup ( ) <EOL> def setup ( self ) : <EOL> raise NotImplementedError <EOL> def get_parser ( self ) : <EOL> return self . all <EOL> def parse ( self , text , dt , pos = <NUM_LIT:0> , debug = - <NUM_LIT> ) : <EOL> parser = self . get_parser ( ) <EOL> d , newpos = parser . parse ( text , dt , pos = pos , debug = debug ) <EOL> if isinstance ( d , ( adatetime , timespan ) ) : <EOL> d = d . disambiguated ( dt ) <EOL> return ( d , newpos ) <EOL> def date_from ( self , text , basedate = None , pos = <NUM_LIT:0> , debug = - <NUM_LIT> , toend = True ) : <EOL> if basedate is None : <EOL> basedate = datetime . utcnow ( ) <EOL> parser = self . get_parser ( ) <EOL> if toend : <EOL> parser = ToEnd ( parser ) <EOL> d = parser . date_from ( text , basedate , pos = pos , debug = debug ) <EOL> if isinstance ( d , ( adatetime , timespan ) ) : <EOL> d = d . disambiguated ( basedate ) <EOL> return d <EOL> class English ( DateParser ) : <EOL> day = Regex ( "<STR_LIT>" , <EOL> lambda p , dt : adatetime ( day = p . day ) ) <EOL> def setup ( self ) : <EOL> self . plusdate = PlusMinus ( "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" ) <EOL> self . dayname = Daynames ( "<STR_LIT>" , "<STR_LIT>" , <EOL> ( "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" ) ) <EOL> midnight_l = lambda p , dt : adatetime ( hour = <NUM_LIT:0> , minute = <NUM_LIT:0> , second = <NUM_LIT:0> , <EOL> microsecond = <NUM_LIT:0> ) <EOL> midnight = Regex ( "<STR_LIT>" , midnight_l ) <EOL> noon_l = lambda p , dt : adatetime ( hour = <NUM_LIT:12> , minute = <NUM_LIT:0> , second = <NUM_LIT:0> , <EOL> microsecond = <NUM_LIT:0> ) <EOL> noon = Regex ( "<STR_LIT>" , noon_l ) <EOL> now = Regex ( "<STR_LIT>" , lambda p , dt : dt ) <EOL> self . time = Choice ( ( self . time12 , self . time24 , midnight , noon , now ) , <EOL> name = "<STR_LIT:time>" ) <EOL> def tomorrow_to_date ( p , dt ) : <EOL> d = dt . date ( ) + timedelta ( days = + <NUM_LIT:1> ) <EOL> return adatetime ( year = d . year , month = d . month , day = d . day ) <EOL> tomorrow = Regex ( "<STR_LIT>" , tomorrow_to_date ) <EOL> def yesterday_to_date ( p , dt ) : <EOL> d = dt . date ( ) + timedelta ( days = - <NUM_LIT:1> ) <EOL> return adatetime ( year = d . year , month = d . month , day = d . day ) <EOL> yesterday = Regex ( "<STR_LIT>" , yesterday_to_date ) <EOL> thisyear = Regex ( "<STR_LIT>" , lambda p , dt : adatetime ( year = dt . year ) ) <EOL> thismonth = Regex ( "<STR_LIT>" , <EOL> lambda p , dt : adatetime ( year = dt . year , <EOL> month = dt . month ) ) <EOL> today = Regex ( "<STR_LIT>" , <EOL> lambda p , dt : adatetime ( year = dt . year , month = dt . month , <EOL> day = dt . day ) ) <EOL> self . month = Month ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , <EOL> "<STR_LIT>" , "<STR_LIT>" ) <EOL> self . dmy = Choice ( ( Sequence ( ( self . day , self . month , self . year ) , <EOL> name = "<STR_LIT>" ) , <EOL> Sequence ( ( self . month , self . day , self . year ) , <EOL> name = "<STR_LIT>" ) , <EOL> Sequence ( ( self . year , self . month , self . day ) , <EOL> name = "<STR_LIT>" ) , <EOL> Sequence ( ( self . year , self . day , self . month ) , <EOL> name = "<STR_LIT>" ) , <EOL> Sequence ( ( self . day , self . month ) , name = "<STR_LIT>" ) , <EOL> Sequence ( ( self . month , self . day ) , name = "<STR_LIT>" ) , <EOL> Sequence ( ( self . month , self . year ) , name = "<STR_LIT>" ) , <EOL> self . month , self . year , self . dayname , tomorrow , <EOL> yesterday , thisyear , thismonth , today , now , <EOL> ) , name = "<STR_LIT:date>" ) <EOL> self . datetime = Bag ( ( self . time , self . dmy ) , name = "<STR_LIT>" ) <EOL> self . bundle = Choice ( ( self . plusdate , self . datetime , self . simple ) , <EOL> name = "<STR_LIT>" ) <EOL> self . torange = Combo ( ( self . bundle , "<STR_LIT:to>" , self . bundle ) , name = "<STR_LIT>" ) <EOL> self . all = Choice ( ( self . torange , self . bundle ) , name = "<STR_LIT:all>" ) <EOL> class DateParserPlugin ( plugins . Plugin ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , basedate = None , dateparser = None , callback = None , <EOL> free = False , free_expr = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> self . basedate = basedate <EOL> if dateparser is None : <EOL> dateparser = English ( ) <EOL> self . dateparser = dateparser <EOL> self . callback = callback <EOL> self . free = free <EOL> self . freeexpr = free_expr <EOL> def taggers ( self , parser ) : <EOL> if self . free : <EOL> return [ ( DateTagger ( self , self . freeexpr ) , - <NUM_LIT:1> ) ] <EOL> else : <EOL> return ( ) <EOL> def filters ( self , parser ) : <EOL> return [ ( self . do_dates , <NUM_LIT> ) ] <EOL> def errorize ( self , message , node ) : <EOL> if self . callback : <EOL> self . callback ( message ) <EOL> return syntax . ErrorNode ( message , node ) <EOL> def text_to_dt ( self , node ) : <EOL> text = node . text <EOL> try : <EOL> dt = self . dateparser . date_from ( text , self . basedate ) <EOL> if dt is None : <EOL> return self . errorize ( text , node ) <EOL> else : <EOL> n = DateTimeNode ( node . fieldname , dt , node . boost ) <EOL> except DateParseError : <EOL> e = sys . exc_info ( ) [ <NUM_LIT:1> ] <EOL> n = self . errorize ( e , node ) <EOL> n . startchar = node . startchar <EOL> n . endchar = node . endchar <EOL> return n <EOL> def range_to_dt ( self , node ) : <EOL> start = end = None <EOL> dp = self . dateparser . get_parser ( ) <EOL> if node . start : <EOL> start = dp . date_from ( node . start , self . basedate ) <EOL> if start is None : <EOL> return self . errorize ( node . start , node ) <EOL> if node . end : <EOL> end = dp . date_from ( node . end , self . basedate ) <EOL> if end is None : <EOL> return self . errorize ( node . end , node ) <EOL> if start and end : <EOL> ts = timespan ( start , end ) . disambiguated ( self . basedate ) <EOL> start , end = ts . start , ts . end <EOL> elif start : <EOL> start = start . disambiguated ( self . basedate ) <EOL> if isinstance ( start , timespan ) : <EOL> start = start . start <EOL> elif end : <EOL> end = end . disambiguated ( self . basedate ) <EOL> if isinstance ( end , timespan ) : <EOL> end = end . end <EOL> drn = DateRangeNode ( node . fieldname , start , end , boost = node . boost ) <EOL> drn . startchar = node . startchar <EOL> drn . endchar = node . endchar <EOL> return drn <EOL> def do_dates ( self , parser , group ) : <EOL> schema = parser . schema <EOL> if not schema : <EOL> return group <EOL> from whoosh . fields import DATETIME <EOL> datefields = frozenset ( fieldname for fieldname , field <EOL> in parser . schema . items ( ) <EOL> if isinstance ( field , DATETIME ) ) <EOL> for i , node in enumerate ( group ) : <EOL> if node . has_fieldname : <EOL> fname = node . fieldname or parser . fieldname <EOL> else : <EOL> fname = None <EOL> if isinstance ( node , syntax . GroupNode ) : <EOL> group [ i ] = self . do_dates ( parser , node ) <EOL> elif fname in datefields : <EOL> if node . has_text : <EOL> group [ i ] = self . text_to_dt ( node ) <EOL> elif isinstance ( node , syntax . RangeNode ) : <EOL> group [ i ] = self . range_to_dt ( node ) <EOL> return group <EOL> class DateTimeNode ( syntax . SyntaxNode ) : <EOL> has_fieldname = True <EOL> has_boost = True <EOL> def __init__ ( self , fieldname , dt , boost = <NUM_LIT:1.0> ) : <EOL> self . fieldname = fieldname <EOL> self . dt = dt <EOL> self . boost = <NUM_LIT:1.0> <EOL> def r ( self ) : <EOL> return repr ( self . dt ) <EOL> def query ( self , parser ) : <EOL> from whoosh import query <EOL> fieldname = self . fieldname or parser . fieldname <EOL> field = parser . schema [ fieldname ] <EOL> dt = self . dt <EOL> if isinstance ( self . dt , datetime ) : <EOL> return query . Term ( fieldname , field . to_text ( dt ) , boost = self . boost ) <EOL> elif isinstance ( self . dt , timespan ) : <EOL> return query . DateRange ( fieldname , dt . start , dt . end , <EOL> boost = self . boost ) <EOL> else : <EOL> raise Exception ( "<STR_LIT>" % dt ) <EOL> class DateRangeNode ( syntax . SyntaxNode ) : <EOL> has_fieldname = True <EOL> has_boost = True <EOL> def __init__ ( self , fieldname , start , end , boost = <NUM_LIT:1.0> ) : <EOL> self . fieldname = fieldname <EOL> self . start = start <EOL> self . end = end <EOL> self . boost = <NUM_LIT:1.0> <EOL> def r ( self ) : <EOL> return "<STR_LIT>" % ( self . start , self . end ) <EOL> def query ( self , parser ) : <EOL> from whoosh import query <EOL> fieldname = self . fieldname or parser . fieldname <EOL> return query . DateRange ( fieldname , self . start , self . end , <EOL> boost = self . boost ) <EOL> class DateTagger ( Tagger ) : <EOL> def __init__ ( self , plugin , expr ) : <EOL> self . plugin = plugin <EOL> self . expr = rcompile ( expr , re . IGNORECASE ) <EOL> def match ( self , parser , text , pos ) : <EOL> from whoosh . fields import DATETIME <EOL> match = self . expr . match ( text , pos ) <EOL> if match : <EOL> fieldname = match . group ( <NUM_LIT:1> ) <EOL> dtext = match . group ( <NUM_LIT:2> ) <EOL> if parser . schema and fieldname in parser . schema : <EOL> field = parser . schema [ fieldname ] <EOL> if isinstance ( field , DATETIME ) : <EOL> plugin = self . plugin <EOL> dateparser = plugin . dateparser <EOL> basedate = plugin . basedate <EOL> d , newpos = dateparser . parse ( dtext , basedate ) <EOL> if d : <EOL> node = DateTimeNode ( fieldname , d ) <EOL> node . startchar = match . start ( ) <EOL> node . endchar = newpos + match . start ( <NUM_LIT:2> ) <EOL> return node </s>
