From 03c8f2d7a536fda95d22aadfc367e9c3ed6ab925 Mon Sep 17 00:00:00 2001 From: outa Date: Thu, 3 Nov 2022 21:29:58 +0100 Subject: [PATCH] Fix type-checking linter --- jrnl/FolderJournal.py | 7 +++++-- jrnl/jrnl.py | 34 +++++++++++++++++-------------- jrnl/plugins/dates_exporter.py | 11 ++++++---- jrnl/plugins/fancy_exporter.py | 11 ++++++---- jrnl/plugins/jrnl_importer.py | 7 +++++-- jrnl/plugins/json_exporter.py | 13 +++++++----- jrnl/plugins/markdown_exporter.py | 11 ++++++---- jrnl/plugins/tag_exporter.py | 12 +++++++---- jrnl/plugins/text_exporter.py | 19 +++++++++-------- jrnl/plugins/util.py | 7 +++++-- jrnl/plugins/xml_exporter.py | 13 +++++++----- jrnl/plugins/yaml_exporter.py | 11 ++++++---- 12 files changed, 97 insertions(+), 59 deletions(-) diff --git a/jrnl/FolderJournal.py b/jrnl/FolderJournal.py index 44fb4887..ab9547ed 100644 --- a/jrnl/FolderJournal.py +++ b/jrnl/FolderJournal.py @@ -4,10 +4,13 @@ import codecs import fnmatch import os +from typing import TYPE_CHECKING from jrnl import Journal from jrnl import time -from jrnl.Entry import Entry + +if TYPE_CHECKING: + from jrnl.Entry import Entry def get_files(journal_config: str) -> list[str]: @@ -82,7 +85,7 @@ class Folder(Journal.Journal): if os.stat(filename).st_size <= 0: os.remove(filename) - def delete_entries(self, entries_to_delete: list[Entry]) -> None: + def delete_entries(self, entries_to_delete: list["Entry"]) -> None: """Deletes specific entries from a journal.""" for entry in entries_to_delete: self.entries.remove(entry) diff --git a/jrnl/jrnl.py b/jrnl/jrnl.py index 7f8fcc6e..39c25b3f 100644 --- a/jrnl/jrnl.py +++ b/jrnl/jrnl.py @@ -2,7 +2,7 @@ # License: https://www.gnu.org/licenses/gpl-3.0.html import logging import sys -from argparse import Namespace +from typing import TYPE_CHECKING from jrnl import install from jrnl import plugins @@ -13,7 +13,6 @@ from jrnl.config import get_journal_name from jrnl.config import scope_config from jrnl.editor import get_text_from_editor from jrnl.editor import get_text_from_stdin -from jrnl.Entry import Entry from jrnl.exception import JrnlException from jrnl.Journal import Journal from jrnl.Journal import open_journal @@ -25,8 +24,13 @@ from jrnl.output import print_msgs from jrnl.override import apply_overrides from jrnl.path import expand_path +if TYPE_CHECKING: + from argparse import Namespace -def run(args: Namespace): + from jrnl.Entry import Entry + + +def run(args: "Namespace"): """ Flow: 1. Run standalone command if it doesn't require config (help, version, etc), then exit @@ -74,7 +78,7 @@ def run(args: Namespace): search_mode(**kwargs) -def _is_write_mode(args: Namespace, config: dict, **kwargs) -> bool: +def _is_write_mode(args: "Namespace", config: dict, **kwargs) -> bool: """Determines if we are in write mode (as opposed to search mode)""" # Are any search filters present? If so, then search mode. write_mode = not any( @@ -115,7 +119,7 @@ def _is_write_mode(args: Namespace, config: dict, **kwargs) -> bool: return write_mode -def write_mode(args: Namespace, config: dict, journal: Journal, **kwargs) -> None: +def write_mode(args: "Namespace", config: dict, journal: Journal, **kwargs) -> None: """ Gets input from the user to write to the journal 1. Check for input from cli @@ -159,7 +163,7 @@ def write_mode(args: Namespace, config: dict, journal: Journal, **kwargs) -> Non logging.debug("Write mode: completed journal.write()") -def search_mode(args: Namespace, journal: Journal, **kwargs) -> None: +def search_mode(args: "Namespace", journal: Journal, **kwargs) -> None: """ Search for entries in a journal, then either: 1. Send them to configured editor for user manipulation (and also @@ -251,7 +255,7 @@ def _get_editor_template(config: dict, **kwargs) -> str: return template -def _has_search_args(args: Namespace) -> bool: +def _has_search_args(args: "Namespace") -> bool: return any( ( args.on_date, @@ -271,7 +275,7 @@ def _has_search_args(args: Namespace) -> bool: ) -def _filter_journal_entries(args: Namespace, journal: Journal, **kwargs) -> None: +def _filter_journal_entries(args: "Namespace", journal: Journal, **kwargs) -> None: """Filter journal entries in-place based upon search args""" if args.on_date: args.start_date = args.end_date = args.on_date @@ -296,7 +300,7 @@ def _filter_journal_entries(args: Namespace, journal: Journal, **kwargs) -> None journal.limit(args.limit) -def _print_entries_found_count(count: int, args: Namespace) -> None: +def _print_entries_found_count(count: int, args: "Namespace") -> None: if count == 0: if args.edit or args.change_time: print_msg(Message(MsgText.NothingToModify, MsgStyle.WARNING)) @@ -317,13 +321,13 @@ def _print_entries_found_count(count: int, args: Namespace) -> None: print_msg(Message(my_msg, MsgStyle.NORMAL, {"num": count})) -def _other_entries(journal: Journal, entries: list[Entry]) -> list[Entry]: +def _other_entries(journal: Journal, entries: list["Entry"]) -> list["Entry"]: """Find entries that are not in journal""" return [e for e in entries if e not in journal.entries] def _edit_search_results( - config: dict, journal: Journal, old_entries: list[Entry], **kwargs + config: dict, journal: Journal, old_entries: list["Entry"], **kwargs ) -> None: """ 1. Send the given journal entries to the user-configured editor @@ -404,7 +408,7 @@ def _get_predit_stats(journal: Journal) -> dict[str, int]: def _delete_search_results( - journal: Journal, old_entries: list[Entry], **kwargs + journal: Journal, old_entries: list["Entry"], **kwargs ) -> None: entries_to_delete = journal.prompt_action_entries(MsgText.DeleteEntryQuestion) @@ -416,9 +420,9 @@ def _delete_search_results( def _change_time_search_results( - args: Namespace, + args: "Namespace", journal: Journal, - old_entries: list[Entry], + old_entries: list["Entry"], no_prompt: bool = False, **kwargs ) -> None: @@ -444,7 +448,7 @@ def _change_time_search_results( journal.write() -def _display_search_results(args: Namespace, journal: Journal, **kwargs) -> None: +def _display_search_results(args: "Namespace", journal: Journal, **kwargs) -> None: # Get export format from config file if not provided at the command line args.export = args.export or kwargs["config"].get("display_format") diff --git a/jrnl/plugins/dates_exporter.py b/jrnl/plugins/dates_exporter.py index 778ec06f..920c6ff9 100644 --- a/jrnl/plugins/dates_exporter.py +++ b/jrnl/plugins/dates_exporter.py @@ -2,11 +2,14 @@ # License: https://www.gnu.org/licenses/gpl-3.0.html from collections import Counter +from typing import TYPE_CHECKING -from jrnl.Entry import Entry -from jrnl.Journal import Journal from jrnl.plugins.text_exporter import TextExporter +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class DatesExporter(TextExporter): """This Exporter lists dates and their respective counts, for heatingmapping etc.""" @@ -15,11 +18,11 @@ class DatesExporter(TextExporter): extension = "dates" @classmethod - def export_entry(cls, entry: Entry): + def export_entry(cls, entry: "Entry"): raise NotImplementedError @classmethod - def export_journal(cls, journal: Journal) -> str: + def export_journal(cls, journal: "Journal") -> str: """Returns dates and their frequencies for an entire journal.""" date_counts = Counter() for entry in journal.entries: diff --git a/jrnl/plugins/fancy_exporter.py b/jrnl/plugins/fancy_exporter.py index 253a0d61..50189ab3 100644 --- a/jrnl/plugins/fancy_exporter.py +++ b/jrnl/plugins/fancy_exporter.py @@ -4,15 +4,18 @@ import logging import os from textwrap import TextWrapper +from typing import TYPE_CHECKING -from jrnl.Entry import Entry from jrnl.exception import JrnlException -from jrnl.Journal import Journal from jrnl.messages import Message from jrnl.messages import MsgStyle from jrnl.messages import MsgText from jrnl.plugins.text_exporter import TextExporter +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class FancyExporter(TextExporter): """This Exporter can convert entries and journals into text with unicode box drawing characters.""" @@ -37,7 +40,7 @@ class FancyExporter(TextExporter): border_m = "┘" @classmethod - def export_entry(cls, entry: Entry) -> str: + def export_entry(cls, entry: "Entry") -> str: """Returns a fancy unicode representation of a single entry.""" date_str = entry.date.strftime(entry.journal.config["timeformat"]) @@ -102,7 +105,7 @@ class FancyExporter(TextExporter): return "\n".join(cls.export_entry(entry) for entry in journal) -def check_provided_linewrap_viability(linewrap: int, card: list[str], journal: Journal): +def check_provided_linewrap_viability(linewrap: int, card: list[str], journal: "Journal"): if len(card[0]) > linewrap: width_violation = len(card[0]) - linewrap raise JrnlException( diff --git a/jrnl/plugins/jrnl_importer.py b/jrnl/plugins/jrnl_importer.py index 907ece4c..e93792de 100644 --- a/jrnl/plugins/jrnl_importer.py +++ b/jrnl/plugins/jrnl_importer.py @@ -2,14 +2,17 @@ # License: https://www.gnu.org/licenses/gpl-3.0.html import sys +from typing import TYPE_CHECKING from jrnl.exception import JrnlException -from jrnl.Journal import Journal from jrnl.messages import Message from jrnl.messages import MsgStyle from jrnl.messages import MsgText from jrnl.output import print_msg +if TYPE_CHECKING: + from jrnl.Journal import Journal + class JRNLImporter: """This plugin imports entries from other jrnl files.""" @@ -17,7 +20,7 @@ class JRNLImporter: names = ["jrnl"] @staticmethod - def import_(journal: Journal, input: str | None = None) -> None: + def import_(journal: "Journal", input: str | None = None) -> None: """Imports from an existing file if input is specified, and standard input otherwise.""" old_cnt = len(journal.entries) diff --git a/jrnl/plugins/json_exporter.py b/jrnl/plugins/json_exporter.py index dd0a4a4d..1a3a5670 100644 --- a/jrnl/plugins/json_exporter.py +++ b/jrnl/plugins/json_exporter.py @@ -2,12 +2,15 @@ # License: https://www.gnu.org/licenses/gpl-3.0.html import json +from typing import TYPE_CHECKING -from jrnl.Entry import Entry -from jrnl.Journal import Journal from jrnl.plugins.text_exporter import TextExporter from jrnl.plugins.util import get_tags_count +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class JSONExporter(TextExporter): """This Exporter can convert entries and journals into json.""" @@ -16,7 +19,7 @@ class JSONExporter(TextExporter): extension = "json" @classmethod - def entry_to_dict(cls, entry: Entry) -> dict: + def entry_to_dict(cls, entry: "Entry") -> dict: entry_dict = { "title": entry.title, "body": entry.body, @@ -51,12 +54,12 @@ class JSONExporter(TextExporter): return entry_dict @classmethod - def export_entry(cls, entry: Entry) -> str: + def export_entry(cls, entry: "Entry") -> str: """Returns a json representation of a single entry.""" return json.dumps(cls.entry_to_dict(entry), indent=2) + "\n" @classmethod - def export_journal(cls, journal: Journal) -> str: + def export_journal(cls, journal: "Journal") -> str: """Returns a json representation of an entire journal.""" tags = get_tags_count(journal) result = { diff --git a/jrnl/plugins/markdown_exporter.py b/jrnl/plugins/markdown_exporter.py index 860646ff..8f0d07b4 100644 --- a/jrnl/plugins/markdown_exporter.py +++ b/jrnl/plugins/markdown_exporter.py @@ -3,15 +3,18 @@ import os import re +from typing import TYPE_CHECKING -from jrnl.Entry import Entry -from jrnl.Journal import Journal from jrnl.messages import Message from jrnl.messages import MsgStyle from jrnl.messages import MsgText from jrnl.output import print_msg from jrnl.plugins.text_exporter import TextExporter +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class MarkdownExporter(TextExporter): """This Exporter can convert entries and journals into Markdown.""" @@ -20,7 +23,7 @@ class MarkdownExporter(TextExporter): extension = "md" @classmethod - def export_entry(cls, entry: Entry, to_multifile: bool = True) -> str: + def export_entry(cls, entry: "Entry", to_multifile: bool = True) -> str: """Returns a markdown representation of a single entry.""" date_str = entry.date.strftime(entry.journal.config["timeformat"]) body_wrapper = "\n" if entry.body else "" @@ -75,7 +78,7 @@ class MarkdownExporter(TextExporter): return f"{heading} {date_str} {entry.title}\n{newbody} " @classmethod - def export_journal(cls, journal: Journal) -> str: + def export_journal(cls, journal: "Journal") -> str: """Returns a Markdown representation of an entire journal.""" out = [] year, month = -1, -1 diff --git a/jrnl/plugins/tag_exporter.py b/jrnl/plugins/tag_exporter.py index b9d40836..250f05c7 100644 --- a/jrnl/plugins/tag_exporter.py +++ b/jrnl/plugins/tag_exporter.py @@ -1,11 +1,15 @@ # Copyright © 2012-2022 jrnl contributors # License: https://www.gnu.org/licenses/gpl-3.0.html -from jrnl.Entry import Entry -from jrnl.Journal import Journal +from typing import TYPE_CHECKING + from jrnl.plugins.text_exporter import TextExporter from jrnl.plugins.util import get_tags_count +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class TagExporter(TextExporter): """This Exporter can lists the tags for entries and journals, exported as a plain text file.""" @@ -14,12 +18,12 @@ class TagExporter(TextExporter): extension = "tags" @classmethod - def export_entry(cls, entry: Entry) -> str: + def export_entry(cls, entry: "Entry") -> str: """Returns a list of tags for a single entry.""" return ", ".join(entry.tags) @classmethod - def export_journal(cls, journal: Journal) -> str: + def export_journal(cls, journal: "Journal") -> str: """Returns a list of tags and their frequency for an entire journal.""" tag_counts = get_tags_count(journal) result = "" diff --git a/jrnl/plugins/text_exporter.py b/jrnl/plugins/text_exporter.py index fe85f002..7f2321e7 100644 --- a/jrnl/plugins/text_exporter.py +++ b/jrnl/plugins/text_exporter.py @@ -5,14 +5,17 @@ import errno import os import re import unicodedata +from typing import TYPE_CHECKING -from jrnl.Entry import Entry -from jrnl.Journal import Journal from jrnl.messages import Message from jrnl.messages import MsgStyle from jrnl.messages import MsgText from jrnl.output import print_msg +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class TextExporter: """This Exporter can convert entries and journals into text files.""" @@ -21,17 +24,17 @@ class TextExporter: extension = "txt" @classmethod - def export_entry(cls, entry: Entry) -> str: + def export_entry(cls, entry: "Entry") -> str: """Returns a string representation of a single entry.""" return str(entry) @classmethod - def export_journal(cls, journal: Journal) -> str: + def export_journal(cls, journal: "Journal") -> str: """Returns a string representation of an entire journal.""" return "\n".join(cls.export_entry(entry) for entry in journal) @classmethod - def write_file(cls, journal: Journal, path: str) -> str: + def write_file(cls, journal: "Journal", path: str) -> str: """Exports a journal into a single file.""" export_str = cls.export_journal(journal) with open(path, "w", encoding="utf-8") as f: @@ -48,13 +51,13 @@ class TextExporter: return "" @classmethod - def make_filename(cls, entry: Entry) -> str: + def make_filename(cls, entry: "Entry") -> str: return entry.date.strftime("%Y-%m-%d") + "_{}.{}".format( cls._slugify(str(entry.title)), cls.extension ) @classmethod - def write_files(cls, journal: Journal, path: str) -> str: + def write_files(cls, journal: "Journal", path: str) -> str: """Exports a journal into individual files for each entry.""" for entry in journal.entries: entry_is_written = False @@ -94,7 +97,7 @@ class TextExporter: return slug @classmethod - def export(cls, journal: Journal, output: str | None = None) -> str: + def export(cls, journal: "Journal", output: str | None = None) -> str: """Exports to individual files if output is an existing path, or into a single file if output is a file name, or returns the exporter's representation as string if output is None.""" diff --git a/jrnl/plugins/util.py b/jrnl/plugins/util.py index 0d6d08ed..009651e9 100644 --- a/jrnl/plugins/util.py +++ b/jrnl/plugins/util.py @@ -1,10 +1,13 @@ # Copyright © 2012-2022 jrnl contributors # License: https://www.gnu.org/licenses/gpl-3.0.html -from jrnl.Journal import Journal +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from jrnl.Journal import Journal -def get_tags_count(journal: Journal) -> set[tuple[int, str]]: +def get_tags_count(journal: "Journal") -> set[tuple[int, str]]: """Returns a set of tuples (count, tag) for all tags present in the journal.""" # Astute reader: should the following line leave you as puzzled as me the first time # I came across this construction, worry not and embrace the ensuing moment of enlightment. diff --git a/jrnl/plugins/xml_exporter.py b/jrnl/plugins/xml_exporter.py index c041bbd6..61b6b297 100644 --- a/jrnl/plugins/xml_exporter.py +++ b/jrnl/plugins/xml_exporter.py @@ -1,13 +1,16 @@ # Copyright © 2012-2022 jrnl contributors # License: https://www.gnu.org/licenses/gpl-3.0.html +from typing import TYPE_CHECKING from xml.dom import minidom -from jrnl.Entry import Entry -from jrnl.Journal import Journal from jrnl.plugins.json_exporter import JSONExporter from jrnl.plugins.util import get_tags_count +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class XMLExporter(JSONExporter): """This Exporter can convert entries and journals into XML.""" @@ -17,7 +20,7 @@ class XMLExporter(JSONExporter): @classmethod def export_entry( - cls, entry: Entry, doc: minidom.Document | None = None + cls, entry: "Entry", doc: minidom.Document | None = None ) -> minidom.Element | str: """Returns an XML representation of a single entry.""" doc_el = doc or minidom.Document() @@ -33,7 +36,7 @@ class XMLExporter(JSONExporter): return entry_el @classmethod - def entry_to_xml(cls, entry: Entry, doc: minidom.Document) -> minidom.Element: + def entry_to_xml(cls, entry: "Entry", doc: minidom.Document) -> minidom.Element: entry_el = doc.createElement("entry") entry_el.setAttribute("date", entry.date.isoformat()) if hasattr(entry, "uuid"): @@ -48,7 +51,7 @@ class XMLExporter(JSONExporter): return entry_el @classmethod - def export_journal(cls, journal: Journal) -> str: + def export_journal(cls, journal: "Journal") -> str: """Returns an XML representation of an entire journal.""" tags = get_tags_count(journal) doc = minidom.Document() diff --git a/jrnl/plugins/yaml_exporter.py b/jrnl/plugins/yaml_exporter.py index bd815365..5f5d5b21 100644 --- a/jrnl/plugins/yaml_exporter.py +++ b/jrnl/plugins/yaml_exporter.py @@ -3,16 +3,19 @@ import os import re +from typing import TYPE_CHECKING -from jrnl.Entry import Entry from jrnl.exception import JrnlException -from jrnl.Journal import Journal from jrnl.messages import Message from jrnl.messages import MsgStyle from jrnl.messages import MsgText from jrnl.output import print_msg from jrnl.plugins.text_exporter import TextExporter +if TYPE_CHECKING: + from jrnl.Entry import Entry + from jrnl.Journal import Journal + class YAMLExporter(TextExporter): """This Exporter can convert entries and journals into Markdown formatted text with YAML front matter.""" @@ -21,7 +24,7 @@ class YAMLExporter(TextExporter): extension = "md" @classmethod - def export_entry(cls, entry: Entry, to_multifile: bool = True) -> str: + def export_entry(cls, entry: "Entry", to_multifile: bool = True) -> str: """Returns a markdown representation of a single entry, with YAML front matter.""" if to_multifile is False: raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgStyle.ERROR)) @@ -126,6 +129,6 @@ class YAMLExporter(TextExporter): ) @classmethod - def export_journal(cls, journal: Journal): + def export_journal(cls, journal: "Journal"): """Returns an error, as YAML export requires a directory as a target.""" raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgStyle.ERROR))