Completed
Push — develop ( e4f288...dec8f0 )
by Jace
02:13
created

yorm.load()   B

Complexity

Conditions 6

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.1979
Metric Value
cc 6
dl 0
loc 29
rs 7.5384
ccs 14
cts 17
cp 0.8235
crap 6.1979
1
"""Functions to work with files and data formats."""
2
3 1
import os
4 1
import shutil
5
6 1
import simplejson as json
0 ignored issues
show
Configuration introduced by
The import simplejson could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7 1
import yaml
0 ignored issues
show
Configuration introduced by
The import yaml could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8
9 1
from . import common, exceptions
10
11 1
log = common.logger(__name__)
12
13
14 1
def touch(path):
15
    """Ensure a file path exists."""
16 1
    if not os.path.exists(path):
17 1
        dirpath = os.path.dirname(path)
18 1
        if dirpath and not os.path.isdir(dirpath):
19 1
            log.trace("Creating directory '{}'...".format(dirpath))
20 1
            os.makedirs(dirpath)
21 1
        log.trace("Creating empty '{}'...".format(path))
22 1
        write("", path)
23
24
25 1
def read(path, encoding='utf-8'):
26
    """Read text from a file.
27
28
    :param path: file path to read from
29
    :param encoding: input file encoding
30
31
    :return: string contents of file
32
33
    """
34 1
    log.trace("Reading text from '{}'...".format(path))
35
36 1
    with open(path, 'r', encoding=encoding) as stream:
37 1
        text = stream.read()
38
39 1
    return text
40
41
42 1
def write(text, path, encoding='utf-8'):
43
    """Write text to a file.
44
45
    :param text: string
46
    :param path: file path to write text
47
    :param encoding: output file encoding
48
49
    :return: path of file
50
51
    """
52 1
    if text:
53 1
        log.trace("Writing text to '{}'...".format(path))
54
55 1
    with open(path, 'wb') as stream:
56 1
        data = text.encode(encoding)
57 1
        stream.write(data)
58
59 1
    return path
60
61
62 1
def stamp(path):
63
    """Get the modification timestamp from a file."""
64 1
    return os.path.getmtime(path)
65
66
67 1
def delete(path):
68
    """Delete a file or directory."""
69 1
    if os.path.isdir(path):
70 1
        try:
71 1
            log.trace("Deleting '{}'...".format(path))
72 1
            shutil.rmtree(path)
73
        except IOError:
74
            # bug: http://code.activestate.com/lists/python-list/159050
75
            msg = "Unable to delete: {}".format(path)
76
            log.warning(msg)
77 1
    elif os.path.isfile(path):
78 1
        log.trace("Deleting '{}'...".format(path))
79 1
        os.remove(path)
80
81
82 1
def load(text, path, ext='yml'):
83
    """Parse a dictionary a data from formatted text.
84
85
    :param text: string containing dumped data
86
    :param path: file path for error messages
87
88
    :return: dictionary of data
89
90
    """
91 1
    data = {}
92
93 1
    try:
94 1
        if ext in ['yml', 'yaml']:
95 1
            data = yaml.load(text) or {}
96 1
        elif ext in ['json']:
97 1
            data = json.loads(text) or {}
98 1
    except yaml.error.YAMLError as exc:
99 1
        msg = "Invalid YAML contents: {}:\n{}".format(path, exc)
100 1
        raise exceptions.ContentError(msg) from None
101
    except json.JSONDecodeError as exc:
102
        msg = "Invalid JSON contents: {}:\n{}".format(path, exc)
103
        raise exceptions.ContentError(msg) from None
104
105
    # Ensure data is a dictionary
106 1
    if not isinstance(data, dict):
107 1
        msg = "Invalid file contents: {}".format(path)
108 1
        raise exceptions.ContentError(msg)
109
110 1
    return data
111
112
113 1
def dump(data, ext):
114
    """Format a dictionary into a serialization format."""
115 1
    if ext in ['json']:
116 1
        return json.dumps(data, indent=4, sort_keys=True)
117
118 1
    if ext not in ['yml', 'yaml']:
119
        log.warning("Unrecognized file extension: %s", ext)
120
121
    return yaml.dump(data, default_flow_style=False, allow_unicode=True)
122