def test_tag_counts(fs): fs.create_file('/notes/one.md', contents='#tag1 #tag1 #tag2') fs.create_file('/notes/two.md', contents='#tag1 #tag3') fs.create_file('/notes/three.md', contents='#tag1 #tag3 #tag4') repo = DirectRepoConf(root_paths={'/notes'}).instantiate() assert repo.tag_counts(FileQuery()) == {'tag1': 3, 'tag2': 1, 'tag3': 2, 'tag4': 1} assert repo.tag_counts(FileQuery.parse('tag:tag3')) == {'tag1': 2, 'tag3': 2, 'tag4': 1}
def tag_counts(self, query: FileQueryIsh = FileQuery()) -> Dict[str, int]: query = FileQuery.parse(query) result = defaultdict(int) for info in self.query(query, FileInfoReq(path=True, tags=True)): for tag in info.tags: result[tag] += 1 return result
def test_parse_query(): strquery = 'tag:first+tag,second -tag:third,fourth+tag tag:fifth sort:created,-backlinks' expected = FileQuery(include_tags={'first tag', 'second', 'fifth'}, exclude_tags={'third', 'fourth tag'}, sort_by=[ FileQuerySort(FileQuerySortField.CREATED), FileQuerySort(FileQuerySortField.BACKLINKS_COUNT, reverse=True) ]) assert FileQuery.parse(strquery) == expected
def query(self, query: FileQueryIsh = FileQuery(), fields: FileInfoReqIsh = FileInfoReq.internal())\ -> Iterator[FileInfo]: fields = dataclasses.replace(FileInfoReq.parse(fields), tags=(fields.tags or query.include_tags or query.exclude_tags)) query = FileQuery.parse(query) filtered = query.apply_filtering( self.info(e.dir_entry.path, fields, path_resolved=True, skip_parse=e.skip_parse) for e in self._paths()) yield from query.apply_sorting(filtered)
def query(self, query: FileQueryIsh = FileQuery(), fields: FileInfoReqIsh = FileInfoReq.internal())\ -> Iterator[FileInfo]: self._refresh_if_needed() query = FileQuery.parse(query) cursor = self.connection.cursor() cursor.execute('SELECT path FROM files WHERE existent = TRUE') # TODO: Obviously, this is super lazy and inefficient. We should do as much filtering and data loading in # the query as we reasonably can. fields = dataclasses.replace(FileInfoReq.parse(fields), tags=(fields.tags or query.include_tags or query.exclude_tags)) filtered = query.apply_filtering( self.info(path, fields, path_resolved=True) for (path, ) in cursor) yield from query.apply_sorting(filtered)
def test_query(fs): fs.create_file('/notes/one.md', contents='#tag1 #tag1 #tag2 #tag4') fs.create_file('/notes/two.md', contents='#tag1 #tag3') fs.create_file('/notes/three.md', contents='#tag1 #tag3 #tag4') repo = DirectRepoConf(root_paths={'/notes'}).instantiate() paths = {i.path for i in repo.query(FileQuery())} assert paths == {'/notes/one.md', '/notes/two.md', '/notes/three.md'} paths = {i.path for i in repo.query(FileQuery.parse('tag:tag3'))} assert paths == {'/notes/two.md', '/notes/three.md'} paths = {i.path for i in repo.query(FileQuery.parse('tag:tag1,tag4'))} assert paths == {'/notes/one.md', '/notes/three.md'} assert not list(repo.query(FileQuery.parse('tag:bogus'))) paths = {i.path for i in repo.query(FileQuery.parse('-tag:tag2'))} assert paths == {'/notes/two.md', '/notes/three.md'} paths = {i.path for i in repo.query(FileQuery.parse('-tag:tag2,tag4'))} assert paths == {'/notes/two.md'} assert not list(repo.query(FileQuery.parse('-tag:tag1'))) paths = {i.path for i in repo.query(FileQuery.parse('tag:tag3 -tag:tag4'))} assert paths == {'/notes/two.md'} assert [os.path.basename(i.path) for i in repo.query('sort:filename')] == ['one.md', 'three.md', 'two.md']
def test_apply_sorting(): data = [ FileInfo('/a/one', tags={'baz'}, backlinks=[LinkInfo(referrer='whatever', href='whatever')]), FileInfo('/b/two', title='Beta', created=datetime(2010, 1, 15)), FileInfo('/c/Three', title='Gamma', created=datetime(2012, 1, 9), backlinks=[ LinkInfo(referrer='whatever', href='whatever'), LinkInfo(referrer='whatever', href='whatever') ]), FileInfo('/d/four', title='delta', created=datetime(2012, 1, 9), tags={'foo', 'bar'}) ] assert FileQuery.parse('sort:path').apply_sorting(data) == data assert FileQuery.parse('sort:-path').apply_sorting(data) == list( reversed(data)) assert FileQuery.parse('sort:filename').apply_sorting(data) == [ data[3], data[0], data[2], data[1] ] assert FileQuery(sort_by=[ FileQuerySort(FileQuerySortField.FILENAME, ignore_case=False) ]).apply_sorting(data) == [data[2], data[3], data[0], data[1]] assert FileQuery.parse('sort:title').apply_sorting(data) == [ data[1], data[3], data[2], data[0] ] assert FileQuery( sort_by=[FileQuerySort(FileQuerySortField.TITLE, ignore_case=False) ]).apply_sorting(data) == [ data[1], data[2], data[3], data[0] ] assert FileQuery( sort_by=[FileQuerySort(FileQuerySortField.TITLE, missing_first=True) ]).apply_sorting(data) == [ data[0], data[1], data[3], data[2] ] assert FileQuery(sort_by=[ FileQuerySort( FileQuerySortField.TITLE, missing_first=True, reverse=True) ]).apply_sorting(data) == [data[2], data[3], data[1], data[0]] assert FileQuery.parse('sort:created').apply_sorting(data) == [ data[1], data[2], data[3], data[0] ] assert FileQuery.parse('sort:-created').apply_sorting(data) == [ data[0], data[2], data[3], data[1] ] assert FileQuery(sort_by=[ FileQuerySort(FileQuerySortField.CREATED, missing_first=True) ]).apply_sorting(data) == [data[0], data[1], data[2], data[3]] assert FileQuery.parse('sort:-tags').apply_sorting(data) == [ data[3], data[0], data[1], data[2] ] assert FileQuery.parse('sort:-backlinks').apply_sorting(data) == [ data[2], data[0], data[1], data[3] ] assert FileQuery.parse('sort:created,title').apply_sorting(data) == [ data[1], data[3], data[2], data[0] ] assert FileQuery.parse('sort:created,-title').apply_sorting(data) == [ data[1], data[2], data[3], data[0] ]
def tag_counts(self, query: FileQueryIsh = FileQuery()) -> Dict[str, int]: """Returns a map of tag names to the number of files matching the query which posses that tag.""" raise NotImplementedError()
def query(self, query: FileQueryIsh = FileQuery(), fields: FileInfoReqIsh = FileInfoReq.internal())\ -> Iterator[FileInfo]: """Returns the requested fields for all files matching the given query.""" raise NotImplementedError()