Fin de refactorización
This commit is contained in:
parent
9db7d96a06
commit
fdd44d72ff
263
yasd.py
263
yasd.py
|
@ -16,7 +16,14 @@ class YASD:
|
||||||
YASD actions performer.
|
YASD actions performer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def do(action="check", indata=None, outfile=None, quiet=False, log=False):
|
def do(
|
||||||
|
action="check",
|
||||||
|
indata=None,
|
||||||
|
outfile=None,
|
||||||
|
quiet=False,
|
||||||
|
log=False,
|
||||||
|
stdout=False,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Performs YASD actions directly.
|
Performs YASD actions directly.
|
||||||
|
|
||||||
|
@ -31,17 +38,27 @@ class YASD:
|
||||||
:type quiet: True or False
|
:type quiet: True or False
|
||||||
:param log: If messages are write in a file or not; 'False' by default
|
:param log: If messages are write in a file or not; 'False' by default
|
||||||
:type log: True or False
|
:type log: True or False
|
||||||
|
:param stdout: if conversion goes to stdout or not; 'False' by default
|
||||||
|
:type stdout: True or False
|
||||||
|
:return: Output data; str on 'document'; bs4.element.Tag on 'convert'
|
||||||
|
or 'sample'; YAML dict on 'check'
|
||||||
|
:rtype: str or bs4.element.Tag or dict
|
||||||
"""
|
"""
|
||||||
yasd = YASD(indata, outfile, quiet, log)
|
yasd = YASD(indata, outfile, quiet, log, stdout)
|
||||||
yasd.msgr.run(f"action_{action}")
|
yasd.msgr.run(f"action_{action}")
|
||||||
if action == "convert":
|
match action:
|
||||||
yasd.convert(stdout=True)
|
case "document":
|
||||||
elif action == "sample":
|
return yasd.document()
|
||||||
yasd.sample(stdout=True)
|
case "convert":
|
||||||
elif action == "document":
|
return yasd.convert()
|
||||||
yasd.document(stdout=True)
|
case "sample":
|
||||||
|
return yasd.sample()
|
||||||
|
case "check":
|
||||||
|
return yasd.yaml
|
||||||
|
|
||||||
def __init__(self, indata=None, outfile=None, quiet=False, log=False):
|
def __init__(
|
||||||
|
self, indata=None, outfile=None, quiet=False, log=False, stdout=False
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Inits YASD object.
|
Inits YASD object.
|
||||||
|
|
||||||
|
@ -55,56 +72,83 @@ class YASD:
|
||||||
:type log: True or False
|
:type log: True or False
|
||||||
"""
|
"""
|
||||||
self.msgr = YASDMessenger(quiet=quiet, log=log)
|
self.msgr = YASDMessenger(quiet=quiet, log=log)
|
||||||
|
self.outfile = YASDCheck.file(outfile, self.msgr)
|
||||||
self.yaml = YASDCheck(indata, self.msgr).yaml
|
self.yaml = YASDCheck(indata, self.msgr).yaml
|
||||||
self.formatter = XMLFormatter(indent=2)
|
self.formatter = XMLFormatter(indent=2)
|
||||||
self.outfile = outfile
|
self.stdout = stdout
|
||||||
self.xsd = None
|
|
||||||
self.out = ""
|
|
||||||
|
|
||||||
def convert(self, stdout=False):
|
def convert(self):
|
||||||
"""
|
"""
|
||||||
Converts YASD to XSD.
|
Converts YASD to XSD.
|
||||||
|
|
||||||
:param stdout: if conversion goes to stdout or not; 'False' by default
|
:return: XSD element
|
||||||
:type stdout: True or False
|
:rtype: bs4.element.Tag
|
||||||
"""
|
"""
|
||||||
|
self.xsd = YASDXSD(self.yaml, self.msgr).xsd
|
||||||
|
return self.__output(self.xsd)
|
||||||
|
|
||||||
|
def sample(self):
|
||||||
|
"""
|
||||||
|
Generates XML sample from YASD.
|
||||||
|
|
||||||
|
:return: XML element
|
||||||
|
:rtype: bs4.element.Tag
|
||||||
|
"""
|
||||||
|
self.xml = YASDXML(self.yaml, self.msgr).xml
|
||||||
|
return self.__output(self.xml, extname=".xml")
|
||||||
|
|
||||||
|
def document(self):
|
||||||
|
"""
|
||||||
|
Generates RST documentation.
|
||||||
|
|
||||||
|
:return: RST document
|
||||||
|
:rtype: str
|
||||||
|
"""
|
||||||
|
self.rst = YASDRST(self.yaml, self.msgr).rst
|
||||||
|
return self.__output(self.rst, extname=".rst")
|
||||||
|
|
||||||
|
def __output(self, outdata, extname=".xsd"):
|
||||||
|
"""
|
||||||
|
Prints in the terminal or writes into a file.
|
||||||
|
|
||||||
|
:return: Output data; str if outdata comes from YASDRST; otherwise
|
||||||
|
bs4.element.Tag
|
||||||
|
:rtype: str or bs4.element.Tag
|
||||||
|
"""
|
||||||
|
if self.stdout:
|
||||||
|
if type(outdata) is not str:
|
||||||
|
outdata = outdata.prettify(formatter=self.formatter)
|
||||||
|
if self.outfile is None:
|
||||||
|
print(outdata)
|
||||||
|
else:
|
||||||
|
suffix = self.outfile.suffix
|
||||||
|
if len(suffix) > 0 and suffix == suffix.replace(" ", ""):
|
||||||
|
extname = suffix
|
||||||
|
filename = f"{self.outfile.stem}{extname}"
|
||||||
|
filename = Path(self.outfile.parent / filename)
|
||||||
|
filename.write_text(outdata)
|
||||||
|
return outdata
|
||||||
|
|
||||||
|
|
||||||
|
class YASDXSD:
|
||||||
|
"""
|
||||||
|
YASD convertor to XSD.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO refactor so it fits XSD grammar, cfr. reference:
|
||||||
|
# https://www.w3schools.com/xml/schema_elements_ref.asp
|
||||||
|
|
||||||
|
def __init__(self, yml=None, messenger=None):
|
||||||
|
"""
|
||||||
|
Inits YASD convertor.
|
||||||
|
"""
|
||||||
|
self.msgr = YASDCheck.messenger(messenger)
|
||||||
|
self.yaml = YASDCheck.yaml(yml, self.msgr)
|
||||||
|
self.xsd = BeautifulSoup(parser="xml")
|
||||||
self.__build_schema()
|
self.__build_schema()
|
||||||
self.__build_elements()
|
self.__build_elements()
|
||||||
self.__build_attributes()
|
self.__build_attributes()
|
||||||
self.__build_groups()
|
self.__build_groups()
|
||||||
self.__stringify_xsd()
|
|
||||||
if stdout:
|
|
||||||
self.__output()
|
|
||||||
else:
|
|
||||||
return self.out
|
|
||||||
|
|
||||||
def sample(self, stdout=False):
|
|
||||||
"""
|
|
||||||
Generates XML sample from YASD.
|
|
||||||
|
|
||||||
:param stdout: if sample goes to stdout or not; 'False' by default
|
|
||||||
:type stdout: True or False
|
|
||||||
"""
|
|
||||||
# TODO XML sample
|
|
||||||
self.out = "XML sample"
|
|
||||||
if stdout:
|
|
||||||
self.__output()
|
|
||||||
else:
|
|
||||||
return self.out
|
|
||||||
|
|
||||||
def document(self, stdout=False):
|
|
||||||
"""
|
|
||||||
Generates RST documentation.
|
|
||||||
|
|
||||||
:param stdout: if document goes to stdout or not; 'False' by default
|
|
||||||
:type stdout: True or False
|
|
||||||
"""
|
|
||||||
# TODO RST document
|
|
||||||
self.out = f"RST document from :{self.__dict__}"
|
|
||||||
if stdout:
|
|
||||||
self.__output()
|
|
||||||
else:
|
|
||||||
return self.out
|
|
||||||
|
|
||||||
def __build_schema(self):
|
def __build_schema(self):
|
||||||
"""
|
"""
|
||||||
|
@ -112,7 +156,6 @@ class YASD:
|
||||||
"""
|
"""
|
||||||
for key in ["version", "schemaLocation"]:
|
for key in ["version", "schemaLocation"]:
|
||||||
del self.yaml["schema"][key]
|
del self.yaml["schema"][key]
|
||||||
self.xsd = BeautifulSoup(parser="xml")
|
|
||||||
schema = self.xsd.new_tag("schema", nsprefix="xs")
|
schema = self.xsd.new_tag("schema", nsprefix="xs")
|
||||||
schema["xmlns:xs"] = "http://www.w3.org/2001/XMLSchema"
|
schema["xmlns:xs"] = "http://www.w3.org/2001/XMLSchema"
|
||||||
for key, val in self.yaml["schema"].items():
|
for key, val in self.yaml["schema"].items():
|
||||||
|
@ -152,8 +195,6 @@ class YASD:
|
||||||
:param dict el: YASD element
|
:param dict el: YASD element
|
||||||
:param str tag: tag name for XSD node
|
:param str tag: tag name for XSD node
|
||||||
"""
|
"""
|
||||||
# TODO fix according to 'attribute', 'element' and 'simpleType' refs
|
|
||||||
# https://www.w3schools.com/xml/schema_elements_ref.asp
|
|
||||||
element = self.xsd.new_tag(tag, nsprefix="xs")
|
element = self.xsd.new_tag(tag, nsprefix="xs")
|
||||||
if "default" in el.keys() and "fixed" in el.keys():
|
if "default" in el.keys() and "fixed" in el.keys():
|
||||||
del el["fixed"]
|
del el["fixed"]
|
||||||
|
@ -172,8 +213,6 @@ class YASD:
|
||||||
|
|
||||||
:param dict el: YASD element
|
:param dict el: YASD element
|
||||||
"""
|
"""
|
||||||
# TODO fix according to 'element' and 'complexType' refs
|
|
||||||
# https://www.w3schools.com/xml/schema_elements_ref.asp
|
|
||||||
element = self.__build_complex_root(el)
|
element = self.__build_complex_root(el)
|
||||||
complex_type = self.__build_complex_type(el)
|
complex_type = self.__build_complex_type(el)
|
||||||
self.__add_references(complex_type, el, is_attr=True)
|
self.__add_references(complex_type, el, is_attr=True)
|
||||||
|
@ -313,32 +352,86 @@ class YASD:
|
||||||
del el["description"]
|
del el["description"]
|
||||||
return el
|
return el
|
||||||
|
|
||||||
def __stringify_xsd(self):
|
|
||||||
"""
|
|
||||||
Converts BeautifulSoups to pretty text format.
|
|
||||||
"""
|
|
||||||
self.out = self.xsd.prettify(formatter=self.formatter)
|
|
||||||
|
|
||||||
def __output(self, extname=".xsd"):
|
class YASDXML:
|
||||||
|
"""
|
||||||
|
YASD sampler to XML.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO XML Sample
|
||||||
|
|
||||||
|
def __init__(self, yml=None, messenger=None):
|
||||||
"""
|
"""
|
||||||
Prints in the terminal or writes into a file.
|
Inits YASD sampler.
|
||||||
"""
|
"""
|
||||||
if self.outfile is None:
|
self.msgr = YASDCheck.messenger(messenger)
|
||||||
print(self.out)
|
self.yaml = YASDCheck.yaml(yml, self.msgr)
|
||||||
else:
|
self.xml = "XML sample"
|
||||||
suffix = self.outfile.suffix
|
|
||||||
if len(suffix) > 0 and suffix == suffix.replace(" ", ""):
|
|
||||||
extname = suffix
|
class YASDRST:
|
||||||
filename = f"{self.outfile.stem}{extname}"
|
"""
|
||||||
filename = Path(self.outfile.parent / filename)
|
YASD document generator to RST.
|
||||||
filename.write_text(self.out)
|
"""
|
||||||
|
|
||||||
|
# TODO RST document
|
||||||
|
|
||||||
|
def __init__(self, yml=None, messenger=None):
|
||||||
|
"""
|
||||||
|
Inits YASD document generator.
|
||||||
|
"""
|
||||||
|
self.msgr = YASDCheck.messenger(messenger)
|
||||||
|
self.yaml = YASDCheck.yaml(yml, self.msgr)
|
||||||
|
self.rst = "RST document"
|
||||||
|
|
||||||
|
|
||||||
class YASDCheck:
|
class YASDCheck:
|
||||||
"""
|
"""
|
||||||
YASD input validator.
|
YASD validator.
|
||||||
|
|
||||||
|
Validates everything related to YASD classes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def messenger(msgr=None):
|
||||||
|
"""
|
||||||
|
Verifies if messenger was initialize.
|
||||||
|
|
||||||
|
:param messenger: Messenger object
|
||||||
|
:type messenger: None or YASDMessenger
|
||||||
|
"""
|
||||||
|
if msgr is None:
|
||||||
|
return YASDMessenger()
|
||||||
|
else:
|
||||||
|
return msgr
|
||||||
|
|
||||||
|
def yaml(yml=None, msgr=None):
|
||||||
|
"""
|
||||||
|
Verifies if yaml exists.
|
||||||
|
|
||||||
|
:param dict yml: YAML object
|
||||||
|
:param msgr: Messenger object
|
||||||
|
:type msgr: None or YASDMessenger
|
||||||
|
"""
|
||||||
|
msgr = YASDCheck.messenger(msgr)
|
||||||
|
if yml is None or type(yml) is not dict:
|
||||||
|
msgr.run("no_yaml", level="error")
|
||||||
|
else:
|
||||||
|
return yml
|
||||||
|
|
||||||
|
def file(filepath=None, msgr=None):
|
||||||
|
"""
|
||||||
|
Verififes if file exists.
|
||||||
|
|
||||||
|
:param filepath: File path
|
||||||
|
:type filepath: None or Path
|
||||||
|
"""
|
||||||
|
msgr = YASDCheck.messenger(msgr)
|
||||||
|
if type(filepath).__module__ != "pathlib":
|
||||||
|
msgr.run("no_input", level="error")
|
||||||
|
elif not filepath.exists() or not filepath.is_file():
|
||||||
|
msgr.run("invalid_input", level="error", file=filepath)
|
||||||
|
return filepath.resolve()
|
||||||
|
|
||||||
def __init__(self, indata=None, messenger=None):
|
def __init__(self, indata=None, messenger=None):
|
||||||
"""
|
"""
|
||||||
Inits YASD validator.
|
Inits YASD validator.
|
||||||
|
@ -348,29 +441,13 @@ class YASDCheck:
|
||||||
:param messenger: Object for print or save messages
|
:param messenger: Object for print or save messages
|
||||||
:type messenger: None or YASDMessenger
|
:type messenger: None or YASDMessenger
|
||||||
"""
|
"""
|
||||||
if messenger is None:
|
self.msgr = YASDCheck.messenger(messenger)
|
||||||
self.msgr = YASDMessenger()
|
|
||||||
else:
|
|
||||||
self.msgr = messenger
|
|
||||||
if type(indata) is dict:
|
if type(indata) is dict:
|
||||||
self.yaml = indata
|
self.yaml = indata
|
||||||
else:
|
else:
|
||||||
self.yaml = self.parse_file(self.check_file(indata))
|
self.yaml = self.parse_file(YASDCheck.file(indata, self.msgr))
|
||||||
self.check_structure()
|
self.check_structure()
|
||||||
|
|
||||||
def check_file(self, filepath):
|
|
||||||
"""
|
|
||||||
Verifies YASD file.
|
|
||||||
|
|
||||||
:param filepath: YASD file path
|
|
||||||
:type filepath: None or Path
|
|
||||||
"""
|
|
||||||
if type(filepath).__module__ != "pathlib":
|
|
||||||
self.msgr.run("no_input", level="error")
|
|
||||||
elif not filepath.exists() or not filepath.is_file():
|
|
||||||
self.msgr.run("invalid_input", level="error", file=filepath)
|
|
||||||
return filepath.resolve()
|
|
||||||
|
|
||||||
def parse_file(self, filepath):
|
def parse_file(self, filepath):
|
||||||
"""
|
"""
|
||||||
Attempts YASD file parsing.
|
Attempts YASD file parsing.
|
||||||
|
@ -429,6 +506,7 @@ class YASDMessenger:
|
||||||
"invalid_level": "Invalid log level '@lvl'",
|
"invalid_level": "Invalid log level '@lvl'",
|
||||||
"invalid_input": "Invalid file '@file'",
|
"invalid_input": "Invalid file '@file'",
|
||||||
"invalid_yaml": "Invalid YAML structure",
|
"invalid_yaml": "Invalid YAML structure",
|
||||||
|
"no_yaml": "YAML dict needed",
|
||||||
"no_input": "Input file needed.",
|
"no_input": "Input file needed.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +579,14 @@ class YASDCLI:
|
||||||
# TODO print man from README
|
# TODO print man from README
|
||||||
print("Manual")
|
print("Manual")
|
||||||
else:
|
else:
|
||||||
YASD.do(args.action, args.input, args.output, args.quiet, args.log)
|
YASD.do(
|
||||||
|
args.action,
|
||||||
|
args.input,
|
||||||
|
args.output,
|
||||||
|
args.quiet,
|
||||||
|
args.log,
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
|
||||||
def __init_parser(self):
|
def __init_parser(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue