Working to reverse the binary format
[crapvine.git] / grapevine_xml.py
blob97f98c497392528acf6314748e842b3fcfc79f89
1 ## This file is part of Crapvine.
2 ##
3 ## Copyright (C) 2007 Andrew Sayman <lorien420@myrealbox.com>
4 ##
5 ## Crapvine is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or
8 ## (at your option) any later version.
9 ##
10 ## Crapvine is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ## GNU General Public License for more details.
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from __future__ import with_statement
19 import gtk
20 from xml.sax.saxutils import quoteattr, unescape
21 from xml.sax import sax2exts
22 from xml.sax.handler import feature_namespaces, property_lexical_handler
23 from dateutil.parser import parse
24 from datetime import datetime
26 from attribute import AttributeBuilder, classmaker
28 class AttributeReader:
29 def __init__(self, attrs):
30 self.attrs = attrs
32 def boolean(self, name, default=False):
33 if self.attrs.has_key(name):
34 bool_val = self.attrs.get(name)
35 if bool_val == 'yes':
36 return True
37 elif bool_val == 'no':
38 return False
39 else:
40 raise AttributeError('Boolean xml field set to invalid value |%s|' % (bool_val))
41 return False
42 def b(self, name, default=False):
43 return self.boolean(name, default)
45 def text(self, name, default=''):
46 if self.attrs.has_key(name):
47 return self.attrs.get(name)
48 return default
49 def t(self, name, default=''):
50 return self.text(name, default)
52 def number_as_text(self, name, default='0'):
53 # Should eventually verify that it's a number
54 return text(name, default)
55 def nat(self, name, default='0'):
56 return self.number_as_text(name, default)
58 def date(self, name, default='unknown'):
59 # Should eventually parse the date?
60 return text(name, default)
61 def d(self, name, default='unknown'):
62 return self.date(name, default)
64 class Attributed(object):
65 __metaclass__ = AttributeBuilder
66 def read_attributes(self, attrs):
67 r = AttributeReader(attrs)
68 for attr in attrs.keys():
69 if hasattr(self, attr):
70 setattr(self, attr, unescape(attrs.get(attr)))
72 def __attr_default(self, name):
73 return getattr(self.__class__, name).default == getattr(self, name)
75 def __get_attrs_names(self, attrs):
76 list = getattr(self, attrs, [])
77 ret_list = []
78 for elem in list:
79 if isinstance(elem, tuple):
80 ret_list.append(elem[0])
81 else:
82 ret_list.append(elem)
83 return ret_list
84 def __get_required_attrs(self):
85 return self.__get_attrs_names('required_attrs')
86 def __get_text_attrs(self):
87 return self.__get_attrs_names('text_attrs')
88 def __get_number_as_text_attrs(self):
89 return self.__get_attrs_names('number_as_text_attrs')
90 def __get_date_attrs(self):
91 return self.__get_attrs_names('date_attrs')
92 def __get_bool_attrs(self):
93 return self.__get_attrs_names('bool_attrs')
95 def get_attrs_xml(self):
96 attrs_strs = []
97 attrs_strs.extend(['%s=%s' % (name, quoteattr(self[name])) for name in self.__get_required_attrs() if not self.__attr_default(name)])
98 attrs_strs.extend(['%s=%s' % (name, quoteattr(self[name])) for name in self.__get_text_attrs() if not self.__attr_default(name)])
99 attrs_strs.extend(['%s=%s' % (name, quoteattr(getattr(self, name))) for name in self.__get_number_as_text_attrs() if not self.__attr_default(name)])
100 attrs_strs.extend(['%s=%s' % (name, quoteattr(str(self[name]))) for name in self.__get_date_attrs() if not self.__attr_default(name)])
101 for bool_attr in self.__get_bool_attrs():
102 if not self.__attr_default(bool_attr):
103 my_bool = 'yes' if self[bool_attr] else 'no'
104 attrs_strs.append('%s="%s"' % (bool_attr, my_bool))
105 return ' '.join(attrs_strs)
107 def __setitem__(self, name, value):
108 return setattr(self, name, value)
109 def __getitem__(self, name):
110 return getattr(self, name)
112 class AttributedListModel(Attributed, gtk.GenericTreeModel):
113 __metaclass__ = classmaker()
115 def __init__(self):
116 Attributed.__init__(self)
117 gtk.GenericTreeModel.__init__(self)
118 def get_item(self, index):
119 return self.list[index]
120 def get_item_from_path(self, path):
121 return self.list[path[0]]
122 def on_get_flags(self):
123 return gtk.TREE_MODEL_LIST_ONLY
124 def on_get_n_columns(self):
125 return len(self.column_attrs)
126 def on_get_column_type(self, index):
127 return self.column_attr_types[index]
128 def on_get_path(self, iter):
129 if len(self.list) == 0:
130 return None
131 return (iter, )
132 def on_get_iter(self, path):
133 if len(self.list) == 0:
134 return None
135 return path[0]
136 def on_get_value(self, index, column):
137 if len(self.list) == 0:
138 return None
139 list = self.list[index]
140 return list[self.column_attrs[column]]
141 def on_iter_next(self, index):
142 if index >= (len(self.list) - 1):
143 return None
144 return index + 1
145 def on_iter_children(self, node):
146 return None
147 def on_iter_has_child(self, node):
148 return False
149 def on_iter_n_children(self, iter):
150 if iter:
151 return 0
152 return len(self.list)
153 def on_iter_nth_child(self, parent, n):
154 if parent:
155 return None
156 try:
157 self.list[n]
158 except IndexError:
159 return None
160 else:
161 return n
162 def on_iter_parent(self, node):
163 return None
165 class GEX(object):
166 def __init__(self):
167 self.filename = None
168 self.chronicle_loader = None
170 def load_from_file(self, filename):
171 from chronicle_loader import ChronicleLoader
172 self.filename = filename
173 self.chronicle_loader = ChronicleLoader()
175 parser = sax2exts.make_parser()
176 parser.setFeature(feature_namespaces, 0)
177 parser.setContentHandler(self.chronicle_loader)
178 parser.setProperty(property_lexical_handler, self.chronicle_loader)
179 print parser
180 parser.parse(self.filename)
182 def save_contents_to_file(self, filename):
183 all_character_xml = [c.get_xml(' ') for c in self.chronicle_loader.vampires.values()]
184 out = ['<?xml version="1.0"?>',
185 '<grapevine version="3">']
186 out.extend(all_character_xml)
187 out.append('</grapevine>')
188 with file(filename, 'w') as f:
189 f.write("\n".join(out))