[IMP]Yaltik DSL : improvements

* Improve typing ;
* Rewrite of xml_write ;
* New tests cases, as xml_write.
This commit is contained in:
Fabien BOURGEOIS 2020-04-30 18:32:47 +02:00
parent 742d395427
commit e46c4bf6ab
6 changed files with 69 additions and 49 deletions

View File

@ -628,11 +628,6 @@ def addpattern(base_func, **kwargs):
raise _coconut.TypeError("addpattern() got unexpected keyword arguments " + _coconut.repr(kwargs)) raise _coconut.TypeError("addpattern() got unexpected keyword arguments " + _coconut.repr(kwargs))
return _coconut.functools.partial(_coconut_base_pattern_func, base_func) return _coconut.functools.partial(_coconut_base_pattern_func, base_func)
_coconut_addpattern = addpattern _coconut_addpattern = addpattern
def prepattern(base_func, **kwargs):
"""DEPRECATED: Use addpattern instead."""
def pattern_prepender(func):
return addpattern(func, **kwargs)(base_func)
return pattern_prepender
class _coconut_partial(object): class _coconut_partial(object):
__slots__ = ("func", "_argdict", "_arglen", "_stargs", "keywords") __slots__ = ("func", "_argdict", "_arglen", "_stargs", "keywords")
if hasattr(_coconut.functools.partial, "__doc__"): if hasattr(_coconut.functools.partial, "__doc__"):
@ -714,9 +709,6 @@ def makedata(data_type, *args):
if _coconut.issubclass(data_type, _coconut.str): if _coconut.issubclass(data_type, _coconut.str):
return "".join(args) return "".join(args)
return data_type(args) return data_type(args)
def datamaker(data_type):
"""DEPRECATED: Use makedata instead."""
return _coconut.functools.partial(makedata, data_type)
def fmap(func, obj): def fmap(func, obj):
"""fmap(func, obj) creates a copy of obj with func applied to its contents. """fmap(func, obj) creates a copy of obj with func applied to its contents.
Override by defining obj.__fmap__(func).""" Override by defining obj.__fmap__(func)."""

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# __coconut_hash__ = 0xe22b9d74 # __coconut_hash__ = 0x5812e74d
# Compiled with Coconut version 1.4.3 [Ernest Scribbler] # Compiled with Coconut version 1.4.3 [Ernest Scribbler]

View File

@ -19,7 +19,8 @@
import unittest import unittest
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from xml_base import xmln, xmlroot, xmlchild from os import unlink
from xml_base import xmln, xmlroot, xmlchild, xml_write
class TestXMLBase(unittest.TestCase): class TestXMLBase(unittest.TestCase):
@ -108,8 +109,24 @@ class TestXMLBase(unittest.TestCase):
('children', err.message) |*> self.assertIn ('children', err.message) |*> self.assertIn
def test_xml_write(self): pass def test_xml_write(self):
children = [('child1', {'attr': 'value'}, []) |*> xmln,
('child2', {}, "Some text") |*> xmln]
tree = xmlroot({'tag': 'root', 'attrs': {}, 'children': children})
xmlw = xml_write$(?, tree)
('/badpath' |> xmlw) `self.assertEquals` None
('/bad.ext' |> xmlw) `self.assertEquals` None
xmlw(__file__)
filepath = __file__.replace('.py', '_views.xml')
with open(filepath, 'r') as output_file:
output_xml = output_file.read()
'<?xml version' `self.assertIn` output_xml
'<root>' `self.assertIn` output_xml
'<child1 attr="value"/>' `self.assertIn` output_xml
'<child2>Some text</child2>' `self.assertIn` output_xml
unlink(filepath)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# __coconut_hash__ = 0x6e1a1e05 # __coconut_hash__ = 0x48175ba9
# Compiled with Coconut version 1.4.3 [Ernest Scribbler] # Compiled with Coconut version 1.4.3 [Ernest Scribbler]
@ -42,9 +42,11 @@ from __coconut__ import _coconut, _coconut_MatchError, _coconut_igetitem, _cocon
import unittest import unittest
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from os import unlink
from xml_base import xmln from xml_base import xmln
from xml_base import xmlroot from xml_base import xmlroot
from xml_base import xmlchild from xml_base import xmlchild
from xml_base import xml_write
class TestXMLBase(unittest.TestCase): class TestXMLBase(unittest.TestCase):
@ -133,8 +135,22 @@ class TestXMLBase(unittest.TestCase):
def test_xml_write(self): def test_xml_write(self):
pass children = [(xmln)(*('child1', {'attr': 'value'}, [])), (xmln)(*('child2', {}, "Some text"))]
tree = xmlroot({'tag': 'root', 'attrs': {}, 'children': children})
xmlw = _coconut_partial(xml_write, {1: tree}, 2)
(self.assertEquals)(((xmlw)('/badpath')), None)
(self.assertEquals)(((xmlw)('/bad.ext')), None)
xmlw(__file__)
filepath = __file__.replace('.py', '_views.xml')
with open(filepath, 'r') as output_file:
output_xml = output_file.read()
(self.assertIn)('<?xml version', output_xml)
(self.assertIn)('<root>', output_xml)
(self.assertIn)('<child1 attr="value"/>', output_xml)
(self.assertIn)('<child2>Some text</child2>', output_xml)
unlink(filepath)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -20,17 +20,15 @@
from os import path from os import path
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from xml.dom import minidom from xml.dom import minidom
from typing import Dict, List, Union, Any from typing import Dict, List, Union, Text, Any
# TODO: fix MyPy / typing # TODO: fix MyPy / typing
# REF and test xml_write
data XMLDictElement(tag: XMLText, attrs: XMLAttrs, children: List[Any]) data XMLDictElement(tag: Text, attrs: XMLAttrs, children: List[Any])
XMLText = Union[str, unicode] XMLAttrs = Dict[Text, Text]
XMLAttrs = Dict[str, str] XMLChild = Union[XMLDictElement, Text, List]
XMLChild = Union[XMLDictElement, XMLText, List]
def xmlroot(tree: Dict[str, Any]) -> ET.Element: def xmlroot(tree: Dict[str, Any]) -> ET.Element:
@ -40,12 +38,11 @@ def xmlroot(tree: Dict[str, Any]) -> ET.Element:
(rootel, tree['children']) |*> xmlchild (rootel, tree['children']) |*> xmlchild
return rootel return rootel
# TODO: addpattern here
def xmlchild(parent: ET.Element, children: XMLDictElement) -> 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) """
case children: case children:
match _ is XMLText: match _ is Text:
parent.text = children parent.text = children
match _ is XMLDictElement: match _ is XMLDictElement:
attrs = {unicode(k): unicode(v) for [k, v] in children.attrs.items()} attrs = {unicode(k): unicode(v) for [k, v] in children.attrs.items()}
@ -53,30 +50,30 @@ def xmlchild(parent: ET.Element, children: XMLDictElement) -> None:
subchildren = children.children subchildren = children.children
if subchildren: if subchildren:
(new_parent, subchildren) |*> xmlchild (new_parent, subchildren) |*> xmlchild
match _ is list: match _ is List:
((xmlchild$ <| parent), children) |*> map |> consume ((xmlchild$ <| parent), children) |*> map |> consume
else: else:
raise TypeError('Invalid arguments for xmlchild') raise TypeError('Invalid arguments for xmlchild')
def xmln(tag: Text = '',
def xmln(tag: XMLText = '',
attrs: XMLAttrs = {}, attrs: XMLAttrs = {},
children: Union[str, List] = []) -> XMLDictElement: children: Union[Text, List] = []) -> XMLDictElement:
""" XMLNode with default children, not attributes """ """ XMLDictElement building from dict object, with defaults """
xmldictel = XMLDictElement$ <*| (tag, attrs) xmldictel = XMLDictElement$ <*| (tag, attrs)
case children: case children:
match c is str: match c is Text:
return [c] |> xmldictel return [c] |> xmldictel
match c is list: match c is list:
return c |> xmldictel return c |> xmldictel
else: else:
raise TypeError('Invalid arguments for xmln') raise TypeError('Invalid arguments for xmln')
def xml_write(filepath, tree): def xml_write(filepath, tree):
""" Write XML file according to filename and given tree """ """ Write XML file according to filename and given tree """
if filepath.endswith('.py'): # if .pyc, no need to generate XML if '.py' |> filepath.endswith: # if .pyc, no need to generate XML
output_xml = minidom.parseString(ET.tostring(tree)).toprettyxml(indent=' ') output_xml = tree |> ET.tostring |> minidom.parseString |> .toprettyxml(indent=' ')
output_path = path.dirname(path.abspath(filepath)) output_path = filepath |> path.abspath |> path.dirname
fpath = '%s/%s' % (output_path, path.basename(filepath).replace('.py', '_views.xml')) fpath = [output_path, filepath |> path.basename] |> '/'.join |> .replace('.py', '_views.xml')
with open(fpath, 'w') as output_file: with open(fpath, 'w') as output_file:
output_file.write(output_xml) output_file.write(output_xml)

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python2 #!/usr/bin/env python2
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# __coconut_hash__ = 0xf1882627 # __coconut_hash__ = 0xeb6b4b07
# Compiled with Coconut version 1.4.3 [Ernest Scribbler] # Compiled with Coconut version 1.4.3 [Ernest Scribbler]
@ -46,13 +46,13 @@ from xml.dom import minidom
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Union from typing import Union
from typing import Text
from typing import Any from typing import Any
# TODO: fix MyPy / typing # TODO: fix MyPy / typing
# REF and test xml_write
class XMLDictElement(_coconut.typing.NamedTuple("XMLDictElement", [("tag", 'XMLText'), ("attrs", 'XMLAttrs'), ("children", 'List[Any]')]), _coconut.object): class XMLDictElement(_coconut.typing.NamedTuple("XMLDictElement", [("tag", 'Text'), ("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):
@ -61,9 +61,8 @@ class XMLDictElement(_coconut.typing.NamedTuple("XMLDictElement", [("tag", 'XMLT
return _coconut.tuple.__hash__(self) ^ hash(self.__class__) return _coconut.tuple.__hash__(self) ^ hash(self.__class__)
XMLText = Union[str, unicode] XMLAttrs = Dict[Text, Text]
XMLAttrs = Dict[str, str] XMLChild = Union[XMLDictElement, Text, List]
XMLChild = Union[XMLDictElement, XMLText, List]
def xmlroot(tree # type: Dict[str, Any] def xmlroot(tree # type: Dict[str, Any]
@ -75,7 +74,6 @@ def xmlroot(tree # type: Dict[str, Any]
(xmlchild)(*(rootel, tree['children'])) (xmlchild)(*(rootel, tree['children']))
return rootel return rootel
# TODO: addpattern here
def xmlchild(parent, # type: ET.Element def xmlchild(parent, # type: ET.Element
children # type: XMLDictElement children # type: XMLDictElement
): ):
@ -84,7 +82,7 @@ def xmlchild(parent, # type: ET.Element
subchildren (recursive) """ subchildren (recursive) """
_coconut_match_to = children _coconut_match_to = children
_coconut_case_check_0 = False _coconut_case_check_0 = False
if _coconut.isinstance(_coconut_match_to, XMLText): if _coconut.isinstance(_coconut_match_to, Text):
_coconut_case_check_0 = True _coconut_case_check_0 = True
if _coconut_case_check_0: if _coconut_case_check_0:
parent.text = children parent.text = children
@ -98,24 +96,23 @@ def xmlchild(parent, # type: ET.Element
if subchildren: if subchildren:
(xmlchild)(*(new_parent, subchildren)) (xmlchild)(*(new_parent, subchildren))
if not _coconut_case_check_0: if not _coconut_case_check_0:
if _coconut.isinstance(_coconut_match_to, list): if _coconut.isinstance(_coconut_match_to, List):
_coconut_case_check_0 = True _coconut_case_check_0 = True
if _coconut_case_check_0: 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: if not _coconut_case_check_0:
raise TypeError('Invalid arguments for xmlchild') raise TypeError('Invalid arguments for xmlchild')
def xmln(tag='', # type: Text
def xmln(tag='', # type: XMLText
attrs={}, # type: XMLAttrs attrs={}, # type: XMLAttrs
children=[] # type: Union[str, List] children=[] # type: Union[Text, List]
): ):
# type: (...) -> XMLDictElement # type: (...) -> XMLDictElement
""" XMLNode with default children, not attributes """ """ XMLDictElement building from dict object, with defaults """
xmldictel = (_coconut.functools.partial(_coconut.functools.partial, XMLDictElement))(*(tag, attrs)) xmldictel = (_coconut.functools.partial(_coconut.functools.partial, XMLDictElement))(*(tag, attrs))
_coconut_match_to = children _coconut_match_to = children
_coconut_case_check_1 = False _coconut_case_check_1 = False
if _coconut.isinstance(_coconut_match_to, str): if _coconut.isinstance(_coconut_match_to, Text):
c = _coconut_match_to c = _coconut_match_to
_coconut_case_check_1 = True _coconut_case_check_1 = True
if _coconut_case_check_1: if _coconut_case_check_1:
@ -129,11 +126,12 @@ def xmln(tag='', # type: XMLText
if not _coconut_case_check_1: 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):
""" Write XML file according to filename and given tree """ """ Write XML file according to filename and given tree """
if filepath.endswith('.py'): # if .pyc, no need to generate XML if (filepath.endswith)('.py'): # if .pyc, no need to generate XML
output_xml = minidom.parseString(ET.tostring(tree)).toprettyxml(indent=' ') output_xml = ((minidom.parseString)((ET.tostring)(tree))).toprettyxml(indent=' ')
output_path = path.dirname(path.abspath(filepath)) output_path = (path.dirname)((path.abspath)(filepath))
fpath = '%s/%s' % (output_path, path.basename(filepath).replace('.py', '_views.xml')) fpath = (('/'.join)([output_path, (path.basename)(filepath)])).replace('.py', '_views.xml')
with open(fpath, 'w') as output_file: with open(fpath, 'w') as output_file:
output_file.write(output_xml) output_file.write(output_xml)