]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blob - tags.py
Feat: Search tags ignoring case
[phdru.name/cgi-bin/blog-ru/search-tags.git] / tags.py
1 blog_filename = "blog_dict.pickle"
2
3 try:
4     import cPickle as pickle
5 except ImportError:
6     import pickle
7
8 try:
9     blog_file = open('../../../../phdru.name/ru/' + blog_filename, "rb")
10 except IOError:
11     blog_dict = {}
12 else:
13     blog_dict = pickle.load(blog_file)
14     blog_file.close()
15
16
17 # blog_dict is a mapping
18 # (year, month, day) => [list of (file, title, lead, tags)]
19
20 # Add lower-case tags
21 _new_dict = {}
22 for (year, month, day), posts in blog_dict.items():
23     _new_dict[year, month, day] = _posts = []
24     for _file, _title, _lead, _tags in posts:
25         tags_lower = [tag.lower() for tag in _tags]
26         _posts.append((_file, _title, _lead, _tags, tags_lower))
27 blog_dict = _new_dict
28
29
30 def real_tag(tag):
31     ltag = tag.lower()
32     for posts in blog_dict.values():
33         for _file, _title, _lead, _tags, _tags_lower in posts:
34             try:
35                 ix = _tags_lower.index(ltag)
36             except ValueError:
37                 continue
38             else:
39                 return _tags[ix]
40
41
42 def _test_post(post, tree):
43     """Test if the list of tags in the post satisfies condition
44
45     Recursively evaluate the tree against the list of tags in the post.
46
47     """
48     op = tree[0]
49     if op == 'NAME':
50         tag = tree[1]
51         assert isinstance(tag, str)
52         return tag.lower() in post[4]
53     elif op in ('AND', 'OR'):
54         value1 = _test_post(post, tree[1])
55         value2 = _test_post(post, tree[2])
56         if op == 'AND':
57             return value1 and value2
58         if op == 'OR':
59             return value1 or value2
60     elif op == 'NOT':
61         return not _test_post(post, tree[1])
62     elif op == 'PARENS':
63         return _test_post(post, tree[1])
64     else:
65         raise ValueError("Cannot get there")
66
67
68 def find_tags(tree):
69     """Test every blog post against parsed expression
70
71     Return all posts that passed the test.
72
73     """
74     _posts = []
75     for (year, month, day), posts in blog_dict.items():
76         for post in posts:
77             if _test_post(post, tree):
78                 _posts.append((
79                     year, month, day,
80                     '/'.join(
81                         (year, month, day, post[0][:-len("tmpl")] + "html")),
82                     post[1]))
83     _posts.sort(reverse=True)
84     return _posts