a little nicer wrt pep8
[sfa.git] / sfa / storage / record.py
1
2
3 from sfa.util.sfatime import utcparse, datetime_to_string
4 from datetime import datetime
5 from sfa.util.xml import XML
6 from sfa.trust.gid import GID
7
8 from sfa.util.sfalogging import logger
9
10
11 class Record:
12
13     def __init__(self, dict=None, xml_str=None):
14         if dict:
15             self.load_from_dict(dict)
16         elif xml_str:
17             xml = XML(xml_str)
18             xml_dict = xml.todict()
19             self.load_from_dict(xml_dict)
20
21     def get_field(self, field):
22         return self.__dict__.get(field, None)
23
24     # xxx fixme
25     # turns out the date_created field is received by the client as a 'created' int
26     # (and 'last_updated' does not make it at all)
27     # let's be flexible
28     def date_repr(self, fields):
29         if not isinstance(fields, list):
30             fields = [fields]
31         for field in fields:
32             value = getattr(self, field, None)
33             if isinstance(value, datetime):
34                 return datetime_to_string(value)
35             elif isinstance(value, (int, float)):
36                 return datetime_to_string(utcparse(value))
37         # fallback
38         return "** undef_datetime **"
39
40     #
41     # need to filter out results, esp. wrt relationships
42     # exclude_types must be a tuple so we can use isinstance
43     #
44     def record_to_dict(self, exclude_types=None):
45         if exclude_types is None:
46             exclude_types = ()
47         d = self.__dict__
48
49         def exclude(k, v):
50             return k.startswith('_') or isinstance(v, exclude_types)
51         keys = [k for k, v in list(d.items()) if not exclude(k, v)]
52         return {k: d[k] for k in keys}
53
54     def toxml(self):
55         return self.save_as_xml()
56
57     def load_from_dict(self, d):
58         for (k, v) in d.items():
59             # experimental
60             if isinstance(v, str) and v.lower() in ['true']:
61                 v = True
62             if isinstance(v, str) and v.lower() in ['false']:
63                 v = False
64             setattr(self, k, v)
65
66     # in addition we provide convenience for converting to and from xml records
67     # for this purpose only, we need the subclasses to define 'fields' as either
68     # a list or a dictionary
69     def fields(self):
70         fields = list(self.__dict__.keys())
71         return fields
72
73     def save_as_xml(self):
74         # xxx not sure about the scope here
75         input_dict = dict([(key, getattr(self, key))
76                            for key in self.fields() if getattr(self, key, None)])
77         xml_record = XML("<record />")
78         xml_record.parse_dict(input_dict)
79         return xml_record.toxml()
80
81     def dump(self, format=None, dump_parents=False, sort=False):
82         if not format:
83             format = 'text'
84         else:
85             format = format.lower()
86         if format == 'text':
87             self.dump_text(dump_parents, sort=sort)
88         elif format == 'xml':
89             print(self.save_as_xml())
90         elif format == 'simple':
91             print(self.dump_simple())
92         else:
93             raise Exception("Invalid format %s" % format)
94
95     def dump_text(self, dump_parents=False, sort=False):
96         print(40 * '=')
97         print("RECORD")
98         # print remaining fields
99         fields = self.fields()
100         if sort:
101             fields.sort()
102         for attrib_name in fields:
103             attrib = getattr(self, attrib_name)
104             # skip internals
105             if attrib_name.startswith('_'):
106                 continue
107             # skip callables
108             if callable(attrib):
109                 continue
110             # handle gid
111             if attrib_name == 'gid':
112                 print("    gid:")
113                 print(GID(string=attrib).dump_string(8, dump_parents))
114             elif attrib_name in ['date created', 'last updated']:
115                 print("    %s: %s" % (attrib_name, self.date_repr(attrib_name)))
116             else:
117                 print("    %s: %s" % (attrib_name, attrib))
118
119     def dump_simple(self):
120         return "%s" % self