Merge branch 'develop' into parallel-tests

This commit is contained in:
Jonathan Wren 2022-06-25 12:52:48 -07:00
commit 8088f4c676
14 changed files with 142 additions and 34 deletions

View file

@ -7,16 +7,25 @@
**Fixed bugs:**
- Adding new entry with date only works with format m.d.Y [\#1509](https://github.com/jrnl-org/jrnl/issues/1509)
- Blank box displays when not making any changes in --edit [\#1501](https://github.com/jrnl-org/jrnl/issues/1501)
- Display message when no edits take place [\#1510](https://github.com/jrnl-org/jrnl/pull/1510) ([apainintheneck](https://github.com/apainintheneck))
**Build:**
- Use tox [\#1361](https://github.com/jrnl-org/jrnl/issues/1361)
- Reduce difference between local and CI environments [\#1518](https://github.com/jrnl-org/jrnl/pull/1518) ([wren](https://github.com/wren))
- Add bdd tests for jrnl installation [\#1513](https://github.com/jrnl-org/jrnl/pull/1513) ([apainintheneck](https://github.com/apainintheneck))
- Stop hardcoding bot info in changelog pipeline [\#1506](https://github.com/jrnl-org/jrnl/pull/1506) ([wren](https://github.com/wren))
- Fix Poetry caching for accessibility tests [\#1505](https://github.com/jrnl-org/jrnl/pull/1505) ([wren](https://github.com/wren))
- Implement Tox for testing [\#1504](https://github.com/jrnl-org/jrnl/pull/1504) ([wren](https://github.com/wren))
- Replace `make` with python alternative \(`poe`\) [\#1503](https://github.com/jrnl-org/jrnl/pull/1503) ([wren](https://github.com/wren))
- Update copyright year [\#1502](https://github.com/jrnl-org/jrnl/pull/1502) ([wren](https://github.com/wren))
**Packaging:**
- Bump cryptography from 37.0.2 to 37.0.3 [\#1516](https://github.com/jrnl-org/jrnl/pull/1516) ([dependabot[bot]](https://github.com/apps/dependabot))
- Bump poethepoet from 0.13.1 to 0.14.0 [\#1514](https://github.com/jrnl-org/jrnl/pull/1514) ([dependabot[bot]](https://github.com/apps/dependabot))
## [v3.0-beta](https://pypi.org/project/jrnl/v3.0-beta/) (2022-06-11)
[Full Changelog](https://github.com/jrnl-org/jrnl/compare/v2.8.4...v3.0-beta)

View file

@ -59,7 +59,7 @@ representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by [emailing the maintainers](mailto:jrnl-sh@googlegroups.com).
reported by [emailing the maintainers](mailto:maintainers@jrnl.sh).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View file

@ -1,6 +1,6 @@
# Security
If you've discovered a potential security issue in jrnl, please contact the maintainers at [jrnl-sh@googlegroups.com](mailto:jrnl-sh@googlegroups.com).
If you've discovered a potential security issue in jrnl, please contact the maintainers at [maintainers@jrnl.sh](mailto:maintainers@jrnl.sh).
You can also feel free to [open an issue](https://github.com/jrnl-org/jrnl/issues/new/choose) (but please don't disclose the vulnerability) in case the email goes to spam.

View file

@ -46,7 +46,7 @@ def get_text_from_editor(config, template=""):
os.remove(tmpfile)
if not raw:
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.ERROR))
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.NORMAL))
return raw

View file

@ -141,7 +141,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, MsgStyle.ERROR))
raise JrnlException(Message(MsgText.NoTextReceived, MsgStyle.NORMAL))
logging.debug(
'Write mode: appending raw text to journal "%s": %s', args.journal_name, raw
@ -342,6 +342,9 @@ def _print_edited_summary(journal, old_stats, **kwargs):
)
msgs.append(Message(my_msg, MsgStyle.NORMAL, {"num": stats["modified"]}))
if not msgs:
msgs.append(Message(MsgText.NoEditsReceived, MsgStyle.NORMAL))
print_msgs(msgs)

View file

@ -149,6 +149,8 @@ class MsgText(Enum):
https://jrnl.sh/en/stable/external-editors/
"""
NoEditsReceived = "No edits to save, because nothing was changed"
NoTextReceived = """
No entry to save, because no text was received
"""

54
poetry.lock generated
View file

@ -137,7 +137,7 @@ test = ["flake8 (==3.7.8)", "hypothesis (==3.55.3)"]
[[package]]
name = "cryptography"
version = "37.0.2"
version = "37.0.3"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
category = "main"
optional = false
@ -579,11 +579,11 @@ testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "poethepoet"
version = "0.13.1"
version = "0.14.0"
description = "A task runner that works well with poetry."
category = "dev"
optional = false
python-versions = ">=3.6.2"
python-versions = ">=3.7"
[package.dependencies]
pastel = ">=0.2.1,<0.3.0"
@ -1175,28 +1175,28 @@ commonmark = [
{file = "commonmark-0.9.1.tar.gz", hash = "sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60"},
]
cryptography = [
{file = "cryptography-37.0.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:ef15c2df7656763b4ff20a9bc4381d8352e6640cfeb95c2972c38ef508e75181"},
{file = "cryptography-37.0.2-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:3c81599befb4d4f3d7648ed3217e00d21a9341a9a688ecdd615ff72ffbed7336"},
{file = "cryptography-37.0.2-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2bd1096476aaac820426239ab534b636c77d71af66c547b9ddcd76eb9c79e004"},
{file = "cryptography-37.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:31fe38d14d2e5f787e0aecef831457da6cec68e0bb09a35835b0b44ae8b988fe"},
{file = "cryptography-37.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:093cb351031656d3ee2f4fa1be579a8c69c754cf874206be1d4cf3b542042804"},
{file = "cryptography-37.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59b281eab51e1b6b6afa525af2bd93c16d49358404f814fe2c2410058623928c"},
{file = "cryptography-37.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:0cc20f655157d4cfc7bada909dc5cc228211b075ba8407c46467f63597c78178"},
{file = "cryptography-37.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f8ec91983e638a9bcd75b39f1396e5c0dc2330cbd9ce4accefe68717e6779e0a"},
{file = "cryptography-37.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:46f4c544f6557a2fefa7ac8ac7d1b17bf9b647bd20b16decc8fbcab7117fbc15"},
{file = "cryptography-37.0.2-cp36-abi3-win32.whl", hash = "sha256:731c8abd27693323b348518ed0e0705713a36d79fdbd969ad968fbef0979a7e0"},
{file = "cryptography-37.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:471e0d70201c069f74c837983189949aa0d24bb2d751b57e26e3761f2f782b8d"},
{file = "cryptography-37.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a68254dd88021f24a68b613d8c51d5c5e74d735878b9e32cc0adf19d1f10aaf9"},
{file = "cryptography-37.0.2-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:a7d5137e556cc0ea418dca6186deabe9129cee318618eb1ffecbd35bee55ddc1"},
{file = "cryptography-37.0.2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aeaba7b5e756ea52c8861c133c596afe93dd716cbcacae23b80bc238202dc023"},
{file = "cryptography-37.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95e590dd70642eb2079d280420a888190aa040ad20f19ec8c6e097e38aa29e06"},
{file = "cryptography-37.0.2-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1b9362d34363f2c71b7853f6251219298124aa4cc2075ae2932e64c91a3e2717"},
{file = "cryptography-37.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e53258e69874a306fcecb88b7534d61820db8a98655662a3dd2ec7f1afd9132f"},
{file = "cryptography-37.0.2-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:1f3bfbd611db5cb58ca82f3deb35e83af34bb8cf06043fa61500157d50a70982"},
{file = "cryptography-37.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:419c57d7b63f5ec38b1199a9521d77d7d1754eb97827bbb773162073ccd8c8d4"},
{file = "cryptography-37.0.2-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:dc26bb134452081859aa21d4990474ddb7e863aa39e60d1592800a8865a702de"},
{file = "cryptography-37.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b8398b3d0efc420e777c40c16764d6870bcef2eb383df9c6dbb9ffe12c64452"},
{file = "cryptography-37.0.2.tar.gz", hash = "sha256:f224ad253cc9cea7568f49077007d2263efa57396a2f2f78114066fd54b5c68e"},
{file = "cryptography-37.0.3-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:d10413d493e98075060d3e62e5826de372912ea653ccc948f3c41b21ddca087f"},
{file = "cryptography-37.0.3-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:cd64147ff16506632893ceb2569624b48c84daa3ba4d89695f7c7bc24188eee9"},
{file = "cryptography-37.0.3-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:17c74f7d9e9e9bb7e84521243695c1b4bdc3a0e44ca764e6bcf8f05f3de3d0df"},
{file = "cryptography-37.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:0713bee6c8077786c56bdec9c5d3f099d40d2c862ff3200416f6862e9dd63156"},
{file = "cryptography-37.0.3-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9c2008417741cdfbe945ef2d16b7b7ba0790886a0b49e1de533acf93eb66ed6"},
{file = "cryptography-37.0.3-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:646905ff7a712e415bf0d0f214e0eb669dd2257c4d7a27db1e8baec5d2a1d55f"},
{file = "cryptography-37.0.3-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:dcafadb5a06cb7a6bb49fb4c1de7414ee2f8c8e12b047606d97c3175d690f582"},
{file = "cryptography-37.0.3-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0b4bfc5ccfe4e5c7de535670680398fed4a0bbc5dfd52b3a295baad42230abdf"},
{file = "cryptography-37.0.3-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a03dbc0d8ce8c1146c177cd0e3a66ea106f36733fb1b997ea4d051f8a68539ff"},
{file = "cryptography-37.0.3-cp36-abi3-win32.whl", hash = "sha256:190a24c14e91c1fa3101069aac7e77d11c5a73911c3904128367f52946bbb6fd"},
{file = "cryptography-37.0.3-cp36-abi3-win_amd64.whl", hash = "sha256:b05c5478524deb7a019e240f2a970040c4b0f01f58f0425e6262c96b126c6a3e"},
{file = "cryptography-37.0.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891ed8312840fd43e0696468a6520a582a033c0109f7b14b96067bfe1123226b"},
{file = "cryptography-37.0.3-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:30d6aabf623a01affc7c0824936c3dde6590076b61f5dd299df3cc2c75fc5915"},
{file = "cryptography-37.0.3-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:31a7c1f1c2551f013d4294d06e22848e2ccd77825f0987cba3239df6ebf7b020"},
{file = "cryptography-37.0.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a94fd1ff80001cb97add71d07f596d8b865b716f25ef501183e0e199390e50d3"},
{file = "cryptography-37.0.3-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:8a85dbcc770256918b40c2f40bd3ffd3b2ae45b0cf19068b561db8f8d61bf492"},
{file = "cryptography-37.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:773d5b5f2e2bd2c7cbb1bd24902ad41283c88b9dd463a0f82adc9a2870d9d066"},
{file = "cryptography-37.0.3-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0f9193428a55a4347af2d4fd8141a2002dedbcc26487e67fd2ae19f977ee8afc"},
{file = "cryptography-37.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bf652c73e8f7c32a3f92f7184bf7f9106dacdf5ef59c3c3683d7dae2c4972fb"},
{file = "cryptography-37.0.3-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:c3c8b1ad2c266fdf7adc041cc4156d6a3d14db93de2f81b26a5af97ef3f209e5"},
{file = "cryptography-37.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2383d6c3088e863304c37c65cd2ea404b7fbb4886823eab1d74137cc27f3d2ee"},
{file = "cryptography-37.0.3.tar.gz", hash = "sha256:ae430d51c67ac638dfbb42edf56c669ca9c74744f4d225ad11c6f3d355858187"},
]
decorator = [
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
@ -1374,8 +1374,8 @@ pluggy = [
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
]
poethepoet = [
{file = "poethepoet-0.13.1-py3-none-any.whl", hash = "sha256:47e7b38c8b5412f840447f7612a9330697e8633e7500a7340b6734f50e26e380"},
{file = "poethepoet-0.13.1.tar.gz", hash = "sha256:4f6962f17f5d5a453fd7fa66e3e7897e9191d4289148433efe441c81f2451a46"},
{file = "poethepoet-0.14.0-py3-none-any.whl", hash = "sha256:e274988b469306c11b634b1c6b1cf1ffc880353afbcff874540090c3c9c50c2c"},
{file = "poethepoet-0.14.0.tar.gz", hash = "sha256:1557f324e3ad791d86f515d4138dbfd97ac71c6ff3ec2d308f4d792e3002d1f0"},
]
pprintpp = [
{file = "pprintpp-0.4.0-py2.py3-none-any.whl", hash = "sha256:b6b4dcdd0c0c0d75e4d7b2f21a9e933e5b2ce62b26e1a54537f9651ae5a5c01d"},

View file

@ -3,13 +3,13 @@ name = "jrnl"
version = "v3.0-beta"
description = "Collect your thoughts and notes without leaving the command line."
authors = [
"jrnl contributors <jrnl-sh@googlegroups.com>",
"jrnl contributors <maintainers@jrnl.sh>",
"Manuel Ebert <manuel@1450.me>",
"Jonathan Wren <jonathan@nowandwren.com>",
"Micah Ellison <micahellison@gmail.com>"
]
maintainers = [
"Jonathan Wren and Micah Ellison <jrnl-sh@googlegroups.com>",
"Jonathan Wren and Micah Ellison <maintainers@jrnl.sh>",
]
license = "GPL-3.0-only"
readme = "README.md"

View file

@ -0,0 +1,45 @@
Feature: Installing jrnl
Scenario: Install jrnl with default options
Given we use no config
When we run "jrnl hello world" and enter
\n
\n
Then the output should contain "Journal 'default' created"
And the default journal "journal.txt" should be in the "." directory
And the config should contain "encrypt: false"
And the version in the config file should be up-to-date
Scenario: Install jrnl with custom relative default journal path
Given we use no config
When we run "jrnl hello world" and enter
default/custom.txt
n
Then the output should contain "Journal 'default' created"
And the default journal "custom.txt" should be in the "default" directory
And the config should contain "encrypt: false"
And the version in the config file should be up-to-date
Scenario: Install jrnl with custom expanded default journal path
Given we use no config
And the home directory is called "home"
When we run "jrnl hello world" and enter
~/custom.txt
n
Then the output should contain "Journal 'default' created"
And the default journal "custom.txt" should be in the "home" directory
And the config should contain "encrypt: false"
And the version in the config file should be up-to-date
Scenario: Install jrnl with encrypted default journal
Given we use no config
When we run "jrnl hello world" and enter
encrypted.txt
y
Then the output should contain "Journal will be encrypted"
And the default journal "encrypted.txt" should be in the "." directory
And the config should contain "encrypt: true"
And the version in the config file should be up-to-date
When we run "jrnl"
Then we should be prompted for a password

View file

@ -13,6 +13,7 @@ scenarios("features/encrypt.feature")
scenarios("features/file_storage.feature")
scenarios("features/format.feature")
scenarios("features/import.feature")
scenarios("features/install.feature")
scenarios("features/multiple_journals.feature")
scenarios("features/override.feature")
scenarios("features/password.feature")

View file

@ -88,6 +88,7 @@ def cli_run(
mock_editor,
mock_user_input,
mock_overrides,
mock_default_journal_path,
):
# Check if we need more mocks
mock_factories.update(mock_args)
@ -96,6 +97,7 @@ def cli_run(
mock_factories.update(mock_editor)
mock_factories.update(mock_config_path)
mock_factories.update(mock_user_input)
mock_factories.update(mock_default_journal_path)
return {
"status": 0,
@ -164,6 +166,19 @@ def mock_config_path(request):
}
@fixture
def mock_default_journal_path(temp_dir):
journal_path = os.path.join(temp_dir.name, "journal.txt")
return {
"default_journal_path_install": lambda: patch(
"jrnl.install.get_default_journal_path", return_value=journal_path
),
"default_journal_path_config": lambda: patch(
"jrnl.config.get_default_journal_path", return_value=journal_path
),
}
@fixture
def temp_dir():
return tempfile.TemporaryDirectory()
@ -216,7 +231,9 @@ def mock_user_input(request, password_input, stdin_input):
return password_input
if isinstance(user_input, Iterable):
return next(user_input)
input_line = next(user_input)
# A raw newline is used to indicate deliberate empty input
return "" if input_line == r"\n" else input_line
# exceptions
return user_input if not kwargs["password"] else password_input

View file

@ -147,3 +147,10 @@ def parse_output_as_language(cli_run, language_name):
assert False, f"Language name {language_name} not recognized"
return {"lang": language_name, "obj": parsed_output}
@given(parse('the home directory is called "{home_dir}"'))
def home_directory(temp_dir, home_dir, monkeypatch):
home_path = os.path.join(temp_dir.name, home_dir)
monkeypatch.setenv("USERPROFILE", home_path) # for windows
monkeypatch.setenv("HOME", home_path) # for *nix

View file

@ -97,6 +97,12 @@ def output_should_contain_version(cli_run, toml_version):
assert toml_version in out, toml_version
@then("the version in the config file should be up-to-date")
def config_file_version(config_on_disk, toml_version):
config_version = config_on_disk["version"]
assert config_version == toml_version
@then(parse("the output should be {width:d} columns wide"))
def output_should_be_columns_wide(cli_run, width):
out = cli_run["stdout"]
@ -105,6 +111,22 @@ def output_should_be_columns_wide(cli_run, width):
assert len(line) <= width
@then(
parse(
'the default journal "{journal_file}" should be in the "{journal_dir}" directory'
)
)
def default_journal_location(journal_file, journal_dir, config_on_disk, temp_dir):
default_journal_path = config_on_disk["journals"]["default"]
expected_journal_path = (
os.path.join(temp_dir.name, journal_file)
if journal_dir == "."
else os.path.join(temp_dir.name, journal_dir, journal_file)
)
# Use os.path.samefile here because both paths might not be fully expanded.
assert os.path.samefile(default_journal_path, expected_journal_path)
@then(
parse(
'the config for journal "{journal_name}" {should_or_should_not} contain "{some_yaml}"'

View file

@ -23,6 +23,8 @@ def when_we_change_directory(directory_name):
command = '(?P<command>[^"]*)'
input_method = "(?P<input_method>enter|pipe|type)"
all_input = '("(?P<all_input>[^"]*)")'
# Note: A line with only a raw newline r'\n' is treated as
# an empty line of input internally for testing purposes.
@when(parse('we run "jrnl {command}" and {input_method}\n{all_input}'))