Use PyXDG to save config and journal in XDG dirs

This change also hides the CONFIG_PATH state information entirely within
the install module. Therefore, the cli module does not have to care about
checking existence of files and paths.
This commit is contained in:
Matthias Vogelgesang 2014-06-24 23:13:41 +02:00
parent fca3d131bd
commit afae3d16a7
4 changed files with 39 additions and 25 deletions

View file

@ -1,5 +1,5 @@
from behave import * from behave import *
from jrnl import cli, Journal, util from jrnl import cli, install, Journal, util
from dateutil import parser as date_parser from dateutil import parser as date_parser
import os import os
import sys import sys
@ -28,14 +28,14 @@ def _parse_args(command):
return nargs return nargs
def read_journal(journal_name="default"): def read_journal(journal_name="default"):
with open(cli.CONFIG_PATH) as config_file: with open(install.CONFIG_FILE_PATH) as config_file:
config = json.load(config_file) config = json.load(config_file)
with open(config['journals'][journal_name]) as journal_file: with open(config['journals'][journal_name]) as journal_file:
journal = journal_file.read() journal = journal_file.read()
return journal return journal
def open_journal(journal_name="default"): def open_journal(journal_name="default"):
with open(cli.CONFIG_PATH) as config_file: with open(install.CONFIG_FILE_PATH) as config_file:
config = json.load(config_file) config = json.load(config_file)
journal_conf = config['journals'][journal_name] journal_conf = config['journals'][journal_name]
if type(journal_conf) is dict: # We can override the default config on a by-journal basis if type(journal_conf) is dict: # We can override the default config on a by-journal basis
@ -47,7 +47,7 @@ def open_journal(journal_name="default"):
@given('we use the config "{config_file}"') @given('we use the config "{config_file}"')
def set_config(context, config_file): def set_config(context, config_file):
full_path = os.path.join("features/configs", config_file) full_path = os.path.join("features/configs", config_file)
cli.CONFIG_PATH = os.path.abspath(full_path) install.CONFIG_FILE_PATH = os.path.abspath(full_path)
@when('we run "{command}" and enter') @when('we run "{command}" and enter')
@when('we run "{command}" and enter "{inputs}"') @when('we run "{command}" and enter "{inputs}"')
@ -161,7 +161,7 @@ def check_journal_content(context, text, journal_name="default"):
@then('journal "{journal_name}" should not exist') @then('journal "{journal_name}" should not exist')
def journal_doesnt_exist(context, journal_name="default"): def journal_doesnt_exist(context, journal_name="default"):
with open(cli.CONFIG_PATH) as config_file: with open(install.CONFIG_FILE_PATH) as config_file:
config = json.load(config_file) config = json.load(config_file)
journal_path = config['journals'][journal_name] journal_path = config['journals'][journal_name]
assert not os.path.exists(journal_path) assert not os.path.exists(journal_path)
@ -175,7 +175,7 @@ def config_var(context, key, value, journal=None):
"int": int, "int": int,
"str": str "str": str
}[t](value) }[t](value)
with open(cli.CONFIG_PATH) as config_file: with open(install.CONFIG_FILE_PATH) as config_file:
config = json.load(config_file) config = json.load(config_file)
if journal: if journal:
config = config["journals"][journal] config = config["journals"][journal]

View file

@ -18,8 +18,6 @@ import os
import argparse import argparse
import sys import sys
xdg_config = os.environ.get('XDG_CONFIG_HOME')
CONFIG_PATH = os.path.join(xdg_config, "jrnl") if xdg_config else os.path.expanduser('~/.jrnl_config')
PYCRYPTO = install.module_exists("Crypto") PYCRYPTO = install.module_exists("Crypto")
@ -122,11 +120,7 @@ def run(manual_args=None):
print(util.py2encode(version_str)) print(util.py2encode(version_str))
sys.exit(0) sys.exit(0)
if not os.path.exists(CONFIG_PATH): config = install.install_jrnl()
config = install.install_jrnl(CONFIG_PATH)
else:
config = util.load_and_fix_json(CONFIG_PATH)
install.upgrade_config(config, CONFIG_PATH)
if args.ls: if args.ls:
print(util.py2encode(list_journals(config))) print(util.py2encode(list_journals(config)))
@ -235,18 +229,18 @@ def run(manual_args=None):
# Not encrypting to a separate file: update config! # Not encrypting to a separate file: update config!
if not args.encrypt: if not args.encrypt:
update_config(original_config, {"encrypt": True}, journal_name, force_local=True) update_config(original_config, {"encrypt": True}, journal_name, force_local=True)
install.save_config(original_config, CONFIG_PATH) install.save_config(original_config)
elif args.decrypt is not False: elif args.decrypt is not False:
decrypt(journal, filename=args.decrypt) decrypt(journal, filename=args.decrypt)
# Not decrypting to a separate file: update config! # Not decrypting to a separate file: update config!
if not args.decrypt: if not args.decrypt:
update_config(original_config, {"encrypt": False}, journal_name, force_local=True) update_config(original_config, {"encrypt": False}, journal_name, force_local=True)
install.save_config(original_config, CONFIG_PATH) install.save_config(original_config)
elif args.edit: elif args.edit:
if not config['editor']: if not config['editor']:
util.prompt("[You need to specify an editor in {0} to use the --edit function.]".format(CONFIG_PATH)) util.prompt("[You need to specify an editor in {0} to use the --edit function.]".format(install.CONFIG_FILE_PATH))
sys.exit(1) sys.exit(1)
other_entries = [e for e in old_entries if e not in journal.entries] other_entries = [e for e in old_entries if e not in journal.entries]
# Edit # Edit

View file

@ -7,9 +7,23 @@ import glob
import getpass import getpass
import json import json
import os import os
import xdg.BaseDirectory
from . import util from . import util
DEFAULT_CONFIG_NAME = 'jrnl.json'
DEFAULT_JOURNAL_NAME = 'journal.txt'
XDG_RESOURCE = 'jrnl'
USER_HOME = os.path.expanduser('~')
CONFIG_PATH = xdg.BaseDirectory.save_config_path(XDG_RESOURCE) or USER_HOME
CONFIG_FILE_PATH = os.path.join(CONFIG_PATH, DEFAULT_CONFIG_NAME)
JOURNAL_PATH = xdg.BaseDirectory.save_data_path(XDG_RESOURCE) or USER_HOME
JOURNAL_FILE_PATH = os.path.join(JOURNAL_PATH, DEFAULT_JOURNAL_NAME)
def module_exists(module_name): def module_exists(module_name):
"""Checks if a module exists and can be imported""" """Checks if a module exists and can be imported"""
try: try:
@ -21,7 +35,7 @@ def module_exists(module_name):
default_config = { default_config = {
'journals': { 'journals': {
"default": os.path.expanduser("~/journal.txt") "default": JOURNAL_FILE_PATH
}, },
'editor': os.getenv('VISUAL') or os.getenv('EDITOR') or "", 'editor': os.getenv('VISUAL') or os.getenv('EDITOR') or "",
'encrypt': False, 'encrypt': False,
@ -34,7 +48,7 @@ default_config = {
} }
def upgrade_config(config, config_path): def upgrade_config(config):
"""Checks if there are keys missing in a given config dict, and if so, updates the config file accordingly. """Checks if there are keys missing in a given config dict, and if so, updates the config file accordingly.
This essentially automatically ports jrnl installations if new config parameters are introduced in later This essentially automatically ports jrnl installations if new config parameters are introduced in later
versions.""" versions."""
@ -42,17 +56,22 @@ def upgrade_config(config, config_path):
if missing_keys: if missing_keys:
for key in missing_keys: for key in missing_keys:
config[key] = default_config[key] config[key] = default_config[key]
with open(config_path, 'w') as f: with open(CONFIG_FILE_PATH, 'w') as f:
json.dump(config, f, indent=2) json.dump(config, f, indent=2)
print("[.jrnl_conf updated to newest version]") print("[.jrnl_conf updated to newest version]")
def save_config(config, config_path): def save_config(config):
with open(config_path, 'w') as f: with open(CONFIG_FILE_PATH, 'w') as f:
json.dump(config, f, indent=2) json.dump(config, f, indent=2)
def install_jrnl(config_path): def install_jrnl():
if os.path.exists(CONFIG_FILE_PATH):
config = util.load_and_fix_json(CONFIG_FILE_PATH)
upgrade_config(config)
return config
def autocomplete(text, state): def autocomplete(text, state):
expansions = glob.glob(os.path.expanduser(os.path.expandvars(text))+'*') expansions = glob.glob(os.path.expanduser(os.path.expandvars(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]
@ -63,8 +82,8 @@ def install_jrnl(config_path):
readline.set_completer(autocomplete) readline.set_completer(autocomplete)
# Where to create the journal? # Where to create the journal?
path_query = 'Path to your journal file (leave blank for ~/journal.txt): ' path_query = 'Path to your journal file (leave blank for {}): '.format(JOURNAL_FILE_PATH)
journal_path = util.py23_input(path_query).strip() or os.path.expanduser('~/journal.txt') journal_path = util.py23_input(path_query).strip() or JOURNAL_FILE_PATH
default_config['journals']['default'] = os.path.expanduser(os.path.expandvars(journal_path)) default_config['journals']['default'] = os.path.expanduser(os.path.expandvars(journal_path))
# Encrypt it? # Encrypt it?
@ -90,7 +109,7 @@ def install_jrnl(config_path):
open(default_config['journals']['default'], 'a').close() # Touch to make sure it's there open(default_config['journals']['default'], 'a').close() # Touch to make sure it's there
# Write config to ~/.jrnl_conf # Write config to ~/.jrnl_conf
with open(config_path, 'w') as f: with open(CONFIG_FILE_PATH, 'w') as f:
json.dump(default_config, f, indent=2) json.dump(default_config, f, indent=2)
config = default_config config = default_config
if password: if password:

View file

@ -81,6 +81,7 @@ setup(
description = "A command line journal application that stores your journal in a plain text file", description = "A command line journal application that stores your journal in a plain text file",
packages = ['jrnl'], packages = ['jrnl'],
install_requires = [ install_requires = [
"pyxdg>=0.19",
"parsedatetime>=1.2", "parsedatetime>=1.2",
"pytz>=2013b", "pytz>=2013b",
"six>=1.6.1", "six>=1.6.1",