[REF][WIP]Yaltik DSL : new tests, refacoring of xml_base, ADTs

This commit is contained in:
Fabien BOURGEOIS 2020-04-30 10:58:36 +02:00
parent 1202e3c6d4
commit cfb99c113d
4 changed files with 114 additions and 105 deletions

View File

@ -27,19 +27,19 @@ class TestXMLBase(unittest.TestCase):
def test_xmln(self): def test_xmln(self):
# Tags # Tags
(xmln(), {'tag': '', 'attrs': {}, 'children': []}) |*> self.assertEquals (xmln()._asdict(), {'tag': '', 'attrs': {}, 'children': []}) |*> self.assertEquals
(xmln <| 'a tag' |> .get <| 'tag', 'a tag') |*> self.assertEquals (xmln <| 'a tag' |> getattr$(?, 'tag'), 'a tag') |*> self.assertEquals
# Attrs # Attrs
(xmln(attrs={'a good': 'one'}).get('attrs'), {'a good': 'one'}) |*> self.assertEquals (xmln(attrs={'a good': 'one'}).attrs, {'a good': 'one'}) |*> self.assertEquals
(xmln <**| {'attrs': {'a good': 'one'}} |> .get <| 'attrs', {'a good': 'one'}) |*> self.assertEquals (xmln <**| {'attrs': {'a good': 'one'}} |> getattr$(?, 'attrs'), {'a good': 'one'}) |*> self.assertEquals
# Childrens # Childrens
attrs ={'children': [1, 2, 3]} attrs ={'children': [1, 2, 3]}
(xmln <**| attrs |> .get <| 'children' == [1, 2, 3]) |> self.assertTrue (xmln <**| attrs |> getattr$(?, 'children') == [1, 2, 3]) |> self.assertTrue
attrs = {'children': 'Some text'} attrs = {'children': 'Some text'}
(xmln <**| attrs |> .get <| 'children' == ['Some text']) |> self.assertTrue (xmln <**| attrs |> getattr$(?, 'children') == ['Some text']) |> self.assertTrue
try: try:
xmln <**| {'children': False} xmln <**| {'children': False}
@ -51,27 +51,35 @@ class TestXMLBase(unittest.TestCase):
parent = {'tag': 'root', 'attrs': {}, 'children': []} |> xmlroot parent = {'tag': 'root', 'attrs': {}, 'children': []} |> xmlroot
xmlc_par = xmlchild$ <| parent xmlc_par = xmlchild$ <| parent
(xmlc_par <| []) `self.assertEquals` None # Bad arguments
try: try:
xmlc_par <| False xmlc_par <| False
except TypeError as err: except TypeError as err:
'is not iterable' `self.assertIn` err.message 'Invalid arguments for xmlchild' `self.assertIn` err.message
try:
xmlc_par <| []
except TypeError as err:
'Invalid arguments for xmlchild' `self.assertIn` err.message
try: # Need XMLDictElement, not dict
xmlc_par <| [{'tag': 't', 'attrs': {'a': 'b'}, 'children': []}]
except TypeError as err:
'Invalid arguments for xmlchild' `self.assertIn` err.message
xmlc_par <| ['some text'] xmlc_par <| ['some text']
parent.text `self.assertEquals` 'some text' parent.text `self.assertEquals` 'some text'
xmlc_par <| [{'tag': 't', 'attrs': {'a': 'b'}, 'children': []}] xmlc_par <| [xmln <**| {'tag': 't', 'attrs': {'a': 'b'}, 'children': []}]
child = parent.iter <| 't' |> next child = parent.iter <| 't' |> next
child.tag `self.assertEquals` 't' child.tag `self.assertEquals` 't'
child.attrib `self.assertEquals` {'a': 'b'} child.attrib `self.assertEquals` {'a': 'b'}
(child |> list) `self.assertEquals` [] (child |> list) `self.assertEquals` []
xmlc_par <| [{'tag': 't2', 'attrs': {1: 2}, 'children': []}] xmlc_par <| [xmln <**| {'tag': 't2', 'attrs': {1: 2}, 'children': []}]
child = parent.iter <| 't2' |> next child = parent.iter <| 't2' |> next
child.attrib `self.assertEquals` {'1': '2'} child.attrib `self.assertEquals` {'1': '2'}
xmlc_par <| [{'tag': 'tchildren', 'attrs': {}, xmlc_par <| [xmln <**| {'tag': 'tchildren', 'attrs': {},
'children': [{'tag': 'subchild', 'attrs': {}, 'children': []}]}] 'children': [xmln <**| {'tag': 'subchild', 'attrs': {}, 'children': []}]}]
child = parent.iter <| 'tchildren' |> next child = parent.iter <| 'tchildren' |> next
subchildren = (child |> list) subchildren = (child |> list)
(subchildren |> len) `self.assertEquals` 1 (subchildren |> len) `self.assertEquals` 1

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# __coconut_hash__ = 0xf82711d8 # __coconut_hash__ = 0x6e1a1e05
# Compiled with Coconut version 1.4.3 [Ernest Scribbler] # Compiled with Coconut version 1.4.3 [Ernest Scribbler]
@ -52,19 +52,19 @@ class TestXMLBase(unittest.TestCase):
def test_xmln(self): def test_xmln(self):
# Tags # Tags
(self.assertEquals)(*(xmln(), {'tag': '', 'attrs': {}, 'children': []})) (self.assertEquals)(*(xmln()._asdict(), {'tag': '', 'attrs': {}, 'children': []}))
(self.assertEquals)(*((((xmln)('a tag')).get)('tag'), 'a tag')) (self.assertEquals)(*((_coconut_partial(getattr, {1: 'tag'}, 2))((xmln)('a tag')), 'a tag'))
# Attrs # Attrs
(self.assertEquals)(*(xmln(attrs={'a good': 'one'}).get('attrs'), {'a good': 'one'})) (self.assertEquals)(*(xmln(attrs={'a good': 'one'}).attrs, {'a good': 'one'}))
(self.assertEquals)(*((((xmln)(**{'attrs': {'a good': 'one'}})).get)('attrs'), {'a good': 'one'})) (self.assertEquals)(*((_coconut_partial(getattr, {1: 'attrs'}, 2))((xmln)(**{'attrs': {'a good': 'one'}})), {'a good': 'one'}))
# Childrens # Childrens
attrs = {'children': [1, 2, 3]} attrs = {'children': [1, 2, 3]}
(self.assertTrue)(((((xmln)(**attrs)).get)('children') == [1, 2, 3])) (self.assertTrue)(((_coconut_partial(getattr, {1: 'children'}, 2))((xmln)(**attrs)) == [1, 2, 3]))
attrs = {'children': 'Some text'} attrs = {'children': 'Some text'}
(self.assertTrue)(((((xmln)(**attrs)).get)('children') == ['Some text'])) (self.assertTrue)(((_coconut_partial(getattr, {1: 'children'}, 2))((xmln)(**attrs)) == ['Some text']))
try: try:
(xmln)(**{'children': False}) (xmln)(**{'children': False})
@ -76,26 +76,34 @@ class TestXMLBase(unittest.TestCase):
parent = (xmlroot)({'tag': 'root', 'attrs': {}, 'children': []}) parent = (xmlroot)({'tag': 'root', 'attrs': {}, 'children': []})
xmlc_par = (_coconut.functools.partial(_coconut.functools.partial, xmlchild))(parent) xmlc_par = (_coconut.functools.partial(_coconut.functools.partial, xmlchild))(parent)
(self.assertEquals)(((xmlc_par)([])), None) # Bad arguments
try: try:
(xmlc_par)(False) (xmlc_par)(False)
except TypeError as err: except TypeError as err:
(self.assertIn)('is not iterable', err.message) (self.assertIn)('Invalid arguments for xmlchild', err.message)
try:
(xmlc_par)([])
except TypeError as err:
(self.assertIn)('Invalid arguments for xmlchild', err.message)
try: # Need XMLDictElement, not dict
(xmlc_par)([{'tag': 't', 'attrs': {'a': 'b'}, 'children': []}])
except TypeError as err:
(self.assertIn)('Invalid arguments for xmlchild', err.message)
(xmlc_par)(['some text']) (xmlc_par)(['some text'])
(self.assertEquals)(parent.text, 'some text') (self.assertEquals)(parent.text, 'some text')
(xmlc_par)([{'tag': 't', 'attrs': {'a': 'b'}, 'children': []}]) (xmlc_par)([(xmln)(**{'tag': 't', 'attrs': {'a': 'b'}, 'children': []})])
child = (next)((parent.iter)('t')) child = (next)((parent.iter)('t'))
(self.assertEquals)(child.tag, 't') (self.assertEquals)(child.tag, 't')
(self.assertEquals)(child.attrib, {'a': 'b'}) (self.assertEquals)(child.attrib, {'a': 'b'})
(self.assertEquals)(((list)(child)), []) (self.assertEquals)(((list)(child)), [])
(xmlc_par)([{'tag': 't2', 'attrs': {1: 2}, 'children': []}]) (xmlc_par)([(xmln)(**{'tag': 't2', 'attrs': {1: 2}, 'children': []})])
child = (next)((parent.iter)('t2')) child = (next)((parent.iter)('t2'))
(self.assertEquals)(child.attrib, {'1': '2'}) (self.assertEquals)(child.attrib, {'1': '2'})
(xmlc_par)([{'tag': 'tchildren', 'attrs': {}, 'children': [{'tag': 'subchild', 'attrs': {}, 'children': []}]}]) (xmlc_par)([(xmln)(**{'tag': 'tchildren', 'attrs': {}, 'children': [(xmln)(**{'tag': 'subchild', 'attrs': {}, 'children': []})]})])
child = (next)((parent.iter)('tchildren')) child = (next)((parent.iter)('tchildren'))
subchildren = ((list)(child)) subchildren = ((list)(child))
(self.assertEquals)(((len)(subchildren)), 1) (self.assertEquals)(((len)(subchildren)), 1)

View File

@ -23,16 +23,15 @@ from xml.dom import minidom
from typing import Dict, List, Union, Any from typing import Dict, List, Union, Any
# TODO: ADT for XMLchild children**s** # TODO: fix MyPy / typing
# REF xml_write # REF and test xml_write
data XMLChildren(clist: List[Union[XMLDict, XMLText]]) data XMLDictElement(tag: XMLText, attrs: XMLAttrs, children: List[Any])
data XMLText(text: Union[str, unicode]) XMLText = Union[str, unicode]
data XMLDict(tag: str, attrs: Dict[str, str], children: XMLChildren) XMLAttrs = Dict[str, str]
XMLChild = Union[XMLDictElement, XMLText, List]
data XMLTag(tag: str)
data XMLAttrs(attrs: Dict[str, str])
def xmlroot(tree: Dict[str, Any]) -> ET.Element: def xmlroot(tree: Dict[str, Any]) -> ET.Element:
""" Special process for root XML Node """ """ Special process for root XML Node """
@ -41,30 +40,35 @@ def xmlroot(tree: Dict[str, Any]) -> ET.Element:
(rootel, tree['children']) |*> xmlchild (rootel, tree['children']) |*> xmlchild
return rootel return rootel
def xmlchild(parent: ET.Element, children: Any) -> None: def xmlchild(parent: ET.Element, children: XMLDictElement) -> None:
""" Handling of children (ie non root) XML Nodes with/o text and """ Handling of children (ie non root) XML Nodes with/o text and
subchildren (recursive) """ subchildren (recursive) """
match _ is (str, unicode) in children: case children:
match _ is XMLText:
parent.text = children parent.text = children
return match _ is XMLDictElement:
match _ is dict in children: attrs = {unicode(k): unicode(v) for [k, v] in children.attrs.items()}
attrs = {unicode(k): unicode(v) for [k, v] in children['attrs'].items()} new_parent = (parent, children.tag, attrs) |*> ET.SubElement
new_parent = (parent, children['tag'], attrs) |*> ET.SubElement subchildren = children.children
subchildren = children['children']
if subchildren: if subchildren:
(new_parent, subchildren) |*> xmlchild (new_parent, subchildren) |*> xmlchild
match _ is list in children: match _ is list:
((xmlchild$ <| parent), children) |*> map |> consume ((xmlchild$ <| parent), children) |*> map |> consume
else:
raise TypeError('Invalid arguments for xmlchild')
def xmln(tag: str = '', def xmln(tag: XMLText = '',
attrs: Dict[str, str] = {}, attrs: XMLAttrs = {},
children: Union[str, List] = []) -> Dict: children: Union[str, List] = []) -> XMLDictElement:
""" XMLNode with default children, not attributes """ """ XMLNode with default children, not attributes """
match c is str in children: case children:
return {'tag': tag, 'attrs': attrs, 'children': [c]} match c is str:
else: match c is list in children: return XMLDictElement(tag=tag, attrs=attrs, children=[c])
return {'tag': tag, 'attrs': attrs, 'children': c} # return {'tag': tag, 'attrs': attrs, 'children': [c]}
match c is list:
return XMLDictElement(tag=tag, attrs=attrs, children=c)
# return {'tag': tag, 'attrs': attrs, 'children': c}
else: else:
raise TypeError('Invalid arguments for xmln') raise TypeError('Invalid arguments for xmln')

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# __coconut_hash__ = 0xd881e1a # __coconut_hash__ = 0x65805ba7
# Compiled with Coconut version 1.4.3 [Ernest Scribbler] # Compiled with Coconut version 1.4.3 [Ernest Scribbler]
@ -49,9 +49,10 @@ from typing import Union
from typing import Any from typing import Any
# TODO: ADT for XMLchild children**s** # TODO: fix MyPy / typing
# REF and test xml_write
class XMLChildren(_coconut.typing.NamedTuple("XMLChildren", [("clist", 'List[Union[XMLChildDict, XMLChildText]]')]), _coconut.object): class XMLDictElement(_coconut.typing.NamedTuple("XMLDictElement", [("tag", 'XMLText'), ("attrs", 'XMLAttrs'), ("children", 'List[Any]')]), _coconut.object):
__slots__ = () __slots__ = ()
__ne__ = _coconut.object.__ne__ __ne__ = _coconut.object.__ne__
def __eq__(self, other): def __eq__(self, other):
@ -59,21 +60,10 @@ class XMLChildren(_coconut.typing.NamedTuple("XMLChildren", [("clist", 'List[Uni
def __hash__(self): def __hash__(self):
return _coconut.tuple.__hash__(self) ^ hash(self.__class__) return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
class XMLChildText(_coconut.typing.NamedTuple("XMLChildText", [("text", 'Union[str, unicode]')]), _coconut.object):
__slots__ = ()
__ne__ = _coconut.object.__ne__
def __eq__(self, other):
return self.__class__ is other.__class__ and _coconut.tuple.__eq__(self, other)
def __hash__(self):
return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
class XMLChildDict(_coconut.typing.NamedTuple("XMLChildDict", [("tag", 'str'), ("attrs", 'Dict[str, str]'), ("children", 'XMLChildren')]), _coconut.object): XMLText = Union[str, unicode]
__slots__ = () XMLAttrs = Dict[str, str]
__ne__ = _coconut.object.__ne__ XMLChild = Union[XMLDictElement, XMLText, List]
def __eq__(self, other):
return self.__class__ is other.__class__ and _coconut.tuple.__eq__(self, other)
def __hash__(self):
return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
def xmlroot(tree # type: Dict[str, Any] def xmlroot(tree # type: Dict[str, Any]
@ -86,58 +76,57 @@ def xmlroot(tree # type: Dict[str, Any]
return rootel return rootel
def xmlchild(parent, # type: ET.Element def xmlchild(parent, # type: ET.Element
children # type: Any children # type: XMLDictElement
): ):
# type: (...) -> None # type: (...) -> None
""" Handling of children (ie non root) XML Nodes with/o text and """ Handling of children (ie non root) XML Nodes with/o text and
subchildren (recursive) """ subchildren (recursive) """
_coconut_match_to = children _coconut_match_to = children
_coconut_match_check = False _coconut_case_check_0 = False
if _coconut.isinstance(_coconut_match_to, (str, unicode)): if _coconut.isinstance(_coconut_match_to, XMLText):
_coconut_match_check = True _coconut_case_check_0 = True
if _coconut_match_check: if _coconut_case_check_0:
parent.text = children parent.text = children
return if not _coconut_case_check_0:
_coconut_match_to = children if _coconut.isinstance(_coconut_match_to, XMLDictElement):
_coconut_match_check = False _coconut_case_check_0 = True
if _coconut.isinstance(_coconut_match_to, dict): if _coconut_case_check_0:
_coconut_match_check = True attrs = dict(((unicode(k)), (unicode(v))) for [k, v] in children.attrs.items())
if _coconut_match_check: new_parent = (ET.SubElement)(*(parent, children.tag, attrs))
attrs = dict(((unicode(k)), (unicode(v))) for [k, v] in children['attrs'].items()) subchildren = children.children
new_parent = (ET.SubElement)(*(parent, children['tag'], attrs))
subchildren = children['children']
if subchildren: if subchildren:
(xmlchild)(*(new_parent, subchildren)) (xmlchild)(*(new_parent, subchildren))
_coconut_match_to = children if not _coconut_case_check_0:
_coconut_match_check = False
if _coconut.isinstance(_coconut_match_to, list): if _coconut.isinstance(_coconut_match_to, list):
_coconut_match_check = True _coconut_case_check_0 = True
if _coconut_match_check: if _coconut_case_check_0:
(consume)((map)(*(((_coconut.functools.partial(_coconut.functools.partial, xmlchild))(parent)), children))) (consume)((map)(*(((_coconut.functools.partial(_coconut.functools.partial, xmlchild))(parent)), children)))
if not _coconut_case_check_0:
raise TypeError('Invalid arguments for xmlchild')
def xmln(tag='', # type: str def xmln(tag='', # type: XMLText
attrs={}, # type: Dict[str, str] attrs={}, # type: XMLAttrs
children=[] # type: Union[str, List] children=[] # type: Union[str, List]
): ):
# type: (...) -> Dict # type: (...) -> XMLDictElement
""" XMLNode with default children, not attributes """ """ XMLNode with default children, not attributes """
_coconut_match_to = children _coconut_match_to = children
_coconut_match_check = False _coconut_case_check_1 = False
if _coconut.isinstance(_coconut_match_to, str): if _coconut.isinstance(_coconut_match_to, str):
c = _coconut_match_to c = _coconut_match_to
_coconut_match_check = True _coconut_case_check_1 = True
if _coconut_match_check: if _coconut_case_check_1:
return {'tag': tag, 'attrs': attrs, 'children': [c]} return XMLDictElement(tag=tag, attrs=attrs, children=[c])
else: # return {'tag': tag, 'attrs': attrs, 'children': [c]}
_coconut_match_to = children if not _coconut_case_check_1:
_coconut_match_check = False
if _coconut.isinstance(_coconut_match_to, list): if _coconut.isinstance(_coconut_match_to, list):
c = _coconut_match_to c = _coconut_match_to
_coconut_match_check = True _coconut_case_check_1 = True
if _coconut_match_check: if _coconut_case_check_1:
return {'tag': tag, 'attrs': attrs, 'children': c} return XMLDictElement(tag=tag, attrs=attrs, children=c)
else: # return {'tag': tag, 'attrs': attrs, 'children': c}
if not _coconut_case_check_1:
raise TypeError('Invalid arguments for xmln') raise TypeError('Invalid arguments for xmln')
def xml_write(filepath, tree): def xml_write(filepath, tree):