From 81854d85ac7a825f430e925344176abfe3a16e55 Mon Sep 17 00:00:00 2001 From: Nguyễn Gia Phong Date: Wed, 9 Nov 2022 07:35:40 +0900 Subject: Polish for distribution --- src/fead.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'src/fead.py') diff --git a/src/fead.py b/src/fead.py index ac1fcd7..ab23bd0 100755 --- a/src/fead.py +++ b/src/fead.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Generate advert from web feeds +# Advert generator from web feeds # Copyright (C) 2022 Nguyễn Gia Phong # # This program is free software: you can redistribute it and/or modify @@ -15,9 +15,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -__version__ = '0.0.1' +__doc__ = 'Advert generator from web feeds' +__version__ = '0.1.0' -from argparse import ArgumentParser, FileType +from argparse import ArgumentParser, FileType, HelpFormatter from asyncio import gather, open_connection, run from collections import namedtuple from datetime import datetime @@ -41,6 +42,18 @@ Advert = namedtuple('Advert', ('source_title', 'source_link', 'title', 'link', 'time', 'summary')) +class GNUHelpFormatter(HelpFormatter): + """Help formatter for ArgumentParser following GNU Coding Standards.""" + + def add_usage(self, usage, actions, groups, prefix='Usage: '): + """Substitute 'Usage:' for 'usage:'.""" + super().add_usage(usage, actions, groups, prefix) + + def start_section(self, heading): + """Substitute 'Options:' for 'options:'.""" + super().start_section(heading.capitalize()) + + def read_urls(path): """Read newline-separated URLs from given file path.""" return Path(path).read_text().splitlines() @@ -101,7 +114,7 @@ def parse_atom_entry(xml): rel = child.attrib.get('rel') if rel == 'alternate' or not rel: link = child.attrib['href'] elif child.tag.endswith('Atom}published'): - iso = child.text.replace('Z', '+00:00') # normalized + iso = child.text.replace('Z', '+00:00') # normalized time = datetime.fromisoformat(iso) elif child.tag.endswith('Atom}summary'): summary = child.text @@ -172,7 +185,7 @@ async def fetch_all(urls): try: return await tasks except: - tasks.cancel() # structured concurrency + tasks.cancel() # structured concurrency raise @@ -187,10 +200,14 @@ def truncate(ad, summary_length): summary_length, placeholder='…')) -if __name__ == '__main__': - parser = ArgumentParser(description='generate advert from web feeds') +def main(): + """Run command-line program.""" + parser = ArgumentParser(prog='fead', usage='%(prog)s [OPTION]...', + description='Generate adverts from web feeds.', + epilog='Any use of -f before -F is ignored.', + formatter_class=GNUHelpFormatter) parser.add_argument('-v', '--version', action='version', - version=f'fead {__version__}') + version=f'%(prog)s {__version__}') parser.add_argument('-F', '--feeds', metavar='PATH', type=read_urls, default=[], help='file containing newline-separated web feed URLs') @@ -218,3 +235,6 @@ if __name__ == '__main__': for ad in select(args.per_feed, feed))): args.output.write(template.format(**truncate(ad, args.len)._asdict())) args.output.close() + + +if __name__ == '__main__': main() -- cgit 1.4.1