示例#1
0
    def runTest(self):
        def basename(name):
            if ":" in name:
                return name.split(":")[-1]
            else:
                return name

        db = sqlite3.connect(':memory:')
        db.row_factory = sqlite3.Row
        pi = PagesIndexer(db, None, tests.MockObject())
        for i, name, cont in self.PAGES:
            db.execute(
                'INSERT INTO pages(id, name, lowerbasename, sortkey, parent, source_file) VALUES (?, ?, ?, ?, 1, 1)',
                (i, name, basename(name).lower(), natural_sort_key(name)))

        ## Test PagesViewInternal methods
        iview = PagesViewInternal(db)
        i, pn = iview.resolve_pagename(Path(''), ['foo'])
        self.assertEqual((i, pn), (3, Path('Foo')))

        i, pn = iview.resolve_link(Path('Foo'), HRef.new_from_wiki_link('Bar'))
        self.assertEqual((i, pn), (2, Path('Bar')))

        ## Test the actual indexer
        pageindexer = tests.MaskedObject(pi, 'connect')
        indexer = LinksIndexer(db, pageindexer)

        for i, name, cont in self.PAGES:
            row = {
                'id': i,
                'name': name,
                'sortkey': natural_sort_key(name),
                'is_link_placeholder': False
            }
            indexer.on_page_row_inserted(pageindexer, row)

        ###
        pageindexer.setObjectAccess('insert_link_placeholder')
        for i, name, text in self.PAGES:
            tree = WikiParser().parse(text)
            row = {'id': i, 'name': name}
            indexer.on_page_changed(pageindexer, row, tree)

        indexer.update()

        links = sorted((r['source'], r['target'])
                       for r in db.execute('SELECT * FROM links'))
        self.assertEqual(links, [(3, 2), (3, 4)])

        ###
        pageindexer.setObjectAccess('remove_page')
        for i, name, cont in self.PAGES:
            row = {'id': i, 'name': name, 'is_link_placeholder': False}
            indexer.on_page_row_deleted(pageindexer, row)

        indexer.update()

        rows = db.execute('SELECT * FROM links').fetchall()
        self.assertEqual(rows, [])
示例#2
0
class TasksView(IndexView):
    '''Database "view" that shows tasks that are indexed'''
    def __init__(self, db):
        IndexView.__init__(self, db)
        self._pages = PagesViewInternal(db)

        # Test the db really has a tasklist
        try:
            db.execute('SELECT * FROM tasklist LIMIT 1')
        except sqlite3.OperationalError:
            raise ValueError('No tasklist in index')

    def list_tasks_in_work_order(self, source):
        '''
		list tasks in order that they can be worked
		:param source:
		:return:
			row dict with keys ['id', 'source', 'parent', 'haschildren', 'hasopenchildren', 'open', 'prio', 'start', 'due', 'tags', 'description']
		'''
        import networkx as nx
        parent_id = 0
        G = nx.DiGraph()

        tasks = {}

        def add_nodes(parent, source, dependant):
            for row in self.db.execute(
                    '''
							SELECT tasklist.*, pages.name as name FROM tasklist
							LEFT JOIN pages ON tasklist.source = pages.id
							WHERE tasklist.open=1 and tasklist.parent=? and pages.name=?
							ORDER BY tasklist.prio DESC, tasklist.due ASC, pages.name ASC, tasklist.id ASC
							''', (parent, source)):
                G.add_node(row['id'])
                tasks[row['id']] = row

                if dependant:
                    # parent depends on child to complete to start
                    # arg2 depends on arg1 being finished first
                    G.add_edge(row['id'], dependant)
                if row['dependency_page']:
                    _, dep_page = self._pages.resolve_link(
                        Path(source),
                        HRef.new_from_wiki_link(row['dependency_page']))
                    add_nodes(0, dep_page.name, row['id'])

                add_nodes(row['id'], source, row['id'])

        add_nodes(parent_id, source, parent_id)
        added = set()
        for id in nx.topological_sort(G):
            if set(G.predecessors(id)) & added:
                # task has predecessors that are listed as open
                # add to the list so that its parents don't get added either
                added.add(id)
                continue
            yield tasks[id]
            added.add(id)

    def list_open_tasks(self, parent=None, source=None):
        '''List tasks
		@param parent: the parent task (as returned by this method) or C{None} to list
		all top level tasks
		@returns: a list of tasks at this level as sqlite Row objects
		'''
        if parent:
            parentid = parent['id']
        else:
            parentid = 0

        if source:
            today = str(datetime.date.today())
            for row in self.db.execute(
                    '''
				SELECT tasklist.* FROM tasklist
				LEFT JOIN pages ON tasklist.source = pages.id
				WHERE tasklist.open=1 and tasklist.parent=? and pages.name=? and tasklist.start<=?
				ORDER BY tasklist.prio DESC, tasklist.due ASC, pages.name ASC, tasklist.id ASC
				''', (parentid, source, today)):
                yield row
        else:
            # Sort:
            #  started tasks by prio, due date, page + id to keep order in page
            #  not-started tasks by start date, ...
            today = str(datetime.date.today())
            for row in self.db.execute(
                    '''
				SELECT tasklist.* FROM tasklist
				LEFT JOIN pages ON tasklist.source = pages.id
				WHERE tasklist.open=1 and tasklist.parent=? and tasklist.start<=?
				ORDER BY tasklist.prio DESC, tasklist.due ASC, pages.name ASC, tasklist.id ASC
				''', (parentid, today)):
                yield row
            for row in self.db.execute(
                    '''
				SELECT tasklist.* FROM tasklist
				LEFT JOIN pages ON tasklist.source = pages.id
				WHERE tasklist.open=1 and tasklist.parent=? and tasklist.start>?
				ORDER BY tasklist.start ASC, tasklist.prio DESC, tasklist.due ASC, pages.name ASC, tasklist.id ASC
				''', (parentid, today)):
                yield row

    def list_open_tasks_flatlist(self):
        '''List tasks
		@returns: a list of tasks as sqlite Row objects
		'''
        # Sort:
        #  started tasks by prio, due date, page + id to keep order in page
        #  not-started tasks by start date, ...
        today = str(datetime.date.today())
        for row in self.db.execute(
                '''
			SELECT tasklist.* FROM tasklist
			LEFT JOIN pages ON tasklist.source = pages.id
			WHERE tasklist.open=1 and tasklist.start<=? and hasopenchildren=0
			ORDER BY tasklist.prio DESC, tasklist.due ASC, pages.name ASC, tasklist.id ASC
			''', (today, )):
            yield row
        for row in self.db.execute(
                '''
			SELECT tasklist.* FROM tasklist
			LEFT JOIN pages ON tasklist.source = pages.id
			WHERE tasklist.open=1 and tasklist.start>? and hasopenchildren=0
			ORDER BY tasklist.start ASC, tasklist.prio DESC, tasklist.due ASC, pages.name ASC, tasklist.id ASC
			''', (today, )):
            yield row

    def get_task(self, taskid):
        row = self.db.execute('SELECT * FROM tasklist WHERE id=?',
                              (taskid, )).fetchone()
        return row

    def get_path(self, task):
        '''Get the L{Path} for the source of a task
		@param task: the task (as returned by L{list_tasks()}
		@returns: an L{IndexPath} object
		'''
        return self._pages.get_pagename(task['source'])