X-Git-Url: https://git.notmuchmail.org/git?a=blobdiff_plain;f=devel%2Fnmbug%2Fnmbug-status;h=e845c2a5c8f702cc5d988fa6ea16ba3b0e53e828;hb=d4053be21acf4c3fce0b477e26eec95b42a36bd7;hp=c4532f1873799e1693fd9d3c60b979f444019f7e;hpb=ffed8f2866a567d52eebeca02d3c362de07efc9d;p=notmuch
diff --git a/devel/nmbug/nmbug-status b/devel/nmbug/nmbug-status
index c4532f18..e845c2a5 100755
--- a/devel/nmbug/nmbug-status
+++ b/devel/nmbug/nmbug-status
@@ -1,10 +1,30 @@
#!/usr/bin/python
#
# Copyright (c) 2011-2012 David Bremner
-# License: Same as notmuch
+#
# dependencies
# - python 2.6 for json
# - argparse; either python 2.7, or install separately
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see http://www.gnu.org/licenses/ .
+
+"""Generate HTML for one or more notmuch searches.
+
+Messages matching each search are grouped by thread. Each message
+that contains both a subject and message-id will have the displayed
+subject link to the Gmane view of the message.
+"""
from __future__ import print_function
from __future__ import unicode_literals
@@ -13,7 +33,6 @@ import codecs
import collections
import datetime
import email.utils
-import locale
try: # Python 3
from urllib.parse import quote
except ImportError: # Python 2
@@ -27,7 +46,7 @@ import subprocess
import xml.sax.saxutils
-_ENCODING = locale.getpreferredencoding() or sys.getdefaultencoding()
+_ENCODING = 'UTF-8'
_PAGES = {}
@@ -42,7 +61,7 @@ if not hasattr(collections, 'OrderedDict'): # Python 2.6 or earlier
super(_OrderedDict, self).__setitem__(key, value)
self._keys.append(key)
- def __values__(self):
+ def values(self):
for key in self._keys:
yield self[key]
@@ -50,28 +69,60 @@ if not hasattr(collections, 'OrderedDict'): # Python 2.6 or earlier
collections.OrderedDict = _OrderedDict
+class ConfigError (Exception):
+ """Errors with config file usage
+ """
+ pass
+
+
def read_config(path=None, encoding=None):
"Read config from json file"
if not encoding:
encoding = _ENCODING
if path:
- fp = open(path)
+ try:
+ with open(path, 'rb') as f:
+ config_bytes = f.read()
+ except IOError as e:
+ raise ConfigError('Could not read config from {}'.format(path))
else:
nmbhome = os.getenv('NMBGIT', os.path.expanduser('~/.nmbug'))
+ branch = 'config'
+ filename = 'status-config.json'
# read only the first line from the pipe
sha1_bytes = subprocess.Popen(
- ['git', '--git-dir', nmbhome, 'show-ref', '-s', 'config'],
+ ['git', '--git-dir', nmbhome, 'show-ref', '-s', '--heads', branch],
stdout=subprocess.PIPE).stdout.readline()
sha1 = sha1_bytes.decode(encoding).rstrip()
+ if not sha1:
+ raise ConfigError(
+ ("No local branch '{branch}' in {nmbgit}. "
+ 'Checkout a local {branch} branch or explicitly set --config.'
+ ).format(branch=branch, nmbgit=nmbhome))
- fp_byte_stream = subprocess.Popen(
+ p = subprocess.Popen(
['git', '--git-dir', nmbhome, 'cat-file', 'blob',
- sha1+':status-config.json'],
- stdout=subprocess.PIPE).stdout
- fp = codecs.getreader(encoding=encoding)(stream=fp_byte_stream)
-
- return json.load(fp)
+ '{}:{}'.format(sha1, filename)],
+ stdout=subprocess.PIPE)
+ config_bytes, err = p.communicate()
+ status = p.wait()
+ if status != 0:
+ raise ConfigError(
+ ("Missing status-config.json in branch '{branch}' of"
+ '{nmbgit}. Add the file or explicitly set --config.'
+ ).format(branch=branch, nmbgit=nmbhome))
+
+ config_json = config_bytes.decode(encoding)
+ try:
+ return json.loads(config_json)
+ except ValueError as e:
+ if not path:
+ path = "{} in branch '{}' of {}".format(
+ filename, branch, nmbhome)
+ raise ConfigError(
+ 'Could not parse JSON from the config file {}:\n{}'.format(
+ path, e))
class Thread (list):
@@ -243,14 +294,29 @@ class HtmlPage (Page):
def _slug(self, string):
return self._slug_regexp.sub('-', string)
+parser = argparse.ArgumentParser(description=__doc__)
+parser.add_argument('--text', help='output plain text format',
+ action='store_true')
+parser.add_argument('--config', help='load config from given file',
+ metavar='PATH')
+parser.add_argument('--list-views', help='list views',
+ action='store_true')
+parser.add_argument('--get-query', help='get query for view',
+ metavar='VIEW')
-_PAGES['text'] = Page()
-_PAGES['html'] = HtmlPage(
- header='''
+args = parser.parse_args()
+
+try:
+ config = read_config(path=args.config)
+except ConfigError as e:
+ print(e)
+ sys.exit(1)
+
+header_template = config['meta'].get('header', '''
- Notmuch Patches
+ {title}
-Notmuch Patches
-
-Generated: {date}
-For more infomation see nmbug
+
{title}
+{blurb}
Views
-'''.format(date=datetime.datetime.utcnow().date(),
- encoding=_ENCODING,
- inter_message_padding='0.25em',
- border_radius='0.5em'),
- footer='\n\n',
- )
-
+''')
+
+footer_template = config['meta'].get('footer', '''
+
+Generated: {datetime}
+