comparison env/lib/python3.9/site-packages/planemo/xml/validation.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """Module describing abstractions for validating XML content."""
2 import abc
3 import subprocess
4 from collections import namedtuple
5
6 from galaxy.tool_util.deps.commands import which
7 from galaxy.util import unicodify
8 try:
9 from lxml import etree
10 except ImportError:
11 etree = None
12 from six import add_metaclass
13
14 XMLLINT_COMMAND = "xmllint --noout --schema {0} {1} 2>&1"
15 INSTALL_VALIDATOR_MESSAGE = ("This feature requires an external dependency "
16 "to function, pleaes install xmllint (e.g 'brew "
17 "install libxml2' or 'apt-get install "
18 "libxml2-utils'.")
19
20
21 @add_metaclass(abc.ABCMeta)
22 class XsdValidator(object):
23 """Class allowing validation of XML files against XSD schema."""
24
25 @abc.abstractmethod
26 def validate(self, schema_path, target_path):
27 """Validate ``target_path`` against ``schema_path``.
28
29 :return type: ValidationResult
30 """
31
32 @abc.abstractmethod
33 def enabled(self):
34 """Return True iff system has dependencies for this validator.
35
36 :return type: bool
37 """
38
39
40 ValidationResult = namedtuple("ValidationResult", ["passed", "output"])
41
42
43 class LxmlValidator(XsdValidator):
44 """Validate XSD files using lxml library."""
45
46 def validate(self, schema_path, target_path):
47 try:
48 xsd_doc = etree.parse(schema_path)
49 xsd = etree.XMLSchema(xsd_doc)
50 xml = etree.parse(target_path)
51 passed = xsd.validate(xml)
52 return ValidationResult(passed, xsd.error_log)
53 except etree.XMLSyntaxError as e:
54 return ValidationResult(False, unicodify(e))
55
56 def enabled(self):
57 return etree is not None
58
59
60 class XmllintValidator(XsdValidator):
61 """Validate XSD files with the external tool xmllint."""
62
63 def validate(self, schema_path, target_path):
64 command = XMLLINT_COMMAND.format(schema_path, target_path)
65 p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
66 stdout, _ = p.communicate()
67 passed = p.returncode == 0
68 return ValidationResult(passed, stdout)
69
70 def enabled(self):
71 return bool(which("xmllint"))
72
73
74 VALIDATORS = [LxmlValidator(), XmllintValidator()]
75
76
77 def get_validator(require=True):
78 """Return a :class:`XsdValidator` object based on available dependencies."""
79 for validator in VALIDATORS:
80 if validator.enabled():
81 return validator
82
83 if require:
84 raise Exception(INSTALL_VALIDATOR_MESSAGE)
85
86 return None
87
88
89 __all__ = (
90 "get_validator",
91 "XsdValidator",
92 )