Completed
Pull Request — master (#125)
by Jasper
01:05
created

niprov.JsonFormat._strcust()   A

Complexity

Conditions 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 2
dl 0
loc 5
rs 9.4285
1
import json
2
import copy
3
from datetime import datetime, timedelta
4
from niprov.format import Format
5
6
7
class JsonFormat(Format):
8
    """Helper to convert provenance data to and from json encoded strings.
9
    """
10
11
    datetimeFields = ['acquired','created','added']
12
    timedeltaFields = ['duration']
13
14
    def __init__(self, dependencies):
15
        super(JsonFormat, self).__init__(dependencies)
16
        self.fileExtension = 'json'
17
        self.file = dependencies.getFileFactory()
18
19
    def serializeSingle(self, record):
20
        """
21
        Convert one provenance item from its native python dict type to
22
        a json string.
23
24
        Args:
25
            record (dict): The provenance item to convert.
26
27
        Returns:
28
            str: Json version of the provenance.
29
        """
30
        return json.dumps(self._deflate(record.provenance))
31
32
    def deserialize(self, jsonRecord):
33
        """
34
        Convert one provenance item from its json string version to the 
35
        native python dictionary format.
36
37
        Args:
38
            jsonRecord (str): The provenance item to convert as json-encoded 
39
                string.
40
41
        Returns:
42
            dict: Python dictionary of the provenance.
43
        """
44
        provenance = self._inflate(json.loads(jsonRecord))
45
        return self.file.fromProvenance(provenance)
46
47
    def serializeList(self, listOfRecords):
48
        """
49
        Convert a list of provenance items from its native list of python dict 
50
        type to a json string.
51
52
        Args:
53
            listOfRecords (list): The provenance items to convert.
54
55
        Returns:
56
            str: Json version of the provenance items.
57
        """
58
        flatRecords = [self._deflate(r.provenance) for r in listOfRecords]
59
        return json.dumps(flatRecords)
60
61
    def deserializeList(self, jsonListOfRecords):
62
        """
63
        Convert a list of provenance items from its json string version to the 
64
        a list of the native python dictionary format.
65
66
        Args:
67
            jsonListOfRecords (str): The provenance items to convert as 
68
                json-encoded string.
69
70
        Returns:
71
            list: Python list of dictionaries of the provenance.
72
        """
73
        flatRecords = json.loads(jsonListOfRecords)
74
        provenanceList = [self._inflate(r) for r in flatRecords]
75
        return [self.file.fromProvenance(p) for p in provenanceList]
76
77
    def _deflate(self, record):
78
        isoformat = "%Y-%m-%dT%H:%M:%S.%f"
79
        flatRecord = copy.deepcopy(record)
80
        for field in self.datetimeFields:
81
            if field in record:
82
                flatRecord[field] = record[field].strftime(isoformat)
83
        for field in self.timedeltaFields:
84
            if field in record:
85
                flatRecord[field] = record[field].total_seconds()
86
        if 'args' in record:
87
            flatRecord['args'] = [self._strcust(a) for a in record['args']]
88
        if 'kwargs' in record:
89
            kwargs = record['kwargs']
90
            flatRecord['kwargs'] = {k: self._strcust(kwargs[k]) 
91
                for k in kwargs.keys()}
92
        if '_id' in record:
93
            del flatRecord['_id']
94
        return flatRecord
95
96
    def _inflate(self, flatRecord):
97
        isoformat = "%Y-%m-%dT%H:%M:%S.%f"
98
        record = flatRecord
99
        for field in self.datetimeFields:
100
            if field in record:
101
                record[field] = datetime.strptime(record[field], isoformat)
102
        for field in self.timedeltaFields:
103
            if field in record:
104
                record[field] = timedelta(seconds=record[field])
105
        return record
106
107
    def _strcust(self, val):
108
        """Stringify an object that is not of a simple type."""
109
        if not isinstance(val, (str, unicode, int, float, bool, type(None))):
110
            return str(val)
111
        return val
112