1 ## This file is part of Crapvine.
3 ## Copyright (C) 2007 Andrew Sayman <lorien420@myrealbox.com>
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.
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
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
):
32 def boolean(self
, name
, default
=False):
33 if self
.attrs
.has_key(name
):
34 bool_val
= self
.attrs
.get(name
)
37 elif bool_val
== 'no':
40 raise 'Boolean xml field set to invalid value |%s|' % (bool_val
)
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
)
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
)
69 for attr
in getattr(self
, 'required_attrs', []):
70 if attrs
.has_key(attr
):
71 setattr(self
, attr
, unescape(attrs
.get(attr
)))
72 required_matched
.append(attr
)
73 if getattr(self
, 'required_attrs', []) != required_matched
:
74 raise AttributeError('Some required attributes were not found!')
75 for attr
in getattr(self
, 'text_attrs', []):
76 if attrs
.has_key(attr
):
77 setattr(self
, attr
, unescape(attrs
.get(attr
)))
78 for attr
in getattr(self
, 'number_as_text_attrs', []):
79 if attrs
.has_key(attr
):
80 setattr(self
, attr
, unescape(attrs
.get(attr
)))
81 for attr
in getattr(self
, 'date_attrs', []):
82 if attrs
.has_key(attr
):
83 setattr(self
, attr
, unescape(attrs
.get(attr
)))
84 for attr
in getattr(self
, 'bool_attrs', []):
85 setattr(self
, attr
, r
.b(attr
))
87 def __attr_default(self
, name
):
88 return getattr(self
.__class
__, name
).default
== getattr(self
, name
)
90 def get_attrs_xml(self
):
92 attrs_strs
.extend(['%s=%s' % (name
, quoteattr(self
[name
])) for name
in getattr(self
, 'required_attrs', []) if not self
.__attr
_default
(name
)])
93 attrs_strs
.extend(['%s=%s' % (name
, quoteattr(self
[name
])) for name
in getattr(self
, 'text_attrs', []) if not self
.__attr
_default
(name
)])
94 attrs_strs
.extend(['%s=%s' % (name
, quoteattr(getattr(self
, name
))) for name
in getattr(self
, 'number_as_text_attrs', []) if not self
.__attr
_default
(name
)])
95 attrs_strs
.extend(['%s=%s' % (name
, quoteattr(str(self
[name
]))) for name
in getattr(self
, 'date_attrs', []) if not self
.__attr
_default
(name
)])
96 for bool_attr
in getattr(self
, 'bool_attrs', []):
97 if not self
.__attr
_default
(bool_attr
):
98 my_bool
= 'yes' if self
[bool_attr
] else 'no'
99 attrs_strs
.append('%s="%s"' % (bool_attr
, my_bool
))
100 return ' '.join(attrs_strs
)
102 def __setitem__(self
, name
, value
):
103 return setattr(self
, name
, value
)
104 def __getitem__(self
, name
):
105 return getattr(self
, name
)
107 class AttributedListModel(Attributed
, gtk
.GenericTreeModel
):
108 __metaclass__
= classmaker()
111 Attributed
.__init
__(self
)
112 gtk
.GenericTreeModel
.__init
__(self
)
113 def get_item(self
, index
):
114 return self
.list[index
]
115 def get_item_from_path(self
, path
):
116 return self
.list[path
[0]]
117 def on_get_flags(self
):
118 return gtk
.TREE_MODEL_LIST_ONLY
119 def on_get_n_columns(self
):
120 return len(self
.column_attrs
)
121 def on_get_column_type(self
, index
):
122 return self
.column_attr_types
[index
]
123 def on_get_path(self
, iter):
124 if len(self
.list) == 0:
127 def on_get_iter(self
, path
):
128 if len(self
.list) == 0:
131 def on_get_value(self
, index
, column
):
132 if len(self
.list) == 0:
134 list = self
.list[index
]
135 return list[self
.column_attrs
[column
]]
136 def on_iter_next(self
, index
):
137 if index
>= (len(self
.list) - 1):
140 def on_iter_children(self
, node
):
142 def on_iter_has_child(self
, node
):
144 def on_iter_n_children(self
, iter):
147 return len(self
.list)
148 def on_iter_nth_child(self
, parent
, n
):
157 def on_iter_parent(self
, node
):
163 self
.chronicle_loader
= None
165 def load_from_file(self
, filename
):
166 from chronicle_loader
import ChronicleLoader
167 self
.filename
= filename
168 self
.chronicle_loader
= ChronicleLoader()
170 parser
= sax2exts
.make_parser()
171 parser
.setFeature(feature_namespaces
, 0)
172 parser
.setContentHandler(self
.chronicle_loader
)
173 parser
.setProperty(property_lexical_handler
, self
.chronicle_loader
)
175 parser
.parse(self
.filename
)
177 def save_contents_to_file(self
, filename
):
178 all_character_xml
= [c
.get_xml(' ') for c
in self
.loader
.chronicle_loader
.vampires
.values()]
179 out
= ['<?xml version="1.0"?>',
180 '<grapevine version="3">']
181 out
.extend(all_character_xml
)
182 out
.append('</grapevine>')
183 with
file(filename
, 'w') as f
:
184 f
.write("\n".join(out
))