[Libguestfs] Extending the nbdkit python plugin

Richard W.M. Jones rjones at redhat.com
Thu Nov 21 15:54:35 UTC 2019


On Thu, Nov 21, 2019 at 04:49:00PM +0100, Tomáš Golembiovský wrote:
> This may be confusing at first but is not that difficult once you wrap
> your head around it.
> 
> There are two types of arguments in Python: positional(*) and
> keyword(**). There is a rule that all positional arguments are defined
> before the keyword arguments. Also once an argument has a default value
> it is considered keyword (not positional). There are some nuances for
> which is best to reach to some documentation.

Thanks for the explanation.  I think the api_version idea is the way
to go, I have a patch for this coming up.

Rich.

> 
> > Another possibility is we could encourage existing Python plugins to
> > add **kwargs to all functions where we might plausibly add extra
> > parameters in future, ie. the above would become:
> > 
> >   def pwrite (h, buf, offset, **kwargs):
> > 
> > This still requires all Python plugins to change, but at least they
> > would remain backwards compatible with old and new nbdkit.  However I
> > couldn't actually work out how to make this work because:
> > 
> >   >>> def test(a, **kwargs):
> 
> Here you defined single positional argument 'a'.
> 
> >   ...   pass
> >   ... 
> >   >>> test(1)
> >   >>> test(1,2)
> 
> You are passing two positional arguments. A keyword argument has to have
> a name. E.g. this will work: test(1, foo=2)
> 
> >   Traceback (most recent call last):
> >     File "<stdin>", line 1, in <module>
> >   TypeError: test() takes 1 positional argument but 2 were given
> > 
> 
> Check the attached script for some examples. Hopefully that will help
> you get a better grasp.
> 
>     Tomas
> 
> -- 
> Tomáš Golembiovský <tgolembi at redhat.com>

> #!/usr/bin/env python3
> 
> def abc(*args, **kwargs):
>     print(args)
>     print(kwargs)
> 
> def with_positional(a, b, c, *args, **kwargs):
>     print(a, b, c)
>     print(args)
>     print(kwargs)
> 
> # Wrong: cannot define keyword arguments before positional
> #def with_keyword(a=None, b=None, c=None, *args, **kwargs):
> #    pass
> 
> def with_keyword(*args, a=None, b=None, c=None, **kwargs):
>     print(a, b, c)
>     print(args)
>     print(kwargs)
> 
> # This is also possible
> def with_keyword2(*args, a, b, c, **kwargs):
>     pass
>     print(a, b, c)
>     print(args)
>     print(kwargs)
> 
> # (1, 'abc')
> # {'foo': 2, 'bar': 3}
> abc(1, 'abc', foo=2, bar=3)
> # Wrong: cannot pass positional arguments after keyword arguments
> #abc(1, 'abc', foo=2, bar=3, 4, 5)
> print('---')
> 
> # 1 2 3
> # (4, 5)
> # {'foo': 10, 'bar': 11}
> with_positional(1, 2, 3, 4, 5, foo=10, bar=11)
> # Wrong: a,b,c are alrady bound to 4,5,6
> #with_positional(4, 5, 6, foo=10, bar=11, a=1, b=2, c=3)
> 
> # This works as one would expect
> with_positional(a=1, b=2, c=3, foo=10, bar=11)
> # These two are wrong
> #with_positional(4, a=1, b=2, c=3, foo=10, bar=11)
> #with_positional(a=1, b=2, c=3, 4, foo=10, bar=11)
> 
> print('---')
> with_keyword(4, 5, foo=10, bar=11)
> with_keyword(4, 5, foo=10, bar=11, a=1, b=2, c=3)
> 
> # These two are equivalent
> with_keyword2(foo=10, bar=11, a=1, b=2, c=3)
> with_keyword2(a=1, b=2, c=3, foo=10, bar=11)


-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
libguestfs lets you edit virtual machines.  Supports shell scripting,
bindings from many languages.  http://libguestfs.org




More information about the Libguestfs mailing list