Make task news nag configurable and deterministic (#3567)

This patch fixes #3497.
This commit is contained in:
Adrian Sadłocha 2024-07-27 01:30:54 +01:00 committed by GitHub
parent 9dde68f918
commit 9c49863795
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 84 additions and 20 deletions

View file

@ -303,6 +303,7 @@ control specific occasions when output is generated. This list may contain:
label Column labels on tabular reports
new-id Provides feedback on any new task with IDs (and UUIDs for new tasks with ID 0, such as new completed tasks).
new-uuid Provides feedback on any new task with UUIDs. Overrides new-id. Useful for automation.
news Reminds to read new release highlights until the user runs "task news".
affected Reports 'N tasks affected' and similar
edit Used the verbose template for the 'edit' command
special Feedback when applying special tags
@ -327,7 +328,7 @@ Here are the shortcut equivalents:
.nf
verbose=on
verbose=blank,header,footnote,label,new-id,affected,edit,special,project,sync,filter,override,recur
verbose=blank,header,footnote,label,new-id,news,affected,edit,special,project,sync,filter,override,recur
.fi
.nf

View file

@ -93,8 +93,8 @@ std::string configurationDefaults =
"\n"
"# Miscellaneous\n"
"# verbose= # Comma-separated list. May contain any subset of:\n"
"# affected,blank,context,default,edit,filter,footnote,header,label,new-id,new-uuid,override,project,recur,special,sync\n"
"verbose=affected,blank,context,edit,header,footnote,label,new-id,project,special,sync,override,recur\n"
"# affected,blank,context,default,edit,filter,footnote,header,label,new-id,new-uuid,news,override,project,recur,special,sync\n"
"verbose=affected,blank,context,edit,header,footnote,label,new-id,news,project,special,sync,override,recur\n"
"confirmation=1 # Confirmation on delete, big changes\n"
"recurrence=1 # Enable recurrence\n"
"recurrence.confirmation=prompt # Confirmation for propagating changes among recurring tasks (yes/no/prompt)\n"
@ -1050,6 +1050,7 @@ bool Context::verbose (const std::string& token)
v != "label" && //
v != "new-id" && //
v != "new-uuid" && //
v != "news" && //
v != "override" && //
v != "project" && //
v != "recur" && //

View file

@ -26,7 +26,6 @@
#include <cmake.h>
#include <CmdCustom.h>
#include <random>
#include <sstream>
#include <map>
#include <vector>
@ -254,23 +253,16 @@ int CmdCustom::execute (std::string& output)
// Inform user about the new release highlights if not presented yet
Version news_version(Context::getContext ().config.get ("news.version"));
Version current_version = Version::Current();
if (news_version != current_version)
auto should_nag = news_version != current_version && Context::getContext ().verbose ("news");
if (should_nag)
{
std::random_device device;
std::mt19937 random_generator(device());
std::uniform_int_distribution<std::mt19937::result_type> twentyfive_percent(1, 4);
// 25% chance to display the message.
if (twentyfive_percent(random_generator) == 4)
{
std::ostringstream notice;
notice << "Recently upgraded to " << current_version << ". "
"Please run 'task news' to read highlights about the new release.";
if (Context::getContext ().verbose ("footnote"))
Context::getContext ().footnote (notice.str());
else if (Context::getContext ().verbose ("header"))
Context::getContext ().header (notice.str());
}
std::ostringstream notice;
notice << "Recently upgraded to " << current_version << ". "
"Please run 'task news' to read highlights about the new release.";
if (Context::getContext ().verbose ("footnote"))
Context::getContext ().footnote (notice.str());
else if (Context::getContext ().verbose ("header"))
Context::getContext ().header (notice.str());
}
std::string location = (Context::getContext ().data_dir);

View file

@ -138,6 +138,7 @@ set (pythonTests
math.test.py
modify.test.py
nag.test.py
news.test.py
obfuscate.test.py
oldest.test.py
operators.test.py

69
test/news.test.py Executable file
View file

@ -0,0 +1,69 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
###############################################################################
#
# Copyright 2024, Adrian Sadłocha.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# https://www.opensource.org/licenses/mit-license.php
#
###############################################################################
import os
import sys
import unittest
# Ensure python finds the local simpletap module
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from basetest import Task, TestCase
class TestNewsNag(TestCase):
def setUp(self):
self.t = Task()
self.t("add Sample")
def test_news_nag_gets_displayed_with_default_verbosity_levels(self):
"""Default verbosity"""
_, _, err = self.t("")
self.assertIn("Please run 'task news'", err)
def test_news_nag_gets_displayed_when_explicitly_toggled_on(self):
"""Explicitly toggled on"""
# Add `footnote` so there is a sink for the nag message.
_, _, err = self.t("rc.verbose:news,footnote")
self.assertIn("Please run 'task news'", err)
def test_news_nag_does_not_get_displayed_when_explicitly_toggled_off(self):
"""Explicitly toggled off"""
# Add `footnote` so there is a sink for the nag message.
_, _, err = self.t("rc.verbose:footnote")
self.assertNotIn("Please run 'task news'", err)
if __name__ == "__main__":
from simpletap import TAPTestRunner
unittest.main(testRunner=TAPTestRunner())
# vim: ai sts=4 et sw=4 ft=python