Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/tools/build_config/schemaCheck.py
169673 views
1
#!/usr/bin/env python
2
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
# Copyright (C) 2009-2025 German Aerospace Center (DLR) and others.
4
# This program and the accompanying materials are made available under the
5
# terms of the Eclipse Public License 2.0 which is available at
6
# https://www.eclipse.org/legal/epl-2.0/
7
# This Source Code may also be made available under the following Secondary
8
# Licenses when the conditions for such availability set forth in the Eclipse
9
# Public License 2.0 are satisfied: GNU General Public License, version 2
10
# or later which is available at
11
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
14
# @file schemaCheck.py
15
# @author Daniel Krajzewicz
16
# @author Michael Behrisch
17
# @author Jakob Erdmann
18
# @date 03.12.2009
19
20
"""
21
Checks schema for files matching certain file names using either
22
lxml or SAX2Count.exe depending on availability.
23
"""
24
from __future__ import absolute_import
25
from __future__ import print_function
26
27
import os
28
import sys
29
import subprocess
30
import glob
31
import traceback
32
try:
33
from urllib.request import unquote
34
except ImportError:
35
from urllib import unquote
36
try:
37
from lxml import etree
38
haveLxml = True
39
schemes = {}
40
except ImportError:
41
haveLxml = False
42
43
44
def validate(root, f):
45
root = os.path.abspath(root)
46
normalized = os.path.abspath(f)[len(root) + 1:].replace('\\', '/')
47
try:
48
if os.path.getsize(f) < 80:
49
# this is probably a texttest place holder file
50
# it is definitely too small to contain a schema
51
return
52
doc = etree.parse(f)
53
schemaLoc = doc.getroot().get(
54
'{http://www.w3.org/2001/XMLSchema-instance}noNamespaceSchemaLocation')
55
if schemaLoc and '/xsd/' in schemaLoc:
56
localSchema = os.path.join(os.path.dirname(
57
__file__), '..', '..', 'data', schemaLoc[schemaLoc.find('/xsd/') + 1:])
58
if os.path.exists(localSchema):
59
schemaLoc = localSchema
60
# if schemaLoc not in schemes: // temporarily disabled due to lxml bug
61
# https://bugs.launchpad.net/lxml/+bug/1222132
62
schemes[schemaLoc] = etree.XMLSchema(etree.parse(schemaLoc))
63
schemes[schemaLoc].validate(doc)
64
for entry in schemes[schemaLoc].error_log:
65
s = unquote(str(entry))
66
# remove everything before (and including) the filename
67
s = s[s.find(f.replace('\\', '/')) + len(f):]
68
print(normalized + s, file=sys.stderr)
69
except Exception as e:
70
print("Error on parsing '%s'!" % normalized, file=sys.stderr)
71
if haveLxml and type(e) is etree.XMLSyntaxError:
72
# we expect to encounter such errors and don't need a full strack trace
73
print(e, file=sys.stderr)
74
else:
75
traceback.print_exc()
76
77
78
def main(srcRoot, toCheck, err):
79
if not toCheck:
80
toCheck = ["*.edg.xml", "*.nod.xml", "*.con.xml", "*.typ.xml",
81
"*.net.xml", "*.rou.xml", "*.add.xml", "*.????cfg",
82
"net.netgen", "net.netconvert",
83
"net.scenario", "tls.scenario",
84
"routes.duarouter", "alts.duarouter", "routes.jtrrouter", "routes.marouter",
85
"vehroutes.sumo", "vehroutes.sumo.meso", "trips.od2trips",
86
"*.turns.xml"]
87
sax2count = "SAX2Count.exe"
88
if 'XERCES_64' in os.environ:
89
sax2count = os.path.join(os.environ['XERCES_64'], "bin", sax2count)
90
elif 'XERCES' in os.environ:
91
sax2count = os.path.join(os.environ['XERCES'], "bin", sax2count)
92
93
fileNo = 0
94
if os.path.exists(srcRoot):
95
if os.path.isdir(srcRoot):
96
for root, dirs, _ in os.walk(srcRoot):
97
for pattern in toCheck:
98
for name in glob.glob(os.path.join(root, pattern)):
99
if haveLxml:
100
validate(srcRoot, name)
101
elif os.name != "posix":
102
subprocess.call(sax2count + " " + name, stdout=open(os.devnull), stderr=err)
103
fileNo += 1
104
if '.svn' in dirs:
105
dirs.remove('.svn')
106
else:
107
if haveLxml:
108
validate("", srcRoot)
109
elif os.name != "posix":
110
subprocess.call(
111
sax2count + " " + srcRoot, stdout=open(os.devnull), stderr=err)
112
fileNo += 1
113
else:
114
print("cannot open", srcRoot, file=err)
115
return 1
116
print("%s files checked" % fileNo)
117
return 0
118
119
120
if __name__ == "__main__":
121
if os.name == "posix" and not haveLxml:
122
print("neither SAX2Count nor lxml available, exiting", file=sys.stderr)
123
sys.exit(1)
124
srcRoot = "."
125
if len(sys.argv) > 1:
126
srcRoot = sys.argv[1]
127
if "$SUMO_HOME" in srcRoot:
128
srcRoot = srcRoot.replace("$SUMO_HOME",
129
os.path.join(os.path.dirname(__file__), '..', '..'))
130
toCheck = None
131
if len(sys.argv) > 2:
132
toCheck = sys.argv[2].split(",")
133
sys.exit(main(srcRoot, toCheck, sys.stderr))
134
135