mirror of
https://github.com/jrnl-org/jrnl.git
synced 2025-05-17 11:38:32 +02:00
merge in develop
This commit is contained in:
commit
15b86cae97
30 changed files with 827 additions and 222 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -6,15 +6,27 @@
|
||||||
|
|
||||||
**Implemented enhancements:**
|
**Implemented enhancements:**
|
||||||
|
|
||||||
|
- Add --change-time command to change the timestamp of an entry [\#1429](https://github.com/jrnl-org/jrnl/issues/1429)
|
||||||
|
- Show name of journal when creating a password/encrypting [\#1478](https://github.com/jrnl-org/jrnl/pull/1478) ([jonakeys](https://github.com/jonakeys))
|
||||||
|
- Implement --change-time flag [\#1452](https://github.com/jrnl-org/jrnl/pull/1452) ([richardjs](https://github.com/richardjs))
|
||||||
- Reformat additional messages and finish centralizing exception handling [\#1424](https://github.com/jrnl-org/jrnl/pull/1424) ([wren](https://github.com/wren))
|
- Reformat additional messages and finish centralizing exception handling [\#1424](https://github.com/jrnl-org/jrnl/pull/1424) ([wren](https://github.com/wren))
|
||||||
- Reformat messages and add new centralized exception handling [\#1417](https://github.com/jrnl-org/jrnl/pull/1417) ([wren](https://github.com/wren))
|
- Reformat messages and add new centralized exception handling [\#1417](https://github.com/jrnl-org/jrnl/pull/1417) ([wren](https://github.com/wren))
|
||||||
|
|
||||||
**Fixed bugs:**
|
**Fixed bugs:**
|
||||||
|
|
||||||
|
- Using -not argument by itself leads to new entry creation [\#1472](https://github.com/jrnl-org/jrnl/issues/1472)
|
||||||
- Empty config file leads to confusing error message [\#1420](https://github.com/jrnl-org/jrnl/issues/1420)
|
- Empty config file leads to confusing error message [\#1420](https://github.com/jrnl-org/jrnl/issues/1420)
|
||||||
- "Entry not saved" text doesn't appear in default stdin editor [\#1419](https://github.com/jrnl-org/jrnl/issues/1419)
|
- "Entry not saved" text doesn't appear in default stdin editor [\#1419](https://github.com/jrnl-org/jrnl/issues/1419)
|
||||||
|
- jrnl --encrypt doesn't prompt me for password change [\#1358](https://github.com/jrnl-org/jrnl/issues/1358)
|
||||||
- '-not -contains x' raises an AttributeError exception [\#1350](https://github.com/jrnl-org/jrnl/issues/1350)
|
- '-not -contains x' raises an AttributeError exception [\#1350](https://github.com/jrnl-org/jrnl/issues/1350)
|
||||||
- Directory YAML export shows stack trace when it doesn't need to [\#1227](https://github.com/jrnl-org/jrnl/issues/1227)
|
- Exception when providing folder name of folder that does not exist as journal path [\#1293](https://github.com/jrnl-org/jrnl/issues/1293)
|
||||||
|
- display\_format: pretty and display\_format: short lead to crash [\#1263](https://github.com/jrnl-org/jrnl/issues/1263)
|
||||||
|
- Fixed error related to display\_format in config file for some values [\#1495](https://github.com/jrnl-org/jrnl/pull/1495) ([apainintheneck](https://github.com/apainintheneck))
|
||||||
|
- Create folder if config ends with \(back\)slash [\#1492](https://github.com/jrnl-org/jrnl/pull/1492) ([jonakeys](https://github.com/jonakeys))
|
||||||
|
- `-not` search parameter no longer opens editor [\#1490](https://github.com/jrnl-org/jrnl/pull/1490) ([apainintheneck](https://github.com/apainintheneck))
|
||||||
|
- Fix TypeError when using debug flag [\#1484](https://github.com/jrnl-org/jrnl/pull/1484) ([jonakeys](https://github.com/jonakeys))
|
||||||
|
- Prompt for password change when using 'jrnl --encrypt' on already encrypted journal [\#1477](https://github.com/jrnl-org/jrnl/pull/1477) ([jonakeys](https://github.com/jonakeys))
|
||||||
|
- Always expand all paths \(journals, templates, etc\) [\#1468](https://github.com/jrnl-org/jrnl/pull/1468) ([apainintheneck](https://github.com/apainintheneck))
|
||||||
- The `-not` option with no arguments now outputs error instead of stack trace [\#1466](https://github.com/jrnl-org/jrnl/pull/1466) ([apainintheneck](https://github.com/apainintheneck))
|
- The `-not` option with no arguments now outputs error instead of stack trace [\#1466](https://github.com/jrnl-org/jrnl/pull/1466) ([apainintheneck](https://github.com/apainintheneck))
|
||||||
- Give a proper message when trying to use an empty config file [\#1461](https://github.com/jrnl-org/jrnl/pull/1461) ([jonakeys](https://github.com/jonakeys))
|
- Give a proper message when trying to use an empty config file [\#1461](https://github.com/jrnl-org/jrnl/pull/1461) ([jonakeys](https://github.com/jonakeys))
|
||||||
- Display "No entry to save, because no text was received" after empty entry on cmdline [\#1459](https://github.com/jrnl-org/jrnl/pull/1459) ([apainintheneck](https://github.com/apainintheneck))
|
- Display "No entry to save, because no text was received" after empty entry on cmdline [\#1459](https://github.com/jrnl-org/jrnl/pull/1459) ([apainintheneck](https://github.com/apainintheneck))
|
||||||
|
@ -23,17 +35,22 @@
|
||||||
**Deprecated:**
|
**Deprecated:**
|
||||||
|
|
||||||
- Remove "sample" format and its asteval dependency [\#1435](https://github.com/jrnl-org/jrnl/issues/1435)
|
- Remove "sample" format and its asteval dependency [\#1435](https://github.com/jrnl-org/jrnl/issues/1435)
|
||||||
|
- Drop support for Python 3.7 and 3.8 [\#1412](https://github.com/jrnl-org/jrnl/pull/1412) ([micahellison](https://github.com/micahellison))
|
||||||
|
|
||||||
**Build:**
|
**Build:**
|
||||||
|
|
||||||
- Clean up .gitignore [\#1286](https://github.com/jrnl-org/jrnl/issues/1286)
|
- Clean up .gitignore [\#1286](https://github.com/jrnl-org/jrnl/issues/1286)
|
||||||
- Pin jinja2 in docs requirements to keep readthedocs builds from failing [\#1439](https://github.com/jrnl-org/jrnl/pull/1439) ([micahellison](https://github.com/micahellison))
|
- Pin jinja2 in docs requirements to keep readthedocs builds from failing [\#1439](https://github.com/jrnl-org/jrnl/pull/1439) ([micahellison](https://github.com/micahellison))
|
||||||
- Tidy up git ignore [\#1414](https://github.com/jrnl-org/jrnl/pull/1414) ([nelnog](https://github.com/nelnog))
|
- Tidy up git ignore [\#1414](https://github.com/jrnl-org/jrnl/pull/1414) ([nelnog](https://github.com/nelnog))
|
||||||
- Drop support for Python 3.7 and 3.8 [\#1412](https://github.com/jrnl-org/jrnl/pull/1412) ([micahellison](https://github.com/micahellison))
|
|
||||||
|
**Documentation:**
|
||||||
|
|
||||||
|
- Document --change-time in web-based docs' command line reference [\#1471](https://github.com/jrnl-org/jrnl/pull/1471) ([micahellison](https://github.com/micahellison))
|
||||||
|
|
||||||
**Packaging:**
|
**Packaging:**
|
||||||
|
|
||||||
- Sync jrnl's Python version support more closely to Python release cycle [\#1406](https://github.com/jrnl-org/jrnl/issues/1406)
|
- Sync jrnl's Python version support more closely to Python release cycle [\#1406](https://github.com/jrnl-org/jrnl/issues/1406)
|
||||||
|
- Bump keyring from 23.5.0 to 23.5.1 [\#1487](https://github.com/jrnl-org/jrnl/pull/1487) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||||
- Bump cryptography from 37.0.1 to 37.0.2 [\#1467](https://github.com/jrnl-org/jrnl/pull/1467) ([dependabot[bot]](https://github.com/apps/dependabot))
|
- Bump cryptography from 37.0.1 to 37.0.2 [\#1467](https://github.com/jrnl-org/jrnl/pull/1467) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||||
- Bump cryptography from 36.0.2 to 37.0.1 [\#1462](https://github.com/jrnl-org/jrnl/pull/1462) ([dependabot[bot]](https://github.com/apps/dependabot))
|
- Bump cryptography from 36.0.2 to 37.0.1 [\#1462](https://github.com/jrnl-org/jrnl/pull/1462) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||||
- Bump pytest from 7.1.1 to 7.1.2 [\#1458](https://github.com/jrnl-org/jrnl/pull/1458) ([dependabot[bot]](https://github.com/apps/dependabot))
|
- Bump pytest from 7.1.1 to 7.1.2 [\#1458](https://github.com/jrnl-org/jrnl/pull/1458) ([dependabot[bot]](https://github.com/apps/dependabot))
|
||||||
|
|
|
@ -28,9 +28,10 @@ you have an entry on May 5th, 2021 in a folder journal at `~/folderjournal`, it
|
||||||
be located in: `~/folderjournal/2021/05/05.txt`
|
be located in: `~/folderjournal/2021/05/05.txt`
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
When creating a new folder journal, you will need to create the folder before running
|
Creating a new folder journal can be done in two ways:
|
||||||
`jrnl`. Otherwise, when you run `jrnl` for the first time, it will assume that you
|
|
||||||
are creating a single file journal instead, and it will create a file at that path.
|
* Create a folder with the name of the journal before running `jrnl`. Otherwise, when you run `jrnl` for the first time, it will assume that you are creating a single file journal instead, and it will create a file at that path.
|
||||||
|
* Create a new journal in your [config_file](advanced.md) and end the path with a ``/`` (on a POSIX system like Linux or MacOSX) or a ``\`` (on a Windows system). The folder will be created automatically if it doesn't exist.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Folder journals can't be encrypted.
|
Folder journals can't be encrypted.
|
||||||
|
|
|
@ -90,6 +90,11 @@ the temporary file you were editing and makes the changes to your journal.
|
||||||
Interactively deletes selected entries. You'll be asked to confirm deletion of
|
Interactively deletes selected entries. You'll be asked to confirm deletion of
|
||||||
each entry.
|
each entry.
|
||||||
|
|
||||||
|
### --change-time DATE
|
||||||
|
Interactively changes the time of the selected entries to the date specified,
|
||||||
|
or to right now if no date is specified. You'll be asked to confirm each entry,
|
||||||
|
unless you are using this with `--edit` on a single entry.
|
||||||
|
|
||||||
### --format TYPE
|
### --format TYPE
|
||||||
Display selected entries in an alternate format. See [formats](formats.md).
|
Display selected entries in an alternate format. See [formats](formats.md).
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
mkdocs==1.2.3
|
mkdocs>=1.0,<1.3
|
||||||
jinja2==3.0.3 # https://github.com/readthedocs/readthedocs.org/issues/9037
|
jinja2==3.0.3 # https://github.com/readthedocs/readthedocs.org/issues/9037
|
||||||
|
|
|
@ -8,6 +8,7 @@ import fnmatch
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from . import Journal
|
from . import Journal
|
||||||
|
from . import time
|
||||||
|
|
||||||
|
|
||||||
def get_files(journal_config):
|
def get_files(journal_config):
|
||||||
|
@ -88,6 +89,17 @@ class Folder(Journal.Journal):
|
||||||
self.entries.remove(entry)
|
self.entries.remove(entry)
|
||||||
self._diff_entry_dates.append(entry.date)
|
self._diff_entry_dates.append(entry.date)
|
||||||
|
|
||||||
|
def change_date_entries(self, date):
|
||||||
|
"""Changes entry dates to given date."""
|
||||||
|
|
||||||
|
date = time.parse(date)
|
||||||
|
|
||||||
|
self._diff_entry_dates.append(date)
|
||||||
|
|
||||||
|
for entry in self.entries:
|
||||||
|
self._diff_entry_dates.append(entry.date)
|
||||||
|
entry.date = date
|
||||||
|
|
||||||
def parse_editable_str(self, edited):
|
def parse_editable_str(self, edited):
|
||||||
"""Parses the output of self.editable_str and updates its entries."""
|
"""Parses the output of self.editable_str and updates its entries."""
|
||||||
mod_entries = self._parse(edited)
|
mod_entries = self._parse(edited)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import re
|
||||||
from . import Entry
|
from . import Entry
|
||||||
from . import time
|
from . import time
|
||||||
from .prompt import yesno
|
from .prompt import yesno
|
||||||
|
from .path import expand_path
|
||||||
|
|
||||||
from jrnl.output import print_msg
|
from jrnl.output import print_msg
|
||||||
from jrnl.messages import Message
|
from jrnl.messages import Message
|
||||||
|
@ -280,13 +281,19 @@ class Journal:
|
||||||
for entry in entries_to_delete:
|
for entry in entries_to_delete:
|
||||||
self.entries.remove(entry)
|
self.entries.remove(entry)
|
||||||
|
|
||||||
def prompt_delete_entries(self):
|
def change_date_entries(self, date):
|
||||||
"""Prompts for deletion of each of the entries in a journal.
|
"""Changes entry dates to given date."""
|
||||||
Returns the entries the user wishes to delete."""
|
date = time.parse(date)
|
||||||
|
|
||||||
to_delete = []
|
for entry in self.entries:
|
||||||
|
entry.date = date
|
||||||
|
|
||||||
def ask_delete(entry):
|
def prompt_action_entries(self, message):
|
||||||
|
"""Prompts for action for each entry in a journal, using given message.
|
||||||
|
Returns the entries the user wishes to apply the action on."""
|
||||||
|
to_act = []
|
||||||
|
|
||||||
|
def ask_action(entry):
|
||||||
return yesno(
|
return yesno(
|
||||||
Message(
|
Message(
|
||||||
MsgText.DeleteEntryQuestion,
|
MsgText.DeleteEntryQuestion,
|
||||||
|
@ -296,10 +303,10 @@ class Journal:
|
||||||
)
|
)
|
||||||
|
|
||||||
for entry in self.entries:
|
for entry in self.entries:
|
||||||
if ask_delete(entry):
|
if ask_action(entry):
|
||||||
to_delete.append(entry)
|
to_act.append(entry)
|
||||||
|
|
||||||
return to_delete
|
return to_act
|
||||||
|
|
||||||
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.
|
||||||
|
@ -426,7 +433,7 @@ def open_journal(journal_name, config, legacy=False):
|
||||||
backwards compatibility with jrnl 1.x
|
backwards compatibility with jrnl 1.x
|
||||||
"""
|
"""
|
||||||
config = config.copy()
|
config = config.copy()
|
||||||
config["journal"] = os.path.expanduser(os.path.expandvars(config["journal"]))
|
config["journal"] = expand_path(config["journal"])
|
||||||
|
|
||||||
if os.path.isdir(config["journal"]):
|
if os.path.isdir(config["journal"]):
|
||||||
if config["encrypt"]:
|
if config["encrypt"]:
|
||||||
|
@ -454,6 +461,10 @@ def open_journal(journal_name, config, legacy=False):
|
||||||
if not config["encrypt"]:
|
if not config["encrypt"]:
|
||||||
if legacy:
|
if legacy:
|
||||||
return LegacyJournal(journal_name, **config).open()
|
return LegacyJournal(journal_name, **config).open()
|
||||||
|
if config["journal"].endswith(os.sep):
|
||||||
|
from . import FolderJournal
|
||||||
|
|
||||||
|
return FolderJournal.Folder(journal_name, **config).open()
|
||||||
return PlainJournal(journal_name, **config).open()
|
return PlainJournal(journal_name, **config).open()
|
||||||
|
|
||||||
from . import EncryptedJournal
|
from . import EncryptedJournal
|
||||||
|
|
|
@ -267,6 +267,14 @@ def parse_args(args=[]):
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Interactively deletes selected entries",
|
help="Interactively deletes selected entries",
|
||||||
)
|
)
|
||||||
|
exporting.add_argument(
|
||||||
|
"--change-time",
|
||||||
|
dest="change_time",
|
||||||
|
nargs="?",
|
||||||
|
metavar="DATE",
|
||||||
|
const="now",
|
||||||
|
help="Change timestamp for seleted entries (default: now)",
|
||||||
|
)
|
||||||
exporting.add_argument(
|
exporting.add_argument(
|
||||||
"--format",
|
"--format",
|
||||||
metavar="TYPE",
|
metavar="TYPE",
|
||||||
|
|
|
@ -19,6 +19,7 @@ from jrnl.exception import JrnlException
|
||||||
from jrnl.messages import Message
|
from jrnl.messages import Message
|
||||||
from jrnl.messages import MsgText
|
from jrnl.messages import MsgText
|
||||||
from jrnl.messages import MsgStyle
|
from jrnl.messages import MsgStyle
|
||||||
|
from jrnl.prompt import create_password
|
||||||
|
|
||||||
|
|
||||||
def preconfig_diagnostic(_):
|
def preconfig_diagnostic(_):
|
||||||
|
@ -86,9 +87,14 @@ def postconfig_encrypt(args, config, original_config, **kwargs):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
journal.config["encrypt"] = True
|
|
||||||
|
|
||||||
new_journal = EncryptedJournal.from_journal(journal)
|
new_journal = EncryptedJournal.from_journal(journal)
|
||||||
|
|
||||||
|
# If journal is encrypted, create new password
|
||||||
|
if journal.config["encrypt"] is True:
|
||||||
|
print(f"Journal {journal.name} is already encrypted. Create a new password.")
|
||||||
|
new_journal.password = create_password(new_journal.name)
|
||||||
|
|
||||||
|
journal.config["encrypt"] = True
|
||||||
new_journal.write(args.filename)
|
new_journal.write(args.filename)
|
||||||
|
|
||||||
print_msg(
|
print_msg(
|
||||||
|
|
|
@ -13,6 +13,7 @@ from jrnl.messages import Message
|
||||||
from jrnl.messages import MsgText
|
from jrnl.messages import MsgText
|
||||||
from jrnl.messages import MsgStyle
|
from jrnl.messages import MsgStyle
|
||||||
|
|
||||||
|
from .path import home_dir
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
DEFAULT_CONFIG_NAME = "jrnl.yaml"
|
DEFAULT_CONFIG_NAME = "jrnl.yaml"
|
||||||
|
@ -81,9 +82,7 @@ def get_config_path():
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return os.path.join(
|
return os.path.join(config_directory_path or home_dir(), DEFAULT_CONFIG_NAME)
|
||||||
config_directory_path or os.path.expanduser("~"), DEFAULT_CONFIG_NAME
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_config():
|
def get_default_config():
|
||||||
|
@ -110,9 +109,7 @@ def get_default_config():
|
||||||
|
|
||||||
|
|
||||||
def get_default_journal_path():
|
def get_default_journal_path():
|
||||||
journal_data_path = xdg.BaseDirectory.save_data_path(
|
journal_data_path = xdg.BaseDirectory.save_data_path(XDG_RESOURCE) or home_dir()
|
||||||
XDG_RESOURCE
|
|
||||||
) or os.path.expanduser("~")
|
|
||||||
return os.path.join(journal_data_path, DEFAULT_JOURNAL_NAME)
|
return os.path.join(journal_data_path, DEFAULT_JOURNAL_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,9 @@ import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from .path import home_dir
|
||||||
|
from .path import absolute_path
|
||||||
|
from .path import expand_path
|
||||||
from .config import DEFAULT_JOURNAL_KEY
|
from .config import DEFAULT_JOURNAL_KEY
|
||||||
from .config import get_config_path
|
from .config import get_config_path
|
||||||
from .config import get_default_config
|
from .config import get_default_config
|
||||||
|
@ -47,7 +50,7 @@ def find_default_config():
|
||||||
config_path = (
|
config_path = (
|
||||||
get_config_path()
|
get_config_path()
|
||||||
if os.path.exists(get_config_path())
|
if os.path.exists(get_config_path())
|
||||||
else os.path.join(os.path.expanduser("~"), ".jrnl_config")
|
else os.path.join(home_dir(), ".jrnl_config")
|
||||||
)
|
)
|
||||||
return config_path
|
return config_path
|
||||||
|
|
||||||
|
@ -119,12 +122,9 @@ def install():
|
||||||
),
|
),
|
||||||
get_input=True,
|
get_input=True,
|
||||||
)
|
)
|
||||||
journal_path = os.path.abspath(user_given_path or default_journal_path)
|
journal_path = absolute_path(user_given_path or default_journal_path)
|
||||||
|
|
||||||
default_config = get_default_config()
|
default_config = get_default_config()
|
||||||
default_config["journals"][DEFAULT_JOURNAL_KEY] = os.path.expanduser(
|
default_config["journals"][DEFAULT_JOURNAL_KEY] = journal_path
|
||||||
os.path.expandvars(journal_path)
|
|
||||||
)
|
|
||||||
|
|
||||||
# If the folder doesn't exist, create it
|
# If the folder doesn't exist, create it
|
||||||
path = os.path.split(default_config["journals"][DEFAULT_JOURNAL_KEY])[0]
|
path = os.path.split(default_config["journals"][DEFAULT_JOURNAL_KEY])[0]
|
||||||
|
@ -154,7 +154,7 @@ def _initialize_autocomplete():
|
||||||
|
|
||||||
|
|
||||||
def _autocomplete_path(text, state):
|
def _autocomplete_path(text, state):
|
||||||
expansions = glob.glob(os.path.expanduser(os.path.expandvars(text)) + "*")
|
expansions = glob.glob(expand_path(text) + "*")
|
||||||
expansions = [e + "/" if os.path.isdir(e) else e for e in expansions]
|
expansions = [e + "/" if os.path.isdir(e) else e for e in expansions]
|
||||||
expansions.append(None)
|
expansions.append(None)
|
||||||
return expansions[state]
|
return expansions[state]
|
||||||
|
|
83
jrnl/jrnl.py
83
jrnl/jrnl.py
|
@ -16,6 +16,7 @@ from . import time
|
||||||
from .override import apply_overrides
|
from .override import apply_overrides
|
||||||
from jrnl.output import print_msg
|
from jrnl.output import print_msg
|
||||||
from jrnl.output import print_msgs
|
from jrnl.output import print_msgs
|
||||||
|
from .path import expand_path
|
||||||
|
|
||||||
from jrnl.exception import JrnlException
|
from jrnl.exception import JrnlException
|
||||||
from jrnl.messages import Message
|
from jrnl.messages import Message
|
||||||
|
@ -81,6 +82,8 @@ def _is_write_mode(args, config, **kwargs):
|
||||||
args.contains,
|
args.contains,
|
||||||
args.delete,
|
args.delete,
|
||||||
args.edit,
|
args.edit,
|
||||||
|
args.change_time,
|
||||||
|
args.excluded,
|
||||||
args.export,
|
args.export,
|
||||||
args.end_date,
|
args.end_date,
|
||||||
args.today_in_history,
|
args.today_in_history,
|
||||||
|
@ -152,13 +155,15 @@ def write_mode(args, config, journal, **kwargs):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
journal.write()
|
journal.write()
|
||||||
logging.debug("Write mode: completed journal.write()", args.journal_name, raw)
|
logging.debug("Write mode: completed journal.write()")
|
||||||
|
|
||||||
|
|
||||||
def search_mode(args, journal, **kwargs):
|
def search_mode(args, journal, **kwargs):
|
||||||
"""
|
"""
|
||||||
Search for entries in a journal, then either:
|
Search for entries in a journal, then either:
|
||||||
1. Send them to configured editor for user manipulation
|
1. Send them to configured editor for user manipulation (and also
|
||||||
|
change their timestamps if requested)
|
||||||
|
2. Change their timestamps
|
||||||
2. Delete them (with confirmation for each entry)
|
2. Delete them (with confirmation for each entry)
|
||||||
3. Display them (with formatting options)
|
3. Display them (with formatting options)
|
||||||
"""
|
"""
|
||||||
|
@ -174,8 +179,27 @@ def search_mode(args, journal, **kwargs):
|
||||||
|
|
||||||
# Where do the search results go?
|
# Where do the search results go?
|
||||||
if args.edit:
|
if args.edit:
|
||||||
|
# If we want to both edit and change time in one action
|
||||||
|
if args.change_time:
|
||||||
|
# Generate a new list instead of assigning so it won't be
|
||||||
|
# modified by _change_time_search_results
|
||||||
|
selected_entries = [e for e in journal.entries]
|
||||||
|
|
||||||
|
no_change_time_prompt = len(journal.entries) == 1
|
||||||
|
_change_time_search_results(no_prompt=no_change_time_prompt, **kwargs)
|
||||||
|
|
||||||
|
# Re-filter the journal enties (_change_time_search_results
|
||||||
|
# puts the filtered entries back); use selected_entries
|
||||||
|
# instead of running _search_journal again, because times
|
||||||
|
# have changed since the original search
|
||||||
|
kwargs["old_entries"] = journal.entries
|
||||||
|
journal.entries = selected_entries
|
||||||
|
|
||||||
_edit_search_results(**kwargs)
|
_edit_search_results(**kwargs)
|
||||||
|
|
||||||
|
elif args.change_time:
|
||||||
|
_change_time_search_results(**kwargs)
|
||||||
|
|
||||||
elif args.delete:
|
elif args.delete:
|
||||||
_delete_search_results(**kwargs)
|
_delete_search_results(**kwargs)
|
||||||
|
|
||||||
|
@ -203,8 +227,10 @@ def _get_editor_template(config, **kwargs):
|
||||||
logging.debug("Write mode: no template configured")
|
logging.debug("Write mode: no template configured")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
template_path = expand_path(config["template"])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
template = open(config["template"]).read()
|
template = open(template_path).read()
|
||||||
logging.debug("Write mode: template loaded: %s", template)
|
logging.debug("Write mode: template loaded: %s", template)
|
||||||
except OSError:
|
except OSError:
|
||||||
logging.error("Write mode: template not loaded")
|
logging.error("Write mode: template not loaded")
|
||||||
|
@ -212,7 +238,7 @@ def _get_editor_template(config, **kwargs):
|
||||||
Message(
|
Message(
|
||||||
MsgText.CantReadTemplate,
|
MsgText.CantReadTemplate,
|
||||||
MsgStyle.ERROR,
|
MsgStyle.ERROR,
|
||||||
{"template": config["template"]},
|
{"template": template_path},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -244,6 +270,11 @@ def _search_journal(args, journal, **kwargs):
|
||||||
journal.limit(args.limit)
|
journal.limit(args.limit)
|
||||||
|
|
||||||
|
|
||||||
|
def _other_entries(journal, entries):
|
||||||
|
"""Find entries that are not in journal"""
|
||||||
|
return [e for e in entries if e not in journal.entries]
|
||||||
|
|
||||||
|
|
||||||
def _edit_search_results(config, journal, old_entries, **kwargs):
|
def _edit_search_results(config, journal, old_entries, **kwargs):
|
||||||
"""
|
"""
|
||||||
1. Send the given journal entries to the user-configured editor
|
1. Send the given journal entries to the user-configured editor
|
||||||
|
@ -260,7 +291,7 @@ def _edit_search_results(config, journal, old_entries, **kwargs):
|
||||||
)
|
)
|
||||||
|
|
||||||
# separate entries we are not editing
|
# separate entries we are not editing
|
||||||
other_entries = [e for e in old_entries if e not in journal.entries]
|
other_entries = _other_entries(journal, old_entries)
|
||||||
|
|
||||||
# Get stats now for summary later
|
# Get stats now for summary later
|
||||||
old_stats = _get_predit_stats(journal)
|
old_stats = _get_predit_stats(journal)
|
||||||
|
@ -322,7 +353,7 @@ def _delete_search_results(journal, old_entries, **kwargs):
|
||||||
if not journal.entries:
|
if not journal.entries:
|
||||||
raise JrnlException(Message(MsgText.NothingToDelete, MsgStyle.ERROR))
|
raise JrnlException(Message(MsgText.NothingToDelete, MsgStyle.ERROR))
|
||||||
|
|
||||||
entries_to_delete = journal.prompt_delete_entries()
|
entries_to_delete = journal.prompt_action_entries("Delete entry")
|
||||||
|
|
||||||
if entries_to_delete:
|
if entries_to_delete:
|
||||||
journal.entries = old_entries
|
journal.entries = old_entries
|
||||||
|
@ -331,23 +362,45 @@ def _delete_search_results(journal, old_entries, **kwargs):
|
||||||
journal.write()
|
journal.write()
|
||||||
|
|
||||||
|
|
||||||
|
def _change_time_search_results(args, journal, old_entries, no_prompt=False, **kwargs):
|
||||||
|
if not journal.entries:
|
||||||
|
raise JrnlException(Message(MsgText.NothingToModify, MsgType.WARNING))
|
||||||
|
|
||||||
|
# separate entries we are not editing
|
||||||
|
other_entries = _other_entries(journal, old_entries)
|
||||||
|
|
||||||
|
if no_prompt:
|
||||||
|
entries_to_change = journal.entries
|
||||||
|
else:
|
||||||
|
entries_to_change = journal.prompt_action_entries("Change time")
|
||||||
|
|
||||||
|
if entries_to_change:
|
||||||
|
other_entries += [e for e in journal.entries if e not in entries_to_change]
|
||||||
|
journal.entries = entries_to_change
|
||||||
|
|
||||||
|
date = time.parse(args.change_time)
|
||||||
|
journal.change_date_entries(date)
|
||||||
|
|
||||||
|
journal.entries += other_entries
|
||||||
|
journal.sort()
|
||||||
|
journal.write()
|
||||||
|
|
||||||
|
|
||||||
def _display_search_results(args, journal, **kwargs):
|
def _display_search_results(args, journal, **kwargs):
|
||||||
if args.short or args.export == "short":
|
# Get export format from config file if not provided at the command line
|
||||||
|
args.export = args.export or kwargs["config"].get("display_format")
|
||||||
|
|
||||||
|
if args.tags:
|
||||||
|
print(plugins.get_exporter("tags").export(journal))
|
||||||
|
|
||||||
|
elif args.short or args.export == "short":
|
||||||
print(journal.pprint(short=True))
|
print(journal.pprint(short=True))
|
||||||
|
|
||||||
elif args.export == "pretty":
|
elif args.export == "pretty":
|
||||||
print(journal.pprint())
|
print(journal.pprint())
|
||||||
|
|
||||||
elif args.tags:
|
|
||||||
print(plugins.get_exporter("tags").export(journal))
|
|
||||||
|
|
||||||
elif args.export:
|
elif args.export:
|
||||||
exporter = plugins.get_exporter(args.export)
|
exporter = plugins.get_exporter(args.export)
|
||||||
print(exporter.export(journal, args.filename))
|
print(exporter.export(journal, args.filename))
|
||||||
|
|
||||||
elif kwargs["config"].get("display_format"):
|
|
||||||
exporter = plugins.get_exporter(kwargs["config"]["display_format"])
|
|
||||||
print(exporter.export(journal, args.filename))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(journal.pprint())
|
print(journal.pprint())
|
||||||
|
|
|
@ -237,7 +237,7 @@ class MsgText(Enum):
|
||||||
|
|
||||||
# --- Password --- #
|
# --- Password --- #
|
||||||
Password = "Password:"
|
Password = "Password:"
|
||||||
PasswordFirstEntry = "Enter new password: "
|
PasswordFirstEntry = "Enter password for journal '{journal_name}': "
|
||||||
PasswordConfirmEntry = "Enter password again: "
|
PasswordConfirmEntry = "Enter password again: "
|
||||||
PasswordMaxTriesExceeded = "Too many attempts with wrong password"
|
PasswordMaxTriesExceeded = "Too many attempts with wrong password"
|
||||||
PasswordCanNotBeEmpty = "Password can't be empty!"
|
PasswordCanNotBeEmpty = "Password can't be empty!"
|
||||||
|
@ -250,6 +250,10 @@ class MsgText(Enum):
|
||||||
No entries to delete, because the search returned no results
|
No entries to delete, because the search returned no results
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
NothingToModify = """
|
||||||
|
No entries to modify, because the search returned no results
|
||||||
|
"""
|
||||||
|
|
||||||
# --- Formats --- #
|
# --- Formats --- #
|
||||||
HeadingsPastH6 = """
|
HeadingsPastH6 = """
|
||||||
Headings increased past H6 on export - {date} {title}
|
Headings increased past H6 on export - {date} {title}
|
||||||
|
|
13
jrnl/path.py
Normal file
13
jrnl/path.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import os.path
|
||||||
|
|
||||||
|
|
||||||
|
def home_dir():
|
||||||
|
return os.path.expanduser("~")
|
||||||
|
|
||||||
|
|
||||||
|
def expand_path(path):
|
||||||
|
return os.path.expanduser(os.path.expandvars(path))
|
||||||
|
|
||||||
|
|
||||||
|
def absolute_path(path):
|
||||||
|
return os.path.abspath(expand_path(path))
|
|
@ -13,7 +13,14 @@ def create_password(journal_name: str) -> str:
|
||||||
"hide_input": True,
|
"hide_input": True,
|
||||||
}
|
}
|
||||||
while True:
|
while True:
|
||||||
pw = print_msg(Message(MsgText.PasswordFirstEntry, MsgStyle.PROMPT), **kwargs)
|
pw = print_msg(
|
||||||
|
Message(
|
||||||
|
MsgText.PasswordFirstEntry,
|
||||||
|
MsgStyle.PROMPT,
|
||||||
|
params={"journal_name": journal_name},
|
||||||
|
),
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
if not pw:
|
if not pw:
|
||||||
print_msg(Message(MsgText.PasswordCanNotBeEmpty, MsgStyle.WARNING))
|
print_msg(Message(MsgText.PasswordCanNotBeEmpty, MsgStyle.WARNING))
|
||||||
|
|
|
@ -10,6 +10,7 @@ from .config import is_config_json
|
||||||
from .config import load_config
|
from .config import load_config
|
||||||
from .config import scope_config
|
from .config import scope_config
|
||||||
from .prompt import yesno
|
from .prompt import yesno
|
||||||
|
from .path import expand_path
|
||||||
|
|
||||||
from jrnl.output import print_msg
|
from jrnl.output import print_msg
|
||||||
from jrnl.output import print_msgs
|
from jrnl.output import print_msgs
|
||||||
|
@ -20,7 +21,7 @@ from jrnl.messages import MsgStyle
|
||||||
|
|
||||||
|
|
||||||
def backup(filename, binary=False):
|
def backup(filename, binary=False):
|
||||||
filename = os.path.expanduser(os.path.expandvars(filename))
|
filename = expand_path(filename)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(filename, "rb" if binary else "r") as original:
|
with open(filename, "rb" if binary else "r") as original:
|
||||||
|
@ -61,13 +62,13 @@ def upgrade_jrnl(config_path):
|
||||||
|
|
||||||
for journal_name, journal_conf in config["journals"].items():
|
for journal_name, journal_conf in config["journals"].items():
|
||||||
if isinstance(journal_conf, dict):
|
if isinstance(journal_conf, dict):
|
||||||
path = journal_conf.get("journal")
|
path = expand_path(journal_conf.get("journal"))
|
||||||
encrypt = journal_conf.get("encrypt")
|
encrypt = journal_conf.get("encrypt")
|
||||||
else:
|
else:
|
||||||
encrypt = config.get("encrypt")
|
encrypt = config.get("encrypt")
|
||||||
path = journal_conf
|
path = expand_path(journal_conf)
|
||||||
|
|
||||||
if os.path.exists(os.path.expanduser(path)):
|
if os.path.exists(path):
|
||||||
path = os.path.expanduser(path)
|
path = os.path.expanduser(path)
|
||||||
else:
|
else:
|
||||||
print_msg(Message(MsgText.DoesNotExist, MsgStyle.ERROR, {"name": path}))
|
print_msg(Message(MsgText.DoesNotExist, MsgStyle.ERROR, {"name": path}))
|
||||||
|
|
285
poetry.lock
generated
285
poetry.lock
generated
|
@ -11,7 +11,7 @@ textwrap3 = ">=0.9.2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "appnope"
|
name = "appnope"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
description = "Disable App Nap on macOS >= 10.9"
|
description = "Disable App Nap on macOS >= 10.9"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -107,11 +107,11 @@ pycparser = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.0.4"
|
version = "8.1.3"
|
||||||
description = "Composable command line interface toolkit"
|
description = "Composable command line interface toolkit"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
|
@ -185,7 +185,7 @@ pyflakes = ">=2.4.0,<2.5.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ghp-import"
|
name = "ghp-import"
|
||||||
version = "2.0.2"
|
version = "2.1.0"
|
||||||
description = "Copy your docs directly to the gh-pages branch."
|
description = "Copy your docs directly to the gh-pages branch."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -207,7 +207,7 @@ python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "importlib-metadata"
|
name = "importlib-metadata"
|
||||||
version = "4.11.2"
|
version = "4.11.3"
|
||||||
description = "Read metadata from Python packages"
|
description = "Read metadata from Python packages"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -244,7 +244,7 @@ toml = {version = ">=0.10.2", markers = "python_version > \"3.6\""}
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipython"
|
name = "ipython"
|
||||||
version = "8.1.1"
|
version = "8.3.0"
|
||||||
description = "IPython: Productive Interactive Computing"
|
description = "IPython: Productive Interactive Computing"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -265,7 +265,7 @@ stack-data = "*"
|
||||||
traitlets = ">=5"
|
traitlets = ">=5"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio", "pytest-asyncio"]
|
all = ["black", "Sphinx (>=1.3)", "ipykernel", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.19)", "pandas", "trio"]
|
||||||
black = ["black"]
|
black = ["black"]
|
||||||
doc = ["Sphinx (>=1.3)"]
|
doc = ["Sphinx (>=1.3)"]
|
||||||
kernel = ["ipykernel"]
|
kernel = ["ipykernel"]
|
||||||
|
@ -274,8 +274,8 @@ nbformat = ["nbformat"]
|
||||||
notebook = ["ipywidgets", "notebook"]
|
notebook = ["ipywidgets", "notebook"]
|
||||||
parallel = ["ipyparallel"]
|
parallel = ["ipyparallel"]
|
||||||
qtconsole = ["qtconsole"]
|
qtconsole = ["qtconsole"]
|
||||||
test = ["pytest", "pytest-asyncio", "testpath"]
|
test = ["pytest (<7.1)", "pytest-asyncio", "testpath"]
|
||||||
test_extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "pytest", "testpath", "trio"]
|
test_extra = ["pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pandas", "trio"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jedi"
|
name = "jedi"
|
||||||
|
@ -294,23 +294,23 @@ testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<7.0.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jeepney"
|
name = "jeepney"
|
||||||
version = "0.7.1"
|
version = "0.8.0"
|
||||||
description = "Low-level, pure Python DBus protocol wrapper."
|
description = "Low-level, pure Python DBus protocol wrapper."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
test = ["pytest", "pytest-trio", "pytest-asyncio", "testpath", "trio", "async-timeout"]
|
test = ["pytest", "pytest-trio", "pytest-asyncio (>=0.17)", "testpath", "trio", "async-timeout"]
|
||||||
trio = ["trio", "async-generator"]
|
trio = ["trio", "async-generator"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinja2"
|
name = "jinja2"
|
||||||
version = "3.0.3"
|
version = "3.1.2"
|
||||||
description = "A very fast and expressive template engine."
|
description = "A very fast and expressive template engine."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
MarkupSafe = ">=2.0"
|
MarkupSafe = ">=2.0"
|
||||||
|
@ -320,7 +320,7 @@ i18n = ["Babel (>=2.7)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "keyring"
|
name = "keyring"
|
||||||
version = "23.5.0"
|
version = "23.5.1"
|
||||||
description = "Store and access your passwords safely."
|
description = "Store and access your passwords safely."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -333,8 +333,8 @@ pywin32-ctypes = {version = "<0.1.0 || >0.1.0,<0.1.1 || >0.1.1", markers = "sys_
|
||||||
SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""}
|
SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""}
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"]
|
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"]
|
||||||
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mako"
|
name = "mako"
|
||||||
|
@ -354,7 +354,7 @@ testing = ["pytest"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markdown"
|
name = "markdown"
|
||||||
version = "3.3.6"
|
version = "3.3.7"
|
||||||
description = "Python implementation of Markdown."
|
description = "Python implementation of Markdown."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -368,7 +368,7 @@ testing = ["coverage", "pyyaml"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "markupsafe"
|
name = "markupsafe"
|
||||||
version = "2.1.0"
|
version = "2.1.1"
|
||||||
description = "Safely add untrusted strings to HTML/XML markup."
|
description = "Safely add untrusted strings to HTML/XML markup."
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -403,7 +403,7 @@ python-versions = ">=3.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mkdocs"
|
name = "mkdocs"
|
||||||
version = "1.3.0"
|
version = "1.2.4"
|
||||||
description = "Project documentation with Markdown."
|
description = "Project documentation with Markdown."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -412,8 +412,8 @@ python-versions = ">=3.6"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
click = ">=3.3"
|
click = ">=3.3"
|
||||||
ghp-import = ">=1.0"
|
ghp-import = ">=1.0"
|
||||||
importlib-metadata = ">=4.3"
|
importlib-metadata = ">=3.10"
|
||||||
Jinja2 = ">=2.10.2"
|
Jinja2 = ">=2.10.1"
|
||||||
Markdown = ">=3.2.1"
|
Markdown = ">=3.2.1"
|
||||||
mergedeep = ">=1.3.4"
|
mergedeep = ">=1.3.4"
|
||||||
packaging = ">=20.5"
|
packaging = ">=20.5"
|
||||||
|
@ -516,15 +516,15 @@ python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "2.5.1"
|
version = "2.5.2"
|
||||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
|
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
|
||||||
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
|
test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
|
@ -548,7 +548,7 @@ python-versions = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prompt-toolkit"
|
name = "prompt-toolkit"
|
||||||
version = "3.0.28"
|
version = "3.0.29"
|
||||||
description = "Library for building powerful interactive command lines in Python"
|
description = "Library for building powerful interactive command lines in Python"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -610,22 +610,22 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygments"
|
name = "pygments"
|
||||||
version = "2.11.2"
|
version = "2.12.0"
|
||||||
description = "Pygments is a syntax highlighting package written in Python."
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyparsing"
|
name = "pyparsing"
|
||||||
version = "3.0.7"
|
version = "3.0.8"
|
||||||
description = "Python parsing module"
|
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6.8"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
diagrams = ["jinja2", "railroad-diagrams"]
|
diagrams = ["railroad-diagrams", "jinja2"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyproject-flake8"
|
name = "pyproject-flake8"
|
||||||
|
@ -745,11 +745,11 @@ pyyaml = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rich"
|
name = "rich"
|
||||||
version = "12.0.0"
|
version = "12.4.0"
|
||||||
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6.2,<4.0.0"
|
python-versions = ">=3.6.3,<4.0.0"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
commonmark = ">=0.9.0,<0.10.0"
|
commonmark = ">=0.9.0,<0.10.0"
|
||||||
|
@ -783,7 +783,7 @@ python-versions = ">=3.5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "secretstorage"
|
name = "secretstorage"
|
||||||
version = "3.3.1"
|
version = "3.3.2"
|
||||||
description = "Python bindings to FreeDesktop.org Secret Service API"
|
description = "Python bindings to FreeDesktop.org Secret Service API"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -854,11 +854,11 @@ test = ["pytest"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.1.1"
|
version = "4.2.0"
|
||||||
description = "Backported and Experimental Type Hints for Python 3.6+"
|
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tzlocal"
|
name = "tzlocal"
|
||||||
|
@ -873,7 +873,7 @@ pytz = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "watchdog"
|
name = "watchdog"
|
||||||
version = "2.1.6"
|
version = "2.1.7"
|
||||||
description = "Filesystem events monitoring"
|
description = "Filesystem events monitoring"
|
||||||
category = "dev"
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
|
@ -917,15 +917,15 @@ tests = ["coverage", "flake8", "wheel"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zipp"
|
name = "zipp"
|
||||||
version = "3.7.0"
|
version = "3.8.0"
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||||
category = "main"
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
|
||||||
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
|
||||||
|
|
||||||
[extras]
|
[extras]
|
||||||
testing = ["pytest", "pytest-bdd", "toml"]
|
testing = ["pytest", "pytest-bdd", "toml"]
|
||||||
|
@ -933,7 +933,7 @@ testing = ["pytest", "pytest-bdd", "toml"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = ">=3.9.0, <3.12"
|
python-versions = ">=3.9.0, <3.12"
|
||||||
content-hash = "8a4b09a72f705e5265d6d1bebc61926df2ff1e0237ac1369bef6dbebb44f4d9c"
|
content-hash = "8cd80d198bf8208d9e4b2054b89a22f1ce9faccc91aaef3440fb22e1782b0239"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
ansiwrap = [
|
ansiwrap = [
|
||||||
|
@ -941,8 +941,8 @@ ansiwrap = [
|
||||||
{file = "ansiwrap-0.8.4.zip", hash = "sha256:ca0c740734cde59bf919f8ff2c386f74f9a369818cdc60efe94893d01ea8d9b7"},
|
{file = "ansiwrap-0.8.4.zip", hash = "sha256:ca0c740734cde59bf919f8ff2c386f74f9a369818cdc60efe94893d01ea8d9b7"},
|
||||||
]
|
]
|
||||||
appnope = [
|
appnope = [
|
||||||
{file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
|
{file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"},
|
||||||
{file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"},
|
{file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"},
|
||||||
]
|
]
|
||||||
argcomplete = [
|
argcomplete = [
|
||||||
{file = "argcomplete-2.0.0-py2.py3-none-any.whl", hash = "sha256:cffa11ea77999bb0dd27bb25ff6dc142a6796142f68d45b1a26b11f58724561e"},
|
{file = "argcomplete-2.0.0-py2.py3-none-any.whl", hash = "sha256:cffa11ea77999bb0dd27bb25ff6dc142a6796142f68d45b1a26b11f58724561e"},
|
||||||
|
@ -1042,8 +1042,8 @@ cffi = [
|
||||||
{file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"},
|
{file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"},
|
||||||
]
|
]
|
||||||
click = [
|
click = [
|
||||||
{file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"},
|
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||||
{file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"},
|
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
|
||||||
]
|
]
|
||||||
colorama = [
|
colorama = [
|
||||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||||
|
@ -1090,15 +1090,15 @@ flake8 = [
|
||||||
{file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
|
{file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
|
||||||
]
|
]
|
||||||
ghp-import = [
|
ghp-import = [
|
||||||
{file = "ghp-import-2.0.2.tar.gz", hash = "sha256:947b3771f11be850c852c64b561c600fdddf794bab363060854c1ee7ad05e071"},
|
{file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
|
||||||
{file = "ghp_import-2.0.2-py3-none-any.whl", hash = "sha256:5f8962b30b20652cdffa9c5a9812f7de6bcb56ec475acac579807719bf242c46"},
|
{file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
|
||||||
]
|
]
|
||||||
glob2 = [
|
glob2 = [
|
||||||
{file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"},
|
{file = "glob2-0.7.tar.gz", hash = "sha256:85c3dbd07c8aa26d63d7aacee34fa86e9a91a3873bc30bf62ec46e531f92ab8c"},
|
||||||
]
|
]
|
||||||
importlib-metadata = [
|
importlib-metadata = [
|
||||||
{file = "importlib_metadata-4.11.2-py3-none-any.whl", hash = "sha256:d16e8c1deb60de41b8e8ed21c1a7b947b0bc62fab7e1d470bcdf331cea2e6735"},
|
{file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"},
|
||||||
{file = "importlib_metadata-4.11.2.tar.gz", hash = "sha256:b36ffa925fe3139b2f6ff11d6925ffd4fa7bc47870165e3ac260ac7b4f91e6ac"},
|
{file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"},
|
||||||
]
|
]
|
||||||
iniconfig = [
|
iniconfig = [
|
||||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||||
|
@ -1108,74 +1108,74 @@ ipdb = [
|
||||||
{file = "ipdb-0.13.9.tar.gz", hash = "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"},
|
{file = "ipdb-0.13.9.tar.gz", hash = "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"},
|
||||||
]
|
]
|
||||||
ipython = [
|
ipython = [
|
||||||
{file = "ipython-8.1.1-py3-none-any.whl", hash = "sha256:6f56bfaeaa3247aa3b9cd3b8cbab3a9c0abf7428392f97b21902d12b2f42a381"},
|
{file = "ipython-8.3.0-py3-none-any.whl", hash = "sha256:341456643a764c28f670409bbd5d2518f9b82c013441084ff2c2fc999698f83b"},
|
||||||
{file = "ipython-8.1.1.tar.gz", hash = "sha256:8138762243c9b3a3ffcf70b37151a2a35c23d3a29f9743878c33624f4207be3d"},
|
{file = "ipython-8.3.0.tar.gz", hash = "sha256:807ae3cf43b84693c9272f70368440a9a7eaa2e7e6882dad943c32fbf7e51402"},
|
||||||
]
|
]
|
||||||
jedi = [
|
jedi = [
|
||||||
{file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
|
{file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
|
||||||
{file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
|
{file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
|
||||||
]
|
]
|
||||||
jeepney = [
|
jeepney = [
|
||||||
{file = "jeepney-0.7.1-py3-none-any.whl", hash = "sha256:1b5a0ea5c0e7b166b2f5895b91a08c14de8915afda4407fb5022a195224958ac"},
|
{file = "jeepney-0.8.0-py3-none-any.whl", hash = "sha256:c0a454ad016ca575060802ee4d590dd912e35c122fa04e70306de3d076cce755"},
|
||||||
{file = "jeepney-0.7.1.tar.gz", hash = "sha256:fa9e232dfa0c498bd0b8a3a73b8d8a31978304dcef0515adc859d4e096f96f4f"},
|
{file = "jeepney-0.8.0.tar.gz", hash = "sha256:5efe48d255973902f6badc3ce55e2aa6c5c3b3bc642059ef3a91247bcfcc5806"},
|
||||||
]
|
]
|
||||||
jinja2 = [
|
jinja2 = [
|
||||||
{file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"},
|
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
|
||||||
{file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"},
|
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
|
||||||
]
|
]
|
||||||
keyring = [
|
keyring = [
|
||||||
{file = "keyring-23.5.0-py3-none-any.whl", hash = "sha256:b0d28928ac3ec8e42ef4cc227822647a19f1d544f21f96457965dc01cf555261"},
|
{file = "keyring-23.5.1-py3-none-any.whl", hash = "sha256:9ef58314bcc823f426b49ec787539a2d73571b37de4cd498f839803b01acff1e"},
|
||||||
{file = "keyring-23.5.0.tar.gz", hash = "sha256:9012508e141a80bd1c0b6778d5c610dd9f8c464d75ac6774248500503f972fb9"},
|
{file = "keyring-23.5.1.tar.gz", hash = "sha256:dee502cdf18a98211bef428eea11456a33c00718b2f08524fd5727c7f424bffd"},
|
||||||
]
|
]
|
||||||
mako = [
|
mako = [
|
||||||
{file = "Mako-1.2.0-py3-none-any.whl", hash = "sha256:23aab11fdbbb0f1051b93793a58323ff937e98e34aece1c4219675122e57e4ba"},
|
{file = "Mako-1.2.0-py3-none-any.whl", hash = "sha256:23aab11fdbbb0f1051b93793a58323ff937e98e34aece1c4219675122e57e4ba"},
|
||||||
{file = "Mako-1.2.0.tar.gz", hash = "sha256:9a7c7e922b87db3686210cf49d5d767033a41d4010b284e747682c92bddd8b39"},
|
{file = "Mako-1.2.0.tar.gz", hash = "sha256:9a7c7e922b87db3686210cf49d5d767033a41d4010b284e747682c92bddd8b39"},
|
||||||
]
|
]
|
||||||
markdown = [
|
markdown = [
|
||||||
{file = "Markdown-3.3.6-py3-none-any.whl", hash = "sha256:9923332318f843411e9932237530df53162e29dc7a4e2b91e35764583c46c9a3"},
|
{file = "Markdown-3.3.7-py3-none-any.whl", hash = "sha256:f5da449a6e1c989a4cea2631aa8ee67caa5a2ef855d551c88f9e309f4634c621"},
|
||||||
{file = "Markdown-3.3.6.tar.gz", hash = "sha256:76df8ae32294ec39dcf89340382882dfa12975f87f45c3ed1ecdb1e8cefc7006"},
|
{file = "Markdown-3.3.7.tar.gz", hash = "sha256:cbb516f16218e643d8e0a95b309f77eb118cb138d39a4f27851e6a63581db874"},
|
||||||
]
|
]
|
||||||
markupsafe = [
|
markupsafe = [
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3028252424c72b2602a323f70fbf50aa80a5d3aa616ea6add4ba21ae9cc9da4c"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:290b02bab3c9e216da57c1d11d2ba73a9f73a614bbdcc027d299a60cdfabb11a"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e104c0c2b4cd765b4e83909cde7ec61a1e313f8a75775897db321450e928cce"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24c3be29abb6b34052fd26fc7a8e0a49b1ee9d282e3665e8ad09a0a68faee5b3"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204730fd5fe2fe3b1e9ccadb2bd18ba8712b111dcabce185af0b3b5285a7c989"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d3b64c65328cb4cd252c94f83e66e3d7acf8891e60ebf588d7b493a55a1dbf26"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96de1932237abe0a13ba68b63e94113678c379dca45afa040a17b6e1ad7ed076"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75bb36f134883fdbe13d8e63b8675f5f12b80bb6627f7714c7d6c5becf22719f"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-win32.whl", hash = "sha256:4056f752015dfa9828dce3140dbadd543b555afb3252507348c493def166d454"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
|
||||||
{file = "MarkupSafe-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:d4e702eea4a2903441f2735799d217f4ac1b55f7d8ad96ab7d4e25417cb0827c"},
|
{file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f0eddfcabd6936558ec020130f932d479930581171368fd728efcfb6ef0dd357"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ddea4c352a488b5e1069069f2f501006b1a4362cb906bee9a193ef1245a7a61"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c86c9643cceb1d87ca08cdc30160d1b7ab49a8a21564868921959bd16441b8"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0a0abef2ca47b33fb615b491ce31b055ef2430de52c5b3fb19a4042dbc5cadb"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:736895a020e31b428b3382a7887bfea96102c529530299f426bf2e636aacec9e"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:679cbb78914ab212c49c67ba2c7396dc599a8479de51b9a87b174700abd9ea49"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:84ad5e29bf8bab3ad70fd707d3c05524862bddc54dc040982b0dbcff36481de7"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-win32.whl", hash = "sha256:8da5924cb1f9064589767b0f3fc39d03e3d0fb5aa29e0cb21d43106519bd624a"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
|
||||||
{file = "MarkupSafe-2.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:454ffc1cbb75227d15667c09f164a0099159da0c1f3d2636aa648f12675491ad"},
|
{file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:142119fb14a1ef6d758912b25c4e803c3ff66920635c44078666fe7cc3f8f759"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b2a5a856019d2833c56a3dcac1b80fe795c95f401818ea963594b345929dffa7"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d1fb9b2eec3c9714dd936860850300b51dbaa37404209c8d4cb66547884b7ed"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62c0285e91414f5c8f621a17b69fc0088394ccdaa961ef469e833dbff64bd5ea"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc3150f85e2dbcf99e65238c842d1cfe69d3e7649b19864c1cc043213d9cd730"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f02cf7221d5cd915d7fa58ab64f7ee6dd0f6cddbb48683debf5d04ae9b1c2cc1"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5653619b3eb5cbd35bfba3c12d575db2a74d15e0e1c08bf1db788069d410ce8"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d2f5d97fcbd004c03df8d8fe2b973fe2b14e7bfeb2cfa012eaa8759ce9a762f"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-win32.whl", hash = "sha256:3cace1837bc84e63b3fd2dfce37f08f8c18aeb81ef5cf6bb9b51f625cb4e6cd8"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
|
||||||
{file = "MarkupSafe-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:fabbe18087c3d33c5824cb145ffca52eccd053061df1d79d4b66dafa5ad2a5ea"},
|
{file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:023af8c54fe63530545f70dd2a2a7eed18d07a9a77b94e8bf1e2ff7f252db9a3"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d66624f04de4af8bbf1c7f21cc06649c1c69a7f84109179add573ce35e46d448"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c532d5ab79be0199fa2658e24a02fce8542df196e60665dd322409a03db6a52c"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ec74fada3841b8c5f4c4f197bea916025cb9aa3fe5abf7d52b655d042f956"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c653fde75a6e5eb814d2a0a89378f83d1d3f502ab710904ee585c38888816c"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:961eb86e5be7d0973789f30ebcf6caab60b844203f4396ece27310295a6082c7"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:598b65d74615c021423bd45c2bc5e9b59539c875a9bdb7e5f2a6b92dfcfc268d"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:599941da468f2cf22bf90a84f6e2a65524e87be2fce844f96f2dd9a6c9d1e635"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-win32.whl", hash = "sha256:e6f7f3f41faffaea6596da86ecc2389672fa949bd035251eab26dc6697451d05"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
|
||||||
{file = "MarkupSafe-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:b8811d48078d1cf2a6863dafb896e68406c5f513048451cd2ded0473133473c7"},
|
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
|
||||||
{file = "MarkupSafe-2.1.0.tar.gz", hash = "sha256:80beaf63ddfbc64a0452b841d8036ca0611e049650e20afcb882f5d3c266d65f"},
|
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
|
||||||
]
|
]
|
||||||
matplotlib-inline = [
|
matplotlib-inline = [
|
||||||
{file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"},
|
{file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"},
|
||||||
|
@ -1190,8 +1190,8 @@ mergedeep = [
|
||||||
{file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
|
{file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"},
|
||||||
]
|
]
|
||||||
mkdocs = [
|
mkdocs = [
|
||||||
{file = "mkdocs-1.3.0-py3-none-any.whl", hash = "sha256:26bd2b03d739ac57a3e6eed0b7bcc86168703b719c27b99ad6ca91dc439aacde"},
|
{file = "mkdocs-1.2.4-py3-none-any.whl", hash = "sha256:f108e7ab5a7ed3e30826dbf82f37638f0d90d11161644616cc4f01a1e2ab3940"},
|
||||||
{file = "mkdocs-1.3.0.tar.gz", hash = "sha256:b504405b04da38795fec9b2e5e28f6aa3a73bb0960cb6d5d27ead28952bd35ea"},
|
{file = "mkdocs-1.2.4.tar.gz", hash = "sha256:8e7970a26183487fe2a1041940c6fd03aa0dbe5549e50c3e7194f565cb3c678a"},
|
||||||
]
|
]
|
||||||
mypy-extensions = [
|
mypy-extensions = [
|
||||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||||
|
@ -1229,8 +1229,8 @@ pickleshare = [
|
||||||
{file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
|
{file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
|
||||||
]
|
]
|
||||||
platformdirs = [
|
platformdirs = [
|
||||||
{file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"},
|
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
|
||||||
{file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
|
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
|
||||||
]
|
]
|
||||||
pluggy = [
|
pluggy = [
|
||||||
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
||||||
|
@ -1241,8 +1241,8 @@ pprintpp = [
|
||||||
{file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"},
|
{file = "pprintpp-0.4.0.tar.gz", hash = "sha256:ea826108e2c7f49dc6d66c752973c3fc9749142a798d6b254e1e301cfdbc6403"},
|
||||||
]
|
]
|
||||||
prompt-toolkit = [
|
prompt-toolkit = [
|
||||||
{file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"},
|
{file = "prompt_toolkit-3.0.29-py3-none-any.whl", hash = "sha256:62291dad495e665fca0bda814e342c69952086afb0f4094d0893d357e5c78752"},
|
||||||
{file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"},
|
{file = "prompt_toolkit-3.0.29.tar.gz", hash = "sha256:bd640f60e8cecd74f0dc249713d433ace2ddc62b65ee07f96d358e0b152b6ea7"},
|
||||||
]
|
]
|
||||||
ptyprocess = [
|
ptyprocess = [
|
||||||
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
|
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
|
||||||
|
@ -1269,12 +1269,12 @@ pyflakes = [
|
||||||
{file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
|
{file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
|
||||||
]
|
]
|
||||||
pygments = [
|
pygments = [
|
||||||
{file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"},
|
{file = "Pygments-2.12.0-py3-none-any.whl", hash = "sha256:dc9c10fb40944260f6ed4c688ece0cd2048414940f1cea51b8b226318411c519"},
|
||||||
{file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
|
{file = "Pygments-2.12.0.tar.gz", hash = "sha256:5eb116118f9612ff1ee89ac96437bb6b49e8f04d8a13b514ba26f620208e26eb"},
|
||||||
]
|
]
|
||||||
pyparsing = [
|
pyparsing = [
|
||||||
{file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
|
{file = "pyparsing-3.0.8-py3-none-any.whl", hash = "sha256:ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06"},
|
||||||
{file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
|
{file = "pyparsing-3.0.8.tar.gz", hash = "sha256:7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954"},
|
||||||
]
|
]
|
||||||
pyproject-flake8 = [
|
pyproject-flake8 = [
|
||||||
{file = "pyproject-flake8-0.0.1a4.tar.gz", hash = "sha256:8ed9453f1d984cfe94c998f9840275359e29e7f435b8ddd188ae084e2dc1270c"},
|
{file = "pyproject-flake8-0.0.1a4.tar.gz", hash = "sha256:8ed9453f1d984cfe94c998f9840275359e29e7f435b8ddd188ae084e2dc1270c"},
|
||||||
|
@ -1347,8 +1347,8 @@ pyyaml-env-tag = [
|
||||||
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
{file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"},
|
||||||
]
|
]
|
||||||
rich = [
|
rich = [
|
||||||
{file = "rich-12.0.0-py3-none-any.whl", hash = "sha256:fdcd2f8d416e152bcf35c659987038d1ae5a7bd336e821ca7551858a4c7e38a9"},
|
{file = "rich-12.4.0-py3-none-any.whl", hash = "sha256:fdf6f447f231289dd446d31e5ee856fb0cc7dccd852a80f3e9d5aeecccabaedc"},
|
||||||
{file = "rich-12.0.0.tar.gz", hash = "sha256:14bfd0507edc633e021b02c45cbf7ca22e33b513817627b8de3412f047a3e798"},
|
{file = "rich-12.4.0.tar.gz", hash = "sha256:7aebf67874dc5cc2c89e2cb6ac322c95bd92510df2af0296c8bf494335ef704f"},
|
||||||
]
|
]
|
||||||
"ruamel.yaml" = [
|
"ruamel.yaml" = [
|
||||||
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
|
{file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
|
||||||
|
@ -1382,8 +1382,8 @@ rich = [
|
||||||
{file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
|
{file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
|
||||||
]
|
]
|
||||||
secretstorage = [
|
secretstorage = [
|
||||||
{file = "SecretStorage-3.3.1-py3-none-any.whl", hash = "sha256:422d82c36172d88d6a0ed5afdec956514b189ddbfb72fefab0c8a1cee4eaf71f"},
|
{file = "SecretStorage-3.3.2-py3-none-any.whl", hash = "sha256:755dc845b6ad76dcbcbc07ea3da75ae54bb1ea529eb72d15f83d26499a5df319"},
|
||||||
{file = "SecretStorage-3.3.1.tar.gz", hash = "sha256:fd666c51a6bf200643495a04abb261f83229dcb6fd8472ec393df7ffc8b6f195"},
|
{file = "SecretStorage-3.3.2.tar.gz", hash = "sha256:0a8eb9645b320881c222e827c26f4cfcf55363e8b374a021981ef886657a912f"},
|
||||||
]
|
]
|
||||||
six = [
|
six = [
|
||||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
|
@ -1410,37 +1410,38 @@ traitlets = [
|
||||||
{file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"},
|
{file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"},
|
||||||
]
|
]
|
||||||
typing-extensions = [
|
typing-extensions = [
|
||||||
{file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
|
{file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"},
|
||||||
{file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
|
{file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"},
|
||||||
]
|
]
|
||||||
tzlocal = [
|
tzlocal = [
|
||||||
{file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"},
|
{file = "tzlocal-2.1-py2.py3-none-any.whl", hash = "sha256:e2cb6c6b5b604af38597403e9852872d7f534962ae2954c7f35efcb1ccacf4a4"},
|
||||||
{file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"},
|
{file = "tzlocal-2.1.tar.gz", hash = "sha256:643c97c5294aedc737780a49d9df30889321cbe1204eac2c2ec6134035a92e44"},
|
||||||
]
|
]
|
||||||
watchdog = [
|
watchdog = [
|
||||||
{file = "watchdog-2.1.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:9693f35162dc6208d10b10ddf0458cc09ad70c30ba689d9206e02cd836ce28a3"},
|
{file = "watchdog-2.1.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:177bae28ca723bc00846466016d34f8c1d6a621383b6caca86745918d55c7383"},
|
||||||
{file = "watchdog-2.1.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:aba5c812f8ee8a3ff3be51887ca2d55fb8e268439ed44110d3846e4229eb0e8b"},
|
{file = "watchdog-2.1.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d1cf7dfd747dec519486a98ef16097e6c480934ef115b16f18adb341df747a4"},
|
||||||
{file = "watchdog-2.1.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4ae38bf8ba6f39d5b83f78661273216e7db5b00f08be7592062cb1fc8b8ba542"},
|
{file = "watchdog-2.1.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f14ce6adea2af1bba495acdde0e510aecaeb13b33f7bd2f6324e551b26688ca"},
|
||||||
{file = "watchdog-2.1.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ad6f1796e37db2223d2a3f302f586f74c72c630b48a9872c1e7ae8e92e0ab669"},
|
{file = "watchdog-2.1.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4d0e98ac2e8dd803a56f4e10438b33a2d40390a72750cff4939b4b274e7906fa"},
|
||||||
{file = "watchdog-2.1.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:922a69fa533cb0c793b483becaaa0845f655151e7256ec73630a1b2e9ebcb660"},
|
{file = "watchdog-2.1.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:81982c7884aac75017a6ecc72f1a4fedbae04181a8665a34afce9539fc1b3fab"},
|
||||||
{file = "watchdog-2.1.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b2fcf9402fde2672545b139694284dc3b665fd1be660d73eca6805197ef776a3"},
|
{file = "watchdog-2.1.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0b4a1fe6201c6e5a1926f5767b8664b45f0fcb429b62564a41f490ff1ce1dc7a"},
|
||||||
{file = "watchdog-2.1.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3386b367e950a11b0568062b70cc026c6f645428a698d33d39e013aaeda4cc04"},
|
{file = "watchdog-2.1.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6e6ae29b72977f2e1ee3d0b760d7ee47896cb53e831cbeede3e64485e5633cc8"},
|
||||||
{file = "watchdog-2.1.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f1c00aa35f504197561060ca4c21d3cc079ba29cf6dd2fe61024c70160c990b"},
|
{file = "watchdog-2.1.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b9777664848160449e5b4260e0b7bc1ae0f6f4992a8b285db4ec1ef119ffa0e2"},
|
||||||
{file = "watchdog-2.1.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b52b88021b9541a60531142b0a451baca08d28b74a723d0c99b13c8c8d48d604"},
|
{file = "watchdog-2.1.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:19b36d436578eb437e029c6b838e732ed08054956366f6dd11875434a62d2b99"},
|
||||||
{file = "watchdog-2.1.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8047da932432aa32c515ec1447ea79ce578d0559362ca3605f8e9568f844e3c6"},
|
{file = "watchdog-2.1.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b61acffaf5cd5d664af555c0850f9747cc5f2baf71e54bbac164c58398d6ca7b"},
|
||||||
{file = "watchdog-2.1.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e92c2d33858c8f560671b448205a268096e17870dcf60a9bb3ac7bfbafb7f5f9"},
|
{file = "watchdog-2.1.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1e877c70245424b06c41ac258023ea4bd0c8e4ff15d7c1368f17cd0ae6e351dd"},
|
||||||
{file = "watchdog-2.1.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b7d336912853d7b77f9b2c24eeed6a5065d0a0cc0d3b6a5a45ad6d1d05fb8cd8"},
|
{file = "watchdog-2.1.7-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d802d65262a560278cf1a65ef7cae4e2bc7ecfe19e5451349e4c67e23c9dc420"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_aarch64.whl", hash = "sha256:cca7741c0fcc765568350cb139e92b7f9f3c9a08c4f32591d18ab0a6ac9e71b6"},
|
{file = "watchdog-2.1.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b3750ee5399e6e9c69eae8b125092b871ee9e2fcbd657a92747aea28f9056a5c"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_armv7l.whl", hash = "sha256:25fb5240b195d17de949588628fdf93032ebf163524ef08933db0ea1f99bd685"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_aarch64.whl", hash = "sha256:ed6d9aad09a2a948572224663ab00f8975fae242aa540509737bb4507133fa2d"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_i686.whl", hash = "sha256:be9be735f827820a06340dff2ddea1fb7234561fa5e6300a62fe7f54d40546a0"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_armv7l.whl", hash = "sha256:b26e13e8008dcaea6a909e91d39b629a39635d1a8a7239dd35327c74f4388601"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0d19fb2441947b58fbf91336638c2b9f4cc98e05e1045404d7a4cb7cddc7a65"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_i686.whl", hash = "sha256:0908bb50f6f7de54d5d31ec3da1654cb7287c6b87bce371954561e6de379d690"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:3becdb380d8916c873ad512f1701f8a92ce79ec6978ffde92919fd18d41da7fb"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_ppc64.whl", hash = "sha256:bdcbf75580bf4b960fb659bbccd00123d83119619195f42d721e002c1621602f"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_s390x.whl", hash = "sha256:ae67501c95606072aafa865b6ed47343ac6484472a2f95490ba151f6347acfc2"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:81a5861d0158a7e55fe149335fb2bbfa6f48cbcbd149b52dbe2cd9a544034bbd"},
|
||||||
{file = "watchdog-2.1.6-py3-none-manylinux2014_x86_64.whl", hash = "sha256:e0f30db709c939cabf64a6dc5babb276e6d823fd84464ab916f9b9ba5623ca15"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_s390x.whl", hash = "sha256:03b43d583df0f18782a0431b6e9e9965c5b3f7cf8ec36a00b930def67942c385"},
|
||||||
{file = "watchdog-2.1.6-py3-none-win32.whl", hash = "sha256:e02794ac791662a5eafc6ffeaf9bcc149035a0e48eb0a9d40a8feb4622605a3d"},
|
{file = "watchdog-2.1.7-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ae934e34c11aa8296c18f70bf66ed60e9870fcdb4cc19129a04ca83ab23e7055"},
|
||||||
{file = "watchdog-2.1.6-py3-none-win_amd64.whl", hash = "sha256:bd9ba4f332cf57b2c1f698be0728c020399ef3040577cde2939f2e045b39c1e5"},
|
{file = "watchdog-2.1.7-py3-none-win32.whl", hash = "sha256:49639865e3db4be032a96695c98ac09eed39bbb43fe876bb217da8f8101689a6"},
|
||||||
{file = "watchdog-2.1.6-py3-none-win_ia64.whl", hash = "sha256:a0f1c7edf116a12f7245be06120b1852275f9506a7d90227648b250755a03923"},
|
{file = "watchdog-2.1.7-py3-none-win_amd64.whl", hash = "sha256:340b875aecf4b0e6672076a6f05cfce6686935559bb6d34cebedee04126a9566"},
|
||||||
{file = "watchdog-2.1.6.tar.gz", hash = "sha256:a36e75df6c767cbf46f61a91c70b3ba71811dfa0aca4a324d9407a06a8b7a2e7"},
|
{file = "watchdog-2.1.7-py3-none-win_ia64.whl", hash = "sha256:351e09b6d9374d5bcb947e6ac47a608ec25b9d70583e9db00b2fcdb97b00b572"},
|
||||||
|
{file = "watchdog-2.1.7.tar.gz", hash = "sha256:3fd47815353be9c44eebc94cc28fe26b2b0c5bd889dafc4a5a7cbdf924143480"},
|
||||||
]
|
]
|
||||||
wcwidth = [
|
wcwidth = [
|
||||||
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
|
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
|
||||||
|
@ -1455,6 +1456,6 @@ yq = [
|
||||||
{file = "yq-2.14.0.tar.gz", hash = "sha256:f4bf2b299d1e5c7ebd74cfb25d1f5d9b6401063bac07a2d09a156144c1d644e1"},
|
{file = "yq-2.14.0.tar.gz", hash = "sha256:f4bf2b299d1e5c7ebd74cfb25d1f5d9b6401063bac07a2d09a156144c1d644e1"},
|
||||||
]
|
]
|
||||||
zipp = [
|
zipp = [
|
||||||
{file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"},
|
{file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
|
||||||
{file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"},
|
{file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
|
||||||
]
|
]
|
||||||
|
|
|
@ -52,7 +52,7 @@ toml = { version = ">=0.10", optional = true }
|
||||||
rich = "^12.2.0"
|
rich = "^12.2.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
mkdocs = ">=1.0"
|
mkdocs = ">=1.0,<1.3"
|
||||||
black = { version = ">=21.5b2", allow-prereleases = true }
|
black = { version = ">=21.5b2", allow-prereleases = true }
|
||||||
toml = ">=0.10"
|
toml = ">=0.10"
|
||||||
pytest = ">=6.2"
|
pytest = ">=6.2"
|
||||||
|
@ -82,6 +82,10 @@ required_plugins = [
|
||||||
]
|
]
|
||||||
markers = [
|
markers = [
|
||||||
"todo",
|
"todo",
|
||||||
|
"skip_win",
|
||||||
|
"skip_posix",
|
||||||
|
"on_win",
|
||||||
|
"on_posix",
|
||||||
]
|
]
|
||||||
addopts = [
|
addopts = [
|
||||||
"--pdbcls=IPython.terminal.debugger:Pdb"
|
"--pdbcls=IPython.terminal.debugger:Pdb"
|
||||||
|
|
240
tests/bdd/features/change_time.feature
Normal file
240
tests/bdd/features/change_time.feature
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
Feature: Change entry times in journal
|
||||||
|
Scenario Outline: Change time flag changes single entry timestamp
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -1"
|
||||||
|
Then the output should contain "2020-09-24 09:14 The third entry finally"
|
||||||
|
When we run "jrnl -1 --change-time '2022-04-23 10:30'" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-29 11:11 Entry the first.
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
Scenario Outline: Change flag changes prompted entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl -1"
|
||||||
|
Then the output should contain "2020-09-24 09:14 The third entry finally"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30'" and enter
|
||||||
|
Y
|
||||||
|
N
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with nonsense input changes nothing
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time now asdfasdf"
|
||||||
|
Then the output should contain "No entries to modify"
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-29 11:11 Entry the first.
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with tag only changes tagged entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' @ipsum" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with multiple tags changes all entries matching any of the tags
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' @ipsum @tagthree" and enter
|
||||||
|
Y
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with -and changes boolean AND of tagged entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' -and @tagone @tagtwo" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with -not does not change entries from given tag
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' @tagone -not @ipsum" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-29 11:11 Entry the first.
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with -from search operator only changes entries since that date
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' -from 2020-09-01" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-29 11:11 Entry the first.
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with -to only changes entries up to specified date
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' -to 2020-08-31" and enter
|
||||||
|
Y
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
2022-04-23 10:30 A second entry in what I hope to be a long series.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with -starred only changes starred entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' -starred" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-29 11:11 Entry the first.
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
2022-04-23 10:30 A second entry in what I hope to be a long series.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with -contains only changes entries containing expression
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' -contains dignissim" and enter
|
||||||
|
Y
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: Change time flag with no enties specified changes nothing
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl --change-time" and enter
|
||||||
|
N
|
||||||
|
N
|
||||||
|
N
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-29 11:11 Entry the first.
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2020-09-24 09:14 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: --change-time with --edit modifies selected entries
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
And we write nothing to the editor if opened
|
||||||
|
And we use the password "test" if prompted
|
||||||
|
When we run "jrnl --change-time '2022-04-23 10:30' --edit" and enter
|
||||||
|
Y
|
||||||
|
N
|
||||||
|
Y
|
||||||
|
Then the error output should contain "No entry to save"
|
||||||
|
And the editor should have been called
|
||||||
|
When we run "jrnl -99 --short"
|
||||||
|
Then the output should be
|
||||||
|
2020-08-31 14:32 A second entry in what I hope to be a long series.
|
||||||
|
2022-04-23 10:30 Entry the first.
|
||||||
|
2022-04-23 10:30 The third entry finally after weeks without writing.
|
||||||
|
|
||||||
|
Examples: Configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
# | basic_dayone.yaml | @todo
|
|
@ -24,10 +24,11 @@ Feature: Encrypting and decrypting journals
|
||||||
2013-06-10 15:40 Life is good.
|
2013-06-10 15:40 Life is good.
|
||||||
|
|
||||||
|
|
||||||
@todo
|
|
||||||
Scenario: Trying to encrypt an already encrypted journal
|
Scenario: Trying to encrypt an already encrypted journal
|
||||||
# This should warn the user that the journal is already encrypted
|
Given we use the config "encrypted.yaml"
|
||||||
|
When we run "jrnl --encrypt" and enter "bad doggie no biscuit"
|
||||||
|
Then the output should contain "already encrypted. Create a new password."
|
||||||
|
Then we should be prompted for a password
|
||||||
|
|
||||||
Scenario Outline: Encrypting a journal
|
Scenario Outline: Encrypting a journal
|
||||||
Given we use the config "simple.yaml"
|
Given we use the config "simple.yaml"
|
||||||
|
|
|
@ -30,6 +30,24 @@ Feature: Journals iteracting with the file system in a way that users can see
|
||||||
Then the journal should exist
|
Then the journal should exist
|
||||||
When we run "jrnl -99 --short"
|
When we run "jrnl -99 --short"
|
||||||
Then the output should contain "This is a new entry in my journal"
|
Then the output should contain "This is a new entry in my journal"
|
||||||
|
|
||||||
|
@on_posix
|
||||||
|
Scenario: If the directory for a Folder journal ending in a slash ('/') doesn't exist, then it should be created
|
||||||
|
Given we use the config "missing_directory.yaml"
|
||||||
|
Then the journal "endslash" directory should not exist
|
||||||
|
When we run "jrnl endslash This is a new entry in my journal"
|
||||||
|
Then the journal "endslash" directory should exist
|
||||||
|
When we run "jrnl endslash -1"
|
||||||
|
Then the output should contain "This is a new entry in my journal"
|
||||||
|
|
||||||
|
@on_win
|
||||||
|
Scenario: If the directory for a Folder journal ending in a backslash ('\') doesn't exist, then it should be created
|
||||||
|
Given we use the config "missing_directory.yaml"
|
||||||
|
Then the journal "endbackslash" directory should not exist
|
||||||
|
When we run "jrnl endbackslash This is a new entry in my journal"
|
||||||
|
Then the journal "endbackslash" directory should exist
|
||||||
|
When we run "jrnl endbackslash -1"
|
||||||
|
Then the output should contain "This is a new entry in my journal"
|
||||||
|
|
||||||
Scenario: Creating journal with relative path should update to absolute path
|
Scenario: Creating journal with relative path should update to absolute path
|
||||||
Given we use no config
|
Given we use no config
|
||||||
|
|
|
@ -560,3 +560,19 @@ Feature: Custom formats
|
||||||
| basic_encrypted.yaml |
|
| basic_encrypted.yaml |
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
| basic_dayone.yaml |
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
|
|
||||||
|
Scenario Outline: display_format short and pretty do not crash if specified as config values
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
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
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_encrypted.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
|
@ -183,6 +183,19 @@ Feature: Searching in a journal
|
||||||
| basic_folder.yaml |
|
| basic_folder.yaml |
|
||||||
| basic_dayone.yaml |
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
|
Scenario Outline: Using -not should exclude all entries with that tag
|
||||||
|
# https://github.com/jrnl-org/jrnl/issues/1472
|
||||||
|
Given we use the config "<config_file>"
|
||||||
|
When we run "jrnl -not @tagtwo"
|
||||||
|
Then the output should not contain "@tagtwo"
|
||||||
|
And the editor should not have been called
|
||||||
|
|
||||||
|
Examples: configs
|
||||||
|
| config_file |
|
||||||
|
| basic_onefile.yaml |
|
||||||
|
| basic_folder.yaml |
|
||||||
|
| basic_dayone.yaml |
|
||||||
|
|
||||||
Scenario: DayOne tag searching should work with tags containing a mixture of upper and lower case.
|
Scenario: DayOne tag searching should work with tags containing a mixture of upper and lower case.
|
||||||
# https://github.com/jrnl-org/jrnl/issues/354
|
# https://github.com/jrnl-org/jrnl/issues/354
|
||||||
Given we use the config "dayone.yaml"
|
Given we use the config "dayone.yaml"
|
||||||
|
|
|
@ -5,6 +5,7 @@ scenarios("features/config_file.feature")
|
||||||
scenarios("features/core.feature")
|
scenarios("features/core.feature")
|
||||||
scenarios("features/datetime.feature")
|
scenarios("features/datetime.feature")
|
||||||
scenarios("features/delete.feature")
|
scenarios("features/delete.feature")
|
||||||
|
scenarios("features/change_time.feature")
|
||||||
scenarios("features/encrypt.feature")
|
scenarios("features/encrypt.feature")
|
||||||
scenarios("features/file_storage.feature")
|
scenarios("features/file_storage.feature")
|
||||||
scenarios("features/format.feature")
|
scenarios("features/format.feature")
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
# License: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
from pytest import mark
|
from pytest import mark
|
||||||
|
from pytest import skip
|
||||||
|
|
||||||
from jrnl.os_compat import on_windows
|
from jrnl.os_compat import on_windows
|
||||||
|
from jrnl.os_compat import on_posix
|
||||||
|
|
||||||
|
|
||||||
pytest_plugins = [
|
pytest_plugins = [
|
||||||
|
@ -15,11 +17,39 @@ pytest_plugins = [
|
||||||
|
|
||||||
|
|
||||||
def pytest_bdd_apply_tag(tag, function):
|
def pytest_bdd_apply_tag(tag, function):
|
||||||
|
# skip markers
|
||||||
if tag == "skip_win":
|
if tag == "skip_win":
|
||||||
marker = mark.skipif(on_windows(), reason="Skip test on Windows")
|
marker = mark.skipif(on_windows(), reason="Skip test on Windows")
|
||||||
|
elif tag == "skip_posix":
|
||||||
|
marker = mark.skipif(on_posix(), reason="Skip test on Mac/Linux")
|
||||||
|
|
||||||
|
# only on OS markers
|
||||||
|
elif tag == "on_win":
|
||||||
|
marker = mark.skipif(not on_windows(), reason="Skip test not on Windows")
|
||||||
|
elif tag == "on_posix":
|
||||||
|
marker = mark.skipif(not on_posix(), reason="Skip test not on Mac/Linux")
|
||||||
else:
|
else:
|
||||||
# Fall back to pytest-bdd's default behavior
|
# Fall back to pytest-bdd's default behavior
|
||||||
return None
|
return None
|
||||||
|
|
||||||
marker(function)
|
marker(function)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
markers = [mark.name for mark in item.iter_markers()]
|
||||||
|
|
||||||
|
on_win = on_windows()
|
||||||
|
on_nix = on_posix()
|
||||||
|
|
||||||
|
if "skip_win" in markers and on_win:
|
||||||
|
skip("Skip test on Windows")
|
||||||
|
|
||||||
|
if "skip_posix" in markers and on_nix:
|
||||||
|
skip("Skip test on Mac/Linux")
|
||||||
|
|
||||||
|
if "on_win" in markers and not on_win:
|
||||||
|
skip("Skip test not on Windows")
|
||||||
|
|
||||||
|
if "on_posix" in markers and not on_nix:
|
||||||
|
skip("Skip test not on Mac/Linux")
|
||||||
|
|
|
@ -5,6 +5,8 @@ encrypt: false
|
||||||
highlight: true
|
highlight: true
|
||||||
journals:
|
journals:
|
||||||
default: features/journals/missing_directory/simple.journal
|
default: features/journals/missing_directory/simple.journal
|
||||||
|
endslash: features/journals/missing_folder/
|
||||||
|
endbackslash: features\journals\missing_folder\
|
||||||
linewrap: 80
|
linewrap: 80
|
||||||
tagsymbols: "@"
|
tagsymbols: "@"
|
||||||
template: false
|
template: false
|
||||||
|
|
|
@ -213,6 +213,16 @@ def journal_should_not_exist(config_on_disk, should_or_should_not):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@then(parse('the journal "{journal_name}" directory {should_or_should_not} exist'))
|
||||||
|
def directory_should_not_exist(config_on_disk, should_or_should_not, journal_name):
|
||||||
|
scoped_config = scope_config(config_on_disk, journal_name)
|
||||||
|
expected_path = scoped_config["journal"]
|
||||||
|
we_should = parse_should_or_should_not(should_or_should_not)
|
||||||
|
dir_exists = os.path.isdir(expected_path)
|
||||||
|
|
||||||
|
assert dir_exists == we_should
|
||||||
|
|
||||||
|
|
||||||
@then(parse('the content of file "{file_path}" in the cache should be\n{file_content}'))
|
@then(parse('the content of file "{file_path}" in the cache should be\n{file_content}'))
|
||||||
def content_of_file_should_be(file_path, file_content, cache_dir):
|
def content_of_file_should_be(file_path, file_content, cache_dir):
|
||||||
assert cache_dir["exists"]
|
assert cache_dir["exists"]
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import argparse
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
import jrnl
|
|
||||||
from jrnl.jrnl import _display_search_results
|
|
||||||
|
|
||||||
|
|
||||||
# fmt: off
|
|
||||||
# see: https://github.com/psf/black/issues/664
|
|
||||||
@pytest.mark.parametrize("export_format", [ "pretty", "short","markdown"])
|
|
||||||
#fmt: on
|
|
||||||
@mock.patch.object(argparse, "Namespace", return_value={"export": "markdown", "filename": "irrele.vant"})
|
|
||||||
def test_export_format(mock_args, export_format):
|
|
||||||
|
|
||||||
test_journal = jrnl.Journal.Journal
|
|
||||||
mock_args.export = export_format
|
|
||||||
#fmt: off
|
|
||||||
# see: https://github.com/psf/black/issues/664
|
|
||||||
with mock.patch("builtins.print") as mock_spy_print, \
|
|
||||||
mock.patch('jrnl.Journal.Journal.pprint') as mock_pprint:
|
|
||||||
_display_search_results(mock_args, test_journal)
|
|
||||||
mock_spy_print.assert_called_once_with(mock_pprint())
|
|
||||||
#fmt: on
|
|
48
tests/unit/test_jrnl.py
Normal file
48
tests/unit/test_jrnl.py
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
import jrnl
|
||||||
|
from jrnl.jrnl import _display_search_results
|
||||||
|
from jrnl.args import parse_args
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def random_string():
|
||||||
|
return "".join(random.choices(string.ascii_uppercase + string.digits, k=25))
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("export_format", ["pretty", "short"])
|
||||||
|
@mock.patch("builtins.print")
|
||||||
|
@mock.patch("jrnl.Journal.Journal.pprint")
|
||||||
|
def test_display_search_results_pretty_short(mock_pprint, mock_print, export_format):
|
||||||
|
mock_args = parse_args(["--format", export_format])
|
||||||
|
test_journal = mock.Mock(wraps=jrnl.Journal.Journal)
|
||||||
|
|
||||||
|
_display_search_results(mock_args, test_journal)
|
||||||
|
|
||||||
|
mock_print.assert_called_once_with(mock_pprint.return_value)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"export_format", ["markdown", "json", "xml", "yaml", "fancy", "dates"]
|
||||||
|
)
|
||||||
|
@mock.patch("jrnl.plugins.get_exporter")
|
||||||
|
@mock.patch("builtins.print")
|
||||||
|
def test_display_search_results_builtin_plugins(
|
||||||
|
mock_print, mock_exporter, export_format, random_string
|
||||||
|
):
|
||||||
|
test_filename = random_string
|
||||||
|
mock_args = parse_args(["--format", export_format, "--file", test_filename])
|
||||||
|
|
||||||
|
test_journal = mock.Mock(wraps=jrnl.Journal.Journal)
|
||||||
|
mock_export = mock.Mock()
|
||||||
|
mock_exporter.return_value.export = mock_export
|
||||||
|
|
||||||
|
_display_search_results(mock_args, test_journal)
|
||||||
|
|
||||||
|
mock_exporter.assert_called_once_with(export_format)
|
||||||
|
mock_export.assert_called_once_with(test_journal, test_filename)
|
||||||
|
mock_print.assert_called_once_with(mock_export.return_value)
|
|
@ -17,6 +17,7 @@ def expected_args(**kwargs):
|
||||||
"contains": None,
|
"contains": None,
|
||||||
"debug": False,
|
"debug": False,
|
||||||
"delete": False,
|
"delete": False,
|
||||||
|
"change_time": None,
|
||||||
"edit": False,
|
"edit": False,
|
||||||
"end_date": None,
|
"end_date": None,
|
||||||
"today_in_history": False,
|
"today_in_history": False,
|
||||||
|
@ -58,6 +59,13 @@ def test_delete_alone():
|
||||||
assert cli_as_dict("--delete") == expected_args(delete=True)
|
assert cli_as_dict("--delete") == expected_args(delete=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_change_time_alone():
|
||||||
|
assert cli_as_dict("--change-time") == expected_args(change_time="now")
|
||||||
|
assert cli_as_dict("--change-time yesterday") == expected_args(
|
||||||
|
change_time="yesterday"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_diagnostic_alone():
|
def test_diagnostic_alone():
|
||||||
from jrnl.commands import preconfig_diagnostic
|
from jrnl.commands import preconfig_diagnostic
|
||||||
|
|
||||||
|
|
103
tests/unit/test_path.py
Normal file
103
tests/unit/test_path.py
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
import pytest
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
from os import getenv
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from jrnl.path import home_dir
|
||||||
|
from jrnl.path import expand_path
|
||||||
|
from jrnl.path import absolute_path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def home_dir_str(monkeypatch):
|
||||||
|
username = "username"
|
||||||
|
monkeypatch.setenv("USERPROFILE", username) # for windows
|
||||||
|
monkeypatch.setenv("HOME", username) # for *nix
|
||||||
|
return username
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def random_test_var(monkeypatch):
|
||||||
|
name = f"JRNL_TEST_{''.join(random.sample(string.ascii_uppercase, 10))}"
|
||||||
|
val = "".join(random.sample(string.ascii_lowercase, 25))
|
||||||
|
monkeypatch.setenv(name, val)
|
||||||
|
return (name, val)
|
||||||
|
|
||||||
|
|
||||||
|
def test_home_dir(home_dir_str):
|
||||||
|
assert home_dir() == home_dir_str
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.on_posix
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"path",
|
||||||
|
["~"],
|
||||||
|
)
|
||||||
|
def test_expand_path_actually_expands_mac_linux(path):
|
||||||
|
# makes sure that path isn't being returns as-is
|
||||||
|
assert expand_path(path) != path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.on_win
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"path",
|
||||||
|
["~", "%USERPROFILE%"],
|
||||||
|
)
|
||||||
|
def test_expand_path_actually_expands_windows(path):
|
||||||
|
# makes sure that path isn't being returns as-is
|
||||||
|
assert expand_path(path) != path
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.on_posix
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"paths",
|
||||||
|
[
|
||||||
|
["~", "HOME"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_expand_path_expands_into_correct_value_mac_linux(paths):
|
||||||
|
input_path, expected_path = paths[0], paths[1]
|
||||||
|
assert expand_path(input_path) == getenv(expected_path)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.on_win
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"paths",
|
||||||
|
[
|
||||||
|
["~", "USERPROFILE"],
|
||||||
|
["%USERPROFILE%", "USERPROFILE"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_expand_path_expands_into_correct_value_windows(paths):
|
||||||
|
input_path, expected_path = paths[0], paths[1]
|
||||||
|
assert expand_path(input_path) == getenv(expected_path)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.on_posix
|
||||||
|
@pytest.mark.parametrize("_", range(25))
|
||||||
|
def test_expand_path_expands_into_random_env_value_mac_linux(_, random_test_var):
|
||||||
|
var_name, var_value = random_test_var[0], random_test_var[1]
|
||||||
|
assert expand_path(var_name) == var_name
|
||||||
|
assert expand_path(f"${var_name}") == var_value # mac & linux
|
||||||
|
assert expand_path(f"${var_name}") == getenv(var_name)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.on_win
|
||||||
|
@pytest.mark.parametrize("_", range(25))
|
||||||
|
def test_expand_path_expands_into_random_env_value_windows(_, random_test_var):
|
||||||
|
var_name, var_value = random_test_var[0], random_test_var[1]
|
||||||
|
assert expand_path(var_name) == var_name
|
||||||
|
assert expand_path(f"%{var_name}%") == var_value # windows
|
||||||
|
assert expand_path(f"%{var_name}%") == getenv(var_name)
|
||||||
|
|
||||||
|
|
||||||
|
@patch("jrnl.path.expand_path")
|
||||||
|
@patch("os.path.abspath")
|
||||||
|
def test_absolute_path(mock_abspath, mock_expand_path):
|
||||||
|
test_val = "test_value"
|
||||||
|
|
||||||
|
assert absolute_path(test_val) == mock_abspath.return_value
|
||||||
|
mock_expand_path.assert_called_with(test_val)
|
||||||
|
mock_abspath.assert_called_with(mock_expand_path.return_value)
|
Loading…
Add table
Reference in a new issue