72 lines
2.4 KiB
Python
72 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# Developer helper: validate the four MTConnect documents this agent produces
|
|
# against the official MTConnect 1.7 XSDs (plus the LinuxCNC extension schema for
|
|
# the streaming endpoints).
|
|
#
|
|
# Requires the `xmlschema` package (XSD 1.1; libxml2/xmllint cannot parse the
|
|
# 1.7 schema, which uses XSD-1.1 constructs). The official schemas are fetched
|
|
# from schemas.mtconnect.org unless a local directory is given via $MTC_XSD_DIR.
|
|
#
|
|
# pip install xmlschema
|
|
# ./validate_schemas.py [INI] # default: example.ini
|
|
#
|
|
# Exit status is non-zero if any document fails, so it can gate CI.
|
|
|
|
import io
|
|
import os
|
|
import sys
|
|
|
|
BASE = "http://schemas.mtconnect.org/schemas"
|
|
|
|
|
|
def _xsd(name):
|
|
d = os.environ.get("MTC_XSD_DIR")
|
|
return os.path.join(d, name) if d else "%s/%s" % (BASE, name)
|
|
|
|
|
|
def _bootstrap_mtc():
|
|
# mtc installs to $EMC2_HOME/lib/python (on PYTHONPATH under rip-environment);
|
|
# add it explicitly so this runs without the full environment.
|
|
home = os.environ.get("EMC2_HOME")
|
|
if home:
|
|
sys.path.insert(0, os.path.join(home, "lib", "python"))
|
|
|
|
|
|
def main(argv):
|
|
ini_path = argv[1] if len(argv) > 1 else "example.ini"
|
|
try:
|
|
import xmlschema
|
|
except ImportError:
|
|
print("error: needs the 'xmlschema' package (pip install xmlschema)")
|
|
return 2
|
|
|
|
_bootstrap_mtc()
|
|
from mtc.agent import AgentState, asset_dir
|
|
EXT_XSD = os.path.join(asset_dir(), "mtconnect-linuxcnc-1.xsd")
|
|
state = AgentState(ini_path)
|
|
state.poll_once()
|
|
docs = {
|
|
"MTConnectDevices_1.7.xsd": ("/probe", state.probe_document()),
|
|
"MTConnectAssets_1.7.xsd": ("/assets", state.assets_document()),
|
|
# Streams validate against the extension schema (which imports the base).
|
|
EXT_XSD: ("/current", state.current_document()),
|
|
}
|
|
ok = True
|
|
for xsd, (label, doc) in docs.items():
|
|
loc = xsd if xsd == EXT_XSD else _xsd(xsd)
|
|
schema = xmlschema.XMLSchema11(loc, validation="skip")
|
|
errors = list(schema.iter_errors(io.StringIO(doc)))
|
|
if errors:
|
|
ok = False
|
|
print("FAIL %s (%d errors)" % (label, len(errors)))
|
|
for e in errors[:8]:
|
|
print(" ", e.reason or e.message)
|
|
else:
|
|
base = "base" if xsd != EXT_XSD else "base+extension"
|
|
print("ok %s valid (%s)" % (label, base))
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv))
|