def feeds(): broken = request.args.get('broken') broken = {None: None, 'no': False, 'yes': True}[broken] updates_enabled = request.args.get('updates-enabled') updates_enabled = {None: None, 'no': False, 'yes': True}[updates_enabled] sort = request.args.get('sort', 'title') assert sort in ('title', 'added') error = None args = request.args.copy() tags_str = tags = args.pop('tags', None) if tags is None: pass elif not tags.strip(): # if tags is '', it's not a tag filter return redirect(url_for('.feeds', **args)) else: try: tags = yaml.safe_load(tags) except yaml.YAMLError as e: error = f"invalid tag query: invalid YAML: {e}: {tags_str}" return stream_template('feeds.html', feed_data=[], error=error) reader = get_reader() kwargs = dict(broken=broken, tags=tags, updates_enabled=updates_enabled) with_counts = request.args.get('counts') with_counts = {None: None, 'no': False, 'yes': True}[with_counts] counts = reader.get_feed_counts(**kwargs) if with_counts else None feed_data = [] try: feeds = reader.get_feeds(sort=sort, **kwargs) feed_data = (( feed, list(reader.get_feed_tags(feed)), reader.get_entry_counts(feed=feed) if with_counts else None, ) for feed in feeds) except ValueError as e: # TODO: there should be a better way of matching this kind of error if 'tag' in str(e).lower(): error = f"invalid tag query: {e}: {tags_str}" else: raise # Ensure flashed messages get removed from the session. # https://github.com/lemon24/reader/issues/81 get_flashed_messages() return stream_template('feeds.html', feed_data=feed_data, error=error, counts=counts)
def iter_tags(): for tag in itertools.chain([None, True, False], reader.get_feed_tags()): feed_counts = None entry_counts = None if with_counts: tags_arg = [tag] if tag is not None else tag feed_counts = reader.get_feed_counts(tags=tags_arg) entry_counts = reader.get_entry_counts(feed_tags=tags_arg) yield tag, feed_counts, entry_counts
def tags(): reader = get_reader() with_counts = request.args.get('counts') with_counts = {None: None, 'no': False, 'yes': True}[with_counts] tags = (( tag, reader.get_feed_counts(tags=[tag]) if with_counts else None, reader.get_entry_counts(feed_tags=[tag]) if with_counts else None, ) for tag in itertools.chain([True, False], reader.get_feed_tags())) return render_template('tags.html', tags=tags)
def update(reader, url, new_only, workers, verbose): """Update one or all feeds. If URL is not given, update all the feeds. Verbosity works like this: \b : progress bar + final status -v: + lines -vv: + warnings -vvv: + info -vvvv: + debug """ if url: def make_it(): try: yield url, reader.update_feed(url) except ParseError as e: yield url, e it = make_it() else: it = reader.update_feeds_iter(new_only=new_only, workers=workers) ok_count = 0 not_modified_count = 0 error_count = 0 new_count = 0 updated_count = 0 def feed_stats(width=None): if not width: width, _ = click.get_terminal_size() if width < 80: return '' if width < 105: return f"{green(ok_count)}/{red(error_count)}/{not_modified_count}" return ( f"{green(f'{ok_count} ok') if ok_count else '0 ok'}, " f"{red(f'{error_count} error') if error_count else '0 error'}, " f"{not_modified_count} not modified") if url: length = 1 else: if not new_only: length = reader.get_feed_counts(updates_enabled=True).total else: # TODO: pending https://github.com/lemon24/reader/issues/217 length = None if not verbose: bar_context = click.progressbar( it, length=length, label='update', show_pos=True, show_eta=True, item_show_func=lambda _: feed_stats(), file=sys.stderr, ) else: bar_context = nullcontext(iter_update_status(it, length)) try: with bar_context as bar: for _, value in bar: update_status = get_update_status(value) if update_status is None: not_modified_count += 1 elif not update_status: error_count += 1 else: ok_count += 1 new_count += value.new updated_count += value.updated finally: click.echo( f"{feed_stats(9999)}; entries: {new_count} new, {updated_count} updated" )