~reducedmodelling/fluidity/ROM_Non-intrusive-ann

« back to all changes in this revision

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

  • Committer: fangf at ac
  • Date: 2012-11-06 12:21:31 UTC
  • mto: This revision was merged to the branch mainline in revision 3989.
  • Revision ID: fangf@imperial.ac.uk-20121106122131-u2zvt7fxc1r3zeou
updated

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
from lxml import etree
 
19
import os
 
20
import os.path
 
21
import debug
 
22
import sys
 
23
import copy
 
24
import urllib2
 
25
 
 
26
def preprocess(schemafile):
 
27
  p = etree.XMLParser(remove_comments=True)
 
28
  ns = 'http://relaxng.org/ns/structure/1.0'
 
29
 
 
30
  if 'http' in schemafile:
 
31
    schemafile_handle = urllib2.urlopen(schemafile)
 
32
  else:
 
33
    schemafile_handle = open(schemafile)
 
34
  
 
35
  try:
 
36
        tree = etree.parse(schemafile_handle, p)
 
37
  except Exception:
 
38
        debug.deprint("Error: %s is not a valid Relax NG schema" % schemafile, 0)
 
39
        sys.exit(1)
 
40
 
 
41
  #
 
42
  # deal with include
 
43
  #
 
44
  includes = tree.xpath('/t:grammar//t:include', namespaces={'t': ns})
 
45
 
 
46
  for include in includes:
 
47
    include_parent = include.getparent()
 
48
    include_index = list(include_parent).index(include)
 
49
 
 
50
    # find the file
 
51
    file = None
 
52
    filename = include.attrib["href"]
 
53
    possible_files = [os.path.join(os.path.dirname(schemafile), filename), filename]
 
54
    possible_files.append(os.path.join("/data/src/fluidity/fluidity_enkf_reduced_new/libspud/../share/spud", filename))
 
55
    possible_files.append(os.path.join(os.path.dirname(__file__) + "/../../schema", filename))
 
56
 
 
57
    for possible_file in possible_files:
 
58
      try:
 
59
        if 'http' in possible_file:
 
60
          file = urllib2.urlopen(possible_file)
 
61
        else:
 
62
          file = open(possible_file)
 
63
        break
 
64
      except IOError:
 
65
        debug.deprint("IOError when searching for included file " + filename, 1)
 
66
 
 
67
    if file is None:
 
68
      debug.deprint("Error: could not locate included file %s" % filename, 0)
 
69
      debug.deprint("Path: %s" % possible_files)
 
70
      sys.exit(1)
 
71
 
 
72
    # parse the included xml file and steal all the nodes
 
73
    include_tree = etree.parse(file, p)
 
74
    nodes_to_take = include_tree.xpath('/t:grammar/*', namespaces={'t': ns})
 
75
 
 
76
    # here's where the magic happens:
 
77
    for node in nodes_to_take:
 
78
      include_parent.insert(include_index, copy.deepcopy(node))
 
79
 
 
80
    # now delete the include:
 
81
    include_parent.remove(include)
 
82
 
 
83
  grammar_list = tree.xpath('/t:grammar', namespaces={'t': ns})
 
84
  
 
85
  # If the .rnc didn't include a start = prefix, then no valid
 
86
  # grammar tag will be present. Let the user know.
 
87
  
 
88
  if len(grammar_list) == 0:
 
89
                debug.deprint("Error: No grammar tag present in schema.", 0)
 
90
                sys.exit(1)
 
91
 
 
92
  grammar = grammar_list[0]
 
93
 
 
94
  defines = {}
 
95
  define_nodes = tree.xpath('/t:grammar//t:define', namespaces={'t': ns})
 
96
 
 
97
  #
 
98
  # deal with combine="interleave"
 
99
  #
 
100
 
 
101
  # first, fetch all the plain definitions
 
102
  for define in define_nodes:
 
103
    if "combine" not in define.attrib:
 
104
      name = define.attrib["name"]
 
105
      defines[name] = define
 
106
 
 
107
  # now look for interleaves with those
 
108
  for define in define_nodes:
 
109
    if "combine" in define.attrib and define.attrib["combine"] == "interleave":
 
110
      name = define.attrib["name"]
 
111
      if name not in defines:
 
112
        defines[name] = define
 
113
      else:
 
114
        matching_defn = defines[name]
 
115
        for child in define:
 
116
          matching_defn.append(copy.deepcopy(child))
 
117
  
 
118
  #
 
119
  # deal with combine="choice"
 
120
  #
 
121
  combine_names = []
 
122
  for define in define_nodes:
 
123
    if "combine" in define.attrib and define.attrib["combine"] == "choice":
 
124
      name = define.attrib["name"]
 
125
      combine_names.append(name)
 
126
 
 
127
  combine_names = list(set(combine_names))
 
128
  for name in combine_names:
 
129
    xpath = tree.xpath('/t:grammar//t:define[@name="%s"]' % name, namespaces={'t': ns})
 
130
    choices = []
 
131
    for node in xpath:
 
132
      choices = choices + list(node)
 
133
    define = etree.Element("define")
 
134
    define.attrib["name"] = name
 
135
    choice = etree.Element("choice")
 
136
    define.append(choice)
 
137
    for x in choices:
 
138
      choice.append(x)
 
139
    defines[name] = define
 
140
 
 
141
  # delete all the define nodes from the xml
 
142
  for define in define_nodes:
 
143
    parent = define.getparent()
 
144
    parent.remove(define)
 
145
  
 
146
  # add the modified defines back to the grammar
 
147
  for define in defines.values():
 
148
    grammar.append(define)
 
149
 
 
150
  return etree.tostring(tree, xml_declaration=True, encoding='utf-8', pretty_print=True)
 
151
 
 
152
if __name__ == "__main__":
 
153
  import sys
 
154
  schemafile = sys.argv[1]
 
155
  newfile = schemafile.replace(".rng", ".pp.rng")
 
156
  f = open(newfile, "w")
 
157
  f.write(preprocess(schemafile))