So Tim, I've talked with another kde dev, and we are planning to translate the ppds.py to C.
As I said earlier:
Well IMO there is no much use for GetMakes, GetModels outside printing tools, also if you do getPPDS you will already have them all.
I think the best thing to do would be to create a method like
IppResult* getBestPPDForID(char *id, IppResult *resultOfPPDS) { this way I can use my QCups class which handles the authentication on cups for me (with DBus the user would have to authenticate twice) then getAllPPDS and pass the cups result to here. Cups server (631) could use this method easily. here there would be the ppd.py code
And returning a new object of IppResult with the best matching ppds ordered. ppds.py isn't that hard to convert here and once done, it would be easier for most KDE devs (which most of them only know C/C++) to help improving the matcher... }
So what do you think of this? I think it's a good start, if you can put this lib in py-cups binding we can work latter on the XML thing that you are working on now.
Having this as a C lib might even be added directly in CUPS thus maybe having Apple (cups devs) to help too.
It would be great if we could do an ippRequest(get-best-ppds) on the server.
Best.
.................................
Hi Daniel,
It's great to hear that the KDE printing tools will be getting some more traction.
On Fri, 2010-11-19 at 16:52 -0800, Daniel Nicoletti wrote:
Well I'm writing new printing tools for KDE with C++, and the thing that these tools are missing is the logic that the python ppd.py file has. As we talked it would be great if that file were converted to C, this way you could write your py bindings around it I could use it easily in my KDE code and even http://localhost:631 could use it.
What I've been trying to get to in preparation for system-config-printer 1.3 is the ability to have D-Bus activation for various parts of the program. I've been concentrating so far on the UI parts (e.g. various dialogs), but it would also be great to have an activatable system service which would provide the interface from ppds.py.
That way it would be usable from any language. I think this would also be the quickest way to make this code usable from any language, rather than converting to the lowest common denominator.
I'm hoping to release 1.2.95 shortly which has several interface changes compared to 1.2.4. In particular, with the PPDs class, there is a new concept of "fit", i.e. how well the driver matches to a particular printer. This is a better and more descriptive model than the status codes used in 1.2.x. A new method, getPPDNamesFromDeviceID, returns the complete set of candidate drivers for a given printer along with how well each fits.
So we could have an interface "….Printing" with methods:
* "SplitMakeAndModel" for converting ppd-make-and-model strings into separate strings for make and model, and
* "GetPPDsMatcher" for creating a new PPDs object for a particular language and returning its object path
This PPDsMatcher object could itself have an interface containing:
* GetMakes, returning a UTF-8 string list * GetModels, given a make, returning a UTF-8 string list * GetInfoFromModel, returning a list of attributes given a make and model * GetInfoFromPPDName, returning a list of attributes given a PPD name * GetPreferredPPDNamesFromDeviceID, returning a list of tuples of PPD names and how well each fits, in preference order using the new XML-driven method¹ (this would be a combination of getPPDNamesFromDeviceID and orderPPDNamesByPreference)
Not entirely sure yet what the D-Bus signature for a list of attributes would be: perhaps a{sav}, or perhaps something simpler.
What do you think about this approach?
Tim. */ ________________________________ Daniel Nicoletti - KDE Developer http://dantti.wordpress.com When a wicked man dies, his hope perishes; all he expected from his power comes to nothing. Prov. 11:7
On Sat, 2010-11-20 at 11:30 -0800, Daniel Nicoletti wrote:
So Tim, I've talked with another kde dev, and we are planning to translate the ppds.py to C.
OK. Please bear in mind that you'll also need to convert cupshelpers/xmldriverprefs.py as well.
It would be great to have this work in progress go in a branch from master. Will you have your own git repository tracking it, or be working in the main fedoraproject.org git repository?
If you do the work as a GObject, Python bindings will be more or less automatic via gir. http://live.gnome.org/GObjectIntrospection
By converting the entire thing to C, you'll still need to preserve the core methods such as getMakes and getModels. You don't get them automatically from CUPS-Get-PPDs, just a list of ppd-make-and-model strings. In simply providing the other interface methods, these lists of makes and models have to be calculated -- hiding them just means the work has to be duplicated elsewhere in the program.
I think the best thing to do would be to create a method like
IppResult* getBestPPDForID(char *id, IppResult *resultOfPPDS) { this way I can use my QCups class which handles the authentication on cups for me (with DBus the user would have to authenticate twice) then getAllPPDS and pass the cups result to here. Cups server (631) could use this method easily. here there would be the ppd.py code
Why do you say that D-Bus would require the user to authenticate twice? Also, in C, surely we'd be using real CUPS types such as ipp_t*?
So what do you think of this? I think it's a good start, if you can put this lib in py-cups binding we can work latter on the XML thing that you are working on now.
I don't see the point in starting with old code. Why not use what's currently in master? It will be more than double the work if you have to redo it, not least because the interface is different.
The work belongs in system-config-printer, not in pycups (which is just what it says and no more). There are already exported interfaces in system-config-printer such as the Python cupshelpers modules -- including cupshelpers/ppds.py, which is what we're talking about.
The interface currently looks like this, excluding deprecated/obsolete parts:
ppdmakeModelSplit: string -> (string, string)
For converting a ppd-make-and-model string into separate make and model strings. This is more expensive than it sounds.
PPDs: constructor: with * result of CUPS-Get-PPDs * optional language name (for native language filtering) * optional XML directory for preferreddrivers.xml
getMakes: void -> string list
getModels: string -> string list
getInfoFromModel: (string, string) -> list of suitable PPDs (unordered)
getInfoFromPPDName: string -> PPD attributes
getPPDNamesFromDeviceID: (broken-down device-id, device-uri, device-make-and-model) -> dict of PPD name:fit
orderPPDNamesByPreference: all params from previous function plus list of downloaded file names to prefer -> sorted string list of PPD names
The downloaded file name thing is so that distributions using Jockey can automatically prefer drivers they've just downloaded (although there's no real reason they can't just look to see which drivers are new...).
So before starting, perhaps it would be nice to make sure the interface we're starting with makes sense. In that spirit, I'll suggest changing 'getPPDNamesFromDeviceID' so that it returns a list of (PPD name, fit) tuples, sorted by preference. That eliminates the need for orderPPDNamesByPreference.
==
How might the C interface look?
Having this as a C lib might even be added directly in CUPS thus maybe having Apple (cups devs) to help too.
I really don't think that would happen, but you'd have to talk to Michael Sweet. Choosing a "best" driver has long been something that the CUPS server is neutral on.
Tim. */
OK. Please bear in mind that you'll
also need to convert
cupshelpers/xmldriverprefs.py as well.
Sure,
It would
be great to have this work in progress go in a branch from
master. Will
you have your own git repository tracking it, or be
working in the main
fedoraproject.org git repository?
I think creating this branch is best, though to be honest, the end of year is a rush, and I'm not sure I'll have time again to work on this ... kde ppl will kill me :P
If you do the work as a GObject, Python
bindings will be more or less
automatic via gir.
href="http://live.gnome.org/GObjectIntrospection" target=_blank
The problem here is that GObject means glib which is not used in cups server.
By converting the entire
thing to C, you'll still need to preserve the
core methods such as getMakes and getModels. You don't get them automatically from CUPS-Get-PPDs, just a list of ppd-make-and-model strings. In simply providing the other interface methods, these lists of makes and models have to be calculated -- hiding them just means the work has to be duplicated elsewhere in the program.
well, at least to get all models iirc there is a get method for that, have to look at admin.c again.
I think the best thing to do would be to create a method like
IppResult* getBestPPDForID(char *id, IppResult *resultOfPPDS) { this way I can use my QCups class which handles the authentication on cups for me (with DBus the user would have to authenticate twice) then getAllPPDS and pass the cups result to here. Cups server (631) could use this method easily. here there would be the ppd.py code
Why do you say that D-Bus would require the user to authenticate twice?
Well first to get the devices (done by qcups) and then to get the ppds list (done by pppds.py).
Also, in C, surely we'd be using real CUPS types such as ipp_t*?
yes cups types it's just that I forgot the name of the type.
So what do you think of this? I think it's a good start, if you can put this lib in py-cups binding we can work
latter on the XML thing that you are working on now.
I don't see the point in starting with old code. Why not use what's currently in master? It will be more than double the work if you have to redo it, not least because the interface is different.
What I see in master is both ppds.py and the xml.py thing so I didn't knew ppds.py was deprecated.
The work belongs in system-config-printer, not in pycups (which is just what it says and no more). There are already exported interfaces in system-config-printer such as the Python cupshelpers modules -- including cupshelpers/ppds.py, which is what we're talking about.
well but in C you could access them through pycups which, would be the same thing in the end I think.
How might the C interface look?
well surely you know these methods better that I do, but I think we can have them all and using the cups types to make it easy to play with.
Having this as a C lib might even be added directly in CUPS thus maybe having Apple (cups devs) to help too.
I really don't think that would happen, but you'd have to talk to Michael Sweet. Choosing a "best" driver has long been something that the CUPS server is neutral on.
Well if it doesn't get accepted by upstream we can patch it downstream easily I think. It would be pretty handy since most printing servers I see the admins only use the cups server interface.
Best, Daniel.
On Mon, 2010-11-22 at 12:53 -0800, Daniel Nicoletti wrote:
If you do the work as a GObject, Python
bindings will be more or less
automatic via gir.
href="http://live.gnome.org/GObjectIntrospection" target=_blank
The problem here is that GObject means glib which is not used in cups server.
As I've said before, I think it quite unlikely that this would ever be used by the CUPS server, but Michael Sweet would be the one with the answer to that.
In any case, whether a particular library does or does not use glib is only visible in terms of the dependencies pulled in. The end result would include an XML parser, of course, so glib is hardly the final straw when it comes to added dependencies!
well, at least to get all models iirc there is a get method for that, have to look at admin.c again.
Well, CUPS has no inherent notion of there being different models of printer. It only knows about different PPDs. A given PPD can declare its manufacturer (this is exposed by CUPS in the ppd-make attribute), and its "nickname", i.e. a combination of the model name, possibly including the manufacturer's name, and the driver used, often as well as other bits of information. This is exposed by CUPS in the ppd-make-and-model attribute.
This is why cupshelpers.ppds has a fairly expensive ppdMakeModelSplit() function: in order to collect together PPDs which are for the same physical printer model.
Well first to get the devices (done by qcups) and then to get the ppds list (done by pppds.py).
Ah. But cupshelpers.ppds doesn't interact with the CUPS service at all. It only processes an IPP result. Think of the PPDs object as the representation of a set of PPDs, and the actions you'd like to perform with them.
What I see in master is both ppds.py and the xml.py thing so I didn't knew ppds.py was deprecated.
No, ppds.py is not deprecated, but the interface it provides is substantially different. The "old" interface gave only one PPD, the "best", when matching a Device ID; the "new" interface gives an ordered list of all the appropriate drivers, in descending order of preference. This allows the interface to present choices based on the Device ID from the printer, something that allows the user to be more sure of getting their printer to work.
For example, if a particular printer is driven by gutenprint (and gutenprint declares the Device ID of that printer in its PPD), the "best" printer driver might be gutenprint. But if that driver doesn't work, the user has to look for other drivers. There may only be generic drivers as alternatives, and we can only offer those based on the Device ID's "CMD" field.
Another important change is that instead of having a status code to describe how well the driver matches to the printer, now a string is used, the "fit", e.g. "exact-cmd" (meaning that the model name matches exactly, and the CMD field positively matches the declared command sets of the PPD), "exact" (meaning just that model name matches), etc. This provides more information than the status codes.
The work belongs in system-config-printer, not in pycups (which is just what it says and no more). There are already exported interfaces in system-config-printer such as the Python cupshelpers modules -- including cupshelpers/ppds.py, which is what we're talking about.
well but in C you could access them through pycups which, would be the same thing in the end I think.
I'm not sure I follow you. The pycups project is separate from system-config-printer. They are separate tarballs, and have quite distinct aims.
Well if it doesn't get accepted by upstream we can patch it downstream easily I think. It would be pretty handy since most printing servers I see the admins only use the cups server interface.
I don't favour this approach at all. If it belongs in the CUPS server, it should go in the CUPS server; if it does not, it shouldn't. I trust Michael Sweet's judgement on whether it belongs there.
What would be the point of having a forked CUPS project with this extra IPP operation? It could not be relied upon by anyone, since they would need to be compatible with the "real" CUPS project as well.
Which "downstream" are you thinking of, in any case?
Tim. */
As I've said before, I think it quite unlikely that this would ever be used by the CUPS server, but Michael Sweet would be the one with the answer to that.
In any case, whether a particular library does or does not use glib is only visible in terms of the dependencies pulled in. The end result would include an XML parser, of course, so glib is hardly the final straw when it comes to added dependencies!
Ok, so let's forget about cups server for now.
Well, CUPS has no inherent notion of there being different models of printer. It only knows about different PPDs. A given PPD can declare its manufacturer (this is exposed by CUPS in the ppd-make attribute), and its "nickname", i.e. a combination of the model name, possibly including the manufacturer's name, and the driver used, often as well as other bits of information. This is exposed by CUPS in the ppd-make-and-model attribute.
This is why cupshelpers.ppds has a fairly expensive ppdMakeModelSplit() function: in order to collect together PPDs which are for the same physical printer model.
Ok please look at this file: http://websvn.kde.org/trunk/playground/base/print-manager/libqcups/PPDModel....
Are you saying that I can't trust on ppd-make string to have the manufacturer? I can filter all my ppds by it's make without running any expensive task, if you can install kdelibs-devel and qt4-devel you can try my code to see how the ppd choser works now.
Well first to get the devices (done by qcups) and then to get the ppds list (done by pppds.py).
Ah. But cupshelpers.ppds doesn't interact with the CUPS service at all. It only processes an IPP result. Think of the PPDs object as the representation of a set of PPDs, and the actions you'd like to perform with them.
See this is the problem, how would you get an ippResult that I got with my bindings? Imagine this, if you can make ppds.py have a cmd line interface and that it does not talk with the cups server then I think this would be the easiest/maybe best solution. (though it would be harder for me to help on ppds.py due to py)
What I see in master is both ppds.py and the xml.py thing so I didn't knew ppds.py was deprecated.
No, ppds.py is not deprecated, but the interface it provides is substantially different. The "old" interface gave only one PPD, the "best", when matching a Device ID; the "new" interface gives an ordered list of all the appropriate drivers, in descending order of preference. This allows the interface to present choices based on the Device ID from the printer, something that allows the user to be more sure of getting their printer to work.
For example, if a particular printer is driven by gutenprint (and gutenprint declares the Device ID of that printer in its PPD), the "best" printer driver might be gutenprint. But if that driver doesn't work, the user has to look for other drivers. There may only be generic drivers as alternatives, and we can only offer those based on the Device ID's "CMD" field.
Right I think it's important for the user to pick a good alternative.
Another important change is that instead of having a status code to describe how well the driver matches to the printer, now a string is used, the "fit", e.g. "exact-cmd" (meaning that the model name matches exactly, and the CMD field positively matches the declared command sets of the PPD), "exact" (meaning just that model name matches), etc. This provides more information than the status codes.
Sure that's good, though I think maybe a percentage value would be nice, so we could display a set of stars.
I'm not sure I follow you. The pycups project is separate from system-config-printer. They are separate tarballs, and have quite distinct aims.
Ok I thought they were basically the same thing.
What would be the point of having a forked CUPS project with this extra IPP operation? It could not be relied upon by anyone, since they would need to be compatible with the "real" CUPS project as well.
Which "downstream" are you thinking of, in any case?
Ok, good point, I think an ipp operation is only good when upstreams accepts, otherwise we will have a non compliant server. But by downstream we can still pacth the cgi part to use the features of best guessing the ppd which wouldn't make the server different.
Daniel.
On Tue, 2010-11-23 at 07:50 -0800, Daniel Nicoletti wrote:
Ok please look at this file: http://websvn.kde.org/trunk/playground/base/print-manager/libqcups/PPDModel....
Are you saying that I can't trust on ppd-make string to have the manufacturer? I can filter all my ppds by it's make without running any expensive task, if you can install kdelibs-devel and qt4-devel you can try my code to see how the ppd choser works now.
I'm saying that in order to find the model, you need to perform lots of operations on the ppd-make-and-model field. It isn't just taking off ppd-make from the beginning.
Well first to get the devices (done by qcups) and then to get the ppds list (done by pppds.py).
Ah. But cupshelpers.ppds doesn't interact with the CUPS service at all. It only processes an IPP result. Think of the PPDs object as the representation of a set of PPDs, and the actions you'd like to perform with them.
See this is the problem, how would you get an ippResult that I got with my bindings?
Well, from libcups. If we're talking about having cupshelpers.ppds re-implementated as a C library, I don't see what's wrong with that part of the interface. It can just take 'ipp_t* ppds', i.e. the result of a CUPS-Get-PPDs query, as a parameter.
Another important change is that instead of having a status code to describe how well the driver matches to the printer, now a string is used, the "fit", e.g. "exact-cmd" (meaning that the model name matches exactly, and the CMD field positively matches the declared command sets of the PPD), "exact" (meaning just that model name matches), etc. This provides more information than the status codes.
Sure that's good, though I think maybe a percentage value would be nice, so we could display a set of stars.
But a percentage of what? I think the string descriptions are best.
Tim. */
On Tue, 2010-11-23 at 07:50 -0800, Daniel Nicoletti wrote:
Ok please look at this file:
http://websvn.kde.org/trunk/playground/base/print-manager/libqcups/PPDModel....
Are you saying that I can't trust on ppd-make string to have the
manufacturer?
I can filter all my ppds by it's make without running any expensive task, if you can install kdelibs-devel and qt4-devel you can try my code to see how the ppd choser works now.
I'm saying that in order to find the model, you need to perform lots of operations on the ppd-make-and-model field. It isn't just taking off ppd-make from the beginning.
Ok, I didn't know that.
Well first to get the devices (done by qcups) and then to get the ppds list (done by pppds.py).
Ah. But cupshelpers.ppds doesn't interact with the CUPS service at all. It only processes an IPP result. Think of the PPDs object as the representation of a set of PPDs, and the actions you'd like to perform with them.
See this is the problem, how would you get an ippResult that I got with my bindings?
Well, from libcups. If we're talking about having cupshelpers.ppds re-implementated as a C library, I don't see what's wrong with that part of the interface. It can just take 'ipp_t* ppds', i.e. the result of a CUPS-Get-PPDs query, as a parameter.
Right, that's why I was saying libqcups using your pppds.py wouldn't work as we could not glue the ppds (at least not without a second auth). So if you are okay with we re-implementing this as a C lib, just tell us which files should go first so that we don't rewrite obsolete code. I really wish I could have something this year cause next year I'll probably be moving abroad and I'm not sure of how much free time I'll have :P
Another important change is that instead of having a status code to describe how well the driver matches to the printer, now a string is used, the "fit", e.g. "exact-cmd" (meaning that the model name matches exactly, and the CMD field positively matches the declared command sets of the PPD), "exact" (meaning just that model name matches), etc. This provides more information than the status codes.
Sure that's good, though I think maybe a percentage value would be nice, so we could display a set of stars.
But a percentage of what? I think the string descriptions are best.
A right, I was thinking at the code I saw that had some numeric metrics, so the idea is just to have a set of strings that can be translated into fit, exact... ok got it :D
Ok I think we are fine then were do you think the development should take place? We can start the code together with our kde tools so we can more easily test and then move to somewhere else. Print-manger is moving from kde svn to kde's git so I guess pushing that to fedora's git would be easier also.. what do you think?
Best, Daniel.
On Fri, 2010-12-03 at 17:31 -0800, Daniel Nicoletti wrote:
See this is the problem, how would you get an ippResult that I got with my bindings?
Well, from libcups. If we're talking about having cupshelpers.ppds re-implementated as a C library, I don't see what's wrong with that part of the interface. It can just take 'ipp_t* ppds', i.e. the result of a CUPS-Get-PPDs query, as a parameter.
Right, that's why I was saying libqcups using your pppds.py wouldn't work as we could not glue the ppds (at least not without a second auth).
I still don't really see what you are saying -- why can't your library do the CUPS operation, and pass the result to "libppds"?
So if you are okay with we re-implementing this as a C lib, just tell us which files should go first so that we don't rewrite obsolete code. I really wish I could have something this year cause next year I'll probably be moving abroad and I'm not sure of how much free time I'll have :P
I hope I've already described well enough what the new interface is. Just read through the functions in that interface. :-)
Basically, it's most of cupshelpers/ppds.py and all of cupshelpers/xmldriverprefs.py. The only bit not to bother with is cupshelpers.ppds.PPDs.getPPDNameFromDeviceID(), as that has been replaced by cupshelpers.ppds.PPDs.getPPDNamesFromDeviceID().
A right, I was thinking at the code I saw that had some numeric metrics,
If you're seeing numeric metrics, you are looking at the wrong code.
Look at the master branch, not 1.2.x.
so the idea is just to have a set of strings that can be translated into fit, exact... ok got it :D
Yes, exactly.
Ok I think we are fine then were do you think the development should take place? We can start the code together with our kde tools so we can more easily test and then move to somewhere else. Print-manger is moving from kde svn to kde's git so I guess pushing that to fedora's git would be easier also.. what do you think?
Yes, that's fine.
Note that there is some design work going on for a GNOME printer settings module: http://live.gnome.org/action/subscribe/Design/SystemSettings/Printers
This might well end up implementing some of the same parts of code as GObjects, so if you implement it without glib it might have to be added in afterwards anyway.
Tim. */
system-config-printer-devel@lists.fedorahosted.org