Browse Source

Implement the BackendJson save method

Yann Weber 9 years ago
parent
commit
18695e3a72

+ 31
- 17
EditorialModel/backend/json_backend.py View File

@@ -9,17 +9,23 @@
9 9
 import json
10 10
 import datetime
11 11
 from Lodel.utils.mlstring import MlString
12
+import EditorialModel
12 13
 
13 14
 
14 15
 def date_cast(date):
15 16
     if len(date):
16
-        return datetime.datetime(date)
17
+        return datetime.datetime.strptime(date, '%c')
17 18
     else:
18 19
         return None
19 20
 
20 21
 
22
+## @brief dirty obsolote cast function
21 23
 def int_or_none(i):
22
-    if len(i):
24
+    if isinstance(i, int):
25
+        return i
26
+    elif i is None:
27
+        return None
28
+    elif len(i):
23 29
         return int(i)
24 30
     else:
25 31
         return None
@@ -47,27 +53,35 @@ class EmBackendJson(object):
47 53
     #
48 54
     # @param json_file str: path to the json_file used as data source
49 55
     def __init__(self, json_file):
50
-        with open(json_file) as json_data:
51
-            self.data = json.loads(json_data.read())
56
+        self.json_file = json_file
57
+        pass
58
+
59
+    @staticmethod
60
+    ## @brief Used by json.dumps to serialize date and datetime
61
+    def date_handler(obj):
62
+        return obj.strftime('%c') if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date) else None
63
+
52 64
 
53 65
     ## Loads the data in the data source json file
54 66
     #
55 67
     # @return list
56 68
     def load(self):
57 69
         data = {}
58
-        for index, component in self.data.items():
59
-            attributes = {}
60
-            for attr_name, attr_value in component.items():
61
-                if attr_name in EmBackendJson.cast_methods:
62
-                    attributes[attr_name] = EmBackendJson.cast_methods[attr_name](attr_value)
63
-                else:
64
-                    attributes[attr_name] = attr_value
65
-            data[int(index)] = attributes
70
+        with open(self.json_file) as json_data:
71
+            rdata = json.loads(json_data.read())
72
+            for index, component in rdata.items():
73
+                attributes = {}
74
+                for attr_name, attr_value in component.items():
75
+                    if attr_name in EmBackendJson.cast_methods:
76
+                        attributes[attr_name] = EmBackendJson.cast_methods[attr_name](attr_value)
77
+                    else:
78
+                        attributes[attr_name] = attr_value
79
+                data[int(index)] = attributes
66 80
         return data
67 81
 
68 82
     ## Saves the data in the data source json file
69
-    #
70
-    # @return bool
71
-    # @todo à implémenter
72
-    def save(self, em):
73
-        return True
83
+    # @param filename str : The filename to save the EM in (if None use self.json_file provided at init )
84
+    def save(self, em, filename = None):
85
+        with open(self.json_file if filename is None else filename, 'w') as fp:
86
+            fp.write(json.dumps({ component.uid : component.dumps() for component in em.components() }, default=self.date_handler))
87
+

+ 18
- 1
EditorialModel/components.py View File

@@ -56,7 +56,7 @@ class EmComponent(object):
56 56
     ## @brief Return a dict with attributes name as key and attributes value as value
57 57
     # @note Used at creation and deletion to call the migration handler
58 58
     def attr_dump(self):
59
-        return {fname: fval for fname, fval in self.__dict__.items() if not (fname.startswith('__') or (fname == 'uid'))}
59
+        return {fname: fval for fname, fval in self.__dict__.items() if not (fname.startswith('_') or (fname == 'uid'))}
60 60
 
61 61
     @property
62 62
     ## @brief Provide a uniq name
@@ -71,6 +71,23 @@ class EmComponent(object):
71 71
         uname += '_'+self.name
72 72
         return uname
73 73
         
74
+    ## @brief dumps attr for serialization
75
+    def dumps(self):
76
+        #attr =  {fname: fval for fname, fval in self.__dict__.items() if not (fname.startswith('_'))}
77
+        attr = self.attr_dump
78
+        del(attr['model'])
79
+        for attr_f in attr:
80
+            if isinstance(attr[attr_f], EmComponent):
81
+                attr[attr_f] = attr[attr_f].uid
82
+            elif isinstance(attr[attr_f], MlString):
83
+                attr[attr_f] = attr[attr_f].__str__()
84
+        if isinstance(self, EditorialModel.fields.EmField):
85
+            attr['component'] = 'EmField'
86
+            attr['type'] = self.fieldtype
87
+        else:
88
+            attr['component'] = self.__class__.__name__
89
+        return attr
90
+
74 91
     ## @brief This function has to be called after the instanciation, checks, and init manipulations are done
75 92
     # @note Create a new attribute _inited that allow __setattr__ to know if it has or not to call the migration handler
76 93
     def init_ended(self):

+ 3
- 1
EditorialModel/fields.py View File

@@ -22,7 +22,7 @@ class EmField(EmComponent):
22 22
     ## Instanciate a new EmField
23 23
     # @todo define and test type for icon and fieldtype
24 24
     # @warning nullable == True by default
25
-    def __init__(self, model, uid, name, fieldgroup_id, optional=False, internal=False, rel_field_id=None, icon='0', string=None, help_text=None, date_update=None, date_create=None, rank=None, nullable = True, default = None, uniq = False, **kwargs):
25
+    def __init__(self, model, uid, name, fieldgroup_id, fieldtype, optional=False, internal=False, rel_field_id=None, icon='0', string=None, help_text=None, date_update=None, date_create=None, rank=None, nullable = True, default = None, uniq = False, **kwargs):
26 26
 
27 27
         if self.ftype == None:
28 28
             raise NotImplementedError("Trying to instanciate an EmField and not one of the fieldtypes child classes")
@@ -37,7 +37,9 @@ class EmField(EmComponent):
37 37
         self.check_type('rel_field_id', (int, type(None)))
38 38
         self.icon = icon
39 39
 
40
+
40 41
         #Field type elements
42
+        self.fieldtype = fieldtype
41 43
         self.nullable = nullable
42 44
         self.default = default
43 45
         self.uniq = uniq

+ 7
- 3
EditorialModel/model.py View File

@@ -77,6 +77,7 @@ class Model(object):
77 77
                 if not 'type' in kwargs:
78 78
                     raise AttributeError("Missing 'type' from EmField instanciation")
79 79
                 cls = EditorialModel.fields.EmField.get_field_class(kwargs['type'])
80
+                kwargs['fieldtype'] = kwargs['type']
80 81
                 del(kwargs['type'])
81 82
             else:
82 83
                 cls = self.emclass_from_name(cls_name)
@@ -103,13 +104,16 @@ class Model(object):
103 104
             component.init_ended()
104 105
 
105 106
     ## Saves data using the current backend
106
-    def save(self):
107
-        return self.backend.save(self)
107
+    # @param filename str | None : if None use the current backend file (provided at backend instanciation)
108
+    def save(self, filename = None):
109
+        return self.backend.save(self, filename)
108 110
 
109 111
     ## Given a EmComponent child class return a list of instances
110 112
     # @param cls EmComponent : A python class
111 113
     # @return a list of instances or False if the class is not an EmComponent child
112
-    def components(self, cls):
114
+    def components(self, cls=None):
115
+        if cls is None:
116
+            return [ self.component(uid) for uid in self._components['uids'] ]
113 117
         key_name = self.name_from_emclass(cls)
114 118
         return False if key_name is False else self._components[key_name]
115 119
 

Loading…
Cancel
Save