summaryrefslogtreecommitdiff
path: root/python/vyos/xml/definition.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/vyos/xml/definition.py')
-rw-r--r--python/vyos/xml/definition.py360
1 files changed, 0 insertions, 360 deletions
diff --git a/python/vyos/xml/definition.py b/python/vyos/xml/definition.py
deleted file mode 100644
index bc3892b42..000000000
--- a/python/vyos/xml/definition.py
+++ /dev/null
@@ -1,360 +0,0 @@
-# Copyright (C) 2020 VyOS maintainers and contributors
-#
-# This library is free software; you can redistribute it and/or modify it under the terms of
-# the GNU Lesser General Public License as published by the Free Software Foundation;
-# either version 2.1 of the License, or (at your option) any later version.
-#
-# This library 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 Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License along with this library;
-# if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-from vyos.xml import kw
-
-# As we index by key, the name is first and then the data:
-# {'dummy': {
-# '[node]': '[tagNode]',
-# 'address': { ... }
-# } }
-
-# so when we encounter a tagNode, we are really encountering
-# the tagNode data.
-
-
-class XML(dict):
- def __init__(self):
- self[kw.tree] = {}
- self[kw.priorities] = {}
- self[kw.owners] = {}
- self[kw.default] = {}
- self[kw.tags] = []
- self[kw.component_version] = {}
-
- dict.__init__(self)
-
- self.tree = self[kw.tree]
- # the options which matched the last incomplete world we had
- # or the last word in a list
- self.options = []
- # store all the part of the command we processed
- self.inside = []
- # should we check the data pass with the constraints
- self.check = False
- # are we still typing a word
- self.filling = False
- # do what have the tagNode value ?
- self.filled = False
- # last word seen
- self.word = ''
- # do we have all the data we want ?
- self.final = False
- # do we have too much data ?
- self.extra = False
- # what kind of node are we in plain vs data not
- self.plain = True
-
- def reset(self):
- self.tree = self[kw.tree]
- self.options = []
- self.inside = []
- self.check = False
- self.filling = False
- self.filled = False
- self.word = ''
- self.final = False
- self.extra = False
- self.plain = True
-
- # from functools import lru_cache
- # @lru_cache(maxsize=100)
- # XXX: need to use cachetool instead - for later
-
- def traverse(self, cmd):
- self.reset()
-
- # using split() intead of split(' ') eats the final ' '
- words = cmd.split(' ')
- passed = []
- word = ''
- data_node = False
- space = False
-
- while words:
- word = words.pop(0)
- space = word == ''
- perfect = False
- if word in self.tree:
- passed = []
- perfect = True
- self.tree = self.tree[word]
- data_node = self.tree[kw.node]
- self.inside.append(word)
- word = ''
- continue
- if word and data_node:
- passed.append(word)
-
- is_valueless = self.tree.get(kw.valueless, False)
- is_leafNode = data_node == kw.leafNode
- is_dataNode = data_node in (kw.leafNode, kw.tagNode)
- named_options = [_ for _ in self.tree if not kw.found(_)]
-
- if is_leafNode:
- self.final = is_valueless or len(passed) > 0
- self.extra = is_valueless and len(passed) > 0
- self.check = len(passed) >= 1
- else:
- self.final = False
- self.extra = False
- self.check = len(passed) == 1 and not space
-
- if self.final:
- self.word = ' '.join(passed)
- else:
- self.word = word
-
- if self.final:
- self.filling = True
- else:
- self.filling = not perfect and bool(cmd and word != '')
-
- self.filled = self.final or (is_dataNode and len(passed) > 0 and word == '')
-
- if is_dataNode and len(passed) == 0:
- self.options = []
- elif word:
- if data_node != kw.plainNode or len(passed) == 1:
- self.options = [_ for _ in self.tree if _.startswith(word)]
- self.options.sort()
- else:
- self.options = []
- else:
- self.options = named_options
- self.options.sort()
-
- self.plain = not is_dataNode
-
- # self.debug()
-
- return self.word
-
- def speculate(self):
- if len(self.options) == 1:
- self.tree = self.tree[self.options[0]]
- self.word = ''
- if self.tree.get(kw.node,'') not in (kw.tagNode, kw.leafNode):
- self.options = [_ for _ in self.tree if not kw.found(_)]
- self.options.sort()
-
- def checks(self, cmd):
- # as we move thought the named node twice
- # the first time we get the data with the node
- # and the second with the pass parameters
- xml = self[kw.tree]
-
- words = cmd.split(' ')
- send = True
- last = []
- while words:
- word = words.pop(0)
- if word in xml:
- xml = xml[word]
- send = True
- last = []
- continue
- if xml[kw.node] in (kw.tagNode, kw.leafNode):
- if kw.constraint in xml:
- if send:
- yield (word, xml[kw.constraint])
- send = False
- else:
- last.append((word, None))
- if len(last) >= 2:
- yield last[0]
-
- def summary(self):
- yield ('enter', '[ summary ]', str(self.inside))
-
- if kw.help not in self.tree:
- yield ('skip', '[ summary ]', str(self.inside))
- return
-
- if self.filled:
- return
-
- yield('', '', '\nHelp:')
-
- if kw.help in self.tree:
- summary = self.tree[kw.help].get(kw.summary)
- values = self.tree[kw.help].get(kw.valuehelp, [])
- if summary:
- yield(summary, '', '')
- for value in values:
- yield(value[kw.format], value[kw.description], '')
-
- def constraint(self):
- yield ('enter', '[ constraint ]', str(self.inside))
-
- if kw.help in self.tree:
- yield ('skip', '[ constraint ]', str(self.inside))
- return
- if kw.error not in self.tree:
- yield ('skip', '[ constraint ]', str(self.inside))
- return
- if not self.word or self.filling:
- yield ('skip', '[ constraint ]', str(self.inside))
- return
-
- yield('', '', '\nData Constraint:')
-
- yield('', 'constraint', str(self.tree[kw.error]))
-
- def listing(self):
- yield ('enter', '[ listing ]', str(self.inside))
-
- # only show the details when we passed the tagNode data
- if not self.plain and not self.filled:
- yield ('skip', '[ listing ]', str(self.inside))
- return
-
- yield('', '', '\nPossible completions:')
-
- options = list(self.tree.keys())
- options.sort()
- for option in options:
- if kw.found(option):
- continue
- if not option.startswith(self.word):
- continue
- inner = self.tree[option]
- prefix = '+> ' if inner.get(kw.node, '') != kw.leafNode else ' '
- if kw.help in inner:
- yield (prefix + option, inner[kw.help].get(kw.summary), '')
- else:
- yield (prefix + option, '(no help available)', '')
-
- def debug(self):
- print('------')
- print("word '%s'" % self.word)
- print("filling " + str(self.filling))
- print("filled " + str(self.filled))
- print("final " + str(self.final))
- print("extra " + str(self.extra))
- print("plain " + str(self.plain))
- print("options " + str(self.options))
-
- # from functools import lru_cache
- # @lru_cache(maxsize=100)
- # XXX: need to use cachetool instead - for later
-
- def component_version(self) -> dict:
- d = {}
- for k in sorted(self[kw.component_version]):
- d[k] = int(self[kw.component_version][k])
- return d
-
- def defaults(self, lpath, flat):
- d = self[kw.default]
- for k in lpath:
- d = d.get(k, {})
-
- if not flat:
- # _flatten will make this conversion
- d = self.multi_to_list(lpath, d, defaults=True)
-
- r = {}
- for k in d:
- under = k.replace('-','_')
- if isinstance(d[k],dict):
- r[under] = self.defaults(lpath + [k], flat)
- continue
- r[under] = d[k]
- return r
-
- def _flatten(inside, index, d):
- r = {}
- local = inside[index:]
- prefix = '_'.join(_.replace('-','_') for _ in local) + '_' if local else ''
- for k in d:
- under = prefix + k.replace('-','_')
- level = inside + [k]
- if isinstance(d[k],dict):
- r.update(_flatten(level, index, d[k]))
- continue
- if self.is_multi(level, with_tag=False):
- r[under] = [_.strip() for _ in d[k].split(',')]
- continue
- r[under] = d[k]
- return r
-
- return _flatten(lpath, len(lpath), d)
-
- def multi_to_list(self, lpath, conf, defaults=False):
- r = {}
- for k in conf:
- # key mangling could also be done here
- # it would prevent two parsing of the config tree
- # under = k.replace('-','_')
- under = k
- fpath = lpath + [k]
- if isinstance(conf[k],dict):
- r[under] = self.multi_to_list(fpath, conf[k], defaults)
- continue
- value = conf[k]
- if self.is_multi(fpath) and not isinstance(value, list):
- if not defaults:
- value = [value]
- else:
- value = value.split(' ')
- r[under] = value
- return r
-
- # from functools import lru_cache
- # @lru_cache(maxsize=100)
- # XXX: need to use cachetool instead - for later
-
- def _tree(self, lpath, with_tag=True):
- """
- returns the part of the tree searched or None if it does not exists
- if with_tag is set, this is a configuration path (with tagNode names)
- and tag name will be removed from the path when traversing the tree
- """
- tree = self[kw.tree]
- spath = lpath.copy()
- while spath:
- p = spath.pop(0)
- if p not in tree:
- return None
- tree = tree[p]
- if with_tag and spath and tree[kw.node] == kw.tagNode:
- spath.pop(0)
- return tree
-
- def _get(self, lpath, tag, with_tag=True):
- tree = self._tree(lpath, with_tag)
- if tree is None:
- return None
- return tree.get(tag, None)
-
- def is_multi(self, lpath, with_tag=True):
- tree = self._get(lpath, kw.multi, with_tag)
- if tree is None:
- return None
- return tree is True
-
- def is_tag(self, lpath, with_tag=True):
- tree = self._get(lpath, kw.node, with_tag)
- if tree is None:
- return None
- return tree == kw.tagNode
-
- def is_leaf(self, lpath, with_tag=True):
- tree = self._get(lpath, kw.node, with_tag)
- if tree is None:
- return None
- return tree == kw.leafNode
-
- def exists(self, lpath, with_tag=True):
- return self._get(lpath, kw.node, with_tag) is not None