From aa569114cc4180dc1242fe0dcc191ccdc2d1b67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 17 Jun 2008 13:05:52 +0200 Subject: [PATCH 01/11] Don't try to validate xml for old version of lxml --- trytond/ir/ui/view.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py index 9c54dbb18a..1178b6ab2b 100644 --- a/trytond/ir/ui/view.py +++ b/trytond/ir/ui/view.py @@ -56,17 +56,19 @@ class View(OSV): trans_views[trans['name']][trans['src']] = trans for view in views: xml = view.arch.strip() + tree = etree.fromstring(xml) + dtd_name = os.path.join(os.path.dirname(__file__), (view.inherit and view.inherit.type or view.type) + '.dtd') - dtd = etree.DTD(file(dtd_name)) - tree = etree.fromstring(xml) - if not dtd.validate(tree): - logger = Logger() - error_log = reduce(lambda x, y: str(x) + '\n' + str(y), - dtd.error_log.filter_from_errors()) - logger.notify_channel('ir', LOG_ERROR, - 'Invalid xml view:\n%s' % (error_log + '\n' + xml)) - return False + if hasattr(etree, 'DTD'): + dtd = etree.DTD(file(dtd_name)) + if not dtd.validate(tree): + logger = Logger() + error_log = reduce(lambda x, y: str(x) + '\n' + str(y), + dtd.error_log.filter_from_errors()) + logger.notify_channel('ir', LOG_ERROR, + 'Invalid xml view:\n%s' % (error_log + '\n' + xml)) + return False root_element = tree.getroottree().getroot() strings = self._translate_view(root_element) view_ids = self.search(cursor, 0, [ From 0dd2b61f2089a764da0bfa7d4789339f1024c9c3 Mon Sep 17 00:00:00 2001 From: "hartmut@demetrius.muc.goebel-consult.de" Date: Tue, 17 Jun 2008 13:00:50 +0200 Subject: [PATCH 02/11] Adding Relax NG schemas for XML files. --- trytond/ir/ui/board.rnc | 145 +++++++ trytond/ir/ui/board.rng | 477 +++++++++++++++++++++++ trytond/ir/ui/form.rnc | 256 ++++++++++++ trytond/ir/ui/form.rng | 841 ++++++++++++++++++++++++++++++++++++++++ trytond/ir/ui/graph.rnc | 40 ++ trytond/ir/ui/graph.rng | 177 +++++++++ trytond/ir/ui/tree.rnc | 55 +++ trytond/ir/ui/tree.rng | 184 +++++++++ trytond/tryton.rnc | 28 ++ 9 files changed, 2203 insertions(+) create mode 100644 trytond/ir/ui/board.rnc create mode 100644 trytond/ir/ui/board.rng create mode 100644 trytond/ir/ui/form.rnc create mode 100644 trytond/ir/ui/form.rng create mode 100644 trytond/ir/ui/graph.rnc create mode 100644 trytond/ir/ui/graph.rng create mode 100644 trytond/ir/ui/tree.rnc create mode 100644 trytond/ir/ui/tree.rng create mode 100644 trytond/tryton.rnc diff --git a/trytond/ir/ui/board.rnc b/trytond/ir/ui/board.rnc new file mode 100644 index 0000000000..9bd3d79d56 --- /dev/null +++ b/trytond/ir/ui/board.rnc @@ -0,0 +1,145 @@ +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +board = + element board { + attlist.board, + (image + | separator + | labe + | newline + | notebook + | group + | hpaned + | vpaned + | action)* + } +attlist.board &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.board &= [ a:defaultValue = "4" ] attribute col { text }? +image = element image { attlist.image, empty } +attlist.image &= attribute name { text } +attlist.image &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.image &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.image &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }? +attlist.image &= attribute help { text }? +attlist.image &= attribute states { text }? +separator = element separator { attlist.separator, empty } +attlist.separator &= [ a:defaultValue = "" ] attribute string { text }? +attlist.separator &= attribute name { text }? +attlist.separator &= attribute states { text }? +attlist.separator &= + [ a:defaultValue = "0.0" ] attribute align { text }? +attlist.separator &= + [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.separator &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.separator &= + [ a:defaultValue = "0" ] attribute fill { "0" | "1" }? +attlist.separator &= attribute help { text }? +label = element label { attlist.label, empty } +attlist.label &= [ a:defaultValue = "" ] attribute string { text }? +attlist.label &= attribute name { text }? +attlist.label &= attribute states { text }? +attlist.label &= [ a:defaultValue = "0.0" ] attribute align { text }? +attlist.label &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.label &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }? +attlist.label &= + [ a:defaultValue = "0" ] attribute xexpand { "0" | "1" }? +attlist.label &= [ a:defaultValue = "1" ] attribute xfill { "0" | "1" }? +attlist.label &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.label &= attribute help { text }? +newline = element newline { attlist.newline, empty } +attlist.newline &= empty +notebook = element notebook { attlist.notebook, page* } +attlist.notebook &= + attribute tabpos { "up" | "down" | "left" | "right" }? +attlist.notebook &= [ a:defaultValue = "4" ] attribute colspan { text }? +page = + element page { + attlist.page, + (image + | separator + | labe + | newline + | notebook + | group + | hpaned + | vpaned + | action)* + } +attlist.page &= attribute angle { text }? +attlist.page &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.page &= [ a:defaultValue = "4" ] attribute col { text }? +group = + element group { + attlist.group, + (image + | separator + | labe + | newline + | notebook + | group + | hpaned + | vpaned + | action)* + } +attlist.group &= attribute string { text }? +attlist.group &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.group &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.group &= [ a:defaultValue = "1" ] attribute fill { "0" | "1" }? +attlist.group &= [ a:defaultValue = "1" ] attribute rowspan { text }? +attlist.group &= [ a:defaultValue = "4" ] attribute col { text }? +hpaned = element hpaned { attlist.hpaned, child1?, child2? } +attlist.hpaned &= [ a:defaultValue = "4" ] attribute colspan { text }? +attlist.hpaned &= attribute position { text }? +vpaned = element vpaned { attlist.vpaned, child1?, child2? } +attlist.vpaned &= [ a:defaultValue = "4" ] attribute colspan { text }? +attlist.vpaned &= attribute position { text }? +child1 = + element child1 { + attlist.child1, + (image + | separator + | labe + | newline + | notebook + | group + | hpaned + | vpaned + | action)* + } +attlist.child1 &= empty +child2 = + element child2 { + attlist.child2, + (image + | separator + | labe + | newline + | notebook + | group + | hpaned + | vpaned + | action)* + } +attlist.child2 &= empty +data = element data { attlist.data, xpath+ } +attlist.data &= empty +xpath = element xpath { attlist.xpath, any } +attlist.xpath &= attribute expr { text } +attlist.xpath &= + [ a:defaultValue = "inside" ] + attribute position { "inside" | "replace" | "after" | "before" }? +action |= notAllowed +labe |= notAllowed +start = data | board | label +any = + (element * { + attribute * { text }*, + any + } + | text)* diff --git a/trytond/ir/ui/board.rng b/trytond/ir/ui/board.rng new file mode 100644 index 0000000000..8534f60a4d --- /dev/null +++ b/trytond/ir/ui/board.rng @@ -0,0 +1,477 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + up + down + left + right + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inside + replace + after + before + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trytond/ir/ui/form.rnc b/trytond/ir/ui/form.rnc new file mode 100644 index 0000000000..961262ee11 --- /dev/null +++ b/trytond/ir/ui/form.rnc @@ -0,0 +1,256 @@ +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +form = + element form { + attlist.form, + (label + | field + | image + | separator + | newline + | button + | notebook + | group + | hpaned + | vpaned + | properties)* + } +attlist.form &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.form &= attribute on_write { text }? +attlist.form &= [ a:defaultValue = "4" ] attribute col { text }? +attlist.form &= attribute cursor { text }? + +tree = element tree { attlist.tree, field+ } +attlist.tree &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.tree &= attribute on_write { text }? +attlist.tree &= attribute editable { "top" | "bottom" }? +attlist.tree &= attribute sequence { text }? +attlist.tree &= attribute colors { text }? + +graph = element graph { attlist.graph, x, y } +attlist.graph &= + [ a:defaultValue = "vbar" ] + attribute type { "vbar" | "hbar" | "line" | "pie" }? +attlist.graph &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.graph &= + [ a:defaultValue = "#f5f5f5" ] attribute background { text }? +attlist.graph &= [ a:defaultValue = "blue" ] attribute color { text }? +attlist.graph &= + [ a:defaultValue = "1" ] attribute legend { "0" | "1" }? + +x = element x { attlist.x, field } +attlist.x &= empty + +y = element y { attlist.y, field+ } +attlist.y &= empty + +label = element label { attlist.label, empty } +attlist.label &= [ a:defaultValue = "" ] attribute string { text }? +attlist.label &= attribute name { text }? +attlist.label &= attribute states { text }? +attlist.label &= [ a:defaultValue = "0.0" ] attribute align { text }? +attlist.label &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.label &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }? +attlist.label &= + [ a:defaultValue = "0" ] attribute xexpand { "0" | "1" }? +attlist.label &= [ a:defaultValue = "1" ] attribute xfill { "0" | "1" }? +attlist.label &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.label &= attribute help { text }? + +field = element field { attlist.field, (tree | form | graph)* } +attlist.field &= attribute name { text } +attlist.field &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.field &= + attribute widget { + "date" + | "char" + | "many2one" + | "date" + | "one2many" + | "selection" + | "float" + | "numeric" + | "float_time" + | "interger" + | "datetime" + | "boolean" + | "text" + | "url" + | "email" + | "callto" + | "sip" + | "sha" + | "reference" + | "binary" + | "many2many" + | "image" + }? +attlist.field &= attribute saves { "0" | "1" }? +attlist.field &= attribute expand { "0" | "1" }? +attlist.field &= attribute fill { "0" | "1" }? +attlist.field &= attribute empty { "0" | "1" }? +attlist.field &= + [ a:defaultValue = "1" ] attribute xexpand { "0" | "1" }? +attlist.field &= [ a:defaultValue = "1" ] attribute xfill { "0" | "1" }? +attlist.field &= attribute help { text }? +attlist.field &= attribute width { text }? +attlist.field &= attribute height { text }? +attlist.field &= attribute readonly { text }? +attlist.field &= attribute required { text }? +attlist.field &= + [ a:defaultValue = "0" ] attribute tree_invisible { "0" | "1" }? +attlist.field &= attribute mode { text }? +attlist.field &= + [ a:defaultValue = "0" ] attribute completion { "0" | "1" }? +attlist.field &= + [ a:defaultValue = "0" ] attribute invisible { "0" | "1" }? +attlist.field &= attribute sum { text }? +attlist.field &= attribute key { text }? +attlist.field &= attribute domain { text }? +attlist.field &= attribute color { text }? +image = element image { attlist.image, empty } +attlist.image &= attribute name { text } +attlist.image &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.image &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.image &= [ a:defaultValue = "0" ] attribute fill { "0" | "1" }? +attlist.image &= attribute help { text }? +attlist.image &= attribute states { text }? +separator = element separator { attlist.separator, empty } +attlist.separator &= [ a:defaultValue = "" ] attribute string { text }? +attlist.separator &= attribute name { text }? +attlist.separator &= attribute states { text }? +attlist.separator &= + [ a:defaultValue = "0.0" ] attribute align { text }? +attlist.separator &= + [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.separator &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.separator &= + [ a:defaultValue = "0" ] attribute fill { "0" | "1" }? +attlist.separator &= attribute help { text }? +newline = element newline { attlist.newline, empty } +attlist.newline &= empty +button = element button { attlist.button, empty } +attlist.button &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.button &= attribute help { text }? +attlist.button &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.button &= attribute icon { text }? +attlist.button &= + [ a:defaultValue = "workflow" ] + attribute type { "workflow" | "object" | "action" }? +attlist.button &= attribute confirm { text }? +attlist.button &= attribute name { text } +attlist.button &= attribute states { text }? +notebook = element notebook { attlist.notebook, page* } +attlist.notebook &= + attribute tabpos { "up" | "down" | "left" | "right" }? +attlist.notebook &= [ a:defaultValue = "4" ] attribute colspan { text }? +page = + element page { + attlist.page, + (label + | field + | image + | separator + | newline + | button + | notebook + | group + | hpaned + | vpaned + | properties)* + } +attlist.page &= attribute angle { text }? +attlist.page &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.page &= [ a:defaultValue = "4" ] attribute col { text }? +group = + element group { + attlist.group, + (label + | field + | image + | separator + | newline + | button + | notebook + | group + | hpaned + | vpaned + | properties)* + } +attlist.group &= attribute string { text }? +attlist.group &= [ a:defaultValue = "1" ] attribute colspan { text }? +attlist.group &= + [ a:defaultValue = "0" ] attribute expand { "0" | "1" }? +attlist.group &= [ a:defaultValue = "1" ] attribute fill { "0" | "1" }? +attlist.group &= [ a:defaultValue = "1" ] attribute rowspan { text }? +attlist.group &= [ a:defaultValue = "4" ] attribute col { text }? + +hpaned = element hpaned { attlist.hpaned, child1?, child2? } +attlist.hpaned &= [ a:defaultValue = "4" ] attribute colspan { text }? +attlist.hpaned &= attribute position { text }? + +vpaned = element vpaned { attlist.vpaned, child1?, child2? } +attlist.vpaned &= [ a:defaultValue = "4" ] attribute colspan { text }? +attlist.vpaned &= attribute position { text }? + +child1 = + element child1 { + attlist.child1, + (label + | field + | image + | separator + | newline + | button + | notebook + | group + | hpaned + | vpaned + | properties)* + } +attlist.child1 &= empty + +child2 = + element child2 { + attlist.child2, + (label + | field + | image + | separator + | newline + | button + | notebook + | group + | hpaned + | vpaned + | properties)* + } +attlist.child2 &= empty + +properties = element properties { attlist.properties, empty } +attlist.properties &= empty + +data = element data { attlist.data, xpath+ } +attlist.data &= empty + +xpath = element xpath { attlist.xpath, any } +attlist.xpath &= attribute expr { text } +attlist.xpath &= + [ a:defaultValue = "inside" ] + attribute position { "inside" | "replace" | "after" | "before" }? + +any = + (element * { + attribute * { text }*, + any + } + | text)* +start = data | form diff --git a/trytond/ir/ui/form.rng b/trytond/ir/ui/form.rng new file mode 100644 index 0000000000..439c6ca690 --- /dev/null +++ b/trytond/ir/ui/form.rng @@ -0,0 +1,841 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + top + bottom + + + + + + + + + + + + + + + + + + + + + + + + + + vbar + hbar + line + pie + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + date + char + many2one + date + one2many + selection + float + numeric + float_time + interger + datetime + boolean + text + url + email + callto + sip + sha + reference + binary + many2many + image + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + workflow + object + action + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + up + down + left + right + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inside + replace + after + before + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trytond/ir/ui/graph.rnc b/trytond/ir/ui/graph.rnc new file mode 100644 index 0000000000..4b299e786e --- /dev/null +++ b/trytond/ir/ui/graph.rnc @@ -0,0 +1,40 @@ +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +graph = element graph { attlist.graph, x, y } +attlist.graph &= + [ a:defaultValue = "vbar" ] + attribute type { "vbar" | "hbar" | "line" | "pie" }? +attlist.graph &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.graph &= + [ a:defaultValue = "#f5f5f5" ] attribute background { text }? +attlist.graph &= [ a:defaultValue = "blue" ] attribute color { text }? +attlist.graph &= + [ a:defaultValue = "1" ] attribute legend { "0" | "1" }? +x = element x { attlist.x, field } +attlist.x &= empty +y = element y { attlist.y, field+ } +attlist.y &= empty +field = element field { attlist.field, empty } +attlist.field &= attribute name { text } +attlist.field &= attribute string { text }? +attlist.field &= attribute key { text }? +attlist.field &= attribute domain { text }? +attlist.field &= attribute fill { "0" | "1" }? +attlist.field &= attribute empty { "0" | "1" }? +attlist.field &= attribute color { text }? +attlist.field &= attribute widget { "float_time" }? +data = element data { attlist.data, xpath+ } +attlist.data &= empty +xpath = element xpath { attlist.xpath, any } +attlist.xpath &= attribute expr { text } +attlist.xpath &= + [ a:defaultValue = "inside" ] + attribute position { "inside" | "replace" | "after" | "before" }? +start = data | graph +any = + (element * { + attribute * { text }*, + any + } + | text)* diff --git a/trytond/ir/ui/graph.rng b/trytond/ir/ui/graph.rng new file mode 100644 index 0000000000..22efa7454b --- /dev/null +++ b/trytond/ir/ui/graph.rng @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + vbar + hbar + line + pie + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + float_time + + + + + + + + + + + + + + + + + + + + + + + + + + + + inside + replace + after + before + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trytond/ir/ui/tree.rnc b/trytond/ir/ui/tree.rnc new file mode 100644 index 0000000000..c54f8615c1 --- /dev/null +++ b/trytond/ir/ui/tree.rnc @@ -0,0 +1,55 @@ +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +tree = element tree { attlist.tree, field+ } +attlist.tree &= + [ a:defaultValue = "Unknown" ] attribute string { text }? +attlist.tree &= attribute on_write { text }? +attlist.tree &= attribute editable { "top" | "bottom" }? +attlist.tree &= attribute sequence { text }? +attlist.tree &= attribute colors { text }? +attlist.tree &= + [ a:defaultValue = "0" ] attribute toolbar { "0" | "1" }? +field = element field { attlist.field, empty } +attlist.field &= attribute name { text } +attlist.field &= attribute readonly { text }? +attlist.field &= attribute required { text }? +attlist.field &= + attribute widget { + "char" + | "many2one" + | "date" + | "one2many" + | "selection" + | "float" + | "numeric" + | "float_time" + | "interger" + | "datetime" + | "boolean" + | "text" + | "url" + | "email" + | "callto" + | "sip" + }? +attlist.field &= + [ a:defaultValue = "0" ] attribute select { "0" | "1" | "2" }? +attlist.field &= + [ a:defaultValue = "0" ] attribute tree_invisible { "0" | "1" }? +attlist.field &= attribute icon { text }? +attlist.field &= attribute sum { text }? +attlist.field &= attribute width { text }? +data = element data { attlist.data, xpath+ } +attlist.data &= empty +xpath = element xpath { attlist.xpath, any } +attlist.xpath &= attribute expr { text } +attlist.xpath &= + [ a:defaultValue = "inside" ] + attribute position { "inside" | "replace" | "after" | "before" }? +start = tree | data +any = + (element * { + attribute * { text }*, + any + } + | text)* diff --git a/trytond/ir/ui/tree.rng b/trytond/ir/ui/tree.rng new file mode 100644 index 0000000000..3e240937e7 --- /dev/null +++ b/trytond/ir/ui/tree.rng @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + top + bottom + + + + + + + + + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + char + many2one + date + one2many + selection + float + numeric + float_time + interger + datetime + boolean + text + url + email + callto + sip + + + + + + + + + 0 + 1 + 2 + + + + + + + + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + inside + replace + after + before + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/trytond/tryton.rnc b/trytond/tryton.rnc new file mode 100644 index 0000000000..d8e3b9955b --- /dev/null +++ b/trytond/tryton.rnc @@ -0,0 +1,28 @@ +namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0" + +tryton = element tryton { attlist.tryton, data* } +attlist.tryton &= empty +data = element data { attlist.data, (record | menuitem)* } +attlist.data &= + [ a:defaultValue = "0" ] attribute noupdate { "0" | "1" }? +record = element record { attlist.record, field* } +attlist.record &= attribute model { text } +attlist.record &= attribute id { text } +attlist.record &= + [ a:defaultValue = "0" ] attribute update { "0" | "1" }? +field = element field { attlist.field, text } +attlist.field &= attribute name { text } +attlist.field &= attribute search { text }? +attlist.field &= attribute model { text }? +attlist.field &= attribute ref { text }? +attlist.field &= attribute eval { text }? +attlist.field &= attribute type { "xml" }? +menuitem = element menuitem { attlist.menuitem, empty } +attlist.menuitem &= attribute id { text } +attlist.menuitem &= attribute name { text }? +attlist.menuitem &= attribute icon { text }? +attlist.menuitem &= attribute sequence { text }? +attlist.menuitem &= attribute parent { text }? +attlist.menuitem &= attribute action { text }? +attlist.menuitem &= attribute groups { text }? +start = tryton From b647363bb464a94f731a23ae0910ae257219d416 Mon Sep 17 00:00:00 2001 From: "hartmut@demetrius.muc.goebel-consult.de" Date: Tue, 17 Jun 2008 13:17:48 +0200 Subject: [PATCH 03/11] Use relaxNG for validation. --- trytond/ir/ui/view.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/trytond/ir/ui/view.py b/trytond/ir/ui/view.py index 1178b6ab2b..445eeaea4e 100644 --- a/trytond/ir/ui/view.py +++ b/trytond/ir/ui/view.py @@ -58,14 +58,15 @@ class View(OSV): xml = view.arch.strip() tree = etree.fromstring(xml) - dtd_name = os.path.join(os.path.dirname(__file__), - (view.inherit and view.inherit.type or view.type) + '.dtd') - if hasattr(etree, 'DTD'): - dtd = etree.DTD(file(dtd_name)) - if not dtd.validate(tree): + # validate the tree using RelaxNG + rng_name = os.path.join(os.path.dirname(__file__), + (view.inherit and view.inherit.type or view.type) + '.rng') + if hasattr(etree, 'RelaxNG'): + validator = etree.RelaxNG(file=rng_name) + if not validator.validate(tree): logger = Logger() error_log = reduce(lambda x, y: str(x) + '\n' + str(y), - dtd.error_log.filter_from_errors()) + validator.error_log.filter_from_errors()) logger.notify_channel('ir', LOG_ERROR, 'Invalid xml view:\n%s' % (error_log + '\n' + xml)) return False From 72b872619e87319ad911f7b46bad36e3e15d2682 Mon Sep 17 00:00:00 2001 From: "hartmut@demetrius.muc.goebel-consult.de" Date: Tue, 17 Jun 2008 13:03:02 +0200 Subject: [PATCH 04/11] Removing .dtd files, no longer used. --- trytond/ir/ui/board.dtd | 57 --------------------- trytond/ir/ui/form.dtd | 106 ---------------------------------------- trytond/ir/ui/graph.dtd | 21 -------- trytond/ir/ui/tree.dtd | 21 -------- trytond/tryton.dtd | 22 --------- 5 files changed, 227 deletions(-) delete mode 100644 trytond/ir/ui/board.dtd delete mode 100644 trytond/ir/ui/form.dtd delete mode 100644 trytond/ir/ui/graph.dtd delete mode 100644 trytond/ir/ui/tree.dtd delete mode 100644 trytond/tryton.dtd diff --git a/trytond/ir/ui/board.dtd b/trytond/ir/ui/board.dtd deleted file mode 100644 index 204f4b03a9..0000000000 --- a/trytond/ir/ui/board.dtd +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/trytond/ir/ui/form.dtd b/trytond/ir/ui/form.dtd deleted file mode 100644 index 461241e7ad..0000000000 --- a/trytond/ir/ui/form.dtd +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/trytond/ir/ui/graph.dtd b/trytond/ir/ui/graph.dtd deleted file mode 100644 index 396512c75d..0000000000 --- a/trytond/ir/ui/graph.dtd +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/trytond/ir/ui/tree.dtd b/trytond/ir/ui/tree.dtd deleted file mode 100644 index 81a82650f3..0000000000 --- a/trytond/ir/ui/tree.dtd +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/trytond/tryton.dtd b/trytond/tryton.dtd deleted file mode 100644 index 4134bdfd1e..0000000000 --- a/trytond/tryton.dtd +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - From cd7d1af9026c47298fca429723012982992449c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 17 Jun 2008 13:22:43 +0200 Subject: [PATCH 05/11] Add rng and rnc files to setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3a735e7d4c..1f19b80136 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ setup(name=PACKAGE, 'trytond': ['init.sql'], 'trytond.ir': ['*.xml'], 'trytond.ir.module': ['*.xml'], - 'trytond.ir.ui': ['*.xml', '*.dtd'], + 'trytond.ir.ui': ['*.xml', '*.rng', '*.rnc'], 'trytond.res': ['*.xml'], 'trytond.webdav': ['*.xml'], 'trytond.workflow': ['*.xml'], From 746fae6bd6b1923a2b88bae7fc38eb6024c5055b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 17 Jun 2008 17:10:37 +0200 Subject: [PATCH 06/11] Fix SQL clause for rule test orm. --- trytond/osv/orm.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index 4fe897f360..4b3645143a 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -1128,7 +1128,7 @@ class ORM(object): ' FROM ' + table_query + '\"' + self._table +'\" ' \ 'WHERE id IN ' \ '(' + ','.join([str(x) for x in sub_ids]) + ')'\ - ' AND ' + domain1 + ' ORDER BY ' + \ + ' AND (' + domain1 + ') ORDER BY ' + \ ','.join([self._table + '.' + x[0] + ' ' + x[1] \ for x in self._order])), table_args + domain2) @@ -1365,7 +1365,7 @@ class ORM(object): domain1, domain2 = self.pool.get('ir.rule').domain_get(cursor, user, self._name) if domain1: - domain1 = ' AND ' + domain1 + domain1 = ' AND (' + domain1 + ') ' for i in range((len(ids) / ID_MAX) + \ ((len(ids) % ID_MAX) and 1 or 0)): sub_ids = ids[ID_MAX * i:ID_MAX * (i + 1)] @@ -1491,7 +1491,7 @@ class ORM(object): domain1, domain2 = self.pool.get('ir.rule').domain_get(cursor, user, self._name) if domain1: - domain1 = ' and ' + domain1 + domain1 = ' AND (' + domain1 + ') ' for i in range((len(ids) / ID_MAX) + \ ((len(ids) % ID_MAX) and 1 or 0)): sub_ids = ids[ID_MAX * i:ID_MAX * (i + 1)] From ce7ef7dd0ca0e2177d3ee43e0dd69c4cf1da8000 Mon Sep 17 00:00:00 2001 From: "hartmut@demetrius.muc.goebel-consult.de" Date: Tue, 17 Jun 2008 18:49:49 +0200 Subject: [PATCH 07/11] Allow passing a time.struct_time to report-function 'formatLang()' --- trytond/report/report.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/trytond/report/report.py b/trytond/report/report.py index 8af3ad0c61..666f7e87e7 100644 --- a/trytond/report/report.py +++ b/trytond/report/report.py @@ -537,16 +537,22 @@ class Report(object): (self._name, localcontext.get('language', False) or 'en_US')) if date: - # length of date like 2001-01-01 is ten: - if len(str(value)) == 10: + if isinstance(value, time.struct_time): locale_format = locale.D_FMT - string_pattern = '%Y-%m-%d' + date = value else: - if len(str(value)) > 19: + # assume string, parse it + if len(str(value)) == 10: + # length of date like 2001-01-01 is ten + # assume format '%Y-%m-%d' + locale_format = locale.D_FMT + string_pattern = '%Y-%m-%d' + else: + # assume format '%Y-%m-%d %H:%M:%S' value = str(value)[:19] - locale_format = locale.D_T_FMT - string_pattern = '%Y-%m-%d %H:%M:%S' - date = time.strptime(str(value), string_pattern) + locale_format = locale.D_T_FMT + string_pattern = '%Y-%m-%d %H:%M:%S' + date = time.strptime(str(value), string_pattern) return time.strftime(locale.nl_langinfo(locale_format).\ replace('%y', '%Y'), date) From e934edd6e72c9ddc99311786cbfe5d695dc79797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 18 Jun 2008 11:35:24 +0200 Subject: [PATCH 08/11] Remove size constraint on ir.property fields. Remove search by orm for models_get and use sql to improve speed. --- trytond/ir/property.py | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/trytond/ir/property.py b/trytond/ir/property.py index 77bf2468f8..774a622560 100644 --- a/trytond/ir/property.py +++ b/trytond/ir/property.py @@ -7,38 +7,16 @@ class Property(OSV): "Property" _name = 'ir.property' _description = __doc__ - name = fields.Char('Name', size=128) + name = fields.Char('Name') #TODO add function field for other type than many2one - value = fields.Reference('Value', selection='models_get2', size=128) - res = fields.Reference('Resource', selection='models_get', size=128) + value = fields.Reference('Value', selection='models_get') + res = fields.Reference('Resource', selection='models_get') field = fields.Many2One('ir.model.field', 'Field', - ondelete='cascade', required=True) - - def models_get2(self, cursor, user, context=None): - model_field_obj = self.pool.get('ir.model.field') - #TODO add domain for only reference fields - ids = model_field_obj.search(cursor, user, []) - res = [] - done = {} - for model_field in model_field_obj.browse(cursor, user, ids, - context=context): - if model_field.relation not in done: - res.append([model_field.relation, model_field.relation]) - done[model_field.relation] = True - return res + ondelete='CASCADE', required=True) def models_get(self, cursor, user, context=None): - model_field_obj = self.pool.get('ir.model.field') - #TODO add domain for only reference fields - ids = model_field_obj.search(cursor, user, []) - res = [] - done = {} - for model_field in model_field_obj.browse(cursor, user, ids, - context=context): - if model_field.model.id not in done: - res.append([model_field.model.model, - model_field.model.name]) - done[model_field.model.id] = True + cursor.execute('SELECT model, name FROM ir_model ORDER BY name ASC') + res = cursor.fetchall() + [('', '')] return res def get(self, cursor, user, name, model, res_ids=None, context=None): From 9d6087762dd5a6985487ccda803fa283ba87ff99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 18 Jun 2008 14:58:55 +0200 Subject: [PATCH 09/11] Fix inherit view with position after --- trytond/osv/orm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/trytond/osv/orm.py b/trytond/osv/orm.py index 4b3645143a..c1a5cca64c 100644 --- a/trytond/osv/orm.py +++ b/trytond/osv/orm.py @@ -1961,10 +1961,10 @@ class ORM(object): elif pos == 'after': parent = element.getparent() next = element.getnext() - if next: + if next is not None: for child in element2: index = parent.index(next) - parent.insert(index - 1, child) + parent.insert(index, child) else: parent.extend(element2.getchildren()) elif pos == 'before': From 30f5e4632c36c6165ab5222e4542481e370d7650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 18 Jun 2008 16:17:28 +0200 Subject: [PATCH 10/11] Export db_exist method --- trytond/web_service/db.py | 1 + 1 file changed, 1 insertion(+) diff --git a/trytond/web_service/db.py b/trytond/web_service/db.py index 64fa47cf45..513e904e9a 100644 --- a/trytond/web_service/db.py +++ b/trytond/web_service/db.py @@ -21,6 +21,7 @@ class DB(Service): self.export_method(self.restore) self.export_method(self.list) self.export_method(self.list_lang) + self.export_method(self.db_exist) self.export_method(self.change_admin_password) def create(self, password, db_name, lang): From 79a3e31f57e506a50d1fab8b4bce99d46fd10a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Wed, 18 Jun 2008 22:57:07 +0200 Subject: [PATCH 11/11] Fix format_lang to work on win32 as tryton --- trytond/report/report.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/trytond/report/report.py b/trytond/report/report.py index 666f7e87e7..394e7e86ff 100644 --- a/trytond/report/report.py +++ b/trytond/report/report.py @@ -18,6 +18,12 @@ import time import os import datetime +if not hasattr(locale, 'nl_langinfo'): + locale.nl_langinfo = lambda *a: '%x' + +if not hasattr(locale, 'D_FMT'): + locale.D_FMT = None + MODULE_LIST = [] MODULE_CLASS_LIST = {} CLASS_POOL = {} @@ -538,22 +544,24 @@ class Report(object): localcontext.get('language', False) or 'en_US')) if date: if isinstance(value, time.struct_time): - locale_format = locale.D_FMT + locale_format = locale.nl_langinfo(locale.D_FMT)\ + .replace('%y', '%Y') date = value else: # assume string, parse it if len(str(value)) == 10: # length of date like 2001-01-01 is ten # assume format '%Y-%m-%d' - locale_format = locale.D_FMT + locale_format = locale.nl_langinfo(locale.D_FMT)\ + .replace('%y', '%Y') string_pattern = '%Y-%m-%d' else: # assume format '%Y-%m-%d %H:%M:%S' value = str(value)[:19] - locale_format = locale.D_T_FMT + locale_format = locale.nl_langinfo(locale.D_FMT)\ + .replace('%y', '%Y') + ' %H:%M:%S' string_pattern = '%Y-%m-%d %H:%M:%S' date = time.strptime(str(value), string_pattern) - return time.strftime(locale.nl_langinfo(locale_format).\ - replace('%y', '%Y'), date) + return time.strftime(locale_format, date) return locale.format('%.' + str(digits) + 'f', value, True)