Merge pull request #103 from maebert/tolerant-json

Tolerant json parsing
This commit is contained in:
Manuel Ebert 2013-11-04 09:39:39 -08:00
commit a30a28c401
6 changed files with 64 additions and 10 deletions

View file

@ -1,6 +1,10 @@
Changelog Changelog
========= =========
#### 1.6.1
* [Improved] Attempts to fix broken config files automatically
#### 1.6.0 #### 1.6.0
* [Improved] Passwords are now saved in the key-chain. The `password` field in `.jrnl_config` is soft-deprecated. * [Improved] Passwords are now saved in the key-chain. The `password` field in `.jrnl_config` is soft-deprecated.

View file

@ -0,0 +1,15 @@
{
"default_hour": 9,
"timeformat": "%Y-%m-%d %H:%M",
"linewrap": 80,
"encrypt": false,
"editor": "",
"default_minute": 0,
"highlight": true
"password": "",
"journals": {
"default": "features/journals/simple.journal"
"work": "features/journals/work.journal",
},
"tagsymbols": "@"
}

14
features/fix_json.feature Normal file
View file

@ -0,0 +1,14 @@
Feature: Fixing broken config files
Scenario: Loading a file with journal
Given we use the config "broken.json"
When we run "jrnl -n 2"
Then we should see the message "Some errors in your jrnl config have been fixed for you."
and the output should be
"""
2013-06-09 15:39 My first entry.
| Everything is alright
2013-06-10 15:40 Life is good.
| But I'm better.
"""

View file

@ -7,7 +7,7 @@ jrnl is a simple journal application for your command line.
""" """
__title__ = 'jrnl' __title__ = 'jrnl'
__version__ = '1.6.0-dev' __version__ = '1.6.1-dev'
__author__ = 'Manuel Ebert' __author__ = 'Manuel Ebert'
__license__ = 'MIT License' __license__ = 'MIT License'
__copyright__ = 'Copyright 2013 Manuel Ebert' __copyright__ = 'Copyright 2013 Manuel Ebert'

View file

@ -22,8 +22,6 @@ import tempfile
import subprocess import subprocess
import argparse import argparse
import sys import sys
try: import simplejson as json
except ImportError: import json
xdg_config = os.environ.get('XDG_CONFIG_HOME') 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') CONFIG_PATH = os.path.join(xdg_config, "jrnl") if xdg_config else os.path.expanduser('~/.jrnl_config')
@ -123,13 +121,7 @@ def cli(manual_args=None):
if not os.path.exists(CONFIG_PATH): if not os.path.exists(CONFIG_PATH):
config = install.install_jrnl(CONFIG_PATH) config = install.install_jrnl(CONFIG_PATH)
else: else:
with open(CONFIG_PATH) as f: config = util.load_and_fix_json(CONFIG_PATH)
try:
config = json.load(f)
except ValueError as e:
util.prompt("[There seems to be something wrong with your jrnl config at {0}: {1}]".format(CONFIG_PATH, e.message))
util.prompt("[Entry was NOT added to your journal]")
sys.exit(1)
install.upgrade_config(config, config_path=CONFIG_PATH) install.upgrade_config(config, config_path=CONFIG_PATH)
original_config = config.copy() original_config = config.copy()

View file

@ -6,6 +6,9 @@ from tzlocal import get_localzone
import getpass as gp import getpass as gp
import keyring import keyring
import pytz import pytz
try: import simplejson as json
except ImportError: import json
import re
PY3 = sys.version_info[0] == 3 PY3 = sys.version_info[0] == 3
PY2 = sys.version_info[0] == 2 PY2 = sys.version_info[0] == 2
@ -88,3 +91,29 @@ def get_local_timezone():
if not __cached_tz or __cached_tz not in pytz.all_timezones_set: if not __cached_tz or __cached_tz not in pytz.all_timezones_set:
__cached_tz = "UTC" __cached_tz = "UTC"
return __cached_tz return __cached_tz
def load_and_fix_json(json_path):
"""Tries to load a json object from a file.
If that fails, tries to fix common errors (no or extra , at end of the line).
"""
with open(json_path) as f:
json_str = f.read()
config = fixed = None
try:
return json.loads(json_str)
except ValueError as e:
# Attempt to fix extra ,
json_str = re.sub(r",[ \n]*}", "}", json_str)
# Attempt to fix missing ,
json_str = re.sub(r"([^{,]) *\n *(\")", r"\1,\n \2", json_str)
try:
config = json.loads(json_str)
with open(json_path, 'w') as f:
json.dump(config, f, indent=2)
prompt("[Some errors in your jrnl config have been fixed for you.]")
return config
except ValueError as e:
prompt("[There seems to be something wrong with your jrnl config at {0}: {1}]".format(json_path, e.message))
prompt("[Entry was NOT added to your journal]")
sys.exit(1)