[IMP]Hy Base : favor defns instead of macros here

This commit is contained in:
Fabien BOURGEOIS 2019-09-22 10:12:41 +02:00
parent dd846361cf
commit 095f4ce7d9
6 changed files with 227 additions and 54 deletions

View File

@ -18,6 +18,7 @@
" Odoo XML macros "
(require [odoo.addons.hy_base.xml [*]])
(import [odoo.addons.hy_base.xml [*]])
(defmacro if-python2 [python2-form python3-form]
"If running on python2, execute python2-form, else, execute python3-form"
@ -26,65 +27,62 @@
python2-form
python3-form))
(defmacro ox-odoo [&rest args] `(xmlr "odoo" ~@args))
(defmacro ox-data [&rest args] `(xmlnc "data" ~@args))
(defmacro ox-record [&rest args] `(xmlnc "record" ~@args))
(defmacro ox-form [&rest args] `(xmlnc "form" ~@args))
(defmacro ox-tree [&rest args] `(xmlnc "tree" ~@args))
(defmacro ox-search [&rest args] `(xmlnc "search" ~@args))
(defmacro ox-act-window [&rest args] `(xmlna "act_window" ~@args))
(defmacro ox-group [&rest args] `(xmlnc "group" ~@args))
(defmacro ox-header [&rest args] `(xmlnc "header" ~@args))
(defmacro ox-footer [&rest args] `(xmlnc "footer" ~@args))
(defmacro ox-button [&rest args] `(xmlna "button" ~@args))
(defmacro ox-p [&rest args] `(xmlnc "p" ~@args))
(defn ox-odoo [&rest args] (xmlroot (xmln "odoo" {} #*args)))
(defn ox-data [&rest args] (xmln "data" {} #*args))
(defn ox-record [&rest args] (xmln "record" #*args))
(defn ox-form [&rest args] (xmln "form" #*args))
(defn ox-tree [&rest args] (xmln "tree" #*args))
(defn ox-search [&rest args] (xmln "search" #*args))
(defn ox-act-window [&rest args] (xmln "act_window" #*args))
(defn ox-group [&rest args] (xmln "group" #*args))
(defn ox-header [&rest args] (xmln "header" #*args))
(defn ox-footer [&rest args] (xmln "footer" #*args))
(defn ox-button [&rest args] (xmln "button" #*args))
(defn ox-p [&rest args] (xmln "p" #*args))
(defn ox-field [&rest args] (xmln "field" #*args))
(defmacro ox-view [xmlid children] `(ox-record {"id" ~xmlid "model" "ir.ui.view"} ~children))
(defmacro ox-view-def [xmlid name model &rest body]
(defn ox-field-name [name] (ox-field {"name" "name"} [name]))
(defn ox-field-model [model] (ox-field {"name" "model"} [model]))
(defn ox-field-inherit [xmlid] (ox-field {"name" "inherit_id" "ref" xmlid} []))
(defn ox-field-arch [&rest args] (ox-field {"name" "arch" "type" "xml"} #*args))
(defn ox-view [xmlid children] (ox-record {"id" xmlid "model" "ir.ui.view"} children))
(defn ox-view-def [xmlid name model arch]
"View and first fields simplification with record xmlid, name, targeted model"
`(do
(ox-view ~xmlid
[(ox-field-name ~name)
(ox-field-model ~model)
(ox-field-arch ~@body)])))
(defmacro ox-view-inherit [name model inherit &rest body]
(ox-view xmlid
[(ox-field-name name)
(ox-field-model model)
(ox-field-arch arch)]))
(defn ox-view-inherit [name model inherit arch]
"Inherited View simplification with name of the record, xmlid for model and
inherited view"
(setv module (get (.split __name__ ".") 2)
inherited (get (.split inherit ".") 1)
xmlid f"{inherited}_inherit_{module}")
`(do
(ox-view ~xmlid
[(ox-field-name ~name)
(ox-field-model ~model)
(ox-field-inherit ~inherit)
(ox-field-arch ~@body)])))
(ox-view xmlid
[(ox-field-name name)
(ox-field-model model)
(ox-field-inherit inherit)
(ox-field-arch arch)]))
(defmacro ox-actions-server-code [xmlid name modelref code]
(defn ox-actions-server-code [xmlid name modelref code]
"Server actions of type code"
`(do
(ox-record {"id" ~xmlid "model" "ir.actions.server"}
[(ox-field-name ~name)
(ox-field {"name" "model_id" "ref" ~modelref} [])
(ox-field {"name" "state"} ["code"])
(ox-field {"name" "code"} [~code])])))
(ox-record {"id" xmlid "model" "ir.actions.server"}
[(ox-field-name name)
(ox-field {"name" "model_id" "ref" modelref} [])
(ox-field {"name" "state"} ["code"])
(ox-field {"name" "code"} [code])]))
(defmacro ox-client-action-multi [xmlid name model action]
(defn ox-client-action-multi [xmlid name model action]
"Client action multi (ir.values), with own xmlid, name, targeted model and
action"
(setv action f"'ir.actions.server,%d'%{action}")
`(do
(ox-record {"id" ~xmlid "model" "ir.values"}
[(ox-field-name ~name)
(ox-field {"name" "key2" "eval" "'client_action_multi'"} [])
(ox-field {"name" "model" "eval" (+ "'" ~model "'")} [])
(ox-field {"name" "value" "eval" ~action})])))
(defmacro ox-field [&rest args] `(xmlna "field" ~@args))
(defmacro ox-field-name [name] `(ox-field {"name" "name"} [~name]))
(defmacro ox-field-model [model] `(ox-field {"name" "model"} [~model]))
(defmacro ox-field-inherit [xmlid] `(ox-field {"name" "inherit_id" "ref" ~xmlid} []))
(defmacro ox-field-arch [&rest args] `(ox-field {"name" "arch" "type" "xml"} ~@args))
(ox-record {"id" xmlid "model" "ir.values"}
[(ox-field-name name)
(ox-field {"name" "key2" "eval" "'client_action_multi'"} [])
(ox-field {"name" "model" "eval" (+ "'" model "'")} [])
(ox-field {"name" "value" "eval" action})]))
(defmacro/g! xml-write [filename tree]
"Write XML file according to filename and given tree"

View File

@ -21,9 +21,8 @@
(defn xmlroot [tree]
"Special process for root XML Node"
(setv root (first tree))
(setv rootel (.Element ET (get root "tag") (get root "attrs")))
(setv children (get root "children"))
(setv rootel (.Element ET (get tree "tag") (get tree "attrs"))
children (get tree "children"))
(if children (xmlchild rootel children))
(return rootel))
@ -34,11 +33,17 @@
(if (string? c)
(setv (. parent text) c)
(do
(setv attrs (dfor [k v] (.items (get c "attrs")) [k (str v)]))
(setv attrs (dfor [k v] (.items (get c "attrs")) [(str k) (str v)]))
(setv new_parent (.SubElement ET parent (get c "tag") attrs))
(setv subchildren (get c "children"))
(if subchildren (xmlchild new_parent subchildren))))))
(defn xmln [tag &optional attrs children text]
"XMLNode with default children, not attributes"
(setv children (or (if text [text] children) []))
{"tag" tag "attrs" (or attrs {}) "children" children}
)
(defmacro xmlnc [&rest args]
"XMLNode with default children, not attributes"
(cond [(= (len args) 1) (setv tag (first args) attrs {} children [])]
@ -59,7 +64,3 @@
[(= (len args) 2) (setv tag (first args) attrs {} text (last args))]
[(= (len args) 3) (setv tag (first args) attrs (get args 1) text (last args))])
`(xmln ~tag ~attrs [~text]))
(defmacro xmlr [&rest args]
"XML Root node"
(setv expr `(xmlnc ~@args)) `(xmlroot [~expr]))

18
xml_dsl/__init__.py Normal file
View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
#
# 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 <http://www.gnu.org/licenses/>.
from . import odoo

29
xml_dsl/__manifest__.py Normal file
View File

@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
#
# 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 <http://www.gnu.org/licenses/>.
{
'name': 'Odoo XML DSL base module and fns',
'summary': 'Odoo XML Domain Specific Language base module and functions',
'description': """ Odoo XML Domain Specific Language base module and functions """,
'version': '10.0.0.1.0',
'category': 'Yaltik',
'author': 'Fabien Bourgeois',
'license': 'AGPL-3',
'application': False,
'installable': True,
'depends': ['base']
}

46
xml_dsl/base.py Normal file
View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
#
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
#
# 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 <http://www.gnu.org/licenses/>.
""" XML helpers and macros """
from xml.etree import ElementTree as ET
def xmlroot(tree):
""" Special process for root XML Node """
rootel = ET.Element(tree['tag'], tree['attrs'])
children = tree['children']
if children:
xmlchild(rootel, children)
return rootel
def xmlchild(parent, children):
""" Handling of children (ie non root) XML Nodes with/o text and
subchildren (recursive) """
for child in children:
if isinstance(child, str):
parent.text = child
else:
attrs = {unicode(k): unicode(v) for k, v in child['attrs'].items()}
new_parent = ET.SubElement(parent, child['tag'], attrs)
subchildren = child['children']
if subchildren:
xmlchild(new_parent, subchildren)
def xmln(tag='', attrs=None, children=None, text=False):
""" XMLNode with default children, not attributes """
children = ([text] if text else children) or []
return {'tag': tag, 'attrs': attrs or {}, 'children': children}

81
xml_dsl/odoo.py Normal file
View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
#
# Copyright 2019 Fabien Bourgeois <fabien@yaltik.com>
#
# 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 <http://www.gnu.org/licenses/>.
""" Odoo XML DSL """
from . import base as x
def odoo(*args):
""" odoo tag shortcut """
return x.xmlroot(x.xmln('odoo', {}, *args))
def data(*args):
""" data tag shortcut """
return x.xmln('data', {}, *args)
def record(*args):
""" record tag shortcut """
return x.xmln('record', *args)
def view(xmlid, children):
""" view tag shortcut """
return record({'id': xmlid, 'model': 'ir.ui.view'}, children)
def view_def(xmlid, name, model, arch):
""" View and first fields simplification with record xmlid, name, targeted model """
return view(xmlid, [field_name(name), field_model(model), field_arch(arch)])
def view_inherit(name, model, inherit, arch):
""" Inherited View simplification with name of the record, xmlid for model
and inherited view """
module = __name__.split('.')[2]
inherited = inherit.split('.')[1]
xmlid = '%s_inherit_%s' % (inherited, module)
return view(xmlid, [field_name(name), field_model(model),
field_inherit(inherit), field_arch(arch)])
def actions_server_code(xmlid, name, modelref, code):
""" Server actions of type code """
return record({'id': xmlid, 'model': 'ir.actions.server'},
[field_name(name),
field({'name': 'model_id', 'ref': modelref}),
field({'name': 'state'}, ['code']),
field({'name': 'code'}, [code])])
def field(*args):
""" field tag shortcut """
return x.xmln('field', *args)
def field_name(name):
""" field name tag shortcut """
return field({'name': 'name'}, [name])
def field_model(model):
""" field model tag shortcut """
return field({'name': 'model'}, [model])
def field_inherit(xmlid):
""" field inherit tag shortcut """
return field({'name': 'inherit_id', 'ref': xmlid})
def field_arch(*args):
""" field arch tag shortcut """
return field({'name': 'arch', 'type': 'xml'}, *args)
def xml_write(mpath, filename, tree):
""" Write XML file according to filename and given tree """
import os.path
from xml.etree import ElementTree as ET
output_xml = ET.tostring(tree)
output_path = os.path.dirname(os.path.abspath(mpath))
fpath = u'%s/%s' % (output_path, filename)
with open(fpath, 'w') as xml_file:
xml_file.write(output_xml)