From cf6f40220ae5407c098e281a1e4aee843b3c2c1e Mon Sep 17 00:00:00 2001 From: Fabien BOURGEOIS Date: Fri, 9 Dec 2022 11:12:59 +0100 Subject: [PATCH] [MIG]Yaltik DSL : from coconut to pure py2 --- yaltik_dsl/src/__init__.coco | 18 --- yaltik_dsl/src/__init__.py | 37 ----- yaltik_dsl/src/odoo_dsl.py | 83 +++------- yaltik_dsl/src/xml_base.py | 46 +----- yaltik_dsl/tests/test_odoo.coco | 247 ------------------------------ yaltik_dsl/tests/test_odoo.py | 86 ++--------- yaltik_dsl/tests/test_xml_base.py | 65 ++------ 7 files changed, 51 insertions(+), 531 deletions(-) delete mode 100644 yaltik_dsl/src/__init__.coco delete mode 100644 yaltik_dsl/tests/test_odoo.coco diff --git a/yaltik_dsl/src/__init__.coco b/yaltik_dsl/src/__init__.coco deleted file mode 100644 index b0fa7d4..0000000 --- a/yaltik_dsl/src/__init__.coco +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright 2020 Fabien Bourgeois -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -from . import odoo_dsl diff --git a/yaltik_dsl/src/__init__.py b/yaltik_dsl/src/__init__.py index 1bad212..bfab0dd 100644 --- a/yaltik_dsl/src/__init__.py +++ b/yaltik_dsl/src/__init__.py @@ -1,40 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# __coconut_hash__ = 0xf09e1c4d - -# Compiled with Coconut version 2.1.1 [The Spanish Inquisition] - -# Coconut Header: ------------------------------------------------------------- - -from __future__ import generator_stop, annotations -import sys as _coconut_sys, os as _coconut_os -_coconut_file_dir = _coconut_os.path.dirname(_coconut_os.path.abspath(__file__)) -_coconut_cached_module = _coconut_sys.modules.get("__coconut__") -if _coconut_cached_module is not None and _coconut_os.path.dirname(_coconut_cached_module.__file__) != _coconut_file_dir: # type: ignore - del _coconut_sys.modules["__coconut__"] -_coconut_sys.path.insert(0, _coconut_file_dir) -_coconut_module_name = _coconut_os.path.splitext(_coconut_os.path.basename(_coconut_file_dir))[0] -if _coconut_module_name and _coconut_module_name[0].isalpha() and all(c.isalpha() or c.isdigit() for c in _coconut_module_name) and "__init__.py" in _coconut_os.listdir(_coconut_file_dir): - _coconut_full_module_name = str(_coconut_module_name + ".__coconut__") - import __coconut__ as _coconut__coconut__ - _coconut__coconut__.__name__ = _coconut_full_module_name - for _coconut_v in vars(_coconut__coconut__).values(): - if getattr(_coconut_v, "__module__", None) == "__coconut__": - try: - _coconut_v.__module__ = _coconut_full_module_name - except AttributeError: - _coconut_v_type = type(_coconut_v) - if getattr(_coconut_v_type, "__module__", None) == "__coconut__": - _coconut_v_type.__module__ = _coconut_full_module_name - _coconut_sys.modules[_coconut_full_module_name] = _coconut__coconut__ -from __coconut__ import * -from __coconut__ import _namedtuple_of, _coconut, _coconut_super, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_multi_dim_arr, _coconut_mk_anon_namedtuple, _coconut_matmul -_coconut_sys.path.pop(0) - -# Compiled Coconut: ----------------------------------------------------------- - -# -*- coding: utf-8 -*- - # Copyright 2020 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify diff --git a/yaltik_dsl/src/odoo_dsl.py b/yaltik_dsl/src/odoo_dsl.py index 3e83dee..2a71693 100644 --- a/yaltik_dsl/src/odoo_dsl.py +++ b/yaltik_dsl/src/odoo_dsl.py @@ -1,42 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# __coconut_hash__ = 0xa5bf2f83 - -# Compiled with Coconut version 2.1.1 [The Spanish Inquisition] - -""" Odoo XML DSL """ - -# Coconut Header: ------------------------------------------------------------- - -from __future__ import generator_stop, annotations -import sys as _coconut_sys, os as _coconut_os -_coconut_file_dir = _coconut_os.path.dirname(_coconut_os.path.abspath(__file__)) -_coconut_cached_module = _coconut_sys.modules.get("__coconut__") -if _coconut_cached_module is not None and _coconut_os.path.dirname(_coconut_cached_module.__file__) != _coconut_file_dir: # type: ignore - del _coconut_sys.modules["__coconut__"] -_coconut_sys.path.insert(0, _coconut_file_dir) -_coconut_module_name = _coconut_os.path.splitext(_coconut_os.path.basename(_coconut_file_dir))[0] -if _coconut_module_name and _coconut_module_name[0].isalpha() and all(c.isalpha() or c.isdigit() for c in _coconut_module_name) and "__init__.py" in _coconut_os.listdir(_coconut_file_dir): - _coconut_full_module_name = str(_coconut_module_name + ".__coconut__") - import __coconut__ as _coconut__coconut__ - _coconut__coconut__.__name__ = _coconut_full_module_name - for _coconut_v in vars(_coconut__coconut__).values(): - if getattr(_coconut_v, "__module__", None) == "__coconut__": - try: - _coconut_v.__module__ = _coconut_full_module_name - except AttributeError: - _coconut_v_type = type(_coconut_v) - if getattr(_coconut_v_type, "__module__", None) == "__coconut__": - _coconut_v_type.__module__ = _coconut_full_module_name - _coconut_sys.modules[_coconut_full_module_name] = _coconut__coconut__ -from __coconut__ import * -from __coconut__ import _namedtuple_of, _coconut, _coconut_super, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_multi_dim_arr, _coconut_mk_anon_namedtuple, _coconut_matmul -_coconut_sys.path.pop(0) - -# Compiled Coconut: ----------------------------------------------------------- - -# -*- coding: utf-8 -*- -# # Copyright 2019-2020 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify @@ -52,10 +13,9 @@ _coconut_sys.path.pop(0) # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +""" Odoo XML DSL """ - -from .xml_base import xmlroot -from .xml_base import xmln +from .xml_base import xmlroot, xmln # XML helpers functions and macros @@ -71,7 +31,6 @@ def data(*args): return xmln('data', *args) # Aliases - function = lambda *args: xmln('function', *args) record = lambda *args: xmln('record', *args) form = lambda *args: xmln('form', *args) @@ -84,38 +43,40 @@ def act_window_model(model, attrs): """ Build new act_window from model and args """ xmlid = '%s_view_action' % (model.replace('.', '_')) name = '%s Action' % ' '.join(map(lambda w: w.capitalize(), model.split('.'))) - attrs_clone = attrs.copy() # Avoid side-effect + attrs_clone = attrs.copy() # Avoid side-effect attrs_clone.update({'id': xmlid, 'name': name, 'res_model': model}) return act_window(attrs_clone) - def action_server_code(xmlid, name, modelref, code): """ Server actions of type code """ - children = [field_name(name), field({'name': 'model_id', 'ref': modelref}, []), field({'name': 'state'}, ['code',]), field({'name': 'code'}, [code,])] + children = [field_name(name), + field({'name': 'model_id', 'ref': modelref}, []), + field({'name': 'state'}, ['code']), + field({'name': 'code'}, [code])] return record({'id': xmlid, 'model': 'ir.actions.server'}, children) - def client_action_multi(xmlid, name, model, action): """ Client action multi (ir.values), with own xmlid, name, targeted model and action """ action = "'ir.actions.server,%d'%{}".format(action) - children = [field_name(name), field({'name': 'key2', 'eval': "'client_action_multi'"}), field({'name': 'model', 'eval': "'%s'" % model}), field({'name': 'value', 'eval': action})] + children = [field_name(name), + field({'name': 'key2', 'eval': "'client_action_multi'"}), + field({'name': 'model', 'eval': "'%s'" % model}), + field({'name': 'value', 'eval': action})] return record({'id': xmlid, 'model': 'ir.values'}, children) # Menus - menuitem = lambda *args: xmln('menuitem', *args) def menuitem_model(model, attrs): """ Build new menuitem from model and attrs """ model_und = model.replace('.', '_') xmlid = '%s_menu' % model_und actionid = '%s_view_action' % model_und - attrs_clone = attrs.copy() # Avoid side-effect + attrs_clone = attrs.copy() # Avoid side-effect attrs_clone.update({'id': xmlid, 'action': actionid}) return menuitem(attrs_clone) # Form aliases - group = lambda *args: xmln('group', *args) header = lambda *args: xmln('header', *args) footer = lambda *args: xmln('footer', *args) @@ -123,13 +84,13 @@ sheet = lambda *args: xmln('sheet', *args) button = lambda *args: xmln('button', *args) p = lambda *args: xmln('p', *args) xpath = lambda *args: xmln('xpath', *args) -attribute = lambda name, value: xmln('attribute', {'name': name}, [value,]) +attribute = lambda name, value: xmln('attribute', {'name': name}, [value]) # Fields field = lambda *args: xmln('field', *args) -field_name = lambda name: field({'name': 'name'}, [name,]) -field_nval = lambda name, value: field({'name': name}, [value,]) -field_model = lambda model: field({'name': 'model'}, [model,]) +field_name = lambda name: field({'name': 'name'}, [name]) +field_nval = lambda name, value: field({'name': name}, [value]) +field_model = lambda model: field({'name': 'model'}, [model]) field_inherit = lambda xmlid: field({'name': 'inherit_id', 'ref': xmlid}, []) field_arch = lambda *args: field({'name': 'arch', 'type': 'xml'}, *args) @@ -141,20 +102,20 @@ def filter_yes_no(field, str_yes=False, str_no=False): """ Double filter for boolean : True and False """ res = [] if str_yes: - res.append(filter({'name': f'{field}_yes', 'string': str_yes, 'domain': f"[('{field}', '=', True)]"})) + res.append(filter({'name': f'{field}_yes', 'string': str_yes, + 'domain': f"[('{field}', '=', True)]"})) if str_no: - res.append(filter({'name': f'{field}_no', 'string': str_no, 'domain': f"[('{field}', '=', False)]"})) + res.append(filter({'name': f'{field}_no', 'string': str_no, + 'domain': f"[('{field}', '=', False)]"})) return res # Views - view = lambda xmlid, children: record({'id': xmlid, 'model': 'ir.ui.view'}, children) def view_def(xmlid, name, model, arch): """ Shortcut for new view """ return view(xmlid, [field_name(name), field_model(model), field_arch(arch)]) - def view_new(view_type, model, arch): """ View : new view definition, based on type (form, tree, ...) and model ID """ model_und = model.replace('.', '_') @@ -163,7 +124,6 @@ def view_new(view_type, model, arch): name = ' '.join([model_cap, view_type.capitalize()]) return view_def(xmlid, name, model, arch) - def view_inherit(filename, model, inherit, arch): """ Inherited View simplification with name of the record, xmlid for model and inherited view """ @@ -172,4 +132,5 @@ def view_inherit(filename, model, inherit, arch): xmlid = '%s_inherit_%s' % (inherited, module) model_cap = ' '.join(map(lambda w: w.capitalize(), model.split('.'))) name = '%s Adaptations' % model_cap - return view(xmlid, [field_name(name), field_model(model), field_inherit(inherit), field_arch(arch)]) + return view(xmlid, [field_name(name), field_model(model), + field_inherit(inherit), field_arch(arch)]) diff --git a/yaltik_dsl/src/xml_base.py b/yaltik_dsl/src/xml_base.py index ccb4a27..ba3d9ef 100644 --- a/yaltik_dsl/src/xml_base.py +++ b/yaltik_dsl/src/xml_base.py @@ -1,42 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# __coconut_hash__ = 0x491ccdad - -# Compiled with Coconut version 2.1.1 [The Spanish Inquisition] - -""" XML helpers and macros """ - -# Coconut Header: ------------------------------------------------------------- - -from __future__ import generator_stop, annotations -import sys as _coconut_sys, os as _coconut_os -_coconut_file_dir = _coconut_os.path.dirname(_coconut_os.path.abspath(__file__)) -_coconut_cached_module = _coconut_sys.modules.get("__coconut__") -if _coconut_cached_module is not None and _coconut_os.path.dirname(_coconut_cached_module.__file__) != _coconut_file_dir: # type: ignore - del _coconut_sys.modules["__coconut__"] -_coconut_sys.path.insert(0, _coconut_file_dir) -_coconut_module_name = _coconut_os.path.splitext(_coconut_os.path.basename(_coconut_file_dir))[0] -if _coconut_module_name and _coconut_module_name[0].isalpha() and all(c.isalpha() or c.isdigit() for c in _coconut_module_name) and "__init__.py" in _coconut_os.listdir(_coconut_file_dir): - _coconut_full_module_name = str(_coconut_module_name + ".__coconut__") - import __coconut__ as _coconut__coconut__ - _coconut__coconut__.__name__ = _coconut_full_module_name - for _coconut_v in vars(_coconut__coconut__).values(): - if getattr(_coconut_v, "__module__", None) == "__coconut__": - try: - _coconut_v.__module__ = _coconut_full_module_name - except AttributeError: - _coconut_v_type = type(_coconut_v) - if getattr(_coconut_v_type, "__module__", None) == "__coconut__": - _coconut_v_type.__module__ = _coconut_full_module_name - _coconut_sys.modules[_coconut_full_module_name] = _coconut__coconut__ -from __coconut__ import * -from __coconut__ import _namedtuple_of, _coconut, _coconut_super, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_multi_dim_arr, _coconut_mk_anon_namedtuple, _coconut_matmul -_coconut_sys.path.pop(0) - -# Compiled Coconut: ----------------------------------------------------------- - -# -*- coding: utf-8 -*- -# # Copyright 2019-2020 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify @@ -52,7 +13,7 @@ _coconut_sys.path.pop(0) # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - +""" XML helpers and macros """ from os import path import xml.etree.ElementTree as ET @@ -70,7 +31,6 @@ def xmlroot(tree): xmlchild(rootel, tree['children']) return rootel - def xmlchild(parent, children): """ Handling of children (ie non root) XML Nodes with/o text and subchildren (recursive) """ @@ -87,7 +47,6 @@ def xmlchild(parent, children): else: raise TypeError('Invalid arguments for xmlchild') - def xmln(tag='', attrs={}, children=[]): """ XMLDictElement building from dict object, with defaults """ if isinstance(attrs, list): @@ -101,10 +60,9 @@ def xmln(tag='', attrs={}, children=[]): raise TypeError('Invalid arguments for xmln') - def xml_write(filepath, tree, pretty=True, suffix='_views'): """ 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 = ET.tostring(tree) if pretty: output_xml = minidom.parseString(output_xml).toprettyxml(indent=' ') diff --git a/yaltik_dsl/tests/test_odoo.coco b/yaltik_dsl/tests/test_odoo.coco deleted file mode 100644 index cc2ad07..0000000 --- a/yaltik_dsl/tests/test_odoo.coco +++ /dev/null @@ -1,247 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright 2020 Fabien Bourgeois -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -""" Odoo Helpers tests """ - -import unittest -import xml.etree.ElementTree as ET -from src.xml_base import XMLDictElement -import src.odoo_dsl as od - -class TestOdooBase(unittest.TestCase): - """ Odoo Helpers tests """ - - def test_odoo(self): - """ Test odoo function """ - element = od.odoo([]) - self.assertIsInstance(element, ET.Element) - self.assertEqual(element.tag, 'odoo') - - def test_data(self): - """ Test data function """ - element = od.data([]) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'data') - self.assertEqual(element.attrs, {}) - - element = od.data({"one": "attribute"}, []) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'data') - self.assertEqual(element.attrs, {"one": "attribute"}) - - def test_aliases(self): - """ Test simple aliases to xmln """ - element = od.record({"one": "attribute"}, 'A child') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs, {"one": "attribute"}) - self.assertEqual(element.children, ['A child']) - - element = od.tree() - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'tree') - - def test_act_window_model(self): - """ Test act_window function """ - element = od.act_window_model('sample.model', {'view_type': 'form'}) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'act_window') - self.assertEqual(element.attrs['view_type'], 'form') - self.assertEqual(element.attrs['id'], 'sample_model_view_action') - self.assertEqual(element.attrs['res_model'], 'sample.model') - self.assertEqual(element.attrs['name'], 'Sample Model Action') - - def test_menunitem_model(self): - """ Test menuitem function """ - element = od.menuitem_model('sample.model', {'groups': 'base.user_employee'}) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'menuitem') - self.assertEqual(element.attrs['groups'], 'base.user_employee') - self.assertEqual(element.attrs['id'], 'sample_model_menu') - self.assertEqual(element.attrs['action'], 'sample_model_view_action') - - def test_attribute(self): - """ Test attribute function """ - element = od.attribute('invisible', "1") - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'attribute') - self.assertEqual(element.attrs['name'], 'invisible') - self.assertEqual(element.children, ["1"]) - - def test_fields(self): - """ Test fields function """ - element = od.field({"one": "attribute"}, 'A child') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'field') - - element = od.field_name('A name') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'field') - self.assertEqual(element.attrs['name'], 'name') - self.assertEqual(element.children, ['A name']) - - element = od.field_model('sample.model') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'field') - self.assertEqual(element.attrs['name'], 'model') - self.assertEqual(element.children, ['sample.model']) - - element = od.field_inherit('module.xml_view') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'field') - self.assertEqual(element.attrs['name'], 'inherit_id') - self.assertEqual(element.attrs['ref'], 'module.xml_view') - self.assertFalse(element.children) - - element = od.field_arch() - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'field') - self.assertEqual(element.attrs['name'], 'arch') - self.assertEqual(element.attrs['type'], 'xml') - self.assertFalse(element.children) - - def test_view(self): - """ Test view function """ - element = od.view('view_xmlid', []) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs['id'], 'view_xmlid') - self.assertEqual(element.attrs['model'], 'ir.ui.view') - self.assertFalse(element.children) - - def test_view_def(self): - """ Test view_def function """ - element = od.view_def('view_xmlid', 'View', 'sample.model', []) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs['id'], 'view_xmlid') - self.assertEqual(element.attrs['model'], 'ir.ui.view') - self.assertEqual((len(element.children)), 3) - self.assertIsInstance(element.children[0], XMLDictElement) - self.assertEqual(element.children[0].tag, 'field') - self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['View']) - self.assertIsInstance(element.children[1], XMLDictElement) - self.assertEqual(element.children[1].tag, 'field') - self.assertEqual(element.children[1].attrs['name'], 'model') - self.assertEqual(element.children[1].children, ['sample.model']) - self.assertIsInstance(element.children[2], XMLDictElement) - self.assertEqual(element.children[2].tag, 'field') - self.assertEqual(element.children[2].attrs['name'], 'arch') - self.assertEqual(element.children[2].attrs['type'], 'xml') - self.assertFalse(element.children[2].children) - - def test_view_new(self): - """ Test view_new function """ - element = od.view_new('tree', 'sample.model', []) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs['id'], 'sample_model_view_tree') - self.assertEqual(element.attrs['model'], 'ir.ui.view') - self.assertEqual((len(element.children)), 3) - self.assertIsInstance(element.children[0], XMLDictElement) - self.assertEqual(element.children[0].tag, 'field') - self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Sample Model Tree']) - self.assertIsInstance(element.children[1], XMLDictElement) - self.assertEqual(element.children[1].tag, 'field') - self.assertEqual(element.children[1].attrs['name'], 'model') - self.assertEqual(element.children[1].children, ['sample.model']) - self.assertIsInstance(element.children[2], XMLDictElement) - self.assertEqual(element.children[2].tag, 'field') - self.assertEqual(element.children[2].attrs['name'], 'arch') - self.assertEqual(element.children[2].attrs['type'], 'xml') - self.assertFalse(element.children[2].children) - - def test_view_inherit(self): - """ Test view_inherit function """ - element = od.view_inherit('odoo.addons.module', 'sample.model', 'parent.view', []) - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs['id'], 'view_inherit_module') - self.assertEqual(element.attrs['model'], 'ir.ui.view') - self.assertEqual((len(element.children)), 4) - self.assertIsInstance(element.children[0], XMLDictElement) - self.assertEqual(element.children[0].tag, 'field') - self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Sample Model Adaptations']) - self.assertIsInstance(element.children[1], XMLDictElement) - self.assertEqual(element.children[1].tag, 'field') - self.assertEqual(element.children[1].attrs['name'], 'model') - self.assertEqual(element.children[1].children, ['sample.model']) - self.assertIsInstance(element.children[2], XMLDictElement) - self.assertEqual(element.children[2].tag, 'field') - self.assertEqual(element.children[2].attrs['name'], 'inherit_id') - self.assertFalse(element.children[2].children) - self.assertIsInstance(element.children[3], XMLDictElement) - self.assertEqual(element.children[3].tag, 'field') - self.assertEqual(element.children[3].attrs['name'], 'arch') - self.assertEqual(element.children[3].attrs['type'], 'xml') - self.assertFalse(element.children[3].children) - - def test_action_server_code(self): - """ Test action_server_code function """ - element = od.action_server_code('sample.xmlid', 'Code', 'sample.model', - '''record.do_something()''') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs['id'], 'sample.xmlid') - self.assertEqual(element.attrs['model'], 'ir.actions.server') - self.assertEqual((len(element.children)), 4) - self.assertIsInstance(element.children[0], XMLDictElement) - self.assertEqual(element.children[0].tag, 'field') - self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Code']) - self.assertIsInstance(element.children[1], XMLDictElement) - self.assertEqual(element.children[1].tag, 'field') - self.assertEqual(element.children[1].attrs['name'], 'model_id') - self.assertEqual(element.children[1].attrs['ref'], 'sample.model') - self.assertFalse(element.children[1].children) - self.assertEqual(element.children[2].tag, 'field') - self.assertEqual(element.children[2].attrs['name'], 'state') - self.assertEqual(element.children[2].children, ['code']) - self.assertEqual(element.children[3].tag, 'field') - self.assertEqual(element.children[3].attrs['name'], 'code') - self.assertEqual(element.children[3].children, ['record.do_something()']) - - def test_client_action_multi(self): - """ Test client_action_multi function """ - element = od.client_action_multi('sample.xmlid', 'Multi', 'sample.model', 'sample.action') - self.assertIsInstance(element, XMLDictElement) - self.assertEqual(element.tag, 'record') - self.assertEqual(element.attrs['id'], 'sample.xmlid') - self.assertEqual(element.attrs['model'], 'ir.values') - self.assertEqual((len(element.children)), 4) - self.assertIsInstance(element.children[0], XMLDictElement) - self.assertEqual(element.children[0].tag, 'field') - self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Multi']) - self.assertIsInstance(element.children[1], XMLDictElement) - self.assertEqual(element.children[1].tag, 'field') - self.assertEqual(element.children[1].attrs['name'], 'key2') - self.assertEqual(element.children[1].attrs['eval'], "'client_action_multi'") - self.assertFalse(element.children[1].children) - self.assertEqual(element.children[2].tag, 'field') - self.assertEqual(element.children[2].attrs['name'], 'model') - self.assertEqual(element.children[2].attrs['eval'], "'sample.model'") - self.assertEqual(element.children[3].tag, 'field') - self.assertEqual(element.children[3].attrs['name'], 'value') - self.assertEqual(element.children[3].attrs['eval'], "'ir.actions.server,%d'%sample.action") - - -if __name__ == '__main__': - unittest.main() diff --git a/yaltik_dsl/tests/test_odoo.py b/yaltik_dsl/tests/test_odoo.py index 701aa3d..db14960 100644 --- a/yaltik_dsl/tests/test_odoo.py +++ b/yaltik_dsl/tests/test_odoo.py @@ -1,42 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# __coconut_hash__ = 0x40e8d147 - -# Compiled with Coconut version 2.1.1 [The Spanish Inquisition] - -""" Odoo Helpers tests """ - -# Coconut Header: ------------------------------------------------------------- - -from __future__ import generator_stop, annotations -import sys as _coconut_sys, os as _coconut_os -_coconut_file_dir = _coconut_os.path.dirname(_coconut_os.path.abspath(__file__)) -_coconut_cached_module = _coconut_sys.modules.get("__coconut__") -if _coconut_cached_module is not None and _coconut_os.path.dirname(_coconut_cached_module.__file__) != _coconut_file_dir: # type: ignore - del _coconut_sys.modules["__coconut__"] -_coconut_sys.path.insert(0, _coconut_file_dir) -_coconut_module_name = _coconut_os.path.splitext(_coconut_os.path.basename(_coconut_file_dir))[0] -if _coconut_module_name and _coconut_module_name[0].isalpha() and all(c.isalpha() or c.isdigit() for c in _coconut_module_name) and "__init__.py" in _coconut_os.listdir(_coconut_file_dir): - _coconut_full_module_name = str(_coconut_module_name + ".__coconut__") - import __coconut__ as _coconut__coconut__ - _coconut__coconut__.__name__ = _coconut_full_module_name - for _coconut_v in vars(_coconut__coconut__).values(): - if getattr(_coconut_v, "__module__", None) == "__coconut__": - try: - _coconut_v.__module__ = _coconut_full_module_name - except AttributeError: - _coconut_v_type = type(_coconut_v) - if getattr(_coconut_v_type, "__module__", None) == "__coconut__": - _coconut_v_type.__module__ = _coconut_full_module_name - _coconut_sys.modules[_coconut_full_module_name] = _coconut__coconut__ -from __coconut__ import * -from __coconut__ import _namedtuple_of, _coconut, _coconut_super, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_multi_dim_arr, _coconut_mk_anon_namedtuple, _coconut_matmul -_coconut_sys.path.pop(0) - -# Compiled Coconut: ----------------------------------------------------------- - -# -*- coding: utf-8 -*- -# # Copyright 2020 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify @@ -52,7 +13,7 @@ _coconut_sys.path.pop(0) # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - +""" Odoo Helpers tests """ import unittest import xml.etree.ElementTree as ET @@ -68,7 +29,6 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element, ET.Element) self.assertEqual(element.tag, 'odoo') - def test_data(self): """ Test data function """ element = od.data([]) @@ -81,20 +41,18 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.tag, 'data') self.assertEqual(element.attrs, {"one": "attribute"}) - def test_aliases(self): """ Test simple aliases to xmln """ element = od.record({"one": "attribute"}, 'A child') self.assertIsInstance(element, XMLDictElement) self.assertEqual(element.tag, 'record') self.assertEqual(element.attrs, {"one": "attribute"}) - self.assertEqual(element.children, ['A child',]) + self.assertEqual(element.children, ['A child']) element = od.tree() self.assertIsInstance(element, XMLDictElement) self.assertEqual(element.tag, 'tree') - def test_act_window_model(self): """ Test act_window function """ element = od.act_window_model('sample.model', {'view_type': 'form'}) @@ -105,7 +63,6 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.attrs['res_model'], 'sample.model') self.assertEqual(element.attrs['name'], 'Sample Model Action') - def test_menunitem_model(self): """ Test menuitem function """ element = od.menuitem_model('sample.model', {'groups': 'base.user_employee'}) @@ -115,15 +72,13 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.attrs['id'], 'sample_model_menu') self.assertEqual(element.attrs['action'], 'sample_model_view_action') - def test_attribute(self): """ Test attribute function """ element = od.attribute('invisible', "1") self.assertIsInstance(element, XMLDictElement) self.assertEqual(element.tag, 'attribute') self.assertEqual(element.attrs['name'], 'invisible') - self.assertEqual(element.children, ["1",]) - + self.assertEqual(element.children, ["1"]) def test_fields(self): """ Test fields function """ @@ -135,13 +90,13 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element, XMLDictElement) self.assertEqual(element.tag, 'field') self.assertEqual(element.attrs['name'], 'name') - self.assertEqual(element.children, ['A name',]) + self.assertEqual(element.children, ['A name']) element = od.field_model('sample.model') self.assertIsInstance(element, XMLDictElement) self.assertEqual(element.tag, 'field') self.assertEqual(element.attrs['name'], 'model') - self.assertEqual(element.children, ['sample.model',]) + self.assertEqual(element.children, ['sample.model']) element = od.field_inherit('module.xml_view') self.assertIsInstance(element, XMLDictElement) @@ -157,7 +112,6 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.attrs['type'], 'xml') self.assertFalse(element.children) - def test_view(self): """ Test view function """ element = od.view('view_xmlid', []) @@ -167,7 +121,6 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.attrs['model'], 'ir.ui.view') self.assertFalse(element.children) - def test_view_def(self): """ Test view_def function """ element = od.view_def('view_xmlid', 'View', 'sample.model', []) @@ -179,18 +132,17 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element.children[0], XMLDictElement) self.assertEqual(element.children[0].tag, 'field') self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['View',]) + self.assertEqual(element.children[0].children, ['View']) self.assertIsInstance(element.children[1], XMLDictElement) self.assertEqual(element.children[1].tag, 'field') self.assertEqual(element.children[1].attrs['name'], 'model') - self.assertEqual(element.children[1].children, ['sample.model',]) + self.assertEqual(element.children[1].children, ['sample.model']) self.assertIsInstance(element.children[2], XMLDictElement) self.assertEqual(element.children[2].tag, 'field') self.assertEqual(element.children[2].attrs['name'], 'arch') self.assertEqual(element.children[2].attrs['type'], 'xml') self.assertFalse(element.children[2].children) - def test_view_new(self): """ Test view_new function """ element = od.view_new('tree', 'sample.model', []) @@ -202,18 +154,17 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element.children[0], XMLDictElement) self.assertEqual(element.children[0].tag, 'field') self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Sample Model Tree',]) + self.assertEqual(element.children[0].children, ['Sample Model Tree']) self.assertIsInstance(element.children[1], XMLDictElement) self.assertEqual(element.children[1].tag, 'field') self.assertEqual(element.children[1].attrs['name'], 'model') - self.assertEqual(element.children[1].children, ['sample.model',]) + self.assertEqual(element.children[1].children, ['sample.model']) self.assertIsInstance(element.children[2], XMLDictElement) self.assertEqual(element.children[2].tag, 'field') self.assertEqual(element.children[2].attrs['name'], 'arch') self.assertEqual(element.children[2].attrs['type'], 'xml') self.assertFalse(element.children[2].children) - def test_view_inherit(self): """ Test view_inherit function """ element = od.view_inherit('odoo.addons.module', 'sample.model', 'parent.view', []) @@ -225,11 +176,11 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element.children[0], XMLDictElement) self.assertEqual(element.children[0].tag, 'field') self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Sample Model Adaptations',]) + self.assertEqual(element.children[0].children, ['Sample Model Adaptations']) self.assertIsInstance(element.children[1], XMLDictElement) self.assertEqual(element.children[1].tag, 'field') self.assertEqual(element.children[1].attrs['name'], 'model') - self.assertEqual(element.children[1].children, ['sample.model',]) + self.assertEqual(element.children[1].children, ['sample.model']) self.assertIsInstance(element.children[2], XMLDictElement) self.assertEqual(element.children[2].tag, 'field') self.assertEqual(element.children[2].attrs['name'], 'inherit_id') @@ -240,10 +191,10 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.children[3].attrs['type'], 'xml') self.assertFalse(element.children[3].children) - def test_action_server_code(self): """ Test action_server_code function """ - element = od.action_server_code('sample.xmlid', 'Code', 'sample.model', '''record.do_something()''') + element = od.action_server_code('sample.xmlid', 'Code', 'sample.model', + '''record.do_something()''') self.assertIsInstance(element, XMLDictElement) self.assertEqual(element.tag, 'record') self.assertEqual(element.attrs['id'], 'sample.xmlid') @@ -252,7 +203,7 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element.children[0], XMLDictElement) self.assertEqual(element.children[0].tag, 'field') self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Code',]) + self.assertEqual(element.children[0].children, ['Code']) self.assertIsInstance(element.children[1], XMLDictElement) self.assertEqual(element.children[1].tag, 'field') self.assertEqual(element.children[1].attrs['name'], 'model_id') @@ -260,11 +211,10 @@ class TestOdooBase(unittest.TestCase): self.assertFalse(element.children[1].children) self.assertEqual(element.children[2].tag, 'field') self.assertEqual(element.children[2].attrs['name'], 'state') - self.assertEqual(element.children[2].children, ['code',]) + self.assertEqual(element.children[2].children, ['code']) self.assertEqual(element.children[3].tag, 'field') self.assertEqual(element.children[3].attrs['name'], 'code') - self.assertEqual(element.children[3].children, ['record.do_something()',]) - + self.assertEqual(element.children[3].children, ['record.do_something()']) def test_client_action_multi(self): """ Test client_action_multi function """ @@ -277,7 +227,7 @@ class TestOdooBase(unittest.TestCase): self.assertIsInstance(element.children[0], XMLDictElement) self.assertEqual(element.children[0].tag, 'field') self.assertEqual(element.children[0].attrs['name'], 'name') - self.assertEqual(element.children[0].children, ['Multi',]) + self.assertEqual(element.children[0].children, ['Multi']) self.assertIsInstance(element.children[1], XMLDictElement) self.assertEqual(element.children[1].tag, 'field') self.assertEqual(element.children[1].attrs['name'], 'key2') @@ -290,7 +240,5 @@ class TestOdooBase(unittest.TestCase): self.assertEqual(element.children[3].attrs['name'], 'value') self.assertEqual(element.children[3].attrs['eval'], "'ir.actions.server,%d'%sample.action") - - if __name__ == '__main__': unittest.main() diff --git a/yaltik_dsl/tests/test_xml_base.py b/yaltik_dsl/tests/test_xml_base.py index a92ec65..0cb2832 100644 --- a/yaltik_dsl/tests/test_xml_base.py +++ b/yaltik_dsl/tests/test_xml_base.py @@ -1,42 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# __coconut_hash__ = 0xfa849aa3 - -# Compiled with Coconut version 2.1.1 [The Spanish Inquisition] - -""" XML Helpers tests """ - -# Coconut Header: ------------------------------------------------------------- - -from __future__ import generator_stop, annotations -import sys as _coconut_sys, os as _coconut_os -_coconut_file_dir = _coconut_os.path.dirname(_coconut_os.path.abspath(__file__)) -_coconut_cached_module = _coconut_sys.modules.get("__coconut__") -if _coconut_cached_module is not None and _coconut_os.path.dirname(_coconut_cached_module.__file__) != _coconut_file_dir: # type: ignore - del _coconut_sys.modules["__coconut__"] -_coconut_sys.path.insert(0, _coconut_file_dir) -_coconut_module_name = _coconut_os.path.splitext(_coconut_os.path.basename(_coconut_file_dir))[0] -if _coconut_module_name and _coconut_module_name[0].isalpha() and all(c.isalpha() or c.isdigit() for c in _coconut_module_name) and "__init__.py" in _coconut_os.listdir(_coconut_file_dir): - _coconut_full_module_name = str(_coconut_module_name + ".__coconut__") - import __coconut__ as _coconut__coconut__ - _coconut__coconut__.__name__ = _coconut_full_module_name - for _coconut_v in vars(_coconut__coconut__).values(): - if getattr(_coconut_v, "__module__", None) == "__coconut__": - try: - _coconut_v.__module__ = _coconut_full_module_name - except AttributeError: - _coconut_v_type = type(_coconut_v) - if getattr(_coconut_v_type, "__module__", None) == "__coconut__": - _coconut_v_type.__module__ = _coconut_full_module_name - _coconut_sys.modules[_coconut_full_module_name] = _coconut__coconut__ -from __coconut__ import * -from __coconut__ import _namedtuple_of, _coconut, _coconut_super, _coconut_MatchError, _coconut_iter_getitem, _coconut_base_compose, _coconut_forward_compose, _coconut_back_compose, _coconut_forward_star_compose, _coconut_back_star_compose, _coconut_forward_dubstar_compose, _coconut_back_dubstar_compose, _coconut_pipe, _coconut_star_pipe, _coconut_dubstar_pipe, _coconut_back_pipe, _coconut_back_star_pipe, _coconut_back_dubstar_pipe, _coconut_none_pipe, _coconut_none_star_pipe, _coconut_none_dubstar_pipe, _coconut_bool_and, _coconut_bool_or, _coconut_none_coalesce, _coconut_minus, _coconut_map, _coconut_partial, _coconut_get_function_match_error, _coconut_base_pattern_func, _coconut_addpattern, _coconut_sentinel, _coconut_assert, _coconut_raise, _coconut_mark_as_match, _coconut_reiterable, _coconut_self_match_types, _coconut_dict_merge, _coconut_exec, _coconut_comma_op, _coconut_multi_dim_arr, _coconut_mk_anon_namedtuple, _coconut_matmul -_coconut_sys.path.pop(0) - -# Compiled Coconut: ----------------------------------------------------------- - -# -*- coding: utf-8 -*- -# # Copyright 2020 Fabien Bourgeois # # This program is free software: you can redistribute it and/or modify @@ -52,16 +13,13 @@ _coconut_sys.path.pop(0) # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . - +""" XML Helpers tests """ from functools import partial import unittest import xml.etree.ElementTree as ET from os import unlink -from src.xml_base import xmln -from src.xml_base import xmlroot -from src.xml_base import xmlchild -from src.xml_base import xml_write +from src.xml_base import xmln, xmlroot, xmlchild, xml_write class TestXMLBase(unittest.TestCase): @@ -69,19 +27,19 @@ class TestXMLBase(unittest.TestCase): def test_xmln(self): """ Text xmln """ -# Tags + # Tags self.assertDictEqual(xmln()._asdict(), {'tag': '', 'attrs': {}, 'children': []}) self.assertEqual(xmln('a tag').tag, 'a tag') -# Attrs + # Attrs self.assertDictEqual(xmln(attrs={'a good': 'one'}).attrs, {'a good': 'one'}) -# Childrens + # Childrens self.assertListEqual(xmln(children=[1, 2, 3]).children, [1, 2, 3]) - self.assertListEqual(xmln(children='Some text').children, ['Some text',]) + self.assertListEqual(xmln(children='Some text').children, ['Some text']) with self.assertRaisesRegex(TypeError, 'Invalid arguments'): xmln(children=False) -# Ensure that only children after tags is managed + # Ensure that only children after tags is managed element = xmln('tag', {'something': 'inside'}) self.assertIsInstance(element.attrs, dict) self.assertIsInstance(element.children, list) @@ -91,7 +49,6 @@ class TestXMLBase(unittest.TestCase): self.assertIsInstance(element.children, list) - def test_xmlchild(self): """ Test xmlchild """ parent = xmlroot({'tag': 'root', 'attrs': {}, 'children': []}) @@ -104,7 +61,7 @@ class TestXMLBase(unittest.TestCase): with self.assertRaisesRegex(TypeError, 'Invalid arguments for xmlchild'): xmlc_par([{'tag': 't', 'attrs': {'a': 'b'}, 'children': []},]) - xmlc_par(['some text',]) + xmlc_par(['some text']) self.assertEqual(parent.text, 'some text') xmlc_par([xmln('t', {'a': 'b'}, []),]) @@ -124,7 +81,6 @@ class TestXMLBase(unittest.TestCase): self.assertEqual(subchildren[0].tag, 'subchild') - def test_xmlroot(self): """ Test xmlroot """ root = xmlroot({'tag': 'root', 'attrs': {}, 'children': []}) @@ -138,10 +94,10 @@ class TestXMLBase(unittest.TestCase): xmlroot({'tag': 'root'}) - def test_xml_write(self): """ test xml_write """ - children = [xmln('child1', {'attr': 'value'}, []), xmln('child2', {}, "Some text")] + children = [xmln('child1', {'attr': 'value'}, []), + xmln('child2', {}, "Some text")] tree = xmlroot({'tag': 'root', 'attrs': {}, 'children': children}) xmlw = lambda p: xml_write(p, tree) @@ -167,6 +123,5 @@ class TestXMLBase(unittest.TestCase): self.assertIn('Some text', output_xml) unlink(filepath) - if __name__ == '__main__': unittest.main()