Mailinglist Archive: yast-devel (28 mails)

< Previous Next >
Re: [yast-devel] Improving the pkg-bindings API
  • From: Josef Reidinger <jreidinger@xxxxxxx>
  • Date: Wed, 15 May 2019 11:29:25 +0200
  • Message-id: <20190515112925.6a1c3c17@linux-vvcf.privatesite>
V Tue, 14 May 2019 15:04:43 +0200
Ladislav Slezak <lslezak@xxxxxxx> napsáno:

Hi all,

I'd like to discuss how to improve the pkg-bindings API in YaST, more
specifically
the Pkg.ResolvableProperties(name, kind, version) call.

But if you find some other pkg-bindings API calls difficult to use just ping
me,
we can improve more calls.


There are basically two problems with Pkg.ResolvableProperties() call:

- You cannot use any input filters, you can only filter by name, kind or
version.
That's quite limited, for the other cases you need to get *all* objects and
filter
the returned list.

- The result contains all possible attributes for each object, even those you
do not
need in most cases (like the package description and summary, installed
size, RPM
size, full RPM name, vendor, ...). That is wasting the memory space.

If you call Pkg.ResolvableProperties("", :package, "") in Leap with the online
repositories enabled you will get a huge detailed list with about 40.000 (!)
packages. And that requires quite a lot of memory and might freeze the
installer as
reported in [1].


A GraphQL Side Note
-------------------

I was interested in some existing generic solution for this problem. And I
found a
quite nice GraphQL project. It can not only describe the search query but also
describe the result (which objects or attributes you need in the response).

Although there is a C++ library [2] or a Ruby library [3] in the end it looks
like an
overkill for the internal API. But if you would need to design some big and
complicated REST API then you could consider it. See more details in [4] or
in the
specification [5].


The Proposal
============

To not break the backward compatibility we cannot change the
ResolvableProperties()
call so let's create a new one:

# <filter_hash> = required matching values
# <attributes_list> = returned attributes, empty list => return all
Yast::Pkg.Resolvables(<filter_hash>, <attributes_list>)


# a ResolvableProperties() compatible version:
Yast::Pkg.Resolvables({kind: :package, name: "yast2"}, []) => Array<Hash>

[{
"arch"=>"x86_64",
"description"=>
"This package contains scripts and data needed for SUSE Linux\n" +
"installation with YaST2",
"download_size"=>518308,
"inst_size"=>2388454,
"location"=>"yast2-4.0.87-lp150.2.9.1.x86_64.rpm",
"locked"=>false,
"medium_nr"=>1,
"name"=>"yast2",
"on_system_by_user"=>false,
"path"=>"./rpms/x86_64/yast2-4.0.87-lp150.2.9.1.x86_64.rpm",
"source"=>7,
"status"=>:available,
"summary"=>"YaST2 - Main Package",
"transact_by"=>:solver,
"vendor"=>"openSUSE",
"version"=>"4.0.87-lp150.2.9.1",
"version_epoch"=>nil,
"version_release"=>"lp150.2.9.1",
"version_version"=>"4.0.87"
}]


# new functionality: more search criteria and limiting the result:
Yast::Pkg.Resolvables({kind: :package, status: :available, name: "yast2"},
[:name, :version]) => Array<Hash>

[{
"name"=>"yast2",
"version"=>"4.0.87-lp150.2.9.1",
}]


Quite often we just need to know whether an object with some attributes exists
without need to know the specific details, like a package is installed:

Yast::Pkg.AnyResolvable(name: "foo", kind: :package, status: :installed) =>
Boolean

That would be basically the same as Pkg.Resolvables, just returning a simple
Boolean
as the result instead of the details. (And it could be faster, it can return
after
finding the first matching item, it does not need to iterate over all
objects.)


Ruby Wrapper
------------

Unfortunately the C++ Pkg-bindings API does not allow specifying optional
parameters
(that's a limitation of the YaST component system)

In fact there is a way, just not so easy.

see e.g.
https://github.com/yast/yast-core/blob/master/libycp/src/YCPBuiltinPath.cc#L155

so you need to define it multiple times there. ( just note that I do not test
it enough with ruby, as it is used now only in builtins which is already
defined in ruby itself.

I do not test it, but maybe also in ruby you can have something like:

publish function: :test, signature: "string (string)"
publish function: :test, signature: "string (string, string)"

You can try it and maybe it will work. If not, I can check a bit more code as
in general component system should allow it, just ycp does not allow it.

Josef


and cannot provide an
object-oriented API so probably having a small Ruby wrapper would be nice:

Yast::Resolvable.find(<filter_hash>) => Array<Resolvable>)

Where the Resolvable would be an object wrapper for the pkg-bindings Hash.

Examples:

Yast::Resolvable.find(kind: :package, status: :selected)
Yast::Resolvable.find(name: "package", kind: :package, status: :installed)

Similarly for the existence check (just for completeness):

Yast::Resolvable.any?(kind: :package, status: :selected)


I'll propose some code snippets at GitHub, I think it will be better to
discuss some
details in a draft pull request with some real code...



[1] https://bugzilla.suse.com/show_bug.cgi?id=1132650
[2] https://github.com/graphql/libgraphqlparser
[3] https://graphql-ruby.org/
[4] https://graphql.org/
[5] https://graphql.github.io/graphql-spec/


--
To unsubscribe, e-mail: yast-devel+unsubscribe@xxxxxxxxxxxx
To contact the owner, e-mail: yast-devel+owner@xxxxxxxxxxxx

< Previous Next >
References