----- Original Message -----
> On Thu, Apr 04, 2013 at 02:08:48PM -0400, Jiri Zupka wrote:
> > Hi Eduardo,
> > 
> > what do you say?
> > 
> >                                   default
> > variants guest_os:            expand all variants
> >    - linux1:
> >    - linux2:
> > 
> > variants host_os:             take linux1
> >    - @linux1:
> >    - linux2:
> 
> I like this mode of operation. I will refer to it as "non-agressive
> expansion mode". In other words: expand everything if there's no "@",
> and use the "@" option if there's only one.
> 
> The problem is: if we make non-agressive-expansion mode the default, we
> will break compartibility with existing config files/jobs where people
> expect everything to be expanded by default.
> 
> But even if we don't make it the default, it would be nice to have it
> very easy to enable, as it makes sense for many use cases.

I agree with easy enabling and disabling default. In example above missing non 
default mode.
Already implemented.

> 
> > 
> > 
> > First part as we talk before.
> > 
> > 
> > Double default variant:
> > 
> > variants system:               It should be impossible at all? There is
> > some case which uses it.
> >    - @ asaa                    Or there should be other marker? I think and
> >    hope that new marker
> >    - @ aaaa                    will not be necessary but with new maker it
> >    could be cleaner.
> 
> That's a good question. It's all about what makes sense to have enabled
> by default or in a easy-to-enable way. I think I think the most
> intuitive behavior is to simply expand only the "@" items by default if
> we are on non-agressive-expansion mode.
> 
> Also, I would like to have other ways to mark the default options. "@"
> means "hidden" (not appearing in short_name). It is useful to use it
> because it is short and makes sense on many cases, but it would be nice
> to allow the default variant to be chosen without requiring it to be
> "hidden".
> 
> Once we decide to have an extensible syntax to set metadata on
> variants-blocks, we could use it to set the default variant and
> expansion-mode, too. e.g.:
> 
> variants system [default=aaa]:
>   - aaa
>   - bbb
> 
> variants subtest [expand_all=true]:
>   - test1
>   - test2
> 

It could help for future syntax expanding. As Paolo mentioned on github.
And make configuration more flexible for users.

> > 
> > 
> > 1)   Exchange '>' to '='
> > 
> > only host_os=linux2            should work
> > host_os=linux:                 should be condition not assigning value to
> > variable
> > 
> > then there will be impossible do assigning:
> >    var1=sddd:                  not work nobody know if this is condition or
> >    something else.
> >    var2="sddd:"                should work
> 
> Oh, so the problem is the ambiguity when "=" is used on conditional
> "<condition>:" blocks. Now I see.
> 
> > 
> > 2)   Exchange '>' to ':'
> > 
> > only host_os:linux2            should work
> > host_os:linux1: var = 2        could work but not good visible
> 
> Without named variants, "linux1: var = 2" already works, right?

sorry yes, copy paste.. but looks strange.

> 
> > host_os:linux1:                but not work      in my opinion looks
> > strange
> >      var1 = 2
> 
> Without named variants, this:
> 
>   linux1:
>       var1 = 2
> 
> already works, right?

yes
 
> 
> I think ":" would work, but it looks strange because the final ":" has a
> different meaning from the ":" in the middle.
> 
> > 
> > 3)   Exchange '>' to '::'
> >                                little more performance expensive
> 
> Why exactly "::" would have any performance problem?

only comparison of char and multiple char and more one if many times.

> 
> 
> > only host_os::linux2           should work
> > host_os::linux1: var = 2       could work but
> > host_os::linux1:               work but
> >      var1 = 2
> > 
> > 4)   Exchange '>' to '-'
> > 
> > only host_os-linux2           should work
> > host_os-linux1: var = 2       could work but not good visible
> 
> What "not good visible" means?

If you have lots of 

host_os-guest1.virt_os-linux.sdff-aaaaa.

Then it could be hard to see in first sight in logs. could be hidden in text.
And as you wrote before looks like part of name.

> 
> > host_os-linux1:
> >      var1 = 2
> > 
> > Which of this version do you prefer most or do you prefer some different
> > version?
> 
> So, the main problem here seems to be how to make the "<condition>:"
> blocks look good and intuitive.
> 
> The answer is: I don't know! I need to think about it a little.
> Currently I see two main possible approaches:
> 
>  * The ones you proposed above (Use something else than "=").
>    I believe any of ":", "::" or "-" look better than ">". I think I
>    would choose "::". ":" is confusing (see my comment above), "-"
>    doesn't look like an "operator", but just part of the variant name.
>  * Require some kind of delimiter when "=" is involved. e.g.:
>    only [host_os=linux2]
>    [host_os=linux2]: var = 2
>    [host_os=linux2]:
>      var = 2
>    [host_os == "linux2"]: var = 2
> 
> I would love to hear suggestions from others as well. Paolo?

I like this version. It could be easy and fast for parsing. And good visible.
only [host_os=linux2]
[host_os=linux2]: var = 2
[host_os=linux2]: 
      var = 2

  disadvantage: This breaks today syntax. There could be choice
    for named variant and filtering with name in config have to be 

      only [host_os=linux2]

    for unnamed it could stay as it for keep compatibility.

      only linux2 
    but could be replaced by
      only [linux2]


    only [host_os=linux2.guest_os]
      or
    only linux2.guest_os


  host_os=linux2.guest_os:        this will be interpreted like variable 
assignation.
  [host_os=linux2.guest_os]:      condition.

It could be little confusing for users.. 

This version is quite overkill from my point of view.
[host_os == "linux2"]: var = 2

I tried to ask person which never see this syntax how they understand
host_os::linux2 and [host_os=linux2]
and they choosed [host_os=linux2] as more intuitive understandable.

> 
> > 
> > 
> > I like your idea with expand_variants. Which with "run" it is not necessary
> > implement it to
> > cart config directly for now. But for autoserv tests it could be better.
> > 
> > >    # will expand only the "subtest" and "guest_os" variants-block, and
> > >    # automatically choose defaults for every other variants-block:
> > >    c = Parser(..., expand_variants=['subtest', 'guest_os'])
> > >    # For somebody who wants to run the default tests with all Windows
> > >    # versions:
> > >    c = Parser(..., expand_variants=['subtest', 'windows_version'])
> > >    # For somebody who wants to run the default tests with all CPU models,
> > >    # and all guest OSes:
> > >    c = Parser(..., expand_variants=['subtest', 'guest_os', 'cpu_model'])
> > >    # (additional nice-to-have: to allow something like "guest_os.*" to
> > >    # expand a variants-block and all its "sub-variants" (guest OS
> > >    # version, guest OS architecture, etc)
> > 
> > 
> > It is necessary to solve one case where there is unnamed variant with
> > default.
> > Then it impossible to expand unnamed variant with expand_variants=[].
> > By this reason the selection of default variant shouldn't work in this
> > case even if variant name contain @.
> > 
> > example:
> >   variants:                        expand all variant again.
> >     - @first:
> >         var1= xxxxx
> >     - second
> 
> We can make the "@"-by-default case work internally even on unnamed
> blocks, we don't need to make all the filtering/expanding decisions be
> solely based on string parameters. The string parameters are just a way
> to choose a parser/expander behavior that's different from the default.
> 
> Now, if an user wants to be able to manually enable/disable expansion of
> an unnamed variants-block from the command-line or control file, then
> they should add a name to the block to be able to do it. I don't think
> it is a big problem.

Ok, make sense.

> 
> > 
> > Thanks for review and your time:-)
> > Jiří
> > 
> > ----- Original Message -----
> > > On Fri, Mar 29, 2013 at 06:14:09PM +0100, Jiří Župka wrote:
> > > > If default variant is not filtered by only or no filters then
> > > > only default variant is chosen. This behavior was used for optimizing
> > > > of speed of Cartesian config.
> > > > If variants don't have default variant then everything works as usual.
> > > > Default variant must be in variants with with_default exactly one
> > > > times.
> > > > The default variant could be filtered by only, no filter. If default
> > > > variant is filtered from variants then variants works same as usual
> > > > variants with
> > > > default variant.
> > > > 
> > > > For calling Cartesian config from command line is used option
> > > > -d/--defaults:
> > > >    ../virttest/cartesian_config.py -d cfg/cc.cfg
> > > > 
> > > > For calling Cartesian config from python:
> > > >    c = Parser(args[0], defaults=options.defaults, debug=options.debug)
> > > 
> > > I believe we have allow that to be per-variants-block, not
> > > all-or-nothing.
> > > 
> > > For example: the default ./run behavior could be to automatically choose
> > > defaults for every variants-block (guest OS, block format, etc), except
> > > for the "subtests" variants-block.
> > > 
> > > I would like the API to look like this:
> > > 
> > >    # this would be the current behavior:
> > >    c = Parser(..., expand_all_variants=True)
> > >    # will expand only the "subtest" and "guest_os" variants-block, and
> > >    # automatically choose defaults for every other variants-block:
> > >    c = Parser(..., expand_variants=['subtest', 'guest_os'])
> > >    # For somebody who wants to run the default tests with all Windows
> > >    # versions:
> > >    c = Parser(..., expand_variants=['subtest', 'windows_version'])
> > >    # For somebody who wants to run the default tests with all CPU models,
> > >    # and all guest OSes:
> > >    c = Parser(..., expand_variants=['subtest', 'guest_os', 'cpu_model'])
> > >    # (additional nice-to-have: to allow something like "guest_os.*" to
> > >    # expand a variants-block and all its "sub-variants" (guest OS
> > >    # version, guest OS architecture, etc)
> > > 
> > > We could also find a way to encode the "expand_variants" instruction
> > > inside the config file syntax, so people could put that information in
> > > their config file. But that can be done later, after we test if the
> > > concept is really working in the Python API and command-line.
> > > 
> > > > 
> > > > *********  example:
> > > > variants name=tests:
> > > >   - wait:
> > > >        run = "wait"
> > > >        variants:
> > > >          - long:
> > > >             time = short_time
> > > >          - short: long
> > > >             time = logn_time
> > > >   - test2:
> > > >        run = "test1"
> > > > 
> > > > variants name=virt_system, with_default:
> > > >   - @linux:
> > > >   - windows:
> > > > 
> > > > variants name=host_os, with_default:
> > > >   - linux:
> > > >        image = linux
> > > >        variants with_default:
> > > >             - ubuntu:
> > > >             - @fedora:
> > > >   - windows:
> > > >        image = windows
> > > >        variants:
> > > >             - @XP:
> > > >             - WIN7:
> > > > 
> > > > only host_os>windows
> > > > 
> > > > In this case is chosen from host_os variants windows variant.
> > > > host_os>windows was choosen because default variant linux was filtered.
> > > > Next step is select one variant from guest_os. There will be chosen
> > > > only
> > > > default variant linux because not filtered and virt_system variant is
> > > > with with_default. There is no default variant in tests variants
> > > > because
> > > > that all of tests will be chosen.
> > > > 
> > > > ********  output:
> > > > dict    1:  host_os>windows.tests>wait.long
> > > >     dep = []
> > > >     host_os = windows
> > > >     image = windows
> > > >     name = host_os>windows.XP.virt_system>linux.tests>wait.long
> > > >     run = wait
> > > >     shortname = host_os>windows.tests>wait.long
> > > >     tests = wait
> > > >     time = short_time
> > > >     virt_system = linux
> > > > dict    2:  host_os>windows.tests>wait.short
> > > >     dep = ['host_os>windows.XP.virt_system>linux.tests>wait.long']
> > > >     host_os = windows
> > > >     image = windows
> > > >     name = host_os>windows.XP.virt_system>linux.tests>wait.short
> > > >     run = wait
> > > >     shortname = host_os>windows.tests>wait.short
> > > >     tests = wait
> > > >     time = logn_time
> > > >     virt_system = linux
> > > > dict    3:  host_os>windows.tests>test2
> > > >     dep = []
> > > >     host_os = windows
> > > >     image = windows
> > > >     name = host_os>windows.XP.virt_system>linux.tests>test2
> > > >     run = test1
> > > >     shortname = host_os>windows.tests>test2
> > > >     tests = test2
> > > >     virt_system = linux
> > > > dict    4:  host_os>windows.WIN7.tests>wait.long
> > > >     dep = []
> > > >     host_os = windows
> > > >     image = windows
> > > >     name = host_os>windows.WIN7.virt_system>linux.tests>wait.long
> > > >     run = wait
> > > >     shortname = host_os>windows.WIN7.tests>wait.long
> > > >     tests = wait
> > > >     time = short_time
> > > >     virt_system = linux
> > > > dict    5:  host_os>windows.WIN7.tests>wait.short
> > > >     dep = ['host_os>windows.WIN7.virt_system>linux.tests>wait.long']
> > > >     host_os = windows
> > > >     image = windows
> > > >     name = host_os>windows.WIN7.virt_system>linux.tests>wait.short
> > > >     run = wait
> > > >     shortname = host_os>windows.WIN7.tests>wait.short
> > > >     tests = wait
> > > >     time = logn_time
> > > >     virt_system = linux
> > > > dict    6:  host_os>windows.WIN7.tests>test2
> > > >     dep = []
> > > >     host_os = windows
> > > >     image = windows
> > > >     name = host_os>windows.WIN7.virt_system>linux.tests>test2
> > > >     run = test1
> > > >     shortname = host_os>windows.WIN7.tests>test2
> > > >     tests = test2
> > > >     virt_system = linux
> > > > 
> > > > Signed-off-by: Jiří Župka <[email protected]>
> > > > ---
> > > >  virttest/cartesian_config.py | 82
> > > >  ++++++++++++++++++++++++++++++++++++--------
> > > >  1 file changed, 68 insertions(+), 14 deletions(-)
> > > > 
> > > > diff --git a/virttest/cartesian_config.py
> > > > b/virttest/cartesian_config.py
> > > > index 04ed2b5..6cd0e88 100755
> > > > --- a/virttest/cartesian_config.py
> > > > +++ b/virttest/cartesian_config.py
> > > > @@ -131,6 +131,10 @@ class ParserError:
> > > >              return "%s (%s:%s)" % (self.msg, self.filename,
> > > >              self.linenum)
> > > >  
> > > >  
> > > > +class MissingDefault:
> > > > +    pass
> > > > +
> > > > +
> > > >  class MissingIncludeError:
> > > >      def __init__(self, line, filename, linenum):
> > > >          self.line = line
> > > > @@ -225,6 +229,7 @@ class Node(object):
> > > >          self.labels = set()
> > > >          self.append_to_shortname = False
> > > >          self.failed_cases = collections.deque()
> > > > +        self.default = False
> > > >  
> > > >  
> > > >      def dump(self, indent, recurse=False):
> > > > @@ -407,14 +412,17 @@ class Parser(object):
> > > >  
> > > >      @see:
> > > >      
> > > > https://github.com/autotest/autotest/wiki/KVMAutotest-CartesianConfigParametersIntro
> > > >      """
> > > > -    def __init__(self, filename=None, debug=False):
> > > > +    def __init__(self, filename=None, defaults=False, debug=False):
> > > >          """
> > > >          Initialize the parser and optionally parse a file.
> > > >  
> > > >          @param filename: Path of the file to parse.
> > > > +        @param defaults: If True adds only defaults variant from
> > > > variants
> > > > +                         if there is some.
> > > >          @param debug: Whether to turn on debugging output.
> > > >          """
> > > >          self.node = Node()
> > > > +        self.defaults = defaults
> > > >          self.debug = debug
> > > >          if filename:
> > > >              self.parse_file(filename)
> > > > @@ -611,10 +619,18 @@ class Parser(object):
> > > >  
> > > >          # Recurse into children
> > > >          count = 0
> > > > -        for n in node.children:
> > > > -            for d in self.get_dicts(n, ctx, new_content, shortname,
> > > > dep):
> > > > -                count += 1
> > > > -                yield d
> > > > +        if self.defaults:
> > > > +            for n in node.children:
> > > > +                for d in self.get_dicts(n, ctx, new_content,
> > > > shortname,
> > > > dep):
> > > > +                    count += 1
> > > > +                    yield d
> > > > +                if n.default and count:
> > > > +                    break
> > > > +        else:
> > > > +            for n in node.children:
> > > > +                for d in self.get_dicts(n, ctx, new_content,
> > > > shortname,
> > > > dep):
> > > > +                    count += 1
> > > > +                    yield d
> > > >          # Reached leaf?
> > > >          if not node.children:
> > > >              self._debug("    reached leaf, returning it")
> > > > @@ -656,7 +672,8 @@ class Parser(object):
> > > >          print s % args
> > > >  
> > > >  
> > > > -    def _parse_variants(self, cr, node, prev_indent=-1,
> > > > var_name=None):
> > > > +    def _parse_variants(self, cr, node, prev_indent=-1, var_name=None,
> > > > +                        with_default=False):
> > > >          """
> > > >          Read and parse lines from a FileReader object until a line
> > > >          with an
> > > >          indent level lower than or equal to prev_indent is
> > > >          encountered.
> > > > @@ -665,8 +682,10 @@ class Parser(object):
> > > >          @param node: A node to operate on.
> > > >          @param prev_indent: The indent level of the "parent" block.
> > > >          @param var_name: Variants name
> > > > +        @param with_default: Variants take only default variant.
> > > >          @return: A node object.
> > > >          """
> > > > +        already_default = False
> > > >          node4 = Node()
> > > >  
> > > >          while True:
> > > > @@ -694,7 +713,9 @@ class Parser(object):
> > > >              node2.labels = node.labels
> > > >  
> > > >              node3 = self._parse(cr, node2, prev_indent=indent)
> > > > -            node3.name = [Label(var_name, n) for n in
> > > > name.lstrip("@").split(".")]
> > > > +            is_default = name.startswith("@")
> > > > +            name = name.lstrip("@")
> > > > +            node3.name = [Label(var_name, n) for n in name.split(".")]
> > > >              node3.dep = [Label(var_name, d) for d in dep.replace(",",
> > > >              "
> > > >              ").split()]
> > > >  
> > > >              if var_name:
> > > > @@ -702,12 +723,33 @@ class Parser(object):
> > > >                  op_match = _ops_exp.search(l)
> > > >                  node3.content += [(cr.filename, linenum, Op(l,
> > > >                  op_match))]
> > > >  
> > > > -            is_default = name.startswith("@")
> > > > -
> > > > -            node4.children += [node3]
> > > > +            node3.append_to_shortname = not is_default
> > > > +
> > > > +            if with_default and self.defaults:
> > > > +                """
> > > > +                Relevant only if defaults is True and
> > > > +                variants is with default.
> > > > +                """
> > > > +                if is_default:
> > > > +                    if not already_default:
> > > > +                        node3.default = True
> > > > +                        already_default = True
> > > > +                    else:
> > > > +                        raise MissingDefault
> > > > +                if node3.default:
> > > > +                    # Move default variant in front of rest of all
> > > > variants.
> > > > +                    # Speed optimization.
> > > > +                    node4.children.insert(0, node3)
> > > > +                else:
> > > > +                    node4.children += [node3]
> > > > +            else:
> > > > +                node4.children += [node3]
> > > >              node4.labels.update(node3.labels)
> > > >              node4.labels.update(node3.name)
> > > >  
> > > > +        if with_default and not already_default:
> > > > +            raise MissingDefault
> > > > +
> > > >          return node4
> > > >  
> > > >  
> > > > @@ -751,6 +793,7 @@ class Parser(object):
> > > >                                  char in "._-=,"):
> > > >                              raise ParserError("Illegal characters in
> > > >                              variants",
> > > >                                                line, cr.filename,
> > > >                                                linenum)
> > > > +                with_default = False
> > > >                  var_name = None
> > > >                  if name:
> > > >                      block = name.split(",")
> > > > @@ -761,12 +804,20 @@ class Parser(object):
> > > >                                  raise ParserError("Missing name of
> > > >                                  variants",
> > > >                                                    line, cr.filename,
> > > >                                                    linenum)
> > > >                              var_name = oper[1].strip()
> > > > +                        elif "with_default" in oper[0]:
> > > > +                            with_default = True
> > > >                          else:
> > > >                              raise ParserError("Ilegal variants param",
> > > >                                                 line, cr.filename,
> > > >                                                 linenum)
> > > > -                node = self._parse_variants(cr, node,
> > > > prev_indent=indent,
> > > > -                                            var_name=var_name)
> > > > -                                            var_name=name)
> > > > +                try:
> > > > +                    node = self._parse_variants(cr, node,
> > > > prev_indent=indent,
> > > > +                                                var_name=var_name,
> > > > +
> > > > with_default=with_default)
> > > > +                except MissingDefault:
> > > > +                    raise ParserError("There must be exactly one
> > > > default "
> > > > +                                      "variant in variants with param
> > > > "
> > > > +                                      "with_default.",
> > > > +                                      line, cr.filename, linenum)
> > > >                  continue
> > > >  
> > > >              # Parse 'include' statements
> > > > @@ -1040,12 +1091,15 @@ if __name__ == "__main__":
> > > >                        help="show dict contents")
> > > >      parser.add_option("-r", "--repr", dest="repr_mode",
> > > >      action="store_true",
> > > >                        help="Output parsing results Python format")
> > > > +    parser.add_option("-d", "--defaults", dest="defaults",
> > > > action="store_true",
> > > > +                      help="use only default variant of variants if
> > > > there"
> > > > +                           " is some")
> > > >  
> > > >      options, args = parser.parse_args()
> > > >      if not args:
> > > >          parser.error("filename required")
> > > >  
> > > > -    c = Parser(args[0], debug=options.debug)
> > > > +    c = Parser(args[0], defaults=options.defaults,
> > > > debug=options.debug)
> > > >      for s in args[1:]:
> > > >          c.parse_string(s)
> > > >  
> > > > --
> > > > 1.8.1.4
> > > > 
> > > 
> > > --
> > > Eduardo
> > > 
> 
> --
> Eduardo
> 

_______________________________________________
Virt-test-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/virt-test-devel

Reply via email to