From c9e24e5d3b8d7abc73294e6d3c32a833d90a4c9d Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 21 Jun 2023 06:18:17 -0700 Subject: [PATCH 01/18] Add calendar heatmap exporter Fix #743 --- jrnl/datatypes/NestedDict.py | 7 ++ jrnl/datatypes/__init__.py | 1 + jrnl/plugins/__init__.py | 6 +- jrnl/plugins/calendar_heatmap_exporter.py | 110 ++++++++++++++++++++++ jrnl/plugins/dates_exporter.py | 7 +- jrnl/plugins/util.py | 26 +++++ 6 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 jrnl/datatypes/NestedDict.py create mode 100644 jrnl/datatypes/__init__.py create mode 100644 jrnl/plugins/calendar_heatmap_exporter.py diff --git a/jrnl/datatypes/NestedDict.py b/jrnl/datatypes/NestedDict.py new file mode 100644 index 000000000..e989fa5f0 --- /dev/null +++ b/jrnl/datatypes/NestedDict.py @@ -0,0 +1,7 @@ +"""https://stackoverflow.com/a/74873621/8740440""" + + +class NestedDict(dict): + def __missing__(self, x): + self[x] = NestedDict() + return self[x] diff --git a/jrnl/datatypes/__init__.py b/jrnl/datatypes/__init__.py new file mode 100644 index 000000000..e9859ff98 --- /dev/null +++ b/jrnl/datatypes/__init__.py @@ -0,0 +1 @@ +from .NestedDict import NestedDict diff --git a/jrnl/plugins/__init__.py b/jrnl/plugins/__init__.py index 993d8686a..e23a3aae6 100644 --- a/jrnl/plugins/__init__.py +++ b/jrnl/plugins/__init__.py @@ -3,6 +3,7 @@ from typing import Type +from jrnl.plugins.calendar_heatmap_exporter import CalendarHeatmapExporter from jrnl.plugins.dates_exporter import DatesExporter from jrnl.plugins.fancy_exporter import FancyExporter from jrnl.plugins.jrnl_importer import JRNLImporter @@ -14,14 +15,15 @@ from jrnl.plugins.yaml_exporter import YAMLExporter __exporters = [ + CalendarHeatmapExporter, + DatesExporter, + FancyExporter, JSONExporter, MarkdownExporter, TagExporter, - DatesExporter, TextExporter, XMLExporter, YAMLExporter, - FancyExporter, ] __importers = [JRNLImporter] diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py new file mode 100644 index 000000000..e7d5c4044 --- /dev/null +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -0,0 +1,110 @@ +# Copyright © 2012-2023 jrnl contributors +# License: https://www.gnu.org/licenses/gpl-3.0.html + +import calendar +from datetime import datetime +from typing import TYPE_CHECKING + +from rich import box +from rich.align import Align +from rich.columns import Columns +from rich.console import Console +from rich.table import Table +from rich.text import Text + +from jrnl.datatypes import NestedDict +from jrnl.plugins.text_exporter import TextExporter +from jrnl.plugins.util import get_journal_frequency_as_dict + +if TYPE_CHECKING: + from jrnl.journals import Entry + from jrnl.journals import Journal + + +class CalendarHeatmapExporter(TextExporter): + """This Exporter displays a calendar heatmap of the journaling frequency.""" + + names = ["calendar", "heatmap"] + extension = "cal" + + @classmethod + def export_entry(cls, entry: "Entry"): + raise NotImplementedError + + @classmethod + def print_calendar_heatmap(cls, journal_frequency: NestedDict) -> str: + """Returns a string representation of the calendar heatmap.""" + console = Console() + cal = calendar.Calendar() + curr_year = datetime.now().year + curr_month = datetime.now().month + curr_day = datetime.now().day + with console.capture() as capture: + for year, month_journaling_freq in journal_frequency.items(): + year_calendar = [] + for month in range(1, 13): + if month > curr_month and year == curr_year: + break + table = Table( + title=f"{calendar.month_name[month]} {year}", + style="white", + box=box.SIMPLE_HEAVY, + padding=0, + ) + + for week_day in cal.iterweekdays(): + table.add_column( + "{:.3}".format(calendar.day_name[week_day]), justify="right" + ) + + month_days = cal.monthdayscalendar(year, month) + for weekdays in month_days: + days = [] + for _, day in enumerate(weekdays): + if day == 0: # Not a part of this month, just filler. + day_label = Text(str(day or ""), style="white") + elif ( + day > curr_day + and month == curr_month + and year == curr_year + ): + break + else: + journal_frequency_for_day = ( + month_journaling_freq[month][day] or 0 + ) + # TODO: Make colors configurable? + if journal_frequency_for_day == 0: + day_label = Text( + str(day or ""), style="red on black" + ) + elif journal_frequency_for_day == 1: + day_label = Text( + str(day or ""), style="black on yellow" + ) + elif journal_frequency_for_day == 2: + day_label = Text( + str(day or ""), style="black on green" + ) + else: + day_label = Text( + str(day or ""), style="black on white" + ) + + days.append(day_label) + table.add_row(*days) + + year_calendar.append(Align.center(table)) + + # Print year header line + console.rule(str(year)) + console.print() + # Print calendar + console.print(Columns(year_calendar, padding=1, expand=True)) + return capture.get() + + @classmethod + def export_journal(cls, journal: "Journal"): + """Returns dates and their frequencies for an entire journal.""" + journal_entry_date_frequency = get_journal_frequency_as_dict(journal) + return cls.print_calendar_heatmap(journal_entry_date_frequency) diff --git a/jrnl/plugins/dates_exporter.py b/jrnl/plugins/dates_exporter.py index 38d101dd8..090d70a5e 100644 --- a/jrnl/plugins/dates_exporter.py +++ b/jrnl/plugins/dates_exporter.py @@ -5,6 +5,7 @@ from typing import TYPE_CHECKING from jrnl.plugins.text_exporter import TextExporter +from jrnl.plugins.util import get_journal_frequency_as_str if TYPE_CHECKING: from jrnl.journals import Entry @@ -24,10 +25,6 @@ def export_entry(cls, entry: "Entry"): @classmethod def export_journal(cls, journal: "Journal") -> str: """Returns dates and their frequencies for an entire journal.""" - date_counts = Counter() - for entry in journal.entries: - # entry.date.date() gets date without time - date = str(entry.date.date()) - date_counts[date] += 1 + date_counts = get_journal_frequency_as_str(journal) result = "\n".join(f"{date}, {count}" for date, count in date_counts.items()) return result diff --git a/jrnl/plugins/util.py b/jrnl/plugins/util.py index ceaa0b041..55c7b1199 100644 --- a/jrnl/plugins/util.py +++ b/jrnl/plugins/util.py @@ -1,8 +1,11 @@ # Copyright © 2012-2023 jrnl contributors # License: https://www.gnu.org/licenses/gpl-3.0.html +from collections import Counter from typing import TYPE_CHECKING +from jrnl.datatypes import NestedDict + if TYPE_CHECKING: from jrnl.journals import Journal @@ -28,3 +31,26 @@ def oxford_list(lst: list) -> str: return lst[0] + " or " + lst[1] else: return ", ".join(lst[:-1]) + ", or " + lst[-1] + + +def get_journal_frequency_as_dict(journal: "Journal") -> NestedDict: + """Returns a NestedDict of the form {year: {month: {day: count}}}""" + journal_frequency = NestedDict() + for entry in journal.entries: + date = entry.date.date() + if date.day in journal_frequency[date.year][date.month]: + journal_frequency[date.year][date.month][date.day] += 1 + else: + journal_frequency[date.year][date.month][date.day] = 1 + + return journal_frequency + + +def get_journal_frequency_as_str(journal: "Journal") -> Counter: + """Returns a Counter of the form {date (YYYY-MM-DD): count}""" + date_counts = Counter() + for entry in journal.entries: + # entry.date.date() gets date without time + date = str(entry.date.date()) + date_counts[date] += 1 + return date_counts From cb83cb43ff4ffcda31a729c42d48a135cec32dc1 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 21 Jun 2023 06:31:46 -0700 Subject: [PATCH 02/18] Lint fixes --- jrnl/plugins/calendar_heatmap_exporter.py | 2 +- jrnl/plugins/dates_exporter.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index e7d5c4044..53061d586 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -12,11 +12,11 @@ from rich.table import Table from rich.text import Text -from jrnl.datatypes import NestedDict from jrnl.plugins.text_exporter import TextExporter from jrnl.plugins.util import get_journal_frequency_as_dict if TYPE_CHECKING: + from jrnl.datatypes import NestedDict from jrnl.journals import Entry from jrnl.journals import Journal diff --git a/jrnl/plugins/dates_exporter.py b/jrnl/plugins/dates_exporter.py index 090d70a5e..6a20170b2 100644 --- a/jrnl/plugins/dates_exporter.py +++ b/jrnl/plugins/dates_exporter.py @@ -1,7 +1,6 @@ # Copyright © 2012-2023 jrnl contributors # License: https://www.gnu.org/licenses/gpl-3.0.html -from collections import Counter from typing import TYPE_CHECKING from jrnl.plugins.text_exporter import TextExporter From bd921f2e0518f0051f7887d3ed42123e750fe26a Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 21 Jun 2023 06:35:22 -0700 Subject: [PATCH 03/18] More lint fixes --- jrnl/plugins/calendar_heatmap_exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index 53061d586..010ab401c 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -32,7 +32,7 @@ def export_entry(cls, entry: "Entry"): raise NotImplementedError @classmethod - def print_calendar_heatmap(cls, journal_frequency: NestedDict) -> str: + def print_calendar_heatmap(cls, journal_frequency: "NestedDict") -> str: """Returns a string representation of the calendar heatmap.""" console = Console() cal = calendar.Calendar() From babc6f251770f408234b79cfe6cf9249ff81a57f Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 21 Jun 2023 07:49:21 -0700 Subject: [PATCH 04/18] Surface total number of entries per month in heatmap --- jrnl/plugins/calendar_heatmap_exporter.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index 010ab401c..8476e662a 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -45,9 +45,17 @@ def print_calendar_heatmap(cls, journal_frequency: "NestedDict") -> str: for month in range(1, 13): if month > curr_month and year == curr_year: break + + entries_this_month = sum(month_journaling_freq[month].values()) + if entries_this_month == 0: + entry_msg = "No entries" + elif entries_this_month == 1: + entry_msg = "1 entry" + else: + entry_msg = f"{entries_this_month} entries" table = Table( - title=f"{calendar.month_name[month]} {year}", - style="white", + title=f"{calendar.month_name[month]} {year} ({entry_msg})", + title_style="bold green", box=box.SIMPLE_HEAVY, padding=0, ) From 7a32e7a8c180cc3156261d128db57ee3dca994f7 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 21 Jun 2023 07:55:30 -0700 Subject: [PATCH 05/18] Refactoring --- jrnl/plugins/calendar_heatmap_exporter.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index 8476e662a..ab7bb4c28 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -81,23 +81,16 @@ def print_calendar_heatmap(cls, journal_frequency: "NestedDict") -> str: journal_frequency_for_day = ( month_journaling_freq[month][day] or 0 ) + day = str(day) # TODO: Make colors configurable? if journal_frequency_for_day == 0: - day_label = Text( - str(day or ""), style="red on black" - ) + day_label = Text(day, style="red on black") elif journal_frequency_for_day == 1: - day_label = Text( - str(day or ""), style="black on yellow" - ) + day_label = Text(day, style="black on yellow") elif journal_frequency_for_day == 2: - day_label = Text( - str(day or ""), style="black on green" - ) + day_label = Text(day, style="black on green") else: - day_label = Text( - str(day or ""), style="black on white" - ) + day_label = Text(day, style="black on white") days.append(day_label) table.add_row(*days) From 491739019cd62a37a510537680ee6b44f83c506e Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 21 Jun 2023 07:58:39 -0700 Subject: [PATCH 06/18] More refactoring --- jrnl/plugins/calendar_heatmap_exporter.py | 4 ++-- jrnl/plugins/dates_exporter.py | 4 ++-- jrnl/plugins/util.py | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index ab7bb4c28..3eecbeb20 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -13,7 +13,7 @@ from rich.text import Text from jrnl.plugins.text_exporter import TextExporter -from jrnl.plugins.util import get_journal_frequency_as_dict +from jrnl.plugins.util import get_journal_frequency_nested if TYPE_CHECKING: from jrnl.datatypes import NestedDict @@ -107,5 +107,5 @@ def print_calendar_heatmap(cls, journal_frequency: "NestedDict") -> str: @classmethod def export_journal(cls, journal: "Journal"): """Returns dates and their frequencies for an entire journal.""" - journal_entry_date_frequency = get_journal_frequency_as_dict(journal) + journal_entry_date_frequency = get_journal_frequency_nested(journal) return cls.print_calendar_heatmap(journal_entry_date_frequency) diff --git a/jrnl/plugins/dates_exporter.py b/jrnl/plugins/dates_exporter.py index 6a20170b2..f35f2c95b 100644 --- a/jrnl/plugins/dates_exporter.py +++ b/jrnl/plugins/dates_exporter.py @@ -4,7 +4,7 @@ from typing import TYPE_CHECKING from jrnl.plugins.text_exporter import TextExporter -from jrnl.plugins.util import get_journal_frequency_as_str +from jrnl.plugins.util import get_journal_frequency_one_level if TYPE_CHECKING: from jrnl.journals import Entry @@ -24,6 +24,6 @@ def export_entry(cls, entry: "Entry"): @classmethod def export_journal(cls, journal: "Journal") -> str: """Returns dates and their frequencies for an entire journal.""" - date_counts = get_journal_frequency_as_str(journal) + date_counts = get_journal_frequency_one_level(journal) result = "\n".join(f"{date}, {count}" for date, count in date_counts.items()) return result diff --git a/jrnl/plugins/util.py b/jrnl/plugins/util.py index 55c7b1199..523dd95a3 100644 --- a/jrnl/plugins/util.py +++ b/jrnl/plugins/util.py @@ -33,7 +33,7 @@ def oxford_list(lst: list) -> str: return ", ".join(lst[:-1]) + ", or " + lst[-1] -def get_journal_frequency_as_dict(journal: "Journal") -> NestedDict: +def get_journal_frequency_nested(journal: "Journal") -> NestedDict: """Returns a NestedDict of the form {year: {month: {day: count}}}""" journal_frequency = NestedDict() for entry in journal.entries: @@ -46,7 +46,7 @@ def get_journal_frequency_as_dict(journal: "Journal") -> NestedDict: return journal_frequency -def get_journal_frequency_as_str(journal: "Journal") -> Counter: +def get_journal_frequency_one_level(journal: "Journal") -> Counter: """Returns a Counter of the form {date (YYYY-MM-DD): count}""" date_counts = Counter() for entry in journal.entries: From a9371f665b5e7b6abeab01b2ee94d03f5ad3b33c Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Thu, 29 Jun 2023 03:59:53 -0700 Subject: [PATCH 07/18] Resolve last lint error --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1d5744285..02c80c3b3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "jrnl" -version = "v4.0.1" +version = "v4.0.2.dev" description = "Collect your thoughts and notes without leaving the command line." authors = [ "jrnl contributors ", @@ -158,7 +158,7 @@ pycodestyle = [ "flake8-*" = ["+*"] flake8-black = ["-BLK901"] -[tool.flakeheaven.exceptions."jrnl/journals/__init__.py"] +[tool.flakeheaven.exceptions."*/__init__.py"] pyflakes = ["-F401"] [build-system] From 0a2f040a9e969a552e5243ca524060a0f1a7ee89 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Mon, 3 Jul 2023 04:28:31 -0700 Subject: [PATCH 08/18] Unbump version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 02c80c3b3..207ee8acd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "jrnl" -version = "v4.0.2.dev" +version = "v4.0.1" description = "Collect your thoughts and notes without leaving the command line." authors = [ "jrnl contributors ", From 1fa091d7dc25f692bca8eacadd31a4af4a71cf1b Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Mon, 3 Jul 2023 04:41:51 -0700 Subject: [PATCH 09/18] Add calendar export test scaffolding --- jrnl/plugins/calendar_heatmap_exporter.py | 8 +++++++- tests/bdd/features/format.feature | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index 3eecbeb20..46bf0ec58 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -39,6 +39,7 @@ def print_calendar_heatmap(cls, journal_frequency: "NestedDict") -> str: curr_year = datetime.now().year curr_month = datetime.now().month curr_day = datetime.now().day + hit_first_entry = False with console.capture() as capture: for year, month_journaling_freq in journal_frequency.items(): year_calendar = [] @@ -47,7 +48,12 @@ def print_calendar_heatmap(cls, journal_frequency: "NestedDict") -> str: break entries_this_month = sum(month_journaling_freq[month].values()) - if entries_this_month == 0: + if not hit_first_entry and entries_this_month > 0: + hit_first_entry = True + + if entries_this_month == 0 and not hit_first_entry: + continue + elif entries_this_month == 0: entry_msg = "No entries" elif entries_this_month == 1: entry_msg = "1 entry" diff --git a/tests/bdd/features/format.feature b/tests/bdd/features/format.feature index d03b1ab2c..de523ca0a 100644 --- a/tests/bdd/features/format.feature +++ b/tests/bdd/features/format.feature @@ -565,6 +565,19 @@ Feature: Custom formats | basic_dayone.yaml | +Scenario Outline: Export calendar heatmap + Given we use the config "" + And we use the password "test" if prompted + When we run "jrnl --format calendar" + Then the output should be + 2013-06-09, 1 + 2013-06-10, 1 + + Examples: configs + | config_file | + | simple.yaml | + + Scenario Outline: display_format short and pretty do not crash if specified as config values Given we use the config "" And we use the password "test" if prompted From 23ae0fa1ccd2b2901f1e5f316227ac6420fffc26 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Mon, 15 Jan 2024 15:00:16 -0800 Subject: [PATCH 10/18] WIP: Test debugging + scaffolding --- .vscode/launch.json | 19 +++++++++++++++++++ .vscode/settings.json | 3 +++ tests/bdd/features/format.feature | 26 ++++++++++++++++++++++++-- tests/lib/then_steps.py | 7 +++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 000000000..46602a478 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Module", + "type": "python", + "request": "launch", + "module": "jrnl", + "justMyCode": true, + "args": [ + "--export", + "heatmap", + "--debug"] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..de288e1ea --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} \ No newline at end of file diff --git a/tests/bdd/features/format.feature b/tests/bdd/features/format.feature index e6c72c4f0..0cea90fe5 100644 --- a/tests/bdd/features/format.feature +++ b/tests/bdd/features/format.feature @@ -570,8 +570,30 @@ Scenario Outline: Export calendar heatmap And we use the password "test" if prompted When we run "jrnl --format calendar" Then the output should be - 2013-06-09, 1 - 2013-06-10, 1 + ──────────────────────────────────────────────────────────────────────── 2013 ───────────────────────────────────────────────────────────────────────── + + June 2013 (2 entries) July 2013 (No entries) August 2013 (No entries) September 2013 (No entries) October 2013 (No entries) + + Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun + ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + 1 2 1 2 3 4 5 6 7 1 2 3 4 1 1 2 3 4 5 6 + 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13 + 10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20 + 17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 + 24 25 26 27 28 29 30 29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 + 30 + + November 2013 (No entries) December 2013 (No entries) + + Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun + ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + 1 2 3 1 + 4 5 6 7 8 9 10 2 3 4 5 6 7 8 + 11 12 13 14 15 16 17 9 10 11 12 13 14 15 + 18 19 20 21 22 23 24 16 17 18 19 20 21 22 + 25 26 27 28 29 30 23 24 25 26 27 28 29 + 30 31 + Examples: configs | config_file | diff --git a/tests/lib/then_steps.py b/tests/lib/then_steps.py index 84461bc3e..e0a93c77d 100644 --- a/tests/lib/then_steps.py +++ b/tests/lib/then_steps.py @@ -84,8 +84,15 @@ def output_should_not_contain(expected_output, cli_run): @then(parse("the output should be\n{expected_output}")) @then(parse('the output should be "{expected_output}"')) def output_should_be(expected_output, cli_run): + from pprint import pprint actual = cli_run["stdout"].strip() + print("ACTUAL: \n\n") + print(type(actual)) + pprint(actual) expected = expected_output.strip() + print("EXPECTED: \n\n") + print(type(expected)) + pprint(expected) assert actual == expected From 53377f32062ddbb090ebcb91497c925b06d2980f Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Mon, 15 Jan 2024 15:30:32 -0800 Subject: [PATCH 11/18] Remove broken tests --- tests/bdd/features/format.feature | 49 +++++-------------------------- tests/lib/then_steps.py | 7 ----- 2 files changed, 7 insertions(+), 49 deletions(-) diff --git a/tests/bdd/features/format.feature b/tests/bdd/features/format.feature index 0cea90fe5..7a2c80a27 100644 --- a/tests/bdd/features/format.feature +++ b/tests/bdd/features/format.feature @@ -72,13 +72,13 @@ Feature: Custom formats And the output should be 2020-08-29 11:11 Entry the first. | Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada - | quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus + | quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus | pellentesque | augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu | consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In | commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget | venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo. - | + | | Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo | ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse | potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget @@ -418,9 +418,9 @@ Feature: Custom formats Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per - conubia nostra, per inceptos himenaeos. + conubia nostra, per inceptos himenaeos. ... - + Examples: configs | config_file | | basic_onefile.yaml | @@ -470,7 +470,7 @@ Feature: Custom formats Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo. Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at - ante eget fringilla. @tagthree and also @tagone + ante eget fringilla. @tagthree and also @tagone ... Examples: configs @@ -565,48 +565,13 @@ Feature: Custom formats | basic_dayone.yaml | -Scenario Outline: Export calendar heatmap - Given we use the config "" - And we use the password "test" if prompted - When we run "jrnl --format calendar" - Then the output should be - ──────────────────────────────────────────────────────────────────────── 2013 ───────────────────────────────────────────────────────────────────────── - - June 2013 (2 entries) July 2013 (No entries) August 2013 (No entries) September 2013 (No entries) October 2013 (No entries) - - Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun - ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ - 1 2 1 2 3 4 5 6 7 1 2 3 4 1 1 2 3 4 5 6 - 3 4 5 6 7 8 9 8 9 10 11 12 13 14 5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13 - 10 11 12 13 14 15 16 15 16 17 18 19 20 21 12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20 - 17 18 19 20 21 22 23 22 23 24 25 26 27 28 19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27 - 24 25 26 27 28 29 30 29 30 31 26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31 - 30 - - November 2013 (No entries) December 2013 (No entries) - - Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat Sun - ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━ - 1 2 3 1 - 4 5 6 7 8 9 10 2 3 4 5 6 7 8 - 11 12 13 14 15 16 17 9 10 11 12 13 14 15 - 18 19 20 21 22 23 24 16 17 18 19 20 21 22 - 25 26 27 28 29 30 23 24 25 26 27 28 29 - 30 31 - - - Examples: configs - | config_file | - | simple.yaml | - - Scenario Outline: display_format short and pretty do not crash if specified as config values Given we use the config "" And we use the password "test" if prompted When we run "jrnl --config-override display_format short -1" Then we should get no error When we run "jrnl --config-override display_format pretty -1" - Then we should get no error + Then we should get no error Examples: configs | config_file | @@ -623,7 +588,7 @@ Scenario Outline: Export calendar heatmap When we run "jrnl --format markdown --file {cache_dir}" Then the cache directory should contain 5 files And we should get no error - + Scenario: Export entries in text format with a title longer than max file name length. Given we use the config "basic_onefile.yaml" And we create a cache directory diff --git a/tests/lib/then_steps.py b/tests/lib/then_steps.py index e0a93c77d..84461bc3e 100644 --- a/tests/lib/then_steps.py +++ b/tests/lib/then_steps.py @@ -84,15 +84,8 @@ def output_should_not_contain(expected_output, cli_run): @then(parse("the output should be\n{expected_output}")) @then(parse('the output should be "{expected_output}"')) def output_should_be(expected_output, cli_run): - from pprint import pprint actual = cli_run["stdout"].strip() - print("ACTUAL: \n\n") - print(type(actual)) - pprint(actual) expected = expected_output.strip() - print("EXPECTED: \n\n") - print(type(expected)) - pprint(expected) assert actual == expected From 6304fb585d317febcd6ba679d0296035008e1995 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Mon, 15 Jan 2024 15:31:25 -0800 Subject: [PATCH 12/18] Remove args from .vscode/launch.json --- .vscode/launch.json | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 46602a478..aac569e49 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,19 +1,16 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Module", - "type": "python", - "request": "launch", - "module": "jrnl", - "justMyCode": true, - "args": [ - "--export", - "heatmap", - "--debug"] - } - ] -} \ No newline at end of file + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Module", + "type": "python", + "request": "launch", + "module": "jrnl", + "justMyCode": true, + "args": [] + } + ] +} From 81f0f6ff4303671c755b3613d410509baf220ee0 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Mon, 15 Jan 2024 16:16:32 -0800 Subject: [PATCH 13/18] Discard changes to tests/bdd/features/format.feature --- tests/bdd/features/format.feature | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/bdd/features/format.feature b/tests/bdd/features/format.feature index 7a2c80a27..b02831d67 100644 --- a/tests/bdd/features/format.feature +++ b/tests/bdd/features/format.feature @@ -72,13 +72,13 @@ Feature: Custom formats And the output should be 2020-08-29 11:11 Entry the first. | Lorem @ipsum dolor sit amet, consectetur adipiscing elit. Praesent malesuada - | quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus + | quis est ac dignissim. Aliquam dignissim rutrum pretium. Phasellus | pellentesque | augue et venenatis facilisis. Suspendisse potenti. Sed dignissim sed nisl eu | consequat. Aenean ante ex, elementum ut interdum et, mattis eget lacus. In | commodo nulla nec tellus placerat, sed ultricies metus bibendum. Duis eget | venenatis erat. In at dolor dui. @tagone and maybe also @tagtwo. - | + | | Curabitur accumsan nunc ac neque tristique, eleifend faucibus justo | ullamcorper. Suspendisse at mattis nunc. Nullam eget lacinia urna. Suspendisse | potenti. Ut urna est, venenatis sed ante in, ultrices congue mi. Maecenas eget @@ -418,9 +418,9 @@ Feature: Custom formats Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam eu ligula eget velit scelerisque fringilla. Phasellus pharetra justo et nulla fringilla, ac porta sapien accumsan. Class aptent taciti sociosqu ad litora torquent per - conubia nostra, per inceptos himenaeos. + conubia nostra, per inceptos himenaeos. ... - + Examples: configs | config_file | | basic_onefile.yaml | @@ -470,7 +470,7 @@ Feature: Custom formats Quisque egestas semper nibh in hendrerit. Nam finibus ex in mi mattis vulputate. Sed mauris urna, consectetur in justo eu, volutpat accumsan justo. Phasellus aliquam lacus placerat convallis vestibulum. Curabitur maximus at - ante eget fringilla. @tagthree and also @tagone + ante eget fringilla. @tagthree and also @tagone ... Examples: configs @@ -571,7 +571,7 @@ Feature: Custom formats When we run "jrnl --config-override display_format short -1" Then we should get no error When we run "jrnl --config-override display_format pretty -1" - Then we should get no error + Then we should get no error Examples: configs | config_file | @@ -588,7 +588,7 @@ Feature: Custom formats When we run "jrnl --format markdown --file {cache_dir}" Then the cache directory should contain 5 files And we should get no error - + Scenario: Export entries in text format with a title longer than max file name length. Given we use the config "basic_onefile.yaml" And we create a cache directory From 8546cc9d1cabadabb36ac55467a2564fee9036d3 Mon Sep 17 00:00:00 2001 From: Micah Jerome Ellison Date: Mon, 26 Feb 2024 19:53:51 -0800 Subject: [PATCH 14/18] Remove extraneous vscode files --- .vscode/launch.json | 16 ---------------- .vscode/settings.json | 3 --- 2 files changed, 19 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/settings.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index aac569e49..000000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Module", - "type": "python", - "request": "launch", - "module": "jrnl", - "justMyCode": true, - "args": [] - } - ] -} diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index de288e1ea..000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.formatting.provider": "black" -} \ No newline at end of file From 0c5270224ad519017139e1cf93cc02f9c541dbd4 Mon Sep 17 00:00:00 2001 From: Jonathan Wren Date: Mon, 26 Feb 2024 19:54:17 -0800 Subject: [PATCH 15/18] move NestedDict to utils file --- jrnl/datatypes/NestedDict.py | 7 ------- jrnl/datatypes/__init__.py | 1 - jrnl/plugins/util.py | 9 +++++++-- 3 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 jrnl/datatypes/NestedDict.py delete mode 100644 jrnl/datatypes/__init__.py diff --git a/jrnl/datatypes/NestedDict.py b/jrnl/datatypes/NestedDict.py deleted file mode 100644 index e989fa5f0..000000000 --- a/jrnl/datatypes/NestedDict.py +++ /dev/null @@ -1,7 +0,0 @@ -"""https://stackoverflow.com/a/74873621/8740440""" - - -class NestedDict(dict): - def __missing__(self, x): - self[x] = NestedDict() - return self[x] diff --git a/jrnl/datatypes/__init__.py b/jrnl/datatypes/__init__.py deleted file mode 100644 index e9859ff98..000000000 --- a/jrnl/datatypes/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .NestedDict import NestedDict diff --git a/jrnl/plugins/util.py b/jrnl/plugins/util.py index 975c1ddd6..56d119061 100644 --- a/jrnl/plugins/util.py +++ b/jrnl/plugins/util.py @@ -4,12 +4,17 @@ from collections import Counter from typing import TYPE_CHECKING -from jrnl.datatypes import NestedDict - if TYPE_CHECKING: from jrnl.journals import Journal +"""https://stackoverflow.com/a/74873621/8740440""" +class NestedDict(dict): + def __missing__(self, x): + self[x] = NestedDict() + return self[x] + + 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 From 86886394c033f14ef4e0a1e63987e09bef831699 Mon Sep 17 00:00:00 2001 From: Jonathan Wren Date: Mon, 26 Feb 2024 20:07:32 -0800 Subject: [PATCH 16/18] run formatter --- jrnl/plugins/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jrnl/plugins/util.py b/jrnl/plugins/util.py index 56d119061..6b569016f 100644 --- a/jrnl/plugins/util.py +++ b/jrnl/plugins/util.py @@ -8,8 +8,9 @@ from jrnl.journals import Journal -"""https://stackoverflow.com/a/74873621/8740440""" class NestedDict(dict): + """https://stackoverflow.com/a/74873621/8740440""" + def __missing__(self, x): self[x] = NestedDict() return self[x] From 4e90caefd01e322e79325a51d180054b02ba866c Mon Sep 17 00:00:00 2001 From: Jonathan Wren Date: Mon, 26 Feb 2024 20:15:25 -0800 Subject: [PATCH 17/18] fix import error --- jrnl/plugins/calendar_heatmap_exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index 46bf0ec58..78cbaf9ab 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -16,7 +16,7 @@ from jrnl.plugins.util import get_journal_frequency_nested if TYPE_CHECKING: - from jrnl.datatypes import NestedDict + from jrnl.plugins.util import NestedDict from jrnl.journals import Entry from jrnl.journals import Journal From 2e57286e9bb501682304ac3b6f46d34c769535b6 Mon Sep 17 00:00:00 2001 From: Aaron Lichtman Date: Wed, 26 Jun 2024 19:14:22 -0700 Subject: [PATCH 18/18] Address lints --- jrnl/plugins/calendar_heatmap_exporter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jrnl/plugins/calendar_heatmap_exporter.py b/jrnl/plugins/calendar_heatmap_exporter.py index 78cbaf9ab..69f9566cc 100644 --- a/jrnl/plugins/calendar_heatmap_exporter.py +++ b/jrnl/plugins/calendar_heatmap_exporter.py @@ -16,9 +16,9 @@ from jrnl.plugins.util import get_journal_frequency_nested if TYPE_CHECKING: - from jrnl.plugins.util import NestedDict from jrnl.journals import Entry from jrnl.journals import Journal + from jrnl.plugins.util import NestedDict class CalendarHeatmapExporter(TextExporter):