~fluidity-core/fluidity/embedded_models

« back to all changes in this revision

Viewing changes to libspud/diamond/diamond/scherror.py

  • Committer: Timothy Bond
  • Date: 2011-04-14 15:40:24 UTC
  • Revision ID: timothy.bond@imperial.ac.uk-20110414154024-116ci9gq6mwigmaw
Following the move from svn to bzr we change the nature of inclusion of these
four software libraries. Previously, they were included as svn externals and
pulled at latest version for trunk, pinned to specific versions for release
and stable trunk. Since bzr is less elegant at dealing with externals we have
made the decision to include the packages directly into the trunk instead.

At this import the versions are:

libadaptivity: r163
libvtkfortran: r67
libspud: r545
libmba2d: r28

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
 
 
3
#    This file is part of Diamond.
 
4
#
 
5
#    Diamond 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
#    Diamond 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.
 
14
#
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with Diamond.  If not, see <http://www.gnu.org/licenses/>.
 
17
 
 
18
import debug
 
19
import pango
 
20
import gobject
 
21
import gtk
 
22
import gtk.glade
 
23
import sys
 
24
import tempfile
 
25
import os
 
26
import re
 
27
 
 
28
import dialogs
 
29
import interface
 
30
 
 
31
class DiamondSchemaError:
 
32
  def __init__(self, parent, gladefile, schema_file, schematron_file):
 
33
    self.parent = parent
 
34
    self.gladefile = gladefile
 
35
    self.schema_file = schema_file
 
36
    self.schematron_file = schematron_file
 
37
    self.errlist_type = 0
 
38
    self.listview = None
 
39
 
 
40
    self.listwindow = self.parent.gui.get_widget("errListWindow")
 
41
    self.listview = self.parent.gui.get_widget("sch_err_list")
 
42
 
 
43
    if self.listwindow is None or self.listview is None:
 
44
      raise Exception("Could not find the error list widgets")
 
45
 
 
46
    self.model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
 
47
    self.cellcombo = gtk.CellRendererCombo()
 
48
    self.cellcombo.set_property("model", self.model)
 
49
    self.cellcombo.set_property("editable", False)
 
50
 
 
51
    column_renderer = gtk.CellRendererText()
 
52
    column_renderer.set_property("editable", False)
 
53
    column_xpath = gtk.TreeViewColumn("Element", column_renderer, text = 0)
 
54
    column_error = gtk.TreeViewColumn("Error", column_renderer, text = 1)
 
55
 
 
56
    self.listview.append_column(column_xpath)
 
57
    self.listview.append_column(column_error)
 
58
 
 
59
    column_xpath.set_property("expand", True)
 
60
    column_xpath.set_resizable(True)
 
61
    column_xpath.set_property("min-width", 75)
 
62
 
 
63
    column_error.set_property("expand", True)
 
64
    column_error.set_resizable(True)
 
65
    column_error.set_property("min-width", 75)
 
66
 
 
67
    # Set adjustment parameters for the list view
 
68
    self.listview.set_model(self.model)
 
69
    self.listview.connect("row_activated", self.on_xml_row_activate)
 
70
 
 
71
    # User can only select one error at a time to go to.
 
72
    self.listview.get_selection().set_mode(gtk.SELECTION_SINGLE)
 
73
 
 
74
    self.listview.hide()
 
75
    self.listwindow.hide()
 
76
 
 
77
  # Create the error list, model and tree view columns if the list does not exist.
 
78
  def create_error_list(self):
 
79
    if self.listview is not None:
 
80
      return
 
81
 
 
82
  # Destroy the error list widgets
 
83
  def destroy_error_list(self):
 
84
    if self.listview is not None:
 
85
      self.listview.hide()
 
86
      self.listwindow.hide()
 
87
 
 
88
  def on_validate(self, widget=None):
 
89
    """
 
90
    Tools > Validate XML. This writes out the XML to a temporary file, then calls
 
91
    xmllint on it. (I didn't use the Xvif validation capabilities because the error
 
92
    messages are worse than useless; xmllint actually gives line numbers and such).
 
93
    """
 
94
 
 
95
    if self.schema_file is None:
 
96
      dialogs.error(self.parent.main_window, "No schema file open")
 
97
      return
 
98
 
 
99
    self.tmp = tempfile.NamedTemporaryFile()
 
100
    self.parent.tree.write(self.tmp.name)
 
101
 
 
102
    std_input, std_output, std_error = os.popen3("xmllint --relaxng %s %s --noout --path \".\"" % (self.schema_file, self.tmp.name))
 
103
    output = std_error.read()
 
104
 
 
105
    output = output.replace("%s fails to validate" % self.tmp.name, "")
 
106
 
 
107
    if output.strip() == "%s validates" % self.tmp.name:
 
108
      # No errors. Close the error list (if it is open) and display a congratulatory message box.
 
109
      self.destroy_error_list()
 
110
      dialogs.message_box(self.parent.main_window, "XML file validated successfully", "Validation successful")
 
111
    else:
 
112
      self.create_error_list()
 
113
 
 
114
      self.errlist_type = 1
 
115
      self.model.clear()
 
116
 
 
117
      lines = output.split("\n")
 
118
 
 
119
      # Read the temporary output file, split it by lines and use it to convert
 
120
      # line numbers to xpaths for the column data.
 
121
      f = file(self.tmp.name)
 
122
      data = f.read()
 
123
      output_lines = data.split("\n")
 
124
 
 
125
      for line in lines:
 
126
        if len(line) == 0:
 
127
          continue
 
128
 
 
129
        tokens = line.split(" ")
 
130
 
 
131
        # Parse each line of the xmllint --relaxng output.
 
132
        # FORMAT:
 
133
        # ELEMENT:LINE: element NAME:  Relax-NG validity error : ERROR MESSAGE
 
134
        # (Capitals denotes variable data). Update the following code if the output changes.
 
135
        sub_tokens = tokens[0].split(":")
 
136
 
 
137
        message = " ".join(tokens[7:])
 
138
 
 
139
        line = sub_tokens[1]
 
140
        xpath = self.add_to_xpath(output_lines, "", long(line)-1)
 
141
 
 
142
        self.model.append([ xpath, message ])
 
143
 
 
144
      self.listview.set_property("visible", True)
 
145
      self.listwindow.set_property("visible", True)
 
146
 
 
147
      # Update the status bar. Inform the user of the number of errors.
 
148
      self.parent.statusbar.set_statusbar("There are %u Relax-NG errors in the document" % len(lines))
 
149
 
 
150
    return
 
151
 
 
152
  def on_validate_schematron(self, widget=None):
 
153
    """
 
154
    Tools > Validate Schematron. This uses the etree.Schematron API, if it exists, to
 
155
    validate the document tree against a supplied schematron file.
 
156
    """
 
157
 
 
158
    if self.schematron_file is None:
 
159
      dialogs.error(self.parent.main_window, "No schematron file supplied")
 
160
      return
 
161
 
 
162
    # Write the current version out to file.
 
163
    tmp = tempfile.NamedTemporaryFile()
 
164
    self.parent.tree.write(tmp.name)
 
165
    std_input, std_output, err_output = os.popen3("xmllint --schematron %s %s --noout" % (self.schematron_file, tmp.name))
 
166
    output = err_output.read()
 
167
 
 
168
    output = output.replace("%s fails to validate" % tmp.name, "")
 
169
    output = output.strip()
 
170
 
 
171
    if output == "%s validates" % tmp.name:
 
172
      self.destroy_error_list()
 
173
      dialogs.message_box(self.parent.main_window, "XML file validated successfully against %s" % self.schematron_file, "XML validation successful")
 
174
 
 
175
    # Clear the list, as there may still be errors from a previous schematron validation.
 
176
    self.model.clear()
 
177
    self.errlist_type = 0
 
178
 
 
179
    # Add each line of output as a new row.
 
180
    lines = output.split("\n")
 
181
 
 
182
    for line in lines:
 
183
      if len(line) == 0:
 
184
        continue
 
185
 
 
186
    tokens = line.split(" ")
 
187
    self.model.append([ tokens[0], " ".join(tokens[3:]), 0 ])
 
188
 
 
189
    # Finish set up of list view widget.
 
190
    self.listview.set_property("visible", True)
 
191
    self.listwindow.set_property("visible", True)
 
192
    self.parent.statusbar.set_statusbar("There are %u Schematron errors in the document" % len(lines))
 
193
 
 
194
  def errlist_is_open(self):
 
195
    return self.listview.get_property("visible")
 
196
 
 
197
  def get_elem_name(self, line):
 
198
    xml = re.compile("<([/?!]?\w+)", re.VERBOSE)
 
199
    matches = xml.findall(line)
 
200
 #   print "get_elem_name", line, "=", matches[0]
 
201
    return matches[0]
 
202
 
 
203
  def add_to_xpath(self, lines, xpath, line_no):
 
204
 
 
205
    line = lines[line_no].strip()
 
206
    name = self.get_elem_name(line)
 
207
 
 
208
    if name not in ["string_value", "integer_value", "real_value"]:
 
209
      xpath = "/" + name + xpath
 
210
 
 
211
    # Are we at the start of the document?
 
212
    if line_no == 0 or line_no == 1:
 
213
      return xpath
 
214
 
 
215
    # Find the parent node.
 
216
    while 1:
 
217
      line_no = line_no - 1
 
218
      line = lines[line_no].strip()
 
219
 
 
220
#      print "MAIN LOOP: ", line
 
221
 
 
222
      # Skip past comments
 
223
      if line.find("-->") != -1:
 
224
        while line.find("<!--") == -1:
 
225
          line_no = line_no - 1
 
226
          line = lines[line_no].strip()
 
227
        continue
 
228
 
 
229
      if line.startswith("</"):
 
230
        name = line.strip("<>/")
 
231
        while line.find("<%s" % (name)) == -1:
 
232
#          print "BACK LOOP: ", line
 
233
          line_no = line_no - 1
 
234
          line = lines[line_no].strip()
 
235
        continue
 
236
 
 
237
      name = self.get_elem_name(line)
 
238
      if name.find("<%s />" % (name)) == -1 and name.find("</ %s>" % (name)):
 
239
        return self.add_to_xpath(lines, xpath, line_no)
 
240
 
 
241
  def scroll_to_xpath(self, xpath):
 
242
    iter = self.parent.get_treestore_iter_from_xmlpath(xpath)
 
243
    path = self.parent.treestore.get_path(iter)
 
244
    self.parent.treeview.expand_to_path(path)
 
245
    self.parent.treeview.get_selection().select_iter(iter)
 
246
    self.parent.treeview.scroll_to_cell(path, use_align=True, col_align=0.5)
 
247
 
 
248
  # Signal handlers
 
249
  def on_xml_row_activate(self, treeview, path, view_column):
 
250
 
 
251
    # Get the selected row.
 
252
    selection = treeview.get_selection()
 
253
    (model, iter) = selection.get_selected()
 
254
 
 
255
    # Get the line number
 
256
    xpath = model.get_value(iter, 0)
 
257
 
 
258
    # Use the in-memory schema representation to get the XPath from the name.
 
259
    self.scroll_to_xpath(xpath)