Prevent filtered delete from deleting journal (#935)

* Prevent filtered deletion from deleting entire journal #932 and add lots of deletion tests
* Undo removal of deletion feature
* Use more performant deletion
This commit is contained in:
Micah Jerome Ellison 2020-05-06 13:47:39 -07:00 committed by GitHub
parent cfbebe0d38
commit d9ebfe852b
6 changed files with 191 additions and 17 deletions

View file

@ -0,0 +1,12 @@
default_hour: 9
default_minute: 0
editor: ""
encrypt: false
highlight: true
journals:
default: features/journals/deletion_filters.journal
linewrap: 80
tagsymbols: "@"
template: false
timeformat: "%Y-%m-%d %H:%M"
indent_character: "|"

View file

@ -0,0 +1,14 @@
[2019-10-01 08:00] It's just another day in October.
Not much to write about.
[2020-01-01 08:00] Happy New Year!
So this is the New Year. @holidays
[2020-03-01 08:00] It's just another day in March.
A stick, a stone, it's the end of the road.
[2020-05-01 09:00] Happy May Day!
@holidays @springtime Several holidays fall on this date.
[2020-05-02 12:10] Writing tests. *
@springtime They will help prevent bugs.

View file

@ -1,5 +1,4 @@
Feature: Delete entries from journal Feature: Delete entries from journal
@skip
Scenario: --delete flag allows deletion of single entry Scenario: --delete flag allows deletion of single entry
Given we use the config "deletion.yaml" Given we use the config "deletion.yaml"
When we run "jrnl -n 1" When we run "jrnl -n 1"
@ -18,3 +17,133 @@ Feature: Delete entries from journal
""" """
2019-10-29 11:11 Second entry. 2019-10-29 11:11 Second entry.
""" """
Scenario: Backing out of interactive delete does not change journal
Given we use the config "deletion.yaml"
When we run "jrnl --delete -n 1" and enter
"""
N
"""
Then the journal should have 3 entries
And the journal should contain "[2019-10-29 11:11] First entry."
And the journal should contain "[2019-10-29 11:11] Second entry."
And the journal should contain "[2019-10-29 11:13] Third entry."
Scenario: --delete flag with nonsense input deletes nothing (issue #932)
Given we use the config "deletion.yaml"
When we run "jrnl --delete asdfasdf"
When we run "jrnl -n 1"
Then the output should contain
"""
2019-10-29 11:13 Third entry.
"""
And the journal should have 3 entries
Scenario: --delete flag with tag only deletes tagged entries
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete @holidays" and enter
"""
Y
Y
"""
Then the journal should have 3 entries
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should contain "[2020-05-02 12:10] Writing tests."
Scenario: --delete flag with multiple tags deletes all entries matching any of the tags
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete @holidays @springtime" and enter
"""
Y
Y
Y
"""
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
and the journal should not contain "[2020-05-02 12:10] Writing tests. *"
and the journal should have 2 entries
Scenario: --delete flag with -and and tags only deletes boolean AND of tagged entries
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete -and @holidays @springtime" and enter
"""
Y
"""
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should contain "[2020-01-01 08:00] Happy New Year!"
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
and the journal should contain "[2020-05-02 12:10] Writing tests. *"
and the journal should have 4 entries
Scenario: --delete flag with -not does not delete entries with -not tag
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete @holidays -not @springtime" and enter
"""
Y
"""
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should contain "[2020-05-01 09:00] Happy May Day!"
and the journal should contain "[2020-05-02 12:10] Writing tests. *"
and the journal should have 4 entries
Scenario: --delete flag with -from only deletes entries since a specified date
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete -from 2020-01-02" and enter
"""
Y
Y
Y
"""
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should contain "[2020-01-01 08:00] Happy New Year!"
and the journal should not contain "[2020-03-01 08:00] It's just another day in March."
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
and the journal should not contain "[2020-05-02 12:10] Writing tests."
and the journal should have 2 entries
Scenario: --delete flag with -to only deletes entries up to specified date
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete -to 2020-01-02" and enter
"""
Y
Y
"""
Then the journal should not contain "[2019-10-01 08:00] It's just another day in October."
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should contain "[2020-05-01 09:00] Happy May Day!"
and the journal should contain "[2020-05-02 12:10] Writing tests."
and the journal should have 3 entries
Scenario: --delete flag with -starred only deletes starred entries
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete -starred" and enter
"""
Y
"""
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should contain "[2020-01-01 08:00] Happy New Year!"
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should contain "[2020-05-01 09:00] Happy May Day!"
and the journal should not contain "[2020-05-02 12:10] Writing tests. *"
and the journal should have 4 entries
Scenario: --delete flag with -contains only entries containing expression
Given we use the config "deletion_filters.yaml"
When we run "jrnl --delete -contains happy" and enter
"""
Y
Y
"""
Then the journal should contain "[2019-10-01 08:00] It's just another day in October."
and the journal should not contain "[2020-01-01 08:00] Happy New Year!"
and the journal should contain "[2020-03-01 08:00] It's just another day in March."
and the journal should not contain "[2020-05-01 09:00] Happy May Day!"
and the journal should contain "[2020-05-02 12:10] Writing tests. *"
and the journal should have 3 entries

View file

@ -257,6 +257,13 @@ def check_journal_content(context, text, journal_name="default"):
assert text in journal, journal assert text in journal, journal
@then('the journal should not contain "{text}"')
@then('journal "{journal_name}" should not contain "{text}"')
def check_not_journal_content(context, text, journal_name="default"):
journal = read_journal(journal_name)
assert text not in journal, journal
@then('journal "{journal_name}" should not exist') @then('journal "{journal_name}" should not exist')
def journal_doesnt_exist(context, journal_name="default"): def journal_doesnt_exist(context, journal_name="default"):
with open(install.CONFIG_FILE_PATH) as config_file: with open(install.CONFIG_FILE_PATH) as config_file:

View file

@ -234,8 +234,14 @@ class Journal:
self.entries = result self.entries = result
def delete_entries(self, entries_to_delete):
"""Deletes specific entries from a journal."""
for entry in entries_to_delete:
self.entries.remove(entry)
def prompt_delete_entries(self): def prompt_delete_entries(self):
"""Prompts for deletion of entries in a journal.""" """Prompts for deletion of each of the entries in a journal.
Returns the entries the user wishes to delete."""
to_delete = [] to_delete = []
@ -248,8 +254,7 @@ class Journal:
if ask_delete(entry): if ask_delete(entry):
to_delete.append(entry) to_delete.append(entry)
self.entries = [entry for entry in self.entries if entry not in to_delete] return to_delete
self.write()
def new_entry(self, raw, date=None, sort=True): def new_entry(self, raw, date=None, sort=True):
"""Constructs a new entry from some raw text input. """Constructs a new entry from some raw text input.

View file

@ -187,14 +187,12 @@ def parse_args(args=None):
action="store_true", action="store_true",
) )
# Disabling this momentarily due to critical bug exporting.add_argument(
# @see https://github.com/jrnl-org/jrnl/issues/932 "--delete",
# exporting.add_argument( dest="delete",
# "--delete", action="store_true",
# dest="delete", help="Opens an interactive interface for deleting entries.",
# action="store_true", )
# help="Opens an interactive interface for deleting entries.",
# )
# Handle '-123' as a shortcut for '-n 123' # Handle '-123' as a shortcut for '-n 123'
num = re.compile(r"^-(\d+)$") num = re.compile(r"^-(\d+)$")
@ -304,9 +302,6 @@ def configure_logger(debug=False):
def run(manual_args=None): def run(manual_args=None):
args = parse_args(manual_args) args = parse_args(manual_args)
# temporary until bring back --delete
args.delete = False # TODO: remove me
configure_logger(args.debug) configure_logger(args.debug)
if args.version: if args.version:
version_str = f"{jrnl.__title__} version {jrnl.__version__}" version_str = f"{jrnl.__title__} version {jrnl.__version__}"
@ -341,6 +336,7 @@ def run(manual_args=None):
config = util.scope_config(config, journal_name) config = util.scope_config(config, journal_name)
log.debug('Using journal "%s"', journal_name) log.debug('Using journal "%s"', journal_name)
mode_compose, mode_export, mode_import = guess_mode(args, config) mode_compose, mode_export, mode_import = guess_mode(args, config)
# How to quit writing? # How to quit writing?
@ -484,5 +480,16 @@ def run(manual_args=None):
journal.write() journal.write()
elif args.delete: elif args.delete:
journal.prompt_delete_entries() if journal.entries:
entries_to_delete = journal.prompt_delete_entries()
if entries_to_delete:
journal.entries = old_entries
journal.delete_entries(entries_to_delete)
journal.write() journal.write()
else:
print(
"No entries deleted, because the search returned no results.",
file=sys.stderr,
)