+Version 0.8 (2024-06-04)
+
+ Python 3.
+
Version 0.7 (2017-12-14)
Use lark instead of parsley.
# Makefile.
#
# __author__ = "Oleg Broytman <phd@phdru.name>"
-# __copyright__ = "Copyright (C) 2014 PhiloSoft Design"
+# __copyright__ = "Copyright (C) 2014-2024 PhiloSoft Design"
%.py: %.tmpl
- cheetah compile --nobackup $< && compyle $@
+ python3 -m Cheetah.CheetahWrapper compile --nobackup $< && \
+ exec python3 -m compileall $@
.PHONY: all
all: html.py redirect.py
-
import sys
+
def response(title, body, status=None):
- from .html import html
- result = html()
+ from .html import html
+ result = html()
+
+ result.title = title
+ result.body = body
- result.title = title
- result.body = body
+ if status:
+ print("Status:", status)
+ sys.stdout.write(str(result.cgiHeaders()))
+ sys.stdout.write(str(result))
- if status:
- print "Status:", status
- sys.stdout.write(str(result.cgiHeaders()))
- #sys.stdout.write(str(result))
- sys.stdout.write(unicode(result).encode('latin1'))
def redirect(url, parameters=None, status=None):
- import urllib
- from .redirect import redirect
- result = redirect()
- if parameters:
- result.url = url + '?' + urllib.urlencode(parameters)
- else:
- result.url = url
- if status:
- print "Status:", status
- sys.stdout.write(str(result.cgiHeaders()))
- sys.stdout.write(str(result))
+ import urllib
+ from .redirect import redirect
+ result = redirect()
+ if parameters:
+ result.url = url + '?' + urllib.urlencode(parameters)
+ else:
+ result.url = url
+ if status:
+ print("Status:", status)
+ sys.stdout.write(str(result.cgiHeaders()))
+ sys.stdout.write(str(result))
-#! /usr/bin/env python
+#! /usr/bin/env python3
import os
from lark import Lark, Transformer
if __name__ == '__main__':
- print '----------'
- print parse('test')
- print parse('!test')
- print parse('not test')
- print parse('foo or bar')
- print parse('foo && bar')
- print parse('foo && bar && baz')
- print parse('!foo && bar && baz')
- print parse('(test)')
- print parse('(foo || bar)')
- print parse('(foo and !bar)')
- print '----------'
+ print('----------')
+ print(parse('test'))
+ print(parse('!test'))
+ print(parse('not test'))
+ print(parse('foo or bar'))
+ print(parse('foo && bar'))
+ print(parse('foo && bar && baz'))
+ print(parse('!foo && bar && baz'))
+ print(parse('(test)'))
+ print(parse('(foo || bar)'))
+ print(parse('(foo and !bar)'))
+ print('----------')
-#! /usr/bin/env python
+#! /usr/bin/env python3
import unittest
from lark import LexError, ParseError
from parser import parse
+
class TestParser(unittest.TestCase):
def _parse(self, input):
return parse(input)
self.assertRaises(LexError, self._parse, 'XXX')
def test_04_expression(self):
- self.assertEqual(self._parse('!(xxx&yyy)'),
+ self.assertEqual(
+ self._parse('!(xxx&yyy)'),
('NOT', ('PARENS', ('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))))
)
- self.assertEqual(self._parse('!(xxx & yyy)'),
+ self.assertEqual(
+ self._parse('!(xxx & yyy)'),
('NOT', ('PARENS', ('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))))
)
- self.assertEqual(self._parse('!xxx&yyy&zzz|ooo'),
+ self.assertEqual(
+ self._parse('!xxx&yyy&zzz|ooo'),
('OR', ('AND',
- ('NOT', ('NAME', 'xxx')),
- ('AND', ('NAME', 'yyy'), ('NAME', 'zzz'))),
- ('NAME', 'ooo'))
+ ('NOT', ('NAME', 'xxx')),
+ ('AND', ('NAME', 'yyy'), ('NAME', 'zzz'))),
+ ('NAME', 'ooo'))
)
- self.assertEqual(self._parse('!(xxx && yyy)'),
+ self.assertEqual(
+ self._parse('!(xxx && yyy)'),
('NOT', ('PARENS', ('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))))
)
- self.assertEqual(self._parse('!(xxx || yyy)'),
+ self.assertEqual(
+ self._parse('!(xxx || yyy)'),
('NOT', ('PARENS', ('OR', ('NAME', 'xxx'), ('NAME', 'yyy'))))
)
- self.assertEqual(self._parse('xxx and yyy'),
+ self.assertEqual(
+ self._parse('xxx and yyy'),
('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))
)
- self.assertEqual(self._parse('xxx or yyy'),
+ self.assertEqual(
+ self._parse('xxx or yyy'),
('OR', ('NAME', 'xxx'), ('NAME', 'yyy'))
)
- self.assertEqual(self._parse('xxx OR yyy'),
+ self.assertEqual(
+ self._parse('xxx OR yyy'),
('OR', ('NAME', 'xxx'), ('NAME', 'yyy'))
)
- self.assertEqual(self._parse('not xxx'),
+ self.assertEqual(
+ self._parse('not xxx'),
('NOT', ('NAME', 'xxx'))
)
- self.assertEqual(self._parse('NOT xxx'),
+ self.assertEqual(
+ self._parse('NOT xxx'),
('NOT', ('NAME', 'xxx'))
)
- self.assertEqual(self._parse('NOT (xxx & yyy) AND zzz | ooo'),
+ self.assertEqual(
+ self._parse('NOT (xxx & yyy) AND zzz | ooo'),
('OR',
('AND',
('NOT',
('PARENS',
('AND', ('NAME', 'xxx'), ('NAME', 'yyy'))
- )
- ),
+ )
+ ),
('NAME', 'zzz')
- ),
+ ),
('NAME', 'ooo')
- )
+ )
)
def test_05_bad_expression(self):
self.assertRaises(ParseError, self._parse, '!(xxx&yyy')
+
if __name__ == "__main__":
unittest.main()
-#! /usr/bin/env python
+#! /usr/bin/env python3
# coding: koi8-r
"""Search tags CGI"""
__author__ = "Oleg Broytman <phd@phdru.name>"
-__copyright__ = "Copyright (C) 2014-2017 PhiloSoft Design"
+__copyright__ = "Copyright (C) 2014-2024 PhiloSoft Design"
__license__ = "GNU GPL"
-import cgi, sys
+import cgi
+import sys
+
from lark import ParseError
+
from html.response import redirect, response
from parser import parser
form = cgi.FieldStorage()
-if not form.has_key('q'):
+if 'q' not in form:
status = "400 Bad request"
title = "Error!"
body = "Required parameter is missing!"
title = "Error!"
body = "Bad query syntax!"
else:
- if tree[0] == 'NAME': # Single tag - just do redirect
+ if tree[0] == 'NAME': # Single tag - just do redirect
tag = tree[1]
assert isinstance(tag, str)
from tags import tag_exists
if tag_exists(tag):
- redirect("/Russian/blog/tags/%s.html" % tag, status="301 Moved")
+ redirect(
+ "/Russian/blog/tags/%s.html" % tag, status="301 Moved")
sys.exit()
status = "404 Tag not found"
title = "Ошибка!"
body = "Тег %s не существует!" % tag
- else: # Process tree
+ else: # Process tree
from tags import find_tags
posts = find_tags(tree)
status = None
<ul>
"""]
for year, month, day, suburl, _title in posts:
- _posts.append('<li>%s-%s-%s <a href="../../../../Russian/blog/%s">%s</a></li>\n' % (year, month, day, suburl, _title))
+ _posts.append(
+ '<li>%s-%s-%s '
+ '<a href="../../../../Russian/blog/%s">%s</a></li>\n'
+ % (year, month, day, suburl, _title))
_posts .append("""\
</ul>
</p>
blog_filename = "blog_dict.pickle"
try:
- import cPickle as pickle
+ import cPickle as pickle
except ImportError:
- import pickle
+ import pickle
try:
- blog_file = open('../../../../phdru.name/ru/' + blog_filename, "rb")
+ blog_file = open('../../../../phdru.name/ru/' + blog_filename, "rb")
except IOError:
- blog_dict = {}
+ blog_dict = {}
else:
- blog_dict = pickle.load(blog_file)
- blog_file.close()
+ blog_dict = pickle.load(blog_file)
+ blog_file.close()
# blog_dict is a mapping
# (year, month, day) => [list of (file, title, lead, tags)]
def tag_exists(tag):
- for posts in blog_dict.itervalues():
+ for posts in blog_dict.values():
for _file, _title, _lead, _tags in posts:
if tag in _tags:
return True
return False
+
def _test_post(post, tree):
"""Test if the list of tags in the post satisfies condition
else:
raise ValueError("Cannot get there")
+
def find_tags(tree):
"""Test every blog post against parsed expression
"""
_posts = []
- for (year, month, day), posts in blog_dict.iteritems():
+ for (year, month, day), posts in blog_dict.items():
for post in posts:
if _test_post(post, tree):
_posts.append((
year, month, day,
- '/'.join((year, month, day, post[0][:-len("tmpl")] + "html")),
+ '/'.join(
+ (year, month, day, post[0][:-len("tmpl")] + "html")),
post[1]))
_posts.sort(reverse=True)
return _posts