rework MsgType into MsgStyle so messages can have different styles

This commit is contained in:
Jonathan Wren 2022-05-01 13:22:11 -07:00
parent 6f5a082075
commit 16755f849a
17 changed files with 161 additions and 99 deletions

View file

@ -24,7 +24,7 @@ from .prompt import create_password
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def make_key(password):
@ -54,13 +54,13 @@ def decrypt_content(
set_keychain(keychain, None)
attempt = 1
while result is None and attempt < max_attempts:
print_msg(Message(MsgText.WrongPasswordTryAgain, MsgType.WARNING))
print_msg(Message(MsgText.WrongPasswordTryAgain, MsgStyle.WARNING))
password = getpass.getpass()
result = decrypt_func(password)
attempt += 1
if result is None:
raise JrnlException(Message(MsgText.PasswordMaxTriesExceeded, MsgType.ERROR))
raise JrnlException(Message(MsgText.PasswordMaxTriesExceeded, MsgStyle.ERROR))
return result
@ -82,7 +82,7 @@ class EncryptedJournal(Journal):
print_msg(
Message(
MsgText.DirectoryCreated,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"directory_name": dirname},
)
)
@ -92,7 +92,7 @@ class EncryptedJournal(Journal):
print_msg(
Message(
MsgText.JournalCreated,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"journal_name": self.name, "path": filename},
)
)
@ -188,7 +188,7 @@ def get_keychain(journal_name):
return keyring.get_password("jrnl", journal_name)
except keyring.errors.KeyringError as e:
if not isinstance(e, keyring.errors.NoKeyringError):
print_msg(Message(MsgText.KeyringRetrievalFailure, MsgType.ERROR))
print_msg(Message(MsgText.KeyringRetrievalFailure, MsgStyle.ERROR))
return ""
@ -205,7 +205,7 @@ def set_keychain(journal_name, password):
keyring.set_password("jrnl", journal_name, password)
except keyring.errors.KeyringError as e:
if isinstance(e, keyring.errors.NoKeyringError):
msg = Message(MsgText.KeyringBackendNotFound, MsgType.WARNING)
msg = Message(MsgText.KeyringBackendNotFound, MsgStyle.WARNING)
else:
msg = Message(MsgText.KeyringRetrievalFailure, MsgType.ERROR)
msg = Message(MsgText.KeyringRetrievalFailure, MsgStyle.ERROR)
print_msg(msg)

View file

@ -15,7 +15,7 @@ from .prompt import yesno
from jrnl.output import print_msg
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
class Tag:
@ -90,7 +90,7 @@ class Journal:
print_msg(
Message(
MsgText.DirectoryCreated,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"directory_name": dirname},
)
)
@ -98,7 +98,7 @@ class Journal:
print_msg(
Message(
MsgText.JournalCreated,
MsgType.NORMAL,
MsgStyle.NORMAL,
{
"journal_name": self.name,
"filename": filename,
@ -431,7 +431,7 @@ def open_journal(journal_name, config, legacy=False):
print_msg(
Message(
MsgText.ConfigEncryptedForUnencryptableJournalType,
MsgType.WARNING,
MsgStyle.WARNING,
{
"journal_name": journal_name,
},

View file

@ -12,7 +12,7 @@ from jrnl.output import print_msg
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def configure_logger(debug=False):
@ -49,7 +49,7 @@ def cli(manual_args=None):
print_msg(
Message(
MsgText.KeyboardInterruptMsg,
MsgType.ERROR,
MsgStyle.ERROR,
)
)
@ -73,7 +73,7 @@ def cli(manual_args=None):
print_msg(
Message(
MsgText.UncaughtException,
MsgType.ERROR,
MsgStyle.ERROR,
{"name": type(e).__name__, "exception": e},
)
)

View file

@ -18,7 +18,7 @@ from jrnl.output import print_msg
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def preconfig_diagnostic(_):
@ -78,7 +78,7 @@ def postconfig_encrypt(args, config, original_config, **kwargs):
raise JrnlException(
Message(
MsgText.CannotEncryptJournalType,
MsgType.ERROR,
MsgStyle.ERROR,
{
"journal_name": args.journal_name,
"journal_type": journal.__class__.__name__,
@ -94,7 +94,7 @@ def postconfig_encrypt(args, config, original_config, **kwargs):
print_msg(
Message(
MsgText.JournalEncryptedTo,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"path": args.filename or new_journal.config["journal"]},
)
)
@ -122,7 +122,7 @@ def postconfig_decrypt(args, config, original_config, **kwargs):
print_msg(
Message(
MsgText.JournalDecryptedTo,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"path": args.filename or new_journal.config["journal"]},
)
)

View file

@ -11,7 +11,7 @@ from jrnl.output import print_msg
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
# Constants
@ -72,7 +72,7 @@ def get_config_path():
raise JrnlException(
Message(
MsgText.ConfigDirectoryIsFile,
MsgType.ERROR,
MsgStyle.ERROR,
{
"config_directory_path": os.path.join(
xdg.BaseDirectory.xdg_config_home, XDG_RESOURCE
@ -147,7 +147,7 @@ def verify_config_colors(config):
print_msg(
Message(
MsgText.InvalidColor,
MsgType.NORMAL,
MsgStyle.NORMAL,
{
"key": key,
"color": color,
@ -202,7 +202,7 @@ def get_journal_name(args, config):
raise JrnlException(
Message(
MsgText.NoDefaultJournal,
MsgType.ERROR,
MsgStyle.ERROR,
{"journals": list_journals(config)},
),
)

View file

@ -12,7 +12,7 @@ from jrnl.output import print_msg
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def get_text_from_editor(config, template=""):
@ -33,7 +33,7 @@ def get_text_from_editor(config, template=""):
raise JrnlException(
Message(
MsgText.EditorMisconfigured,
MsgType.ERROR,
MsgStyle.ERROR,
{"editor_key": config["editor"]},
)
)
@ -43,7 +43,7 @@ def get_text_from_editor(config, template=""):
os.remove(tmpfile)
if not raw:
raise JrnlException(Message(MsgText.NoTextReceived, MsgType.ERROR))
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.ERROR))
return raw
@ -52,7 +52,7 @@ def get_text_from_stdin():
print_msg(
Message(
MsgText.WritingEntryStart,
MsgType.TITLE,
MsgStyle.TITLE,
{
"how_to_quit": MsgText.HowToQuitWindows
if on_windows()
@ -66,8 +66,8 @@ def get_text_from_stdin():
except KeyboardInterrupt:
logging.error("Write mode: keyboard interrupt")
raise JrnlException(
Message(MsgText.KeyboardInterruptMsg, MsgType.ERROR),
Message(MsgText.JournalNotSaved, MsgType.WARNING),
Message(MsgText.KeyboardInterruptMsg, MsgStyle.ERROR),
Message(MsgText.JournalNotSaved, MsgStyle.WARNING),
)
return raw

View file

@ -21,7 +21,7 @@ from jrnl.output import print_msg
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def upgrade_config(config_data, alt_config_path=None):
@ -37,7 +37,9 @@ def upgrade_config(config_data, alt_config_path=None):
save_config(config_data, alt_config_path)
config_path = alt_config_path if alt_config_path else get_config_path()
print_msg(
Message(MsgText.ConfigUpdated, MsgType.NORMAL, {"config_path": config_path})
Message(
MsgText.ConfigUpdated, MsgStyle.NORMAL, {"config_path": config_path}
)
)
@ -54,7 +56,7 @@ def find_alt_config(alt_config):
if not os.path.exists(alt_config):
raise JrnlException(
Message(
MsgText.AltConfigNotFound, MsgType.ERROR, {"config_file": alt_config}
MsgText.AltConfigNotFound, MsgStyle.ERROR, {"config_file": alt_config}
)
)
@ -121,7 +123,7 @@ def install():
)
if encrypt:
default_config["encrypt"] = True
print_msg(Message(MsgText.JournalEncrypted, MsgType.NORMAL))
print_msg(Message(MsgText.JournalEncrypted, MsgStyle.NORMAL))
save_config(default_config)
return default_config

View file

@ -20,7 +20,7 @@ from jrnl.output import print_msgs
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def run(args):
@ -138,9 +138,7 @@ def write_mode(args, config, journal, **kwargs):
if not raw or raw.isspace():
logging.error("Write mode: couldn't get raw text or entry was empty")
raise JrnlException(
Message(MsgText.NoTextReceived, MsgType.ERROR)
)
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.ERROR))
logging.debug(
'Write mode: appending raw text to journal "%s": %s', args.journal_name, raw
@ -149,7 +147,7 @@ def write_mode(args, config, journal, **kwargs):
print_msg(
Message(
MsgText.JournalEntryAdded,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"journal_name": args.journal_name},
)
)
@ -213,7 +211,7 @@ def _get_editor_template(config, **kwargs):
raise JrnlException(
Message(
MsgText.CantReadTemplate,
MsgType.ERROR,
MsgStyle.ERROR,
{"template": config["template"]},
)
)
@ -256,7 +254,7 @@ def _edit_search_results(config, journal, old_entries, **kwargs):
raise JrnlException(
Message(
MsgText.EditorNotConfigured,
MsgType.ERROR,
MsgStyle.ERROR,
{"config_file": get_config_path()},
)
)
@ -295,7 +293,7 @@ def _print_edited_summary(journal, old_stats, **kwargs):
if stats["added"] == 1
else MsgText.JournalCountAddedPlural
)
msgs.append(Message(my_msg, MsgType.NORMAL, {"num": stats["added"]}))
msgs.append(Message(my_msg, MsgStyle.NORMAL, {"num": stats["added"]}))
if stats["deleted"] > 0:
my_msg = (
@ -303,7 +301,7 @@ def _print_edited_summary(journal, old_stats, **kwargs):
if stats["deleted"] == 1
else MsgText.JournalCountDeletedPlural
)
msgs.append(Message(my_msg, MsgType.NORMAL, {"num": stats["deleted"]}))
msgs.append(Message(my_msg, MsgStyle.NORMAL, {"num": stats["deleted"]}))
if stats["modified"] > 0:
my_msg = (
@ -311,7 +309,7 @@ def _print_edited_summary(journal, old_stats, **kwargs):
if stats["modified"] == 1
else MsgText.JournalCountModifiedPlural
)
msgs.append(Message(my_msg, MsgType.NORMAL, {"num": stats["modified"]}))
msgs.append(Message(my_msg, MsgStyle.NORMAL, {"num": stats["modified"]}))
print_msgs(msgs)
@ -322,7 +320,7 @@ def _get_predit_stats(journal):
def _delete_search_results(journal, old_entries, **kwargs):
if not journal.entries:
raise JrnlException(Message(MsgText.NothingToDelete, MsgType.ERROR))
raise JrnlException(Message(MsgText.NothingToDelete, MsgStyle.ERROR))
entries_to_delete = journal.prompt_delete_entries()

View file

@ -1,23 +1,81 @@
from enum import Enum
from typing import NamedTuple
from typing import Mapping
from typing import Callable
from rich.panel import Panel
from rich import box
class _MsgColor(NamedTuple):
# This is a colorama color, and colorama doesn't support enums or type hints
# see: https://github.com/tartley/colorama/issues/91
"""
String representing a standard color to display
see: https://rich.readthedocs.io/en/stable/appendix/colors.html
"""
color: str
class MsgType(Enum):
TITLE = _MsgColor("cyan")
NORMAL = _MsgColor("blue")
WARNING = _MsgColor("yellow")
ERROR = _MsgColor("red")
class MsgDecoration(Enum):
NONE = {
"callback": lambda x, **kwargs: x,
"args": {}
}
BRACKET = {
"callback": lambda x, **kwargs: f"[ {x} ]",
"args": {}
}
BOX = {
"callback": Panel,
"args": {
"expand": False,
"padding": (0, 2),
"title_align": "left",
"box": box.HEAVY,
},
}
@property
def callback(self) -> Callable:
return self.value["callback"]
@property
def args(self) -> dict:
return self.value["args"]
class MsgStyle(Enum):
BARE = {
"decoration": MsgDecoration.NONE,
"color": _MsgColor("white"),
}
PLAIN = {
"decoration": MsgDecoration.BRACKET,
"color": _MsgColor("white"),
}
TITLE = {
"decoration": MsgDecoration.BOX,
"color": _MsgColor("cyan"),
}
NORMAL = {
"decoration": MsgDecoration.BOX,
"color": _MsgColor("white"),
}
WARNING = {
"decoration": MsgDecoration.BOX,
"color": _MsgColor("yellow"),
}
ERROR = {
"decoration": MsgDecoration.BOX,
"color": _MsgColor("red"),
}
@property
def decoration(self) -> MsgDecoration:
return self.value["decoration"]
@property
def color(self) -> _MsgColor:
return self.value.color
return self.value["color"].color
class MsgText(Enum):
@ -193,7 +251,11 @@ class MsgText(Enum):
Too many attempts with wrong password
"""
WrongPasswordTryAgain = "Wrong password, try again."
PasswordCanNotBeEmpty = """
Password can't be empty!
"""
WrongPasswordTryAgain = "Wrong password, try again"
# --- Search --- #
NothingToDelete = """
@ -238,5 +300,5 @@ class MsgText(Enum):
class Message(NamedTuple):
text: MsgText
type: MsgType = MsgType.NORMAL
style: MsgStyle = MsgStyle.NORMAL
params: Mapping = {}

View file

@ -6,13 +6,11 @@ import sys
import textwrap
from rich import print
from rich.panel import Panel
from rich.text import Text
from rich import box
from rich.console import Console
from jrnl.messages import Message
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
from jrnl.messages import MsgText
@ -20,7 +18,7 @@ def deprecated_cmd(old_cmd, new_cmd, callback=None, **kwargs):
print_msg(
Message(
MsgText.DeprecatedCommand,
MsgType.WARNING,
MsgStyle.WARNING,
{"old_cmd": old_cmd, "new_cmd": new_cmd},
)
)
@ -43,25 +41,21 @@ def list_journals(configuration):
def print_msg(msg: Message) -> None:
print_msgs([msg])
print_msgs([msg], style=msg.style)
def print_msgs(msgs: list[Message], delimiter: str = "\n") -> None:
def print_msgs(
msgs: list[Message], delimiter: str = "\n", style: MsgStyle = MsgStyle.NORMAL
) -> None:
# Same as print_msg, but for a list
text = Text("")
kwargs = {
"expand": False,
"border_style": None,
"padding": (0, 2),
"title_align": "left",
"box": box.HEAVY,
}
callback = style.decoration.callback
args = style.decoration.args
for msg in msgs:
kwargs["border_style"] = msg.type.color
if msg.type == MsgType.ERROR:
kwargs["title"] = "Error"
args["border_style"] = msg.style.color
if msg.style == MsgStyle.ERROR:
args["title"] = "Error"
if is_keyboard_int(msg):
print()
@ -72,7 +66,8 @@ def print_msgs(msgs: list[Message], delimiter: str = "\n") -> None:
text.rstrip()
Console(stderr=True).print(Panel(text, **kwargs))
# import ipdb; ipdb.sset_trace()
Console(stderr=True).print(callback(text, **args))
def is_keyboard_int(msg: Message) -> bool:

View file

@ -5,7 +5,7 @@
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
from textwrap import TextWrapper
from .text_exporter import TextExporter
@ -90,7 +90,7 @@ def check_provided_linewrap_viability(linewrap, card, journal):
raise JrnlException(
Message(
MsgText.LineWrapTooSmallForDateFormat,
MsgType.NORMAL,
MsgStyle.NORMAL,
{
"config_linewrap": linewrap,
"columns": width_violation,

View file

@ -7,7 +7,7 @@ import sys
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
from jrnl.output import print_msg
@ -29,8 +29,8 @@ class JRNLImporter:
other_journal_txt = sys.stdin.read()
except KeyboardInterrupt:
raise JrnlException(
Message(MsgText.KeyboardInterruptMsg, MsgType.ERROR),
Message(MsgText.ImportAborted, MsgType.WARNING),
Message(MsgText.KeyboardInterruptMsg, MsgStyle.ERROR),
Message(MsgText.ImportAborted, MsgStyle.WARNING),
)
journal.import_(other_journal_txt)
@ -39,7 +39,7 @@ class JRNLImporter:
print_msg(
Message(
MsgText.ImportSummary,
MsgType.NORMAL,
MsgStyle.NORMAL,
{
"count": new_cnt - old_cnt,
"journal_name": journal.name,

View file

@ -10,7 +10,7 @@ from .text_exporter import TextExporter
from jrnl.output import print_msg
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
class MarkdownExporter(TextExporter):
@ -67,7 +67,7 @@ class MarkdownExporter(TextExporter):
print_msg(
Message(
MsgText.HeadingsPastH6,
MsgType.WARNING,
MsgStyle.WARNING,
{"date": date_str, "title": entry.title},
)
)

View file

@ -9,7 +9,7 @@ import unicodedata
from jrnl.output import print_msg
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
class TextExporter:
@ -36,7 +36,7 @@ class TextExporter:
print_msg(
Message(
MsgText.JournalExportedTo,
MsgType.NORMAL,
MsgStyle.NORMAL,
{
"path": path,
},
@ -60,7 +60,7 @@ class TextExporter:
print_msg(
Message(
MsgText.JournalExportedTo,
MsgType.NORMAL,
MsgStyle.NORMAL,
{"path": path},
)
)

View file

@ -11,7 +11,7 @@ from .text_exporter import TextExporter
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
from jrnl.output import print_msg
@ -25,7 +25,7 @@ class YAMLExporter(TextExporter):
def export_entry(cls, entry, to_multifile=True):
"""Returns a markdown representation of a single entry, with YAML front matter."""
if to_multifile is False:
raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgType.ERROR))
raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgStyle.ERROR))
date_str = entry.date.strftime(entry.journal.config["timeformat"])
body_wrapper = "\n" if entry.body else ""
@ -80,7 +80,7 @@ class YAMLExporter(TextExporter):
print_msg(
Message(
MsgText.HeadingsPastH6,
MsgType.WARNING,
MsgStyle.WARNING,
{"date": date_str, "title": entry.title},
)
)
@ -129,4 +129,4 @@ class YAMLExporter(TextExporter):
@classmethod
def export_journal(cls, journal):
"""Returns an error, as YAML export requires a directory as a target."""
raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgType.ERROR))
raise JrnlException(Message(MsgText.YamlMustBeDirectory, MsgStyle.ERROR))

View file

@ -4,6 +4,11 @@
import getpass
import sys
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgStyle
from jrnl.output import print_msg
def create_password(
journal_name: str, prompt: str = "Enter password for new journal: "
@ -11,7 +16,7 @@ def create_password(
while True:
pw = getpass.getpass(prompt)
if not pw:
print("Password can't be an empty string!", file=sys.stderr)
print_msg(Message(MsgText.PasswordCanNotBeEmpty, MsgStyle.PLAIN))
continue
elif pw == getpass.getpass("Enter password again: "):
break

View file

@ -17,7 +17,7 @@ from jrnl.output import print_msgs
from jrnl.exception import JrnlException
from jrnl.messages import Message
from jrnl.messages import MsgText
from jrnl.messages import MsgType
from jrnl.messages import MsgStyle
def backup(filename, binary=False):
@ -32,15 +32,15 @@ def backup(filename, binary=False):
print_msg(
Message(
MsgText.BackupCreated, MsgType.NORMAL, {"filename": f"filename.backup"}
MsgText.BackupCreated, MsgStyle.NORMAL, {"filename": f"filename.backup"}
)
)
except FileNotFoundError:
print_msg(Message(MsgText.DoesNotExist, MsgType.WARNING, {"name": filename}))
print_msg(Message(MsgText.DoesNotExist, MsgStyle.WARNING, {"name": filename}))
cont = yesno(f"\nCreate {filename}?", default=False)
if not cont:
raise JrnlException(Message(MsgText.UpgradeAborted, MsgType.WARNING))
raise JrnlException(Message(MsgText.UpgradeAborted, MsgStyle.WARNING))
def check_exists(path):
@ -53,7 +53,7 @@ def check_exists(path):
def upgrade_jrnl(config_path):
config = load_config(config_path)
print_msg(Message(MsgText.WelcomeToJrnl, MsgType.NORMAL, {"version": __version__}))
print_msg(Message(MsgText.WelcomeToJrnl, MsgStyle.NORMAL, {"version": __version__}))
encrypted_journals = {}
plain_journals = {}
@ -71,7 +71,7 @@ def upgrade_jrnl(config_path):
if os.path.exists(os.path.expanduser(path)):
path = os.path.expanduser(path)
else:
print_msg(Message(MsgText.DoesNotExist, MsgType.ERROR, {"name": path}))
print_msg(Message(MsgText.DoesNotExist, MsgStyle.ERROR, {"name": path}))
continue
if encrypt:
@ -117,7 +117,7 @@ def upgrade_jrnl(config_path):
cont = yesno("\nContinue upgrading jrnl?", default=False)
if not cont:
raise JrnlException(Message(MsgText.UpgradeAborted), MsgType.WARNING)
raise JrnlException(Message(MsgText.UpgradeAborted), MsgStyle.WARNING)
for journal_name, path in encrypted_journals.items():
print_msg(
@ -158,10 +158,10 @@ def upgrade_jrnl(config_path):
if len(failed_journals) > 0:
raise JrnlException(
Message(MsgText.AbortingUpgrade, MsgType.WARNING),
Message(MsgText.AbortingUpgrade, MsgStyle.WARNING),
Message(
MsgText.JournalFailedUpgrade,
MsgType.ERROR,
MsgStyle.ERROR,
{
"s": "s" if len(failed_journals) > 1 else "",
"failed_journals": "\n".join(j.name for j in failed_journals),
@ -173,11 +173,11 @@ def upgrade_jrnl(config_path):
for j in all_journals:
j.write()
print_msg(Message(MsgText.UpgradingConfig, MsgType.NORMAL))
print_msg(Message(MsgText.UpgradingConfig, MsgStyle.NORMAL))
backup(config_path)
print_msg(Message(MsgText.AllDoneUpgrade, MsgType.NORMAL))
print_msg(Message(MsgText.AllDoneUpgrade, MsgStyle.NORMAL))
def is_old_version(config_path):