yorm.diskutils._parse_json()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.5

Importance

Changes 0
Metric Value
cc 2
eloc 6
nop 2
dl 0
loc 6
ccs 3
cts 6
cp 0.5
crap 2.5
rs 10
c 0
b 0
f 0
1
"""Functions to work with files and data formats."""
2
3 1
import os
4 1
import shutil
5 1
import logging
6
7 1
import simplejson as json
8 1
import yaml
9
10 1
from . import exceptions
11
12 1
log = logging.getLogger(__name__)
13
14
15 1
def exists(path):
16
    """Determine if a path exists."""
17 1
    return os.path.exists(path)
18
19
20 1
def touch(path):
21
    """Ensure a file path exists."""
22 1
    if not os.path.exists(path):
23 1
        dirpath = os.path.dirname(path)
24 1
        if dirpath and not os.path.isdir(dirpath):
25 1
            log.trace("Creating directory '{}'...".format(dirpath))
26 1
            os.makedirs(dirpath)
27 1
        log.trace("Creating empty '{}'...".format(path))
28 1
        write("", path)
29
30
31 1
def read(path, encoding='utf-8'):
32
    """Read text from a file.
33
34
    :param path: file path to read from
35
    :param encoding: input file encoding
36
37
    :return: string contents of file
38
39
    """
40 1
    log.trace("Reading text from '{}'...".format(path))
41
42 1
    with open(path, 'r', encoding=encoding) as stream:
43 1
        text = stream.read()
44
45 1
    return text
46
47
48 1
def write(text, path, encoding='utf-8'):
49
    """Write text to a file.
50
51
    :param text: string
52
    :param path: file path to write text
53
    :param encoding: output file encoding
54
55
    :return: path of file
56
57
    """
58 1
    if text:
59 1
        log.trace("Writing text to '{}'...".format(path))
60
61 1
    with open(path, 'wb') as stream:
62 1
        data = text.encode(encoding)
63 1
        stream.write(data)
64
65 1
    return path
66
67
68 1
def stamp(path):
69
    """Get the modification timestamp from a file."""
70 1
    return os.path.getmtime(path)
71
72
73 1
def delete(path):
74
    """Delete a file or directory."""
75 1
    if os.path.isdir(path):
76 1
        try:
77 1
            log.trace("Deleting '{}'...".format(path))
78 1
            shutil.rmtree(path)
79
        except IOError:
80
            # bug: http://code.activestate.com/lists/python-list/159050
81
            msg = "Unable to delete: {}".format(path)
82
            log.warning(msg)
83 1
    elif os.path.isfile(path):
84 1
        log.trace("Deleting '{}'...".format(path))
85 1
        os.remove(path)
86
87
88 1
def parse(text, path):
89
    """Parse a dictionary of data from formatted text.
90
91
    :param text: string containing dumped data
92
    :param path: file path to specify formatting
93
94
    :return: dictionary of data
95
96
    """
97 1
    ext = _get_ext(path)
98 1
    if ext in ['json']:
99 1
        data = _parse_json(text, path)
100 1
    elif ext in ['yml', 'yaml']:
101 1
        data = _parse_yaml(text, path)
102
    else:
103
        log.warning("Unrecognized file extension (.%s), assuming YAML", ext)
104
        data = _parse_yaml(text, path)
105
106 1
    if not isinstance(data, dict):
107 1
        msg = "Invalid file contents: {}".format(path)
108 1
        raise exceptions.FileContentError(msg)
109
110 1
    return data
111
112
113 1
def _parse_json(text, path):
114 1
    try:
115 1
        return json.loads(text) or {}
116
    except json.JSONDecodeError:
117
        msg = "Invalid JSON contents: {}:\n{}".format(path, text)
118
        raise exceptions.FileContentError(msg)
119
120
121 1
def _parse_yaml(text, path):
122 1
    try:
123 1
        return yaml.load(text) or {}
124 1
    except yaml.error.YAMLError:
125 1
        msg = "Invalid YAML contents: {}:\n{}".format(path, text)
126 1
        raise exceptions.FileContentError(msg)
127
128
129 1
def dump(data, path):
130
    """Format a dictionary into a serialization format.
131
132
    :param text: dictionary of data to format
133
    :param path: file path to specify formatting
134
135
    :return: string of formatted data
136
137
    """
138 1
    ext = _get_ext(path)
139
140 1
    if ext in ['json']:
141 1
        return json.dumps(data, indent=4, sort_keys=True)
142
143 1
    if ext not in ['yml', 'yaml']:
144
        log.warning("Unrecognized file extension (.%s), assuming YAML", ext)
145
146 1
    return yaml.dump(data, default_flow_style=False, allow_unicode=True)
147
148
149 1
def _get_ext(path):
150 1
    if '.' in path:
151 1
        return path.split('.')[-1].lower()
152
    else:
153
        return 'yml'
154