2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  webob . dec  import  wsgify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  webob . exc  import  * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  webob  import  Response 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								#from pprint import pprint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    import  simplejson  as  json 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    from  simplejson  import  JSONDecodeError 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								except  ImportError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    import  json 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    JSONDecodeError  =  ValueError 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								import  os ,  logging 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 03:17:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								import  anki . consts 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								import  anki . lang 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								from  anki . lang  import  _  as  t 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 03:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								__all__  =  [ ' RestApp ' ,  ' RestHandlerBase ' ,  ' noReturnValue ' ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  noReturnValue ( func ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    func . hasReturnValue  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  func 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								class  RestHandlerBase ( object ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Parent class for a handler group. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    hasReturnValue  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								class  _RestHandlerWrapper ( RestHandlerBase ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Wrapper for functions that we can ' t modify. """ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    def  __init__ ( self ,  func_name ,  func ,  hasReturnValue = True ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . func_name  =  func_name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . func  =  func 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . hasReturnValue  =  hasReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  __call__ ( self ,  * args ,  * * kw ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  self . func ( * args ,  * * kw ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								class  RestHandlerRequest ( object ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  __init__ ( self ,  app ,  data ,  ids ,  session ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . app  =  app 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        self . data  =  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . ids  =  ids 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . session  =  session 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  copy ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  RestHandlerRequest ( self . app ,  self . data . copy ( ) ,  self . ids [ : ] ,  self . session ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  __eq__ ( self ,  other ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  self . app  ==  other . app  and  self . data  ==  other . data  and  self . ids  ==  other . ids  and  self . session  ==  other . session 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								class  RestApp ( object ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ A WSGI app that implements RESTful operations on Collections, Decks and Cards. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # Defines not only the valid handler types, but their position in the URL string 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    handler_types  =  [ ' collection ' ,  [ ' model ' ,  ' note ' ,  ' deck ' ,  ' card ' ] ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 02:45:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  __init__ ( self ,  data_root ,  allowed_hosts = ' * ' ,  setup_new_collection = None ,  use_default_handlers = True ,  collection_manager = None ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        from  AnkiServer . threading  import  getCollectionManager 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . data_root  =  os . path . abspath ( data_root ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . allowed_hosts  =  allowed_hosts 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 02:45:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        self . setup_new_collection  =  setup_new_collection 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  collection_manager  is  not  None : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 02:45:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            self . collection_manager  =  collection_manager 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 02:45:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            self . collection_manager  =  getCollectionManager ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . handlers  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        for  type_list  in  self . handler_types : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  type ( type_list )  is  not  list : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                type_list  =  [ type_list ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            for  handler_type  in  type_list : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                self . handlers [ handler_type ]  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  use_default_handlers : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            self . add_handler_group ( ' collection ' ,  CollectionHandler ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            self . add_handler_group ( ' note ' ,  NoteHandler ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            self . add_handler_group ( ' model ' ,  ModelHandler ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            self . add_handler_group ( ' deck ' ,  DeckHandler ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            self . add_handler_group ( ' card ' ,  CardHandler ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # hold per collection session data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . sessions  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    def  add_handler ( self ,  type ,  name ,  handler ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Adds a callback handler for a type (collection, deck, card) with a unique name. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         -  ' type '  is  the  item  that  will  be  worked  on ,  for  example :  collection ,  deck ,  and  card . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         -  ' name '  is  a  unique  name  for  the  handler  that  gets  used  in  the  URL . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								         -  ' handler '  is  a  callable  that  takes  ( collection ,  data ,  ids ) . 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  self . handlers [ type ] . has_key ( name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  " Handler already for  %(type)s / %(name)s  exists! " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . handlers [ type ] [ name ]  =  handler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  add_handler_group ( self ,  type ,  group ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        """ Adds several handlers for every public method on an object descended from RestHandlerBase. 
 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        This  allows  you  to  create  a  single  class  with  several  methods ,  so  that  you  can  quickly 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        create  a  group  of  related  handlers . """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  inspect 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  name ,  method  in  inspect . getmembers ( group ,  predicate = inspect . ismethod ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  name . startswith ( ' _ ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                if  hasattr ( group ,  ' hasReturnValue ' )  and  not  hasattr ( method ,  ' hasReturnValue ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    method  =  _RestHandlerWrapper ( group . __class__ . __name__  +  ' . '  +  name ,  method ,  group . hasReturnValue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                self . add_handler ( type ,  name ,  method ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  execute_handler ( self ,  type ,  name ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Executes the handler with the given type and name, passing in the col and req as arguments. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        handler ,  hasReturnValue  =  self . _getHandler ( type ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ret  =  handler ( col ,  req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  hasReturnValue : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  ret 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 01:17:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  list_collections ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Returns an array of valid collection names in our self.data_path. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  [ x  for  x  in  os . listdir ( self . data_root )  if  os . path . exists ( os . path . join ( self . data_root ,  x ,  ' collection.anki2 ' ) ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  _checkRequest ( self ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Raises an exception if the request isn ' t allowed or valid for some reason. """ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  self . allowed_hosts  !=  ' * ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                remote_addr  =  req . headers [ ' X-Forwarded-For ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            except  KeyError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                remote_addr  =  req . remote_addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  remote_addr  !=  self . allowed_hosts : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                raise  HTTPForbidden ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        if  req . method  !=  ' POST ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPMethodNotAllowed ( allow = [ ' POST ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  _parsePath ( self ,  path ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Takes a request path and returns a tuple containing the handler type, name 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        and  a  list  of  ids . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Raises  an  HTTPNotFound  exception  if  the  path  is  invalid . """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  path  in  ( ' ' ,  ' / ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPNotFound ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        # split the URL into a list of parts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  path [ 0 ]  ==  ' / ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            path  =  path [ 1 : ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        parts  =  path . split ( ' / ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # pull the type and context from the URL parts 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        handler_type  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        ids  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        for  type_list  in  self . handler_types : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  len ( parts )  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # some URL positions can have multiple types 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  type ( type_list )  is  not  list : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                type_list  =  [ type_list ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # get the handler_type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  parts [ 0 ]  not  in  type_list : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            handler_type  =  parts . pop ( 0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            # add the id to the id list 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            if  len ( parts )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ids . append ( parts . pop ( 0 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            # break if we don't have enough parts to make a new type/id pair 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            if  len ( parts )  <  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        # sanity check to make sure the URL is valid 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  len ( parts )  >  1  or  len ( ids )  ==  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPNotFound ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get the handler name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  len ( parts )  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name  =  ' index ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            name  =  parts [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  ( handler_type ,  name ,  ids ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _getCollectionPath ( self ,  collection_id ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Returns the path to the collection based on the collection_id from the request. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Raises  HTTPBadRequest  if  the  collection_id  is  invalid . """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        path  =  os . path . normpath ( os . path . join ( self . data_root ,  collection_id ,  ' collection.anki2 ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  path [ 0 : len ( self . data_root ) ]  !=  self . data_root : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # attempting to escape our data jail! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPBadRequest ( ' " %s "  is not a valid collection '  %  collection_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _getHandler ( self ,  type ,  name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Returns a tuple containing handler function for this type and name, and a boolean flag 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  that  handler  has  a  return  value . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Raises  an  HTTPNotFound  exception  if  the  handler  doesn ' t exist. " " " 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get the handler function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            handler  =  self . handlers [ type ] [ name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        except  KeyError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPNotFound ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								         
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get if we have a return value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        hasReturnValue  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  hasattr ( handler ,  ' hasReturnValue ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            hasReturnValue  =  handler . hasReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  ( handler ,  hasReturnValue ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _parseRequestBody ( self ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Parses the request body (JSON) into a Python dict and returns it. 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Raises  an  HTTPBadRequest  exception  if  the  request  isn ' t valid JSON. " " " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            data  =  json . loads ( req . body ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        except  JSONDecodeError ,  e : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								            logging . error ( req . path + ' : Unable to parse JSON:  ' + str ( e ) ,  exc_info = True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPBadRequest ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 00:11:28 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        # make the keys into non-unicode strings 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        data  =  dict ( [ ( str ( k ) ,  v )  for  k ,  v  in  data . items ( ) ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @wsgify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  __call__ ( self ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # make sure the request is valid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        self . _checkRequest ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 01:17:58 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  req . path  ==  ' /list_collections ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  Response ( json . dumps ( self . list_collections ( ) ) ,  content_type = ' application/json ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-15 23:13:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # parse the path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        type ,  name ,  ids  =  self . _parsePath ( req . path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get the collection path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        collection_path  =  self . _getCollectionPath ( ids [ 0 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        print  collection_path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get the handler function 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        handler ,  hasReturnValue  =  self . _getHandler ( type ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # parse the request body 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        data  =  self . _parseRequestBody ( req ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # get the users session 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            session  =  self . sessions [ ids [ 0 ] ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        except  KeyError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            session  =  self . sessions [ ids [ 0 ] ]  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        # debug 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        from  pprint  import  pprint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        pprint ( data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # run it! 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 02:45:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        col  =  self . collection_manager . get_collection ( collection_path ,  self . setup_new_collection ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        handler_request  =  RestHandlerRequest ( self ,  data ,  ids ,  session ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            output  =  col . execute ( handler ,  [ handler_request ] ,  { } ,  hasReturnValue ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        except  Exception ,  e : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            logging . error ( e ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  HTTPInternalServerError ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  output  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  Response ( ' ' ,  content_type = ' text/plain ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  Response ( json . dumps ( output ) ,  content_type = ' application/json ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								class  CollectionHandler ( RestHandlerBase ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    """ Default handler group for  ' collection '  type. """ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # MODELS - Store fields definitions and templates for notes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  list_models ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # This is already a list of dicts, so it doesn't need to be serialized 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  col . models . all ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  find_model_by_name ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # This is already a list of dicts, so it doesn't need to be serialized 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  col . models . byName ( req . data [ ' model ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # NOTES - Information (in fields per the model) that can generate a card 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #         (based on a template from the model). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  find_notes ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        query  =  req . data . get ( ' query ' ,  ' ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ids  =  col . findNotes ( query ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  req . data . get ( ' preload ' ,  False ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:17:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            notes  =  [ NoteHandler . _serialize ( col . getNote ( id ) )  for  id  in  ids ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:17:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            notes  =  [ { ' id ' :  id }  for  id  in  ids ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:17:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  notes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  latest_notes ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # TODO: use SQLAlchemy objects to do this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  =  " SELECT n.id FROM notes AS n " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        args  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  req . data . has_key ( ' updated_since ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            sql  + =  '  WHERE n.mod > ? ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            args . append ( req . data [ ' updated_since ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  + =  '  ORDER BY n.mod DESC ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  + =  '  LIMIT  '  +  str ( req . data . get ( ' limit ' ,  10 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ids  =  col . db . list ( sql ,  * args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  req . data . get ( ' preload ' ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            notes  =  [ NoteHandler . _serialize ( col . getNote ( id ) )  for  id  in  ids ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            notes  =  [ { ' id ' :  id }  for  id  in  ids ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  notes 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  add_note ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        from  anki . notes  import  Note 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # TODO: I think this would be better with 'model' for the name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # and 'mid' for the model id. 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  type ( req . data [ ' model ' ] )  in  ( str ,  unicode ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            model  =  col . models . byName ( req . data [ ' model ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            model  =  col . models . get ( req . data [ ' model ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        note  =  Note ( col ,  model ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        for  name ,  value  in  req . data [ ' fields ' ] . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            note [ name ]  =  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  req . data . has_key ( ' tags ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            note . setTagsFromStr ( req . data [ ' tags ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . addNote ( note ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 02:28:24 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  list_tags ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  col . tags . all ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # DECKS - Groups of cards 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  list_decks ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # This is already a list of dicts, so it doesn't need to be serialized 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								        return  col . decks . all ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  select_deck ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . decks . select ( req . data [ ' deck_id ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 03:17:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    dyn_modes  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ' random ' :  anki . consts . DYN_RANDOM , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ' added ' :  anki . consts . DYN_ADDED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ' due ' :  anki . consts . DYN_DUE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  create_dynamic_deck ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        name  =  req . data . get ( ' name ' ,  t ( ' Custom Study Session ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        deck  =  col . decks . byName ( name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  deck : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  deck [ ' dyn ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                raise  HTTPBadRequest ( " There is an existing non-dynamic deck with the name  %s "  %  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # safe to empty it because it's a dynamic deck 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            # TODO: maybe this should be an option? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            col . sched . emptyDyn ( deck [ ' id ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            deck  =  col . decks . get ( col . decks . newDyn ( name ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        query  =  req . data . get ( ' query ' ,  ' ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 04:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        count  =  int ( req . data . get ( ' count ' ,  100 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 03:17:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        mode  =  req . data . get ( ' mode ' ,  ' random ' )  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            mode  =  self . dyn_modes [ mode ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        except  KeyError : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPBadRequest ( " Unknown mode:  %s "  %  mode ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        deck [ ' terms ' ] [ 0 ]  =  [ query ,  count ,  mode ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  mode  !=  anki . consts . DYN_RANDOM : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            deck [ ' resched ' ]  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            deck [ ' resched ' ]  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  not  col . sched . rebuildDyn ( deck [ ' id ' ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPBadRequest ( " No cards matched the criteria you provided " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . decks . save ( deck ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 04:29:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        col . sched . reset ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 03:17:52 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  deck 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # CARD - A specific card in a deck with a history of review (generated from 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    #        a note based on the template). 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  find_cards ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        query  =  req . data . get ( ' query ' ,  ' ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 02:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        order  =  req . data . get ( ' order ' ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ids  =  anki . find . Finder ( col ) . findCards ( query ,  order ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  req . data . get ( ' preload ' ,  False ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:09:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            cards  =  [ CardHandler . _serialize ( col . getCard ( id ) ,  req . data )  for  id  in  ids ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:09:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            cards  =  [ { ' id ' :  id }  for  id  in  ids ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  cards 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:24:59 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  latest_cards ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # TODO: use SQLAlchemy objects to do this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  =  " SELECT c.id FROM notes AS n INNER JOIN cards AS c ON c.nid = n.id " ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        args  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  req . data . has_key ( ' updated_since ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            sql  + =  '  WHERE n.mod > ? ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            args . append ( req . data [ ' updated_since ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  + =  '  ORDER BY n.mod DESC ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  + =  '  LIMIT  '  +  str ( req . data . get ( ' limit ' ,  10 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ids  =  col . db . list ( sql ,  * args ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  req . data . get ( ' preload ' ,  False ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:31:48 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            cards  =  [ CardHandler . _serialize ( col . getCard ( id ) ,  req . data )  for  id  in  ids ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:24:59 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            cards  =  [ { ' id ' :  id }  for  id  in  ids ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  cards 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # SCHEDULER - Controls card review, ie. intervals, what cards are due, answering a card, etc. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  reset_scheduler ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 00:06:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  req . data . has_key ( ' deck ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            deck  =  DeckHandler . _get_deck ( col ,  req . data [ ' deck ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            col . decks . select ( deck [ ' id ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        col . sched . reset ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 00:06:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        counts  =  col . sched . counts ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' new_cards ' :  counts [ 0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' learning_cards ' :  counts [ 1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' review_cards ' :  counts [ 1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  extend_scheduler_limits ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        new_cards  =  int ( req . data . get ( ' new_cards ' ,  0 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        review_cards  =  int ( req . data . get ( ' review_cards ' ,  0 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . sched . extendLimits ( new_cards ,  review_cards ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 00:15:59 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        col . sched . reset ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    button_labels  =  [ ' Easy ' ,  ' Good ' ,  ' Hard ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _get_answer_buttons ( self ,  col ,  card ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        l  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Put the correct number of buttons 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        cnt  =  col . sched . answerButtons ( card ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  idx  in  range ( 0 ,  cnt  -  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            l . append ( self . button_labels [ idx ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        l . append ( ' Again ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        l . reverse ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # Loop through and add the ease, estimated time (in seconds) and other info 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  [ { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' ease ' :  ease , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' label ' :  label , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' string_label ' :  t ( label ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' interval ' :  col . sched . nextIvl ( card ,  ease ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								          ' string_interval ' :  col . sched . nextIvlStr ( card ,  ease ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        }  for  ease ,  label  in  enumerate ( l ,  1 ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  next_card ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  req . data . has_key ( ' deck ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            deck  =  DeckHandler . _get_deck ( col ,  req . data [ ' deck ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            col . decks . select ( deck [ ' id ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card  =  col . sched . getCard ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  card  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # put it into the card cache to be removed when we answer it 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        #if not req.session.has_key('cards'): 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        #    req.session['cards'] = {} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        #req.session['cards'][long(card.id)] = card 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card . startTimer ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        result  =  CardHandler . _serialize ( card ,  req . data ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        result [ ' answer_buttons ' ]  =  self . _get_answer_buttons ( col ,  card ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  answer_card ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  time 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card_id  =  long ( req . data [ ' id ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ease  =  int ( req . data [ ' ease ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card  =  col . getCard ( card_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  card . timerStarted  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            card . timerStarted  =  float ( req . data . get ( ' timeStarted ' ,  time . time ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . sched . answerCard ( card ,  ease ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 07:33:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  suspend_cards ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card_ids  =  req . data [ ' ids ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . sched . suspendCards ( card_ids ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  unsuspend_cards ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card_ids  =  req . data [ ' ids ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . sched . unsuspendCards ( card_ids ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 20:41:20 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  cards_recent_ease ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        """ Returns the most recent ease for each card. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # TODO: Use sqlalchemy to build this query! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        sql  =  " SELECT r.cid, r.ease, r.id FROM revlog AS r INNER JOIN (SELECT cid, MAX(id) AS id FROM revlog GROUP BY cid) AS q ON r.cid = q.cid AND r.id = q.id " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        where  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  req . data . has_key ( ' ids ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            where . append ( ' ids IN ( '  +  ( ' , ' . join ( [ " ' %s ' "  %  x  for  x  in  req . data [ ' ids ' ] ] ) )  +  ' ) ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  len ( where )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            sql  + =  '  WHERE  '  +  '  AND  ' . join ( where ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        result  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  r  in  col . db . all ( sql ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            result . append ( { ' id ' :  r [ 0 ] ,  ' ease ' :  r [ 1 ] ,  ' timestamp ' :  int ( r [ 2 ]  /  1000 ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  result 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    stats_reports  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' today ' :  ' todayStats ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' due ' :  ' dueGraph ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' reps ' :  ' repsGraph ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' interval ' :  ' ivlGraph ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' hourly ' :  ' hourGraph ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' ease ' :  ' easeGraph ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' card ' :  ' cardGraph ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								      ' footer ' :  ' footer ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    stats_reports_order  =  [ ' today ' ,  ' due ' ,  ' reps ' ,  ' interval ' ,  ' hourly ' ,  ' ease ' ,  ' card ' ,  ' footer ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  stats_report ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  anki . stats 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:43:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        import  re 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stats  =  anki . stats . CollectionStats ( col ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:43:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        stats . width  =  int ( req . data . get ( ' width ' ,  600 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        stats . height  =  int ( req . data . get ( ' height ' ,  200 ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        reports  =  req . data . get ( ' reports ' ,  self . stats_reports_order ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        include_css  =  req . data . get ( ' include_css ' ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        include_jquery  =  req . data . get ( ' include_jquery ' ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        include_flot  =  req . data . get ( ' include_flot ' ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  include_css : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            from  anki . statsbg  import  bg 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:43:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            html  =  stats . css  %  bg 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            html  =  ' ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  name  in  reports : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  not  self . stats_reports . has_key ( name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                raise  HTTPBadRequest ( " Unknown report name:  %s "  %  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            func  =  getattr ( stats ,  self . stats_reports [ name ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:43:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            html  + =  ' <div class= " anki-graph anki-graph- %s " > '  %  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            html  + =  func ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            html  + =  ' </div> ' 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # fix an error in some inline styles 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # TODO: submit a patch to Anki! 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:43:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        html  =  re . sub ( r ' style= " width:([0-9 \ .]+); height:([0-9 \ .]+); " ' ,  r ' style= " width: \ 1px; height:  \ 2px; " ' ,  html ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:52:36 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        html  =  re . sub ( r ' -webkit-transform: ([^;]+); ' ,  r ' -webkit-transform:  \ 1; -moz-transform:  \ 1; -ms-transform:  \ 1; -o-transform:  \ 1; transform:  \ 1; ' ,  html ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 03:16:26 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        scripts  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  include_jquery  or  include_flot : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            import  anki . js 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  include_jquery : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                scripts . append ( anki . js . jquery ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  include_flot : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                scripts . append ( anki . js . plot ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  len ( scripts )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            html  =  " <script> %s \n </script> "  %  ' ' . join ( scripts )  +  html 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  html 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # GLOBAL / MISC 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    # 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  set_language ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        anki . lang . setLang ( req . data [ ' code ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								class  ImportExportHandler ( RestHandlerBase ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Handler group for the  ' collection '  type, but it ' s not added by default. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _get_filedata ( self ,  data ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        import  urllib2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  data . has_key ( ' data ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  data [ ' data ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        fd  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            fd  =  urllib2 . urlopen ( data [ ' url ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            filedata  =  fd . read ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        finally : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  fd  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                fd . close ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  filedata 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _get_importer_class ( self ,  data ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        filetype  =  data [ ' filetype ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 03:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        from  AnkiServer . importer  import  get_importer_class 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        importer_class  =  get_importer_class ( filetype ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  importer_class  is  None : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            raise  HTTPBadRequest ( " Unknown filetype  ' %s ' "  %  filetype ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 03:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  importer_class 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  import_file ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 03:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        import  AnkiServer . importer 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        import  tempfile 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get the importer class 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        importer_class  =  self . _get_importer_class ( req . data ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # get the file data 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        filedata  =  self . _get_filedata ( req . data ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # write the file data to a temporary file 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            path  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            with  tempfile . NamedTemporaryFile ( ' wt ' ,  delete = False )  as  fd : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                path  =  fd . name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                fd . write ( filedata ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 03:22:17 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            AnkiServer . importer . import_file ( importer_class ,  col ,  path ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 23:58:04 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        finally : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  path  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                os . unlink ( path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								class  ModelHandler ( RestHandlerBase ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    """ Default handler group for  ' model '  type. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  field_names ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        model  =  col . models . get ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  model  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            raise  HTTPNotFound ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  col . models . fieldNames ( model ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								class  NoteHandler ( RestHandlerBase ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Default handler group for  ' note '  type. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  _serialize ( note ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        d  =  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' id ' :  note . id , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:48:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' guid ' :  note . guid , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' model ' :  note . model ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:48:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' mid ' :  note . mid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' mod ' :  note . mod , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' scm ' :  note . scm , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' tags ' :  note . tags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' string_tags ' :  '   ' . join ( note . tags ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' fields ' :  { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' flags ' :  note . flags , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' usn ' :  note . usn , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:48:06 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # add all the fields 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  name ,  value  in  note . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            d [ ' fields ' ] [ name ]  =  value 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  d 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  index ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        note  =  col . getNote ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  self . _serialize ( note ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 07:33:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  add_tags ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        note  =  col . getNote ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  tag  in  req . data [ ' tags ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            note . addTag ( tag ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        note . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  remove_tags ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        note  =  col . getNote ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        for  tag  in  req . data [ ' tags ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            note . delTag ( tag ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        note . flush ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								class  DeckHandler ( RestHandlerBase ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    """ Default handler group for  ' deck '  type. """ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _get_deck ( col ,  val ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            did  =  long ( val ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            deck  =  col . decks . get ( did ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        except  ValueError : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            deck  =  col . decks . byName ( val ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  deck  is  None : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            raise  HTTPNotFound ( ' No deck with id or name:  '  +  str ( val ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  deck 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 00:06:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  index ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  self . _get_deck ( col ,  req . ids [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 00:44:09 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  next_card ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        req_copy  =  req . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        req_copy . data [ ' deck ' ]  =  req . ids [ 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        del  req_copy . ids [ 1 ] 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 05:37:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        # forward this to the CollectionHandler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  req . app . execute_handler ( ' collection ' ,  ' next_card ' ,  col ,  req_copy ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-25 00:06:08 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  get_conf ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        # TODO: should probably live in a ConfHandler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  col . decks . confForDid ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  set_update_conf ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        data  =  req . data . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        del  data [ ' id ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        conf  =  col . decks . confForDid ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        conf  =  conf . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        conf . update ( data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        col . decks . updateConf ( conf ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 22:12:05 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								class  CardHandler ( RestHandlerBase ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    """ Default handler group for  ' card '  type. """ 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  _serialize ( card ,  opts ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        d  =  { 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' id ' :  card . id , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' isEmpty ' :  card . isEmpty ( ) , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 21:09:25 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' css ' :  card . css ( ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' question ' :  card . _getQA ( ) [ ' q ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' answer ' :  card . _getQA ( ) [ ' a ' ] , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 00:34:34 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' did ' :  card . did , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' due ' :  card . due , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' factor ' :  card . factor , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' ivl ' :  card . ivl , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' lapses ' :  card . lapses , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' left ' :  card . left , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' mod ' :  card . mod , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' nid ' :  card . nid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' odid ' :  card . odid , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' odue ' :  card . odue , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' ord ' :  card . ord , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' queue ' :  card . queue , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' reps ' :  card . reps , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' type ' :  card . type , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' usn ' :  card . usn , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            ' timerStarted ' :  card . timerStarted , 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  opts . get ( ' load_note ' ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            d [ ' note ' ]  =  NoteHandler . _serialize ( card . col . getNote ( card . nid ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  opts . get ( ' load_deck ' ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            d [ ' deck ' ]  =  card . col . decks . get ( card . did ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:01:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  opts . get ( ' load_latest_revlog ' ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            d [ ' latest_revlog ' ]  =  CardHandler . _latest_revlog ( card . col ,  card . id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-16 21:20:31 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  d 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:01:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    @staticmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  _latest_revlog ( col ,  card_id ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        r  =  col . db . first ( " SELECT r.id, r.ease FROM revlog AS r WHERE r.cid = ? ORDER BY id DESC LIMIT 1 " ,  card_id ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  r : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  { ' id ' :  r [ 0 ] ,  ' ease ' :  r [ 1 ] ,  ' timestamp ' :  int ( r [ 0 ]  /  1000 ) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 06:35:03 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  index ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card  =  col . getCard ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  self . _serialize ( card ,  req . data ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 20:38:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  _forward_to_note ( self ,  col ,  req ,  name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card  =  col . getCard ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 07:33:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        req_copy  =  req . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        req_copy . ids [ 1 ]  =  card . nid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 20:38:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  req . app . execute_handler ( ' note ' ,  name ,  col ,  req ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 07:33:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  add_tags ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 20:38:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        self . _forward_to_note ( col ,  req ,  ' add_tags ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 07:33:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    @noReturnValue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    def  remove_tags ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-26 20:38:50 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        self . _forward_to_note ( col ,  req ,  ' remove_tags ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 07:33:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-27 02:25:42 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  stats_report ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        card  =  col . getCard ( req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  col . cardStats ( card ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-08-01 03:01:35 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    def  latest_revlog ( self ,  col ,  req ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  self . _latest_revlog ( col ,  req . ids [ 1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								# Our entry point 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								def  make_app ( global_conf ,  * * local_conf ) : 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-23 03:11:53 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    # TODO: we should setup the default language from conf! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								    # setup the logger 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-17 02:50:45 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    from  AnkiServer . utils  import  setup_logging 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-18 09:17:36 +08:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    setup_logging ( local_conf . get ( ' logging.config_file ' ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2013-07-13 05:08:16 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    return  RestApp ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        data_root = local_conf . get ( ' data_root ' ,  ' . ' ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        allowed_hosts = local_conf . get ( ' allowed_hosts ' ,  ' * ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    )